From 672bb9e431158b4f1c352701f8843f83063df232 Mon Sep 17 00:00:00 2001 From: Miriam Rathbun Date: Mon, 22 Nov 2021 22:46:40 -0700 Subject: [PATCH 0001/2654] I believe I successfully implemented condensation of diffusion coefficients (as opposed to transport cross sections). --- openmc/mgxs/mgxs.py | 125 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 114 insertions(+), 11 deletions(-) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index ff739fe85..6502a5ef2 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -3154,30 +3154,133 @@ class DiffusionCoefficient(TransportXS): raise ValueError(msg) # Switch EnergyoutFilter to EnergyFilter + if 'scatter-1' in self.tallies: + p1_tally = self.tallies['scatter-1'] + old_filt = p1_tally.filters[-2] + new_filt = openmc.EnergyFilter(old_filt.values) + p1_tally.filters[-2] = new_filt + + p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], + filter_bins=[('P1',)],squeeze=True) + p1_tally._scores = ['scatter-1'] + total_xs = self.tallies['total'] / self.tallies['flux (tracklength)'] + trans_corr = p1_tally / self.tallies['flux (analog)'] + transport = total_xs - trans_corr + diff_coef = transport**(-1) / 3.0 + self._xs_tally = diff_coef + self._compute_xs() + + else: + self._xs_tally = self.tallies[self._rxn_type] / self.tallies['flux (tracklength)'] + self._compute_xs() + + return self._xs_tally + + def get_condensed_xs(self, coarse_groups, condense_diff_coef=True): + """Construct an energy-condensed version of this cross section. + + Parameters + ---------- + coarse_groups : openmc.mgxs.EnergyGroups + The coarse energy group structure of interest + + Returns + ------- + MGXS + A new MGXS condensed to the group structure of interest + + """ + + cv.check_type('coarse_groups', coarse_groups, EnergyGroups) + cv.check_less_than('coarse groups', coarse_groups.num_groups, + self.num_groups, equality=True) + cv.check_value('upper coarse energy', coarse_groups.group_edges[-1], + [self.energy_groups.group_edges[-1]]) + cv.check_value('lower coarse energy', coarse_groups.group_edges[0], + [self.energy_groups.group_edges[0]]) + + # Clone this MGXS to initialize the condensed version + condensed_xs = copy.deepcopy(self) + + if condense_diff_coef: p1_tally = self.tallies['scatter-1'] old_filt = p1_tally.filters[-2] new_filt = openmc.EnergyFilter(old_filt.values) p1_tally.filters[-2] = new_filt - - # Slice Legendre expansion filter and change name of score p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], filter_bins=[('P1',)], squeeze=True) p1_tally._scores = ['scatter-1'] - - # Compute total cross section total_xs = self.tallies['total'] / self.tallies['flux (tracklength)'] - - # Compute transport correction term trans_corr = p1_tally / self.tallies['flux (analog)'] - - # Compute the diffusion coefficient transport = total_xs - trans_corr diff_coef = transport**(-1) / 3.0 - self._xs_tally = diff_coef - self._compute_xs() + diff_coef *= self.tallies['flux (tracklength)'] + flux_tally = condensed_xs.tallies['flux (tracklength)'] + condensed_xs._tallies = OrderedDict() + condensed_xs._tallies[self._rxn_type] = diff_coef + condensed_xs._tallies['flux (tracklength)'] = flux_tally + condensed_xs._rxn_rate_tally = diff_coef + condensed_xs._xs_tally = None + condensed_xs._sparse = False + condensed_xs._energy_groups = coarse_groups - return self._xs_tally + else: + condensed_xs._rxn_rate_tally = None + condensed_xs._xs_tally = None + condensed_xs._sparse = False + condensed_xs._energy_groups = coarse_groups + + # Build energy indices to sum across + energy_indices = [] + for group in range(coarse_groups.num_groups, 0, -1): + low, high = coarse_groups.get_group_bounds(group) + low_index = np.where(self.energy_groups.group_edges == low)[0][0] + energy_indices.append(low_index) + + fine_edges = self.energy_groups.group_edges + + # Condense each of the tallies to the coarse group structure + for tally in condensed_xs.tallies.values(): + + # Make condensed tally derived and null out sum, sum_sq + tally._derived = True + tally._sum = None + tally._sum_sq = None + + # Get tally data arrays reshaped with one dimension per filter + mean = tally.get_reshaped_data(value='mean') + std_dev = tally.get_reshaped_data(value='std_dev') + + # Sum across all applicable fine energy group filters + for i, tally_filter in enumerate(tally.filters): + if not isinstance(tally_filter, (openmc.EnergyFilter, + openmc.EnergyoutFilter)): + continue + elif len(tally_filter.bins) != len(fine_edges) - 1: + continue + elif not np.allclose(tally_filter.bins[:, 0], fine_edges[:-1]): + continue + else: + cedge = coarse_groups.group_edges + tally_filter.values = cedge + tally_filter.bins = np.vstack((cedge[:-1], cedge[1:])).T + mean = np.add.reduceat(mean, energy_indices, axis=i) + std_dev = np.add.reduceat(std_dev**2, energy_indices, + axis=i) + std_dev = np.sqrt(std_dev) + + # Reshape condensed data arrays with one dimension for all filters + mean = np.reshape(mean, tally.shape) + std_dev = np.reshape(std_dev, tally.shape) + + # Override tally's data with the new condensed data + tally._mean = mean + tally._std_dev = std_dev + + # Compute the energy condensed multi-group cross section + condensed_xs.sparse = self.sparse + return condensed_xs class AbsorptionXS(MGXS): r"""An absorption multi-group cross section. From 12db3d12ac2baca91683dff70edcc77a84f6ab5e Mon Sep 17 00:00:00 2001 From: Miriam Rathbun Date: Mon, 22 Nov 2021 22:56:13 -0700 Subject: [PATCH 0002/2654] Updated results from mgxs_library_condense to reflect new changes. --- .../mgxs_library_condense/results_true.dat | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/regression_tests/mgxs_library_condense/results_true.dat b/tests/regression_tests/mgxs_library_condense/results_true.dat index 349d9debe..ac0dd2163 100644 --- a/tests/regression_tests/mgxs_library_condense/results_true.dat +++ b/tests/regression_tests/mgxs_library_condense/results_true.dat @@ -214,16 +214,16 @@ 28 2 2 y-min out 1 total 4.548 0.156691 mesh 1 group in nuclide mean std. dev. x y z -0 1 1 1 1 total 0.757948 0.035459 -2 1 2 1 1 total 0.779112 0.047034 -1 2 1 1 1 total 0.787475 0.050368 -3 2 2 1 1 total 0.769656 0.058065 +0 1 1 1 1 total 0.931945 0.045510 +2 1 2 1 1 total 0.962029 0.072431 +1 2 1 1 1 total 0.971983 0.071094 +3 2 2 1 1 total 0.930013 0.102254 mesh 1 group in nuclide mean std. dev. x y z -0 1 1 1 1 total 0.757948 0.035459 -2 1 2 1 1 total 0.778934 0.047027 -1 2 1 1 1 total 0.787475 0.050368 -3 2 2 1 1 total 0.769656 0.058065 +0 1 1 1 1 total 0.931945 0.045510 +2 1 2 1 1 total 0.961685 0.072418 +1 2 1 1 1 total 0.971983 0.071094 +3 2 2 1 1 total 0.930013 0.102254 mesh 1 delayedgroup group in nuclide mean std. dev. x y z 0 1 1 1 1 1 total 0.000006 3.699363e-07 From ccec9ee7bfdaab126ca2a33020df6667618abf5b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Feb 2022 21:29:37 -0600 Subject: [PATCH 0003/2654] Optimization for complete list of bin indices --- openmc/tallies.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index c7bc35933..436e3189e 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1110,7 +1110,11 @@ class Tally(IDManagerMixin): bins = self_filter.bins # Add indices for each bin in this Filter to the list - indices = np.array([self_filter.get_bin_index(b) for b in bins]) + + if type(self_filter) in filters: + indices = np.array([self_filter.get_bin_index(b) for b in bins]) + else: + indices = np.arange(len(bins)) filter_indices.append(indices) # Account for stride in each of the previous filters From 49d25ae8b6d9587ac9fac82ea453a36009be45c3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 14 Feb 2022 11:42:23 -0600 Subject: [PATCH 0004/2654] Change version number to 0.13.1-dev --- CMakeLists.txt | 2 +- docs/source/conf.py | 2 +- include/openmc/version.h.in | 2 +- openmc/__init__.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cfffbdccc..a01d02fb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(openmc C CXX) # Set version numbers set(OPENMC_VERSION_MAJOR 0) set(OPENMC_VERSION_MINOR 13) -set(OPENMC_VERSION_RELEASE 0) +set(OPENMC_VERSION_RELEASE 1) set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) diff --git a/docs/source/conf.py b/docs/source/conf.py index fb12a4f56..ed36a9c28 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -71,7 +71,7 @@ copyright = '2011-2022, Massachusetts Institute of Technology, UChicago Argonne # The short X.Y version. version = "0.13" # The full version, including alpha/beta/rc tags. -release = "0.13.0" +release = "0.13.1-dev" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index 98f431288..2933746e2 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -7,7 +7,7 @@ namespace openmc { constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {false}; +constexpr bool VERSION_DEV {true}; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/openmc/__init__.py b/openmc/__init__.py index d7bcdffff..0a11fbf53 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -36,4 +36,4 @@ from . import examples from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.13.0' +__version__ = '0.13.1-dev' From 6dadcc9c032f8f284392acc3c6dc2dd213c73cc6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 14 Feb 2022 11:42:41 -0600 Subject: [PATCH 0005/2654] Fix latexpdf doc build (missing unicode character conversion) --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index ed36a9c28..a7a3c803a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -215,6 +215,7 @@ latex_elements = { \setcounter{tocdepth}{2} \numberwithin{equation}{section} \DeclareUnicodeCharacter{03B1}{$\alpha$} +\DeclareUnicodeCharacter{03C0}{$\pi$} """, 'printindex': r"" } From 1da0eac5d580d4908ebc2e7afdb21fab8402e0ea Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 14 Feb 2022 23:36:14 +0000 Subject: [PATCH 0006/2654] minor typo fix --- docs/source/capi/index.rst | 2 +- docs/source/devguide/workflow.rst | 4 ++-- docs/source/io_formats/geometry.rst | 2 +- docs/source/io_formats/statepoint.rst | 2 +- docs/source/methods/cmfd.rst | 4 ++-- docs/source/methods/cross_sections.rst | 2 +- docs/source/methods/energy_deposition.rst | 2 +- docs/source/methods/introduction.rst | 2 +- docs/source/methods/neutron_physics.rst | 2 +- docs/source/methods/parallelization.rst | 4 ++-- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index eb6493e0e..222f81c4b 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -355,7 +355,7 @@ Functions Get density of a material. :param int32_t index: Index in the materials array - :param double* denity: Pointer to a density + :param double* density: Pointer to a density :return: Return status (negative if an error occurs) :rtype: int diff --git a/docs/source/devguide/workflow.rst b/docs/source/devguide/workflow.rst index 57f2b1c68..3bad04cae 100644 --- a/docs/source/devguide/workflow.rst +++ b/docs/source/devguide/workflow.rst @@ -4,7 +4,7 @@ Development Workflow ==================== -Anyone wishing to make contributions to OpenMC should be fully acquianted and +Anyone wishing to make contributions to OpenMC should be fully acquainted and comfortable working with git_ and GitHub_. We assume here that you have git installed on your system, have a GitHub account, and have setup SSH keys to be able to create/push to repositories on GitHub. @@ -81,7 +81,7 @@ features and bug fixes. The general steps for contributing are as follows: openmc-dev/openmc as the target. At a minimum, you should describe what the changes you've made are and why - you are making them. If the changes are related to an oustanding issue, make + you are making them. If the changes are related to an outstanding issue, make sure it is cross-referenced. 5. A committer will review your pull request based on the criteria diff --git a/docs/source/io_formats/geometry.rst b/docs/source/io_formats/geometry.rst index ff2f6eb74..ac48e48d2 100644 --- a/docs/source/io_formats/geometry.rst +++ b/docs/source/io_formats/geometry.rst @@ -48,7 +48,7 @@ Each ```` element can have the following attributes or sub-elements: :periodic_surface_id: If a periodic boundary condition is applied, this attribute identifies the - ``id`` of the corresponding periodic sufrace. + ``id`` of the corresponding periodic surface. The following quadratic surfaces can be modeled: diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 591dc2777..f96d7181d 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -149,7 +149,7 @@ All values are given in seconds and are measured on the master process. finalization. - **transport** (*double*) -- Time spent transporting particles. - **inactive batches** (*double*) -- Time spent in the inactive - batches (including non-transport activities like communcating + batches (including non-transport activities like communicating sites). - **active batches** (*double*) -- Time spent in the active batches (including non-transport activities like communicating sites). diff --git a/docs/source/methods/cmfd.rst b/docs/source/methods/cmfd.rst index 344a4cc1a..66d545ac1 100644 --- a/docs/source/methods/cmfd.rst +++ b/docs/source/methods/cmfd.rst @@ -266,11 +266,11 @@ and eq. :eq:`eq_cell_bound` can be written in this generic form, The parameter :math:`\widetilde{D}_{l,m,n}^{u,g}` represents the linear coupling term between current and flux. These current relationships can be -sustituted into eq. :eq:`eq_neut_bal` to produce a linear system of multigroup +substituted into eq. :eq:`eq_neut_bal` to produce a linear system of multigroup diffusion equations for each spatial cell and energy group. However, a solution to these equations is not consistent with a higher order transport solution unless equivalence factors are present. This is because both the diffusion -approximation, governed by Fick's Law, and spatial trunction error will produce +approximation, governed by Fick's Law, and spatial truncation error will produce differences. Therefore, a nonlinear parameter, :math:`\widehat{D}_{l,m,n}^{u,g}`, is added to eqs. :eq:`eq_cell_cell` and :eq:`eq_cell_bound`. These equations are, respectively, diff --git a/docs/source/methods/cross_sections.rst b/docs/source/methods/cross_sections.rst index c6d1f44f4..2210dfa45 100644 --- a/docs/source/methods/cross_sections.rst +++ b/docs/source/methods/cross_sections.rst @@ -9,7 +9,7 @@ Continuous-Energy Data ---------------------- In OpenMC, the data governing the interaction of neutrons with various nuclei -for continous-energy problems are represented using an HDF5 format that can be +for continuous-energy problems are represented using an HDF5 format that can be produced by converting files in the ACE format, which is used by MCNP_ and Serpent_. ACE-format data can be generated with the NJOY_ nuclear data processing system, which converts raw `ENDF/B data`_ into linearly-interpolable diff --git a/docs/source/methods/energy_deposition.rst b/docs/source/methods/energy_deposition.rst index fbcccc26b..4675aee3f 100644 --- a/docs/source/methods/energy_deposition.rst +++ b/docs/source/methods/energy_deposition.rst @@ -7,7 +7,7 @@ Heating and Energy Deposition As particles traverse a problem, some portion of their energy is deposited at collision sites. This energy is deposited when charged particles, including electrons and recoil nuclei, undergo electromagnetic interactions with -surrounding electons and ions. The information describing how much energy +surrounding electrons and ions. The information describing how much energy is deposited for a specific reaction is referred to as "heating numbers" and can be computed using a program like NJOY with the ``heatr`` module. diff --git a/docs/source/methods/introduction.rst b/docs/source/methods/introduction.rst index 924d4858d..eacdd70f5 100644 --- a/docs/source/methods/introduction.rst +++ b/docs/source/methods/introduction.rst @@ -45,7 +45,7 @@ following steps: - Initialize the pseudorandom number generator. - - Read the contiuous-energy or multi-group cross section data specified in + - Read the continuous-energy or multi-group cross section data specified in the problem. - If using a special energy grid treatment such as a union energy grid or diff --git a/docs/source/methods/neutron_physics.rst b/docs/source/methods/neutron_physics.rst index 7c1490647..e9061eea1 100644 --- a/docs/source/methods/neutron_physics.rst +++ b/docs/source/methods/neutron_physics.rst @@ -182,7 +182,7 @@ Inelastic Scattering -------------------- Note that the multi-group mode makes no distinction between elastic or -inelastic scattering reactions. The spceific multi-group scattering +inelastic scattering reactions. The specific multi-group scattering implementation is discussed in the :ref:`multi-group-scatter` section. The major algorithms for inelastic scattering were described in previous diff --git a/docs/source/methods/parallelization.rst b/docs/source/methods/parallelization.rst index 29748807a..d9fc15c9f 100644 --- a/docs/source/methods/parallelization.rst +++ b/docs/source/methods/parallelization.rst @@ -293,7 +293,7 @@ Cost of Nearest Neighbor Algorithm ---------------------------------- With the communication cost of the traditional fission bank algorithm -quantified, we now proceed to discuss the communicatin cost of the proposed +quantified, we now proceed to discuss the communication cost of the proposed algorithm. Comparing the cost of communication of this algorithm with the traditional algorithm is not trivial due to fact that the cost will be a function of how many fission sites are sampled on each node. If each node @@ -398,7 +398,7 @@ equation :eq:`k-to-source`, we can relate the stochastic eigenvalue to the integral of the noise component of the source distribution as .. math:: - :label: noise-integeral + :label: noise-integral N\hat{k} = Nk + \sqrt{N} \int \hat{\epsilon}(\mathbf{r}) \: d\mathbf{r}. From 03fe9d3200bd61965dc738911652b98df85fcb7d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 13 Jan 2022 18:32:17 -0600 Subject: [PATCH 0007/2654] Don't modify wgt_last in russian_roulette --- src/physics_common.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/physics_common.cpp b/src/physics_common.cpp index f6820f81f..964678fbe 100644 --- a/src/physics_common.cpp +++ b/src/physics_common.cpp @@ -12,12 +12,10 @@ namespace openmc { void russian_roulette(Particle& p) { if (p.wgt() < settings::weight_cutoff) { - if (prn(p.current_seed()) < p.wgt() / settings::weight_survive) { + if (settings::weight_survive * prn(p.current_seed()) < p.wgt()) { p.wgt() = settings::weight_survive; - p.wgt_last() = p.wgt(); } else { p.wgt() = 0.; - p.wgt_last() = 0.; p.alive() = false; } } From f741568d06028eee5499ca8a01201680b11d092d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 16 Jan 2022 14:12:45 -0600 Subject: [PATCH 0008/2654] Don't modify wgt_last in survival biasing --- src/physics.cpp | 1 - src/physics_mg.cpp | 1 - src/tallies/tally_scoring.cpp | 211 +++++++----------- .../regression_tests/tallies/results_true.dat | 2 +- 4 files changed, 83 insertions(+), 132 deletions(-) diff --git a/src/physics.cpp b/src/physics.cpp index 196c7dc3b..f6fc31cb9 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -631,7 +631,6 @@ void absorption(Particle& p, int i_nuclide) // Adjust weight of particle by probability of absorption p.wgt() -= p.wgt_absorb(); - p.wgt_last() = p.wgt(); // Score implicit absorption estimate of keff if (settings::run_mode == RunMode::EIGENVALUE) { diff --git a/src/physics_mg.cpp b/src/physics_mg.cpp index eaf13b441..ce7db3faf 100644 --- a/src/physics_mg.cpp +++ b/src/physics_mg.cpp @@ -220,7 +220,6 @@ void absorption(Particle& p) // Adjust weight of particle by the probability of absorption p.wgt() -= p.wgt_absorb(); - p.wgt_last() = p.wgt(); // Score implicit absorpion estimate of keff p.keff_tally_absorption() += diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index fd7509166..8c91314aa 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -203,10 +203,10 @@ double score_fission_q(const Particle& p, int score_bin, const Tally& tally, // No fission events occur if survival biasing is on -- need to // calculate fraction of absorptions that would have resulted in // fission scaled by the Q-value - if (p.neutron_xs(p.event_nuclide()).absorption > 0) { - return p.wgt_absorb() * get_nuc_fission_q(nuc, p, score_bin) * + if (p.neutron_xs(p.event_nuclide()).total > 0) { + return p.wgt_last() * get_nuc_fission_q(nuc, p, score_bin) * p.neutron_xs(p.event_nuclide()).fission * flux / - p.neutron_xs(p.event_nuclide()).absorption; + p.neutron_xs(p.event_nuclide()).total; } } else { // Skip any non-absorption events @@ -291,7 +291,6 @@ double get_nuclide_neutron_heating( double score_neutron_heating(const Particle& p, const Tally& tally, double flux, int rxn_bin, int i_nuclide, double atom_density) { - double score; // Get heating macroscopic "cross section" double heating_xs; if (i_nuclide >= 0) { @@ -318,17 +317,12 @@ double score_neutron_heating(const Particle& p, const Tally& tally, double flux, } } } - score = heating_xs * flux; + double score = heating_xs * flux; if (tally.estimator_ == TallyEstimator::ANALOG) { // All events score to a heating tally bin. We actually use a // collision estimator in place of an analog one since there is no // reaction-wise heating cross section - if (settings::survival_biasing) { - // Account for the fact that some weight has been absorbed - score *= p.wgt_last() + p.wgt_absorb(); - } else { - score *= p.wgt_last(); - } + score *= p.wgt_last(); } return score; } @@ -565,16 +559,8 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // All events score to a flux bin. We actually use a collision estimator // in place of an analog one since there is no way to count 'events' // exactly for the flux - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p.wgt_last() + p.wgt_absorb(); - } else { - score = p.wgt_last(); - } - if (p.type() == Type::neutron || p.type() == Type::photon) { - score *= flux / p.macro_xs().total; + score = flux * p.wgt_last() / p.macro_xs().total; } else { score = 0.; } @@ -587,13 +573,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (tally.estimator_ == TallyEstimator::ANALOG) { // All events will score to the total reaction rate. We can just use // use the weight of the particle entering the collision as the score - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = (p.wgt_last() + p.wgt_absorb()) * flux; - } else { - score = p.wgt_last() * flux; - } + score = p.wgt_last() * flux; } else { if (i_nuclide >= 0) { @@ -616,14 +596,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // All events score to an inverse velocity bin. We actually use a // collision estimator in place of an analog one since there is no way // to count 'events' exactly for the inverse velocity - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p.wgt_last() + p.wgt_absorb(); - } else { - score = p.wgt_last(); - } - score *= flux / p.macro_xs().total; + score = flux * p.wgt_last() / p.macro_xs().total; } else { score = flux; } @@ -641,7 +614,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, continue; // Since only scattering events make it here, again we can use the // weight entering the collision as the estimator for the reaction rate - score = p.wgt_last() * flux; + score = (p.wgt_last() - p.wgt_absorb()) * flux; } else { if (i_nuclide >= 0) { if (p.type() == Type::neutron) { @@ -672,17 +645,17 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // For scattering production, we need to use the pre-collision weight // times the yield as the estimate for the number of neutrons exiting a // reaction with neutrons in the exit channel - if (p.event_mt() == ELASTIC || p.event_mt() == N_LEVEL || - (p.event_mt() >= N_N1 && p.event_mt() <= N_NC)) { - // Don't waste time on very common reactions we know have - // multiplicities of one. - score = p.wgt_last() * flux; - } else { + score = (p.wgt_last() - p.wgt_absorb()) * flux; + + // Don't waste time on very common reactions we know have multiplicities + // of one. + if (p.event_mt() != ELASTIC && p.event_mt() != N_LEVEL && + !(p.event_mt() >= N_N1 && p.event_mt() <= N_NC)) { // Get yield and apply to score auto m = data::nuclides[p.event_nuclide()]->reaction_index_[p.event_mt()]; const auto& rxn {*data::nuclides[p.event_nuclide()]->reactions_[m]}; - score = p.wgt_last() * flux * (*rxn.products_[0].yield_)(E); + score *= (*rxn.products_[0].yield_)(E); } break; @@ -725,16 +698,15 @@ void score_general_ce(Particle& p, int i_tally, int start_index, break; case SCORE_FISSION: - if (p.macro_xs().absorption == 0) + if (p.macro_xs().fission == 0) continue; if (tally.estimator_ == TallyEstimator::ANALOG) { if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // fission - if (p.neutron_xs(p.event_nuclide()).absorption > 0) { - score = p.wgt_absorb() * p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).absorption * flux; + // No fission events occur if survival biasing is on -- use collision + // estimator instead + if (p.neutron_xs(p.event_nuclide()).total > 0) { + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission / + p.neutron_xs(p.event_nuclide()).total * flux; } else { score = 0.; } @@ -758,7 +730,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, break; case SCORE_NU_FISSION: - if (p.macro_xs().absorption == 0) + if (p.macro_xs().fission == 0) continue; if (tally.estimator_ == TallyEstimator::ANALOG) { if (settings::survival_biasing || p.fission()) { @@ -770,13 +742,11 @@ void score_general_ce(Particle& p, int i_tally, int start_index, } } if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // nu-fission - if (p.neutron_xs(p.event_nuclide()).absorption > 0) { - score = p.wgt_absorb() * - p.neutron_xs(p.event_nuclide()).nu_fission / - p.neutron_xs(p.event_nuclide()).absorption * flux; + // No fission events occur if survival biasing is on -- use collision + // estimator instead + if (p.neutron_xs(p.event_nuclide()).total > 0) { + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).nu_fission / + p.neutron_xs(p.event_nuclide()).total * flux; } else { score = 0.; } @@ -801,7 +771,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, break; case SCORE_PROMPT_NU_FISSION: - if (p.macro_xs().absorption == 0) + if (p.macro_xs().fission == 0) continue; if (tally.estimator_ == TallyEstimator::ANALOG) { if (settings::survival_biasing || p.fission()) { @@ -816,11 +786,11 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // No fission events occur if survival biasing is on -- need to // calculate fraction of absorptions that would have resulted in // prompt-nu-fission - if (p.neutron_xs(p.event_nuclide()).absorption > 0) { - score = p.wgt_absorb() * p.neutron_xs(p.event_nuclide()).fission * + if (p.neutron_xs(p.event_nuclide()).total > 0) { + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission * data::nuclides[p.event_nuclide()]->nu( E, ReactionProduct::EmissionMode::prompt) / - p.neutron_xs(p.event_nuclide()).absorption * flux; + p.neutron_xs(p.event_nuclide()).total * flux; } else { score = 0.; } @@ -863,7 +833,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, break; case SCORE_DELAYED_NU_FISSION: - if (p.macro_xs().absorption == 0) + if (p.macro_xs().fission == 0) continue; if (tally.estimator_ == TallyEstimator::ANALOG) { if (settings::survival_biasing || p.fission()) { @@ -878,7 +848,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // No fission events occur if survival biasing is on -- need to // calculate fraction of absorptions that would have resulted in // delayed-nu-fission - if (p.neutron_xs(p.event_nuclide()).absorption > 0 && + if (p.neutron_xs(p.event_nuclide()).total > 0 && data::nuclides[p.event_nuclide()]->fissionable_) { if (tally.delayedgroup_filter_ != C_NONE) { auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; @@ -890,9 +860,9 @@ void score_general_ce(Particle& p, int i_tally, int start_index, auto dg = filt.groups()[d_bin]; auto yield = data::nuclides[p.event_nuclide()]->nu( E, ReactionProduct::EmissionMode::delayed, dg); - score = p.wgt_absorb() * yield * + score = p.wgt_last() * yield * p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).absorption * flux; + p.neutron_xs(p.event_nuclide()).total * flux; score_fission_delayed_dg( i_tally, d_bin, score, score_index, p.filter_matches()); } @@ -901,10 +871,10 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // If the delayed group filter is not present, compute the score // by multiplying the absorbed weight by the fraction of the // delayed-nu-fission xs to the absorption xs - score = p.wgt_absorb() * p.neutron_xs(p.event_nuclide()).fission * + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission * data::nuclides[p.event_nuclide()]->nu( E, ReactionProduct::EmissionMode::delayed) / - p.neutron_xs(p.event_nuclide()).absorption * flux; + p.neutron_xs(p.event_nuclide()).total * flux; } } } else { @@ -1007,7 +977,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, break; case SCORE_DECAY_RATE: - if (p.macro_xs().absorption == 0) + if (p.macro_xs().fission == 0) continue; if (tally.estimator_ == TallyEstimator::ANALOG) { if (settings::survival_biasing) { @@ -1015,8 +985,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // calculate fraction of absorptions that would have resulted in // delayed-nu-fission const auto& nuc {*data::nuclides[p.event_nuclide()]}; - if (p.neutron_xs(p.event_nuclide()).absorption > 0 && - nuc.fissionable_) { + if (p.neutron_xs(p.event_nuclide()).total > 0 && nuc.fissionable_) { const auto& rxn {*nuc.fission_rx_[0]}; if (tally.delayedgroup_filter_ != C_NONE) { auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; @@ -1029,10 +998,9 @@ void score_general_ce(Particle& p, int i_tally, int start_index, auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); auto rate = rxn.products_[d].decay_rate_; - score = p.wgt_absorb() * yield * + score = p.wgt_last() * yield * p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).absorption * rate * - flux; + p.neutron_xs(p.event_nuclide()).total * rate * flux; score_fission_delayed_dg( i_tally, d_bin, score, score_index, p.filter_matches()); } @@ -1048,13 +1016,17 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // rxn.products_ array to be exceeded. Hence, we use the size // of this array and not the MAX_DELAYED_GROUPS constant for // this loop. - for (auto d = 0; d < rxn.products_.size() - 2; ++d) { + for (auto d = 1; d < rxn.products_.size(); ++d) { + const auto& product = rxn.products_[d]; + if (product.particle_ != Type::neutron) + continue; + auto yield = - nuc.nu(E, ReactionProduct::EmissionMode::delayed, d + 1); - auto rate = rxn.products_[d + 1].decay_rate_; - score += rate * p.wgt_absorb() * + nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = product.decay_rate_; + score += rate * p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission * yield / - p.neutron_xs(p.event_nuclide()).absorption * flux; + p.neutron_xs(p.event_nuclide()).total * flux; } } } @@ -1123,10 +1095,13 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // rxn.products_ array to be exceeded. Hence, we use the size // of this array and not the MAX_DELAYED_GROUPS constant for // this loop. - for (auto d = 0; d < rxn.products_.size() - 2; ++d) { - auto yield = - nuc.nu(E, ReactionProduct::EmissionMode::delayed, d + 1); - auto rate = rxn.products_[d + 1].decay_rate_; + for (auto d = 1; d < rxn.products_.size(); ++d) { + const auto& product = rxn.products_[d]; + if (product.particle_ != Type::neutron) + continue; + + auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = product.decay_rate_; score += p.neutron_xs(i_nuclide).fission * flux * yield * atom_density * rate; } @@ -1174,10 +1149,14 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // rxn.products_ array to be exceeded. Hence, we use the size // of this array and not the MAX_DELAYED_GROUPS constant for // this loop. - for (auto d = 0; d < rxn.products_.size() - 2; ++d) { + for (auto d = 1; d < rxn.products_.size(); ++d) { + const auto& product = rxn.products_[d]; + if (product.particle_ != Type::neutron) + continue; + auto yield = - nuc.nu(E, ReactionProduct::EmissionMode::delayed, d + 1); - auto rate = rxn.products_[d + 1].decay_rate_; + nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = product.decay_rate_; score += p.neutron_xs(j_nuclide).fission * yield * atom_density * flux * rate; } @@ -1190,7 +1169,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, break; case SCORE_KAPPA_FISSION: - if (p.macro_xs().absorption == 0.) + if (p.macro_xs().fission == 0.) continue; score = 0.; // Kappa-fission values are determined from the Q-value listed for the @@ -1201,12 +1180,11 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // calculate fraction of absorptions that would have resulted in // fission scaled by the Q-value const auto& nuc {*data::nuclides[p.event_nuclide()]}; - if (p.neutron_xs(p.event_nuclide()).absorption > 0 && - nuc.fissionable_) { + if (p.neutron_xs(p.event_nuclide()).total > 0 && nuc.fissionable_) { const auto& rxn {*nuc.fission_rx_[0]}; - score = p.wgt_absorb() * rxn.q_value_ * + score = p.wgt_last() * rxn.q_value_ * p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).absorption * flux; + p.neutron_xs(p.event_nuclide()).total * flux; } } else { // Skip any non-absorption events @@ -1262,7 +1240,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // Check if event MT matches if (p.event_mt() != ELASTIC) continue; - score = p.wgt_last() * flux; + score = (p.wgt_last() - p.wgt_absorb()) * flux; } else { if (i_nuclide >= 0) { if (p.neutron_xs(i_nuclide).elastic == CACHE_INVALID) @@ -1286,7 +1264,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, case SCORE_FISS_Q_PROMPT: case SCORE_FISS_Q_RECOV: - if (p.macro_xs().absorption == 0.) + if (p.macro_xs().fission == 0.) continue; score = score_fission_q(p, score_bin, tally, flux, i_nuclide, atom_density); @@ -1311,7 +1289,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // Check if the event MT matches if (p.event_mt() != score_bin) continue; - score = p.wgt_last() * flux; + score = (p.wgt_last() - p.wgt_absorb()) * flux; } else { int m; switch (score_bin) { @@ -1423,12 +1401,11 @@ void score_general_ce(Particle& p, int i_tally, int start_index, continue; if (tally.estimator_ == TallyEstimator::ANALOG) { - // Any other score is assumed to be a MT number. Thus, we just need // to check if it matches the MT number of the event if (p.event_mt() != score_bin) continue; - score = p.wgt_last() * flux; + score = (p.wgt_last() - p.wgt_absorb()) * flux; } else { // Any other cross section has to be calculated on-the-fly if (score_bin < 2) @@ -1532,14 +1509,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // All events score to a flux bin. We actually use a collision estimator // in place of an analog one since there is no way to count 'events' // exactly for the flux - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p.wgt_last() + p.wgt_absorb(); - } else { - score = p.wgt_last(); - } - score *= flux / p.macro_xs().total; + score = flux * p.wgt_last() / p.macro_xs().total; } else { score = flux; } @@ -1549,16 +1519,9 @@ void score_general_mg(Particle& p, int i_tally, int start_index, if (tally.estimator_ == TallyEstimator::ANALOG) { // All events will score to the total reaction rate. We can just use // use the weight of the particle entering the collision as the score - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p.wgt_last() + p.wgt_absorb(); - } else { - score = p.wgt_last(); - } - // TODO: should flux be multiplied in above instead of below? + score = flux * p.wgt_last(); if (i_nuclide >= 0) { - score *= flux * atom_density * nuc_xs.get_xs(MgxsType::TOTAL, p_g) / + score *= atom_density * nuc_xs.get_xs(MgxsType::TOTAL, p_g) / macro_xs.get_xs(MgxsType::TOTAL, p_g); } } else { @@ -1576,18 +1539,12 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // All events score to an inverse velocity bin. We actually use a // collision estimator in place of an analog one since there is no way // to count 'events' exactly for the inverse velocity - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p.wgt_last() + p.wgt_absorb(); - } else { - score = p.wgt_last(); - } + score = flux * p.wgt_last(); if (i_nuclide >= 0) { - score *= flux * nuc_xs.get_xs(MgxsType::INVERSE_VELOCITY, p_g) / + score *= nuc_xs.get_xs(MgxsType::INVERSE_VELOCITY, p_g) / macro_xs.get_xs(MgxsType::TOTAL, p_g); } else { - score *= flux * macro_xs.get_xs(MgxsType::INVERSE_VELOCITY, p_g) / + score *= macro_xs.get_xs(MgxsType::INVERSE_VELOCITY, p_g) / macro_xs.get_xs(MgxsType::TOTAL, p_g); } } else { @@ -1606,7 +1563,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, continue; // Since only scattering events make it here, again we can use the // weight entering the collision as the estimator for the reaction rate - score = p.wgt_last() * flux; + score = (p.wgt_last() - p.wgt_absorb()) * flux; if (i_nuclide >= 0) { score *= atom_density * nuc_xs.get_xs(MgxsType::SCATTER_FMU, p.g_last(), &p.g(), @@ -1634,7 +1591,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // For scattering production, we need to use the pre-collision weight // times the multiplicity as the estimate for the number of neutrons // exiting a reaction with neutrons in the exit channel - score = p.wgt() * flux; + score = (p.wgt_last() - p.wgt_absorb()) * flux; // Since we transport based on material data, the angle selected // was not selected from the f(mu) for the nuclide. Therefore // adjust the score by the actual probability for that nuclide. @@ -2362,11 +2319,7 @@ void score_collision_tally(Particle& p) // Determine the collision estimate of the flux double flux = 0.0; if (p.type() == ParticleType::neutron || p.type() == ParticleType::photon) { - if (!settings::survival_biasing) { - flux = p.wgt_last() / p.macro_xs().total; - } else { - flux = (p.wgt_last() + p.wgt_absorb()) / p.macro_xs().total; - } + flux = p.wgt_last() / p.macro_xs().total; } for (auto i_tally : model::active_collision_tallies) { diff --git a/tests/regression_tests/tallies/results_true.dat b/tests/regression_tests/tallies/results_true.dat index c73ff33a4..6ff900331 100644 --- a/tests/regression_tests/tallies/results_true.dat +++ b/tests/regression_tests/tallies/results_true.dat @@ -1 +1 @@ -de09325b517aad9f58940e5fcd53b005c57ea008a15699769ab91aba723de141014101e55be2621e34c369beefb6db8c6cf847e241ee26e73e394c0f155138b0 \ No newline at end of file +683a82a10c4254c7e503f9c86e192070224c0d19c1817e51da7acd74b9529a475020a6cbd658644f7cd18b244cc477d1810521aa720c4fa9354cb6955bce13f6 \ No newline at end of file From f18caa1712a2a511ab4923be44c67bc60574d8e6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 16 Jan 2022 15:13:36 -0600 Subject: [PATCH 0009/2654] Get rid of wgt_absorb in ParticleData --- include/openmc/particle_data.h | 3 --- src/physics.cpp | 10 +++---- src/physics_mg.cpp | 8 +++--- src/tallies/tally_scoring.cpp | 49 +++++++++++++++++++++------------- 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 38c0aa1df..a1804f7be 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -244,7 +244,6 @@ private: Position r_last_; //!< previous coordinates Direction u_last_; //!< previous direction coordinates double wgt_last_ {1.0}; //!< pre-collision particle weight - double wgt_absorb_ {0.0}; //!< weight absorbed for survival biasing // What event took place bool fission_ {false}; //!< did particle cause implicit fission @@ -375,8 +374,6 @@ public: const Position& u_last() const { return u_last_; } double& wgt_last() { return wgt_last_; } const double& wgt_last() const { return wgt_last_; } - double& wgt_absorb() { return wgt_absorb_; } - const double& wgt_absorb() const { return wgt_absorb_; } bool& fission() { return fission_; } TallyEvent& event() { return event_; } diff --git a/src/physics.cpp b/src/physics.cpp index f6fc31cb9..345b79947 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -134,8 +134,6 @@ void sample_neutron_reaction(Particle& p) if (p.neutron_xs(i_nuclide).absorption > 0.0) { absorption(p, i_nuclide); - } else { - p.wgt_absorb() = 0.0; } if (!p.alive()) return; @@ -626,15 +624,15 @@ void absorption(Particle& p, int i_nuclide) { if (settings::survival_biasing) { // Determine weight absorbed in survival biasing - p.wgt_absorb() = p.wgt() * p.neutron_xs(i_nuclide).absorption / - p.neutron_xs(i_nuclide).total; + double wgt_absorb = p.wgt() * p.neutron_xs(i_nuclide).absorption / + p.neutron_xs(i_nuclide).total; // Adjust weight of particle by probability of absorption - p.wgt() -= p.wgt_absorb(); + p.wgt() -= wgt_absorb; // Score implicit absorption estimate of keff if (settings::run_mode == RunMode::EIGENVALUE) { - p.keff_tally_absorption() += p.wgt_absorb() * + p.keff_tally_absorption() += wgt_absorb * p.neutron_xs(i_nuclide).nu_fission / p.neutron_xs(i_nuclide).absorption; } diff --git a/src/physics_mg.cpp b/src/physics_mg.cpp index ce7db3faf..d363c2d8e 100644 --- a/src/physics_mg.cpp +++ b/src/physics_mg.cpp @@ -55,8 +55,6 @@ void sample_reaction(Particle& p) // weight of the particle. Otherwise, it checks to see if absorption occurs. if (p.macro_xs().absorption > 0.) { absorption(p); - } else { - p.wgt_absorb() = 0.; } if (!p.alive()) return; @@ -216,14 +214,14 @@ void absorption(Particle& p) { if (settings::survival_biasing) { // Determine weight absorbed in survival biasing - p.wgt_absorb() = p.wgt() * p.macro_xs().absorption / p.macro_xs().total; + double wgt_absorb = p.wgt() * p.macro_xs().absorption / p.macro_xs().total; // Adjust weight of particle by the probability of absorption - p.wgt() -= p.wgt_absorb(); + p.wgt() -= wgt_absorb; // Score implicit absorpion estimate of keff p.keff_tally_absorption() += - p.wgt_absorb() * p.macro_xs().nu_fission / p.macro_xs().absorption; + wgt_absorb * p.macro_xs().nu_fission / p.macro_xs().absorption; } else { if (p.macro_xs().absorption > prn(p.current_seed()) * p.macro_xs().total) { p.keff_tally_absorption() += diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index 8c91314aa..bd516ca18 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -546,6 +546,14 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // Get the pre-collision energy of the particle. auto E = p.E_last(); + // Determine how much weight was absorbed due to survival biasing + double wgt_absorb = 0.0; + if (tally.estimator_ == TallyEstimator::ANALOG && + settings::survival_biasing) { + wgt_absorb = p.wgt_last() * p.neutron_xs(p.event_nuclide()).absorption / + p.neutron_xs(p.event_nuclide()).total; + } + using Type = ParticleType; for (auto i = 0; i < tally.scores_.size(); ++i) { @@ -614,7 +622,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, continue; // Since only scattering events make it here, again we can use the // weight entering the collision as the estimator for the reaction rate - score = (p.wgt_last() - p.wgt_absorb()) * flux; + score = (p.wgt_last() - wgt_absorb) * flux; } else { if (i_nuclide >= 0) { if (p.type() == Type::neutron) { @@ -645,7 +653,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // For scattering production, we need to use the pre-collision weight // times the yield as the estimate for the number of neutrons exiting a // reaction with neutrons in the exit channel - score = (p.wgt_last() - p.wgt_absorb()) * flux; + score = (p.wgt_last() - wgt_absorb) * flux; // Don't waste time on very common reactions we know have multiplicities // of one. @@ -667,7 +675,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (settings::survival_biasing) { // No absorption events actually occur if survival biasing is on -- // just use weight absorbed in survival biasing - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; } else { // Skip any event where the particle wasn't absorbed if (p.event() == TallyEvent::SCATTER) @@ -1240,7 +1248,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // Check if event MT matches if (p.event_mt() != ELASTIC) continue; - score = (p.wgt_last() - p.wgt_absorb()) * flux; + score = (p.wgt_last() - wgt_absorb) * flux; } else { if (i_nuclide >= 0) { if (p.neutron_xs(i_nuclide).elastic == CACHE_INVALID) @@ -1289,7 +1297,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // Check if the event MT matches if (p.event_mt() != score_bin) continue; - score = (p.wgt_last() - p.wgt_absorb()) * flux; + score = (p.wgt_last() - wgt_absorb) * flux; } else { int m; switch (score_bin) { @@ -1405,7 +1413,7 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // to check if it matches the MT number of the event if (p.event_mt() != score_bin) continue; - score = (p.wgt_last() - p.wgt_absorb()) * flux; + score = (p.wgt_last() - wgt_absorb) * flux; } else { // Any other cross section has to be calculated on-the-fly if (score_bin < 2) @@ -1452,10 +1460,13 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // Set the direction and group to use with get_xs Direction p_u; int p_g; + double wgt_absorb = 0.0; if (tally.estimator_ == TallyEstimator::ANALOG || tally.estimator_ == TallyEstimator::COLLISION) { - if (settings::survival_biasing) { + // Determine weight that was absorbed + wgt_absorb = p.wgt_last() * p.neutron_xs(p.event_nuclide()).absorption / + p.neutron_xs(p.event_nuclide()).total; // Then we either are alive and had a scatter (and so g changed), // or are dead and g did not change @@ -1563,7 +1574,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, continue; // Since only scattering events make it here, again we can use the // weight entering the collision as the estimator for the reaction rate - score = (p.wgt_last() - p.wgt_absorb()) * flux; + score = (p.wgt_last() - wgt_absorb) * flux; if (i_nuclide >= 0) { score *= atom_density * nuc_xs.get_xs(MgxsType::SCATTER_FMU, p.g_last(), &p.g(), @@ -1591,7 +1602,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // For scattering production, we need to use the pre-collision weight // times the multiplicity as the estimate for the number of neutrons // exiting a reaction with neutrons in the exit channel - score = (p.wgt_last() - p.wgt_absorb()) * flux; + score = (p.wgt_last() - wgt_absorb) * flux; // Since we transport based on material data, the angle selected // was not selected from the f(mu) for the nuclide. Therefore // adjust the score by the actual probability for that nuclide. @@ -1617,7 +1628,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, if (settings::survival_biasing) { // No absorption events actually occur if survival biasing is on -- // just use weight absorbed in survival biasing - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; } else { // Skip any event where the particle wasn't absorbed if (p.event() == TallyEvent::SCATTER) @@ -1646,7 +1657,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // No fission events occur if survival biasing is on -- need to // calculate fraction of absorptions that would have resulted in // fission - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; } else { // Skip any non-absorption events if (p.event() == TallyEvent::SCATTER) @@ -1686,7 +1697,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // No fission events occur if survival biasing is on -- need to // calculate fraction of absorptions that would have resulted in // nu-fission - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; if (i_nuclide >= 0) { score *= atom_density * nuc_xs.get_xs(MgxsType::NU_FISSION, p_g) / macro_xs.get_xs(MgxsType::ABSORPTION, p_g); @@ -1733,7 +1744,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // No fission events occur if survival biasing is on -- need to // calculate fraction of absorptions that would have resulted in // prompt-nu-fission - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; if (i_nuclide >= 0) { score *= atom_density * nuc_xs.get_xs(MgxsType::PROMPT_NU_FISSION, p_g) / @@ -1794,7 +1805,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // Tally each delayed group bin individually for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { auto d = filt.groups()[d_bin] - 1; - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; if (i_nuclide >= 0) { score *= nuc_xs.get_xs(MgxsType::DELAYED_NU_FISSION, p_g, nullptr, nullptr, &d) / @@ -1812,7 +1823,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // If the delayed group filter is not present, compute the score // by multiplying the absorbed weight by the fraction of the // delayed-nu-fission xs to the absorption xs - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; if (i_nuclide >= 0) { score *= nuc_xs.get_xs(MgxsType::DELAYED_NU_FISSION, p_g) / abs_xs; @@ -1909,7 +1920,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // Tally each delayed group bin individually for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { auto d = filt.groups()[d_bin] - 1; - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; if (i_nuclide >= 0) { score *= nuc_xs.get_xs( MgxsType::DECAY_RATE, p_g, nullptr, nullptr, &d) * @@ -1935,14 +1946,14 @@ void score_general_mg(Particle& p, int i_tally, int start_index, score = 0.; for (auto d = 0; d < data::mg.num_delayed_groups_; ++d) { if (i_nuclide >= 0) { - score += p.wgt_absorb() * flux * + score += wgt_absorb * flux * nuc_xs.get_xs( MgxsType::DECAY_RATE, p_g, nullptr, nullptr, &d) * nuc_xs.get_xs(MgxsType::DELAYED_NU_FISSION, p_g, nullptr, nullptr, &d) / abs_xs; } else { - score += p.wgt_absorb() * flux * + score += wgt_absorb * flux * macro_xs.get_xs( MgxsType::DECAY_RATE, p_g, nullptr, nullptr, &d) * macro_xs.get_xs(MgxsType::DELAYED_NU_FISSION, p_g, @@ -2050,7 +2061,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, // No fission events occur if survival biasing is on -- need to // calculate fraction of absorptions that would have resulted in // fission scaled by the Q-value - score = p.wgt_absorb() * flux; + score = wgt_absorb * flux; } else { // Skip any non-absorption events if (p.event() == TallyEvent::SCATTER) From de50a7bfcac3378b1c4ac233f14d8aa9d1bcd10b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 19 Jan 2022 09:14:41 -0600 Subject: [PATCH 0010/2654] Generalize russian_roulette function --- include/openmc/physics_common.h | 4 +++- src/physics.cpp | 6 +++--- src/physics_common.cpp | 14 ++++++-------- src/physics_mg.cpp | 6 +++--- src/weight_windows.cpp | 11 +++-------- 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/include/openmc/physics_common.h b/include/openmc/physics_common.h index 1398557dc..2c5e79dad 100644 --- a/include/openmc/physics_common.h +++ b/include/openmc/physics_common.h @@ -9,7 +9,9 @@ namespace openmc { //! \brief Performs the russian roulette operation for a particle -void russian_roulette(Particle& p); +//! \param[in,out] p Particle object +//! \param[in] weight_cutoff Weight below which particles are rouletted +void russian_roulette(Particle& p, double weight_survive); } // namespace openmc #endif // OPENMC_PHYSICS_COMMON_H diff --git a/src/physics.cpp b/src/physics.cpp index 345b79947..01af1259f 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -151,9 +151,9 @@ void sample_neutron_reaction(Particle& p) // Play russian roulette if survival biasing is turned on if (settings::survival_biasing) { - russian_roulette(p); - if (!p.alive()) - return; + if (p.wgt() < settings::weight_cutoff) { + russian_roulette(p, settings::weight_survive); + } } } diff --git a/src/physics_common.cpp b/src/physics_common.cpp index 964678fbe..7e65c9bbf 100644 --- a/src/physics_common.cpp +++ b/src/physics_common.cpp @@ -9,15 +9,13 @@ namespace openmc { // RUSSIAN_ROULETTE //============================================================================== -void russian_roulette(Particle& p) +void russian_roulette(Particle& p, double weight_survive) { - if (p.wgt() < settings::weight_cutoff) { - if (settings::weight_survive * prn(p.current_seed()) < p.wgt()) { - p.wgt() = settings::weight_survive; - } else { - p.wgt() = 0.; - p.alive() = false; - } + if (weight_survive * prn(p.current_seed()) < p.wgt()) { + p.wgt() = weight_survive; + } else { + p.wgt() = 0.; + p.alive() = false; } } diff --git a/src/physics_mg.cpp b/src/physics_mg.cpp index d363c2d8e..6e89fde5e 100644 --- a/src/physics_mg.cpp +++ b/src/physics_mg.cpp @@ -64,9 +64,9 @@ void sample_reaction(Particle& p) // Play Russian roulette if survival biasing is turned on if (settings::survival_biasing) { - russian_roulette(p); - if (!p.alive()) - return; + if (p.wgt() < settings::weight_cutoff) { + russian_roulette(p, settings::weight_survive); + } } } diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index e742d48c3..e753fc6ac 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -5,6 +5,7 @@ #include "openmc/hdf5_interface.h" #include "openmc/particle.h" #include "openmc/particle_data.h" +#include "openmc/physics_common.h" #include "openmc/search.h" #include "openmc/xml_interface.h" @@ -94,14 +95,8 @@ void apply_weight_windows(Particle& p) // if the particle weight is below the window, play Russian roulette double weight_survive = std::min(weight * weight_window.max_split, weight_window.survival_weight); - if (weight_survive * prn(p.current_seed()) <= weight) { - p.wgt() = weight_survive; - } else { - p.alive() = false; - p.wgt() = 0.0; - } - // else particle is in the window, continue as normal - } + russian_roulette(p, weight_survive); + } // else particle is in the window, continue as normal } void free_memory_weight_windows() From 3944c2f1e84838c7004a8bebf344a045429a30ad Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 15 Feb 2022 11:11:18 -0600 Subject: [PATCH 0011/2654] Fix bug in Halfspace.rotate when rotation matrix is passed --- openmc/surface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/surface.py b/openmc/surface.py index 146e16c28..f2b496f72 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -2633,7 +2633,7 @@ class Halfspace(Region): memo = {} # If rotated surface not in memo, add it - key = (self.surface, tuple(rotation), tuple(pivot), order, inplace) + key = (self.surface, tuple(np.ravel(rotation)), tuple(pivot), order, inplace) if key not in memo: memo[key] = self.surface.rotate(rotation, pivot=pivot, order=order, inplace=inplace) From ceb6687e1cc9d2fdec887f9dcaac9211acfca116 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 15 Feb 2022 15:34:57 -0600 Subject: [PATCH 0012/2654] Update survival_biasing regression test --- .../survival_biasing/results_true.dat | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/survival_biasing/results_true.dat b/tests/regression_tests/survival_biasing/results_true.dat index b9868f3d3..edd968340 100644 --- a/tests/regression_tests/survival_biasing/results_true.dat +++ b/tests/regression_tests/survival_biasing/results_true.dat @@ -1,10 +1,10 @@ k-combined: 9.826269E-01 1.626276E-02 tally 1: -4.212303E+01 -3.550855E+02 -1.760388E+01 -6.205773E+01 +4.209907E+01 +3.546281E+02 +1.759415E+01 +6.197412E+01 2.165888E+00 9.392975E-01 1.873459E+00 @@ -16,5 +16,5 @@ tally 1: 3.628554E+08 2.635633E+16 tally 2: -1.760388E+01 -6.205773E+01 +1.759415E+01 +6.197412E+01 From 3e6eba4439f14d57c29f58b8a2711128e83e718a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Feb 2022 09:34:34 -0600 Subject: [PATCH 0013/2654] Respond to @gridley comments on #1974 --- include/openmc/physics_common.h | 2 +- src/physics.cpp | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/openmc/physics_common.h b/include/openmc/physics_common.h index 2c5e79dad..e38a3c7f8 100644 --- a/include/openmc/physics_common.h +++ b/include/openmc/physics_common.h @@ -10,7 +10,7 @@ namespace openmc { //! \brief Performs the russian roulette operation for a particle //! \param[in,out] p Particle object -//! \param[in] weight_cutoff Weight below which particles are rouletted +//! \param[in] weight_survive Weight assigned to particles that survive void russian_roulette(Particle& p, double weight_survive); } // namespace openmc diff --git a/src/physics.cpp b/src/physics.cpp index 01af1259f..63d764b67 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -624,8 +624,8 @@ void absorption(Particle& p, int i_nuclide) { if (settings::survival_biasing) { // Determine weight absorbed in survival biasing - double wgt_absorb = p.wgt() * p.neutron_xs(i_nuclide).absorption / - p.neutron_xs(i_nuclide).total; + const double wgt_absorb = p.wgt() * p.neutron_xs(i_nuclide).absorption / + p.neutron_xs(i_nuclide).total; // Adjust weight of particle by probability of absorption p.wgt() -= wgt_absorb; @@ -949,9 +949,8 @@ Direction sample_target_velocity(const Nuclide& nuc, double E, Direction u, // cdf value at upper bound attainable energy double m = (nuc.xs_cdf_[i_E_up + 1] - nuc.xs_cdf_[i_E_up]) / - (nuc.energy_0K_[i_E_up + 1] - nuc.energy_0K_[i_E_up]); - double cdf_up = - nuc.xs_cdf_[i_E_up] + m * (E_up - nuc.energy_0K_[i_E_up]); + (nuc.energy_0K_[i_E_up + 1] - nuc.energy_0K_[i_E_up]); + double cdf_up = nuc.xs_cdf_[i_E_up] + m * (E_up - nuc.energy_0K_[i_E_up]); while (true) { // directly sample Maxwellian @@ -959,9 +958,8 @@ Direction sample_target_velocity(const Nuclide& nuc, double E, Direction u, // sample a relative energy using the xs cdf double cdf_rel = cdf_low + prn(seed) * (cdf_up - cdf_low); - int i_E_rel = lower_bound_index(nuc.xs_cdf_.begin() + i_E_low, - nuc.xs_cdf_.begin() + i_E_up+2, - cdf_rel); + int i_E_rel = lower_bound_index(nuc.xs_cdf_.begin() + i_E_low, + nuc.xs_cdf_.begin() + i_E_up + 2, cdf_rel); double E_rel = nuc.energy_0K_[i_E_low + i_E_rel]; double m = (nuc.xs_cdf_[i_E_low + i_E_rel + 1] - nuc.xs_cdf_[i_E_low + i_E_rel]) / From 30fdbaeb1313b1daa57e89bdb1f86f2ebf0ed20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 16 Feb 2022 12:42:43 -0500 Subject: [PATCH 0014/2654] Tiny typo --- docs/source/usersguide/troubleshoot.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/troubleshoot.rst b/docs/source/usersguide/troubleshoot.rst index dd1c86a13..06e5c5704 100644 --- a/docs/source/usersguide/troubleshoot.rst +++ b/docs/source/usersguide/troubleshoot.rst @@ -80,7 +80,7 @@ high enough to produce any pixels in the overlapping area. To reliably validate a geometry input, it is best to run the problem in geometry debugging mode with the ``-g``, ``-geometry-debug``, or ``--geometry-debug`` command-line options. This will enable checks for -overlapping cells at every move of esch simulated particle. Depending on the +overlapping cells at every move of each simulated particle. Depending on the complexity of the geometry input file, this could add considerable overhead to the run (these runs can still be done in parallel). As a result, for this run mode the user will probably want to run fewer particles than a normal From e2c432484ecda9c4a9dc85996c57070ff7c04aa1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Feb 2022 08:39:18 -0600 Subject: [PATCH 0015/2654] Reworking main for loop of get_filter_indices based on comments from @paulromano --- openmc/tallies.py | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 436e3189e..fbf1efa3c 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1092,29 +1092,16 @@ class Tally(IDManagerMixin): for i, self_filter in enumerate(self.filters): # If a user-requested Filter, get the user-requested bins for j, test_filter in enumerate(filters): + if type(self_filter) is openmc.EnergyFunctionFilter: + indices = [self_filter.get_bin_index(None)] + break if type(self_filter) is test_filter: bins = filter_bins[j] + indices = np.array([self_filter.get_bin_index(b) for b in bins]) break else: - # If not a user-requested Filter, get all bins - if isinstance(self_filter, openmc.DistribcellFilter): - # Create list of cell instance IDs for distribcell Filters - bins = list(range(self_filter.num_bins)) + indices = np.arange(self_filter.num_bins) - elif isinstance(self_filter, openmc.EnergyFunctionFilter): - # EnergyFunctionFilters don't have bins so just add a None - bins = [None] - - else: - # Create list of IDs for bins for all other filter types - bins = self_filter.bins - - # Add indices for each bin in this Filter to the list - - if type(self_filter) in filters: - indices = np.array([self_filter.get_bin_index(b) for b in bins]) - else: - indices = np.arange(len(bins)) filter_indices.append(indices) # Account for stride in each of the previous filters From 9a28bc8da14dfca15b3fb95c20029497e10813ab Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Feb 2022 15:26:51 -0600 Subject: [PATCH 0016/2654] Removing special case for EnergyFunctionFilter --- openmc/tallies.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index fbf1efa3c..db2ef6570 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1092,9 +1092,6 @@ class Tally(IDManagerMixin): for i, self_filter in enumerate(self.filters): # If a user-requested Filter, get the user-requested bins for j, test_filter in enumerate(filters): - if type(self_filter) is openmc.EnergyFunctionFilter: - indices = [self_filter.get_bin_index(None)] - break if type(self_filter) is test_filter: bins = filter_bins[j] indices = np.array([self_filter.get_bin_index(b) for b in bins]) From 9aff0b4b9c91aaaaf9613b38f00f4487fb637d72 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 18 Feb 2022 15:21:14 +0000 Subject: [PATCH 0017/2654] removed dev install -e for regular install --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 739998864..dd12f826d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -201,7 +201,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ -DHDF5_PREFER_PARALLEL=on ; \ fi ; \ make 2>/dev/null -j${compile_cores} install \ - && cd ../openmc && pip install -e .[test,depletion-mpi] + && cd ../openmc && pip install .[test,depletion-mpi] # Download cross sections (NNDC and WMP) and ENDF data needed by test suite RUN ${HOME}/OpenMC/openmc/tools/ci/download-xs.sh From 8d002454f0b9c3813485973dbbe38b31a2fe719d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 10 Feb 2022 10:05:50 -0600 Subject: [PATCH 0018/2654] Add Reaction::xs methods --- include/openmc/reaction.h | 13 ++++++++++ src/physics.cpp | 45 ++++++++++------------------------- src/reaction.cpp | 17 +++++++++++++ src/tallies/tally_scoring.cpp | 38 +++++++++++------------------ 4 files changed, 56 insertions(+), 57 deletions(-) diff --git a/include/openmc/reaction.h b/include/openmc/reaction.h index 46705acf5..93987d9d7 100644 --- a/include/openmc/reaction.h +++ b/include/openmc/reaction.h @@ -9,6 +9,7 @@ #include "hdf5.h" #include +#include "openmc/particle_data.h" #include "openmc/reaction_product.h" #include "openmc/vector.h" @@ -27,6 +28,18 @@ public: //! \param[in] temperatures Desired temperatures for cross sections explicit Reaction(hid_t group, const vector& temperatures); + //! Calculate cross section given temperautre/grid index, interpolation factor + // + //! \param[in] i_temp Temperature index + //! \param[in] i_grid Energy grid index + //! \param[in] interp_factor Interpolation factor between grid points + double xs(gsl::index i_temp, gsl::index i_grid, double interp_factor) const; + + //! Calculate cross section + // + //! \param[in] micro Microscopic cross section cache + double xs(const NuclideMicroXS& micro) const; + //! \brief Calculate reaction rate based on group-wise flux distribution // //! \param[in] i_temp Temperature index diff --git a/src/physics.cpp b/src/physics.cpp index 63d764b67..edc581c42 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -541,23 +541,15 @@ Reaction& sample_fission(int i_nuclide, Particle& p) } } - // Get grid index and interpolatoin factor and sample fission cdf - int i_temp = p.neutron_xs(i_nuclide).index_temp; - int i_grid = p.neutron_xs(i_nuclide).index_grid; - double f = p.neutron_xs(i_nuclide).interp_factor; + // Get grid index and interpolation factor and sample fission cdf + const auto& micro = p.neutron_xs(i_nuclide); double cutoff = prn(p.current_seed()) * p.neutron_xs(i_nuclide).fission; double prob = 0.0; // Loop through each partial fission reaction type for (auto& rx : nuc->fission_rx_) { - // if energy is below threshold for this reaction, skip it - int threshold = rx->xs_[i_temp].threshold; - if (i_grid < threshold) - continue; - // add to cumulative probability - prob += (1.0 - f) * rx->xs_[i_temp].value[i_grid - threshold] + - f * rx->xs_[i_temp].value[i_grid - threshold + 1]; + prob += rx->xs(micro); // Create fission bank sites if fission occurs if (prob > cutoff) @@ -573,25 +565,20 @@ void sample_photon_product( int i_nuclide, Particle& p, int* i_rx, int* i_product) { // Get grid index and interpolation factor and sample photon production cdf - int i_temp = p.neutron_xs(i_nuclide).index_temp; - int i_grid = p.neutron_xs(i_nuclide).index_grid; - double f = p.neutron_xs(i_nuclide).interp_factor; - double cutoff = prn(p.current_seed()) * p.neutron_xs(i_nuclide).photon_prod; + const auto& micro = p.neutron_xs(i_nuclide); + double cutoff = prn(p.current_seed()) * micro.photon_prod; double prob = 0.0; // Loop through each reaction type const auto& nuc {data::nuclides[i_nuclide]}; for (int i = 0; i < nuc->reactions_.size(); ++i) { - const auto& rx = nuc->reactions_[i]; - int threshold = rx->xs_[i_temp].threshold; - - // if energy is below threshold for this reaction, skip it - if (i_grid < threshold) - continue; - // Evaluate neutron cross section - double xs = ((1.0 - f) * rx->xs_[i_temp].value[i_grid - threshold] + - f * (rx->xs_[i_temp].value[i_grid - threshold + 1])); + const auto& rx = nuc->reactions_[i]; + double xs = rx->xs(micro); + + // if cross section is zero for this reaction, skip it + if (xs == 0.0) + continue; for (int j = 0; j < rx->products_.size(); ++j) { if (rx->products_[j].particle_ == ParticleType::photon) { @@ -663,8 +650,6 @@ void scatter(Particle& p, int i_nuclide) const auto& nuc {data::nuclides[i_nuclide]}; const auto& micro {p.neutron_xs(i_nuclide)}; int i_temp = micro.index_temp; - int i_grid = micro.index_grid; - double f = micro.interp_factor; // For tallying purposes, this routine might be called directly. In that // case, we need to sample a reaction via the cutoff variable @@ -718,14 +703,8 @@ void scatter(Particle& p, int i_nuclide) fatal_error("Did not sample any reaction for nuclide " + nuc->name_); } - // if energy is below threshold for this reaction, skip it - const auto& xs {nuc->reactions_[i]->xs_[i_temp]}; - if (i_grid < xs.threshold) - continue; - // add to cumulative probability - prob += (1.0 - f) * xs.value[i_grid - xs.threshold] + - f * xs.value[i_grid - xs.threshold + 1]; + prob += nuc->reactions_[i]->xs(micro); } // Perform collision physics for inelastic scattering diff --git a/src/reaction.cpp b/src/reaction.cpp index c929677f2..ec9d32f9a 100644 --- a/src/reaction.cpp +++ b/src/reaction.cpp @@ -65,6 +65,23 @@ Reaction::Reaction(hid_t group, const vector& temperatures) } } +double Reaction::xs( + gsl::index i_temp, gsl::index i_grid, double interp_factor) const +{ + // If energy is below threshold, return 0. Otherwise interpolate between + // nearest grid points + const auto& x = xs_[i_temp]; + return (i_grid < x.threshold) + ? 0.0 + : (1.0 - interp_factor) * x.value[i_grid - x.threshold] + + interp_factor * x.value[i_grid - x.threshold + 1]; +} + +double Reaction::xs(const NuclideMicroXS& micro) const +{ + return this->xs(micro.index_temp, micro.index_grid, micro.interp_factor); +} + double Reaction::collapse_rate(gsl::index i_temp, gsl::span energy, gsl::span flux, const vector& grid) const diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index bd516ca18..b06570b99 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -251,20 +251,16 @@ double get_nuclide_neutron_heating( if (mt == C_NONE) return 0.0; - auto i_temp = p.neutron_xs(i_nuclide).index_temp; + const auto& micro = p.neutron_xs(i_nuclide); + auto i_temp = micro.index_temp; if (i_temp < 0) return 0.0; // Can be true due to multipole - const auto& rxn {*nuc.reactions_[mt]}; - const auto& xs {rxn.xs_[i_temp]}; - auto i_grid = p.neutron_xs(i_nuclide).index_grid; - if (i_grid < xs.threshold) - return 0.0; - // Determine total kerma - auto f = p.neutron_xs(i_nuclide).interp_factor; - double kerma = (1.0 - f) * xs.value[i_grid - xs.threshold] + - f * xs.value[i_grid - xs.threshold + 1]; + const auto& rx {*nuc.reactions_[mt]}; + double kerma = rx.xs(micro); + if (kerma == 0.0) + return 0.0; if (settings::run_mode == RunMode::EIGENVALUE) { // Determine kerma for fission as (EFR + EB)*sigma_f @@ -477,7 +473,7 @@ double get_nuclide_xs(const Particle& p, int i_nuclide, int score_bin) auto m = nuc.reaction_index_[score_bin]; if (m == C_NONE) return 0.0; - const auto& rxn {*nuc.reactions_[m]}; + const auto& rx {*nuc.reactions_[m]}; const auto& micro {p.neutron_xs(i_nuclide)}; // In the URR, the (n,gamma) cross section is sampled randomly from @@ -494,14 +490,7 @@ double get_nuclide_xs(const Particle& p, int i_nuclide, int score_bin) auto f = micro.interp_factor; // Calculate interpolated cross section - const auto& xs {rxn.xs_[i_temp]}; - double value; - if (i_grid >= xs.threshold) { - value = ((1.0 - f) * xs.value[i_grid - xs.threshold] + - f * xs.value[i_grid - xs.threshold + 1]); - } else { - value = 0.0; - } + double xs = rx.xs(micro); if (settings::run_mode == RunMode::EIGENVALUE && score_bin == HEATING_LOCAL) { @@ -515,18 +504,18 @@ double get_nuclide_xs(const Particle& p, int i_nuclide, int score_bin) : 0.0; // Determine non-fission kerma as difference - double kerma_non_fission = value - kerma_fission; + double kerma_non_fission = xs - kerma_fission; // Re-weight non-fission kerma by keff to properly balance energy release // and deposition. See D. P. Griesheimer, S. J. Douglass, and M. H. // Stedry, "Self-consistent energy normalization for quasistatic reactor // calculations", Proc. PHYSOR, Cambridge, UK, Mar 29-Apr 2, 2020. - value = simulation::keff * kerma_non_fission + kerma_fission; + xs = simulation::keff * kerma_non_fission + kerma_fission; } - return value; + return xs; } else { // For multipole, calculate (n,gamma) from other reactions - return rxn.mt_ == N_GAMMA ? micro.absorption - micro.fission : 0.0; + return rx.mt_ == N_GAMMA ? micro.absorption - micro.fission : 0.0; } return 0.0; } @@ -1497,7 +1486,8 @@ void score_general_mg(Particle& p, int i_tally, int start_index, } // For shorthand, assign pointers to the material and nuclide xs set - auto& nuc_xs = (i_nuclide >= 0) ? data::mg.nuclides_[i_nuclide] : data::mg.macro_xs_[p.material()]; + auto& nuc_xs = (i_nuclide >= 0) ? data::mg.nuclides_[i_nuclide] + : data::mg.macro_xs_[p.material()]; auto& macro_xs = data::mg.macro_xs_[p.material()]; // Find the temperature and angle indices of interest From af4a8400c5d7f6dd416cf1ce676332f67420618b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 10 Feb 2022 23:29:43 -0600 Subject: [PATCH 0019/2654] Remove archaic 'all' nuclides tally feature --- include/openmc/tallies/tally.h | 3 - src/tallies/tally.cpp | 20 +-- src/tallies/tally_scoring.cpp | 151 +++++------------- .../regression_tests/tallies/inputs_true.dat | 26 +-- .../regression_tests/tallies/results_true.dat | 2 +- tests/regression_tests/tallies/test.py | 14 +- 6 files changed, 50 insertions(+), 166 deletions(-) diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h index 13b8317ee..73618a3da 100644 --- a/include/openmc/tallies/tally.h +++ b/include/openmc/tallies/tally.h @@ -104,9 +104,6 @@ public: //! Index of each nuclide to be tallied. -1 indicates total material. vector nuclides_ {-1}; - //! True if this tally has a bin for every nuclide in the problem - bool all_nuclides_ {false}; - //! Results for each bin -- the first dimension of the array is for the //! combination of filters (e.g. specific cell, specific energy group, etc.) //! and the second dimension of the array is for scores (e.g. flux, total diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 2d673d7bc..c0fedd973 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -542,22 +542,10 @@ void Tally::set_nuclides(pugi::xml_node node) return; } - if (get_node_value(node, "nuclides") == "all") { - // This tally should bin every nuclide in the problem. It should also bin - // the total material rates. To achieve this, set the nuclides_ vector to - // 0, 1, 2, ..., -1. - nuclides_.reserve(data::nuclides.size() + 1); - for (auto i = 0; i < data::nuclides.size(); ++i) - nuclides_.push_back(i); - nuclides_.push_back(-1); - all_nuclides_ = true; - - } else { - // The user provided specifics nuclides. Parse it as an array with either - // "total" or a nuclide name like "U-235" in each position. - auto words = get_node_array(node, "nuclides"); - this->set_nuclides(words); - } + // The user provided specifics nuclides. Parse it as an array with either + // "total" or a nuclide name like "U235" in each position. + auto words = get_node_array(node, "nuclides"); + this->set_nuclides(words); } void Tally::set_nuclides(const vector& nuclides) diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index b06570b99..e3104f59a 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -2095,43 +2095,6 @@ void score_general_mg(Particle& p, int i_tally, int start_index, } } -//! Tally rates for when the user requests a tally on all nuclides. - -void score_all_nuclides( - Particle& p, int i_tally, double flux, int filter_index, double filter_weight) -{ - const Tally& tally {*model::tallies[i_tally]}; - const Material& material {*model::materials[p.material()]}; - - // Score all individual nuclide reaction rates. - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - - // TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, i_nuclide * tally.scores_.size(), - filter_index, filter_weight, i_nuclide, atom_density, flux); - } else { - score_general_mg(p, i_tally, i_nuclide * tally.scores_.size(), - filter_index, filter_weight, i_nuclide, atom_density, flux); - } - } - - // Score total material reaction rates. - int i_nuclide = -1; - double atom_density = 0.; - auto n_nuclides = data::nuclides.size(); - // TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, n_nuclides * tally.scores_.size(), - filter_index, filter_weight, i_nuclide, atom_density, flux); - } else { - score_general_mg(p, i_tally, n_nuclides * tally.scores_.size(), - filter_index, filter_weight, i_nuclide, atom_density, flux); - } -} - void score_analog_tally_ce(Particle& p) { // Since electrons/positrons are not transported, we assign a flux of zero. @@ -2159,30 +2122,15 @@ void score_analog_tally_ce(Particle& p) auto filter_weight = filter_iter.weight_; // Loop over nuclide bins. - if (!tally.all_nuclides_) { - for (auto i = 0; i < tally.nuclides_.size(); ++i) { - auto i_nuclide = tally.nuclides_[i]; + for (auto i = 0; i < tally.nuclides_.size(); ++i) { + auto i_nuclide = tally.nuclides_[i]; - // Tally this event in the present nuclide bin if that bin represents - // the event nuclide or the total material. Note that the atomic - // density argument for score_general is not used for analog tallies. - if (i_nuclide == p.event_nuclide() || i_nuclide == -1) - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, -1.0, flux); - } - - } else { - // In the case that the user has requested to tally all nuclides, we - // can take advantage of the fact that we know exactly how nuclide - // bins correspond to nuclide indices. First, tally the nuclide. - auto i = p.event_nuclide(); - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, -1, -1.0, flux); - - // Now tally the total material. - i = tally.nuclides_.size(); - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, -1, -1.0, flux); + // Tally this event in the present nuclide bin if that bin represents + // the event nuclide or the total material. Note that the atomic + // density argument for score_general is not used for analog tallies. + if (i_nuclide == p.event_nuclide() || i_nuclide == -1) + score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, + filter_weight, i_nuclide, -1.0, flux); } } @@ -2270,34 +2218,27 @@ void score_tracklength_tally(Particle& p, double distance) auto filter_weight = filter_iter.weight_; // Loop over nuclide bins. - if (tally.all_nuclides_) { - if (p.material() != MATERIAL_VOID) - score_all_nuclides( - p, i_tally, flux * filter_weight, filter_index, filter_weight); + for (auto i = 0; i < tally.nuclides_.size(); ++i) { + auto i_nuclide = tally.nuclides_[i]; - } else { - for (auto i = 0; i < tally.nuclides_.size(); ++i) { - auto i_nuclide = tally.nuclides_[i]; - - double atom_density = 0.; - if (i_nuclide >= 0) { - if (p.material() != MATERIAL_VOID) { - auto j = - model::materials[p.material()]->mat_nuclide_index_[i_nuclide]; - if (j == C_NONE) - continue; - atom_density = model::materials[p.material()]->atom_density_(j); - } + double atom_density = 0.; + if (i_nuclide >= 0) { + if (p.material() != MATERIAL_VOID) { + auto j = + model::materials[p.material()]->mat_nuclide_index_[i_nuclide]; + if (j == C_NONE) + continue; + atom_density = model::materials[p.material()]->atom_density_(j); } + } - // TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, atom_density, flux); - } else { - score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, atom_density, flux); - } + // TODO: consider replacing this "if" with pointers or templates + if (settings::run_CE) { + score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, + filter_weight, i_nuclide, atom_density, flux); + } else { + score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index, + filter_weight, i_nuclide, atom_density, flux); } } } @@ -2340,31 +2281,25 @@ void score_collision_tally(Particle& p) auto filter_weight = filter_iter.weight_; // Loop over nuclide bins. - if (tally.all_nuclides_) { - score_all_nuclides( - p, i_tally, flux * filter_weight, filter_index, filter_weight); + for (auto i = 0; i < tally.nuclides_.size(); ++i) { + auto i_nuclide = tally.nuclides_[i]; - } else { - for (auto i = 0; i < tally.nuclides_.size(); ++i) { - auto i_nuclide = tally.nuclides_[i]; + double atom_density = 0.; + if (i_nuclide >= 0) { + auto j = + model::materials[p.material()]->mat_nuclide_index_[i_nuclide]; + if (j == C_NONE) + continue; + atom_density = model::materials[p.material()]->atom_density_(j); + } - double atom_density = 0.; - if (i_nuclide >= 0) { - auto j = - model::materials[p.material()]->mat_nuclide_index_[i_nuclide]; - if (j == C_NONE) - continue; - atom_density = model::materials[p.material()]->atom_density_(j); - } - - // TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, atom_density, flux); - } else { - score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, atom_density, flux); - } + // TODO: consider replacing this "if" with pointers or templates + if (settings::run_CE) { + score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, + filter_weight, i_nuclide, atom_density, flux); + } else { + score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index, + filter_weight, i_nuclide, atom_density, flux); } } } diff --git a/tests/regression_tests/tallies/inputs_true.dat b/tests/regression_tests/tallies/inputs_true.dat index bc9efe97e..61daba0d4 100644 --- a/tests/regression_tests/tallies/inputs_true.dat +++ b/tests/regression_tests/tallies/inputs_true.dat @@ -446,7 +446,7 @@ 12 total - + 15 scatter @@ -499,30 +499,6 @@ collision - 13 - all - total - tracklength - - - 13 - all - total - collision - - - 2 - all - total - tracklength - - - 2 - U235 - total - tracklength - - H1-production H2-production H3-production He3-production He4-production heating damage-energy diff --git a/tests/regression_tests/tallies/results_true.dat b/tests/regression_tests/tallies/results_true.dat index 6ff900331..6739f5348 100644 --- a/tests/regression_tests/tallies/results_true.dat +++ b/tests/regression_tests/tallies/results_true.dat @@ -1 +1 @@ -683a82a10c4254c7e503f9c86e192070224c0d19c1817e51da7acd74b9529a475020a6cbd658644f7cd18b244cc477d1810521aa720c4fa9354cb6955bce13f6 \ No newline at end of file +ad28e723270c25dc46f27f1482052e381c802cb111ea8224368d4ea3d903eeaba1a3dce541957f24ec0634ed2ada6f20f97c0270c269b9bcae4b34a1b317a165 \ No newline at end of file diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index 7746a4e24..3e1c6e7ba 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -154,17 +154,6 @@ def test_tallies(): flux_tallies[1].estimator = 'analog' flux_tallies[2].estimator = 'collision' - all_nuclide_tallies = [Tally() for i in range(4)] - for t in all_nuclide_tallies: - t.filters = [cell_filter] - t.estimator = 'tracklength' - t.nuclides = ['all'] - t.scores = ['total'] - all_nuclide_tallies[1].estimator = 'collision' - all_nuclide_tallies[2].filters = [mesh_filter] - all_nuclide_tallies[3].filters = [mesh_filter] - all_nuclide_tallies[3].nuclides = ['U235'] - fusion_tally = Tally() fusion_tally.scores = ['H1-production', 'H2-production', 'H3-production', 'He3-production', 'He4-production', 'heating', 'damage-energy'] @@ -180,11 +169,10 @@ def test_tallies(): cellborn_tally, dg_tally, energy_tally, energyout_tally, transfer_tally, material_tally, mu_tally1, mu_tally2, polar_tally1, polar_tally2, polar_tally3, legendre_tally, - harmonics_tally, harmonics_tally2, harmonics_tally3, + harmonics_tally, harmonics_tally2, harmonics_tally3, universe_tally, collision_tally] model.tallies += score_tallies model.tallies += flux_tallies - model.tallies += all_nuclide_tallies model.tallies.append(fusion_tally) harness.main() From 696290f051d169251101eb83097c77e0b94541e9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 22 Feb 2022 16:45:12 -0600 Subject: [PATCH 0020/2654] Update nuclide naming in documentation --- docs/source/io_formats/tallies.rst | 8 ++++---- openmc/mgxs/mdgxs.py | 30 +++++++++++++++--------------- openmc/mgxs/mgxs.py | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/source/io_formats/tallies.rst b/docs/source/io_formats/tallies.rst index 3cde6fc85..8594bb11c 100644 --- a/docs/source/io_formats/tallies.rst +++ b/docs/source/io_formats/tallies.rst @@ -40,15 +40,15 @@ The ```` element accepts the following sub-elements: :nuclides: If specified, the scores listed will be for particular nuclides, not the - summation of reactions from all nuclides. The format for nuclides should be - [Atomic symbol]-[Mass number], e.g. "U-235". The reaction rate for all + summation of reactions from all nuclides. Nuclides are expressed using the + GNDS naming convention, e.g. "U235" or "Am242_m1". The reaction rate for all nuclides can be obtained with "total". For example, to obtain the reaction - rates for U-235, Pu-239, and all nuclides in a material, this element should + rates for U235, Pu239, and all nuclides in a material, this element should be: .. code-block:: xml - U-235 Pu-239 total + U235 Pu239 total *Default*: total diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 7a139c7f8..13aa924a1 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -110,7 +110,7 @@ class MDGXS(MGXS): being tracked. This is unity if the by_nuclide attribute is False. nuclides : Iterable of str or 'sum' The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides are not specified by the user, all nuclides in the spatial domain are included. This attribute is 'sum' if by_nuclide is false. sparse : bool @@ -303,7 +303,7 @@ class MDGXS(MGXS): subdomains : Iterable of Integral or 'all' Subdomain IDs of interest. Defaults to 'all'. nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U-235', 'U-238']). The + A list of nuclide name strings (e.g., ['U235', 'U238']). The special string 'all' will return the cross sections for all nuclides in the spatial domain. The special string 'sum' will return the cross section summed over all nuclides. Defaults to 'all'. @@ -453,7 +453,7 @@ class MDGXS(MGXS): ---------- nuclides : list of str A list of nuclide name strings - (e.g., ['U-235', 'U-238']; default is []) + (e.g., ['U235', 'U238']; default is []) groups : list of int A list of energy group indices starting at 1 for the high energies (e.g., [1, 2, 3]; default is []) @@ -565,7 +565,7 @@ class MDGXS(MGXS): Defaults to 'all'. nuclides : Iterable of str or 'all' or 'sum' The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + may be a list of nuclide name strings (e.g., ['U235', 'U238']). The special string 'all' will report the cross sections for all nuclides in the spatial domain. The special string 'sum' will report the cross sections summed over all nuclides. Defaults to 'all'. @@ -782,7 +782,7 @@ class MDGXS(MGXS): Energy groups of interest. Defaults to 'all'. nuclides : Iterable of str or 'all' or 'sum' The nuclides of the cross-sections to include in the dataframe. This - may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + may be a list of nuclide name strings (e.g., ['U235', 'U238']). The special string 'all' will include the cross sections for all nuclides in the spatial domain. The special string 'sum' will include the cross sections summed over all nuclides. Defaults @@ -990,7 +990,7 @@ class ChiDelayed(MDGXS): being tracked. This is unity if the by_nuclide attribute is False. nuclides : Iterable of str or 'sum' The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides are not specified by the user, all nuclides in the spatial domain are included. This attribute is 'sum' if by_nuclide is false. sparse : bool @@ -1006,8 +1006,8 @@ class ChiDelayed(MDGXS): """ # Store whether or not the number density should be removed for microscopic - # values of this data; since this chi data is normalized to 1.0, the - # data should not be divided by the number density + # values of this data; since this chi data is normalized to 1.0, the + # data should not be divided by the number density _divide_by_density = False def __init__(self, domain=None, domain_type=None, energy_groups=None, @@ -1107,7 +1107,7 @@ class ChiDelayed(MDGXS): ---------- nuclides : list of str A list of nuclide name strings - (e.g., ['U-235', 'U-238']; default is []) + (e.g., ['U235', 'U238']; default is []) groups : list of Integral A list of energy group indices starting at 1 for the high energies (e.g., [1, 2, 3]; default is []) @@ -1241,7 +1241,7 @@ class ChiDelayed(MDGXS): subdomains : Iterable of Integral or 'all' Subdomain IDs of interest. Defaults to 'all'. nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U-235', 'U-238']). The + A list of nuclide name strings (e.g., ['U235', 'U238']). The special string 'all' will return the cross sections for all nuclides in the spatial domain. The special string 'sum' will return the cross section summed over all nuclides. Defaults to 'all'. @@ -1506,7 +1506,7 @@ class DelayedNuFissionXS(MDGXS): being tracked. This is unity if the by_nuclide attribute is False. nuclides : Iterable of str or 'sum' The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides are not specified by the user, all nuclides in the spatial domain are included. This attribute is 'sum' if by_nuclide is false. sparse : bool @@ -1642,7 +1642,7 @@ class Beta(MDGXS): being tracked. This is unity if the by_nuclide attribute is False. nuclides : Iterable of str or 'sum' The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides are not specified by the user, all nuclides in the spatial domain are included. This attribute is 'sum' if by_nuclide is false. sparse : bool @@ -1832,7 +1832,7 @@ class DecayRate(MDGXS): being tracked. This is unity if the by_nuclide attribute is False. nuclides : Iterable of str or 'sum' The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides are not specified by the user, all nuclides in the spatial domain are included. This attribute is 'sum' if by_nuclide is false. sparse : bool @@ -1935,7 +1935,7 @@ class DecayRate(MDGXS): subdomains : Iterable of Integral or 'all' Subdomain IDs of interest. Defaults to 'all'. nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U-235', 'U-238']). The + A list of nuclide name strings (e.g., ['U235', 'U238']). The special string 'all' will return the cross sections for all nuclides in the spatial domain. The special string 'sum' will return the cross section summed over all nuclides. Defaults to 'all'. @@ -2738,7 +2738,7 @@ class DelayedNuFissionMatrixXS(MatrixMDGXS): being tracked. This is unity if the by_nuclide attribute is False. nuclides : Iterable of str or 'sum' The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides are not specified by the user, all nuclides in the spatial domain are included. This attribute is 'sum' if by_nuclide is false. sparse : bool diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index ff739fe85..fe8883135 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -6455,7 +6455,7 @@ class InverseVelocity(MGXS): being tracked. This is unity if the by_nuclide attribute is False. nuclides : Iterable of str or 'sum' The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides are not specified by the user, all nuclides in the spatial domain are included. This attribute is 'sum' if by_nuclide is false. sparse : bool From 96d0726e42c5ecb00cb2a5bc2bc6ae746bc9d802 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 23 Feb 2022 06:35:05 -0600 Subject: [PATCH 0021/2654] Fix failing tests that were using "all" in tally nuclides --- tests/regression_tests/tally_nuclides/tallies.xml | 2 +- tests/regression_tests/trigger_batch_interval/tallies.xml | 2 +- tests/regression_tests/trigger_no_batch_interval/tallies.xml | 2 +- tests/regression_tests/trigger_no_status/tallies.xml | 2 +- tests/regression_tests/trigger_tallies/tallies.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/regression_tests/tally_nuclides/tallies.xml b/tests/regression_tests/tally_nuclides/tallies.xml index 3440dbf21..ea25596a4 100644 --- a/tests/regression_tests/tally_nuclides/tallies.xml +++ b/tests/regression_tests/tally_nuclides/tallies.xml @@ -2,7 +2,7 @@ - all + Pu239 total total absorption fission scatter diff --git a/tests/regression_tests/trigger_batch_interval/tallies.xml b/tests/regression_tests/trigger_batch_interval/tallies.xml index 3440dbf21..ea25596a4 100644 --- a/tests/regression_tests/trigger_batch_interval/tallies.xml +++ b/tests/regression_tests/trigger_batch_interval/tallies.xml @@ -2,7 +2,7 @@ - all + Pu239 total total absorption fission scatter diff --git a/tests/regression_tests/trigger_no_batch_interval/tallies.xml b/tests/regression_tests/trigger_no_batch_interval/tallies.xml index 3440dbf21..ea25596a4 100644 --- a/tests/regression_tests/trigger_no_batch_interval/tallies.xml +++ b/tests/regression_tests/trigger_no_batch_interval/tallies.xml @@ -2,7 +2,7 @@ - all + Pu239 total total absorption fission scatter diff --git a/tests/regression_tests/trigger_no_status/tallies.xml b/tests/regression_tests/trigger_no_status/tallies.xml index 3440dbf21..ea25596a4 100644 --- a/tests/regression_tests/trigger_no_status/tallies.xml +++ b/tests/regression_tests/trigger_no_status/tallies.xml @@ -2,7 +2,7 @@ - all + Pu239 total total absorption fission scatter diff --git a/tests/regression_tests/trigger_tallies/tallies.xml b/tests/regression_tests/trigger_tallies/tallies.xml index 0d66e1538..ffe8a1a9e 100644 --- a/tests/regression_tests/trigger_tallies/tallies.xml +++ b/tests/regression_tests/trigger_tallies/tallies.xml @@ -2,7 +2,7 @@ - all + Pu239 total total absorption fission scatter From 93364e63637e31387cad25dafd38d910b7204bc2 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 25 Feb 2022 11:42:09 +0000 Subject: [PATCH 0022/2654] pinned NJOY version added import openmc test --- Dockerfile | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index dd12f826d..d35c6ddeb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ ENV DD_REPO='https://github.com/pshriwise/double-down' ENV DD_INSTALL_DIR=$HOME/Double_down # DAGMC variables -ENV DAGMC_BRANCH='develop' +ENV DAGMC_BRANCH='v3.2.1' ENV DAGMC_REPO='https://github.com/svalinn/DAGMC' ENV DAGMC_INSTALL_DIR=$HOME/DAGMC/ @@ -55,6 +55,10 @@ ENV LIBMESH_TAG='v1.6.0' ENV LIBMESH_REPO='https://github.com/libMesh/libmesh' ENV LIBMESH_INSTALL_DIR=$HOME/LIBMESH +# NJOY variables +ENV NJOY_TAG='2016.65' +ENV NJOY_REPO='https://github.com/njoy/NJOY2016' + # Setup environment variables for Docker image ENV CC=/usr/bin/mpicc CXX=/usr/bin/mpicxx \ LD_LIBRARY_PATH=${DAGMC_INSTALL_DIR}/lib:$LD_LIBRARY_PATH \ @@ -75,10 +79,14 @@ RUN apt-get update -y && \ RUN pip install --upgrade pip # Clone and install NJOY2016 -RUN cd $HOME && git clone --depth 1 https://github.com/njoy/NJOY2016.git && \ - cd NJOY2016 && mkdir build && cd build && \ - cmake -Dstatic=on .. && make 2>/dev/null -j${compile_cores} install && \ - rm -rf $HOME/NJOY2016 +RUN cd $HOME \ + && git clone --single-branch -b ${NJOY_TAG} --depth 1 ${NJOY_REPO} \ + && cd NJOY2016 \ + && mkdir build \ + && cd build \ + && cmake -Dstatic=on .. \ + && make 2>/dev/null -j${compile_cores} install \ + && rm -rf $HOME/NJOY2016 RUN if [ "$build_dagmc" = "on" ]; then \ @@ -167,7 +175,7 @@ RUN if [ "$build_libmesh" = "on" ]; then \ # clone and install openmc RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ - && git clone --shallow-submodules --recurse-submodules -b ${openmc_branch} --depth=1 ${OPENMC_REPO} \ + && git clone --shallow-submodules --recurse-submodules --single-branch -b ${openmc_branch} --depth=1 ${OPENMC_REPO} \ && mkdir build && cd build ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ @@ -201,7 +209,8 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ -DHDF5_PREFER_PARALLEL=on ; \ fi ; \ make 2>/dev/null -j${compile_cores} install \ - && cd ../openmc && pip install .[test,depletion-mpi] + && cd ../openmc && pip install .[test,depletion-mpi] \ + && python -c "import openmc" # Download cross sections (NNDC and WMP) and ENDF data needed by test suite RUN ${HOME}/OpenMC/openmc/tools/ci/download-xs.sh From dbbba828f6928f9198fe863c64b96237840f610d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 11 Feb 2022 09:08:06 -0600 Subject: [PATCH 0023/2654] Split score_general_ce into analog and non-analog cases --- src/tallies/tally_scoring.cpp | 1474 ++++++++++++++++++--------------- 1 file changed, 788 insertions(+), 686 deletions(-) diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index e3104f59a..9186aeca4 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -520,13 +520,10 @@ double get_nuclide_xs(const Particle& p, int i_nuclide, int score_bin) return 0.0; } -//! Update tally results for continuous-energy tallies with any estimator. -// -//! For analog tallies, the flux estimate depends on the score type so the flux -//! argument is really just used for filter weights. The atom_density argument -//! is not used for analog tallies. +//! Update tally results for continuous-energy tallies with a tracklength or +//! collision estimator. -void score_general_ce(Particle& p, int i_tally, int start_index, +void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, int filter_index, double filter_weight, int i_nuclide, double atom_density, double flux) { @@ -535,14 +532,6 @@ void score_general_ce(Particle& p, int i_tally, int start_index, // Get the pre-collision energy of the particle. auto E = p.E_last(); - // Determine how much weight was absorbed due to survival biasing - double wgt_absorb = 0.0; - if (tally.estimator_ == TallyEstimator::ANALOG && - settings::survival_biasing) { - wgt_absorb = p.wgt_last() * p.neutron_xs(p.event_nuclide()).absorption / - p.neutron_xs(p.event_nuclide()).total; - } - using Type = ParticleType; for (auto i = 0; i < tally.scores_.size(); ++i) { @@ -552,36 +541,18 @@ void score_general_ce(Particle& p, int i_tally, int start_index, switch (score_bin) { case SCORE_FLUX: - if (tally.estimator_ == TallyEstimator::ANALOG) { - // All events score to a flux bin. We actually use a collision estimator - // in place of an analog one since there is no way to count 'events' - // exactly for the flux - if (p.type() == Type::neutron || p.type() == Type::photon) { - score = flux * p.wgt_last() / p.macro_xs().total; - } else { - score = 0.; - } - } else { - score = flux; - } + score = flux; break; case SCORE_TOTAL: - if (tally.estimator_ == TallyEstimator::ANALOG) { - // All events will score to the total reaction rate. We can just use - // use the weight of the particle entering the collision as the score - score = p.wgt_last() * flux; - - } else { - if (i_nuclide >= 0) { - if (p.type() == Type::neutron) { - score = p.neutron_xs(i_nuclide).total * atom_density * flux; - } else if (p.type() == Type::photon) { - score = p.photon_xs(i_nuclide).total * atom_density * flux; - } - } else { - score = p.macro_xs().total * flux; + if (i_nuclide >= 0) { + if (p.type() == Type::neutron) { + score = p.neutron_xs(i_nuclide).total * atom_density * flux; + } else if (p.type() == Type::photon) { + score = p.photon_xs(i_nuclide).total * atom_density * flux; } + } else { + score = p.macro_xs().total * flux; } break; @@ -589,70 +560,28 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (p.type() != Type::neutron) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - // All events score to an inverse velocity bin. We actually use a - // collision estimator in place of an analog one since there is no way - // to count 'events' exactly for the inverse velocity - score = flux * p.wgt_last() / p.macro_xs().total; - } else { - score = flux; - } // Score inverse velocity in units of s/cm. - score /= p.speed(); + score = flux / p.speed(); break; case SCORE_SCATTER: if (p.type() != Type::neutron && p.type() != Type::photon) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - // Skip any event where the particle didn't scatter - if (p.event() != TallyEvent::SCATTER) - continue; - // Since only scattering events make it here, again we can use the - // weight entering the collision as the estimator for the reaction rate - score = (p.wgt_last() - wgt_absorb) * flux; - } else { - if (i_nuclide >= 0) { - if (p.type() == Type::neutron) { - const auto& micro = p.neutron_xs(i_nuclide); - score = (micro.total - micro.absorption) * atom_density * flux; - } else { - const auto& micro = p.photon_xs(i_nuclide); - score = (micro.coherent + micro.incoherent) * atom_density * flux; - } + if (i_nuclide >= 0) { + if (p.type() == Type::neutron) { + const auto& micro = p.neutron_xs(i_nuclide); + score = (micro.total - micro.absorption) * atom_density * flux; } else { - if (p.type() == Type::neutron) { - score = (p.macro_xs().total - p.macro_xs().absorption) * flux; - } else { - score = (p.macro_xs().coherent + p.macro_xs().incoherent) * flux; - } + const auto& micro = p.photon_xs(i_nuclide); + score = (micro.coherent + micro.incoherent) * atom_density * flux; + } + } else { + if (p.type() == Type::neutron) { + score = (p.macro_xs().total - p.macro_xs().absorption) * flux; + } else { + score = (p.macro_xs().coherent + p.macro_xs().incoherent) * flux; } - } - break; - - case SCORE_NU_SCATTER: - if (p.type() != Type::neutron) - continue; - - // Only analog estimators are available. - // Skip any event where the particle didn't scatter - if (p.event() != TallyEvent::SCATTER) - continue; - // For scattering production, we need to use the pre-collision weight - // times the yield as the estimate for the number of neutrons exiting a - // reaction with neutrons in the exit channel - score = (p.wgt_last() - wgt_absorb) * flux; - - // Don't waste time on very common reactions we know have multiplicities - // of one. - if (p.event_mt() != ELASTIC && p.event_mt() != N_LEVEL && - !(p.event_mt() >= N_N1 && p.event_mt() <= N_NC)) { - // Get yield and apply to score - auto m = - data::nuclides[p.event_nuclide()]->reaction_index_[p.event_mt()]; - const auto& rxn {*data::nuclides[p.event_nuclide()]->reactions_[m]}; - score *= (*rxn.products_[0].yield_)(E); } break; @@ -660,36 +589,20 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (p.type() != Type::neutron && p.type() != Type::photon) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (settings::survival_biasing) { - // No absorption events actually occur if survival biasing is on -- - // just use weight absorbed in survival biasing - score = wgt_absorb * flux; + if (i_nuclide >= 0) { + if (p.type() == Type::neutron) { + score = p.neutron_xs(i_nuclide).absorption * atom_density * flux; } else { - // Skip any event where the particle wasn't absorbed - if (p.event() == TallyEvent::SCATTER) - continue; - // All fission and absorption events will contribute here, so we - // can just use the particle's weight entering the collision - score = p.wgt_last() * flux; + const auto& xs = p.photon_xs(i_nuclide); + score = + (xs.total - xs.coherent - xs.incoherent) * atom_density * flux; } } else { - if (i_nuclide >= 0) { - if (p.type() == Type::neutron) { - score = p.neutron_xs(i_nuclide).absorption * atom_density * flux; - } else { - const auto& xs = p.photon_xs(i_nuclide); - score = - (xs.total - xs.coherent - xs.incoherent) * atom_density * flux; - } + if (p.type() == Type::neutron) { + score = p.macro_xs().absorption * flux; } else { - if (p.type() == Type::neutron) { - score = p.macro_xs().absorption * flux; - } else { - score = - (p.macro_xs().photoelectric + p.macro_xs().pair_production) * - flux; - } + score = + (p.macro_xs().photoelectric + p.macro_xs().pair_production) * flux; } } break; @@ -697,133 +610,45 @@ void score_general_ce(Particle& p, int i_tally, int start_index, case SCORE_FISSION: if (p.macro_xs().fission == 0) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- use collision - // estimator instead - if (p.neutron_xs(p.event_nuclide()).total > 0) { - score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).total * flux; - } else { - score = 0.; - } - } else { - // Skip any non-absorption events - if (p.event() == TallyEvent::SCATTER) - continue; - // All fission events will contribute, so again we can use particle's - // weight entering the collision as the estimate for the fission - // reaction rate - score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).absorption * flux; - } + + if (i_nuclide >= 0) { + score = p.neutron_xs(i_nuclide).fission * atom_density * flux; } else { - if (i_nuclide >= 0) { - score = p.neutron_xs(i_nuclide).fission * atom_density * flux; - } else { - score = p.macro_xs().fission * flux; - } + score = p.macro_xs().fission * flux; } break; case SCORE_NU_FISSION: if (p.macro_xs().fission == 0) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (settings::survival_biasing || p.fission()) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- use collision - // estimator instead - if (p.neutron_xs(p.event_nuclide()).total > 0) { - score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).nu_fission / - p.neutron_xs(p.event_nuclide()).total * flux; - } else { - score = 0.; - } - } else { - // Skip any non-fission events - if (!p.fission()) - continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. - score = simulation::keff * p.wgt_bank() * flux; - } + + if (i_nuclide >= 0) { + score = p.neutron_xs(i_nuclide).nu_fission * atom_density * flux; } else { - if (i_nuclide >= 0) { - score = p.neutron_xs(i_nuclide).nu_fission * atom_density * flux; - } else { - score = p.macro_xs().nu_fission * flux; - } + score = p.macro_xs().nu_fission * flux; } break; case SCORE_PROMPT_NU_FISSION: if (p.macro_xs().fission == 0) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (settings::survival_biasing || p.fission()) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // prompt-nu-fission - if (p.neutron_xs(p.event_nuclide()).total > 0) { - score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission * - data::nuclides[p.event_nuclide()]->nu( - E, ReactionProduct::EmissionMode::prompt) / - p.neutron_xs(p.event_nuclide()).total * flux; - } else { - score = 0.; - } - } else { - // Skip any non-fission events - if (!p.fission()) - continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. - auto n_delayed = std::accumulate( - p.n_delayed_bank(), p.n_delayed_bank() + MAX_DELAYED_GROUPS, 0); - auto prompt_frac = 1. - n_delayed / static_cast(p.n_bank()); - score = simulation::keff * p.wgt_bank() * prompt_frac * flux; - } + if (i_nuclide >= 0) { + score = p.neutron_xs(i_nuclide).fission * + data::nuclides[i_nuclide]->nu( + E, ReactionProduct::EmissionMode::prompt) * + atom_density * flux; } else { - if (i_nuclide >= 0) { - score = p.neutron_xs(i_nuclide).fission * - data::nuclides[i_nuclide]->nu( - E, ReactionProduct::EmissionMode::prompt) * - atom_density * flux; - } else { - score = 0.; - // Add up contributions from each nuclide in the material. - if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - score += p.neutron_xs(j_nuclide).fission * - data::nuclides[j_nuclide]->nu( - E, ReactionProduct::EmissionMode::prompt) * - atom_density * flux; - } + score = 0.; + // Add up contributions from each nuclide in the material. + if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + score += p.neutron_xs(j_nuclide).fission * + data::nuclides[j_nuclide]->nu( + E, ReactionProduct::EmissionMode::prompt) * + atom_density * flux; } } } @@ -832,141 +657,65 @@ void score_general_ce(Particle& p, int i_tally, int start_index, case SCORE_DELAYED_NU_FISSION: if (p.macro_xs().fission == 0) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (settings::survival_biasing || p.fission()) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; + if (i_nuclide >= 0) { + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt {*dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + // Tally each delayed group bin individually + for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { + auto d = filt.groups()[d_bin]; + auto yield = data::nuclides[i_nuclide]->nu( + E, ReactionProduct::EmissionMode::delayed, d); + score = + p.neutron_xs(i_nuclide).fission * yield * atom_density * flux; + score_fission_delayed_dg( + i_tally, d_bin, score, score_index, p.filter_matches()); } + continue; + } else { + // If the delayed group filter is not present, compute the score + // by multiplying the delayed-nu-fission macro xs by the flux + score = p.neutron_xs(i_nuclide).fission * + data::nuclides[i_nuclide]->nu( + E, ReactionProduct::EmissionMode::delayed) * + atom_density * flux; } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // delayed-nu-fission - if (p.neutron_xs(p.event_nuclide()).total > 0 && - data::nuclides[p.event_nuclide()]->fissionable_) { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt { - *dynamic_cast( - model::tally_filters[i_dg_filt].get())}; + } else { + // Need to add up contributions for each nuclide + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt {*dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); // Tally each delayed group bin individually for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto dg = filt.groups()[d_bin]; - auto yield = data::nuclides[p.event_nuclide()]->nu( - E, ReactionProduct::EmissionMode::delayed, dg); - score = p.wgt_last() * yield * - p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).total * flux; + auto d = filt.groups()[d_bin]; + auto yield = data::nuclides[j_nuclide]->nu( + E, ReactionProduct::EmissionMode::delayed, d); + score = + p.neutron_xs(j_nuclide).fission * yield * atom_density * flux; score_fission_delayed_dg( i_tally, d_bin, score, score_index, p.filter_matches()); } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the absorbed weight by the fraction of the - // delayed-nu-fission xs to the absorption xs - score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission * - data::nuclides[p.event_nuclide()]->nu( - E, ReactionProduct::EmissionMode::delayed) / - p.neutron_xs(p.event_nuclide()).total * flux; } } + continue; } else { - // Skip any non-fission events - if (!p.fission()) - continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. Loop over the neutrons produced from fission and check which - // ones are delayed. If a delayed neutron is encountered, add its - // contribution to the fission bank to the score. - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - score = simulation::keff * p.wgt_bank() / p.n_bank() * - p.n_delayed_bank(d - 1) * flux; - score_fission_delayed_dg( - i_tally, d_bin, score, score_index, p.filter_matches()); - } - continue; - } else { - // Add the contribution from all delayed groups - auto n_delayed = std::accumulate( - p.n_delayed_bank(), p.n_delayed_bank() + MAX_DELAYED_GROUPS, 0); - score = - simulation::keff * p.wgt_bank() / p.n_bank() * n_delayed * flux; - } - } - } else { - if (i_nuclide >= 0) { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = data::nuclides[i_nuclide]->nu( - E, ReactionProduct::EmissionMode::delayed, d); - score = - p.neutron_xs(i_nuclide).fission * yield * atom_density * flux; - score_fission_delayed_dg( - i_tally, d_bin, score, score_index, p.filter_matches()); - } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the delayed-nu-fission macro xs by the flux - score = p.neutron_xs(i_nuclide).fission * - data::nuclides[i_nuclide]->nu( - E, ReactionProduct::EmissionMode::delayed) * - atom_density * flux; - } - } else { - // Need to add up contributions for each nuclide - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = data::nuclides[j_nuclide]->nu( - E, ReactionProduct::EmissionMode::delayed, d); - score = p.neutron_xs(j_nuclide).fission * yield * - atom_density * flux; - score_fission_delayed_dg( - i_tally, d_bin, score, score_index, p.filter_matches()); - } - } - } - continue; - } else { - score = 0.; - if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - score += p.neutron_xs(j_nuclide).fission * - data::nuclides[j_nuclide]->nu( - E, ReactionProduct::EmissionMode::delayed) * - atom_density * flux; - } + score = 0.; + if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + score += p.neutron_xs(j_nuclide).fission * + data::nuclides[j_nuclide]->nu( + E, ReactionProduct::EmissionMode::delayed) * + atom_density * flux; } } } @@ -976,187 +725,97 @@ void score_general_ce(Particle& p, int i_tally, int start_index, case SCORE_DECAY_RATE: if (p.macro_xs().fission == 0) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // delayed-nu-fission - const auto& nuc {*data::nuclides[p.event_nuclide()]}; - if (p.neutron_xs(p.event_nuclide()).total > 0 && nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt { - *dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = - nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = rxn.products_[d].decay_rate_; - score = p.wgt_last() * yield * - p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).total * rate * flux; - score_fission_delayed_dg( - i_tally, d_bin, score, score_index, p.filter_matches()); - } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the absorbed weight by the fraction of the - // delayed-nu-fission xs to the absorption xs for all delayed - // groups - score = 0.; - // We need to be careful not to overshoot the number of - // delayed groups since this could cause the range of the - // rxn.products_ array to be exceeded. Hence, we use the size - // of this array and not the MAX_DELAYED_GROUPS constant for - // this loop. - for (auto d = 1; d < rxn.products_.size(); ++d) { - const auto& product = rxn.products_[d]; - if (product.particle_ != Type::neutron) - continue; - - auto yield = - nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = product.decay_rate_; - score += rate * p.wgt_last() * - p.neutron_xs(p.event_nuclide()).fission * yield / - p.neutron_xs(p.event_nuclide()).total * flux; - } - } + if (i_nuclide >= 0) { + const auto& nuc {*data::nuclides[i_nuclide]}; + if (!nuc.fissionable_) + continue; + const auto& rxn {*nuc.fission_rx_[0]}; + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt {*dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + // Tally each delayed group bin individually + for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { + auto d = filt.groups()[d_bin]; + auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = rxn.products_[d].decay_rate_; + score = p.neutron_xs(i_nuclide).fission * yield * flux * + atom_density * rate; + score_fission_delayed_dg( + i_tally, d_bin, score, score_index, p.filter_matches()); } + continue; } else { - // Skip any non-fission events - if (!p.fission()) - continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. Loop over the neutrons produced from fission and check which - // ones are delayed. If a delayed neutron is encountered, add its - // contribution to the fission bank to the score. score = 0.; - for (auto i = 0; i < p.n_bank(); ++i) { - const auto& bank = p.nu_bank(i); - auto g = bank.delayed_group; - if (g != 0) { - const auto& nuc {*data::nuclides[p.event_nuclide()]}; - const auto& rxn {*nuc.fission_rx_[0]}; - auto rate = rxn.products_[g].decay_rate_; - score += simulation::keff * bank.wgt * rate * flux; - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt { - *dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Find the corresponding filter bin and then score - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - if (d == g) - score_fission_delayed_dg( - i_tally, d_bin, score, score_index, p.filter_matches()); - } - score = 0.; - } - } + // We need to be careful not to overshoot the number of + // delayed groups since this could cause the range of the + // rxn.products_ array to be exceeded. Hence, we use the size + // of this array and not the MAX_DELAYED_GROUPS constant for + // this loop. + for (auto d = 1; d < rxn.products_.size(); ++d) { + const auto& product = rxn.products_[d]; + if (product.particle_ != Type::neutron) + continue; + + auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = product.decay_rate_; + score += p.neutron_xs(i_nuclide).fission * flux * yield * + atom_density * rate; } } } else { - if (i_nuclide >= 0) { - const auto& nuc {*data::nuclides[i_nuclide]}; - if (!nuc.fissionable_) - continue; - const auto& rxn {*nuc.fission_rx_[0]}; - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = rxn.products_[d].decay_rate_; - score = p.neutron_xs(i_nuclide).fission * yield * flux * - atom_density * rate; - score_fission_delayed_dg( - i_tally, d_bin, score, score_index, p.filter_matches()); - } - continue; - } else { - score = 0.; - // We need to be careful not to overshoot the number of - // delayed groups since this could cause the range of the - // rxn.products_ array to be exceeded. Hence, we use the size - // of this array and not the MAX_DELAYED_GROUPS constant for - // this loop. - for (auto d = 1; d < rxn.products_.size(); ++d) { - const auto& product = rxn.products_[d]; - if (product.particle_ != Type::neutron) - continue; - - auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = product.decay_rate_; - score += p.neutron_xs(i_nuclide).fission * flux * yield * - atom_density * rate; - } - } - } else { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const auto& nuc {*data::nuclides[j_nuclide]}; - if (nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = - nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = rxn.products_[d].decay_rate_; - score = p.neutron_xs(j_nuclide).fission * yield * flux * - atom_density * rate; - score_fission_delayed_dg( - i_tally, d_bin, score, score_index, p.filter_matches()); - } + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt {*dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + const auto& nuc {*data::nuclides[j_nuclide]}; + if (nuc.fissionable_) { + const auto& rxn {*nuc.fission_rx_[0]}; + // Tally each delayed group bin individually + for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { + auto d = filt.groups()[d_bin]; + auto yield = + nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = rxn.products_[d].decay_rate_; + score = p.neutron_xs(j_nuclide).fission * yield * flux * + atom_density * rate; + score_fission_delayed_dg( + i_tally, d_bin, score, score_index, p.filter_matches()); } } } - continue; - } else { - score = 0.; - if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const auto& nuc {*data::nuclides[j_nuclide]}; - if (nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - // We need to be careful not to overshoot the number of - // delayed groups since this could cause the range of the - // rxn.products_ array to be exceeded. Hence, we use the size - // of this array and not the MAX_DELAYED_GROUPS constant for - // this loop. - for (auto d = 1; d < rxn.products_.size(); ++d) { - const auto& product = rxn.products_[d]; - if (product.particle_ != Type::neutron) - continue; + } + continue; + } else { + score = 0.; + if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + const auto& nuc {*data::nuclides[j_nuclide]}; + if (nuc.fissionable_) { + const auto& rxn {*nuc.fission_rx_[0]}; + // We need to be careful not to overshoot the number of + // delayed groups since this could cause the range of the + // rxn.products_ array to be exceeded. Hence, we use the size + // of this array and not the MAX_DELAYED_GROUPS constant for + // this loop. + for (auto d = 1; d < rxn.products_.size(); ++d) { + const auto& product = rxn.products_[d]; + if (product.particle_ != Type::neutron) + continue; - auto yield = - nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = product.decay_rate_; - score += p.neutron_xs(j_nuclide).fission * yield * - atom_density * flux * rate; - } + auto yield = + nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = product.decay_rate_; + score += p.neutron_xs(j_nuclide).fission * yield * + atom_density * flux * rate; } } } @@ -1171,53 +830,23 @@ void score_general_ce(Particle& p, int i_tally, int start_index, score = 0.; // Kappa-fission values are determined from the Q-value listed for the // fission cross section. - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // fission scaled by the Q-value - const auto& nuc {*data::nuclides[p.event_nuclide()]}; - if (p.neutron_xs(p.event_nuclide()).total > 0 && nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - score = p.wgt_last() * rxn.q_value_ * - p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).total * flux; - } - } else { - // Skip any non-absorption events - if (p.event() == TallyEvent::SCATTER) - continue; - // All fission events will contribute, so again we can use particle's - // weight entering the collision as the estimate for the fission - // reaction rate - const auto& nuc {*data::nuclides[p.event_nuclide()]}; - if (p.neutron_xs(p.event_nuclide()).absorption > 0 && - nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - score = p.wgt_last() * rxn.q_value_ * - p.neutron_xs(p.event_nuclide()).fission / - p.neutron_xs(p.event_nuclide()).absorption * flux; - } + if (i_nuclide >= 0) { + const auto& nuc {*data::nuclides[i_nuclide]}; + if (nuc.fissionable_) { + const auto& rxn {*nuc.fission_rx_[0]}; + score = rxn.q_value_ * p.neutron_xs(i_nuclide).fission * + atom_density * flux; } - } else { - if (i_nuclide >= 0) { - const auto& nuc {*data::nuclides[i_nuclide]}; + } else if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + const auto& nuc {*data::nuclides[j_nuclide]}; if (nuc.fissionable_) { const auto& rxn {*nuc.fission_rx_[0]}; - score = rxn.q_value_ * p.neutron_xs(i_nuclide).fission * - atom_density * flux; - } - } else if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const auto& nuc {*data::nuclides[j_nuclide]}; - if (nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - score += rxn.q_value_ * p.neutron_xs(j_nuclide).fission * - atom_density * flux; - } + score += rxn.q_value_ * p.neutron_xs(j_nuclide).fission * + atom_density * flux; } } } @@ -1233,27 +862,20 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (p.type() != Type::neutron) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - // Check if event MT matches - if (p.event_mt() != ELASTIC) - continue; - score = (p.wgt_last() - wgt_absorb) * flux; + if (i_nuclide >= 0) { + if (p.neutron_xs(i_nuclide).elastic == CACHE_INVALID) + data::nuclides[i_nuclide]->calculate_elastic_xs(p); + score = p.neutron_xs(i_nuclide).elastic * atom_density * flux; } else { - if (i_nuclide >= 0) { - if (p.neutron_xs(i_nuclide).elastic == CACHE_INVALID) - data::nuclides[i_nuclide]->calculate_elastic_xs(p); - score = p.neutron_xs(i_nuclide).elastic * atom_density * flux; - } else { - score = 0.; - if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - if (p.neutron_xs(j_nuclide).elastic == CACHE_INVALID) - data::nuclides[j_nuclide]->calculate_elastic_xs(p); - score += p.neutron_xs(j_nuclide).elastic * atom_density * flux; - } + score = 0.; + if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + if (p.neutron_xs(j_nuclide).elastic == CACHE_INVALID) + data::nuclides[j_nuclide]->calculate_elastic_xs(p); + score += p.neutron_xs(j_nuclide).elastic * atom_density * flux; } } } @@ -1282,45 +904,27 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (p.type() != Type::neutron) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - // Check if the event MT matches - if (p.event_mt() != score_bin) - continue; - score = (p.wgt_last() - wgt_absorb) * flux; + int m; + switch (score_bin) { + // clang-format off + case N_GAMMA: m = 0; break; + case N_P: m = 1; break; + case N_A: m = 2; break; + case N_2N: m = 3; break; + case N_3N: m = 4; break; + case N_4N: m = 5; break; + // clang-format on + } + if (i_nuclide >= 0) { + score = p.neutron_xs(i_nuclide).reaction[m] * atom_density * flux; } else { - int m; - switch (score_bin) { - case N_GAMMA: - m = 0; - break; - case N_P: - m = 1; - break; - case N_A: - m = 2; - break; - case N_2N: - m = 3; - break; - case N_3N: - m = 4; - break; - case N_4N: - m = 5; - break; - } - if (i_nuclide >= 0) { - score = p.neutron_xs(i_nuclide).reaction[m] * atom_density * flux; - } else { - score = 0.; - if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - score += - p.neutron_xs(j_nuclide).reaction[m] * atom_density * flux; - } + score = 0.; + if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + score += p.neutron_xs(j_nuclide).reaction[m] * atom_density * flux; } } } @@ -1333,39 +937,24 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (p.type() != Type::photon) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - if (score_bin == PHOTOELECTRIC) { - // Photoelectric events are assigned an MT value corresponding to the - // shell cross section. Also, photons below the energy cutoff are - // assumed to have been absorbed via photoelectric absorption - if ((p.event_mt() < 534 || p.event_mt() > 572) && - p.event_mt() != REACTION_NONE) - continue; - } else { - if (p.event_mt() != score_bin) - continue; - } - score = p.wgt_last() * flux; - } else { - if (i_nuclide >= 0) { - const auto& micro = p.photon_xs(i_nuclide); - double xs = (score_bin == COHERENT) ? micro.coherent - : (score_bin == INCOHERENT) - ? micro.incoherent + if (i_nuclide >= 0) { + const auto& micro = p.photon_xs(i_nuclide); + double xs = (score_bin == COHERENT) + ? micro.coherent + : (score_bin == INCOHERENT) ? micro.incoherent : (score_bin == PHOTOELECTRIC) ? micro.photoelectric : micro.pair_production; - score = xs * atom_density * flux; - } else { - double xs = (score_bin == COHERENT) - ? p.macro_xs().coherent - : (score_bin == INCOHERENT) - ? p.macro_xs().incoherent - : (score_bin == PHOTOELECTRIC) - ? p.macro_xs().photoelectric - : p.macro_xs().pair_production; - score = xs * flux; - } + score = xs * atom_density * flux; + } else { + double xs = (score_bin == COHERENT) + ? p.macro_xs().coherent + : (score_bin == INCOHERENT) + ? p.macro_xs().incoherent + : (score_bin == PHOTOELECTRIC) + ? p.macro_xs().photoelectric + : p.macro_xs().pair_production; + score = xs * flux; } break; @@ -1397,30 +986,543 @@ void score_general_ce(Particle& p, int i_tally, int start_index, if (p.type() != Type::neutron) continue; - if (tally.estimator_ == TallyEstimator::ANALOG) { - // Any other score is assumed to be a MT number. Thus, we just need - // to check if it matches the MT number of the event - if (p.event_mt() != score_bin) - continue; - score = (p.wgt_last() - wgt_absorb) * flux; + // Any other cross section has to be calculated on-the-fly + if (score_bin < 2) + fatal_error("Invalid score type on tally " + std::to_string(tally.id_)); + score = 0.; + if (i_nuclide >= 0) { + score = get_nuclide_xs(p, i_nuclide, score_bin) * atom_density * flux; + } else if (p.material() != MATERIAL_VOID) { + const Material& material {*model::materials[p.material()]}; + for (auto i = 0; i < material.nuclide_.size(); ++i) { + auto j_nuclide = material.nuclide_[i]; + auto atom_density = material.atom_density_(i); + score += + get_nuclide_xs(p, j_nuclide, score_bin) * atom_density * flux; + } + } + } + + // Add derivative information on score for differential tallies. + if (tally.deriv_ != C_NONE) + apply_derivative_to_score( + p, i_tally, i_nuclide, atom_density, score_bin, score); + +// Update tally results +#pragma omp atomic + tally.results_(filter_index, score_index, TallyResult::VALUE) += + score * filter_weight; + } +} + +//! Update tally results for continuous-energy tallies with an analog estimator. +// +//! For analog tallies, the flux estimate depends on the score type so the flux +//! argument is really just used for filter weights. The atom_density argument +//! is not used for analog tallies. + +void score_general_ce_analog(Particle& p, int i_tally, int start_index, + int filter_index, double filter_weight, int i_nuclide, double atom_density, + double flux) +{ + Tally& tally {*model::tallies[i_tally]}; + + // Get the pre-collision energy of the particle. + auto E = p.E_last(); + + // Determine how much weight was absorbed due to survival biasing + double wgt_absorb = settings::survival_biasing + ? p.wgt_last() * + p.neutron_xs(p.event_nuclide()).absorption / + p.neutron_xs(p.event_nuclide()).total + : 0.0; + + using Type = ParticleType; + + for (auto i = 0; i < tally.scores_.size(); ++i) { + auto score_bin = tally.scores_[i]; + auto score_index = start_index + i; + double score = 0.0; + + switch (score_bin) { + case SCORE_FLUX: + // All events score to a flux bin. We actually use a collision estimator + // in place of an analog one since there is no way to count 'events' + // exactly for the flux + if (p.type() == Type::neutron || p.type() == Type::photon) { + score = flux * p.wgt_last() / p.macro_xs().total; } else { - // Any other cross section has to be calculated on-the-fly - if (score_bin < 2) - fatal_error( - "Invalid score type on tally " + std::to_string(tally.id_)); score = 0.; - if (i_nuclide >= 0) { - score = get_nuclide_xs(p, i_nuclide, score_bin) * atom_density * flux; - } else if (p.material() != MATERIAL_VOID) { - const Material& material {*model::materials[p.material()]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - score += - get_nuclide_xs(p, j_nuclide, score_bin) * atom_density * flux; + } + break; + + case SCORE_TOTAL: + // All events will score to the total reaction rate. We can just use + // use the weight of the particle entering the collision as the score + score = p.wgt_last() * flux; + break; + + case SCORE_INVERSE_VELOCITY: + if (p.type() != Type::neutron) + continue; + + // All events score to an inverse velocity bin. We actually use a + // collision estimator in place of an analog one since there is no way + // to count 'events' exactly for the inverse velocity + score = flux * p.wgt_last() / (p.macro_xs().total * p.speed()); + break; + + case SCORE_SCATTER: + if (p.type() != Type::neutron && p.type() != Type::photon) + continue; + + // Skip any event where the particle didn't scatter + if (p.event() != TallyEvent::SCATTER) + continue; + // Since only scattering events make it here, again we can use the + // weight entering the collision as the estimator for the reaction rate + score = (p.wgt_last() - wgt_absorb) * flux; + break; + + case SCORE_NU_SCATTER: + if (p.type() != Type::neutron) + continue; + + // Only analog estimators are available. + // Skip any event where the particle didn't scatter + if (p.event() != TallyEvent::SCATTER) + continue; + // For scattering production, we need to use the pre-collision weight + // times the yield as the estimate for the number of neutrons exiting a + // reaction with neutrons in the exit channel + score = (p.wgt_last() - wgt_absorb) * flux; + + // Don't waste time on very common reactions we know have multiplicities + // of one. + if (p.event_mt() != ELASTIC && p.event_mt() != N_LEVEL && + !(p.event_mt() >= N_N1 && p.event_mt() <= N_NC)) { + // Get yield and apply to score + auto m = + data::nuclides[p.event_nuclide()]->reaction_index_[p.event_mt()]; + const auto& rxn {*data::nuclides[p.event_nuclide()]->reactions_[m]}; + score *= (*rxn.products_[0].yield_)(E); + } + break; + + case SCORE_ABSORPTION: + if (p.type() != Type::neutron && p.type() != Type::photon) + continue; + + if (settings::survival_biasing) { + // No absorption events actually occur if survival biasing is on -- + // just use weight absorbed in survival biasing + score = wgt_absorb * flux; + } else { + // Skip any event where the particle wasn't absorbed + if (p.event() == TallyEvent::SCATTER) + continue; + // All fission and absorption events will contribute here, so we + // can just use the particle's weight entering the collision + score = p.wgt_last() * flux; + } + break; + + case SCORE_FISSION: + if (p.macro_xs().fission == 0) + continue; + if (settings::survival_biasing) { + // No fission events occur if survival biasing is on -- use collision + // estimator instead + if (p.neutron_xs(p.event_nuclide()).total > 0) { + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission / + p.neutron_xs(p.event_nuclide()).total * flux; + } else { + score = 0.; + } + } else { + // Skip any non-absorption events + if (p.event() == TallyEvent::SCATTER) + continue; + // All fission events will contribute, so again we can use particle's + // weight entering the collision as the estimate for the fission + // reaction rate + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission / + p.neutron_xs(p.event_nuclide()).absorption * flux; + } + break; + + case SCORE_NU_FISSION: + if (p.macro_xs().fission == 0) + continue; + if (settings::survival_biasing || p.fission()) { + if (tally.energyout_filter_ != C_NONE) { + // Fission has multiple outgoing neutrons so this helper function + // is used to handle scoring the multiple filter bins. + score_fission_eout(p, i_tally, score_index, score_bin); + continue; + } + } + if (settings::survival_biasing) { + // No fission events occur if survival biasing is on -- use collision + // estimator instead + if (p.neutron_xs(p.event_nuclide()).total > 0) { + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).nu_fission / + p.neutron_xs(p.event_nuclide()).total * flux; + } else { + score = 0.; + } + } else { + // Skip any non-fission events + if (!p.fission()) + continue; + // If there is no outgoing energy filter, than we only need to score + // to one bin. For the score to be 'analog', we need to score the + // number of particles that were banked in the fission bank. Since + // this was weighted by 1/keff, we multiply by keff to get the proper + // score. + score = simulation::keff * p.wgt_bank() * flux; + } + break; + + case SCORE_PROMPT_NU_FISSION: + if (p.macro_xs().fission == 0) + continue; + if (settings::survival_biasing || p.fission()) { + if (tally.energyout_filter_ != C_NONE) { + // Fission has multiple outgoing neutrons so this helper function + // is used to handle scoring the multiple filter bins. + score_fission_eout(p, i_tally, score_index, score_bin); + continue; + } + } + if (settings::survival_biasing) { + // No fission events occur if survival biasing is on -- need to + // calculate fraction of absorptions that would have resulted in + // prompt-nu-fission + if (p.neutron_xs(p.event_nuclide()).total > 0) { + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission * + data::nuclides[p.event_nuclide()]->nu( + E, ReactionProduct::EmissionMode::prompt) / + p.neutron_xs(p.event_nuclide()).total * flux; + } else { + score = 0.; + } + } else { + // Skip any non-fission events + if (!p.fission()) + continue; + // If there is no outgoing energy filter, than we only need to score + // to one bin. For the score to be 'analog', we need to score the + // number of particles that were banked in the fission bank. Since + // this was weighted by 1/keff, we multiply by keff to get the proper + // score. + auto n_delayed = std::accumulate( + p.n_delayed_bank(), p.n_delayed_bank() + MAX_DELAYED_GROUPS, 0); + auto prompt_frac = 1. - n_delayed / static_cast(p.n_bank()); + score = simulation::keff * p.wgt_bank() * prompt_frac * flux; + } + break; + + case SCORE_DELAYED_NU_FISSION: + if (p.macro_xs().fission == 0) + continue; + if (settings::survival_biasing || p.fission()) { + if (tally.energyout_filter_ != C_NONE) { + // Fission has multiple outgoing neutrons so this helper function + // is used to handle scoring the multiple filter bins. + score_fission_eout(p, i_tally, score_index, score_bin); + continue; + } + } + if (settings::survival_biasing) { + // No fission events occur if survival biasing is on -- need to + // calculate fraction of absorptions that would have resulted in + // delayed-nu-fission + if (p.neutron_xs(p.event_nuclide()).total > 0 && + data::nuclides[p.event_nuclide()]->fissionable_) { + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt {*dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + // Tally each delayed group bin individually + for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { + auto dg = filt.groups()[d_bin]; + auto yield = data::nuclides[p.event_nuclide()]->nu( + E, ReactionProduct::EmissionMode::delayed, dg); + score = p.wgt_last() * yield * + p.neutron_xs(p.event_nuclide()).fission / + p.neutron_xs(p.event_nuclide()).total * flux; + score_fission_delayed_dg( + i_tally, d_bin, score, score_index, p.filter_matches()); + } + continue; + } else { + // If the delayed group filter is not present, compute the score + // by multiplying the absorbed weight by the fraction of the + // delayed-nu-fission xs to the absorption xs + score = p.wgt_last() * p.neutron_xs(p.event_nuclide()).fission * + data::nuclides[p.event_nuclide()]->nu( + E, ReactionProduct::EmissionMode::delayed) / + p.neutron_xs(p.event_nuclide()).total * flux; + } + } + } else { + // Skip any non-fission events + if (!p.fission()) + continue; + // If there is no outgoing energy filter, than we only need to score + // to one bin. For the score to be 'analog', we need to score the + // number of particles that were banked in the fission bank. Since + // this was weighted by 1/keff, we multiply by keff to get the proper + // score. Loop over the neutrons produced from fission and check which + // ones are delayed. If a delayed neutron is encountered, add its + // contribution to the fission bank to the score. + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt {*dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + // Tally each delayed group bin individually + for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { + auto d = filt.groups()[d_bin]; + score = simulation::keff * p.wgt_bank() / p.n_bank() * + p.n_delayed_bank(d - 1) * flux; + score_fission_delayed_dg( + i_tally, d_bin, score, score_index, p.filter_matches()); + } + continue; + } else { + // Add the contribution from all delayed groups + auto n_delayed = std::accumulate( + p.n_delayed_bank(), p.n_delayed_bank() + MAX_DELAYED_GROUPS, 0); + score = + simulation::keff * p.wgt_bank() / p.n_bank() * n_delayed * flux; + } + } + break; + + case SCORE_DECAY_RATE: + if (p.macro_xs().fission == 0) + continue; + if (settings::survival_biasing) { + // No fission events occur if survival biasing is on -- need to + // calculate fraction of absorptions that would have resulted in + // delayed-nu-fission + const auto& nuc {*data::nuclides[p.event_nuclide()]}; + if (p.neutron_xs(p.event_nuclide()).total > 0 && nuc.fissionable_) { + const auto& rxn {*nuc.fission_rx_[0]}; + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt {*dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + // Tally each delayed group bin individually + for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { + auto d = filt.groups()[d_bin]; + auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = rxn.products_[d].decay_rate_; + score = p.wgt_last() * yield * + p.neutron_xs(p.event_nuclide()).fission / + p.neutron_xs(p.event_nuclide()).total * rate * flux; + score_fission_delayed_dg( + i_tally, d_bin, score, score_index, p.filter_matches()); + } + continue; + } else { + // If the delayed group filter is not present, compute the score + // by multiplying the absorbed weight by the fraction of the + // delayed-nu-fission xs to the absorption xs for all delayed + // groups + score = 0.; + // We need to be careful not to overshoot the number of + // delayed groups since this could cause the range of the + // rxn.products_ array to be exceeded. Hence, we use the size + // of this array and not the MAX_DELAYED_GROUPS constant for + // this loop. + for (auto d = 1; d < rxn.products_.size(); ++d) { + const auto& product = rxn.products_[d]; + if (product.particle_ != Type::neutron) + continue; + + auto yield = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); + auto rate = product.decay_rate_; + score += rate * p.wgt_last() * + p.neutron_xs(p.event_nuclide()).fission * yield / + p.neutron_xs(p.event_nuclide()).total * flux; + } + } + } + } else { + // Skip any non-fission events + if (!p.fission()) + continue; + // If there is no outgoing energy filter, than we only need to score + // to one bin. For the score to be 'analog', we need to score the + // number of particles that were banked in the fission bank. Since + // this was weighted by 1/keff, we multiply by keff to get the proper + // score. Loop over the neutrons produced from fission and check which + // ones are delayed. If a delayed neutron is encountered, add its + // contribution to the fission bank to the score. + score = 0.; + for (auto i = 0; i < p.n_bank(); ++i) { + const auto& bank = p.nu_bank(i); + auto g = bank.delayed_group; + if (g != 0) { + const auto& nuc {*data::nuclides[p.event_nuclide()]}; + const auto& rxn {*nuc.fission_rx_[0]}; + auto rate = rxn.products_[g].decay_rate_; + score += simulation::keff * bank.wgt * rate * flux; + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt { + *dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + // Find the corresponding filter bin and then score + for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { + auto d = filt.groups()[d_bin]; + if (d == g) + score_fission_delayed_dg( + i_tally, d_bin, score, score_index, p.filter_matches()); + } + score = 0.; + } } } } + break; + + case SCORE_KAPPA_FISSION: + if (p.macro_xs().fission == 0.) + continue; + score = 0.; + // Kappa-fission values are determined from the Q-value listed for the + // fission cross section. + if (settings::survival_biasing) { + // No fission events occur if survival biasing is on -- need to + // calculate fraction of absorptions that would have resulted in + // fission scaled by the Q-value + const auto& nuc {*data::nuclides[p.event_nuclide()]}; + if (p.neutron_xs(p.event_nuclide()).total > 0 && nuc.fissionable_) { + const auto& rxn {*nuc.fission_rx_[0]}; + score = p.wgt_last() * rxn.q_value_ * + p.neutron_xs(p.event_nuclide()).fission / + p.neutron_xs(p.event_nuclide()).total * flux; + } + } else { + // Skip any non-absorption events + if (p.event() == TallyEvent::SCATTER) + continue; + // All fission events will contribute, so again we can use particle's + // weight entering the collision as the estimate for the fission + // reaction rate + const auto& nuc {*data::nuclides[p.event_nuclide()]}; + if (p.neutron_xs(p.event_nuclide()).absorption > 0 && + nuc.fissionable_) { + const auto& rxn {*nuc.fission_rx_[0]}; + score = p.wgt_last() * rxn.q_value_ * + p.neutron_xs(p.event_nuclide()).fission / + p.neutron_xs(p.event_nuclide()).absorption * flux; + } + } + break; + + case SCORE_EVENTS: +// Simply count the number of scoring events +#pragma omp atomic + tally.results_(filter_index, score_index, TallyResult::VALUE) += 1.0; + continue; + + case ELASTIC: + if (p.type() != Type::neutron) + continue; + + // Check if event MT matches + if (p.event_mt() != ELASTIC) + continue; + score = (p.wgt_last() - wgt_absorb) * flux; + break; + + case SCORE_FISS_Q_PROMPT: + case SCORE_FISS_Q_RECOV: + if (p.macro_xs().fission == 0.) + continue; + score = + score_fission_q(p, score_bin, tally, flux, i_nuclide, atom_density); + break; + + case N_2N: + case N_3N: + case N_4N: + case N_GAMMA: + case N_P: + case N_A: + // This case block only works if cross sections for these reactions have + // been precalculated. When they are not, we revert to the default case, + // which looks up cross sections + if (!simulation::need_depletion_rx) + goto default_case; + + if (p.type() != Type::neutron) + continue; + + // Check if the event MT matches + if (p.event_mt() != score_bin) + continue; + score = (p.wgt_last() - wgt_absorb) * flux; + break; + + case COHERENT: + case INCOHERENT: + case PHOTOELECTRIC: + case PAIR_PROD: + if (p.type() != Type::photon) + continue; + + if (score_bin == PHOTOELECTRIC) { + // Photoelectric events are assigned an MT value corresponding to the + // shell cross section. Also, photons below the energy cutoff are + // assumed to have been absorbed via photoelectric absorption + if ((p.event_mt() < 534 || p.event_mt() > 572) && + p.event_mt() != REACTION_NONE) + continue; + } else { + if (p.event_mt() != score_bin) + continue; + } + score = p.wgt_last() * flux; + break; + + case HEATING: + if (p.type() == Type::neutron) { + score = score_neutron_heating( + p, tally, flux, HEATING, i_nuclide, atom_density); + } else { + // The energy deposited is the difference between the pre-collision and + // post-collision energy... + score = E - p.E(); + + // ...less the energy of any secondary particles since they will be + // transported individually later + const auto& bank = p.secondary_bank(); + for (auto it = bank.end() - p.n_bank_second(); it < bank.end(); ++it) { + score -= it->E; + } + + score *= p.wgt_last(); + } + break; + + default: + default_case: + + // The default block is really only meant for redundant neutron reactions + // (e.g. 444, 901) + if (p.type() != Type::neutron) + continue; + + // Any other score is assumed to be a MT number. Thus, we just need + // to check if it matches the MT number of the event + if (p.event_mt() != score_bin) + continue; + score = (p.wgt_last() - wgt_absorb) * flux; } // Add derivative information on score for differential tallies. @@ -2129,8 +2231,8 @@ void score_analog_tally_ce(Particle& p) // the event nuclide or the total material. Note that the atomic // density argument for score_general is not used for analog tallies. if (i_nuclide == p.event_nuclide() || i_nuclide == -1) - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, -1.0, flux); + score_general_ce_analog(p, i_tally, i * tally.scores_.size(), + filter_index, filter_weight, i_nuclide, -1.0, flux); } } @@ -2234,8 +2336,8 @@ void score_tracklength_tally(Particle& p, double distance) // TODO: consider replacing this "if" with pointers or templates if (settings::run_CE) { - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, atom_density, flux); + score_general_ce_nonanalog(p, i_tally, i * tally.scores_.size(), + filter_index, filter_weight, i_nuclide, atom_density, flux); } else { score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index, filter_weight, i_nuclide, atom_density, flux); @@ -2295,8 +2397,8 @@ void score_collision_tally(Particle& p) // TODO: consider replacing this "if" with pointers or templates if (settings::run_CE) { - score_general_ce(p, i_tally, i * tally.scores_.size(), filter_index, - filter_weight, i_nuclide, atom_density, flux); + score_general_ce_nonanalog(p, i_tally, i * tally.scores_.size(), + filter_index, filter_weight, i_nuclide, atom_density, flux); } else { score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index, filter_weight, i_nuclide, atom_density, flux); From f4a8f06c82d49509c16195281f58c659a7eb75c0 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 25 Feb 2022 13:51:03 +0000 Subject: [PATCH 0024/2654] returning to use latest release of NJOY --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index d35c6ddeb..bf0bc81cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,7 +56,6 @@ ENV LIBMESH_REPO='https://github.com/libMesh/libmesh' ENV LIBMESH_INSTALL_DIR=$HOME/LIBMESH # NJOY variables -ENV NJOY_TAG='2016.65' ENV NJOY_REPO='https://github.com/njoy/NJOY2016' # Setup environment variables for Docker image @@ -80,7 +79,7 @@ RUN pip install --upgrade pip # Clone and install NJOY2016 RUN cd $HOME \ - && git clone --single-branch -b ${NJOY_TAG} --depth 1 ${NJOY_REPO} \ + && git clone --single-branch --depth 1 ${NJOY_REPO} \ && cd NJOY2016 \ && mkdir build \ && cd build \ From 8b6e49df4738b78df40ee91c9cfc963570fd9738 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Fri, 25 Feb 2022 10:35:26 -0500 Subject: [PATCH 0025/2654] fixing logic for spherical mesh string repr --- openmc/mesh.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 1f17dbae2..6c210ae59 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -960,19 +960,19 @@ class SphericalMesh(MeshBase): fmt = '{0: <16}{1}{2}\n' string = super().__repr__() string += fmt.format('\tDimensions', '=\t', self.n_dimension) - r_grid_str = str(self._r_grid) if not self._r_grid else len(self._r_grid) + r_grid_str = str(self._r_grid) if self._r_grid is None else len(self._r_grid) string += fmt.format('\tN R pnts:', '=\t', r_grid_str) - if self._r_grid: + if self._r_grid is not None: string += fmt.format('\tR Min:', '=\t', self._r_grid[0]) string += fmt.format('\tR Max:', '=\t', self._r_grid[-1]) - theta_grid_str = str(self._theta_grid) if not self._theta_grid else len(self._theta_grid) + theta_grid_str = str(self._theta_grid) if self._theta_grid is None else len(self._theta_grid) string += fmt.format('\tN Theta pnts:', '=\t', theta_grid_str) - if self._theta_grid: + if self._theta_grid is not None: string += fmt.format('\tTheta Min:', '=\t', self._theta_grid[0]) string += fmt.format('\tTheta Max:', '=\t', self._theta_grid[-1]) - phi_grid_str = str(self._phi_grid) if not self._phi_grid else len(self._phi_grid) + phi_grid_str = str(self._phi_grid) if self._phi_grid is None else len(self._phi_grid) string += fmt.format('\tN Phi pnts:', '=\t', phi_grid_str) - if self._phi_grid: + if self._phi_grid is not None: string += fmt.format('\tPhi Min:', '=\t', self._phi_grid[0]) string += fmt.format('\tPhi Max:', '=\t', self._phi_grid[-1]) return string From 57bc5490c91fd03ddc81d150c196c45ed66cbe1c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 25 Feb 2022 17:23:43 +0000 Subject: [PATCH 0026/2654] added import test for pymoab --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index bf0bc81cf..367777b6e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -119,6 +119,7 @@ RUN if [ "$build_dagmc" = "on" ]; then \ && make 2>/dev/null -j${compile_cores} install \ && cd pymoab && bash install.sh \ && python setup.py install \ + && python -c "import pymoab" \ && rm -rf $HOME/MOAB ; \ # Clone and install Double-Down mkdir -p $HOME/Double_down && cd $HOME/Double_down \ From c2ff25881efda9697ce93105d9173d0e5ca10750 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 25 Feb 2022 20:33:10 +0000 Subject: [PATCH 0027/2654] added @shimwell for docker --- CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CODEOWNERS b/CODEOWNERS index a061b7b6e..1b5130e0b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -46,3 +46,6 @@ openmc/lib/plot.py @pshriwise # Resonance covariance openmc/data/resonance_covariance.py @icmeyer + +# Docker +Dockerfile @shimwell From f10d9ac7b629e984fb6fbc9adfde0217a1dacb50 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Feb 2022 16:56:56 -0600 Subject: [PATCH 0028/2654] Making volume retrieval consistent in Python API --- openmc/mesh.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 6c210ae59..9a217497f 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -203,6 +203,22 @@ class RegularMesh(MeshBase): def num_mesh_cells(self): return np.prod(self._dimension) + @property + def volumes(self): + """Return Volumes for every mesh cell + + Returns + ------- + volumes : Iterable of float + Volumes + + """ + return np.full(self.dimension, np.prod(self.width)) + + @property + def total_volume(self): + return np.prod(self.dimension) * np.prod(self.width) + @property def indices(self): ndim = len(self._dimension) @@ -575,6 +591,26 @@ class RectilinearMesh(MeshBase): def z_grid(self): return self._z_grid + @property + def volumes(self): + """Return Volumes for every mesh cell + + Returns + ------- + volumes : Iterable of float + Volumes + + """ + V_x = np.diff(self.x_grid) + V_y = np.diff(self.y_grid) + V_z = np.diff(self.z_grid) + + return np.multiply.outer(np.outer(V_x, V_y), V_z) + + @property + def total_volume(self): + return np.sum(self.volumes) + @property def indices(self): nx = len(self.x_grid) - 1 @@ -681,6 +717,7 @@ class RectilinearMesh(MeshBase): return element + class CylindricalMesh(MeshBase): """A 3D cylindrical mesh @@ -850,7 +887,8 @@ class CylindricalMesh(MeshBase): mesh.z_grid = [float(x) for x in get_text(elem, "z_grid").split()] return mesh - def calc_mesh_volumes(self): + @property + def volumes(self): """Return Volumes for every mesh cell Returns @@ -1037,7 +1075,8 @@ class SphericalMesh(MeshBase): mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] return mesh - def calc_mesh_volumes(self): + @property + def volumes(self): """Return Volumes for every mesh cell Returns @@ -1150,6 +1189,15 @@ class UnstructuredMesh(MeshBase): @property def volumes(self): + """Return Volumes for every mesh cell if + populated by a StatePoint file + + Returns + ------- + volumes : Iterable of float + Volumes + + """ return self._volumes @volumes.setter From fb1d2ff00b3670a7c6b07541e34d0f83596c6bfd Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Feb 2022 21:34:35 -0600 Subject: [PATCH 0029/2654] Adding volume check to filter mesh test --- tests/regression_tests/filter_mesh/test.py | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/regression_tests/filter_mesh/test.py b/tests/regression_tests/filter_mesh/test.py index fc24b1b9b..e949c1a4c 100644 --- a/tests/regression_tests/filter_mesh/test.py +++ b/tests/regression_tests/filter_mesh/test.py @@ -46,21 +46,45 @@ def model(): mesh_3d.dimension = [5, 5, 5] mesh_3d.lower_left = [-7.5, -7.5, -7.5] mesh_3d.upper_right = [7.5, 7.5, 7.5] + dx = dy = dz = 15 / 5 + reg_mesh_exp_vols = np.full(mesh_3d.dimension, dx*dy*dz) + np.testing.assert_equal(mesh_3d.volumes, reg_mesh_exp_vols) + recti_mesh = openmc.RectilinearMesh() recti_mesh.x_grid = np.linspace(-7.5, 7.5, 18) recti_mesh.y_grid = np.linspace(-7.5, 7.5, 18) recti_mesh.z_grid = np.logspace(0, np.log10(7.5), 11) + dx = dy = 15 / 17 + dz = np.diff(np.logspace(0, np.log10(7.5), 11)) + dxdy = np.full(recti_mesh.dimension[:2], dx*dy) + recti_mesh_exp_vols = np.multiply.outer(dxdy, dz) + np.testing.assert_allclose(recti_mesh.volumes, recti_mesh_exp_vols) cyl_mesh = openmc.CylindricalMesh() cyl_mesh.r_grid = np.linspace(0, 7.5, 18) cyl_mesh.phi_grid = np.linspace(0, 2*pi, 19) cyl_mesh.z_grid = np.linspace(-7.5, 7.5, 17) + dr = 0.5 * np.diff(np.linspace(0, 7.5, 18)**2) + dp = np.full(cyl_mesh.dimension[1], 2*pi / 18) + dz = np.full(cyl_mesh.dimension[2], 15 / 16) + drdp = np.outer(dr, dp) + cyl_mesh_exp_vols = np.multiply.outer(drdp, dz) + np.testing.assert_allclose(cyl_mesh.volumes, cyl_mesh_exp_vols) + + sph_mesh = openmc.SphericalMesh() sph_mesh.r_grid = np.linspace(0, 7.5, 18) sph_mesh.theta_grid = np.linspace(0, pi, 9) sph_mesh.phi_grid = np.linspace(0, 2*pi, 19) + dr = np.diff(np.linspace(0, 7.5, 18)**3) / 3 + dt = np.diff(-np.cos(np.linspace(0, pi, 9))) + dp = np.full(sph_mesh.dimension[2], 2*pi / 18) + drdt = np.outer(dr, dt) + sph_mesh_exp_vols = np.multiply.outer(drdt, dp) + np.testing.assert_allclose(sph_mesh.volumes, sph_mesh_exp_vols) + # Create filters reg_filters = [ From 8bced043f553585ec79ff64d9af79adf9150011d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 26 Feb 2022 08:55:40 -0600 Subject: [PATCH 0030/2654] Adding check for dimensionality of the mesh --- openmc/mesh.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 9a217497f..0de73bbe9 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -59,6 +59,12 @@ class MeshBase(IDManagerMixin, ABC): string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) return string + def _volume_dim_check(self): + if len(self.dimension) != 3 or \ + any([d == 0 for d in self.dimension]): + raise RuntimeError(f'Mesh {self.id} is not 3D. ' + 'Volumes cannot be provided.') + @classmethod def from_hdf5(cls, group): """Create mesh from HDF5 group @@ -213,6 +219,7 @@ class RegularMesh(MeshBase): Volumes """ + self._volume_dim_check() return np.full(self.dimension, np.prod(self.width)) @property @@ -601,6 +608,7 @@ class RectilinearMesh(MeshBase): Volumes """ + self._volume_dim_check() V_x = np.diff(self.x_grid) V_y = np.diff(self.y_grid) V_z = np.diff(self.z_grid) @@ -897,7 +905,7 @@ class CylindricalMesh(MeshBase): Volumes """ - + self._volume_dim_check() V_r = np.diff(np.asarray(self.r_grid)**2 / 2) V_p = np.diff(self.phi_grid) V_z = np.diff(self.z_grid) @@ -1085,7 +1093,7 @@ class SphericalMesh(MeshBase): Volumes """ - + self._volume_dim_check() V_r = np.diff(np.asarray(self.r_grid)**3 / 3) V_t = np.diff(-np.cos(self.theta_grid)) V_p = np.diff(self.phi_grid) From cc8f1f3e6bd84e078b50b185f55d3786adb2318a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Feb 2022 14:10:04 -0600 Subject: [PATCH 0031/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/mesh.py | 6 +++--- tests/regression_tests/filter_mesh/test.py | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 0de73bbe9..2556e4510 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -215,7 +215,7 @@ class RegularMesh(MeshBase): Returns ------- - volumes : Iterable of float + volumes : numpy.ndarray Volumes """ @@ -604,7 +604,7 @@ class RectilinearMesh(MeshBase): Returns ------- - volumes : Iterable of float + volumes : numpy.ndarray Volumes """ @@ -1202,7 +1202,7 @@ class UnstructuredMesh(MeshBase): Returns ------- - volumes : Iterable of float + volumes : numpy.ndarray Volumes """ diff --git a/tests/regression_tests/filter_mesh/test.py b/tests/regression_tests/filter_mesh/test.py index e949c1a4c..b047dd252 100644 --- a/tests/regression_tests/filter_mesh/test.py +++ b/tests/regression_tests/filter_mesh/test.py @@ -50,7 +50,6 @@ def model(): reg_mesh_exp_vols = np.full(mesh_3d.dimension, dx*dy*dz) np.testing.assert_equal(mesh_3d.volumes, reg_mesh_exp_vols) - recti_mesh = openmc.RectilinearMesh() recti_mesh.x_grid = np.linspace(-7.5, 7.5, 18) recti_mesh.y_grid = np.linspace(-7.5, 7.5, 18) @@ -73,7 +72,6 @@ def model(): cyl_mesh_exp_vols = np.multiply.outer(drdp, dz) np.testing.assert_allclose(cyl_mesh.volumes, cyl_mesh_exp_vols) - sph_mesh = openmc.SphericalMesh() sph_mesh.r_grid = np.linspace(0, 7.5, 18) sph_mesh.theta_grid = np.linspace(0, pi, 9) @@ -85,7 +83,6 @@ def model(): sph_mesh_exp_vols = np.multiply.outer(drdt, dp) np.testing.assert_allclose(sph_mesh.volumes, sph_mesh_exp_vols) - # Create filters reg_filters = [ openmc.MeshFilter(mesh_1d), From 17b2f5eb6aa703e083101c0df165ba258d5454bd Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Feb 2022 16:29:32 -0600 Subject: [PATCH 0032/2654] Making all *_grid attributes of mesh numpy arrays --- openmc/mesh.py | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 2556e4510..938211a46 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -557,12 +557,12 @@ class RectilinearMesh(MeshBase): The number of mesh cells in each direction. n_dimension : int Number of mesh dimensions (always 3 for a RectilinearMesh). - x_grid : Iterable of float - Mesh boundary points along the x-axis. - y_grid : Iterable of float - Mesh boundary points along the y-axis. - z_grid : Iterable of float - Mesh boundary points along the z-axis. + x_grid : numpy.ndarray + 1-D array of mesh boundary points along the x-axis. + y_grid : numpy.ndarray + 1-D array of mesh boundary points along the y-axis. + z_grid : numpy.ndarray + 1-D array of mesh boundary points along the z-axis. indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), (2, 1, 1), ...] @@ -632,17 +632,17 @@ class RectilinearMesh(MeshBase): @x_grid.setter def x_grid(self, grid): cv.check_type('mesh x_grid', grid, Iterable, Real) - self._x_grid = grid + self._x_grid = np.asarray(grid) @y_grid.setter def y_grid(self, grid): cv.check_type('mesh y_grid', grid, Iterable, Real) - self._y_grid = grid + self._y_grid = np.asarray(grid) @z_grid.setter def z_grid(self, grid): cv.check_type('mesh z_grid', grid, Iterable, Real) - self._z_grid = grid + self._z_grid = np.asarray(grid) def __repr__(self): fmt = '{0: <16}{1}{2}\n' @@ -746,14 +746,14 @@ class CylindricalMesh(MeshBase): The number of mesh cells in each direction. n_dimension : int Number of mesh dimensions (always 3 for a CylindricalMesh). - r_grid : Iterable of float - Mesh boundary points along the r-axis. + r_grid : numpy.ndarray + 1-D array of mesh boundary points along the r-axis. Requirement is r >= 0. - phi_grid : Iterable of float - Mesh boundary points along the phi-axis. + phi_grid : numpy.ndarray + 1-D array of mesh boundary points along the phi-axis. The default value is [0, 2π], i.e. the full phi range. - z_grid : Iterable of float - Mesh boundary points along the z-axis. + z_grid : numpy.ndarray + 1-D array of mesh boundary points along the z-axis. indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), (2, 1, 1), ...] @@ -802,7 +802,7 @@ class CylindricalMesh(MeshBase): @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) - self._r_grid = grid + self._r_grid = np.asarray(grid) @phi_grid.setter def phi_grid(self, grid): @@ -933,14 +933,14 @@ class SphericalMesh(MeshBase): The number of mesh cells in each direction. n_dimension : int Number of mesh dimensions (always 3 for a SphericalMesh). - r_grid : Iterable of float - Mesh boundary points along the r-axis. + r_grid : numpy.ndarray + 1-D array of mesh boundary points along the r-axis. Requirement is r >= 0. - theta_grid : Iterable of float - Mesh boundary points along the theta-axis in degrees. + theta_grid : numpy.ndarray + 1-D array of mesh boundary points along the theta-axis in degrees. The default value is [0, π], i.e. the full theta range. - phi_grid : Iterable of float - Mesh boundary points along the phi-axis in degrees. + phi_grid : numpy.ndarray + 1-D array of mesh boundary points along the phi-axis in degrees. The default value is [0, 2π], i.e. the full phi range. indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), @@ -990,7 +990,7 @@ class SphericalMesh(MeshBase): @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) - self._r_grid = grid + self._r_grid = np.asarray(grid) @theta_grid.setter def theta_grid(self, grid): From 2bb6ba25af85e4f91cc241a9139d623f98387881 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 1 Mar 2022 14:33:15 -0600 Subject: [PATCH 0033/2654] Remove alive_ data member on ParticleData --- include/openmc/particle_data.h | 7 +++---- src/particle.cpp | 11 +++++------ src/physics.cpp | 13 ++++++------- src/physics_common.cpp | 1 - src/physics_mg.cpp | 2 +- src/tallies/tally_scoring.cpp | 5 ++--- src/weight_windows.cpp | 1 - 7 files changed, 17 insertions(+), 23 deletions(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index a1804f7be..ee0dc6dfc 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -235,7 +235,6 @@ private: double mu_; //!< angle of scatter double time_ {0.0}; //!< time in [s] double time_last_ {0.0}; //!< previous time in [s] - bool alive_ {true}; //!< is particle alive? // Other physical data Position r_last_current_; //!< coordinates of the last collision or @@ -309,7 +308,8 @@ private: // Weight window information int n_split_ {0}; // Number of times this particle has been split - double ww_factor_ {0.0}; // Particle-specific factor for on-the-fly weight window adjustment + double ww_factor_ { + 0.0}; // Particle-specific factor for on-the-fly weight window adjustment // DagMC state variables #ifdef DAGMC @@ -342,7 +342,6 @@ public: const LocalCoord& coord(int i) const { return coord_[i]; } const vector& coord() const { return coord_; } - int& n_coord_last() { return n_coord_last_; } const int& n_coord_last() const { return n_coord_last_; } int& cell_last(int i) { return cell_last_[i]; } @@ -364,7 +363,7 @@ public: const double& time() const { return time_; } double& time_last() { return time_last_; } const double& time_last() const { return time_last_; } - bool& alive() { return alive_; } + bool alive() { return wgt_ > 0.0; } Position& r_last_current() { return r_last_current_; } const Position& r_last_current() const { return r_last_current_; } diff --git a/src/particle.cpp b/src/particle.cpp index b3dd72d9a..b622a4d69 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -86,7 +86,6 @@ void Particle::from_source(const SourceSite* src) { // Reset some attributes clear(); - alive() = true; surface() = 0; cell_born() = C_NONE; material() = C_NONE; @@ -333,7 +332,7 @@ void Particle::event_revive_from_secondary() if (n_event() == MAX_EVENTS) { warning("Particle " + std::to_string(id()) + " underwent maximum number of events."); - alive() = false; + wgt() = 0.0; } // Check for secondary particles if this particle is dead @@ -483,9 +482,6 @@ void Particle::cross_surface() void Particle::cross_vacuum_bc(const Surface& surf) { - // Kill the particle - alive() = false; - // Score any surface current tallies -- note that the particle is moved // forward slightly so that if the mesh boundary is on the surface, it is // still processed @@ -501,6 +497,9 @@ void Particle::cross_vacuum_bc(const Surface& surf) // Score to global leakage tally keff_tally_leakage() += wgt(); + // Kill the particle + wgt() = 0.0; + // Display message if (settings::verbosity >= 10 || trace()) { write_message(1, " Leaked out of surface {}", surf.id_); @@ -618,7 +617,7 @@ void Particle::mark_as_lost(const char* message) write_restart(); // Increment number of lost particles - alive() = false; + wgt() = 0.0; #pragma omp atomic simulation::n_lost_particles += 1; diff --git a/src/physics.cpp b/src/physics.cpp index edc581c42..13dd063de 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -66,7 +66,6 @@ void collision(Particle& p) // Kill particle if energy falls below cutoff int type = static_cast(p.type()); if (p.E() < settings::energy_cutoff[type]) { - p.alive() = false; p.wgt() = 0.0; } @@ -272,7 +271,7 @@ void sample_photon_reaction(Particle& p) int photon = static_cast(ParticleType::photon); if (p.E() < settings::energy_cutoff[photon]) { p.E() = 0.0; - p.alive() = false; + p.wgt() = 0.0; return; } @@ -397,7 +396,7 @@ void sample_photon_reaction(Particle& p) element.atomic_relaxation(i_shell, p); p.event() = TallyEvent::ABSORB; p.event_mt() = 533 + shell.index_subshell; - p.alive() = false; + p.wgt() = 0.0; p.E() = 0.0; return; } @@ -423,7 +422,7 @@ void sample_photon_reaction(Particle& p) p.event() = TallyEvent::ABSORB; p.event_mt() = PAIR_PROD; - p.alive() = false; + p.wgt() = 0.0; p.E() = 0.0; } } @@ -438,7 +437,7 @@ void sample_electron_reaction(Particle& p) } p.E() = 0.0; - p.alive() = false; + p.wgt() = 0.0; p.event() = TallyEvent::ABSORB; } @@ -459,7 +458,7 @@ void sample_positron_reaction(Particle& p) p.create_secondary(p.wgt(), -u, MASS_ELECTRON_EV, ParticleType::photon); p.E() = 0.0; - p.alive() = false; + p.wgt() = 0.0; p.event() = TallyEvent::ABSORB; } @@ -634,7 +633,7 @@ void absorption(Particle& p, int i_nuclide) p.neutron_xs(i_nuclide).absorption; } - p.alive() = false; + p.wgt() = 0.0; p.event() = TallyEvent::ABSORB; p.event_mt() = N_DISAPPEAR; } diff --git a/src/physics_common.cpp b/src/physics_common.cpp index 7e65c9bbf..e25ae6b97 100644 --- a/src/physics_common.cpp +++ b/src/physics_common.cpp @@ -15,7 +15,6 @@ void russian_roulette(Particle& p, double weight_survive) p.wgt() = weight_survive; } else { p.wgt() = 0.; - p.alive() = false; } } diff --git a/src/physics_mg.cpp b/src/physics_mg.cpp index 6e89fde5e..ab1fdef02 100644 --- a/src/physics_mg.cpp +++ b/src/physics_mg.cpp @@ -226,7 +226,7 @@ void absorption(Particle& p) if (p.macro_xs().absorption > prn(p.current_seed()) * p.macro_xs().total) { p.keff_tally_absorption() += p.wgt() * p.macro_xs().nu_fission / p.macro_xs().absorption; - p.alive() = false; + p.wgt() = 0.0; p.event() = TallyEvent::ABSORB; } } diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index e3104f59a..230a06def 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -2319,8 +2319,7 @@ void score_collision_tally(Particle& p) void score_surface_tally(Particle& p, const vector& tallies) { - // No collision, so no weight change when survival biasing - double flux = p.wgt(); + double current = p.wgt_last(); for (auto i_tally : tallies) { auto& tally {*model::tallies[i_tally]}; @@ -2341,7 +2340,7 @@ void score_surface_tally(Particle& p, const vector& tallies) // Loop over scores. // There is only one score type for current tallies so there is no need // for a further scoring function. - double score = flux * filter_weight; + double score = current * filter_weight; for (auto score_index = 0; score_index < tally.scores_.size(); ++score_index) { #pragma omp atomic diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index e753fc6ac..94c6c5908 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -52,7 +52,6 @@ void apply_weight_windows(Particle& p) // first check to see if particle should be killed for weight cutoff if (p.wgt() < weight_window.weight_cutoff) { - p.alive() = false; p.wgt() = 0.0; return; } From 6bafc9ab92221957744892c995419cdb25a4665a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 1 Mar 2022 16:52:21 -0600 Subject: [PATCH 0034/2654] Apply suggestions from @eepeterson Co-authored-by: Ethan Peterson --- openmc/mesh.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 938211a46..40d56f502 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -750,7 +750,7 @@ class CylindricalMesh(MeshBase): 1-D array of mesh boundary points along the r-axis. Requirement is r >= 0. phi_grid : numpy.ndarray - 1-D array of mesh boundary points along the phi-axis. + 1-D array of mesh boundary points along the phi-axis in radians. The default value is [0, 2π], i.e. the full phi range. z_grid : numpy.ndarray 1-D array of mesh boundary points along the z-axis. @@ -937,10 +937,10 @@ class SphericalMesh(MeshBase): 1-D array of mesh boundary points along the r-axis. Requirement is r >= 0. theta_grid : numpy.ndarray - 1-D array of mesh boundary points along the theta-axis in degrees. + 1-D array of mesh boundary points along the theta-axis in radians. The default value is [0, π], i.e. the full theta range. phi_grid : numpy.ndarray - 1-D array of mesh boundary points along the phi-axis in degrees. + 1-D array of mesh boundary points along the phi-axis in radians. The default value is [0, 2π], i.e. the full phi range. indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), From d2ddc6e7ad165028b41a5d52415c907792b7ef52 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 1 Mar 2022 17:05:17 -0600 Subject: [PATCH 0035/2654] Particle is alive is wgt != 0 --- include/openmc/particle_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index ee0dc6dfc..e32451f3a 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -363,7 +363,7 @@ public: const double& time() const { return time_; } double& time_last() { return time_last_; } const double& time_last() const { return time_last_; } - bool alive() { return wgt_ > 0.0; } + bool alive() { return wgt_ != 0.0; } Position& r_last_current() { return r_last_current_; } const Position& r_last_current() const { return r_last_current_; } From 50a35cf7f3c9ef6c20a910fbfdffc53ce4515e8c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 2 Mar 2022 15:31:02 -0600 Subject: [PATCH 0036/2654] Make ParticleData::alive() a const method --- include/openmc/particle_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index e32451f3a..ddf072517 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -363,7 +363,7 @@ public: const double& time() const { return time_; } double& time_last() { return time_last_; } const double& time_last() const { return time_last_; } - bool alive() { return wgt_ != 0.0; } + bool alive() const { return wgt_ != 0.0; } Position& r_last_current() { return r_last_current_; } const Position& r_last_current() const { return r_last_current_; } From 51b6d591052fa14139817f5da1b6887b38c450e5 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 3 Mar 2022 18:14:17 +0000 Subject: [PATCH 0037/2654] minimal changes to allow mat objects not id strings --- openmc/deplete/results.py | 2 ++ openmc/deplete/results_list.py | 15 ++++++++------- tests/unit_tests/test_deplete_activation.py | 4 ++-- tests/unit_tests/test_deplete_integrator.py | 8 ++++++-- tests/unit_tests/test_deplete_restart.py | 7 +++++-- tests/unit_tests/test_deplete_resultslist.py | 15 ++++++++++----- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index cda1864a1..89c6f8874 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -86,6 +86,8 @@ class Results: """ stage, mat, nuc = pos + if isinstance(mat, openmc.Material): + mat = str(mat.id) if isinstance(mat, str): mat = self.mat_to_ind[mat] if isinstance(nuc, str): diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index a9a0e5211..9ffbe6e73 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -58,8 +58,8 @@ class ResultsList(list): Parameters ---------- - mat : str - Material name to evaluate + mat : openmc.Material + Material object to evaluate nuc : str Nuclide name to evaluate nuc_units : {"atoms", "atom/b-cm", "atom/cm3"}, optional @@ -84,13 +84,14 @@ class ResultsList(list): cv.check_value("nuc_units", nuc_units, {"atoms", "atom/b-cm", "atom/cm3"}) + mat_id = str(mat.id) times = np.empty_like(self, dtype=float) concentrations = np.empty_like(self, dtype=float) # Evaluate value in each region for i, result in enumerate(self): times[i] = result.time[0] - concentrations[i] = result[0, mat, nuc] + concentrations[i] = result[0, mat_id, nuc] # Unit conversions if time_units == "d": @@ -102,7 +103,7 @@ class ResultsList(list): if nuc_units != "atoms": # Divide by volume to get density - concentrations /= self[0].volume[mat] + concentrations /= self[0].volume[mat_id] if nuc_units == "atom/b-cm": # 1 barn = 1e-24 cm^2 concentrations *= 1e-24 @@ -122,8 +123,8 @@ class ResultsList(list): Parameters ---------- - mat : str - Material name to evaluate + mat : openmc.Material + Material object to evaluate nuc : str Nuclide name to evaluate rx : str @@ -143,7 +144,7 @@ class ResultsList(list): # Evaluate value in each region for i, result in enumerate(self): times[i] = result.time[0] - rates[i] = result.rates[0].get(mat, nuc, rx) * result[0, mat, nuc] + rates[i] = result.rates[0].get(str(mat.id), nuc, rx) * result[0, mat, nuc] return times, rates diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 37b29e1ea..5ad560019 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -108,7 +108,7 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts # Get resulting number of atoms results = openmc.deplete.ResultsList.from_hdf5('depletion_results.h5') - _, atoms = results.get_atoms(str(w.id), "W186") + _, atoms = results.get_atoms(w.id, "W186") assert atoms[0] == pytest.approx(n0) assert atoms[1] / atoms[0] == pytest.approx(0.5, rel=tolerance) @@ -156,7 +156,7 @@ def test_decay(run_in_tmpdir): # Get resulting number of atoms results = openmc.deplete.ResultsList.from_hdf5('depletion_results.h5') - _, atoms = results.get_atoms(str(mat.id), "Sr89") + _, atoms = results.get_atoms(mat, "Sr89") # Ensure density goes down by a factor of 2 after each half-life assert atoms[1] / atoms[0] == pytest.approx(0.5) diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py index a08d8738c..c22f075aa 100644 --- a/tests/unit_tests/test_deplete_integrator.py +++ b/tests/unit_tests/test_deplete_integrator.py @@ -14,6 +14,7 @@ import numpy as np from uncertainties import ufloat import pytest +from openmc import Material from openmc.mpi import comm from openmc.deplete import ( ReactionRates, Results, ResultsList, OperatorResult, PredictorIntegrator, @@ -179,8 +180,11 @@ def test_integrator(run_in_tmpdir, scheme): res = ResultsList.from_hdf5( operator.output_dir / "depletion_results.h5") - t1, y1 = res.get_atoms("1", "1") - t2, y2 = res.get_atoms("1", "2") + mat = Material() + mat.id = 1 + + t1, y1 = res.get_atoms(mat, "1") + t2, y2 = res.get_atoms(mat, "2") assert (t1 == [0.0, 0.75, 1.5]).all() assert y1 == pytest.approx(bundle.atoms_1) diff --git a/tests/unit_tests/test_deplete_restart.py b/tests/unit_tests/test_deplete_restart.py index 82ef05ac7..f396a8b8f 100644 --- a/tests/unit_tests/test_deplete_restart.py +++ b/tests/unit_tests/test_deplete_restart.py @@ -87,8 +87,11 @@ def test_restart(run_in_tmpdir, scheme): results = openmc.deplete.ResultsList.from_hdf5( operator.output_dir / "depletion_results.h5") - _t, y1 = results.get_atoms("1", "1") - _t, y2 = results.get_atoms("1", "2") + mat = openmc.Material() + mat.id = 1 + + _t, y1 = results.get_atoms(mat, "1") + _t, y2 = results.get_atoms(mat, "2") assert y1 == pytest.approx(bundle.atoms_1) assert y2 == pytest.approx(bundle.atoms_2) diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 5d8fb11e4..96bbcab77 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -18,7 +18,10 @@ def res(): def test_get_atoms(res): """Tests evaluating single nuclide concentration.""" - t, n = res.get_atoms("1", "Xe135") + mat = openmc.Material() + mat.id = 1 + + t, n = res.get_atoms(mat, "Xe135") t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) n_ref = np.array( @@ -30,22 +33,24 @@ def test_get_atoms(res): # Check alternate units volume = res[0].volume["1"] - t_days, n_cm3 = res.get_atoms("1", "Xe135", nuc_units="atom/cm3", time_units="d") + t_days, n_cm3 = res.get_atoms(mat, "Xe135", nuc_units="atom/cm3", time_units="d") assert t_days == pytest.approx(t_ref / (60 * 60 * 24)) assert n_cm3 == pytest.approx(n_ref / volume) - t_min, n_bcm = res.get_atoms("1", "Xe135", nuc_units="atom/b-cm", time_units="min") + t_min, n_bcm = res.get_atoms(mat, "Xe135", nuc_units="atom/b-cm", time_units="min") assert n_bcm == pytest.approx(n_cm3 * 1e-24) assert t_min == pytest.approx(t_ref / 60) - t_hour, _n = res.get_atoms("1", "Xe135", time_units="h") + t_hour, _n = res.get_atoms(mat, "Xe135", time_units="h") assert t_hour == pytest.approx(t_ref / (60 * 60)) def test_get_reaction_rate(res): """Tests evaluating reaction rate.""" - t, r = res.get_reaction_rate("1", "Xe135", "(n,gamma)") + mat = openmc.Material() + mat.id = 1 + t, r = res.get_reaction_rate(mat, "Xe135", "(n,gamma)") t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] n_ref = [6.67473282e+08, 3.72442707e+14, 3.61129692e+14, 4.01920099e+14] From 504d58f04564c79b4b83e40467104e395f3ea9b9 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 3 Mar 2022 18:18:39 +0000 Subject: [PATCH 0038/2654] passing arg of type material not string --- examples/pincell_depletion/restart_depletion.py | 4 ++-- examples/pincell_depletion/run_depletion.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pincell_depletion/restart_depletion.py b/examples/pincell_depletion/restart_depletion.py index fd0a4a8dd..991120399 100644 --- a/examples/pincell_depletion/restart_depletion.py +++ b/examples/pincell_depletion/restart_depletion.py @@ -62,10 +62,10 @@ results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") time, keff = results.get_eigenvalue() # Obtain U235 concentration as a function of time -time, n_U235 = results.get_atoms('1', 'U235') +time, n_U235 = results.get_atoms(uo2, 'U235') # Obtain Xe135 capture reaction rate as a function of time -time, Xe_capture = results.get_reaction_rate('1', 'Xe135', '(n,gamma)') +time, Xe_capture = results.get_reaction_rate(uo2, 'Xe135', '(n,gamma)') ############################################################################### # Generate plots diff --git a/examples/pincell_depletion/run_depletion.py b/examples/pincell_depletion/run_depletion.py index 45dfd2a87..75bc3b542 100644 --- a/examples/pincell_depletion/run_depletion.py +++ b/examples/pincell_depletion/run_depletion.py @@ -107,10 +107,10 @@ results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") time, keff = results.get_eigenvalue() # Obtain U235 concentration as a function of time -time, n_U235 = results.get_atoms('1', 'U235') +time, n_U235 = results.get_atoms(uo2, 'U235') # Obtain Xe135 capture reaction rate as a function of time -time, Xe_capture = results.get_reaction_rate('1', 'Xe135', '(n,gamma)') +time, Xe_capture = results.get_reaction_rate(uo2, 'Xe135', '(n,gamma)') ############################################################################### # Generate plots From 130b3a2dc62c55b2c726d12886a897fe0cd95866 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 3 Mar 2022 19:14:00 +0000 Subject: [PATCH 0039/2654] corrected arg type to material --- tests/unit_tests/test_deplete_activation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 5ad560019..2f02ec4b8 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -108,7 +108,7 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts # Get resulting number of atoms results = openmc.deplete.ResultsList.from_hdf5('depletion_results.h5') - _, atoms = results.get_atoms(w.id, "W186") + _, atoms = results.get_atoms(w, "W186") assert atoms[0] == pytest.approx(n0) assert atoms[1] / atoms[0] == pytest.approx(0.5, rel=tolerance) From cf273b35a3b59cd4088364a793025dec0053ce47 Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 3 Mar 2022 17:20:44 -0800 Subject: [PATCH 0040/2654] Fix package_data specification to include pyx files for Cython builds. This fixes building of a standalone distributable python package. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f2a9929ae..1b2b66a91 100755 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ kwargs = { # Data files and librarries 'package_data': { 'openmc.lib': ['libopenmc.{}'.format(suffix)], - 'openmc.data': ['mass16.txt', 'BREMX.DAT', '*.h5'], + 'openmc.data': ['mass16.txt', 'BREMX.DAT', '*.h5', '*.pyx'], 'openmc.data.effective_dose': ['*.txt'] }, From aeb7cbd0e218cf53b4a89d26745d6109f866dec2 Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 3 Mar 2022 23:06:37 -0800 Subject: [PATCH 0041/2654] Use statement in MANIFEST.in instead --- MANIFEST.in | 4 ++-- setup.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index e660a1161..b9f5f21cd 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -27,7 +27,7 @@ recursive-include examples *.py recursive-include examples *.xml recursive-include include *.h recursive-include man *.1 -recursive-inlcude openmc *.pyx +recursive-include openmc *.pyx recursive-include openmc *.c recursive-include src *.c recursive-include src *.cc @@ -38,7 +38,7 @@ recursive-include src *.rnc recursive-include src *.rng recursive-include tests *.dat recursive-include tests *.h5 -recursive-inlcude tests *.h5m +recursive-include tests *.h5m recursive-include tests *.py recursive-include tests *.xml recursive-include vendor CMakeLists.txt diff --git a/setup.py b/setup.py index 1b2b66a91..b2e3f160a 100755 --- a/setup.py +++ b/setup.py @@ -29,10 +29,10 @@ kwargs = { 'packages': find_packages(exclude=['tests*']), 'scripts': glob.glob('scripts/openmc-*'), - # Data files and librarries + # Data files and libraries 'package_data': { 'openmc.lib': ['libopenmc.{}'.format(suffix)], - 'openmc.data': ['mass16.txt', 'BREMX.DAT', '*.h5', '*.pyx'], + 'openmc.data': ['mass16.txt', 'BREMX.DAT', '*.h5'], 'openmc.data.effective_dose': ['*.txt'] }, From 48f3321e3d6b23cef9e09522b41eb53bd0dc09ae Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Mar 2022 07:25:44 -0600 Subject: [PATCH 0042/2654] Allow meshes with same ID to appear in different files --- src/mesh.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 9310248c3..78e2e8952 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -21,6 +21,7 @@ #include "openmc/capi.h" #include "openmc/constants.h" +#include "openmc/container_util.h" #include "openmc/error.h" #include "openmc/file_utils.h" #include "openmc/hdf5_interface.h" @@ -97,16 +98,8 @@ inline bool check_intersection_point(double x1, double x0, double y1, double y0, Mesh::Mesh(pugi::xml_node node) { - // Copy mesh id - if (check_for_node(node, "id")) { - id_ = std::stoi(get_node_value(node, "id")); - - // Check to make sure 'id' hasn't been used - if (model::mesh_map.find(id_) != model::mesh_map.end()) { - fatal_error( - "Two or more meshes use the same unique ID: " + std::to_string(id_)); - } - } + // Read mesh id + id_ = std::stoi(get_node_value(node, "id")); } void Mesh::set_id(int32_t id) @@ -2568,7 +2561,24 @@ double LibMesh::volume(int bin) const void read_meshes(pugi::xml_node root) { + std::unordered_set mesh_ids; + for (auto node : root.children("mesh")) { + // Check to make sure multiple meshes in the same file don't share IDs + int id = std::stoi(get_node_value(node, "id")); + if (contains(mesh_ids, id)) { + fatal_error( + "Two or more meshes use the same unique ID: " + std::to_string(id)); + } + mesh_ids.insert(id); + + // If we've already read a mesh with the same ID in a *different* file, + // assume it is the same here + if (model::mesh_map.find(id) != model::mesh_map.end()) { + warning(fmt::format("Mesh with ID={} appears in multiple files.", id)); + continue; + } + std::string mesh_type; if (check_for_node(node, "type")) { mesh_type = get_node_value(node, "type", true, true); From 093886a4eba866e5b084447ee5993214cc5b6f28 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 4 Mar 2022 14:07:16 +0000 Subject: [PATCH 0043/2654] [skip ci] suggestion from review by @Paulromano Co-authored-by: Paul Romano --- openmc/deplete/results_list.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 9ffbe6e73..30ade440c 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -84,7 +84,8 @@ class ResultsList(list): cv.check_value("nuc_units", nuc_units, {"atoms", "atom/b-cm", "atom/cm3"}) - mat_id = str(mat.id) + if isinstance(mat, openmc.Material): + mat = mat.id times = np.empty_like(self, dtype=float) concentrations = np.empty_like(self, dtype=float) From 00ebf5706cc72dc3c2955f99c81458869699877b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 4 Mar 2022 14:24:43 +0000 Subject: [PATCH 0044/2654] accepting str or Material types --- openmc/deplete/results_list.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 9ffbe6e73..a9e55c177 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -58,8 +58,8 @@ class ResultsList(list): Parameters ---------- - mat : openmc.Material - Material object to evaluate + mat : openmc.Material, str + Material object or material id to evaluate nuc : str Nuclide name to evaluate nuc_units : {"atoms", "atom/b-cm", "atom/cm3"}, optional @@ -84,7 +84,12 @@ class ResultsList(list): cv.check_value("nuc_units", nuc_units, {"atoms", "atom/b-cm", "atom/cm3"}) - mat_id = str(mat.id) + if isinstance(mat, Material): + mat_id = str(mat.id) + elif isinstance(mat, str): + mat_id = mat + else: + raise TypeError('mat should be of type openmc.Material or str') times = np.empty_like(self, dtype=float) concentrations = np.empty_like(self, dtype=float) @@ -123,8 +128,8 @@ class ResultsList(list): Parameters ---------- - mat : openmc.Material - Material object to evaluate + mat : openmc.Material, str + Material object or material id to evaluate nuc : str Nuclide name to evaluate rx : str @@ -141,10 +146,17 @@ class ResultsList(list): times = np.empty_like(self, dtype=float) rates = np.empty_like(self, dtype=float) + if isinstance(mat, Material): + mat_id = str(mat.id) + elif isinstance(mat, str): + mat_id = mat + else: + raise TypeError('mat should be of type openmc.Material or str') + # Evaluate value in each region for i, result in enumerate(self): times[i] = result.time[0] - rates[i] = result.rates[0].get(str(mat.id), nuc, rx) * result[0, mat, nuc] + rates[i] = result.rates[0].get(mat_id, nuc, rx) * result[0, mat, nuc] return times, rates From 8418eaeedbeac03848780f64a873af9caf1f5290 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Mar 2022 10:13:05 -0600 Subject: [PATCH 0045/2654] Update troubleshooting guide with better instructions for geometry debugging --- docs/source/usersguide/troubleshoot.rst | 96 +++++++++++++------------ 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/docs/source/usersguide/troubleshoot.rst b/docs/source/usersguide/troubleshoot.rst index 06e5c5704..888158837 100644 --- a/docs/source/usersguide/troubleshoot.rst +++ b/docs/source/usersguide/troubleshoot.rst @@ -15,13 +15,15 @@ error you are receiving is among the following options. Problems with Simulations ------------------------- -Segmentation Fault -****************** +RuntimeError: OpenMC aborted unexpectedly. +****************************************** -A segmentation fault occurs when the program tries to access a variable in -memory that was outside the memory allocated for the program. The best way to -debug a segmentation fault is to re-compile OpenMC with debug options turned -on. Create a new build directory and type the following commands: +This error usually indicates that OpenMC experienced a segmentation fault. A +segmentation fault occurs when the program tries to access a variable in memory +that was outside the memory allocated for the program. The best way to debug a +segmentation fault is to :ref:`compile OpenMC from source ` with +debug options turned on. Create a new build directory and type the following +commands: .. code-block:: sh @@ -34,6 +36,28 @@ failed. If after reading the debug output, you are still unsure why the program failed, post a message on the `OpenMC Discourse Forum `_. +.. _troubleshoot_lost_particles: + +WARNING: After particle __ crossed surface __ it could not be located in any cell and it did not leak. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +During a simulation, particles can become "lost" if they reach a surface and +there is no cell defined on the other side of the surface. It is important to +ensure that 1) proper boundary conditions have been applied to the outer +surfaces of your model and 2) all space in your model is filled with a cell, +even regions that are void and have no material assigned to them. + +Please see the instructions in :ref:`troubleshoot_geometry` on how to resolve +issues with lost particles. + +ERROR: Maximum number of lost particles has been reached. +********************************************************* + +See the above description regarding :ref:`lost particles +`. When too many particles are lost, the simulation +will abort altogether. Again, please see the instructions in +:ref:`troubleshoot_geometry` on how to resolve issues with lost particles. + ERROR: No cross_sections.xml file was specified in settings.xml or in the OPENMC_CROSS_SECTIONS environment variable. ********************************************************************************************************************* @@ -62,22 +86,33 @@ it is recommended that data be extracted from statepoint files in a context mana or that the :meth:`StatePoint.close` method is called before executing a subsequent OpenMC run. +.. _troubleshoot_geometry: + Geometry Debugging ****************** -Overlapping Cells -^^^^^^^^^^^^^^^^^ +To identify issues in your geometry, it is highly recommended to use the `OpenMC +Plot Explorer `_ GUI application. This +application enables you to interactively explore a model, identify regions that +may be missing a cell definition, and identify overlapping cells. -For fast run times, normal simulations do not check if the geometry is -incorrectly defined to have overlapping cells. This can lead to incorrect -results that may or may not be obvious when there are errors in the geometry -input file. The built-in 2D and 3D plotters will check for cell overlaps at -the center of every pixel or voxel position they process, however this might -not be a sufficient check to ensure correctly defined geometry. For instance, -if an overlap is of small aspect ratio, the plotting resolution might not be -high enough to produce any pixels in the overlapping area. +If you are having issues with lost particles, the following procedure may be +helpful. If OpenMC reports, for example, that a particle reaching surface 50 +could not be located, look at your geometry.xml to see which cells have a region +definition that includes surface 50, e.g.: -To reliably validate a geometry input, it is best to run the problem in +.. code-block:: xml + + + +This may indicate that you need to define a cell on the other side of cell 10. +At this point, using the OpenMC Plot Explorer to locate cell 10 may provide a +visual clue as to whether there is a missing or overlapping cell near cell 10. +Working with the unique integer IDs of cells may be cumbersome; if you provide +names to your cells, these names will show up in the Plot Explorer, which will +aid geometry debugging. + +Another method to check for overlapping cells in a geometry is to run the problem in geometry debugging mode with the ``-g``, ``-geometry-debug``, or ``--geometry-debug`` command-line options. This will enable checks for overlapping cells at every move of each simulated particle. Depending on the @@ -92,33 +127,6 @@ output after a geometry debug run to see how many checks were performed in each cell, and then adjust the number of starting particles or starting source distributions accordingly to achieve good coverage. -ERROR: After particle __ crossed surface __ it could not be located in any cell and it did not leak. -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This error can arise either if a problem is specified with no boundary -conditions or if there is an error in the geometry itself. First check to ensure -that all of the outer surfaces of your geometry have been given vacuum or -reflective boundary conditions. If proper boundary conditions have been applied -and you still receive this error, it means that a surface/cell/lattice in your -geometry has been specified incorrectly or is missing. - -The best way to debug this error is to turn on a trace for the particle getting -lost. After the error message, the code will display what batch, generation, and -particle number caused the error. In your settings.xml, add a :ref:`trace` -followed by the batch, generation, and particle number. This will give you -detailed output every time that particle enters a cell, crosses a boundary, or -has a collision. For example, if you received this error at cycle 5, generation -1, particle 4032, you would enter: - -.. code-block:: xml - - 5 1 4032 - -For large runs it is often advantageous to run only the offending particle by -using particle restart mode with the ``-r`` command-line option in conjunction -with the particle restart files that are created when particles are lost with -this error. - Depletion ********* From 338abf2fab859c672089d2161707e0439afa5e1b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Mar 2022 10:34:37 -0600 Subject: [PATCH 0046/2654] Fix broken links, remove section talking about MATLAB --- docs/source/devguide/workflow.rst | 4 ++-- docs/source/methods/cross_sections.rst | 9 ++++---- docs/source/methods/neutron_physics.rst | 7 +++--- docs/source/methods/tallies.rst | 2 +- docs/source/usersguide/cross_sections.rst | 4 ++-- docs/source/usersguide/geometry.rst | 8 +++---- docs/source/usersguide/install.rst | 5 +++-- docs/source/usersguide/processing.rst | 27 ++++++++--------------- 8 files changed, 29 insertions(+), 37 deletions(-) diff --git a/docs/source/devguide/workflow.rst b/docs/source/devguide/workflow.rst index 3bad04cae..6b5ec63cb 100644 --- a/docs/source/devguide/workflow.rst +++ b/docs/source/devguide/workflow.rst @@ -119,8 +119,8 @@ pip_. From the root directory of the OpenMC repository, run: pip install -e .[test] This installs the OpenMC Python package in `"editable" mode -`_ so -that 1) it can be imported from a Python interpreter and 2) any changes made are +`_ so that 1) +it can be imported from a Python interpreter and 2) any changes made are immediately reflected in the installed version (that is, you don't need to keep reinstalling it). While the same effect can be achieved using the :envvar:`PYTHONPATH` environment variable, this is generally discouraged as it diff --git a/docs/source/methods/cross_sections.rst b/docs/source/methods/cross_sections.rst index 2210dfa45..3396d7f25 100644 --- a/docs/source/methods/cross_sections.rst +++ b/docs/source/methods/cross_sections.rst @@ -187,9 +187,10 @@ are represented using a multi-group library format specific to the OpenMC code. The format is described in the :ref:`mgxs_lib_spec`. The data itself can be prepared via traditional paths or directly from a continuous-energy OpenMC calculation by use of the Python API as is shown in an `example notebook -<../examples/mg-mode-part-i.ipynb>`_. This multi-group library consists of -meta-data (such as the energy group structure) and multiple `xsdata` objects -which contains the required microscopic or macroscopic multi-group data. +`_. +This multi-group library consists of meta-data (such as the energy group +structure) and multiple `xsdata` objects which contains the required microscopic +or macroscopic multi-group data. At a minimum, the library must contain the absorption cross section (:math:`\sigma_{a,g}`) and a scattering matrix. If the problem is an eigenvalue @@ -275,6 +276,6 @@ or even isotropic scattering. .. _MCNP: https://mcnp.lanl.gov .. _Serpent: http://montecarlo.vtt.fi .. _NJOY: https://www.njoy21.io/NJOY21/ -.. _ENDF/B data: https://www.nndc.bnl.gov/endf/b8.0/ +.. _ENDF/B data: https://www.nndc.bnl.gov/endf-b8.0/ .. _Leppanen: https://doi.org/10.1016/j.anucene.2009.03.019 .. _algorithms: http://ab-initio.mit.edu/wiki/index.php/Faddeeva_Package diff --git a/docs/source/methods/neutron_physics.rst b/docs/source/methods/neutron_physics.rst index e9061eea1..2e9f313d7 100644 --- a/docs/source/methods/neutron_physics.rst +++ b/docs/source/methods/neutron_physics.rst @@ -359,7 +359,7 @@ secondary energy and angle sampling. For a reaction with secondary products, it is necessary to determine the outgoing angle and energy of the products. For any reaction other than elastic and level inelastic scattering, the outgoing energy must be determined based on -tabulated or parameterized data. The `ENDF-6 Format `_ specifies a +tabulated or parameterized data. The `ENDF-6 Format` specifies a variety of ways that the secondary energy distribution can be represented. ENDF File 5 contains uncorrelated energy distribution whereas ENDF File 6 contains correlated energy-angle distributions. The ACE format specifies its own @@ -1416,8 +1416,7 @@ For incoherent elastic scattering, OpenMC has two methods for calculating the cosine of the angle of scattering. The first method uses the Debye-Waller integral, :math:`W'`, and the characteristic bound cross section as given directly in an ENDF-6 formatted file. In this case, the cosine of the angle of -scattering can be sampled by inverting equation 7.4 from the `ENDF-6 Format -Manual `_: +scattering can be sampled by inverting equation 7.4 from the `ENDF-6 Format`_: .. math:: :label: incoherent-elastic-mu-exact @@ -1752,7 +1751,7 @@ types. .. _PREPRO: https://www-nds.iaea.org/ndspub/endf/prepro/ -.. _endf102: https://www.oecd-nea.org/dbdata/data/manual-endf/endf102.pdf +.. _ENDF-6 Format: https://www.oecd-nea.org/dbdata/data/manual-endf/endf102.pdf .. _Monte Carlo Sampler: https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-09721-MS diff --git a/docs/source/methods/tallies.rst b/docs/source/methods/tallies.rst index dc3a63dec..1aae47d6e 100644 --- a/docs/source/methods/tallies.rst +++ b/docs/source/methods/tallies.rst @@ -510,6 +510,6 @@ improve the estimate of the percentile. .. _Cauchy distribution: https://en.wikipedia.org/wiki/Cauchy_distribution -.. _unpublished rational approximation: https://web.archive.org/web/20150926021742/http://home.online.no/~pjacklam/notes/invnorm/ +.. _unpublished rational approximation: https://stackedboxes.org/2017/05/01/acklams-normal-quantile-function/ .. _MC21: http://www.osti.gov/bridge/servlets/purl/903083-HT5p1o/903083.pdf diff --git a/docs/source/usersguide/cross_sections.rst b/docs/source/usersguide/cross_sections.rst index 58bf1a293..0cbb581bd 100644 --- a/docs/source/usersguide/cross_sections.rst +++ b/docs/source/usersguide/cross_sections.rst @@ -124,7 +124,7 @@ OpenMC. .. hint:: The :class:`IncidentNeutron` class allows you to view/modify cross sections, secondary angle/energy distributions, probability tables, etc. For a more thorough overview of the capabilities of this class, - see the `example notebook <../examples/nuclear-data.ipynb>`__. + see the `example notebook `_. Manually Creating a Library from ENDF files ------------------------------------------- @@ -259,7 +259,7 @@ For an example of how to create a multi-group library, see the `example notebook .. _NNDC: https://www.nndc.bnl.gov/endf .. _MCNP: https://mcnp.lanl.gov .. _Serpent: http://montecarlo.vtt.fi -.. _ENDF/B: https://www.nndc.bnl.gov/endf/b7.1/acefiles.html +.. _ENDF/B: https://www.nndc.bnl.gov/endf-b7.1/acefiles.html .. _JEFF: https://www.oecd-nea.org/dbdata/jeff/jeff33/ .. _TENDL: https://tendl.web.psi.ch/tendl_2017/tendl2017.html .. _Seltzer and Berger: https://doi.org/10.1016/0092-640X(86)90014-8 diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index 68ecfce95..2382609a4 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -478,10 +478,10 @@ OpenMC to verify that the model matches one's expectations. **Note:** DAGMC geometries used in OpenMC are currently required to be clean, meaning that all surfaces have been `imprinted and merged -`_ -successfully and that the model is `watertight -`_. Future -implementations of DAGMC geometry will support small volume overlaps and +`_ successfully +and that the model is `watertight +`_. +Future implementations of DAGMC geometry will support small volume overlaps and un-merged surfaces. Cell, Surface, and Material IDs diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 7961b3e38..fb721c7ce 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -512,8 +512,9 @@ distributions. are used for several optional features in the API. `pandas `_ - Pandas is used to generate tally DataFrames as demonstrated in - an `example notebook <../examples/pandas-dataframes.ipynb>`_. + Pandas is used to generate tally DataFrames as demonstrated in an `example + notebook + `_. `h5py `_ h5py provides Python bindings to the HDF5 library. Since OpenMC outputs diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index e61ba33bf..3103b7b7c 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -34,30 +34,20 @@ as requested; it is used in many of the provided plotting utilities, OpenMC's regression test suite, and can be used in user-created scripts to carry out manipulations of the data. -An `example notebook <../examples/post-processing.ipynb>`_ demonstrates how to -extract data from a statepoint using the Python API. +An `example notebook`_ demonstrates how to extract data from a statepoint using +the Python API. Plotting in 2D -------------- -The `notebook example <../examples/post-processing.ipynb>`_ also demonstrates -how to plot a structured mesh tally in two dimensions using the Python API. One -can also use the :ref:`scripts_plot` script which provides an interactive GUI to -explore and plot structured mesh tallies for any scores and filter bins. +The `example notebook`_ also demonstrates how to plot a structured mesh tally in +two dimensions using the Python API. One can also use the :ref:`scripts_plot` +script which provides an interactive GUI to explore and plot structured mesh +tallies for any scores and filter bins. .. image:: ../_images/plotmeshtally.png :width: 400px -Getting Data into MATLAB ------------------------- - -There is currently no front-end utility to dump tally data to MATLAB files, but -the process is straightforward. First extract the data using the Python API via -``openmc.statepoint`` and then use the `Scipy MATLAB IO routines -`_ to save to a MAT -file. Note that all arrays that are accessible in a statepoint are already in -NumPy arrays that can be reshaped and dumped to MATLAB in one step. - .. _usersguide_track: ---------------------------- @@ -101,5 +91,6 @@ For eigenvalue problems, OpenMC will store information on the fission source sites in the statepoint file by default. For each source site, the weight, position, sampled direction, and sampled energy are stored. To extract this data from a statepoint file, the ``openmc.statepoint`` module can be used. An -`example notebook <../examples/post-processing.ipynb>`_ demontrates how to -analyze and plot source information. +`example notebook`_ demontrates how to analyze and plot source information. + +.. _example notebook: https://nbviewer.jupyter.org/github/openmc-dev/openmc-notebooks/blob/main/post-processing.ipynb From fc9e71ede09b20c8b1896f26f12bc07c9903be3f Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 4 Mar 2022 15:00:28 -0800 Subject: [PATCH 0047/2654] Fix warnings in MANIFEST.in file caused by looking for non-existent files in examples and src --- MANIFEST.in | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index b9f5f21cd..c2789a152 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -8,7 +8,6 @@ include schemas.xml include pyproject.toml include pytest.ini include docs/source/_templates/layout.html -include docs/sphinxext/LICENSE global-include *.cmake global-include *.cmake.in global-include *.rst @@ -20,8 +19,6 @@ recursive-include docs *.svg recursive-include docs *.tex recursive-include docs *.txt recursive-include docs Makefile -recursive-include examples *.h5 -recursive-include examples *.png recursive-include examples *.cpp recursive-include examples *.py recursive-include examples *.xml @@ -29,11 +26,7 @@ recursive-include include *.h recursive-include man *.1 recursive-include openmc *.pyx recursive-include openmc *.c -recursive-include src *.c -recursive-include src *.cc recursive-include src *.cpp -recursive-include src *.h -recursive-include src *.hpp recursive-include src *.rnc recursive-include src *.rng recursive-include tests *.dat From aac4903e74a6087157b08d09b68f5dc475ef8d6d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 7 Mar 2022 14:10:21 -0600 Subject: [PATCH 0048/2654] Fix link in neutron_physics.rst Co-authored-by: Patrick Shriwise --- docs/source/methods/neutron_physics.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/methods/neutron_physics.rst b/docs/source/methods/neutron_physics.rst index 2e9f313d7..bea92f992 100644 --- a/docs/source/methods/neutron_physics.rst +++ b/docs/source/methods/neutron_physics.rst @@ -359,7 +359,7 @@ secondary energy and angle sampling. For a reaction with secondary products, it is necessary to determine the outgoing angle and energy of the products. For any reaction other than elastic and level inelastic scattering, the outgoing energy must be determined based on -tabulated or parameterized data. The `ENDF-6 Format` specifies a +tabulated or parameterized data. The `ENDF-6 Format`_ specifies a variety of ways that the secondary energy distribution can be represented. ENDF File 5 contains uncorrelated energy distribution whereas ENDF File 6 contains correlated energy-angle distributions. The ACE format specifies its own From 4ba635f472ee2b7dcab1935c702908440fa2ad64 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 7 Mar 2022 20:15:03 +0000 Subject: [PATCH 0049/2654] Suggestions from PR review by @Paulromano Co-authored-by: Paul Romano --- tests/unit_tests/test_deplete_integrator.py | 8 ++------ tests/unit_tests/test_deplete_restart.py | 7 ++----- tests/unit_tests/test_deplete_resultslist.py | 12 +++++------- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py index c22f075aa..a08d8738c 100644 --- a/tests/unit_tests/test_deplete_integrator.py +++ b/tests/unit_tests/test_deplete_integrator.py @@ -14,7 +14,6 @@ import numpy as np from uncertainties import ufloat import pytest -from openmc import Material from openmc.mpi import comm from openmc.deplete import ( ReactionRates, Results, ResultsList, OperatorResult, PredictorIntegrator, @@ -180,11 +179,8 @@ def test_integrator(run_in_tmpdir, scheme): res = ResultsList.from_hdf5( operator.output_dir / "depletion_results.h5") - mat = Material() - mat.id = 1 - - t1, y1 = res.get_atoms(mat, "1") - t2, y2 = res.get_atoms(mat, "2") + t1, y1 = res.get_atoms("1", "1") + t2, y2 = res.get_atoms("1", "2") assert (t1 == [0.0, 0.75, 1.5]).all() assert y1 == pytest.approx(bundle.atoms_1) diff --git a/tests/unit_tests/test_deplete_restart.py b/tests/unit_tests/test_deplete_restart.py index f396a8b8f..82ef05ac7 100644 --- a/tests/unit_tests/test_deplete_restart.py +++ b/tests/unit_tests/test_deplete_restart.py @@ -87,11 +87,8 @@ def test_restart(run_in_tmpdir, scheme): results = openmc.deplete.ResultsList.from_hdf5( operator.output_dir / "depletion_results.h5") - mat = openmc.Material() - mat.id = 1 - - _t, y1 = results.get_atoms(mat, "1") - _t, y2 = results.get_atoms(mat, "2") + _t, y1 = results.get_atoms("1", "1") + _t, y2 = results.get_atoms("1", "2") assert y1 == pytest.approx(bundle.atoms_1) assert y2 == pytest.approx(bundle.atoms_2) diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 96bbcab77..bcce45769 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -21,7 +21,7 @@ def test_get_atoms(res): mat = openmc.Material() mat.id = 1 - t, n = res.get_atoms(mat, "Xe135") + t, n = res.get_atoms("1", "Xe135") t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) n_ref = np.array( @@ -33,24 +33,22 @@ def test_get_atoms(res): # Check alternate units volume = res[0].volume["1"] - t_days, n_cm3 = res.get_atoms(mat, "Xe135", nuc_units="atom/cm3", time_units="d") + t_days, n_cm3 = res.get_atoms("1", "Xe135", nuc_units="atom/cm3", time_units="d") assert t_days == pytest.approx(t_ref / (60 * 60 * 24)) assert n_cm3 == pytest.approx(n_ref / volume) - t_min, n_bcm = res.get_atoms(mat, "Xe135", nuc_units="atom/b-cm", time_units="min") + t_min, n_bcm = res.get_atoms("1", "Xe135", nuc_units="atom/b-cm", time_units="min") assert n_bcm == pytest.approx(n_cm3 * 1e-24) assert t_min == pytest.approx(t_ref / 60) - t_hour, _n = res.get_atoms(mat, "Xe135", time_units="h") + t_hour, _n = res.get_atoms("1", "Xe135", time_units="h") assert t_hour == pytest.approx(t_ref / (60 * 60)) def test_get_reaction_rate(res): """Tests evaluating reaction rate.""" - mat = openmc.Material() - mat.id = 1 - t, r = res.get_reaction_rate(mat, "Xe135", "(n,gamma)") + t, r = res.get_reaction_rate("1", "Xe135", "(n,gamma)") t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] n_ref = [6.67473282e+08, 3.72442707e+14, 3.61129692e+14, 4.01920099e+14] From aa5e8ec418f6421790f70c65f3ad5cdf6829a81b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 7 Mar 2022 20:28:24 +0000 Subject: [PATCH 0050/2654] Suggestions from PR review by @Paulromano Co-authored-by: Paul Romano --- tests/unit_tests/test_deplete_resultslist.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index bcce45769..5d8fb11e4 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -18,9 +18,6 @@ def res(): def test_get_atoms(res): """Tests evaluating single nuclide concentration.""" - mat = openmc.Material() - mat.id = 1 - t, n = res.get_atoms("1", "Xe135") t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) From 6eb00c6c6f158c7dbf300108d0a5fcee66591b05 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 8 Mar 2022 13:04:42 +0000 Subject: [PATCH 0051/2654] added typehints to match docstrings --- openmc/settings.py | 96 +++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 9aef9a1fe..e09d13ed9 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -2,6 +2,8 @@ from collections.abc import Iterable, MutableSequence, Mapping from enum import Enum from pathlib import Path from numbers import Real, Integral +import typing as typing # imported separately as py3.8 requires typing.Iterable +from typing import Optional, Union from xml.etree import ElementTree as ET from math import ceil @@ -472,51 +474,51 @@ class Settings: return self._max_splits @run_mode.setter - def run_mode(self, run_mode): + def run_mode(self, run_mode: RunMode): cv.check_value('run mode', run_mode, {x.value for x in RunMode}) for mode in RunMode: if mode.value == run_mode: self._run_mode = mode @batches.setter - def batches(self, batches): + def batches(self, batches: int): cv.check_type('batches', batches, Integral) cv.check_greater_than('batches', batches, 0) self._batches = batches @generations_per_batch.setter - def generations_per_batch(self, generations_per_batch): + def generations_per_batch(self, generations_per_batch: int): cv.check_type('generations per patch', generations_per_batch, Integral) cv.check_greater_than('generations per batch', generations_per_batch, 0) self._generations_per_batch = generations_per_batch @inactive.setter - def inactive(self, inactive): + def inactive(self, inactive: int): cv.check_type('inactive batches', inactive, Integral) cv.check_greater_than('inactive batches', inactive, 0, True) self._inactive = inactive @max_lost_particles.setter - def max_lost_particles(self, max_lost_particles): + def max_lost_particles(self, max_lost_particles: int): cv.check_type('max_lost_particles', max_lost_particles, Integral) cv.check_greater_than('max_lost_particles', max_lost_particles, 0) self._max_lost_particles = max_lost_particles @rel_max_lost_particles.setter - def rel_max_lost_particles(self, rel_max_lost_particles): + def rel_max_lost_particles(self, rel_max_lost_particles: int): cv.check_type('rel_max_lost_particles', rel_max_lost_particles, Real) cv.check_greater_than('rel_max_lost_particles', rel_max_lost_particles, 0) cv.check_less_than('rel_max_lost_particles', rel_max_lost_particles, 1) self._rel_max_lost_particles = rel_max_lost_particles @particles.setter - def particles(self, particles): + def particles(self, particles: int): cv.check_type('particles', particles, Integral) cv.check_greater_than('particles', particles, 0) self._particles = particles @keff_trigger.setter - def keff_trigger(self, keff_trigger): + def keff_trigger(self, keff_trigger: dict): if not isinstance(keff_trigger, dict): msg = f'Unable to set a trigger on keff from "{keff_trigger}" ' \ 'which is not a Python dictionary' @@ -545,13 +547,13 @@ class Settings: self._keff_trigger = keff_trigger @energy_mode.setter - def energy_mode(self, energy_mode): + def energy_mode(self, energy_mode: str): cv.check_value('energy mode', energy_mode, ['continuous-energy', 'multi-group']) self._energy_mode = energy_mode @max_order.setter - def max_order(self, max_order): + def max_order(self, max_order: Optional[int]): if max_order is not None: cv.check_type('maximum scattering order', max_order, Integral) cv.check_greater_than('maximum scattering order', max_order, 0, @@ -559,13 +561,13 @@ class Settings: self._max_order = max_order @source.setter - def source(self, source): + def source(self, source: typing.Iterable[Source]): if not isinstance(source, MutableSequence): source = [source] self._source = cv.CheckedList(Source, 'source distributions', source) @output.setter - def output(self, output): + def output(self, output: dict): cv.check_type('output', output, Mapping) for key, value in output.items(): cv.check_value('output key', key, ('summary', 'tallies', 'path')) @@ -576,14 +578,14 @@ class Settings: self._output = output @verbosity.setter - def verbosity(self, verbosity): + def verbosity(self, verbosity: int): cv.check_type('verbosity', verbosity, Integral) cv.check_greater_than('verbosity', verbosity, 1, True) cv.check_less_than('verbosity', verbosity, 10, True) self._verbosity = verbosity @sourcepoint.setter - def sourcepoint(self, sourcepoint): + def sourcepoint(self, sourcepoint: dict): cv.check_type('sourcepoint options', sourcepoint, Mapping) for key, value in sourcepoint.items(): if key == 'batches': @@ -602,7 +604,7 @@ class Settings: self._sourcepoint = sourcepoint @statepoint.setter - def statepoint(self, statepoint): + def statepoint(self, statepoint: dict): cv.check_type('statepoint options', statepoint, Mapping) for key, value in statepoint.items(): if key == 'batches': @@ -615,7 +617,7 @@ class Settings: self._statepoint = statepoint @surf_source_read.setter - def surf_source_read(self, surf_source_read): + def surf_source_read(self, surf_source_read: dict): cv.check_type('surface source reading options', surf_source_read, Mapping) for key, value in surf_source_read.items(): cv.check_value('surface source reading key', key, @@ -625,7 +627,7 @@ class Settings: self._surf_source_read = surf_source_read @surf_source_write.setter - def surf_source_write(self, surf_source_write): + def surf_source_write(self, surf_source_write: dict): cv.check_type('surface source writing options', surf_source_write, Mapping) for key, value in surf_source_write.items(): cv.check_value('surface source writing key', key, @@ -644,38 +646,38 @@ class Settings: self._surf_source_write = surf_source_write @confidence_intervals.setter - def confidence_intervals(self, confidence_intervals): + def confidence_intervals(self, confidence_intervals: bool): cv.check_type('confidence interval', confidence_intervals, bool) self._confidence_intervals = confidence_intervals @electron_treatment.setter - def electron_treatment(self, electron_treatment): + def electron_treatment(self, electron_treatment: str): cv.check_value('electron treatment', electron_treatment, ['led', 'ttb']) self._electron_treatment = electron_treatment @photon_transport.setter - def photon_transport(self, photon_transport): + def photon_transport(self, photon_transport: bool): cv.check_type('photon transport', photon_transport, bool) self._photon_transport = photon_transport @ptables.setter - def ptables(self, ptables): + def ptables(self, ptables: bool): cv.check_type('probability tables', ptables, bool) self._ptables = ptables @seed.setter - def seed(self, seed): + def seed(self, seed: int): cv.check_type('random number generator seed', seed, Integral) cv.check_greater_than('random number generator seed', seed, 0) self._seed = seed @survival_biasing.setter - def survival_biasing(self, survival_biasing): + def survival_biasing(self, survival_biasing: bool): cv.check_type('survival biasing', survival_biasing, bool) self._survival_biasing = survival_biasing @cutoff.setter - def cutoff(self, cutoff): + def cutoff(self, cutoff: dict): if not isinstance(cutoff, Mapping): msg = f'Unable to set cutoff from "{cutoff}" which is not a '\ 'Python dictionary' @@ -699,34 +701,34 @@ class Settings: self._cutoff = cutoff @entropy_mesh.setter - def entropy_mesh(self, entropy): + def entropy_mesh(self, entropy: RegularMesh): cv.check_type('entropy mesh', entropy, RegularMesh) self._entropy_mesh = entropy @trigger_active.setter - def trigger_active(self, trigger_active): + def trigger_active(self, trigger_active: bool): cv.check_type('trigger active', trigger_active, bool) self._trigger_active = trigger_active @trigger_max_batches.setter - def trigger_max_batches(self, trigger_max_batches): + def trigger_max_batches(self, trigger_max_batches: int): cv.check_type('trigger maximum batches', trigger_max_batches, Integral) cv.check_greater_than('trigger maximum batches', trigger_max_batches, 0) self._trigger_max_batches = trigger_max_batches @trigger_batch_interval.setter - def trigger_batch_interval(self, trigger_batch_interval): + def trigger_batch_interval(self, trigger_batch_interval: int): cv.check_type('trigger batch interval', trigger_batch_interval, Integral) cv.check_greater_than('trigger batch interval', trigger_batch_interval, 0) self._trigger_batch_interval = trigger_batch_interval @no_reduce.setter - def no_reduce(self, no_reduce): + def no_reduce(self, no_reduce: bool): cv.check_type('no reduction option', no_reduce, bool) self._no_reduce = no_reduce @tabular_legendre.setter - def tabular_legendre(self, tabular_legendre): + def tabular_legendre(self, tabular_legendre: dict): cv.check_type('tabular_legendre settings', tabular_legendre, Mapping) for key, value in tabular_legendre.items(): cv.check_value('tabular_legendre key', key, @@ -739,7 +741,7 @@ class Settings: self._tabular_legendre = tabular_legendre @temperature.setter - def temperature(self, temperature): + def temperature(self, temperature: dict): cv.check_type('temperature settings', temperature, Mapping) for key, value in temperature.items(): @@ -763,7 +765,7 @@ class Settings: self._temperature = temperature @trace.setter - def trace(self, trace): + def trace(self, trace: Iterable): cv.check_type('trace', trace, Iterable, Integral) cv.check_length('trace', trace, 3) cv.check_greater_than('trace batch', trace[0], 0) @@ -772,7 +774,7 @@ class Settings: self._trace = trace @track.setter - def track(self, track): + def track(self, track: Iterable): cv.check_type('track', track, Iterable, Integral) if len(track) % 3 != 0: msg = f'Unable to set the track to "{track}" since its length is ' \ @@ -785,7 +787,7 @@ class Settings: self._track = track @ufs_mesh.setter - def ufs_mesh(self, ufs_mesh): + def ufs_mesh(self, ufs_mesh: RegularMesh): cv.check_type('UFS mesh', ufs_mesh, RegularMesh) cv.check_length('UFS mesh dimension', ufs_mesh.dimension, 3) cv.check_length('UFS mesh lower-left corner', ufs_mesh.lower_left, 3) @@ -793,7 +795,7 @@ class Settings: self._ufs_mesh = ufs_mesh @resonance_scattering.setter - def resonance_scattering(self, res): + def resonance_scattering(self, res: dict): cv.check_type('resonance scattering settings', res, Mapping) keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides') for key, value in res.items(): @@ -817,52 +819,52 @@ class Settings: self._resonance_scattering = res @volume_calculations.setter - def volume_calculations(self, vol_calcs): + def volume_calculations(self, vol_calcs: Union[VolumeCalculation, typing.Iterable[VolumeCalculation]]): if not isinstance(vol_calcs, MutableSequence): vol_calcs = [vol_calcs] self._volume_calculations = cv.CheckedList( VolumeCalculation, 'stochastic volume calculations', vol_calcs) @create_fission_neutrons.setter - def create_fission_neutrons(self, create_fission_neutrons): + def create_fission_neutrons(self, create_fission_neutrons: bool): cv.check_type('Whether create fission neutrons', create_fission_neutrons, bool) self._create_fission_neutrons = create_fission_neutrons @delayed_photon_scaling.setter - def delayed_photon_scaling(self, value): + def delayed_photon_scaling(self, value: bool): cv.check_type('delayed photon scaling', value, bool) self._delayed_photon_scaling = value @event_based.setter - def event_based(self, value): + def event_based(self, value: bool): cv.check_type('event based', value, bool) self._event_based = value @max_particles_in_flight.setter - def max_particles_in_flight(self, value): + def max_particles_in_flight(self, value: int): cv.check_type('max particles in flight', value, Integral) cv.check_greater_than('max particles in flight', value, 0) self._max_particles_in_flight = value @material_cell_offsets.setter - def material_cell_offsets(self, value): + def material_cell_offsets(self, value: bool): cv.check_type('material cell offsets', value, bool) self._material_cell_offsets = value @log_grid_bins.setter - def log_grid_bins(self, log_grid_bins): + def log_grid_bins(self, log_grid_bins: int): cv.check_type('log grid bins', log_grid_bins, Real) cv.check_greater_than('log grid bins', log_grid_bins, 0) self._log_grid_bins = log_grid_bins @write_initial_source.setter - def write_initial_source(self, value): + def write_initial_source(self, value: bool): cv.check_type('write initial source', value, bool) self._write_initial_source = value @weight_windows.setter - def weight_windows(self, value): + def weight_windows(self, value: Union[WeightWindows, typing.Iterable[WeightWindows]]): if not isinstance(value, MutableSequence): value = [value] self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows', value) @@ -873,7 +875,7 @@ class Settings: self._weight_windows_on = value @max_splits.setter - def max_splits(self, value): + def max_splits(self, value: int): cv.check_type('maximum particle splits', value, Integral) cv.check_greater_than('max particles in flight', value, 0) self._max_splits = value @@ -1492,7 +1494,7 @@ class Settings: if text is not None: self.max_splits = int(text) - def export_to_xml(self, path='settings.xml'): + def export_to_xml(self, path: str = 'settings.xml'): """Export simulation settings to an XML file. Parameters @@ -1563,7 +1565,7 @@ class Settings: tree.write(str(p), xml_declaration=True, encoding='utf-8') @classmethod - def from_xml(cls, path='settings.xml'): + def from_xml(cls, path: str = 'settings.xml'): """Generate settings from XML file .. versionadded:: 0.13.0 From 1fc44e4f9d871f77a28e40fa8f74be42c1024bac Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 8 Mar 2022 16:34:04 -0600 Subject: [PATCH 0052/2654] Clarify error message for meshes with same ID in same file Co-authored-by: Patrick Shriwise --- src/mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 78e2e8952..de29233fb 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2568,7 +2568,7 @@ void read_meshes(pugi::xml_node root) int id = std::stoi(get_node_value(node, "id")); if (contains(mesh_ids, id)) { fatal_error( - "Two or more meshes use the same unique ID: " + std::to_string(id)); + fmt::format("Two or more meshes use the same unique ID '{}' in the same input file", id)); } mesh_ids.insert(id); From 8e5dad821072fbb9e35b8ef0a60c51e772981b93 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 9 Mar 2022 09:45:14 -0600 Subject: [PATCH 0053/2654] fix overwritten variable in ace.py::get_libraries_from_xsdata --- openmc/data/ace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/data/ace.py b/openmc/data/ace.py index 97be6f627..06c581b42 100644 --- a/openmc/data/ace.py +++ b/openmc/data/ace.py @@ -573,11 +573,11 @@ def get_libraries_from_xsdata(path): List of paths to ACE libraries """ xsdata = Path(path) - with open(xsdata, 'r') as xsdata: + with open(xsdata, 'r') as xsdata_file: # As in get_libraries_from_xsdir, we use a dict for O(1) membership # check while retaining insertion order libraries = OrderedDict() - for line in xsdata: + for line in xsdata_file: words = line.split() if len(words) >= 9: lib = (xsdata.parent / words[8]).resolve() From 6cbd1ed288411f5ded5ce918cfbb24f4d0932a09 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 9 Mar 2022 17:08:05 -0600 Subject: [PATCH 0054/2654] Add cell instance test with duplicated lattice --- tests/unit_tests/test_cell_instance.py | 73 ++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/unit_tests/test_cell_instance.py diff --git a/tests/unit_tests/test_cell_instance.py b/tests/unit_tests/test_cell_instance.py new file mode 100644 index 000000000..00424f9c5 --- /dev/null +++ b/tests/unit_tests/test_cell_instance.py @@ -0,0 +1,73 @@ +import numpy as np +import pytest + +import openmc +import openmc.lib + +from tests import cdtemp + + +@pytest.fixture(scope='module', autouse=True) +def double_lattice_model(): + model = openmc.Model() + + # Create a single material + m = openmc.Material() + m.add_nuclide('U235', 1.0) + m.set_density('g/cm3', 10.0) + model.materials.append(m) + + # Create a universe with a single infinite cell + c = openmc.Cell(fill=m) + u = openmc.Universe(cells=[c]) + + # Create a 2x2 lattice filled with above universe + lattice = openmc.RectLattice() + lattice.lower_left = (0.0, 0.0) + lattice.pitch = (1.0, 1.0) + lattice.universes = np.full((2, 2), u) + + # Create two cells each filled with the same lattice, one from x=0..2 and + # y=0..2 and the other from x=2..4 and y=0..2 + x0 = openmc.XPlane(0.0, boundary_type='vacuum') + x2 = openmc.XPlane(2.0) + x4 = openmc.XPlane(4.0, boundary_type='vacuum') + y0 = openmc.YPlane(0.0, boundary_type='vacuum') + y2 = openmc.YPlane(2.0, boundary_type='vacuum') + cell_with_lattice1 = openmc.Cell(fill=lattice, region=+x0 & -x2 & +y0 & -y2) + cell_with_lattice2 = openmc.Cell(fill=lattice, region=+x2 & -x4 & +y0 & -y2) + cell_with_lattice2.translation = (2., 0., 0.) + model.geometry = openmc.Geometry([cell_with_lattice1, cell_with_lattice2]) + + # Add necessary settings and export + model.settings.batches = 10 + model.settings.inactive = 0 + model.settings.particles = 100 + + with cdtemp(): + model.export_to_xml() + openmc.lib.init() + yield + openmc.lib.finalize() + + +# This shows the expected cell instance numbers for each lattice position: +# ┌─┬─┬─┬─┐ +# │2│3│6│7│ +# ├─┼─┼─┼─┤ +# │0│1│4│5│ +# └─┴─┴─┴─┘ +expected_results = [ + ((0.5, 0.5, 0.0), 0), + ((1.5, 0.5, 0.0), 1), + ((0.5, 1.5, 0.0), 2), + ((1.5, 1.5, 0.0), 3), + ((2.5, 0.5, 0.0), 4), + ((3.5, 0.5, 0.0), 5), + ((2.5, 1.5, 0.0), 6), + ((3.5, 1.5, 0.0), 7), +] +@pytest.mark.parametrize("r,expected_cell_instance", expected_results) +def test_cell_instance_multilattice(r, expected_cell_instance): + _, cell_instance = openmc.lib.find_cell(r) + assert cell_instance == expected_cell_instance From 34a35d832a1cfe1fec304eace56676265d5b6f3d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 7 Mar 2022 22:02:24 -0600 Subject: [PATCH 0055/2654] Fix cell instance counting bug with same lattice in multiple cells --- src/geometry.cpp | 1 + src/geometry_aux.cpp | 3 ++- src/lattice.cpp | 12 ++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/geometry.cpp b/src/geometry.cpp index acce3fc78..216650ff1 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -86,6 +86,7 @@ int cell_instance_at_level(const Particle& p, int level) if (c_i.type_ == Fill::UNIVERSE) { instance += c_i.offset_[c.distribcell_index_]; } else if (c_i.type_ == Fill::LATTICE) { + instance += c_i.offset_[c.distribcell_index_]; auto& lat {*model::lattices[p.coord(i + 1).lattice]}; const auto& i_xyz {p.coord(i + 1).lattice_i}; if (lat.are_valid_indices(i_xyz)) { diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 842822d05..ddce2469b 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -412,8 +412,9 @@ void prepare_distribcell(const std::vector* user_distribcells) search_univ, target_univ_id, univ_count_memo); } else if (c.type_ == Fill::LATTICE) { + c.offset_[map] = offset; Lattice& lat = *model::lattices[c.fill_]; - offset = + offset += lat.fill_offset_table(offset, target_univ_id, map, univ_count_memo); } } diff --git a/src/lattice.cpp b/src/lattice.cpp index 3875b2fa7..fa2e2828e 100644 --- a/src/lattice.cpp +++ b/src/lattice.cpp @@ -101,6 +101,18 @@ void Lattice::adjust_indices() int32_t Lattice::fill_offset_table(int32_t offset, int32_t target_univ_id, int map, std::unordered_map& univ_count_memo) { + // If the offsets have already been determined for this "map", don't bother + // recalculating all of them and just return the total offset. Note that the + // offsets_ array doesn't actually include the offset accounting for the last + // universe, so we get the before-last offset for the given map and then + // explicitly add the count for the last universe. + if (offsets_[map * universes_.size()] != C_NONE) { + int last_offset = offsets_[(map + 1) * universes_.size() - 1]; + int last_univ = universes_.back(); + return last_offset + + count_universe_instances(last_univ, target_univ_id, univ_count_memo); + } + for (LatticeIter it = begin(); it != end(); ++it) { offsets_[map * universes_.size() + it.indx_] = offset; offset += count_universe_instances(*it, target_univ_id, univ_count_memo); From f85dc9dc9b52f38d151e82cd5bdcb9475a66c250 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 10 Mar 2022 13:35:41 -0500 Subject: [PATCH 0056/2654] adding helper method for EnergyFilter creation --- openmc/filter.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/openmc/filter.py b/openmc/filter.py index df06d713f..be3d97679 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1324,6 +1324,20 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) + @classmethod + def from_group_structure(cls, group_structure): + """Construct an EnergyFilter instance from a standard group structure. + + Parameters + ---------- + group_structure : str + Name of the group structure. Must be a valid key of + openmc.mgxs.GROUP_STRUCTURES dictionary. + + """ + + return cls(openmc.mgxs.GROUP_STRUCTURES[group_structure.upper()]) + class EnergyoutFilter(EnergyFilter): """Bins tally events based on outgoing particle energy. From da53fd6e6e19edd86d090559d8714d0b3227d1c6 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 10 Mar 2022 15:37:18 -0500 Subject: [PATCH 0057/2654] added unit test --- tests/unit_tests/test_filters.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 49526ac67..6b344b827 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -240,3 +240,9 @@ def test_first_moment(run_in_tmpdir, box_model): assert first_score(sph_scat_tally) == scatter assert first_score(sph_flux_tally) == approx(flux) assert first_score(zernike_tally) == approx(scatter) + + +def test_energy(): + f = openmc.EnergyFilter.from_group_structure('CCFE-709') + assert f.bins.shape == (709, 2) + assert len(f.values) == 710 From 698a15d7f94b04563f9207e1e3f06957ca19db79 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 10 Mar 2022 21:00:53 +0000 Subject: [PATCH 0058/2654] writing files to output folder --- src/output.cpp | 5 ++++- src/summary.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/output.cpp b/src/output.cpp index 401ad8338..132f153bf 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -576,9 +576,12 @@ void write_tallies() if (model::tallies.empty()) return; + // Set filename for tallies_out + filename = fmt::format("{}tallies.out", settings::path_output, w); + // Open the tallies.out file. std::ofstream tallies_out; - tallies_out.open("tallies.out", std::ios::out | std::ios::trunc); + tallies_out.open(filename, std::ios::out | std::ios::trunc); // Loop over each tally. for (auto i_tally = 0; i_tally < model::tallies.size(); ++i_tally) { diff --git a/src/summary.cpp b/src/summary.cpp index fc81ac7bb..213ce9437 100644 --- a/src/summary.cpp +++ b/src/summary.cpp @@ -22,8 +22,11 @@ void write_summary() // Display output message write_message("Writing summary.h5 file...", 5); + // Set filename for summary file + filename = fmt::format("{}summary.h5", settings::path_output, w); + // Create a new file using default properties. - hid_t file = file_open("summary.h5", 'w'); + hid_t file = file_open(filename, 'w'); write_header(file); write_nuclides(file); From e14de1600abd4ffb67f0a5390d826f1baefaa930 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 10 Mar 2022 21:08:46 +0000 Subject: [PATCH 0059/2654] removing ,w from filename --- src/output.cpp | 2 +- src/summary.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/output.cpp b/src/output.cpp index 132f153bf..e277f4f62 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -577,7 +577,7 @@ void write_tallies() return; // Set filename for tallies_out - filename = fmt::format("{}tallies.out", settings::path_output, w); + filename = fmt::format("{}tallies.out", settings::path_output); // Open the tallies.out file. std::ofstream tallies_out; diff --git a/src/summary.cpp b/src/summary.cpp index 213ce9437..3075f621f 100644 --- a/src/summary.cpp +++ b/src/summary.cpp @@ -23,7 +23,7 @@ void write_summary() write_message("Writing summary.h5 file...", 5); // Set filename for summary file - filename = fmt::format("{}summary.h5", settings::path_output, w); + filename = fmt::format("{}summary.h5", settings::path_output); // Create a new file using default properties. hid_t file = file_open(filename, 'w'); From 1b6a341878f0e46c70ca39f7c7f50a758c301fd8 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 10 Mar 2022 21:30:41 +0000 Subject: [PATCH 0060/2654] declared filename before use --- src/output.cpp | 1 + src/summary.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/output.cpp b/src/output.cpp index e277f4f62..5c6f2b677 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -577,6 +577,7 @@ void write_tallies() return; // Set filename for tallies_out + std::string filename; filename = fmt::format("{}tallies.out", settings::path_output); // Open the tallies.out file. diff --git a/src/summary.cpp b/src/summary.cpp index 3075f621f..1915fde33 100644 --- a/src/summary.cpp +++ b/src/summary.cpp @@ -23,6 +23,7 @@ void write_summary() write_message("Writing summary.h5 file...", 5); // Set filename for summary file + std::string filename; filename = fmt::format("{}summary.h5", settings::path_output); // Create a new file using default properties. From 99cb83c035e12b54ff6c9ab58f34214d1b5ee951 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 10 Mar 2022 22:14:37 +0000 Subject: [PATCH 0061/2654] Suggestions from PR review by @Paulromano Co-authored-by: Paul Romano --- openmc/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index e09d13ed9..1f295d99e 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -474,7 +474,7 @@ class Settings: return self._max_splits @run_mode.setter - def run_mode(self, run_mode: RunMode): + def run_mode(self, run_mode: str): cv.check_value('run mode', run_mode, {x.value for x in RunMode}) for mode in RunMode: if mode.value == run_mode: @@ -774,7 +774,7 @@ class Settings: self._trace = trace @track.setter - def track(self, track: Iterable): + def track(self, track: typint.Iterable[int]): cv.check_type('track', track, Iterable, Integral) if len(track) % 3 != 0: msg = f'Unable to set the track to "{track}" since its length is ' \ From 4cfc01f5b971561a70d4e9932a5f694f37b32ec9 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 10 Mar 2022 22:20:25 +0000 Subject: [PATCH 0062/2654] sorted imports improved source and path type hints --- openmc/settings.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 1f295d99e..a9f0cdb8e 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1,14 +1,16 @@ -from collections.abc import Iterable, MutableSequence, Mapping +import os +import typing as typing # imported separately as py3.8 requires typing.Iterable +from collections.abc import Iterable, Mapping, MutableSequence from enum import Enum +from math import ceil +from numbers import Integral, Real from pathlib import Path -from numbers import Real, Integral -import typing as typing # imported separately as py3.8 requires typing.Iterable from typing import Optional, Union from xml.etree import ElementTree as ET -from math import ceil import openmc.checkvalue as cv -from . import VolumeCalculation, Source, RegularMesh, WeightWindows + +from . import RegularMesh, Source, VolumeCalculation, WeightWindows from ._xml import clean_indentation, get_text, reorder_attributes @@ -561,7 +563,7 @@ class Settings: self._max_order = max_order @source.setter - def source(self, source: typing.Iterable[Source]): + def source(self, source: Union[Source, typing.Iterable[Source]]): if not isinstance(source, MutableSequence): source = [source] self._source = cv.CheckedList(Source, 'source distributions', source) @@ -1494,7 +1496,7 @@ class Settings: if text is not None: self.max_splits = int(text) - def export_to_xml(self, path: str = 'settings.xml'): + def export_to_xml(self, path: Union[str, os.PathLike] = 'settings.xml'): """Export simulation settings to an XML file. Parameters @@ -1565,7 +1567,7 @@ class Settings: tree.write(str(p), xml_declaration=True, encoding='utf-8') @classmethod - def from_xml(cls, path: str = 'settings.xml'): + def from_xml(cls, path: Union[str, os.PathLike] = 'settings.xml'): """Generate settings from XML file .. versionadded:: 0.13.0 From 7657e5ffcf707ec1af624fa03bb55897084760f6 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 10 Mar 2022 22:45:13 +0000 Subject: [PATCH 0063/2654] fixed typo --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index a9f0cdb8e..75c04a637 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -776,7 +776,7 @@ class Settings: self._trace = trace @track.setter - def track(self, track: typint.Iterable[int]): + def track(self, track: typing.Iterable[int]): cv.check_type('track', track, Iterable, Integral) if len(track) % 3 != 0: msg = f'Unable to set the track to "{track}" since its length is ' \ From c8de525c001cd9787b9f875442071ab258408b01 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 11 Mar 2022 15:36:44 +0000 Subject: [PATCH 0064/2654] Suggestions from review by @paulromano Co-authored-by: Paul Romano --- src/output.cpp | 3 +-- src/summary.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/output.cpp b/src/output.cpp index 5c6f2b677..58f081f67 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -577,8 +577,7 @@ void write_tallies() return; // Set filename for tallies_out - std::string filename; - filename = fmt::format("{}tallies.out", settings::path_output); + std::string filename = fmt::format("{}tallies.out", settings::path_output); // Open the tallies.out file. std::ofstream tallies_out; diff --git a/src/summary.cpp b/src/summary.cpp index 1915fde33..b3ea0254e 100644 --- a/src/summary.cpp +++ b/src/summary.cpp @@ -23,8 +23,7 @@ void write_summary() write_message("Writing summary.h5 file...", 5); // Set filename for summary file - std::string filename; - filename = fmt::format("{}summary.h5", settings::path_output); + std::string filename = fmt::format("{}summary.h5", settings::path_output); // Create a new file using default properties. hid_t file = file_open(filename, 'w'); From 7b627cc55f923a26b1e91ad86ba935880cc96365 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:51:22 -0600 Subject: [PATCH 0065/2654] Changing attrigute energy_bins to energy_bounds for wws --- include/openmc/weight_windows.h | 2 +- openmc/weight_windows.py | 36 +++++++++---------- src/weight_windows.cpp | 14 ++++---- .../weightwindows/inputs_true.dat | 4 +-- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/openmc/weight_windows.h b/include/openmc/weight_windows.h index c2ef29ae8..45c1de919 100644 --- a/include/openmc/weight_windows.h +++ b/include/openmc/weight_windows.h @@ -100,7 +100,7 @@ private: // Data members int32_t id_; //!< Unique ID ParticleType particle_type_; //!< Particle type to apply weight windows to - vector energy_bins_; //!< Energy bins [eV] + vector energy_bounds_; //!< Energy boundaries [eV] vector lower_ww_; //!< Lower weight window bounds vector upper_ww_; //!< Upper weight window bounds double survival_ratio_ {3.0}; //!< Survival weight ratio diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index e07e8a84f..5e21d5f4b 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -40,7 +40,7 @@ class WeightWindows(IDManagerMixin): window upper_bound_ratio : float Ratio of the lower to upper weight window bounds - energy_bins : Iterable of Real + energy_bounds : Iterable of Real A list of values for which each successive pair constitutes a range of energies in [eV] for a single bin particle_type : {'neutron', 'photon'} @@ -69,7 +69,7 @@ class WeightWindows(IDManagerMixin): Mesh for the weight windows particle_type : str Particle type the weight windows apply to - energy_bins : Iterable of Real + energy_bounds : Iterable of Real A list of values for which each successive pair constitutes a range of energies in [eV] for a single bin lower_ww_bounds : Iterable of Real @@ -98,16 +98,16 @@ class WeightWindows(IDManagerMixin): used_ids = set() def __init__(self, mesh, lower_ww_bounds, upper_ww_bounds=None, - upper_bound_ratio=None, energy_bins=None, particle_type='neutron', + upper_bound_ratio=None, energy_bounds=None, particle_type='neutron', survival_ratio=3, max_lower_bound_ratio=None, max_split=10, weight_cutoff=1.e-38, id=None): self.mesh = mesh self.id = id self.particle_type = particle_type - self.energy_bins = energy_bins + self.energy_bounds = energy_bounds self.lower_ww_bounds = lower_ww_bounds - cv.check_length('Lower window bounds', self.lower_ww_bounds, len(self.energy_bins)) + cv.check_length('Lower window bounds', self.lower_ww_bounds, len(self.energy_bounds)) if upper_ww_bounds is not None and upper_bound_ratio: raise ValueError("Exactly one of upper_ww_bounds and " @@ -143,7 +143,7 @@ class WeightWindows(IDManagerMixin): string += '{: <16}=\t{}\n'.format('\tID', self._id) string += '{: <16}=\t{}\n'.format('\tMesh:', self.mesh) string += '{: <16}=\t{}\n'.format('\tParticle Type', self._particle_type) - string += '{: <16}=\t{}\n'.format('\tEnergy Bins', self._energy_bins) + string += '{: <16}=\t{}\n'.format('\tEnergy Bounds', self._energy_bounds) string += '{: <16}=\t{}\n'.format('\tLower WW Bounds', self._lower_ww_bounds) string += '{: <16}=\t{}\n'.format('\tUpper WW Bounds', self._upper_ww_bounds) string += '{: <16}=\t{}\n'.format('\tSurvival Ratio', self._survival_ratio) @@ -170,13 +170,13 @@ class WeightWindows(IDManagerMixin): self._particle_type = pt @property - def energy_bins(self): - return self._energy_bins + def energy_bounds(self): + return self._energy_bounds - @energy_bins.setter - def energy_bins(self, bins): - cv.check_type('Energy bins', bins, Iterable, Real) - self._energy_bins = np.array(bins) + @energy_bounds.setter + def energy_bounds(self, bnds): + cv.check_type('Energy bounds', bnds, Iterable, Real) + self._energy_bounds = np.array(bnds) @property def lower_ww_bounds(self): @@ -253,8 +253,8 @@ class WeightWindows(IDManagerMixin): subelement = ET.SubElement(element, 'particle_type') subelement.text = self.particle_type - subelement = ET.SubElement(element, 'energy_bins') - subelement.text = ' '.join(str(e) for e in self.energy_bins) + subelement = ET.SubElement(element, 'energy_bounds') + subelement.text = ' '.join(str(e) for e in self.energy_bounds) subelement = ET.SubElement(element, 'lower_ww_bounds') subelement.text = ' '.join(str(b) for b in self.lower_ww_bounds) @@ -303,7 +303,7 @@ class WeightWindows(IDManagerMixin): # Read all other parameters lower_ww_bounds = [float(l) for l in get_text(elem, 'lower_ww_bounds').split()] upper_ww_bounds = [float(u) for u in get_text(elem, 'upper_ww_bounds').split()] - ebins = [float(b) for b in get_text(elem, 'energy_bins').split()] + ebnds = [float(b) for b in get_text(elem, 'energy_bounds').split()] particle_type = get_text(elem, 'particle_type') survival_ratio = float(get_text(elem, 'survival_ratio')) @@ -319,7 +319,7 @@ class WeightWindows(IDManagerMixin): mesh=mesh, lower_ww_bounds=lower_ww_bounds, upper_ww_bounds=upper_ww_bounds, - energy_bins=ebins, + energy_bounds=ebnds, particle_type=particle_type, survival_ratio=survival_ratio, max_lower_bound_ratio=max_lower_bound_ratio, @@ -348,7 +348,7 @@ class WeightWindows(IDManagerMixin): id = int(group.name.split('/')[-1].lstrip('weight_windows')) mesh_id = group['mesh'][()] ptype = group['particle_type'][()].decode() - ebins = group['energy_bins'][()] + ebnds = group['energy_bounds'][()] lower_ww_bounds = group['lower_ww_bounds'][()] upper_ww_bounds = group['upper_ww_bounds'][()] survival_ratio = group['survival_ratio'][()] @@ -364,7 +364,7 @@ class WeightWindows(IDManagerMixin): mesh=meshes[mesh_id], lower_ww_bounds=lower_ww_bounds, upper_ww_bounds=upper_ww_bounds, - energy_bins=ebins, + energy_bounds=ebnds, particle_type=ptype, survival_ratio=survival_ratio, max_lower_bound_ratio=max_lower_bound_ratio, diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index e753fc6ac..b8b927194 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -112,8 +112,8 @@ void free_memory_weight_windows() WeightWindows::WeightWindows(pugi::xml_node node) { // Make sure required elements are present - const vector required_elems { - "id", "particle_type", "energy_bins", "lower_ww_bounds", "upper_ww_bounds"}; + const vector required_elems {"id", "particle_type", + "energy_bounds", "lower_ww_bounds", "upper_ww_bounds"}; for (const auto& elem : required_elems) { if (!check_for_node(node, elem.c_str())) { fatal_error(fmt::format("Must specify <{}> for weight windows.", elem)); @@ -133,7 +133,7 @@ WeightWindows::WeightWindows(pugi::xml_node node) mesh_idx_ = model::mesh_map.at(mesh_id); // energy bounds - energy_bins_ = get_node_array(node, "energy_bins"); + energy_bounds_ = get_node_array(node, "energy_bounds"); // read the lower/upper weight bounds lower_ww_ = get_node_array(node, "lower_ww_bounds"); @@ -178,7 +178,7 @@ WeightWindows::WeightWindows(pugi::xml_node node) // num spatial*energy bins must match num weight bins int num_spatial_bins = this->mesh().n_bins(); - int num_energy_bins = energy_bins_.size() - 1; + int num_energy_bins = energy_bounds_.size() - 1; int num_weight_bins = lower_ww_.size(); if (num_weight_bins != num_spatial_bins * num_energy_bins) { auto err_msg = @@ -240,12 +240,12 @@ WeightWindow WeightWindows::get_weight_window(const Particle& p) const double E = p.E(); // check to make sure energy is in range, expects sorted energy values - if (E < energy_bins_.front() || E > energy_bins_.back()) + if (E < energy_bounds_.front() || E > energy_bounds_.back()) return {}; // get the mesh bin in energy group int energy_bin = - lower_bound_index(energy_bins_.begin(), energy_bins_.end(), E); + lower_bound_index(energy_bounds_.begin(), energy_bounds_.end(), E); // indices now points to the correct weight for the given energy ww_index += energy_bin * mesh.n_bins(); @@ -267,7 +267,7 @@ void WeightWindows::to_hdf5(hid_t group) const write_dataset( ww_group, "particle_type", openmc::particle_type_to_str(particle_type_)); - write_dataset(ww_group, "energy_bins", energy_bins_); + write_dataset(ww_group, "energy_bounds", energy_bounds_); write_dataset(ww_group, "lower_ww_bounds", lower_ww_); write_dataset(ww_group, "upper_ww_bounds", upper_ww_); write_dataset(ww_group, "survival_ratio", survival_ratio_); diff --git a/tests/regression_tests/weightwindows/inputs_true.dat b/tests/regression_tests/weightwindows/inputs_true.dat index 13641bf7a..e6a0ad55f 100644 --- a/tests/regression_tests/weightwindows/inputs_true.dat +++ b/tests/regression_tests/weightwindows/inputs_true.dat @@ -47,7 +47,7 @@ 2 neutron - 0.0 0.5 20000000.0 + 0.0 0.5 20000000.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 7.695031155172816e-14 -1.0 7.476545089278482e-06 -1.0 2.1612150425221703e-06 -1.0 -1.0 -1.0 2.1360401784344975e-18 -1.0 1.3455341306162382e-05 -1.0 3.353295403842037e-05 -1.0 3.0160758454323657e-07 -1.0 1.0262431550731535e-13 -1.0 1.6859219614058024e-19 -1.0 3.853097455417877e-06 -1.0 4.354946981329799e-05 -1.0 7.002861620919232e-08 -1.0 -1.0 -1.0 -1.0 -1.0 1.6205064883026195e-11 -1.0 1.7041669224797384e-09 -1.0 1.8747824667478637e-14 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 5.619835883512353e-14 -1.0 1.951356547084204e-15 -1.0 8.48176145671274e-10 -1.0 -1.0 -1.0 1.4508262073256659e-13 -1.0 4.109066205029878e-05 -1.0 0.00020573181450240786 -1.0 2.124999182004655e-05 -1.0 5.5379154134462336e-08 -1.0 1.5550455959178486e-06 -1.0 0.0007213722022489493 -1.0 0.007673145137236567 -1.0 0.0008175033526488423 -1.0 1.008394964750947e-06 -1.0 6.848642863465585e-07 -1.0 0.0010737081832502356 -1.0 0.007197662162700777 -1.0 0.0007151459162818186 -1.0 2.253382683081525e-06 -1.0 1.3181562352445092e-10 -1.0 1.93847081892941e-05 -1.0 0.00046029617115127556 -1.0 2.5629068330446215e-05 -1.0 5.504813693036933e-12 -1.0 -1.0 -1.0 3.3164825349503764e-16 -1.0 3.937160538176268e-07 -1.0 -1.0 -1.0 -1.0 -1.0 1.5172912057312398e-14 -1.0 6.315154082213375e-07 -1.0 3.855884234344845e-06 -1.0 1.7770136411255912e-05 -1.0 1.6421491993751715e-11 -1.0 5.97653814110781e-06 -1.0 0.001959411999677113 -1.0 0.013330619853379314 -1.0 0.0017950613169359904 -1.0 2.4306375693722205e-06 -1.0 6.922231352729155e-05 -1.0 0.08657573566388353 -1.0 -1.0 -1.0 0.0835648710074336 -1.0 0.00016419031150495913 -1.0 9.03108551826469e-05 -1.0 0.0848872967381878 -1.0 -1.0 -1.0 0.08288806458368345 -1.0 5.6949597066784976e-05 -1.0 8.037131813528501e-07 -1.0 0.0016637126543321873 -1.0 0.01664109232689093 -1.0 0.0018327593437608 -1.0 6.542700644645627e-07 -1.0 -1.0 -1.0 6.655926357459275e-08 -1.0 5.783974359937857e-06 -1.0 2.679340942769232e-06 -1.0 -1.0 -1.0 -1.0 -1.0 2.1040609012865134e-05 -1.0 2.9282097947816224e-05 -1.0 1.284759166582202e-05 -1.0 1.0092905083158804e-11 -1.0 1.3228013765525015e-05 -1.0 0.007136750029575816 -1.0 0.06539005235506369 -1.0 0.0064803314120165335 -1.0 2.6011787393916806e-06 -1.0 8.887234042637684e-05 -1.0 0.5 -1.0 -1.0 -1.0 0.4877856021170283 -1.0 0.00017699858357744463 -1.0 0.0001670700632870335 -1.0 0.4899999304038166 -1.0 -1.0 -1.0 0.48573842213878143 -1.0 0.00021534568699157805 -1.0 7.84289689494925e-06 -1.0 0.0063790654507599135 -1.0 0.06550426960512012 -1.0 0.006639379668946672 -1.0 7.754700849337902e-06 -1.0 2.7207433165796702e-11 -1.0 5.985108617124989e-06 -1.0 3.634644995026692e-05 -1.0 3.932389299316285e-06 -1.0 -1.0 -1.0 -1.0 -1.0 1.271128669411295e-07 -1.0 8.846493399850663e-06 -1.0 2.499931357628383e-07 -1.0 8.533030345699353e-17 -1.0 1.6699254277734109e-06 -1.0 0.0017541380096893788 -1.0 0.015148978428271613 -1.0 0.0016279794552427574 -1.0 2.380955631371226e-06 -1.0 2.1648918040467363e-05 -1.0 0.0833931797381589 -1.0 -1.0 -1.0 0.08285899874014539 -1.0 2.762955748645507e-05 -1.0 5.1161740516205715e-05 -1.0 0.08095280568305474 -1.0 -1.0 -1.0 0.08636569925236791 -1.0 3.452537179033895e-05 -1.0 3.5981031766416143e-06 -1.0 0.001570829313580841 -1.0 0.01621821782442112 -1.0 0.0015447823995470042 -1.0 7.989579285134734e-06 -1.0 -1.0 -1.0 2.594951085377588e-06 -1.0 4.323138781337963e-05 -1.0 6.948292975998466e-07 -1.0 -1.0 -1.0 -1.0 -1.0 2.4469456008493614e-09 -1.0 9.041149893307806e-07 -1.0 2.2060992580622125e-11 -1.0 -1.0 -1.0 1.681305446488884e-11 -1.0 7.091263906557291e-05 -1.0 0.00027464244062887683 -1.0 1.28584557092134e-05 -1.0 2.0295213621716706e-09 -1.0 1.2911827198500372e-08 -1.0 0.0009127050763987511 -1.0 0.007385384405891666 -1.0 0.0010019432401508087 -1.0 1.080711295768551e-05 -1.0 8.020767115181574e-07 -1.0 0.0009252532821720597 -1.0 0.007188410694198128 -1.0 0.0007245451610090619 -1.0 2.5157355790201773e-07 -1.0 1.4825219199133353e-12 -1.0 4.756872959630257e-05 -1.0 0.0002668579837809081 -1.0 2.8226276944532696e-05 -1.0 5.182269672663266e-10 -1.0 -1.0 -1.0 2.936268747135548e-14 -1.0 2.5447281241730366e-07 -1.0 3.89841667138598e-08 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 2.639268952045579e-10 -1.0 3.7051518220083886e-06 -1.0 1.1333627604823673e-09 -1.0 -1.0 -1.0 -1.0 -1.0 1.2296747260635405e-06 -1.0 7.962899789920809e-06 -1.0 8.211982683649991e-09 -1.0 -1.0 -1.0 -1.0 -1.0 2.5639656866250453e-06 -1.0 2.2487617828938326e-05 -1.0 3.2799045883372075e-06 -1.0 4.076762579823379e-17 -1.0 1.5476769237571295e-14 -1.0 1.0305672698745657e-11 -1.0 1.957092814065688e-05 -1.0 3.8523247550378815e-12 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 2.7697233171399416e-13 -1.0 -1.0 -1.0 -1.0 -1.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 7.695031155172816e-13 -10.0 7.476545089278483e-05 -10.0 2.1612150425221703e-05 -10.0 -10.0 -10.0 2.1360401784344976e-17 -10.0 0.00013455341306162382 -10.0 0.00033532954038420373 -10.0 3.0160758454323656e-06 -10.0 1.0262431550731535e-12 -10.0 1.6859219614058023e-18 -10.0 3.853097455417877e-05 -10.0 0.00043549469813297995 -10.0 7.002861620919232e-07 -10.0 -10.0 -10.0 -10.0 -10.0 1.6205064883026195e-10 -10.0 1.7041669224797384e-08 -10.0 1.8747824667478637e-13 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 5.619835883512353e-13 -10.0 1.951356547084204e-14 -10.0 8.48176145671274e-09 -10.0 -10.0 -10.0 1.4508262073256658e-12 -10.0 0.0004109066205029878 -10.0 0.0020573181450240785 -10.0 0.00021249991820046548 -10.0 5.537915413446234e-07 -10.0 1.5550455959178486e-05 -10.0 0.0072137220224894934 -10.0 0.07673145137236567 -10.0 0.008175033526488424 -10.0 1.0083949647509469e-05 -10.0 6.848642863465585e-06 -10.0 0.010737081832502356 -10.0 0.07197662162700777 -10.0 0.007151459162818186 -10.0 2.253382683081525e-05 -10.0 1.3181562352445092e-09 -10.0 0.000193847081892941 -10.0 0.004602961711512756 -10.0 0.00025629068330446217 -10.0 5.504813693036933e-11 -10.0 -10.0 -10.0 3.3164825349503764e-15 -10.0 3.937160538176268e-06 -10.0 -10.0 -10.0 -10.0 -10.0 1.51729120573124e-13 -10.0 6.3151540822133754e-06 -10.0 3.855884234344845e-05 -10.0 0.0001777013641125591 -10.0 1.6421491993751715e-10 -10.0 5.97653814110781e-05 -10.0 0.01959411999677113 -10.0 0.13330619853379314 -10.0 0.017950613169359905 -10.0 2.4306375693722206e-05 -10.0 0.0006922231352729155 -10.0 0.8657573566388354 -10.0 -10.0 -10.0 0.8356487100743359 -10.0 0.0016419031150495913 -10.0 0.000903108551826469 -10.0 0.848872967381878 -10.0 -10.0 -10.0 0.8288806458368345 -10.0 0.0005694959706678497 -10.0 8.037131813528501e-06 -10.0 0.016637126543321872 -10.0 0.1664109232689093 -10.0 0.018327593437608 -10.0 6.5427006446456266e-06 -10.0 -10.0 -10.0 6.655926357459275e-07 -10.0 5.7839743599378564e-05 -10.0 2.679340942769232e-05 -10.0 -10.0 -10.0 -10.0 -10.0 0.00021040609012865135 -10.0 0.00029282097947816227 -10.0 0.0001284759166582202 -10.0 1.0092905083158804e-10 -10.0 0.00013228013765525016 -10.0 0.07136750029575815 -10.0 0.6539005235506369 -10.0 0.06480331412016534 -10.0 2.6011787393916804e-05 -10.0 0.0008887234042637684 -10.0 5.0 -10.0 -10.0 -10.0 4.877856021170283 -10.0 0.0017699858357744464 -10.0 0.001670700632870335 -10.0 4.899999304038166 -10.0 -10.0 -10.0 4.8573842213878144 -10.0 0.0021534568699157807 -10.0 7.84289689494925e-05 -10.0 0.06379065450759913 -10.0 0.6550426960512012 -10.0 0.06639379668946672 -10.0 7.754700849337902e-05 -10.0 2.7207433165796704e-10 -10.0 5.985108617124989e-05 -10.0 0.0003634644995026692 -10.0 3.9323892993162844e-05 -10.0 -10.0 -10.0 -10.0 -10.0 1.271128669411295e-06 -10.0 8.846493399850663e-05 -10.0 2.499931357628383e-06 -10.0 8.533030345699353e-16 -10.0 1.669925427773411e-05 -10.0 0.017541380096893787 -10.0 0.15148978428271614 -10.0 0.016279794552427576 -10.0 2.380955631371226e-05 -10.0 0.00021648918040467362 -10.0 0.8339317973815891 -10.0 -10.0 -10.0 0.828589987401454 -10.0 0.0002762955748645507 -10.0 0.0005116174051620571 -10.0 0.8095280568305474 -10.0 -10.0 -10.0 0.8636569925236791 -10.0 0.0003452537179033895 -10.0 3.5981031766416144e-05 -10.0 0.015708293135808408 -10.0 0.16218217824421122 -10.0 0.015447823995470043 -10.0 7.989579285134734e-05 -10.0 -10.0 -10.0 2.594951085377588e-05 -10.0 0.0004323138781337963 -10.0 6.948292975998466e-06 -10.0 -10.0 -10.0 -10.0 -10.0 2.4469456008493615e-08 -10.0 9.041149893307805e-06 -10.0 2.2060992580622125e-10 -10.0 -10.0 -10.0 1.681305446488884e-10 -10.0 0.0007091263906557291 -10.0 0.002746424406288768 -10.0 0.000128584557092134 -10.0 2.0295213621716707e-08 -10.0 1.2911827198500372e-07 -10.0 0.009127050763987512 -10.0 0.07385384405891665 -10.0 0.010019432401508087 -10.0 0.0001080711295768551 -10.0 8.020767115181574e-06 -10.0 0.009252532821720597 -10.0 0.07188410694198127 -10.0 0.0072454516100906195 -10.0 2.515735579020177e-06 -10.0 1.4825219199133352e-11 -10.0 0.0004756872959630257 -10.0 0.0026685798378090807 -10.0 0.000282262769445327 -10.0 5.182269672663266e-09 -10.0 -10.0 -10.0 2.9362687471355483e-13 -10.0 2.5447281241730365e-06 -10.0 3.89841667138598e-07 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 2.639268952045579e-09 -10.0 3.7051518220083885e-05 -10.0 1.1333627604823672e-08 -10.0 -10.0 -10.0 -10.0 -10.0 1.2296747260635405e-05 -10.0 7.96289978992081e-05 -10.0 8.211982683649991e-08 -10.0 -10.0 -10.0 -10.0 -10.0 2.5639656866250452e-05 -10.0 0.00022487617828938325 -10.0 3.2799045883372076e-05 -10.0 4.076762579823379e-16 -10.0 1.5476769237571296e-13 -10.0 1.0305672698745658e-10 -10.0 0.0001957092814065688 -10.0 3.852324755037882e-11 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 2.7697233171399415e-12 -10.0 -10.0 -10.0 -10.0 -10.0 3 @@ -63,7 +63,7 @@ 2 neutron - 0.0 0.5 20000000.0 + 0.0 0.5 20000000.0 -1.0 -1.0 -1.0 5.447493368067179e-10 -1.0 4.0404626147344e-13 -1.0 9.382800796426366e-17 -1.0 -1.0 -1.0 5.752120832330886e-11 -1.0 3.520674728719278e-05 -1.0 8.76041935303527e-05 -1.0 3.136829920007009e-05 -1.0 -1.0 -1.0 4.233410073487772e-06 -1.0 0.00025519632243117644 -1.0 0.0004777967757842694 -1.0 0.00035983547999740665 -1.0 4.6258592060517866e-07 -1.0 4.587143797469485e-08 -1.0 0.00012918433677593975 -1.0 0.000469589568463265 -1.0 8.862760180332873e-05 -1.0 3.2790914744011534e-06 -1.0 1.1514579117272292e-10 -1.0 2.2950716170641463e-05 -1.0 6.92296299242814e-05 -1.0 2.1606550732170693e-05 -1.0 2.617878055106949e-16 -1.0 -1.0 -1.0 -1.0 -1.0 1.722191123879782e-08 -1.0 -1.0 -1.0 -1.0 -1.0 2.1234980618763222e-13 -1.0 1.4628847959717225e-05 -1.0 2.777791741571174e-05 -1.0 9.53380658669839e-06 -1.0 1.078687446476881e-14 -1.0 3.0571050855707084e-06 -1.0 0.0008231482263927564 -1.0 0.0038811025614225057 -1.0 0.0012297303081805393 -1.0 4.6842350882367666e-05 -1.0 0.00016757997590048827 -1.0 0.011724714376848187 -1.0 0.06827568359008944 -1.0 0.011440381012864086 -1.0 0.0003782322077390033 -1.0 5.098747893974248e-05 -1.0 0.01208261392046878 -1.0 0.06428782790571179 -1.0 0.011294708566804167 -1.0 8.168081568291806e-05 -1.0 2.34750482787598e-05 -1.0 0.0008787411098754915 -1.0 0.0051513292132259495 -1.0 0.0011028020390507682 -1.0 1.0882011018684852e-06 -1.0 1.0588257623722672e-07 -1.0 2.7044817176109556e-05 -1.0 2.6211239246796104e-05 -1.0 2.0707648529746894e-06 -1.0 -1.0 -1.0 1.3806577785135177e-06 -1.0 0.00010077009726691265 -1.0 0.00043130977711323417 -1.0 0.0001335621430311088 -1.0 3.792209399652396e-06 -1.0 0.00022057970761624768 -1.0 0.01884234453311008 -1.0 0.11510120013926417 -1.0 0.01825795827020865 -1.0 0.00020848309220162036 -1.0 0.0013332554437480327 -1.0 0.49317081643076643 -1.0 -1.0 -1.0 0.4899952354672477 -1.0 0.0014957033281168012 -1.0 0.001550036616828061 -1.0 0.4897735047310072 -1.0 -1.0 -1.0 0.5 -1.0 0.0011076796092102186 -1.0 0.0002792896409558745 -1.0 0.01721806295736377 -1.0 0.11891251244906934 -1.0 0.019040707071165303 -1.0 0.00017329528628152923 -1.0 4.670673837764874e-08 -1.0 0.00012637534695610975 -1.0 0.00027052054298385255 -1.0 0.0001497958445994315 -1.0 3.2478301680021854e-08 -1.0 7.239087311622819e-08 -1.0 0.00046693784586018913 -1.0 0.001537590300149361 -1.0 0.00023686818807101741 -1.0 8.616027294555462e-07 -1.0 0.0002362355168421952 -1.0 0.05708498338352203 -1.0 0.42372713683725016 -1.0 0.054902816619122045 -1.0 0.00030002326388383244 -1.0 0.0023295401596005313 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 0.0027847329307350423 -1.0 0.003432919201293737 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 0.002672923773363389 -1.0 0.0003182108781955478 -1.0 0.05639071613735579 -1.0 0.4346984808472855 -1.0 0.05500108683629957 -1.0 0.00024175998138228048 -1.0 2.774067049392004e-07 -1.0 0.0003257646134837451 -1.0 0.0012648333883989995 -1.0 0.0002981891705231209 -1.0 4.986698316296507e-06 -1.0 3.419181071650816e-06 -1.0 0.00010814452764860558 -1.0 0.0006934466049804711 -1.0 0.00025106741008066317 -1.0 5.515522196186723e-06 -1.0 0.00014242053195529864 -1.0 0.018541112907970003 -1.0 0.12364069326350118 -1.0 0.017602971074583987 -1.0 0.00021305826462238593 -1.0 0.0015016500045374082 -1.0 0.4903495510314233 -1.0 -1.0 -1.0 0.4952432605379829 -1.0 0.0017693279949094218 -1.0 0.0009304497896205121 -1.0 0.4873897581604287 -1.0 -1.0 -1.0 0.4981497862127628 -1.0 0.0011273340972061078 -1.0 0.00014126153603265097 -1.0 0.01729816946709781 -1.0 0.11819165666519223 -1.0 0.017802624844035688 -1.0 0.0001319677450153934 -1.0 2.210707325798542e-07 -1.0 0.00017287873387910357 -1.0 0.0005197081842709918 -1.0 9.256616392487858e-05 -1.0 1.0325207105027347e-08 -1.0 2.027381220364608e-16 -1.0 1.2257360246712472e-05 -1.0 3.8561696337086434e-05 -1.0 1.8064550990294753e-05 -1.0 7.691527781829036e-17 -1.0 1.298062961617927e-05 -1.0 0.001178616843705956 -1.0 0.004441328419270369 -1.0 0.0008919466185572302 -1.0 5.272021975060514e-06 -1.0 0.00016079768514218546 -1.0 0.011128424196387618 -1.0 0.06433819434431046 -1.0 0.010955637485319249 -1.0 8.370896020975689e-05 -1.0 0.00022234471595443313 -1.0 0.01102706140784316 -1.0 0.06684484191345574 -1.0 0.011113024641218336 -1.0 0.00012558879474108074 -1.0 1.0044390728858277e-05 -1.0 0.000808100901275472 -1.0 0.005384625561469684 -1.0 0.001146714816952061 -1.0 3.5740607788414942e-06 -1.0 2.2512327083641865e-10 -1.0 6.717625881826167e-05 -1.0 6.949587369646497e-05 -1.0 2.9093345975075226e-05 -1.0 -1.0 -1.0 -1.0 -1.0 8.582011716859219e-15 -1.0 8.304845400451923e-08 -1.0 4.5757238372058234e-11 -1.0 -1.0 -1.0 1.3116807133030035e-15 -1.0 2.6866894852481906e-05 -1.0 4.3166052799897375e-05 -1.0 6.401055165502384e-06 -1.0 5.726152701849347e-16 -1.0 8.541606727879512e-07 -1.0 0.0002029396545382813 -1.0 0.0004299195570308035 -1.0 8.544159282151438e-05 -1.0 1.0995322456277382e-06 -1.0 1.289814511028015e-06 -1.0 0.00011042047857307253 -1.0 0.0006870228272606287 -1.0 0.0001399807456616496 -1.0 4.279460329782799e-09 -1.0 1.2907171695294846e-13 -1.0 1.9257248009114363e-05 -1.0 9.332371598523186e-05 -1.0 1.3106335518133802e-05 -1.0 6.574706543646946e-16 -1.0 -1.0 -1.0 3.8270536025799805e-15 -1.0 2.101790478097517e-09 -1.0 9.904481358675478e-13 -1.0 -1.0 -10.0 -10.0 -10.0 5.447493368067179e-09 -10.0 4.0404626147344005e-12 -10.0 9.382800796426367e-16 -10.0 -10.0 -10.0 5.752120832330886e-10 -10.0 0.0003520674728719278 -10.0 0.0008760419353035269 -10.0 0.0003136829920007009 -10.0 -10.0 -10.0 4.233410073487772e-05 -10.0 0.0025519632243117644 -10.0 0.004777967757842694 -10.0 0.0035983547999740664 -10.0 4.625859206051786e-06 -10.0 4.587143797469485e-07 -10.0 0.0012918433677593976 -10.0 0.0046958956846326495 -10.0 0.0008862760180332873 -10.0 3.279091474401153e-05 -10.0 1.151457911727229e-09 -10.0 0.00022950716170641464 -10.0 0.0006922962992428139 -10.0 0.00021606550732170693 -10.0 2.6178780551069492e-15 -10.0 -10.0 -10.0 -10.0 -10.0 1.722191123879782e-07 -10.0 -10.0 -10.0 -10.0 -10.0 2.123498061876322e-12 -10.0 0.00014628847959717226 -10.0 0.0002777791741571174 -10.0 9.53380658669839e-05 -10.0 1.078687446476881e-13 -10.0 3.0571050855707086e-05 -10.0 0.008231482263927564 -10.0 0.03881102561422506 -10.0 0.012297303081805393 -10.0 0.00046842350882367664 -10.0 0.0016757997590048828 -10.0 0.11724714376848187 -10.0 0.6827568359008944 -10.0 0.11440381012864086 -10.0 0.003782322077390033 -10.0 0.0005098747893974248 -10.0 0.1208261392046878 -10.0 0.6428782790571179 -10.0 0.11294708566804167 -10.0 0.0008168081568291806 -10.0 0.000234750482787598 -10.0 0.008787411098754914 -10.0 0.0515132921322595 -10.0 0.011028020390507681 -10.0 1.0882011018684853e-05 -10.0 1.0588257623722672e-06 -10.0 0.00027044817176109554 -10.0 0.000262112392467961 -10.0 2.0707648529746893e-05 -10.0 -10.0 -10.0 1.3806577785135176e-05 -10.0 0.0010077009726691265 -10.0 0.004313097771132342 -10.0 0.001335621430311088 -10.0 3.792209399652396e-05 -10.0 0.0022057970761624767 -10.0 0.1884234453311008 -10.0 1.1510120013926417 -10.0 0.1825795827020865 -10.0 0.0020848309220162036 -10.0 0.013332554437480326 -10.0 4.931708164307665 -10.0 -10.0 -10.0 4.899952354672477 -10.0 0.014957033281168012 -10.0 0.01550036616828061 -10.0 4.897735047310072 -10.0 -10.0 -10.0 5.0 -10.0 0.011076796092102187 -10.0 0.002792896409558745 -10.0 0.17218062957363772 -10.0 1.1891251244906933 -10.0 0.19040707071165303 -10.0 0.0017329528628152924 -10.0 4.670673837764874e-07 -10.0 0.0012637534695610975 -10.0 0.0027052054298385255 -10.0 0.001497958445994315 -10.0 3.2478301680021856e-07 -10.0 7.239087311622819e-07 -10.0 0.004669378458601891 -10.0 0.01537590300149361 -10.0 0.002368681880710174 -10.0 8.61602729455546e-06 -10.0 0.002362355168421952 -10.0 0.5708498338352204 -10.0 4.237271368372502 -10.0 0.5490281661912204 -10.0 0.0030002326388383245 -10.0 0.023295401596005315 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 0.027847329307350423 -10.0 0.03432919201293737 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 0.026729237733633893 -10.0 0.0031821087819554777 -10.0 0.5639071613735579 -10.0 4.346984808472855 -10.0 0.5500108683629957 -10.0 0.0024175998138228046 -10.0 2.774067049392004e-06 -10.0 0.0032576461348374514 -10.0 0.012648333883989995 -10.0 0.002981891705231209 -10.0 4.986698316296507e-05 -10.0 3.419181071650816e-05 -10.0 0.0010814452764860557 -10.0 0.006934466049804711 -10.0 0.0025106741008066318 -10.0 5.515522196186723e-05 -10.0 0.0014242053195529865 -10.0 0.18541112907970003 -10.0 1.2364069326350118 -10.0 0.17602971074583987 -10.0 0.0021305826462238594 -10.0 0.015016500045374082 -10.0 4.903495510314233 -10.0 -10.0 -10.0 4.952432605379829 -10.0 0.01769327994909422 -10.0 0.00930449789620512 -10.0 4.873897581604287 -10.0 -10.0 -10.0 4.981497862127628 -10.0 0.011273340972061077 -10.0 0.0014126153603265096 -10.0 0.1729816946709781 -10.0 1.1819165666519222 -10.0 0.1780262484403569 -10.0 0.001319677450153934 -10.0 2.210707325798542e-06 -10.0 0.0017287873387910357 -10.0 0.0051970818427099184 -10.0 0.0009256616392487858 -10.0 1.0325207105027347e-07 -10.0 2.027381220364608e-15 -10.0 0.00012257360246712473 -10.0 0.00038561696337086434 -10.0 0.00018064550990294753 -10.0 7.6915277818290365e-16 -10.0 0.00012980629616179268 -10.0 0.01178616843705956 -10.0 0.04441328419270369 -10.0 0.008919466185572301 -10.0 5.272021975060514e-05 -10.0 0.0016079768514218546 -10.0 0.11128424196387618 -10.0 0.6433819434431045 -10.0 0.10955637485319249 -10.0 0.0008370896020975689 -10.0 0.0022234471595443312 -10.0 0.1102706140784316 -10.0 0.6684484191345574 -10.0 0.11113024641218336 -10.0 0.0012558879474108074 -10.0 0.00010044390728858278 -10.0 0.00808100901275472 -10.0 0.05384625561469684 -10.0 0.01146714816952061 -10.0 3.574060778841494e-05 -10.0 2.2512327083641864e-09 -10.0 0.0006717625881826168 -10.0 0.0006949587369646498 -10.0 0.0002909334597507523 -10.0 -10.0 -10.0 -10.0 -10.0 8.582011716859219e-14 -10.0 8.304845400451923e-07 -10.0 4.5757238372058235e-10 -10.0 -10.0 -10.0 1.3116807133030034e-14 -10.0 0.00026866894852481903 -10.0 0.00043166052799897375 -10.0 6.401055165502385e-05 -10.0 5.726152701849347e-15 -10.0 8.541606727879512e-06 -10.0 0.0020293965453828133 -10.0 0.004299195570308035 -10.0 0.0008544159282151438 -10.0 1.0995322456277382e-05 -10.0 1.289814511028015e-05 -10.0 0.0011042047857307254 -10.0 0.006870228272606287 -10.0 0.0013998074566164962 -10.0 4.279460329782799e-08 -10.0 1.2907171695294846e-12 -10.0 0.00019257248009114364 -10.0 0.0009332371598523186 -10.0 0.000131063355181338 -10.0 6.574706543646946e-15 -10.0 -10.0 -10.0 3.8270536025799805e-14 -10.0 2.101790478097517e-08 -10.0 9.904481358675478e-12 -10.0 -10.0 3 From 1e61ccb27faf48b93d2184592e321f7f9ff02208 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 10:39:38 -0600 Subject: [PATCH 0066/2654] Add check that ww class can be converted to str successfully --- tests/unit_tests/weightwindows/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit_tests/weightwindows/test.py b/tests/unit_tests/weightwindows/test.py index aaa0bb523..4f986e064 100644 --- a/tests/unit_tests/weightwindows/test.py +++ b/tests/unit_tests/weightwindows/test.py @@ -126,6 +126,7 @@ def test_weightwindows(model): model.settings.weight_windows = [ww_n, ww_p] + _ = [str(ww) for ww in model.settings.weight_windows] # run again with variance reduction on model.settings.weight_windows_on = True From 5ae761796362002c86a7de16259807add18e35b5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 11:31:25 -0600 Subject: [PATCH 0067/2654] Removing specified length multiplier attribute. Updating string representation --- openmc/mesh.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 40d56f502..584ea81ce 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1137,9 +1137,6 @@ class UnstructuredMesh(MeshBase): output : bool Indicates whether or not automatic tally output should be generated for this mesh - specified_length_multiplier: bool - Indicates whether a non-unity length multiplier has been - applied to this mesh volumes : Iterable of float Volumes of the unstructured mesh elements total_volume : float @@ -1156,7 +1153,6 @@ class UnstructuredMesh(MeshBase): self._centroids = None self.library = library self._output = True - self._specified_length_multiplier = False self.length_multiplier = length_multiplier @property @@ -1241,17 +1237,17 @@ class UnstructuredMesh(MeshBase): @length_multiplier.setter def length_multiplier(self, length_multiplier): cv.check_type("Unstructured mesh length multiplier", - length_multiplier, - Real) + length_multiplier, + Real) self._length_multiplier = length_multiplier - if (self._length_multiplier != 1.0): - self._specified_length_multiplier = True - def __repr__(self): string = super().__repr__() string += '{: <16}=\t{}\n'.format('\tFilename', self.filename) string += '{: <16}=\t{}\n'.format('\tMesh Library', self.mesh_lib) + if self.length_multiplier != 1.0: + string += '{: <16}=\t{}\n'.format('\tLength multiplier', + self.length_multiplier) return string def write_data_to_vtk(self, filename, datasets, volume_normalization=True): @@ -1374,7 +1370,7 @@ class UnstructuredMesh(MeshBase): subelement = ET.SubElement(element, "filename") subelement.text = self.filename - if (self._specified_length_multiplier): + if self._length_multiplier != 1.0: element.set("length_multiplier", str(self.length_multiplier)) return element From 2909182443dcba5dcf8b23a4293180e189a260db Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 11:38:04 -0600 Subject: [PATCH 0068/2654] Enforcing shape when settings lower/upper ww bounds --- openmc/weight_windows.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 5e21d5f4b..f8e058f70 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -5,7 +5,7 @@ from xml.etree import ElementTree as ET import numpy as np from openmc.filter import _PARTICLES -from openmc.mesh import MeshBase +from openmc.mesh import MeshBase, UnstructuredMesh import openmc.checkvalue as cv from ._xml import get_text @@ -178,14 +178,28 @@ class WeightWindows(IDManagerMixin): cv.check_type('Energy bounds', bnds, Iterable, Real) self._energy_bounds = np.array(bnds) + @property + def num_energy_bins(self): + return self.energy_bounds.size - 1 + @property def lower_ww_bounds(self): return self._lower_ww_bounds @lower_ww_bounds.setter def lower_ww_bounds(self, bounds): - cv.check_type('Lower WW bounds', bounds, Iterable, Real) - self._lower_ww_bounds = np.array(bounds) + cv.check_iterable_type('Lower WW bounds', + bounds, + Real, + min_depth=1, + max_depth=4) + # reshape data according to mesh and energy bins + bounds = np.asarray(bounds) + if isinstance(self.mesh, UnstructuredMesh): + bounds.reshape(-1, self.num_energy_bins) + else: + bounds.reshape(*self.mesh.dimension, self.num_energy_bins) + self._lower_ww_bounds = bounds @property def upper_ww_bounds(self): @@ -193,8 +207,18 @@ class WeightWindows(IDManagerMixin): @upper_ww_bounds.setter def upper_ww_bounds(self, bounds): - cv.check_type('Upper WW bounds', bounds, Iterable, Real) - self._upper_ww_bounds = np.array(bounds) + cv.check_iterable_type('Upper WW bounds', + bounds, + Real, + min_depth=1, + max_depth=4) + # reshape data according to mesh and energy bins + bounds = np.asarray(bounds) + if isinstance(self.mesh, UnstructuredMesh): + bounds.reshape(-1, self.num_energy_bins) + else: + bounds.reshape(*self.mesh.dimension, self.num_energy_bins) + self._upper_ww_bounds = bounds @property def survival_ratio(self): From 88afaac4dac404acc7c6cd6547bfff103f76ac50 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 11:47:58 -0600 Subject: [PATCH 0069/2654] Updating doc strings --- openmc/weight_windows.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index f8e058f70..ad966652e 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -50,34 +50,38 @@ class WeightWindows(IDManagerMixin): rouletting max_lower_bound_ratio : float Maximum allowed ratio of a particle's weight to the weight window's - lower bound. A factor will be applied to raise the weight window to be lower - than the particle's weight by a factor of max_lower_bound_ratio + lower bound. A factor will be applied to raise the weight window to be + lower than the particle's weight by a factor of max_lower_bound_ratio during transport if exceeded. max_split : int Maximum allowable number of particles when splitting weight_cutoff : float Threshold below which particles will be terminated id : int - Unique identifier for the weight window settings. If not - specified an identifier will automatically be assigned. + Unique identifier for the weight window settings. If not specified an + identifier will automatically be assigned. Attributes ---------- id : int Unique identifier for the weight window settings. mesh : openmc.MeshBase - Mesh for the weight windows + Mesh for the weight windows with dimension (ni, nj, nk) particle_type : str Particle type the weight windows apply to energy_bounds : Iterable of Real A list of values for which each successive pair constitutes a range of energies in [eV] for a single bin - lower_ww_bounds : Iterable of Real - A list of values for which each value is the lower bound of a weight - window - upper_ww_bounds : Iterable of Real - A list of values for which each value is the upper bound of a weight - window + num_energy_bins : int + Number of energy bins + lower_ww_bounds : numpy.ndarray of float + An array of values for which each value is the lower bound of a weight + window. Shape: (ni, nj, nk, num_energy_bins) for StructuredMesh; (-1, + num_energy_bins) for UnstructuredMesh + upper_ww_bounds : numpy.ndarray of float + An array of values for which each value is the upper bound of a weight + window. Shape: (ni, nj, nk, num_energy_bins) for StructuredMesh; (-1, + num_energy_bins) for UnstructuredMesh survival_ratio : float Ratio of the survival weight to the lower weight window bound for rouletting From 4cd9b585f4a12c4309d5fa1b617d6458d7e51808 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 11:54:56 -0600 Subject: [PATCH 0070/2654] Some PEP8 updates --- openmc/weight_windows.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index ad966652e..b96908747 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -58,7 +58,7 @@ class WeightWindows(IDManagerMixin): weight_cutoff : float Threshold below which particles will be terminated id : int - Unique identifier for the weight window settings. If not specified an + Unique identifier for the weight window settings. If not specified, an identifier will automatically be assigned. Attributes @@ -101,17 +101,25 @@ class WeightWindows(IDManagerMixin): next_id = 1 used_ids = set() - def __init__(self, mesh, lower_ww_bounds, upper_ww_bounds=None, - upper_bound_ratio=None, energy_bounds=None, particle_type='neutron', - survival_ratio=3, max_lower_bound_ratio=None, max_split=10, - weight_cutoff=1.e-38, id=None): + def __init__(self, mesh, lower_ww_bounds, + upper_ww_bounds=None, + upper_bound_ratio=None, + energy_bounds=None, + particle_type='neutron', + survival_ratio=3, + max_lower_bound_ratio=None, + max_split=10, + weight_cutoff=1.e-38, + id=None): self.mesh = mesh self.id = id self.particle_type = particle_type self.energy_bounds = energy_bounds self.lower_ww_bounds = lower_ww_bounds - cv.check_length('Lower window bounds', self.lower_ww_bounds, len(self.energy_bounds)) + cv.check_length('Lower window bounds', + self.lower_ww_bounds, + len(self.energy_bounds)) if upper_ww_bounds is not None and upper_bound_ratio: raise ValueError("Exactly one of upper_ww_bounds and " @@ -130,8 +138,8 @@ class WeightWindows(IDManagerMixin): self.upper_ww_bounds = upper_ww_bounds if len(self.lower_ww_bounds) != len(self.upper_ww_bounds): - raise ValueError('Size of the lower and upper weight window bounds ' - 'do not match') + raise ValueError('Size of the lower and upper weight ' + 'window bounds do not match') self.survival_ratio = survival_ratio From a76bd56ecd8f606b2b782805721bc52178971ddf Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 11:56:15 -0600 Subject: [PATCH 0071/2654] Adding check that energy bounds are set --- openmc/weight_windows.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index b96908747..36c3932fc 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -192,6 +192,8 @@ class WeightWindows(IDManagerMixin): @property def num_energy_bins(self): + if self.energy_bounds is None: + raise ValueError('Energy bounds are not set') return self.energy_bounds.size - 1 @property From a000921e7c8e87e2085a0f35f1ccd4d7ec572c2a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 11:58:17 -0600 Subject: [PATCH 0072/2654] Adding comment for clarity --- tests/unit_tests/weightwindows/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit_tests/weightwindows/test.py b/tests/unit_tests/weightwindows/test.py index 4f986e064..09055b831 100644 --- a/tests/unit_tests/weightwindows/test.py +++ b/tests/unit_tests/weightwindows/test.py @@ -126,6 +126,7 @@ def test_weightwindows(model): model.settings.weight_windows = [ww_n, ww_p] + # check that string form of the class can be created _ = [str(ww) for ww in model.settings.weight_windows] # run again with variance reduction on From 44a5237d44f82b16d41e4ebbd7ebbd7126e1ad4b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 15:32:39 -0600 Subject: [PATCH 0073/2654] Updating docstrings --- openmc/weight_windows.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 36c3932fc..238678ed7 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -76,12 +76,12 @@ class WeightWindows(IDManagerMixin): Number of energy bins lower_ww_bounds : numpy.ndarray of float An array of values for which each value is the lower bound of a weight - window. Shape: (ni, nj, nk, num_energy_bins) for StructuredMesh; (-1, - num_energy_bins) for UnstructuredMesh + window. Shape: (ni, nj, nk, num_energy_bins) for StructuredMesh; + (num_elements, num_energy_bins) for UnstructuredMesh upper_ww_bounds : numpy.ndarray of float An array of values for which each value is the upper bound of a weight - window. Shape: (ni, nj, nk, num_energy_bins) for StructuredMesh; (-1, - num_energy_bins) for UnstructuredMesh + window. Shape: (ni, nj, nk, num_energy_bins) for StructuredMesh; + (num_elements, num_energy_bins) for UnstructuredMesh survival_ratio : float Ratio of the survival weight to the lower weight window bound for rouletting From b3112dc451f7b1d718a1bf44a4cbc7f4d05cee63 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 15:33:39 -0600 Subject: [PATCH 0074/2654] Apply @paulromano suggestions from review Co-authored-by: Paul Romano --- openmc/weight_windows.py | 14 +++++++------- tests/unit_tests/weightwindows/test.py | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 238678ed7..c10bb7bf4 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -186,9 +186,9 @@ class WeightWindows(IDManagerMixin): return self._energy_bounds @energy_bounds.setter - def energy_bounds(self, bnds): - cv.check_type('Energy bounds', bnds, Iterable, Real) - self._energy_bounds = np.array(bnds) + def energy_bounds(self, bounds): + cv.check_type('Energy bounds', bounds, Iterable, Real) + self._energy_bounds = np.asarray(bounds) @property def num_energy_bins(self): @@ -341,7 +341,7 @@ class WeightWindows(IDManagerMixin): # Read all other parameters lower_ww_bounds = [float(l) for l in get_text(elem, 'lower_ww_bounds').split()] upper_ww_bounds = [float(u) for u in get_text(elem, 'upper_ww_bounds').split()] - ebnds = [float(b) for b in get_text(elem, 'energy_bounds').split()] + e_bounds = [float(b) for b in get_text(elem, 'energy_bounds').split()] particle_type = get_text(elem, 'particle_type') survival_ratio = float(get_text(elem, 'survival_ratio')) @@ -357,7 +357,7 @@ class WeightWindows(IDManagerMixin): mesh=mesh, lower_ww_bounds=lower_ww_bounds, upper_ww_bounds=upper_ww_bounds, - energy_bounds=ebnds, + energy_bounds=e_bounds, particle_type=particle_type, survival_ratio=survival_ratio, max_lower_bound_ratio=max_lower_bound_ratio, @@ -386,7 +386,7 @@ class WeightWindows(IDManagerMixin): id = int(group.name.split('/')[-1].lstrip('weight_windows')) mesh_id = group['mesh'][()] ptype = group['particle_type'][()].decode() - ebnds = group['energy_bounds'][()] + e_bounds = group['energy_bounds'][()] lower_ww_bounds = group['lower_ww_bounds'][()] upper_ww_bounds = group['upper_ww_bounds'][()] survival_ratio = group['survival_ratio'][()] @@ -402,7 +402,7 @@ class WeightWindows(IDManagerMixin): mesh=meshes[mesh_id], lower_ww_bounds=lower_ww_bounds, upper_ww_bounds=upper_ww_bounds, - energy_bounds=ebnds, + energy_bounds=e_bounds, particle_type=ptype, survival_ratio=survival_ratio, max_lower_bound_ratio=max_lower_bound_ratio, diff --git a/tests/unit_tests/weightwindows/test.py b/tests/unit_tests/weightwindows/test.py index 09055b831..d065ef6d2 100644 --- a/tests/unit_tests/weightwindows/test.py +++ b/tests/unit_tests/weightwindows/test.py @@ -127,7 +127,8 @@ def test_weightwindows(model): model.settings.weight_windows = [ww_n, ww_p] # check that string form of the class can be created - _ = [str(ww) for ww in model.settings.weight_windows] + for ww in model.settings.weight_windows: + str(ww) # run again with variance reduction on model.settings.weight_windows_on = True From 1451e7bfed06c2f3b14b871352ddcfaaeee575d8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 11 Mar 2022 19:15:48 -0600 Subject: [PATCH 0075/2654] Improve error message if user doesn't set lattice universes --- openmc/lattice.py | 8 +++++++- tests/unit_tests/test_lattice.py | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/openmc/lattice.py b/openmc/lattice.py index 1c311fbb1..b6f1a2774 100644 --- a/openmc/lattice.py +++ b/openmc/lattice.py @@ -852,6 +852,10 @@ class RectLattice(Lattice): if memo is not None: memo.add(self) + # Make sure universes have been assigned + if self.universes is None: + raise ValueError(f"Lattice {self.id} does not have universes assigned.") + lattice_subelement = ET.Element("lattice") lattice_subelement.set("id", str(self._id)) @@ -876,7 +880,7 @@ class RectLattice(Lattice): lower_left = ET.SubElement(lattice_subelement, "lower_left") lower_left.text = ' '.join(map(str, self._lower_left)) - # Export the Lattice nested Universe IDs - column major for Fortran + # Export the Lattice nested Universe IDs universe_ids = '\n' # 3D Lattices @@ -1448,6 +1452,8 @@ class HexLattice(Lattice): center.text = ' '.join(map(str, self._center)) # Export the Lattice nested Universe IDs. + if self.universes is None: + raise ValueError(f"Lattice {self.id} does not have universes assigned.") # 3D Lattices if self._num_axial is not None: diff --git a/tests/unit_tests/test_lattice.py b/tests/unit_tests/test_lattice.py index 31433af7d..28da217b7 100644 --- a/tests/unit_tests/test_lattice.py +++ b/tests/unit_tests/test_lattice.py @@ -361,3 +361,19 @@ def test_show_indices(): assert len(lines) == 4*i - 3 lines_x = openmc.HexLattice.show_indices(i, 'x').split('\n') assert len(lines) == 4*i - 3 + + +def test_unset_universes(): + elem = ET.Element("dummy") + + lattice = openmc.RectLattice() + lattice.lower_left = (-1., -1.) + lattice.pitch = (1., 1.) + with pytest.raises(ValueError): + lattice.create_xml_subelement(elem) + + hex_lattice = openmc.HexLattice() + hex_lattice.center = (0., 0.) + hex_lattice.pitch = (1.,) + with pytest.raises(ValueError): + hex_lattice.create_xml_subelement(elem) From e5d1b88ec7d9099aeab19a7ff3f76e1af18aca20 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 2 Mar 2022 10:12:10 -0600 Subject: [PATCH 0076/2654] Adding support for generating a WeightWindows class from a wwinp file. --- openmc/weight_windows.py | 160 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 1 deletion(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index c10bb7bf4..74019a6ac 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -5,7 +5,7 @@ from xml.etree import ElementTree as ET import numpy as np from openmc.filter import _PARTICLES -from openmc.mesh import MeshBase, UnstructuredMesh +from openmc.mesh import MeshBase, RectilinearMesh, UnstructuredMesh import openmc.checkvalue as cv from ._xml import get_text @@ -410,3 +410,161 @@ class WeightWindows(IDManagerMixin): weight_cutoff=weight_cutoff, id=id ) + + @staticmethod + def wwinp(filename): + """ + Returns the next value in the wwinp file. + + filename : str or pathlib.Path + Location of the wwinp file + """ + fh = open(filename, 'r') + + # read the first line of the file and + # keep only the first four entries + while(True): + line = next(fh) + if line and not line.startswith('c'): + break + + values = line.strip().split()[:4] + for value in values: + yield value + + # the remainder of the file can be read as + # sequential values + while(True): + line = next(fh) + # skip empty or commented lines + if not line or line.startswith('c'): + continue + values = line.strip().split() + for value in values: + yield value + + @classmethod + def from_wwinp(cls, filename): + """Reads a wwinp file into WeightWindowDomain's + + Parameters + ---------- + path : str + Path to the wwinp file. + + Returns + ------- + list of openmc.WeightWindows + """ + # create generator for getting the next parameter from the file + wwinp = WeightWindows.wwinp(filename) + + # first parameter, if, of wwinp file is unused + next(wwinp) + + # check time parameter, iv + if int(float(next(wwinp))) > 1: + raise ValueError('Time-dependent weight windows are not yet supported.') + + # number of particles, ni + ni = int(float(next(wwinp))) + + # read the mesh type, nr + nr = int(float(next(wwinp))) + + if nr != 10: + # TODO: read the first entry by default and display a warning + raise ValueError('Cylindrical meshes are not currently supported') + + # read the number of energy groups for each particle, ne + nes = [int(next(wwinp)) for _ in range(ni)] + + if len(nes) == 1: + particles = ['neutron'] + elif len(nes) == 2: + particles = ['neutron', 'photon'] + else: + msg = ('More than two particle types are present. ' + 'Only neutron and photon weight windows will be read.') + raise Warning(msg) + + # read number of fine mesh elements in each coarse + # element: nfx, nfy, nfz + nfx = int(float(next(wwinp))) + nfy = int(float(next(wwinp))) + nfz = int(float(next(wwinp))) + + # read the mesh origin: x0, y0, z0 + llc = tuple(float(next(wwinp)) for _ in range(3)) + + # read the number of coarse mesh elements, ncx, ncy, ncz + ncx = int(float(next(wwinp))) + ncy = int(float(next(wwinp))) + ncz = int(float(next(wwinp))) + + # skip the value defining the geometry type, nwg, we already know this + next(wwinp) + + def _read_mesh_coords(wwinp, n_coarse_bins): + coords = [float(next(wwinp))] + + for _ in range(n_coarse_bins): + # TODO: These are setup to read according to the MCNP5 format + sx = int(float(next(wwinp))) # number of fine mesh elements in between, sx + px = float(next(wwinp)) # value of next coordinate, px + qx = next(wwinp) # this value is unused, qx + print(qx) + + # append the fine mesh coordinates for this coarse element + coords += list(np.linspace(coords[-1], px, sx + 1))[1:] + + return np.asarray(coords) + + # read the coordinates for each dimension into a rectilinear mesh + mesh = RectilinearMesh() + mesh.x_grid = _read_mesh_coords(wwinp, ncx) + mesh.y_grid = _read_mesh_coords(wwinp, ncy) + mesh.z_grid = _read_mesh_coords(wwinp, ncz) + + dims = ('x', 'y', 'z') + # check consistency of mesh coordinates + mesh_llc = mesh_val = (mesh.x_grid[0], mesh.y_grid[0], mesh.z_grid[0]) + for dim, header_val, mesh_val in zip(dims, llc, mesh_llc): + if header_val != mesh_val: + msg = ('The {} corner of the mesh ({}) does not match ' + 'the value read in block 1 of the wwinp file ({})') + raise ValueError(msg.format(dim, mesh_val, header_val)) + + mesh_dims = mesh.dimension + for dim, header_val, mesh_val in zip(dims, (nfx, nfy, nfz), mesh_dims): + if header_val != mesh_val: + msg = ('Total number of mesh elements read in the {} ' + 'direction ({}) is inconsistent with the ' + 'number read in block 1 of the wwinp file ({})') + raise ValueError(msg.format(dim, mesh_val, header_val)) + + # total number of fine mesh elements, nft + nft = nfx * nfy * nfz + # read energy bins and weight window values for each particle + wws = [] + for particle, ne in zip(particles, nes): + # read energy + e_groups = np.asarray([float(next(wwinp)) for _ in range(ne)]) + + # adjust energy from MeV to eV + e_groups *= 1E6 + + # create an array for weight window lower bounds + ww_lb = np.zeros((ne, nft)) + for e in range(ne): + ww_lb[e, :] = [float(next(wwinp)) for _ in range(nft)] + + settings = WeightWindows(id=None, + mesh=mesh, + lower_ww_bounds=ww_lb.flatten(), + upper_bound_ratio=5.0, + energy_bins=e_groups, + particle_type=particle) + wws.append(settings) + + return wws \ No newline at end of file From 2a8df194ca40481a14055df75bf6a757bf15e270 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Mar 2022 10:24:51 -0600 Subject: [PATCH 0077/2654] Using warnings.warn instead of raising a warning --- openmc/weight_windows.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 74019a6ac..1456e33bd 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -1,5 +1,6 @@ from collections.abc import Iterable from numbers import Real, Integral +import warnings from xml.etree import ElementTree as ET import numpy as np @@ -486,7 +487,7 @@ class WeightWindows(IDManagerMixin): else: msg = ('More than two particle types are present. ' 'Only neutron and photon weight windows will be read.') - raise Warning(msg) + raise warnings.warn(msg) # read number of fine mesh elements in each coarse # element: nfx, nfy, nfz From 69dcabc6b5b961b6259638af660ea6daa32b2d65 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Mar 2022 10:57:37 -0600 Subject: [PATCH 0078/2654] Updating variable names to be more readable --- openmc/weight_windows.py | 84 +++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 1456e33bd..02bb2afaf 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -413,14 +413,14 @@ class WeightWindows(IDManagerMixin): ) @staticmethod - def wwinp(filename): + def wwinp(path): """ - Returns the next value in the wwinp file. + Generator that returns the next value in a wwinp file. - filename : str or pathlib.Path + path : str or pathlib.Path Location of the wwinp file """ - fh = open(filename, 'r') + fh = open(path, 'r') # read the first line of the file and # keep only the first four entries @@ -445,8 +445,8 @@ class WeightWindows(IDManagerMixin): yield value @classmethod - def from_wwinp(cls, filename): - """Reads a wwinp file into WeightWindowDomain's + def from_wwinp(cls, path): + """Creates WeightWindows classes from a wwinp file Parameters ---------- @@ -458,7 +458,7 @@ class WeightWindows(IDManagerMixin): list of openmc.WeightWindows """ # create generator for getting the next parameter from the file - wwinp = WeightWindows.wwinp(filename) + wwinp = WeightWindows.wwinp(path) # first parameter, if, of wwinp file is unused next(wwinp) @@ -467,45 +467,57 @@ class WeightWindows(IDManagerMixin): if int(float(next(wwinp))) > 1: raise ValueError('Time-dependent weight windows are not yet supported.') - # number of particles, ni - ni = int(float(next(wwinp))) + # number of particle types, ni + n_particle_types = int(float(next(wwinp))) - # read the mesh type, nr - nr = int(float(next(wwinp))) + # read an indicator of the mesh type. + # this will be 10 if a rectilinear mesh + # and 16 for cylindrical or spherical meshes + mesh_chars = int(float(next(wwinp))) - if nr != 10: + if mesh_chars != 10: # TODO: read the first entry by default and display a warning - raise ValueError('Cylindrical meshes are not currently supported') + raise ValueError('Cylindrical and Spherical meshes are not currently supported') # read the number of energy groups for each particle, ne - nes = [int(next(wwinp)) for _ in range(ni)] + n_egroups = [int(next(wwinp)) for _ in range(n_particle_types)] - if len(nes) == 1: + if len(n_egroups) == 1: particles = ['neutron'] - elif len(nes) == 2: + elif len(n_egroups) == 2: particles = ['neutron', 'photon'] - else: + + if len(n_egroups) > 2: msg = ('More than two particle types are present. ' 'Only neutron and photon weight windows will be read.') - raise warnings.warn(msg) + warnings.warn(msg) - # read number of fine mesh elements in each coarse - # element: nfx, nfy, nfz - nfx = int(float(next(wwinp))) - nfy = int(float(next(wwinp))) - nfz = int(float(next(wwinp))) + # read total number of fine mesh elements in each coarse + # element (nfx, nfy, nfz) + n_fine_x = int(float(next(wwinp))) + n_fine_y = int(float(next(wwinp))) + n_fine_z = int(float(next(wwinp))) + header_mesh_dims = (n_fine_x, n_fine_y, n_fine_z) # read the mesh origin: x0, y0, z0 llc = tuple(float(next(wwinp)) for _ in range(3)) - # read the number of coarse mesh elements, ncx, ncy, ncz - ncx = int(float(next(wwinp))) - ncy = int(float(next(wwinp))) - ncz = int(float(next(wwinp))) + # read the number of coarse mesh elements (ncx, ncy, ncz) + n_coarse_x = int(float(next(wwinp))) + n_coarse_y = int(float(next(wwinp))) + n_coarse_z = int(float(next(wwinp))) # skip the value defining the geometry type, nwg, we already know this - next(wwinp) + # 1 - rectilinear mesh + # 2 - cylindrical mesh + # 3 - spherical mesh + mesh_type = int(float(next(wwinp))) + if mesh_type != 1: + # TODO: support additional mesh types + raise ValueError('Cylindrical and Spherical meshes are not currently supported') + + # internal function for parsing mesh coordinates def _read_mesh_coords(wwinp, n_coarse_bins): coords = [float(next(wwinp))] @@ -523,9 +535,9 @@ class WeightWindows(IDManagerMixin): # read the coordinates for each dimension into a rectilinear mesh mesh = RectilinearMesh() - mesh.x_grid = _read_mesh_coords(wwinp, ncx) - mesh.y_grid = _read_mesh_coords(wwinp, ncy) - mesh.z_grid = _read_mesh_coords(wwinp, ncz) + mesh.x_grid = _read_mesh_coords(wwinp, n_coarse_x) + mesh.y_grid = _read_mesh_coords(wwinp, n_coarse_y) + mesh.z_grid = _read_mesh_coords(wwinp, n_coarse_z) dims = ('x', 'y', 'z') # check consistency of mesh coordinates @@ -537,7 +549,7 @@ class WeightWindows(IDManagerMixin): raise ValueError(msg.format(dim, mesh_val, header_val)) mesh_dims = mesh.dimension - for dim, header_val, mesh_val in zip(dims, (nfx, nfy, nfz), mesh_dims): + for dim, header_val, mesh_val in zip(dims, header_mesh_dims, mesh_dims): if header_val != mesh_val: msg = ('Total number of mesh elements read in the {} ' 'direction ({}) is inconsistent with the ' @@ -545,10 +557,10 @@ class WeightWindows(IDManagerMixin): raise ValueError(msg.format(dim, mesh_val, header_val)) # total number of fine mesh elements, nft - nft = nfx * nfy * nfz + n_elements = n_fine_x * n_fine_y * n_fine_z # read energy bins and weight window values for each particle wws = [] - for particle, ne in zip(particles, nes): + for particle, ne in zip(particles, n_egroups): # read energy e_groups = np.asarray([float(next(wwinp)) for _ in range(ne)]) @@ -556,9 +568,9 @@ class WeightWindows(IDManagerMixin): e_groups *= 1E6 # create an array for weight window lower bounds - ww_lb = np.zeros((ne, nft)) + ww_lb = np.zeros((ne, n_elements)) for e in range(ne): - ww_lb[e, :] = [float(next(wwinp)) for _ in range(nft)] + ww_lb[e, :] = [float(next(wwinp)) for _ in range(n_elements)] settings = WeightWindows(id=None, mesh=mesh, From 8a33d739e7300a42cf7999cd79baa50812ef147b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Mar 2022 10:58:19 -0600 Subject: [PATCH 0079/2654] More small adjustments to comments for clarity. Moving to normal method. --- openmc/weight_windows.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 02bb2afaf..be319fcef 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -444,8 +444,7 @@ class WeightWindows(IDManagerMixin): for value in values: yield value - @classmethod - def from_wwinp(cls, path): + def wws_from_wwinp(self, path): """Creates WeightWindows classes from a wwinp file Parameters @@ -522,12 +521,12 @@ class WeightWindows(IDManagerMixin): coords = [float(next(wwinp))] for _ in range(n_coarse_bins): - # TODO: These are setup to read according to the MCNP5 format - sx = int(float(next(wwinp))) # number of fine mesh elements in between, sx - px = float(next(wwinp)) # value of next coordinate, px - qx = next(wwinp) # this value is unused, qx - print(qx) - + # number of fine mesh elements in this coarse element, sx + sx = int(float(next(wwinp))) + # value of next coordinate, px + px = float(next(wwinp)) + # fine mesh ratio, qx, is currently unused + qx = next(wwinp) # append the fine mesh coordinates for this coarse element coords += list(np.linspace(coords[-1], px, sx + 1))[1:] @@ -548,6 +547,7 @@ class WeightWindows(IDManagerMixin): 'the value read in block 1 of the wwinp file ({})') raise ValueError(msg.format(dim, mesh_val, header_val)) + # check totaly number of mesh elements in each direction mesh_dims = mesh.dimension for dim, header_val, mesh_val in zip(dims, header_mesh_dims, mesh_dims): if header_val != mesh_val: @@ -561,8 +561,8 @@ class WeightWindows(IDManagerMixin): # read energy bins and weight window values for each particle wws = [] for particle, ne in zip(particles, n_egroups): - # read energy - e_groups = np.asarray([float(next(wwinp)) for _ in range(ne)]) + # read upper energy bounds + e_groups = np.asarray([0.0] + [float(next(wwinp)) for _ in range(ne)]) # adjust energy from MeV to eV e_groups *= 1E6 From 8fc481e966a8b44a0382e282ddc434e4d5327864 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Mar 2022 14:52:55 -0600 Subject: [PATCH 0080/2654] Making wwinp reader a file-level-function. Correcting order of ww vals --- openmc/weight_windows.py | 278 ++++++++++++++++++++------------------- 1 file changed, 141 insertions(+), 137 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index be319fcef..32acbf500 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -412,172 +412,176 @@ class WeightWindows(IDManagerMixin): id=id ) - @staticmethod - def wwinp(path): - """ - Generator that returns the next value in a wwinp file. +def __wwinp_reader(path): + """ + Generator that returns the next value in a wwinp file. - path : str or pathlib.Path - Location of the wwinp file - """ - fh = open(path, 'r') + path : str or pathlib.Path + Location of the wwinp file + """ + fh = open(path, 'r') - # read the first line of the file and - # keep only the first four entries - while(True): - line = next(fh) - if line and not line.startswith('c'): - break + # read the first line of the file and + # keep only the first four entries + while(True): + line = next(fh) + if line and not line.startswith('c'): + break - values = line.strip().split()[:4] + values = line.strip().split()[:4] + for value in values: + yield value + + # the remainder of the file can be read as + # sequential values + while(True): + line = next(fh) + # skip empty or commented lines + if not line or line.startswith('c'): + continue + values = line.strip().split() for value in values: yield value - # the remainder of the file can be read as - # sequential values - while(True): - line = next(fh) - # skip empty or commented lines - if not line or line.startswith('c'): - continue - values = line.strip().split() - for value in values: - yield value +def wwinp_to_wws(path): + """Creates WeightWindows classes from a wwinp file - def wws_from_wwinp(self, path): - """Creates WeightWindows classes from a wwinp file + Parameters + ---------- + path : str + Path to the wwinp file. - Parameters - ---------- - path : str - Path to the wwinp file. + Returns + ------- + list of openmc.WeightWindows + """ + # create generator for getting the next parameter from the file + wwinp = __wwinp_reader(path) - Returns - ------- - list of openmc.WeightWindows - """ - # create generator for getting the next parameter from the file - wwinp = WeightWindows.wwinp(path) + # first parameter, if, of wwinp file is unused + next(wwinp) - # first parameter, if, of wwinp file is unused - next(wwinp) + # check time parameter, iv + if int(float(next(wwinp))) > 1: + raise ValueError('Time-dependent weight windows are not yet supported.') - # check time parameter, iv - if int(float(next(wwinp))) > 1: - raise ValueError('Time-dependent weight windows are not yet supported.') + # number of particle types, ni + n_particle_types = int(float(next(wwinp))) - # number of particle types, ni - n_particle_types = int(float(next(wwinp))) + # read an indicator of the mesh type. + # this will be 10 if a rectilinear mesh + # and 16 for cylindrical or spherical meshes + mesh_chars = int(float(next(wwinp))) - # read an indicator of the mesh type. - # this will be 10 if a rectilinear mesh - # and 16 for cylindrical or spherical meshes - mesh_chars = int(float(next(wwinp))) + if mesh_chars != 10: + # TODO: read the first entry by default and display a warning + raise ValueError('Cylindrical and Spherical meshes are not currently supported') - if mesh_chars != 10: - # TODO: read the first entry by default and display a warning - raise ValueError('Cylindrical and Spherical meshes are not currently supported') + # read the number of energy groups for each particle, ne + n_egroups = [int(next(wwinp)) for _ in range(n_particle_types)] - # read the number of energy groups for each particle, ne - n_egroups = [int(next(wwinp)) for _ in range(n_particle_types)] + if len(n_egroups) == 1: + particles = ['neutron'] + elif len(n_egroups) == 2: + particles = ['neutron', 'photon'] - if len(n_egroups) == 1: - particles = ['neutron'] - elif len(n_egroups) == 2: - particles = ['neutron', 'photon'] + if len(n_egroups) > 2: + msg = ('More than two particle types are present. ' + 'Only neutron and photon weight windows will be read.') + warnings.warn(msg) - if len(n_egroups) > 2: - msg = ('More than two particle types are present. ' - 'Only neutron and photon weight windows will be read.') - warnings.warn(msg) + # read total number of fine mesh elements in each coarse + # element (nfx, nfy, nfz) + n_fine_x = int(float(next(wwinp))) + n_fine_y = int(float(next(wwinp))) + n_fine_z = int(float(next(wwinp))) + header_mesh_dims = (n_fine_x, n_fine_y, n_fine_z) - # read total number of fine mesh elements in each coarse - # element (nfx, nfy, nfz) - n_fine_x = int(float(next(wwinp))) - n_fine_y = int(float(next(wwinp))) - n_fine_z = int(float(next(wwinp))) - header_mesh_dims = (n_fine_x, n_fine_y, n_fine_z) + # read the mesh origin: x0, y0, z0 + llc = tuple(float(next(wwinp)) for _ in range(3)) - # read the mesh origin: x0, y0, z0 - llc = tuple(float(next(wwinp)) for _ in range(3)) + # read the number of coarse mesh elements (ncx, ncy, ncz) + n_coarse_x = int(float(next(wwinp))) + n_coarse_y = int(float(next(wwinp))) + n_coarse_z = int(float(next(wwinp))) - # read the number of coarse mesh elements (ncx, ncy, ncz) - n_coarse_x = int(float(next(wwinp))) - n_coarse_y = int(float(next(wwinp))) - n_coarse_z = int(float(next(wwinp))) + # skip the value defining the geometry type, nwg, we already know this + # 1 - rectilinear mesh + # 2 - cylindrical mesh + # 3 - spherical mesh + mesh_type = int(float(next(wwinp))) - # skip the value defining the geometry type, nwg, we already know this - # 1 - rectilinear mesh - # 2 - cylindrical mesh - # 3 - spherical mesh - mesh_type = int(float(next(wwinp))) + if mesh_type != 1: + # TODO: support additional mesh types + raise ValueError('Cylindrical and Spherical meshes are not currently supported') - if mesh_type != 1: - # TODO: support additional mesh types - raise ValueError('Cylindrical and Spherical meshes are not currently supported') + # internal function for parsing mesh coordinates + def _read_mesh_coords(wwinp, n_coarse_bins): + coords = [float(next(wwinp))] - # internal function for parsing mesh coordinates - def _read_mesh_coords(wwinp, n_coarse_bins): - coords = [float(next(wwinp))] + for _ in range(n_coarse_bins): + # number of fine mesh elements in this coarse element, sx + sx = int(float(next(wwinp))) + # value of next coordinate, px + px = float(next(wwinp)) + # fine mesh ratio, qx, is currently unused + qx = next(wwinp) + # append the fine mesh coordinates for this coarse element + coords += list(np.linspace(coords[-1], px, sx + 1))[1:] - for _ in range(n_coarse_bins): - # number of fine mesh elements in this coarse element, sx - sx = int(float(next(wwinp))) - # value of next coordinate, px - px = float(next(wwinp)) - # fine mesh ratio, qx, is currently unused - qx = next(wwinp) - # append the fine mesh coordinates for this coarse element - coords += list(np.linspace(coords[-1], px, sx + 1))[1:] + return np.asarray(coords) - return np.asarray(coords) + # read the coordinates for each dimension into a rectilinear mesh + mesh = RectilinearMesh() + mesh.x_grid = _read_mesh_coords(wwinp, n_coarse_x) + mesh.y_grid = _read_mesh_coords(wwinp, n_coarse_y) + mesh.z_grid = _read_mesh_coords(wwinp, n_coarse_z) - # read the coordinates for each dimension into a rectilinear mesh - mesh = RectilinearMesh() - mesh.x_grid = _read_mesh_coords(wwinp, n_coarse_x) - mesh.y_grid = _read_mesh_coords(wwinp, n_coarse_y) - mesh.z_grid = _read_mesh_coords(wwinp, n_coarse_z) + dims = ('x', 'y', 'z') + # check consistency of mesh coordinates + mesh_llc = mesh_val = (mesh.x_grid[0], mesh.y_grid[0], mesh.z_grid[0]) + for dim, header_val, mesh_val in zip(dims, llc, mesh_llc): + if header_val != mesh_val: + msg = ('The {} corner of the mesh ({}) does not match ' + 'the value read in block 1 of the wwinp file ({})') + raise ValueError(msg.format(dim, mesh_val, header_val)) - dims = ('x', 'y', 'z') - # check consistency of mesh coordinates - mesh_llc = mesh_val = (mesh.x_grid[0], mesh.y_grid[0], mesh.z_grid[0]) - for dim, header_val, mesh_val in zip(dims, llc, mesh_llc): - if header_val != mesh_val: - msg = ('The {} corner of the mesh ({}) does not match ' - 'the value read in block 1 of the wwinp file ({})') - raise ValueError(msg.format(dim, mesh_val, header_val)) + # check totaly number of mesh elements in each direction + mesh_dims = mesh.dimension + for dim, header_val, mesh_val in zip(dims, header_mesh_dims, mesh_dims): + if header_val != mesh_val: + msg = ('Total number of mesh elements read in the {} ' + 'direction ({}) is inconsistent with the ' + 'number read in block 1 of the wwinp file ({})') + raise ValueError(msg.format(dim, mesh_val, header_val)) - # check totaly number of mesh elements in each direction - mesh_dims = mesh.dimension - for dim, header_val, mesh_val in zip(dims, header_mesh_dims, mesh_dims): - if header_val != mesh_val: - msg = ('Total number of mesh elements read in the {} ' - 'direction ({}) is inconsistent with the ' - 'number read in block 1 of the wwinp file ({})') - raise ValueError(msg.format(dim, mesh_val, header_val)) + # total number of fine mesh elements, nft + n_elements = n_fine_x * n_fine_y * n_fine_z + # read energy bins and weight window values for each particle + wws = [] + for particle, ne in zip(particles, n_egroups): + # read upper energy bounds + # it is implied that zero is always the first bound in MCNP + e_groups = np.asarray([0.0] + [float(next(wwinp)) for _ in range(ne)]) - # total number of fine mesh elements, nft - n_elements = n_fine_x * n_fine_y * n_fine_z - # read energy bins and weight window values for each particle - wws = [] - for particle, ne in zip(particles, n_egroups): - # read upper energy bounds - e_groups = np.asarray([0.0] + [float(next(wwinp)) for _ in range(ne)]) + # adjust energy from MeV to eV + e_groups *= 1E6 - # adjust energy from MeV to eV - e_groups *= 1E6 + # create an array for weight window lower bounds + ww_lb = np.zeros((ne, n_elements)) + for e in range(ne): + ww_lb[e, :] = [float(next(wwinp)) for _ in range(n_elements)] - # create an array for weight window lower bounds - ww_lb = np.zeros((ne, n_elements)) - for e in range(ne): - ww_lb[e, :] = [float(next(wwinp)) for _ in range(n_elements)] + # reorder weight window lower bounds + # MCNP ordering - 'zyx', with z changing fastest + # OpenMC ordering 'xyz', with x changing fastest + ww_lb = np.swapaxes(ww_lb, 1, 3) + settings = WeightWindows(id=None, + mesh=mesh, + lower_ww_bounds=ww_lb.flatten(), + upper_bound_ratio=5.0, + energy_bins=e_groups, + particle_type=particle) + wws.append(settings) - settings = WeightWindows(id=None, - mesh=mesh, - lower_ww_bounds=ww_lb.flatten(), - upper_bound_ratio=5.0, - energy_bins=e_groups, - particle_type=particle) - wws.append(settings) - - return wws \ No newline at end of file + return wws \ No newline at end of file From 74dd96b21dd2addb12506bb639e7c65a13a444b6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Mar 2022 16:55:59 -0600 Subject: [PATCH 0081/2654] Adding zero energy bound. Reshaping ww values as an extra check on sizing --- openmc/weight_windows.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 32acbf500..e3ea42fa2 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -562,25 +562,23 @@ def wwinp_to_wws(path): for particle, ne in zip(particles, n_egroups): # read upper energy bounds # it is implied that zero is always the first bound in MCNP - e_groups = np.asarray([0.0] + [float(next(wwinp)) for _ in range(ne)]) - + e_bounds = np.asarray([0.0] + [float(next(wwinp)) for _ in range(ne)]) # adjust energy from MeV to eV - e_groups *= 1E6 + e_bounds *= 1E6 # create an array for weight window lower bounds - ww_lb = np.zeros((ne, n_elements)) + ww_lb = np.zeros((ne, *mesh.dimension)) for e in range(ne): - ww_lb[e, :] = [float(next(wwinp)) for _ in range(n_elements)] + # MCNP ordering for weight windows matches that of OpenMC + # ('xyz' with x changing fastest) + ww_vals = [float(next(wwinp)) for _ in range(n_elements)] + ww_lb[e, :] = np.asarray(ww_vals).reshape(mesh.dimension) - # reorder weight window lower bounds - # MCNP ordering - 'zyx', with z changing fastest - # OpenMC ordering 'xyz', with x changing fastest - ww_lb = np.swapaxes(ww_lb, 1, 3) settings = WeightWindows(id=None, mesh=mesh, lower_ww_bounds=ww_lb.flatten(), upper_bound_ratio=5.0, - energy_bins=e_groups, + energy_bins=e_bounds, particle_type=particle) wws.append(settings) From 7abb11f7c45aa1cfc13e08838c35bed2826bbfad Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 9 Mar 2022 23:35:18 -0600 Subject: [PATCH 0082/2654] Adding wwinp test file for neutrons only Adding wwinp reader test file Updating tests for more test cases and adding readable labels Fixes for iteration ordering, shape, and particles read Updating weight window values of neutron-only file. Adding neutron-photon and photon-only test files Updates to wwinp file format. All can be read by MCNP. --- openmc/weight_windows.py | 31 ++- .../weightwindows/test_wwinp_reader.py | 117 ++++++++ tests/unit_tests/weightwindows/wwinp_n | 263 ++++++++++++++++++ tests/unit_tests/weightwindows/wwinp_np | 48 ++++ tests/unit_tests/weightwindows/wwinp_p | 48 ++++ 5 files changed, 494 insertions(+), 13 deletions(-) create mode 100644 tests/unit_tests/weightwindows/test_wwinp_reader.py create mode 100644 tests/unit_tests/weightwindows/wwinp_n create mode 100644 tests/unit_tests/weightwindows/wwinp_np create mode 100644 tests/unit_tests/weightwindows/wwinp_p diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index e3ea42fa2..4dabe2a1f 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -480,12 +480,15 @@ def wwinp_to_wws(path): # read the number of energy groups for each particle, ne n_egroups = [int(next(wwinp)) for _ in range(n_particle_types)] - if len(n_egroups) == 1: - particles = ['neutron'] - elif len(n_egroups) == 2: - particles = ['neutron', 'photon'] + # order that supported particle types will appear in the file + particle_types = ['neutron', 'photon'] - if len(n_egroups) > 2: + # add particle to list if at least one energy group is present + particles = [p for e, p in zip(n_egroups, particle_types) if e > 0] + # truncate list of energy groups if needed + n_egroups = [e for e in n_egroups if e > 0] + + if n_particle_types > 2: msg = ('More than two particle types are present. ' 'Only neutron and photon weight windows will be read.') warnings.warn(msg) @@ -546,7 +549,7 @@ def wwinp_to_wws(path): 'the value read in block 1 of the wwinp file ({})') raise ValueError(msg.format(dim, mesh_val, header_val)) - # check totaly number of mesh elements in each direction + # check total number of mesh elements in each direction mesh_dims = mesh.dimension for dim, header_val, mesh_val in zip(dims, header_mesh_dims, mesh_dims): if header_val != mesh_val: @@ -567,13 +570,15 @@ def wwinp_to_wws(path): e_bounds *= 1E6 # create an array for weight window lower bounds - ww_lb = np.zeros((ne, *mesh.dimension)) - for e in range(ne): - # MCNP ordering for weight windows matches that of OpenMC - # ('xyz' with x changing fastest) - ww_vals = [float(next(wwinp)) for _ in range(n_elements)] - ww_lb[e, :] = np.asarray(ww_vals).reshape(mesh.dimension) - + ww_lb = np.zeros((*mesh.dimension, ne)) + for ijk in mesh.indices: + idx = tuple([v - 1 for v in ijk] + [slice(None)]) + ww_lb[idx] = [float(next(wwinp)) for _ in range(ne)] + # for e in range(ne): + # # MCNP ordering for weight windows matches that of OpenMC + # # ('xyz' with x changing fastest) + # ww_vals = [float(next(wwinp)) for _ in range(n_elements)] + # ww_lb[e, :] = np.asarray(ww_vals).reshape(mesh.dimension) settings = WeightWindows(id=None, mesh=mesh, lower_ww_bounds=ww_lb.flatten(), diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py new file mode 100644 index 000000000..910c0e912 --- /dev/null +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -0,0 +1,117 @@ +import numpy as np + +import openmc +import pytest + + +# check that we can successfully read wwinp files with the following contents: +# +# - neutrons on a rectilinear mesh +# - neutrons and photons on a rectilinear mesh + +# check that the following raises the correct exceptions (for now): +# +# - wwinp file with multiple time steps +# - wwinp file with cylindrical or spherical mesh + + +# expected retults - neutron data only +n_mesh = openmc.RectilinearMesh() +n_mesh.x_grid = np.asarray([-100.0, + -99.0, + -97.0, + -79.36364, + -61.72727, + -44.09091, + -26.45455, + -8.818182, + 8.818182, + 26.45455, + 44.09091, + 61.72727, + 79.36364, + 97.0, + 99.0, + 100]) +n_mesh.y_grid = np.asarray([-100.0, + -50.0, + -13.33333, + 23.33333, + 60.0, + 70.0, + 80.0, + 90.0, + 100.0]) +n_mesh.z_grid = np.asarray([-100.0, + -66.66667, + -33.33333, + 0.0, + 33.33333, + 66.66667, + 100.0]) +n_e_bounds = np.asarray([0.0, + 100000.0, + 146780.0]) + +# expected results - neutron and photon data +np_mesh = openmc.RectilinearMesh() +np_mesh.x_grid = np.asarray([-100.0, 100.0]) +# y grid and z grid are the same as the previous mesh +np_mesh.y_grid = n_mesh.y_grid +np_mesh.z_grid = n_mesh.z_grid + +np_n_e_bounds = np.asarray([0.0, 100000.0, 146780.0, 215440.0]) +np_p_e_bounds = np.asarray([0.0, 1.0E8]) + +# expected results - photon data only +p_mesh = openmc.RectilinearMesh() +# adopts z grid from previous meshes as its x grid +p_mesh.x_grid = np_mesh.z_grid +# uses the same y grid +p_mesh.y_grid = np_mesh.y_grid +p_mesh.z_grid = np.asarray([-50.0, 50.0]) + +p_e_bounds = np.asarray([0.0, 100000.0, 146780.0, 215440.0, 316230.0]) + +expected_results = [('wwinp_n', n_mesh, ('neutron',), (n_e_bounds,)), + ('wwinp_np', np_mesh, ('neutron', 'photon'), (np_n_e_bounds, np_p_e_bounds)), + ('wwinp_p', p_mesh, ('photon',), (p_e_bounds,))] + +def id_fn(params): + suffix = params[0].split('_')[-1] + if suffix == 'n': + return 'neutron-only' + elif suffix == 'np': + return 'neutron-photon' + elif suffix == 'p': + return 'photon-only' + + +@pytest.mark.parametrize('wwinp_data', expected_results, ids=id_fn) +def test_wwinp_reader(wwinp_data): + wwinp_file, mesh, particle_types, energy_bounds = wwinp_data + + wws = openmc.wwinp_to_wws(wwinp_file) + + for i, ww in enumerate(wws): + e_bounds = energy_bounds[i] + particle_type = particle_types[i] + + assert ww.particle_type == particle_type + + # check the mesh grid + # there will be some very small changes due to the number of digits + # provided in the wwinp format and the use of np.linspace to compute + # boundaries of the fine mesh intervals + np.testing.assert_allclose(mesh.x_grid, ww.mesh.x_grid, rtol=1e-6) + np.testing.assert_allclose(mesh.y_grid, ww.mesh.y_grid, rtol=1e-6) + np.testing.assert_allclose(mesh.z_grid, ww.mesh.z_grid, rtol=1e-6) + + # check the energy bounds + np.testing.assert_array_equal(e_bounds, ww.energy_bins) + + # check the expected weight window values mocked in the file -- + # a reversed array of the flat index into the numpy array + n_wws = np.prod((*mesh.dimension, e_bounds.size - 1)) + exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1] + np.testing.assert_array_equal(exp_ww_lb, ww.lower_ww_bounds) diff --git a/tests/unit_tests/weightwindows/wwinp_n b/tests/unit_tests/weightwindows/wwinp_n new file mode 100644 index 000000000..b9611e945 --- /dev/null +++ b/tests/unit_tests/weightwindows/wwinp_n @@ -0,0 +1,263 @@ + 1 1 1 10 + 2 + 15.0 8.0 6.0 -1.00000E+02 -1.00000E+02 -1.00000E+02 + 15.0 8.0 6.0 1.0 + -1.00000E+02 1.00000E+00 -9.90000E+01 1.00000E+00 1.00000E+00 -9.70000E+01 + 1.00000E+00 1.00000E+00 -7.93636E+01 1.00000E+00 1.00000E+00 -6.17273E+01 + 1.00000E+00 1.00000E+00 -4.40909E+01 1.00000E+00 1.00000E+00 -2.64546E+01 + 1.00000E+00 1.00000E+00 -8.81818E+00 1.00000E+00 1.00000E+00 8.81818E+00 + 1.00000E+00 1.00000E+00 2.64546E+01 1.00000E+00 1.00000E+00 4.40909E+01 + 1.00000E+00 1.00000E+00 6.17273E+01 1.00000E+00 1.00000E+00 7.93636E+01 + 1.00000E+00 1.00000E+00 9.70000E+01 1.00000E+00 1.00000E+00 9.90000E+01 + 1.00000E+00 1.00000E+00 1.00000E+02 1.00000E+00 + -1.00000E+02 1.00000E+00 -5.00000E+01 1.00000E+00 1.00000E+00 -1.33333E+01 + 1.00000E+00 1.00000E+00 2.33333E+01 1.00000E+00 1.00000E+00 6.00000E+01 + 1.00000E+00 1.00000E+00 7.00000E+01 1.00000E+00 1.00000E+00 8.00000E+01 + 1.00000E+00 1.00000E+00 9.00000E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -1.00000E+02 1.00000E+00 -6.66667E+01 1.00000E+00 1.00000E+00 -3.33333E+01 + 1.00000E+00 1.00000E+00 0.00000E+00 1.00000E+00 1.00000E+00 3.33333E+01 + 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + 1.00000E-01 1.46780E-01 + 1.44000E+03 1.43900E+03 1.34400E+03 1.34300E+03 1.24800E+03 1.24700E+03 + 1.15200E+03 1.15100E+03 1.05600E+03 1.05500E+03 9.60000E+02 9.59000E+02 + 8.64000E+02 8.63000E+02 7.68000E+02 7.67000E+02 6.72000E+02 6.71000E+02 + 5.76000E+02 5.75000E+02 4.80000E+02 4.79000E+02 3.84000E+02 3.83000E+02 + 2.88000E+02 2.87000E+02 1.92000E+02 1.91000E+02 9.60000E+01 9.50000E+01 + 1.42800E+03 1.42700E+03 1.33200E+03 1.33100E+03 1.23600E+03 1.23500E+03 + 1.14000E+03 1.13900E+03 1.04400E+03 1.04300E+03 9.48000E+02 9.47000E+02 + 8.52000E+02 8.51000E+02 7.56000E+02 7.55000E+02 6.60000E+02 6.59000E+02 + 5.64000E+02 5.63000E+02 4.68000E+02 4.67000E+02 3.72000E+02 3.71000E+02 + 2.76000E+02 2.75000E+02 1.80000E+02 1.79000E+02 8.40000E+01 8.30000E+01 + 1.41600E+03 1.41500E+03 1.32000E+03 1.31900E+03 1.22400E+03 1.22300E+03 + 1.12800E+03 1.12700E+03 1.03200E+03 1.03100E+03 9.36000E+02 9.35000E+02 + 8.40000E+02 8.39000E+02 7.44000E+02 7.43000E+02 6.48000E+02 6.47000E+02 + 5.52000E+02 5.51000E+02 4.56000E+02 4.55000E+02 3.60000E+02 3.59000E+02 + 2.64000E+02 2.63000E+02 1.68000E+02 1.67000E+02 7.20000E+01 7.10000E+01 + 1.40400E+03 1.40300E+03 1.30800E+03 1.30700E+03 1.21200E+03 1.21100E+03 + 1.11600E+03 1.11500E+03 1.02000E+03 1.01900E+03 9.24000E+02 9.23000E+02 + 8.28000E+02 8.27000E+02 7.32000E+02 7.31000E+02 6.36000E+02 6.35000E+02 + 5.40000E+02 5.39000E+02 4.44000E+02 4.43000E+02 3.48000E+02 3.47000E+02 + 2.52000E+02 2.51000E+02 1.56000E+02 1.55000E+02 6.00000E+01 5.90000E+01 + 1.39200E+03 1.39100E+03 1.29600E+03 1.29500E+03 1.20000E+03 1.19900E+03 + 1.10400E+03 1.10300E+03 1.00800E+03 1.00700E+03 9.12000E+02 9.11000E+02 + 8.16000E+02 8.15000E+02 7.20000E+02 7.19000E+02 6.24000E+02 6.23000E+02 + 5.28000E+02 5.27000E+02 4.32000E+02 4.31000E+02 3.36000E+02 3.35000E+02 + 2.40000E+02 2.39000E+02 1.44000E+02 1.43000E+02 4.80000E+01 4.70000E+01 + 1.38000E+03 1.37900E+03 1.28400E+03 1.28300E+03 1.18800E+03 1.18700E+03 + 1.09200E+03 1.09100E+03 9.96000E+02 9.95000E+02 9.00000E+02 8.99000E+02 + 8.04000E+02 8.03000E+02 7.08000E+02 7.07000E+02 6.12000E+02 6.11000E+02 + 5.16000E+02 5.15000E+02 4.20000E+02 4.19000E+02 3.24000E+02 3.23000E+02 + 2.28000E+02 2.27000E+02 1.32000E+02 1.31000E+02 3.60000E+01 3.50000E+01 + 1.36800E+03 1.36700E+03 1.27200E+03 1.27100E+03 1.17600E+03 1.17500E+03 + 1.08000E+03 1.07900E+03 9.84000E+02 9.83000E+02 8.88000E+02 8.87000E+02 + 7.92000E+02 7.91000E+02 6.96000E+02 6.95000E+02 6.00000E+02 5.99000E+02 + 5.04000E+02 5.03000E+02 4.08000E+02 4.07000E+02 3.12000E+02 3.11000E+02 + 2.16000E+02 2.15000E+02 1.20000E+02 1.19000E+02 2.40000E+01 2.30000E+01 + 1.35600E+03 1.35500E+03 1.26000E+03 1.25900E+03 1.16400E+03 1.16300E+03 + 1.06800E+03 1.06700E+03 9.72000E+02 9.71000E+02 8.76000E+02 8.75000E+02 + 7.80000E+02 7.79000E+02 6.84000E+02 6.83000E+02 5.88000E+02 5.87000E+02 + 4.92000E+02 4.91000E+02 3.96000E+02 3.95000E+02 3.00000E+02 2.99000E+02 + 2.04000E+02 2.03000E+02 1.08000E+02 1.07000E+02 1.20000E+01 1.10000E+01 + 1.43800E+03 1.43700E+03 1.34200E+03 1.34100E+03 1.24600E+03 1.24500E+03 + 1.15000E+03 1.14900E+03 1.05400E+03 1.05300E+03 9.58000E+02 9.57000E+02 + 8.62000E+02 8.61000E+02 7.66000E+02 7.65000E+02 6.70000E+02 6.69000E+02 + 5.74000E+02 5.73000E+02 4.78000E+02 4.77000E+02 3.82000E+02 3.81000E+02 + 2.86000E+02 2.85000E+02 1.90000E+02 1.89000E+02 9.40000E+01 9.30000E+01 + 1.42600E+03 1.42500E+03 1.33000E+03 1.32900E+03 1.23400E+03 1.23300E+03 + 1.13800E+03 1.13700E+03 1.04200E+03 1.04100E+03 9.46000E+02 9.45000E+02 + 8.50000E+02 8.49000E+02 7.54000E+02 7.53000E+02 6.58000E+02 6.57000E+02 + 5.62000E+02 5.61000E+02 4.66000E+02 4.65000E+02 3.70000E+02 3.69000E+02 + 2.74000E+02 2.73000E+02 1.78000E+02 1.77000E+02 8.20000E+01 8.10000E+01 + 1.41400E+03 1.41300E+03 1.31800E+03 1.31700E+03 1.22200E+03 1.22100E+03 + 1.12600E+03 1.12500E+03 1.03000E+03 1.02900E+03 9.34000E+02 9.33000E+02 + 8.38000E+02 8.37000E+02 7.42000E+02 7.41000E+02 6.46000E+02 6.45000E+02 + 5.50000E+02 5.49000E+02 4.54000E+02 4.53000E+02 3.58000E+02 3.57000E+02 + 2.62000E+02 2.61000E+02 1.66000E+02 1.65000E+02 7.00000E+01 6.90000E+01 + 1.40200E+03 1.40100E+03 1.30600E+03 1.30500E+03 1.21000E+03 1.20900E+03 + 1.11400E+03 1.11300E+03 1.01800E+03 1.01700E+03 9.22000E+02 9.21000E+02 + 8.26000E+02 8.25000E+02 7.30000E+02 7.29000E+02 6.34000E+02 6.33000E+02 + 5.38000E+02 5.37000E+02 4.42000E+02 4.41000E+02 3.46000E+02 3.45000E+02 + 2.50000E+02 2.49000E+02 1.54000E+02 1.53000E+02 5.80000E+01 5.70000E+01 + 1.39000E+03 1.38900E+03 1.29400E+03 1.29300E+03 1.19800E+03 1.19700E+03 + 1.10200E+03 1.10100E+03 1.00600E+03 1.00500E+03 9.10000E+02 9.09000E+02 + 8.14000E+02 8.13000E+02 7.18000E+02 7.17000E+02 6.22000E+02 6.21000E+02 + 5.26000E+02 5.25000E+02 4.30000E+02 4.29000E+02 3.34000E+02 3.33000E+02 + 2.38000E+02 2.37000E+02 1.42000E+02 1.41000E+02 4.60000E+01 4.50000E+01 + 1.37800E+03 1.37700E+03 1.28200E+03 1.28100E+03 1.18600E+03 1.18500E+03 + 1.09000E+03 1.08900E+03 9.94000E+02 9.93000E+02 8.98000E+02 8.97000E+02 + 8.02000E+02 8.01000E+02 7.06000E+02 7.05000E+02 6.10000E+02 6.09000E+02 + 5.14000E+02 5.13000E+02 4.18000E+02 4.17000E+02 3.22000E+02 3.21000E+02 + 2.26000E+02 2.25000E+02 1.30000E+02 1.29000E+02 3.40000E+01 3.30000E+01 + 1.36600E+03 1.36500E+03 1.27000E+03 1.26900E+03 1.17400E+03 1.17300E+03 + 1.07800E+03 1.07700E+03 9.82000E+02 9.81000E+02 8.86000E+02 8.85000E+02 + 7.90000E+02 7.89000E+02 6.94000E+02 6.93000E+02 5.98000E+02 5.97000E+02 + 5.02000E+02 5.01000E+02 4.06000E+02 4.05000E+02 3.10000E+02 3.09000E+02 + 2.14000E+02 2.13000E+02 1.18000E+02 1.17000E+02 2.20000E+01 2.10000E+01 + 1.35400E+03 1.35300E+03 1.25800E+03 1.25700E+03 1.16200E+03 1.16100E+03 + 1.06600E+03 1.06500E+03 9.70000E+02 9.69000E+02 8.74000E+02 8.73000E+02 + 7.78000E+02 7.77000E+02 6.82000E+02 6.81000E+02 5.86000E+02 5.85000E+02 + 4.90000E+02 4.89000E+02 3.94000E+02 3.93000E+02 2.98000E+02 2.97000E+02 + 2.02000E+02 2.01000E+02 1.06000E+02 1.05000E+02 1.00000E+01 9.00000E+00 + 1.43600E+03 1.43500E+03 1.34000E+03 1.33900E+03 1.24400E+03 1.24300E+03 + 1.14800E+03 1.14700E+03 1.05200E+03 1.05100E+03 9.56000E+02 9.55000E+02 + 8.60000E+02 8.59000E+02 7.64000E+02 7.63000E+02 6.68000E+02 6.67000E+02 + 5.72000E+02 5.71000E+02 4.76000E+02 4.75000E+02 3.80000E+02 3.79000E+02 + 2.84000E+02 2.83000E+02 1.88000E+02 1.87000E+02 9.20000E+01 9.10000E+01 + 1.42400E+03 1.42300E+03 1.32800E+03 1.32700E+03 1.23200E+03 1.23100E+03 + 1.13600E+03 1.13500E+03 1.04000E+03 1.03900E+03 9.44000E+02 9.43000E+02 + 8.48000E+02 8.47000E+02 7.52000E+02 7.51000E+02 6.56000E+02 6.55000E+02 + 5.60000E+02 5.59000E+02 4.64000E+02 4.63000E+02 3.68000E+02 3.67000E+02 + 2.72000E+02 2.71000E+02 1.76000E+02 1.75000E+02 8.00000E+01 7.90000E+01 + 1.41200E+03 1.41100E+03 1.31600E+03 1.31500E+03 1.22000E+03 1.21900E+03 + 1.12400E+03 1.12300E+03 1.02800E+03 1.02700E+03 9.32000E+02 9.31000E+02 + 8.36000E+02 8.35000E+02 7.40000E+02 7.39000E+02 6.44000E+02 6.43000E+02 + 5.48000E+02 5.47000E+02 4.52000E+02 4.51000E+02 3.56000E+02 3.55000E+02 + 2.60000E+02 2.59000E+02 1.64000E+02 1.63000E+02 6.80000E+01 6.70000E+01 + 1.40000E+03 1.39900E+03 1.30400E+03 1.30300E+03 1.20800E+03 1.20700E+03 + 1.11200E+03 1.11100E+03 1.01600E+03 1.01500E+03 9.20000E+02 9.19000E+02 + 8.24000E+02 8.23000E+02 7.28000E+02 7.27000E+02 6.32000E+02 6.31000E+02 + 5.36000E+02 5.35000E+02 4.40000E+02 4.39000E+02 3.44000E+02 3.43000E+02 + 2.48000E+02 2.47000E+02 1.52000E+02 1.51000E+02 5.60000E+01 5.50000E+01 + 1.38800E+03 1.38700E+03 1.29200E+03 1.29100E+03 1.19600E+03 1.19500E+03 + 1.10000E+03 1.09900E+03 1.00400E+03 1.00300E+03 9.08000E+02 9.07000E+02 + 8.12000E+02 8.11000E+02 7.16000E+02 7.15000E+02 6.20000E+02 6.19000E+02 + 5.24000E+02 5.23000E+02 4.28000E+02 4.27000E+02 3.32000E+02 3.31000E+02 + 2.36000E+02 2.35000E+02 1.40000E+02 1.39000E+02 4.40000E+01 4.30000E+01 + 1.37600E+03 1.37500E+03 1.28000E+03 1.27900E+03 1.18400E+03 1.18300E+03 + 1.08800E+03 1.08700E+03 9.92000E+02 9.91000E+02 8.96000E+02 8.95000E+02 + 8.00000E+02 7.99000E+02 7.04000E+02 7.03000E+02 6.08000E+02 6.07000E+02 + 5.12000E+02 5.11000E+02 4.16000E+02 4.15000E+02 3.20000E+02 3.19000E+02 + 2.24000E+02 2.23000E+02 1.28000E+02 1.27000E+02 3.20000E+01 3.10000E+01 + 1.36400E+03 1.36300E+03 1.26800E+03 1.26700E+03 1.17200E+03 1.17100E+03 + 1.07600E+03 1.07500E+03 9.80000E+02 9.79000E+02 8.84000E+02 8.83000E+02 + 7.88000E+02 7.87000E+02 6.92000E+02 6.91000E+02 5.96000E+02 5.95000E+02 + 5.00000E+02 4.99000E+02 4.04000E+02 4.03000E+02 3.08000E+02 3.07000E+02 + 2.12000E+02 2.11000E+02 1.16000E+02 1.15000E+02 2.00000E+01 1.90000E+01 + 1.35200E+03 1.35100E+03 1.25600E+03 1.25500E+03 1.16000E+03 1.15900E+03 + 1.06400E+03 1.06300E+03 9.68000E+02 9.67000E+02 8.72000E+02 8.71000E+02 + 7.76000E+02 7.75000E+02 6.80000E+02 6.79000E+02 5.84000E+02 5.83000E+02 + 4.88000E+02 4.87000E+02 3.92000E+02 3.91000E+02 2.96000E+02 2.95000E+02 + 2.00000E+02 1.99000E+02 1.04000E+02 1.03000E+02 8.00000E+00 7.00000E+00 + 1.43400E+03 1.43300E+03 1.33800E+03 1.33700E+03 1.24200E+03 1.24100E+03 + 1.14600E+03 1.14500E+03 1.05000E+03 1.04900E+03 9.54000E+02 9.53000E+02 + 8.58000E+02 8.57000E+02 7.62000E+02 7.61000E+02 6.66000E+02 6.65000E+02 + 5.70000E+02 5.69000E+02 4.74000E+02 4.73000E+02 3.78000E+02 3.77000E+02 + 2.82000E+02 2.81000E+02 1.86000E+02 1.85000E+02 9.00000E+01 8.90000E+01 + 1.42200E+03 1.42100E+03 1.32600E+03 1.32500E+03 1.23000E+03 1.22900E+03 + 1.13400E+03 1.13300E+03 1.03800E+03 1.03700E+03 9.42000E+02 9.41000E+02 + 8.46000E+02 8.45000E+02 7.50000E+02 7.49000E+02 6.54000E+02 6.53000E+02 + 5.58000E+02 5.57000E+02 4.62000E+02 4.61000E+02 3.66000E+02 3.65000E+02 + 2.70000E+02 2.69000E+02 1.74000E+02 1.73000E+02 7.80000E+01 7.70000E+01 + 1.41000E+03 1.40900E+03 1.31400E+03 1.31300E+03 1.21800E+03 1.21700E+03 + 1.12200E+03 1.12100E+03 1.02600E+03 1.02500E+03 9.30000E+02 9.29000E+02 + 8.34000E+02 8.33000E+02 7.38000E+02 7.37000E+02 6.42000E+02 6.41000E+02 + 5.46000E+02 5.45000E+02 4.50000E+02 4.49000E+02 3.54000E+02 3.53000E+02 + 2.58000E+02 2.57000E+02 1.62000E+02 1.61000E+02 6.60000E+01 6.50000E+01 + 1.39800E+03 1.39700E+03 1.30200E+03 1.30100E+03 1.20600E+03 1.20500E+03 + 1.11000E+03 1.10900E+03 1.01400E+03 1.01300E+03 9.18000E+02 9.17000E+02 + 8.22000E+02 8.21000E+02 7.26000E+02 7.25000E+02 6.30000E+02 6.29000E+02 + 5.34000E+02 5.33000E+02 4.38000E+02 4.37000E+02 3.42000E+02 3.41000E+02 + 2.46000E+02 2.45000E+02 1.50000E+02 1.49000E+02 5.40000E+01 5.30000E+01 + 1.38600E+03 1.38500E+03 1.29000E+03 1.28900E+03 1.19400E+03 1.19300E+03 + 1.09800E+03 1.09700E+03 1.00200E+03 1.00100E+03 9.06000E+02 9.05000E+02 + 8.10000E+02 8.09000E+02 7.14000E+02 7.13000E+02 6.18000E+02 6.17000E+02 + 5.22000E+02 5.21000E+02 4.26000E+02 4.25000E+02 3.30000E+02 3.29000E+02 + 2.34000E+02 2.33000E+02 1.38000E+02 1.37000E+02 4.20000E+01 4.10000E+01 + 1.37400E+03 1.37300E+03 1.27800E+03 1.27700E+03 1.18200E+03 1.18100E+03 + 1.08600E+03 1.08500E+03 9.90000E+02 9.89000E+02 8.94000E+02 8.93000E+02 + 7.98000E+02 7.97000E+02 7.02000E+02 7.01000E+02 6.06000E+02 6.05000E+02 + 5.10000E+02 5.09000E+02 4.14000E+02 4.13000E+02 3.18000E+02 3.17000E+02 + 2.22000E+02 2.21000E+02 1.26000E+02 1.25000E+02 3.00000E+01 2.90000E+01 + 1.36200E+03 1.36100E+03 1.26600E+03 1.26500E+03 1.17000E+03 1.16900E+03 + 1.07400E+03 1.07300E+03 9.78000E+02 9.77000E+02 8.82000E+02 8.81000E+02 + 7.86000E+02 7.85000E+02 6.90000E+02 6.89000E+02 5.94000E+02 5.93000E+02 + 4.98000E+02 4.97000E+02 4.02000E+02 4.01000E+02 3.06000E+02 3.05000E+02 + 2.10000E+02 2.09000E+02 1.14000E+02 1.13000E+02 1.80000E+01 1.70000E+01 + 1.35000E+03 1.34900E+03 1.25400E+03 1.25300E+03 1.15800E+03 1.15700E+03 + 1.06200E+03 1.06100E+03 9.66000E+02 9.65000E+02 8.70000E+02 8.69000E+02 + 7.74000E+02 7.73000E+02 6.78000E+02 6.77000E+02 5.82000E+02 5.81000E+02 + 4.86000E+02 4.85000E+02 3.90000E+02 3.89000E+02 2.94000E+02 2.93000E+02 + 1.98000E+02 1.97000E+02 1.02000E+02 1.01000E+02 6.00000E+00 5.00000E+00 + 1.43200E+03 1.43100E+03 1.33600E+03 1.33500E+03 1.24000E+03 1.23900E+03 + 1.14400E+03 1.14300E+03 1.04800E+03 1.04700E+03 9.52000E+02 9.51000E+02 + 8.56000E+02 8.55000E+02 7.60000E+02 7.59000E+02 6.64000E+02 6.63000E+02 + 5.68000E+02 5.67000E+02 4.72000E+02 4.71000E+02 3.76000E+02 3.75000E+02 + 2.80000E+02 2.79000E+02 1.84000E+02 1.83000E+02 8.80000E+01 8.70000E+01 + 1.42000E+03 1.41900E+03 1.32400E+03 1.32300E+03 1.22800E+03 1.22700E+03 + 1.13200E+03 1.13100E+03 1.03600E+03 1.03500E+03 9.40000E+02 9.39000E+02 + 8.44000E+02 8.43000E+02 7.48000E+02 7.47000E+02 6.52000E+02 6.51000E+02 + 5.56000E+02 5.55000E+02 4.60000E+02 4.59000E+02 3.64000E+02 3.63000E+02 + 2.68000E+02 2.67000E+02 1.72000E+02 1.71000E+02 7.60000E+01 7.50000E+01 + 1.40800E+03 1.40700E+03 1.31200E+03 1.31100E+03 1.21600E+03 1.21500E+03 + 1.12000E+03 1.11900E+03 1.02400E+03 1.02300E+03 9.28000E+02 9.27000E+02 + 8.32000E+02 8.31000E+02 7.36000E+02 7.35000E+02 6.40000E+02 6.39000E+02 + 5.44000E+02 5.43000E+02 4.48000E+02 4.47000E+02 3.52000E+02 3.51000E+02 + 2.56000E+02 2.55000E+02 1.60000E+02 1.59000E+02 6.40000E+01 6.30000E+01 + 1.39600E+03 1.39500E+03 1.30000E+03 1.29900E+03 1.20400E+03 1.20300E+03 + 1.10800E+03 1.10700E+03 1.01200E+03 1.01100E+03 9.16000E+02 9.15000E+02 + 8.20000E+02 8.19000E+02 7.24000E+02 7.23000E+02 6.28000E+02 6.27000E+02 + 5.32000E+02 5.31000E+02 4.36000E+02 4.35000E+02 3.40000E+02 3.39000E+02 + 2.44000E+02 2.43000E+02 1.48000E+02 1.47000E+02 5.20000E+01 5.10000E+01 + 1.38400E+03 1.38300E+03 1.28800E+03 1.28700E+03 1.19200E+03 1.19100E+03 + 1.09600E+03 1.09500E+03 1.00000E+03 9.99000E+02 9.04000E+02 9.03000E+02 + 8.08000E+02 8.07000E+02 7.12000E+02 7.11000E+02 6.16000E+02 6.15000E+02 + 5.20000E+02 5.19000E+02 4.24000E+02 4.23000E+02 3.28000E+02 3.27000E+02 + 2.32000E+02 2.31000E+02 1.36000E+02 1.35000E+02 4.00000E+01 3.90000E+01 + 1.37200E+03 1.37100E+03 1.27600E+03 1.27500E+03 1.18000E+03 1.17900E+03 + 1.08400E+03 1.08300E+03 9.88000E+02 9.87000E+02 8.92000E+02 8.91000E+02 + 7.96000E+02 7.95000E+02 7.00000E+02 6.99000E+02 6.04000E+02 6.03000E+02 + 5.08000E+02 5.07000E+02 4.12000E+02 4.11000E+02 3.16000E+02 3.15000E+02 + 2.20000E+02 2.19000E+02 1.24000E+02 1.23000E+02 2.80000E+01 2.70000E+01 + 1.36000E+03 1.35900E+03 1.26400E+03 1.26300E+03 1.16800E+03 1.16700E+03 + 1.07200E+03 1.07100E+03 9.76000E+02 9.75000E+02 8.80000E+02 8.79000E+02 + 7.84000E+02 7.83000E+02 6.88000E+02 6.87000E+02 5.92000E+02 5.91000E+02 + 4.96000E+02 4.95000E+02 4.00000E+02 3.99000E+02 3.04000E+02 3.03000E+02 + 2.08000E+02 2.07000E+02 1.12000E+02 1.11000E+02 1.60000E+01 1.50000E+01 + 1.34800E+03 1.34700E+03 1.25200E+03 1.25100E+03 1.15600E+03 1.15500E+03 + 1.06000E+03 1.05900E+03 9.64000E+02 9.63000E+02 8.68000E+02 8.67000E+02 + 7.72000E+02 7.71000E+02 6.76000E+02 6.75000E+02 5.80000E+02 5.79000E+02 + 4.84000E+02 4.83000E+02 3.88000E+02 3.87000E+02 2.92000E+02 2.91000E+02 + 1.96000E+02 1.95000E+02 1.00000E+02 9.90000E+01 4.00000E+00 3.00000E+00 + 1.43000E+03 1.42900E+03 1.33400E+03 1.33300E+03 1.23800E+03 1.23700E+03 + 1.14200E+03 1.14100E+03 1.04600E+03 1.04500E+03 9.50000E+02 9.49000E+02 + 8.54000E+02 8.53000E+02 7.58000E+02 7.57000E+02 6.62000E+02 6.61000E+02 + 5.66000E+02 5.65000E+02 4.70000E+02 4.69000E+02 3.74000E+02 3.73000E+02 + 2.78000E+02 2.77000E+02 1.82000E+02 1.81000E+02 8.60000E+01 8.50000E+01 + 1.41800E+03 1.41700E+03 1.32200E+03 1.32100E+03 1.22600E+03 1.22500E+03 + 1.13000E+03 1.12900E+03 1.03400E+03 1.03300E+03 9.38000E+02 9.37000E+02 + 8.42000E+02 8.41000E+02 7.46000E+02 7.45000E+02 6.50000E+02 6.49000E+02 + 5.54000E+02 5.53000E+02 4.58000E+02 4.57000E+02 3.62000E+02 3.61000E+02 + 2.66000E+02 2.65000E+02 1.70000E+02 1.69000E+02 7.40000E+01 7.30000E+01 + 1.40600E+03 1.40500E+03 1.31000E+03 1.30900E+03 1.21400E+03 1.21300E+03 + 1.11800E+03 1.11700E+03 1.02200E+03 1.02100E+03 9.26000E+02 9.25000E+02 + 8.30000E+02 8.29000E+02 7.34000E+02 7.33000E+02 6.38000E+02 6.37000E+02 + 5.42000E+02 5.41000E+02 4.46000E+02 4.45000E+02 3.50000E+02 3.49000E+02 + 2.54000E+02 2.53000E+02 1.58000E+02 1.57000E+02 6.20000E+01 6.10000E+01 + 1.39400E+03 1.39300E+03 1.29800E+03 1.29700E+03 1.20200E+03 1.20100E+03 + 1.10600E+03 1.10500E+03 1.01000E+03 1.00900E+03 9.14000E+02 9.13000E+02 + 8.18000E+02 8.17000E+02 7.22000E+02 7.21000E+02 6.26000E+02 6.25000E+02 + 5.30000E+02 5.29000E+02 4.34000E+02 4.33000E+02 3.38000E+02 3.37000E+02 + 2.42000E+02 2.41000E+02 1.46000E+02 1.45000E+02 5.00000E+01 4.90000E+01 + 1.38200E+03 1.38100E+03 1.28600E+03 1.28500E+03 1.19000E+03 1.18900E+03 + 1.09400E+03 1.09300E+03 9.98000E+02 9.97000E+02 9.02000E+02 9.01000E+02 + 8.06000E+02 8.05000E+02 7.10000E+02 7.09000E+02 6.14000E+02 6.13000E+02 + 5.18000E+02 5.17000E+02 4.22000E+02 4.21000E+02 3.26000E+02 3.25000E+02 + 2.30000E+02 2.29000E+02 1.34000E+02 1.33000E+02 3.80000E+01 3.70000E+01 + 1.37000E+03 1.36900E+03 1.27400E+03 1.27300E+03 1.17800E+03 1.17700E+03 + 1.08200E+03 1.08100E+03 9.86000E+02 9.85000E+02 8.90000E+02 8.89000E+02 + 7.94000E+02 7.93000E+02 6.98000E+02 6.97000E+02 6.02000E+02 6.01000E+02 + 5.06000E+02 5.05000E+02 4.10000E+02 4.09000E+02 3.14000E+02 3.13000E+02 + 2.18000E+02 2.17000E+02 1.22000E+02 1.21000E+02 2.60000E+01 2.50000E+01 + 1.35800E+03 1.35700E+03 1.26200E+03 1.26100E+03 1.16600E+03 1.16500E+03 + 1.07000E+03 1.06900E+03 9.74000E+02 9.73000E+02 8.78000E+02 8.77000E+02 + 7.82000E+02 7.81000E+02 6.86000E+02 6.85000E+02 5.90000E+02 5.89000E+02 + 4.94000E+02 4.93000E+02 3.98000E+02 3.97000E+02 3.02000E+02 3.01000E+02 + 2.06000E+02 2.05000E+02 1.10000E+02 1.09000E+02 1.40000E+01 1.30000E+01 + 1.34600E+03 1.34500E+03 1.25000E+03 1.24900E+03 1.15400E+03 1.15300E+03 + 1.05800E+03 1.05700E+03 9.62000E+02 9.61000E+02 8.66000E+02 8.65000E+02 + 7.70000E+02 7.69000E+02 6.74000E+02 6.73000E+02 5.78000E+02 5.77000E+02 + 4.82000E+02 4.81000E+02 3.86000E+02 3.85000E+02 2.90000E+02 2.89000E+02 + 1.94000E+02 1.93000E+02 9.80000E+01 9.70000E+01 2.00000E+00 1.00000E+00 + diff --git a/tests/unit_tests/weightwindows/wwinp_np b/tests/unit_tests/weightwindows/wwinp_np new file mode 100644 index 000000000..6d77afc3e --- /dev/null +++ b/tests/unit_tests/weightwindows/wwinp_np @@ -0,0 +1,48 @@ + 1 1 2 10 + 3 1 + 1.0 8.0 6.0 -1.00000E+02 -1.00000E+02 -1.00000E+02 + 1.0 8.0 6.0 1.0 + -1.00000E+02 1.00000E+00 1.00000E+02 1.00000E+00 + -1.00000E+02 1.00000E+00 -5.00000E+01 1.00000E+00 1.00000E+00 -1.33333E+01 + 1.00000E+00 1.00000E+00 2.33333E+01 1.00000E+00 1.00000E+00 6.00000E+01 + 1.00000E+00 1.00000E+00 7.00000E+01 1.00000E+00 1.00000E+00 8.00000E+01 + 1.00000E+00 1.00000E+00 9.00000E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -1.00000E+02 1.00000E+00 -6.66667E+01 1.00000E+00 1.00000E+00 -3.33333E+01 + 1.00000E+00 1.00000E+00 0.00000E+00 1.00000E+00 1.00000E+00 3.33333E+01 + 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + 1.00000E-01 1.46780E-01 2.15440E-01 + 1.44000E+02 1.43000E+02 1.42000E+02 1.26000E+02 1.25000E+02 1.24000E+02 + 1.08000E+02 1.07000E+02 1.06000E+02 9.00000E+01 8.90000E+01 8.80000E+01 + 7.20000E+01 7.10000E+01 7.00000E+01 5.40000E+01 5.30000E+01 5.20000E+01 + 3.60000E+01 3.50000E+01 3.40000E+01 1.80000E+01 1.70000E+01 1.60000E+01 + 1.41000E+02 1.40000E+02 1.39000E+02 1.23000E+02 1.22000E+02 1.21000E+02 + 1.05000E+02 1.04000E+02 1.03000E+02 8.70000E+01 8.60000E+01 8.50000E+01 + 6.90000E+01 6.80000E+01 6.70000E+01 5.10000E+01 5.00000E+01 4.90000E+01 + 3.30000E+01 3.20000E+01 3.10000E+01 1.50000E+01 1.40000E+01 1.30000E+01 + 1.38000E+02 1.37000E+02 1.36000E+02 1.20000E+02 1.19000E+02 1.18000E+02 + 1.02000E+02 1.01000E+02 1.00000E+02 8.40000E+01 8.30000E+01 8.20000E+01 + 6.60000E+01 6.50000E+01 6.40000E+01 4.80000E+01 4.70000E+01 4.60000E+01 + 3.00000E+01 2.90000E+01 2.80000E+01 1.20000E+01 1.10000E+01 1.00000E+01 + 1.35000E+02 1.34000E+02 1.33000E+02 1.17000E+02 1.16000E+02 1.15000E+02 + 9.90000E+01 9.80000E+01 9.70000E+01 8.10000E+01 8.00000E+01 7.90000E+01 + 6.30000E+01 6.20000E+01 6.10000E+01 4.50000E+01 4.40000E+01 4.30000E+01 + 2.70000E+01 2.60000E+01 2.50000E+01 9.00000E+00 8.00000E+00 7.00000E+00 + 1.32000E+02 1.31000E+02 1.30000E+02 1.14000E+02 1.13000E+02 1.12000E+02 + 9.60000E+01 9.50000E+01 9.40000E+01 7.80000E+01 7.70000E+01 7.60000E+01 + 6.00000E+01 5.90000E+01 5.80000E+01 4.20000E+01 4.10000E+01 4.00000E+01 + 2.40000E+01 2.30000E+01 2.20000E+01 6.00000E+00 5.00000E+00 4.00000E+00 + 1.29000E+02 1.28000E+02 1.27000E+02 1.11000E+02 1.10000E+02 1.09000E+02 + 9.30000E+01 9.20000E+01 9.10000E+01 7.50000E+01 7.40000E+01 7.30000E+01 + 5.70000E+01 5.60000E+01 5.50000E+01 3.90000E+01 3.80000E+01 3.70000E+01 + 2.10000E+01 2.00000E+01 1.90000E+01 3.00000E+00 2.00000E+00 1.00000E+00 + 1.00000E+02 + 4.80000E+01 4.20000E+01 3.60000E+01 3.00000E+01 2.40000E+01 1.80000E+01 + 1.20000E+01 6.00000E+00 4.70000E+01 4.10000E+01 3.50000E+01 2.90000E+01 + 2.30000E+01 1.70000E+01 1.10000E+01 5.00000E+00 4.60000E+01 4.00000E+01 + 3.40000E+01 2.80000E+01 2.20000E+01 1.60000E+01 1.00000E+01 4.00000E+00 + 4.50000E+01 3.90000E+01 3.30000E+01 2.70000E+01 2.10000E+01 1.50000E+01 + 9.00000E+00 3.00000E+00 4.40000E+01 3.80000E+01 3.20000E+01 2.60000E+01 + 2.00000E+01 1.40000E+01 8.00000E+00 2.00000E+00 4.30000E+01 3.70000E+01 + 3.10000E+01 2.50000E+01 1.90000E+01 1.30000E+01 7.00000E+00 1.00000E+00 diff --git a/tests/unit_tests/weightwindows/wwinp_p b/tests/unit_tests/weightwindows/wwinp_p new file mode 100644 index 000000000..95315692f --- /dev/null +++ b/tests/unit_tests/weightwindows/wwinp_p @@ -0,0 +1,48 @@ + 1 1 2 10 + 0 4 + 6.0 8.0 1.0 -1.00000E+02 -1.00000E+02 -5.00000E+01 + 6.0 8.0 1.0 1.0 + -1.00000E+02 1.00000E+00 -6.66667E+01 1.00000E+00 1.00000E+00 -3.33333E+01 + 1.00000E+00 1.00000E+00 0.00000E+00 1.00000E+00 1.00000E+00 3.33333E+01 + 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -1.00000E+02 1.00000E+00 -5.00000E+01 1.00000E+00 1.00000E+00 -1.33333E+01 + 1.00000E+00 1.00000E+00 2.33333E+01 1.00000E+00 1.00000E+00 6.00000E+01 + 1.00000E+00 1.00000E+00 7.00000E+01 1.00000E+00 1.00000E+00 8.00000E+01 + 1.00000E+00 1.00000E+00 9.00000E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -5.00000E+01 1.00000E+00 5.00000E+01 1.00000E+00 + 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 + 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 + 1.58000E+02 1.57000E+02 1.28000E+02 1.27000E+02 1.26000E+02 1.25000E+02 + 9.60000E+01 9.50000E+01 9.40000E+01 9.30000E+01 6.40000E+01 6.30000E+01 + 6.20000E+01 6.10000E+01 3.20000E+01 3.10000E+01 3.00000E+01 2.90000E+01 + 1.88000E+02 1.87000E+02 1.86000E+02 1.85000E+02 1.56000E+02 1.55000E+02 + 1.54000E+02 1.53000E+02 1.24000E+02 1.23000E+02 1.22000E+02 1.21000E+02 + 9.20000E+01 9.10000E+01 9.00000E+01 8.90000E+01 6.00000E+01 5.90000E+01 + 5.80000E+01 5.70000E+01 2.80000E+01 2.70000E+01 2.60000E+01 2.50000E+01 + 1.84000E+02 1.83000E+02 1.82000E+02 1.81000E+02 1.52000E+02 1.51000E+02 + 1.50000E+02 1.49000E+02 1.20000E+02 1.19000E+02 1.18000E+02 1.17000E+02 + 8.80000E+01 8.70000E+01 8.60000E+01 8.50000E+01 5.60000E+01 5.50000E+01 + 5.40000E+01 5.30000E+01 2.40000E+01 2.30000E+01 2.20000E+01 2.10000E+01 + 1.80000E+02 1.79000E+02 1.78000E+02 1.77000E+02 1.48000E+02 1.47000E+02 + 1.46000E+02 1.45000E+02 1.16000E+02 1.15000E+02 1.14000E+02 1.13000E+02 + 8.40000E+01 8.30000E+01 8.20000E+01 8.10000E+01 5.20000E+01 5.10000E+01 + 5.00000E+01 4.90000E+01 2.00000E+01 1.90000E+01 1.80000E+01 1.70000E+01 + 1.76000E+02 1.75000E+02 1.74000E+02 1.73000E+02 1.44000E+02 1.43000E+02 + 1.42000E+02 1.41000E+02 1.12000E+02 1.11000E+02 1.10000E+02 1.09000E+02 + 8.00000E+01 7.90000E+01 7.80000E+01 7.70000E+01 4.80000E+01 4.70000E+01 + 4.60000E+01 4.50000E+01 1.60000E+01 1.50000E+01 1.40000E+01 1.30000E+01 + 1.72000E+02 1.71000E+02 1.70000E+02 1.69000E+02 1.40000E+02 1.39000E+02 + 1.38000E+02 1.37000E+02 1.08000E+02 1.07000E+02 1.06000E+02 1.05000E+02 + 7.60000E+01 7.50000E+01 7.40000E+01 7.30000E+01 4.40000E+01 4.30000E+01 + 4.20000E+01 4.10000E+01 1.20000E+01 1.10000E+01 1.00000E+01 9.00000E+00 + 1.68000E+02 1.67000E+02 1.66000E+02 1.65000E+02 1.36000E+02 1.35000E+02 + 1.34000E+02 1.33000E+02 1.04000E+02 1.03000E+02 1.02000E+02 1.01000E+02 + 7.20000E+01 7.10000E+01 7.00000E+01 6.90000E+01 4.00000E+01 3.90000E+01 + 3.80000E+01 3.70000E+01 8.00000E+00 7.00000E+00 6.00000E+00 5.00000E+00 + 1.64000E+02 1.63000E+02 1.62000E+02 1.61000E+02 1.32000E+02 1.31000E+02 + 1.30000E+02 1.29000E+02 1.00000E+02 9.90000E+01 9.80000E+01 9.70000E+01 + 6.80000E+01 6.70000E+01 6.60000E+01 6.50000E+01 3.60000E+01 3.50000E+01 + 3.40000E+01 3.30000E+01 4.00000E+00 3.00000E+00 2.00000E+00 1.00000E+00 + From 7b8bc4ae9041c55c97f6295581be6f2a40f984d5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 10 Mar 2022 15:20:40 -0600 Subject: [PATCH 0083/2654] Updating comments --- openmc/weight_windows.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 4dabe2a1f..197a01eb7 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -570,21 +570,20 @@ def wwinp_to_wws(path): e_bounds *= 1E6 # create an array for weight window lower bounds + # # MCNP ordering for weight windows matches that of OpenMC + # # ('xyz' with x changing fastest) ww_lb = np.zeros((*mesh.dimension, ne)) for ijk in mesh.indices: idx = tuple([v - 1 for v in ijk] + [slice(None)]) ww_lb[idx] = [float(next(wwinp)) for _ in range(ne)] - # for e in range(ne): - # # MCNP ordering for weight windows matches that of OpenMC - # # ('xyz' with x changing fastest) - # ww_vals = [float(next(wwinp)) for _ in range(n_elements)] - # ww_lb[e, :] = np.asarray(ww_vals).reshape(mesh.dimension) - settings = WeightWindows(id=None, - mesh=mesh, - lower_ww_bounds=ww_lb.flatten(), - upper_bound_ratio=5.0, - energy_bins=e_bounds, - particle_type=particle) - wws.append(settings) + + # create a WeightWindows object and add it to the output list + ww = WeightWindows(id=None, + mesh=mesh, + lower_ww_bounds=ww_lb.flatten(), + upper_bound_ratio=5.0, + energy_bins=e_bounds, + particle_type=particle) + wws.append(ww) return wws \ No newline at end of file From fe6920afb146d704c29d4695a16381e1d4ca3205 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:13:22 -0600 Subject: [PATCH 0084/2654] Updates to mesh boundaries for MCNP compliant format in test files --- .../weightwindows/test_wwinp_reader.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index 910c0e912..666c332ec 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -20,34 +20,34 @@ n_mesh = openmc.RectilinearMesh() n_mesh.x_grid = np.asarray([-100.0, -99.0, -97.0, - -79.36364, - -61.72727, - -44.09091, - -26.45455, - -8.818182, - 8.818182, - 26.45455, - 44.09091, - 61.72727, - 79.36364, + -79.3636, + -61.7273, + -44.0909, + -26.4546, + -8.81818, + 8.81818, + 26.4546, + 44.0909, + 61.7273, + 79.3636, 97.0, 99.0, 100]) n_mesh.y_grid = np.asarray([-100.0, -50.0, - -13.33333, - 23.33333, + -13.3333, + 23.3333, 60.0, 70.0, 80.0, 90.0, 100.0]) n_mesh.z_grid = np.asarray([-100.0, - -66.66667, - -33.33333, + -66.6667, + -33.3333, 0.0, - 33.33333, - 66.66667, + 33.3333, + 66.6667, 100.0]) n_e_bounds = np.asarray([0.0, 100000.0, From 7ed72b73fa959f0f614d7cf6e6bd9a66dae87ead Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:21:23 -0600 Subject: [PATCH 0085/2654] PEP8 updates for test file --- .../weightwindows/test_wwinp_reader.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index 666c332ec..faf29e60d 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -49,9 +49,10 @@ n_mesh.z_grid = np.asarray([-100.0, 33.3333, 66.6667, 100.0]) -n_e_bounds = np.asarray([0.0, +n_e_bounds = (np.asarray([0.0, 100000.0, - 146780.0]) + 146780.0]),) +n_particles = ('neutron',) # expected results - neutron and photon data np_mesh = openmc.RectilinearMesh() @@ -60,8 +61,9 @@ np_mesh.x_grid = np.asarray([-100.0, 100.0]) np_mesh.y_grid = n_mesh.y_grid np_mesh.z_grid = n_mesh.z_grid -np_n_e_bounds = np.asarray([0.0, 100000.0, 146780.0, 215440.0]) -np_p_e_bounds = np.asarray([0.0, 1.0E8]) +np_e_bounds = (np.asarray([0.0, 100000.0, 146780.0, 215440.0]), + np.asarray([0.0, 1.0E8])) +np_particles = ('neutron', 'photon') # expected results - photon data only p_mesh = openmc.RectilinearMesh() @@ -71,11 +73,13 @@ p_mesh.x_grid = np_mesh.z_grid p_mesh.y_grid = np_mesh.y_grid p_mesh.z_grid = np.asarray([-50.0, 50.0]) -p_e_bounds = np.asarray([0.0, 100000.0, 146780.0, 215440.0, 316230.0]) +p_e_bounds = (np.asarray([0.0, 100000.0, 146780.0, 215440.0, 316230.0]),) +p_particles = ('photon',) + +expected_results = [('wwinp_n', n_mesh, n_particles, n_e_bounds), + ('wwinp_np', np_mesh, np_particles, np_e_bounds), + ('wwinp_p', p_mesh, p_particles, p_e_bounds)] -expected_results = [('wwinp_n', n_mesh, ('neutron',), (n_e_bounds,)), - ('wwinp_np', np_mesh, ('neutron', 'photon'), (np_n_e_bounds, np_p_e_bounds)), - ('wwinp_p', p_mesh, ('photon',), (p_e_bounds,))] def id_fn(params): suffix = params[0].split('_')[-1] From 3301c50d0ee3c5a2ce9dc8c52be8ad83eafe7fae Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:23:27 -0600 Subject: [PATCH 0086/2654] PEP8 updates for weight_windows module --- openmc/weight_windows.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 197a01eb7..f878f618b 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -463,7 +463,8 @@ def wwinp_to_wws(path): # check time parameter, iv if int(float(next(wwinp))) > 1: - raise ValueError('Time-dependent weight windows are not yet supported.') + raise ValueError('Time-dependent weight windows ' + 'are not yet supported.') # number of particle types, ni n_particle_types = int(float(next(wwinp))) @@ -475,7 +476,8 @@ def wwinp_to_wws(path): if mesh_chars != 10: # TODO: read the first entry by default and display a warning - raise ValueError('Cylindrical and Spherical meshes are not currently supported') + raise ValueError('Cylindrical and Spherical meshes ' + 'are not currently supported') # read the number of energy groups for each particle, ne n_egroups = [int(next(wwinp)) for _ in range(n_particle_types)] @@ -490,7 +492,7 @@ def wwinp_to_wws(path): if n_particle_types > 2: msg = ('More than two particle types are present. ' - 'Only neutron and photon weight windows will be read.') + 'Only neutron and photon weight windows will be read.') warnings.warn(msg) # read total number of fine mesh elements in each coarse @@ -546,7 +548,7 @@ def wwinp_to_wws(path): for dim, header_val, mesh_val in zip(dims, llc, mesh_llc): if header_val != mesh_val: msg = ('The {} corner of the mesh ({}) does not match ' - 'the value read in block 1 of the wwinp file ({})') + 'the value read in block 1 of the wwinp file ({})') raise ValueError(msg.format(dim, mesh_val, header_val)) # check total number of mesh elements in each direction @@ -554,8 +556,8 @@ def wwinp_to_wws(path): for dim, header_val, mesh_val in zip(dims, header_mesh_dims, mesh_dims): if header_val != mesh_val: msg = ('Total number of mesh elements read in the {} ' - 'direction ({}) is inconsistent with the ' - 'number read in block 1 of the wwinp file ({})') + 'direction ({}) is inconsistent with the ' + 'number read in block 1 of the wwinp file ({})') raise ValueError(msg.format(dim, mesh_val, header_val)) # total number of fine mesh elements, nft @@ -586,4 +588,4 @@ def wwinp_to_wws(path): particle_type=particle) wws.append(ww) - return wws \ No newline at end of file + return wws From 4a0f32fc234099523eb0c2d425b0f34a4613937f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:28:07 -0600 Subject: [PATCH 0087/2654] Fixing ordering comment --- openmc/weight_windows.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index f878f618b..024637e93 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -572,10 +572,10 @@ def wwinp_to_wws(path): e_bounds *= 1E6 # create an array for weight window lower bounds - # # MCNP ordering for weight windows matches that of OpenMC - # # ('xyz' with x changing fastest) ww_lb = np.zeros((*mesh.dimension, ne)) for ijk in mesh.indices: + # MCNP ordering for weight windows matches that of OpenMC + # ('xyz' with x changing fastest) idx = tuple([v - 1 for v in ijk] + [slice(None)]) ww_lb[idx] = [float(next(wwinp)) for _ in range(ne)] From 6ddce789877b62dffb6c5ddd577bfcb5037dc9a3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:42:53 -0600 Subject: [PATCH 0088/2654] Adding test files for time-dependent and cylindrical mesh weight windows --- tests/unit_tests/weightwindows/wwinp_cyl | 47 ++++++++++++++++++++++++ tests/unit_tests/weightwindows/wwinp_t | 47 ++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 tests/unit_tests/weightwindows/wwinp_cyl create mode 100644 tests/unit_tests/weightwindows/wwinp_t diff --git a/tests/unit_tests/weightwindows/wwinp_cyl b/tests/unit_tests/weightwindows/wwinp_cyl new file mode 100644 index 000000000..391e4bcf6 --- /dev/null +++ b/tests/unit_tests/weightwindows/wwinp_cyl @@ -0,0 +1,47 @@ + 1 1 2 16 + 0 4 + 6.0 8.0 1.0 -1.00000E+02 -1.00000E+02 -5.00000E+01 + 6.0 8.0 1.0 1.0 + -1.00000E+02 1.00000E+00 -6.66667E+01 1.00000E+00 1.00000E+00 -3.33333E+01 + 1.00000E+00 1.00000E+00 0.00000E+00 1.00000E+00 1.00000E+00 3.33333E+01 + 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -1.00000E+02 1.00000E+00 -5.00000E+01 1.00000E+00 1.00000E+00 -1.33333E+01 + 1.00000E+00 1.00000E+00 2.33333E+01 1.00000E+00 1.00000E+00 6.00000E+01 + 1.00000E+00 1.00000E+00 7.00000E+01 1.00000E+00 1.00000E+00 8.00000E+01 + 1.00000E+00 1.00000E+00 9.00000E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -5.00000E+01 1.00000E+00 5.00000E+01 1.00000E+00 + 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 + 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 + 1.58000E+02 1.57000E+02 1.28000E+02 1.27000E+02 1.26000E+02 1.25000E+02 + 9.60000E+01 9.50000E+01 9.40000E+01 9.30000E+01 6.40000E+01 6.30000E+01 + 6.20000E+01 6.10000E+01 3.20000E+01 3.10000E+01 3.00000E+01 2.90000E+01 + 1.88000E+02 1.87000E+02 1.86000E+02 1.85000E+02 1.56000E+02 1.55000E+02 + 1.54000E+02 1.53000E+02 1.24000E+02 1.23000E+02 1.22000E+02 1.21000E+02 + 9.20000E+01 9.10000E+01 9.00000E+01 8.90000E+01 6.00000E+01 5.90000E+01 + 5.80000E+01 5.70000E+01 2.80000E+01 2.70000E+01 2.60000E+01 2.50000E+01 + 1.84000E+02 1.83000E+02 1.82000E+02 1.81000E+02 1.52000E+02 1.51000E+02 + 1.50000E+02 1.49000E+02 1.20000E+02 1.19000E+02 1.18000E+02 1.17000E+02 + 8.80000E+01 8.70000E+01 8.60000E+01 8.50000E+01 5.60000E+01 5.50000E+01 + 5.40000E+01 5.30000E+01 2.40000E+01 2.30000E+01 2.20000E+01 2.10000E+01 + 1.80000E+02 1.79000E+02 1.78000E+02 1.77000E+02 1.48000E+02 1.47000E+02 + 1.46000E+02 1.45000E+02 1.16000E+02 1.15000E+02 1.14000E+02 1.13000E+02 + 8.40000E+01 8.30000E+01 8.20000E+01 8.10000E+01 5.20000E+01 5.10000E+01 + 5.00000E+01 4.90000E+01 2.00000E+01 1.90000E+01 1.80000E+01 1.70000E+01 + 1.76000E+02 1.75000E+02 1.74000E+02 1.73000E+02 1.44000E+02 1.43000E+02 + 1.42000E+02 1.41000E+02 1.12000E+02 1.11000E+02 1.10000E+02 1.09000E+02 + 8.00000E+01 7.90000E+01 7.80000E+01 7.70000E+01 4.80000E+01 4.70000E+01 + 4.60000E+01 4.50000E+01 1.60000E+01 1.50000E+01 1.40000E+01 1.30000E+01 + 1.72000E+02 1.71000E+02 1.70000E+02 1.69000E+02 1.40000E+02 1.39000E+02 + 1.38000E+02 1.37000E+02 1.08000E+02 1.07000E+02 1.06000E+02 1.05000E+02 + 7.60000E+01 7.50000E+01 7.40000E+01 7.30000E+01 4.40000E+01 4.30000E+01 + 4.20000E+01 4.10000E+01 1.20000E+01 1.10000E+01 1.00000E+01 9.00000E+00 + 1.68000E+02 1.67000E+02 1.66000E+02 1.65000E+02 1.36000E+02 1.35000E+02 + 1.34000E+02 1.33000E+02 1.04000E+02 1.03000E+02 1.02000E+02 1.01000E+02 + 7.20000E+01 7.10000E+01 7.00000E+01 6.90000E+01 4.00000E+01 3.90000E+01 + 3.80000E+01 3.70000E+01 8.00000E+00 7.00000E+00 6.00000E+00 5.00000E+00 + 1.64000E+02 1.63000E+02 1.62000E+02 1.61000E+02 1.32000E+02 1.31000E+02 + 1.30000E+02 1.29000E+02 1.00000E+02 9.90000E+01 9.80000E+01 9.70000E+01 + 6.80000E+01 6.70000E+01 6.60000E+01 6.50000E+01 3.60000E+01 3.50000E+01 + 3.40000E+01 3.30000E+01 4.00000E+00 3.00000E+00 2.00000E+00 1.00000E+00 diff --git a/tests/unit_tests/weightwindows/wwinp_t b/tests/unit_tests/weightwindows/wwinp_t new file mode 100644 index 000000000..91f7a93ac --- /dev/null +++ b/tests/unit_tests/weightwindows/wwinp_t @@ -0,0 +1,47 @@ + 1 2 2 10 + 0 4 + 6.0 8.0 1.0 -1.00000E+02 -1.00000E+02 -5.00000E+01 + 6.0 8.0 1.0 1.0 + -1.00000E+02 1.00000E+00 -6.66667E+01 1.00000E+00 1.00000E+00 -3.33333E+01 + 1.00000E+00 1.00000E+00 0.00000E+00 1.00000E+00 1.00000E+00 3.33333E+01 + 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -1.00000E+02 1.00000E+00 -5.00000E+01 1.00000E+00 1.00000E+00 -1.33333E+01 + 1.00000E+00 1.00000E+00 2.33333E+01 1.00000E+00 1.00000E+00 6.00000E+01 + 1.00000E+00 1.00000E+00 7.00000E+01 1.00000E+00 1.00000E+00 8.00000E+01 + 1.00000E+00 1.00000E+00 9.00000E+01 1.00000E+00 1.00000E+00 1.00000E+02 + 1.00000E+00 + -5.00000E+01 1.00000E+00 5.00000E+01 1.00000E+00 + 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 + 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 + 1.58000E+02 1.57000E+02 1.28000E+02 1.27000E+02 1.26000E+02 1.25000E+02 + 9.60000E+01 9.50000E+01 9.40000E+01 9.30000E+01 6.40000E+01 6.30000E+01 + 6.20000E+01 6.10000E+01 3.20000E+01 3.10000E+01 3.00000E+01 2.90000E+01 + 1.88000E+02 1.87000E+02 1.86000E+02 1.85000E+02 1.56000E+02 1.55000E+02 + 1.54000E+02 1.53000E+02 1.24000E+02 1.23000E+02 1.22000E+02 1.21000E+02 + 9.20000E+01 9.10000E+01 9.00000E+01 8.90000E+01 6.00000E+01 5.90000E+01 + 5.80000E+01 5.70000E+01 2.80000E+01 2.70000E+01 2.60000E+01 2.50000E+01 + 1.84000E+02 1.83000E+02 1.82000E+02 1.81000E+02 1.52000E+02 1.51000E+02 + 1.50000E+02 1.49000E+02 1.20000E+02 1.19000E+02 1.18000E+02 1.17000E+02 + 8.80000E+01 8.70000E+01 8.60000E+01 8.50000E+01 5.60000E+01 5.50000E+01 + 5.40000E+01 5.30000E+01 2.40000E+01 2.30000E+01 2.20000E+01 2.10000E+01 + 1.80000E+02 1.79000E+02 1.78000E+02 1.77000E+02 1.48000E+02 1.47000E+02 + 1.46000E+02 1.45000E+02 1.16000E+02 1.15000E+02 1.14000E+02 1.13000E+02 + 8.40000E+01 8.30000E+01 8.20000E+01 8.10000E+01 5.20000E+01 5.10000E+01 + 5.00000E+01 4.90000E+01 2.00000E+01 1.90000E+01 1.80000E+01 1.70000E+01 + 1.76000E+02 1.75000E+02 1.74000E+02 1.73000E+02 1.44000E+02 1.43000E+02 + 1.42000E+02 1.41000E+02 1.12000E+02 1.11000E+02 1.10000E+02 1.09000E+02 + 8.00000E+01 7.90000E+01 7.80000E+01 7.70000E+01 4.80000E+01 4.70000E+01 + 4.60000E+01 4.50000E+01 1.60000E+01 1.50000E+01 1.40000E+01 1.30000E+01 + 1.72000E+02 1.71000E+02 1.70000E+02 1.69000E+02 1.40000E+02 1.39000E+02 + 1.38000E+02 1.37000E+02 1.08000E+02 1.07000E+02 1.06000E+02 1.05000E+02 + 7.60000E+01 7.50000E+01 7.40000E+01 7.30000E+01 4.40000E+01 4.30000E+01 + 4.20000E+01 4.10000E+01 1.20000E+01 1.10000E+01 1.00000E+01 9.00000E+00 + 1.68000E+02 1.67000E+02 1.66000E+02 1.65000E+02 1.36000E+02 1.35000E+02 + 1.34000E+02 1.33000E+02 1.04000E+02 1.03000E+02 1.02000E+02 1.01000E+02 + 7.20000E+01 7.10000E+01 7.00000E+01 6.90000E+01 4.00000E+01 3.90000E+01 + 3.80000E+01 3.70000E+01 8.00000E+00 7.00000E+00 6.00000E+00 5.00000E+00 + 1.64000E+02 1.63000E+02 1.62000E+02 1.61000E+02 1.32000E+02 1.31000E+02 + 1.30000E+02 1.29000E+02 1.00000E+02 9.90000E+01 9.80000E+01 9.70000E+01 + 6.80000E+01 6.70000E+01 6.60000E+01 6.50000E+01 3.60000E+01 3.50000E+01 + 3.40000E+01 3.30000E+01 4.00000E+00 3.00000E+00 2.00000E+00 1.00000E+00 From d79f2899a84b58341804f4638ad410392dc1ac9d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:43:31 -0600 Subject: [PATCH 0089/2654] Adding tests for time-dependent and non-rectilinear mesh wws --- openmc/weight_windows.py | 7 +++--- .../weightwindows/test_wwinp_reader.py | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 024637e93..0a5ea6409 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -476,8 +476,8 @@ def wwinp_to_wws(path): if mesh_chars != 10: # TODO: read the first entry by default and display a warning - raise ValueError('Cylindrical and Spherical meshes ' - 'are not currently supported') + raise NotImplementedError('Cylindrical and Spherical meshes ' + 'are not currently supported') # read the number of energy groups for each particle, ne n_egroups = [int(next(wwinp)) for _ in range(n_particle_types)] @@ -518,7 +518,8 @@ def wwinp_to_wws(path): if mesh_type != 1: # TODO: support additional mesh types - raise ValueError('Cylindrical and Spherical meshes are not currently supported') + raise NotImplementedError('Cylindrical and Spherical meshes ' + 'are not currently supported') # internal function for parsing mesh coordinates def _read_mesh_coords(wwinp, n_coarse_bins): diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index faf29e60d..dde7356bb 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -3,6 +3,8 @@ import numpy as np import openmc import pytest +from openmc.weight_windows import wwinp_to_wws + # check that we can successfully read wwinp files with the following contents: # @@ -81,6 +83,7 @@ expected_results = [('wwinp_n', n_mesh, n_particles, n_e_bounds), ('wwinp_p', p_mesh, p_particles, p_e_bounds)] +# function for printing readable test labels def id_fn(params): suffix = params[0].split('_')[-1] if suffix == 'n': @@ -119,3 +122,24 @@ def test_wwinp_reader(wwinp_data): n_wws = np.prod((*mesh.dimension, e_bounds.size - 1)) exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1] np.testing.assert_array_equal(exp_ww_lb, ww.lower_ww_bounds) + + +# check expected failures +def fail_id_fn(params): + suffix = params[0].split('_')[-1] + if suffix == 't': + return 'time-steps-failure' + elif suffix == 'cyl': + return 'cyl-mesh-failure' + + +expected_failure_data = (('wwinp_t', ValueError), + ('wwinp_cyl', NotImplementedError)) + + +@pytest.mark.parametrize('wwinp_data', expected_failure_data, ids=fail_id_fn) +def test_wwinp_reader_failures(wwinp_data): + filename, expected_failure = wwinp_data + + with pytest.raises(expected_failure): + _ = openmc.wwinp_to_wws(filename) From 1cdd7084fc7383dad22ba636382a4c7830396fdd Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 09:45:16 -0600 Subject: [PATCH 0090/2654] PEP8 updates, correcting comment, removing unused var --- openmc/weight_windows.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 0a5ea6409..7cb9d1036 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -443,6 +443,7 @@ def __wwinp_reader(path): for value in values: yield value + def wwinp_to_wws(path): """Creates WeightWindows classes from a wwinp file @@ -530,7 +531,7 @@ def wwinp_to_wws(path): sx = int(float(next(wwinp))) # value of next coordinate, px px = float(next(wwinp)) - # fine mesh ratio, qx, is currently unused + # fine mesh ratio, qx (currently unused) qx = next(wwinp) # append the fine mesh coordinates for this coarse element coords += list(np.linspace(coords[-1], px, sx + 1))[1:] @@ -561,8 +562,6 @@ def wwinp_to_wws(path): 'number read in block 1 of the wwinp file ({})') raise ValueError(msg.format(dim, mesh_val, header_val)) - # total number of fine mesh elements, nft - n_elements = n_fine_x * n_fine_y * n_fine_z # read energy bins and weight window values for each particle wws = [] for particle, ne in zip(particles, n_egroups): From 87bde4d72c70a6c8019afc467d51af83028581e9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 14:33:34 -0600 Subject: [PATCH 0091/2654] Using context manager. Improving docstring --- openmc/weight_windows.py | 41 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 7cb9d1036..1a54c1b9b 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -419,38 +419,39 @@ def __wwinp_reader(path): path : str or pathlib.Path Location of the wwinp file """ - fh = open(path, 'r') - # read the first line of the file and - # keep only the first four entries - while(True): - line = next(fh) - if line and not line.startswith('c'): - break + with open(path, 'r') as fh: - values = line.strip().split()[:4] - for value in values: - yield value + # read the first line of the file and + # keep only the first four entries + while True: + line = next(fh) + if line and not line.startswith('c'): + break - # the remainder of the file can be read as - # sequential values - while(True): - line = next(fh) - # skip empty or commented lines - if not line or line.startswith('c'): - continue - values = line.strip().split() + values = line.strip().split()[:4] for value in values: yield value + # the remainder of the file can be read as + # sequential values + while True: + line = next(fh) + # skip empty or commented lines + if not line or line.startswith('c'): + continue + values = line.strip().split() + for value in values: + yield value + def wwinp_to_wws(path): """Creates WeightWindows classes from a wwinp file Parameters ---------- - path : str - Path to the wwinp file. + path : str or pathlib.Path object + Path to the wwinp file Returns ------- From 61bce00f08bec4abc4b27085656b5f947c6ed999 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 11 Mar 2022 14:33:59 -0600 Subject: [PATCH 0092/2654] Adding function to resolve the full path to the test data files. --- tests/unit_tests/weightwindows/test_wwinp_reader.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index dde7356bb..b9de6b329 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -1,11 +1,9 @@ import numpy as np +from pathlib import Path import openmc import pytest -from openmc.weight_windows import wwinp_to_wws - - # check that we can successfully read wwinp files with the following contents: # # - neutrons on a rectilinear mesh @@ -93,12 +91,16 @@ def id_fn(params): elif suffix == 'p': return 'photon-only' +# function to resolve full path to the test data +def full_path(filename): + cwd = Path(__file__).parent.absolute() + return cwd / Path(filename) @pytest.mark.parametrize('wwinp_data', expected_results, ids=id_fn) def test_wwinp_reader(wwinp_data): wwinp_file, mesh, particle_types, energy_bounds = wwinp_data - wws = openmc.wwinp_to_wws(wwinp_file) + wws = openmc.wwinp_to_wws(full_path(wwinp_file)) for i, ww in enumerate(wws): e_bounds = energy_bounds[i] @@ -142,4 +144,4 @@ def test_wwinp_reader_failures(wwinp_data): filename, expected_failure = wwinp_data with pytest.raises(expected_failure): - _ = openmc.wwinp_to_wws(filename) + _ = openmc.wwinp_to_wws(full_path(filename)) From 176b1a09a3cc98c8aa4753b4ba33ee7fb67cd8b6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Mar 2022 09:59:52 -0500 Subject: [PATCH 0093/2654] Updates to attribute name --- openmc/weight_windows.py | 2 +- tests/unit_tests/weightwindows/test_wwinp_reader.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 1a54c1b9b..ca71a9f0f 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -585,7 +585,7 @@ def wwinp_to_wws(path): mesh=mesh, lower_ww_bounds=ww_lb.flatten(), upper_bound_ratio=5.0, - energy_bins=e_bounds, + energy_bounds=e_bounds, particle_type=particle) wws.append(ww) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index b9de6b329..fdabfe18a 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -117,7 +117,7 @@ def test_wwinp_reader(wwinp_data): np.testing.assert_allclose(mesh.z_grid, ww.mesh.z_grid, rtol=1e-6) # check the energy bounds - np.testing.assert_array_equal(e_bounds, ww.energy_bins) + np.testing.assert_array_equal(e_bounds, ww.energy_bounds) # check the expected weight window values mocked in the file -- # a reversed array of the flat index into the numpy array From 64e039502ecd4593e06db54755520704401a0365 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Mar 2022 10:04:30 -0500 Subject: [PATCH 0094/2654] PEP8 --- tests/unit_tests/weightwindows/test_wwinp_reader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index fdabfe18a..b890b7f37 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -91,11 +91,13 @@ def id_fn(params): elif suffix == 'p': return 'photon-only' + # function to resolve full path to the test data def full_path(filename): cwd = Path(__file__).parent.absolute() return cwd / Path(filename) + @pytest.mark.parametrize('wwinp_data', expected_results, ids=id_fn) def test_wwinp_reader(wwinp_data): wwinp_file, mesh, particle_types, energy_bounds = wwinp_data From 01117b10ffa027423906cd7bf801b24d3be92ca2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 15 Mar 2022 10:43:22 -0500 Subject: [PATCH 0095/2654] use xtensor library on system if it already exists, else use vendored submodule --- CMakeLists.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a01d02fb3..1e514e32b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,12 @@ if(pugixml_FOUND) else() message(STATUS "Did not find pugixml, will use submodule instead") endif() - +find_package(xtensor QUIET NO_SYSTEM_ENVIRONMENT_PATH) +if(xtensor_FOUND) + message(STATUS "Found xtensor: ${xtensor_DIR} (version ${xtensor_VERSION})") +else() + message(STATUS "Did not find xtensor, will use submodule instead") +endif() #=============================================================================== # libMesh Unstructured Mesh Support #=============================================================================== @@ -211,9 +216,11 @@ if (NOT (CMAKE_VERSION VERSION_LESS 3.13)) cmake_policy(SET CMP0079 NEW) endif() -add_subdirectory(vendor/xtl) -set(xtl_DIR ${CMAKE_CURRENT_BINARY_DIR}/vendor/xtl) -add_subdirectory(vendor/xtensor) +if (NOT xtensor_FOUND) + add_subdirectory(vendor/xtl) + set(xtl_DIR ${CMAKE_CURRENT_BINARY_DIR}/vendor/xtl) + add_subdirectory(vendor/xtensor) +endif() #=============================================================================== # GSL header-only library From 42f95cc0f716b53356368aaca2cb3feb0b678efd Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 15 Mar 2022 10:49:01 -0500 Subject: [PATCH 0096/2654] check for xtl on system --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e514e32b..bcc6fb7db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,11 @@ if(xtensor_FOUND) else() message(STATUS "Did not find xtensor, will use submodule instead") endif() +if(xtl_FOUND) + message(STATUS "Found xtl: ${xtl_DIR} (version ${xtl_VERSION})") +else() + message(STATUS "Did not find xtl, will use submodule instead") +endif() #=============================================================================== # libMesh Unstructured Mesh Support #=============================================================================== @@ -216,9 +221,12 @@ if (NOT (CMAKE_VERSION VERSION_LESS 3.13)) cmake_policy(SET CMP0079 NEW) endif() -if (NOT xtensor_FOUND) +if (NOT xtl_FOUND) add_subdirectory(vendor/xtl) set(xtl_DIR ${CMAKE_CURRENT_BINARY_DIR}/vendor/xtl) +endif() + +if (NOT xtensor_FOUND) add_subdirectory(vendor/xtensor) endif() From 7369796425f9051904142deb0dd5cb3b7bc3f3cc Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 15 Mar 2022 11:01:09 -0500 Subject: [PATCH 0097/2654] look for existing gls-lite package --- CMakeLists.txt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bcc6fb7db..9cd8395c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,11 +77,18 @@ if(xtensor_FOUND) else() message(STATUS "Did not find xtensor, will use submodule instead") endif() +find_package(xtl QUIET NO_SYSTEM_ENVIRONMENT_PATH) if(xtl_FOUND) message(STATUS "Found xtl: ${xtl_DIR} (version ${xtl_VERSION})") else() message(STATUS "Did not find xtl, will use submodule instead") endif() +find_package(gsl-lite QUIET NO_SYSTEM_ENVIRONMENT_PATH) +if(gsl-lite_FOUND) + message(STATUS "Found : ${gsl-lite_DIR} (version ${gsl-lite_VERSION})") +else() + message(STATUS "Did not find gsl-lite, will use submodule instead") +endif() #=============================================================================== # libMesh Unstructured Mesh Support #=============================================================================== @@ -234,11 +241,13 @@ endif() # GSL header-only library #=============================================================================== -add_subdirectory(vendor/gsl-lite) +if (NOT gsl-lite_FOUND) + add_subdirectory(vendor/gsl-lite) -# Make sure contract violations throw exceptions -target_compile_definitions(gsl-lite-v1 INTERFACE GSL_THROW_ON_CONTRACT_VIOLATION) -target_compile_definitions(gsl-lite-v1 INTERFACE gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=1) + # Make sure contract violations throw exceptions + target_compile_definitions(gsl-lite-v1 INTERFACE GSL_THROW_ON_CONTRACT_VIOLATION) + target_compile_definitions(gsl-lite-v1 INTERFACE gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=1) +endif() #=============================================================================== # RPATH information From 8c972528b3b87544c516a4ca256c86c0841a01a2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 15 Mar 2022 11:18:55 -0500 Subject: [PATCH 0098/2654] typo in status message --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cd8395c1..3d588cb84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ else() endif() find_package(gsl-lite QUIET NO_SYSTEM_ENVIRONMENT_PATH) if(gsl-lite_FOUND) - message(STATUS "Found : ${gsl-lite_DIR} (version ${gsl-lite_VERSION})") + message(STATUS "Found gsl-lite: ${gsl-lite_DIR} (version ${gsl-lite_VERSION})") else() message(STATUS "Did not find gsl-lite, will use submodule instead") endif() From 097c53f63419406ab65353c375e4dd19816ec288 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Mar 2022 18:51:33 -0500 Subject: [PATCH 0099/2654] Changes requested by @paulromano --- openmc/weight_windows.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index ca71a9f0f..443500c84 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -412,7 +412,7 @@ class WeightWindows(IDManagerMixin): id=id ) -def __wwinp_reader(path): +def _wwinp_reader(path): """ Generator that returns the next value in a wwinp file. @@ -458,7 +458,7 @@ def wwinp_to_wws(path): list of openmc.WeightWindows """ # create generator for getting the next parameter from the file - wwinp = __wwinp_reader(path) + wwinp = _wwinp_reader(path) # first parameter, if, of wwinp file is unused next(wwinp) @@ -493,9 +493,8 @@ def wwinp_to_wws(path): n_egroups = [e for e in n_egroups if e > 0] if n_particle_types > 2: - msg = ('More than two particle types are present. ' - 'Only neutron and photon weight windows will be read.') - warnings.warn(msg) + warnings.warn('More than two particle types are present. ' + 'Only neutron and photon weight windows will be read.') # read total number of fine mesh elements in each coarse # element (nfx, nfy, nfz) From def829ad7668fec962314d327b7b200e38e8758d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Mar 2022 18:52:11 -0500 Subject: [PATCH 0100/2654] Improvements to test file from suggestions by @paulromano --- .../weightwindows/test_wwinp_reader.py | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index b890b7f37..c225f12f2 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -17,7 +17,7 @@ import pytest # expected retults - neutron data only n_mesh = openmc.RectilinearMesh() -n_mesh.x_grid = np.asarray([-100.0, +n_mesh.x_grid = np.array([-100.0, -99.0, -97.0, -79.3636, @@ -33,7 +33,7 @@ n_mesh.x_grid = np.asarray([-100.0, 97.0, 99.0, 100]) -n_mesh.y_grid = np.asarray([-100.0, +n_mesh.y_grid = np.array([-100.0, -50.0, -13.3333, 23.3333, @@ -42,27 +42,27 @@ n_mesh.y_grid = np.asarray([-100.0, 80.0, 90.0, 100.0]) -n_mesh.z_grid = np.asarray([-100.0, +n_mesh.z_grid = np.array([-100.0, -66.6667, -33.3333, 0.0, 33.3333, 66.6667, 100.0]) -n_e_bounds = (np.asarray([0.0, +n_e_bounds = (np.array([0.0, 100000.0, 146780.0]),) n_particles = ('neutron',) # expected results - neutron and photon data np_mesh = openmc.RectilinearMesh() -np_mesh.x_grid = np.asarray([-100.0, 100.0]) +np_mesh.x_grid = np.array([-100.0, 100.0]) # y grid and z grid are the same as the previous mesh np_mesh.y_grid = n_mesh.y_grid np_mesh.z_grid = n_mesh.z_grid -np_e_bounds = (np.asarray([0.0, 100000.0, 146780.0, 215440.0]), - np.asarray([0.0, 1.0E8])) +np_e_bounds = (np.array([0.0, 100000.0, 146780.0, 215440.0]), + np.array([0.0, 1.0E8])) np_particles = ('neutron', 'photon') # expected results - photon data only @@ -71,9 +71,9 @@ p_mesh = openmc.RectilinearMesh() p_mesh.x_grid = np_mesh.z_grid # uses the same y grid p_mesh.y_grid = np_mesh.y_grid -p_mesh.z_grid = np.asarray([-50.0, 50.0]) +p_mesh.z_grid = np.array([-50.0, 50.0]) -p_e_bounds = (np.asarray([0.0, 100000.0, 146780.0, 215440.0, 316230.0]),) +p_e_bounds = (np.array([0.0, 100000.0, 146780.0, 215440.0, 316230.0]),) p_particles = ('photon',) expected_results = [('wwinp_n', n_mesh, n_particles, n_e_bounds), @@ -92,17 +92,11 @@ def id_fn(params): return 'photon-only' -# function to resolve full path to the test data -def full_path(filename): - cwd = Path(__file__).parent.absolute() - return cwd / Path(filename) - - @pytest.mark.parametrize('wwinp_data', expected_results, ids=id_fn) -def test_wwinp_reader(wwinp_data): +def test_wwinp_reader(wwinp_data, request): wwinp_file, mesh, particle_types, energy_bounds = wwinp_data - wws = openmc.wwinp_to_wws(full_path(wwinp_file)) + wws = openmc.wwinp_to_wws(request.node.path.parent / wwinp_file) for i, ww in enumerate(wws): e_bounds = energy_bounds[i] @@ -142,8 +136,8 @@ expected_failure_data = (('wwinp_t', ValueError), @pytest.mark.parametrize('wwinp_data', expected_failure_data, ids=fail_id_fn) -def test_wwinp_reader_failures(wwinp_data): +def test_wwinp_reader_failures(wwinp_data, request): filename, expected_failure = wwinp_data with pytest.raises(expected_failure): - _ = openmc.wwinp_to_wws(full_path(filename)) + _ = openmc.wwinp_to_wws(request.node.path.parent / filename) From 2eab6fd3351527cd24639df68010f93a984acd8c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Mar 2022 18:53:42 -0500 Subject: [PATCH 0101/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/weight_windows.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 443500c84..734d73d4d 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -460,7 +460,7 @@ def wwinp_to_wws(path): # create generator for getting the next parameter from the file wwinp = _wwinp_reader(path) - # first parameter, if, of wwinp file is unused + # first parameter, 'if' (file type), of wwinp file is unused next(wwinp) # check time parameter, iv @@ -569,7 +569,7 @@ def wwinp_to_wws(path): # it is implied that zero is always the first bound in MCNP e_bounds = np.asarray([0.0] + [float(next(wwinp)) for _ in range(ne)]) # adjust energy from MeV to eV - e_bounds *= 1E6 + e_bounds *= 1e6 # create an array for weight window lower bounds ww_lb = np.zeros((*mesh.dimension, ne)) From 22fc5d8e2cdfc7f090cf7593c3336f95a8742df6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Mar 2022 18:57:54 -0500 Subject: [PATCH 0102/2654] Adding relevant time bin lines to test file --- tests/unit_tests/weightwindows/wwinp_t | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/weightwindows/wwinp_t b/tests/unit_tests/weightwindows/wwinp_t index 91f7a93ac..f1aa26d6d 100644 --- a/tests/unit_tests/weightwindows/wwinp_t +++ b/tests/unit_tests/weightwindows/wwinp_t @@ -1,4 +1,5 @@ 1 2 2 10 + 1 1 0 4 6.0 8.0 1.0 -1.00000E+02 -1.00000E+02 -5.00000E+01 6.0 8.0 1.0 1.0 @@ -11,6 +12,7 @@ 1.00000E+00 1.00000E+00 7.00000E+01 1.00000E+00 1.00000E+00 8.00000E+01 1.00000E+00 1.00000E+00 9.00000E+01 1.00000E+00 1.00000E+00 1.00000E+02 1.00000E+00 + 1.00000E+02 -5.00000E+01 1.00000E+00 5.00000E+01 1.00000E+00 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 From 695cae93912805ad30ab9445459fc3c1f2af0e6b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Mar 2022 19:07:26 -0500 Subject: [PATCH 0103/2654] Updating wwinp_cyl to meet wwinp spec --- tests/unit_tests/weightwindows/wwinp_cyl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/weightwindows/wwinp_cyl b/tests/unit_tests/weightwindows/wwinp_cyl index 391e4bcf6..890844b87 100644 --- a/tests/unit_tests/weightwindows/wwinp_cyl +++ b/tests/unit_tests/weightwindows/wwinp_cyl @@ -1,7 +1,8 @@ 1 1 2 16 0 4 6.0 8.0 1.0 -1.00000E+02 -1.00000E+02 -5.00000E+01 - 6.0 8.0 1.0 1.0 + 6.0 8.0 1.0 -1.00000E+02 -1.00000E+02 5.00000E+01 + -1.00000E+02 1.00000E+02 -5.00000E+01 2.0 -1.00000E+02 1.00000E+00 -6.66667E+01 1.00000E+00 1.00000E+00 -3.33333E+01 1.00000E+00 1.00000E+00 0.00000E+00 1.00000E+00 1.00000E+00 3.33333E+01 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 @@ -11,7 +12,7 @@ 1.00000E+00 1.00000E+00 7.00000E+01 1.00000E+00 1.00000E+00 8.00000E+01 1.00000E+00 1.00000E+00 9.00000E+01 1.00000E+00 1.00000E+00 1.00000E+02 1.00000E+00 - -5.00000E+01 1.00000E+00 5.00000E+01 1.00000E+00 + 0.00000E+01 1.00000E+00 3.14159E+00 1.00000E+00 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 1.58000E+02 1.57000E+02 1.28000E+02 1.27000E+02 1.26000E+02 1.25000E+02 From 09d355475af1e9e94463e55d598a6310b5175dbb Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 16 Mar 2022 09:49:14 -0500 Subject: [PATCH 0104/2654] fixed gsl compile error --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d588cb84..38069662a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,7 +446,7 @@ endif() # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES} - pugixml faddeeva xtensor gsl-lite-v1 fmt::fmt) + pugixml faddeeva xtensor gsl::gsl-lite-v1 fmt::fmt) if(dagmc) target_compile_definitions(libopenmc PRIVATE DAGMC) From 80517d1d4f36e57d90a5de61f86a3dffa3d82c8e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 10:13:44 -0500 Subject: [PATCH 0105/2654] wwinp IO refactor --- openmc/weight_windows.py | 121 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 734d73d4d..d6067e63d 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -1,4 +1,5 @@ from collections.abc import Iterable +import math from numbers import Real, Integral import warnings @@ -457,6 +458,126 @@ def wwinp_to_wws(path): ------- list of openmc.WeightWindows """ + + # read wwinp data + with open(path) as wwinp: + # BLOCK 1 + header = wwinp.readline().split(None, 4) + # read file type, time-dependence, number of + # particles, mesh type and problem identifier + _if, iv, ni, nr = [int(x) for x in header[:4]] + probid = header[4] if len(header) > 4 else "" + + if _if != 1: + raise ValueError(f'Found incorrect file type, if: "{_if}"') + if iv > 1: + # read number of time bins for each particle, 'nt(1...ni)' + nt = np.fromstring(wwinp.readline(), sep=' ', dtype=int) + + # raise error if time bins are present for now + raise ValueError('Time-dependent weight windows ' + 'are not yet supported') + else: + nt = ni * [1] + + # read number of energy bins for each particle, 'ne(1...ni)' + ne = np.fromstring(wwinp.readline(), sep=' ', dtype=int) + + # read coarse mesh dimensions and lower left corner + mesh_description = np.fromstring(wwinp.readline(), sep=' ') + nfx, nfy, nfz = [int(x) for x in mesh_description[:3]] + x0, y0, z0 = mesh_description[3:] + + # read cylindrical and spherical mesh data if needed + if nr == 16: + # read number of coarse bins + line_arr = np.fromstring(wwinp.readline(), sep=' ') + ncx, ncy, ncz = [int(x) for x in line_arr[:3]] + # read polar vector (x1, y1, z1) + polar_vec = line_arr[3:] - mesh_llc + polar_vec /= np.linalg.norm(polar_vec) + line_arr = np.fromstring(wwinp.readline(), sep=' ') + # read azimuthal vector (x2, y2, z2) + azimuthal_vec = line_arr[:3] - mesh_llc + azimuthal_vec /= np.linalg.norm(polar_vec) + # read geometry type + nwg = int(line_arr[-1]) + elif nr == 10: + # read rectilinear data: + # number of coarse mesh bins and mesh type + ncx, ncy, ncz, nwg = np.fromstring(wwinp.readline(), sep=' ', dtype=int) + else: + raise RuntimeError(f'Invalid mesh description (nr) found: {nr}') + + # BLOCK 2 + # read the x dimension description of the mesh + # x0, (qx(i), px(i), sx(i), i...ncx) + # y0, (qy(i), py(i), sy(i), i...ncy) + # z0, (qz(i), pz(i), sz(i), i...ncz) + # deterine number of lines to read (6 entries per line) + n_x_lines = math.ceil((1 + 3 * ncx) / 6) + x_vals = np.fromstring([wwinp.readline() for _ in range(n_x_lines)], sep=' ').flatten() + n_y_lines = math.ceil((1 + 3 * ncy) / 6) + y_vals = np.fromstring([wwinp.readline() for _ in range(n_y_lines)], sep=' ').flatten() + n_z_lines = math.ceil((1 + 3 * ncz) / 6) + z_vals = np.fromstring([wwinp.readline() for _ in range(n_z_lines)], sep=' ').flatten() + + # BLOCK 3 - option A + particle_data = [] + for p in range(ni): + if iv > 1: + # read time bins + n_time_bin_lines = math.ceil(nt[p] / 6) + time_bins = np.fromstring([wwinp.readline() for _ in range(n_time_bin_lines)], sep=' ').flatten() + + # read energy bins + n_energy_bin_lines = math.ceil(ne[p] / 6) + energy_bins = np.np.fromstring([wwinp.readline() for _ in range(n_energy_bin_lines)], sep=' ').flatten() + + # read weight window parameters + n_ww_lines = math.ceil((nfx * nfy * nfz) * (nt[p]) * (num_energy_bins[p]) / 6) + ww_values = np.fromstring([wwinp.readline() for _ in range(n_ww_lines)], sep=' ').flatten() + + particle_dict = {'time_bins': time_bins, + 'energy_bins': energy_bins, + 'ww_values': ww_values} + + particle_data.append(particle_dict) + + # BLOCK 3 - option B + # read all remaining ww data + ww_data = np.fromstring(wwinp.read(), sep=' ') + + start_idx = 0 + particle_data = [] + for p in range(ni): + if iv > 1: + end_idx = start_idx + nt[p] + time_bins = ww_data[start_idx:end_idx] + + start_idx += end_idx + + end_idx = start_idx + ne[p] + energy_bins = ww_data[start_idx:end_idx] + + end_idx = start_idx + (nfx * nfy * nfz) * nt[p] * ne[p] + ww_values = ww_data[start_idx:end_idx] + start_idx += end_idx + + particle_dict = {'time_bins': time_bins, + 'energy_bins': energy_bins, + 'ww_values': ww_values} + + particle_data.append(particle_dict) + + + # create mesh object here + + for i, data in enumerate(particle_data): + pass + # create WeightWindow objects here + + # create generator for getting the next parameter from the file wwinp = _wwinp_reader(path) From c3997b3fbd623f2a7aff12673b84e75bd7c10ab0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 12:18:21 -0500 Subject: [PATCH 0106/2654] Cleaning up reader --- openmc/weight_windows.py | 305 +++++++++++---------------------------- 1 file changed, 84 insertions(+), 221 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index d6067e63d..c9c9be316 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -1,5 +1,6 @@ from collections.abc import Iterable import math +from multiprocessing.sharedctypes import Value from numbers import Real, Integral import warnings @@ -119,10 +120,6 @@ class WeightWindows(IDManagerMixin): self.energy_bounds = energy_bounds self.lower_ww_bounds = lower_ww_bounds - cv.check_length('Lower window bounds', - self.lower_ww_bounds, - len(self.energy_bounds)) - if upper_ww_bounds is not None and upper_bound_ratio: raise ValueError("Exactly one of upper_ww_bounds and " "upper_bound_ratio must be present.") @@ -413,38 +410,6 @@ class WeightWindows(IDManagerMixin): id=id ) -def _wwinp_reader(path): - """ - Generator that returns the next value in a wwinp file. - - path : str or pathlib.Path - Location of the wwinp file - """ - - with open(path, 'r') as fh: - - # read the first line of the file and - # keep only the first four entries - while True: - line = next(fh) - if line and not line.startswith('c'): - break - - values = line.strip().split()[:4] - for value in values: - yield value - - # the remainder of the file can be read as - # sequential values - while True: - line = next(fh) - # skip empty or commented lines - if not line or line.startswith('c'): - continue - values = line.strip().split() - for value in values: - yield value - def wwinp_to_wws(path): """Creates WeightWindows classes from a wwinp file @@ -459,7 +424,6 @@ def wwinp_to_wws(path): list of openmc.WeightWindows """ - # read wwinp data with open(path) as wwinp: # BLOCK 1 header = wwinp.readline().split(None, 4) @@ -468,8 +432,10 @@ def wwinp_to_wws(path): _if, iv, ni, nr = [int(x) for x in header[:4]] probid = header[4] if len(header) > 4 else "" + # header value checks if _if != 1: - raise ValueError(f'Found incorrect file type, if: "{_if}"') + raise ValueError(f'Found incorrect file type, if: {_if}') + if iv > 1: # read number of time bins for each particle, 'nt(1...ni)' nt = np.fromstring(wwinp.readline(), sep=' ', dtype=int) @@ -480,233 +446,130 @@ def wwinp_to_wws(path): else: nt = ni * [1] + if nr == 16: + raise NotImplementedError('Cylindrical and spherical mesh ' + 'types are not yet supported') + # read number of energy bins for each particle, 'ne(1...ni)' ne = np.fromstring(wwinp.readline(), sep=' ', dtype=int) # read coarse mesh dimensions and lower left corner mesh_description = np.fromstring(wwinp.readline(), sep=' ') nfx, nfy, nfz = [int(x) for x in mesh_description[:3]] - x0, y0, z0 = mesh_description[3:] + xyz0 = mesh_description[3:] - # read cylindrical and spherical mesh data if needed + # read cylindrical and spherical mesh vectors if present if nr == 16: # read number of coarse bins line_arr = np.fromstring(wwinp.readline(), sep=' ') ncx, ncy, ncz = [int(x) for x in line_arr[:3]] # read polar vector (x1, y1, z1) - polar_vec = line_arr[3:] - mesh_llc - polar_vec /= np.linalg.norm(polar_vec) - line_arr = np.fromstring(wwinp.readline(), sep=' ') + xyz1 = line_arr[3:] - xyz0 + polar_vec = xyz1 / np.linalg.norm(xyz1) # read azimuthal vector (x2, y2, z2) - azimuthal_vec = line_arr[:3] - mesh_llc - azimuthal_vec /= np.linalg.norm(polar_vec) + line_arr = np.fromstring(wwinp.readline(), sep=' ') + xyz2 = line_arr[:3] - xyz0 + azimuthal_vec = xyz2 / np.linalg.norm(xyz2) # read geometry type nwg = int(line_arr[-1]) elif nr == 10: # read rectilinear data: # number of coarse mesh bins and mesh type - ncx, ncy, ncz, nwg = np.fromstring(wwinp.readline(), sep=' ', dtype=int) + ncx, ncy, ncz, nwg = [int(x) for x in np.fromstring(wwinp.readline(), sep=' ')] else: raise RuntimeError(f'Invalid mesh description (nr) found: {nr}') - # BLOCK 2 - # read the x dimension description of the mesh - # x0, (qx(i), px(i), sx(i), i...ncx) - # y0, (qy(i), py(i), sy(i), i...ncy) - # z0, (qz(i), pz(i), sz(i), i...ncz) - # deterine number of lines to read (6 entries per line) - n_x_lines = math.ceil((1 + 3 * ncx) / 6) - x_vals = np.fromstring([wwinp.readline() for _ in range(n_x_lines)], sep=' ').flatten() - n_y_lines = math.ceil((1 + 3 * ncy) / 6) - y_vals = np.fromstring([wwinp.readline() for _ in range(n_y_lines)], sep=' ').flatten() - n_z_lines = math.ceil((1 + 3 * ncz) / 6) - z_vals = np.fromstring([wwinp.readline() for _ in range(n_z_lines)], sep=' ').flatten() - - # BLOCK 3 - option A - particle_data = [] - for p in range(ni): - if iv > 1: - # read time bins - n_time_bin_lines = math.ceil(nt[p] / 6) - time_bins = np.fromstring([wwinp.readline() for _ in range(n_time_bin_lines)], sep=' ').flatten() - - # read energy bins - n_energy_bin_lines = math.ceil(ne[p] / 6) - energy_bins = np.np.fromstring([wwinp.readline() for _ in range(n_energy_bin_lines)], sep=' ').flatten() - - # read weight window parameters - n_ww_lines = math.ceil((nfx * nfy * nfz) * (nt[p]) * (num_energy_bins[p]) / 6) - ww_values = np.fromstring([wwinp.readline() for _ in range(n_ww_lines)], sep=' ').flatten() - - particle_dict = {'time_bins': time_bins, - 'energy_bins': energy_bins, - 'ww_values': ww_values} - - particle_data.append(particle_dict) - - # BLOCK 3 - option B - # read all remaining ww data + # read BLOCK 2 and BLOCK 3 data into a single array ww_data = np.fromstring(wwinp.read(), sep=' ') - start_idx = 0 - particle_data = [] - for p in range(ni): - if iv > 1: - end_idx = start_idx + nt[p] - time_bins = ww_data[start_idx:end_idx] + # extract mesh data from the ww_data array + start_idx = 0 - start_idx += end_idx + end_idx = start_idx + 1 + 3 * ncx + x_vals = ww_data[start_idx:end_idx] + start_idx = end_idx - end_idx = start_idx + ne[p] - energy_bins = ww_data[start_idx:end_idx] + end_idx = start_idx + 1 + 3 * ncy + y_vals = ww_data[start_idx:end_idx] + start_idx = end_idx - end_idx = start_idx + (nfx * nfy * nfz) * nt[p] * ne[p] - ww_values = ww_data[start_idx:end_idx] - start_idx += end_idx + end_idx = start_idx + 1 + 3 * ncz + z_vals = ww_data[start_idx:end_idx] + start_idx = end_idx - particle_dict = {'time_bins': time_bins, - 'energy_bins': energy_bins, - 'ww_values': ww_values} + # mesh consistency checks + if nr == 16 and nwg == 1: + raise ValueError(f'Mesh description in header ({nr}) ' + f'does not match the mesh type ({nwg})') - particle_data.append(particle_dict) + if not (xyz0 == (x_vals[0], y_vals[0], z_vals[0])).all(): + raise ValueError(f'Mesh origin in the header ({xyz0}) ' + f' does not match the origin in the mesh ' + f' description ({x_vals[0], y_vals[0], z_vals[0]})') + # extract weight window values from array + particle_types = {0: 'neutron', 1: 'photon'} + particle_data = [] + for p in range(ni): + # no information to read for this particle if + # either the energy bins or time bins are empty + if ne[p] == 0 or nt[p] == 0: + continue - # create mesh object here + if iv > 1: + # unused for now + end_idx = start_idx + nt[p] + time_bounds = ww_data[start_idx:end_idx] + np.insert(time_bounds, (0,), (0.0,)) + start_idx = end_idx - for i, data in enumerate(particle_data): - pass - # create WeightWindow objects here + # read energy boundaries and convert from MeV to eV + end_idx = start_idx + ne[p] + energy_bounds = 1e6 * np.insert(ww_data[start_idx:end_idx], (0,), (0.0,)) + start_idx = end_idx + # read weight window values + end_idx = start_idx + (nfx * nfy * nfz) * nt[p] * ne[p] - # create generator for getting the next parameter from the file - wwinp = _wwinp_reader(path) + # read values and reshape according to ordering + # slowest to fastest: z, y, x, e + ww_values = ww_data[start_idx:end_idx].reshape(nfz, nfy, nfx, ne[p]) + # swap z and x axes for correct shape and (ijk, e) mesh indexing + ww_values = np.swapaxes(ww_values, 2, 0) + start_idx = end_idx - # first parameter, 'if' (file type), of wwinp file is unused - next(wwinp) + # gather particle data in container + particle_dict = {'particle': particle_types[p], + 'energy_bounds': energy_bounds, + 'ww_values': ww_values} + particle_data.append(particle_dict) - # check time parameter, iv - if int(float(next(wwinp))) > 1: - raise ValueError('Time-dependent weight windows ' - 'are not yet supported.') + # create openmc mesh object + grids = [] + for grid_info in [x_vals, y_vals, z_vals]: + # first value is the start of the grid + coords = [grid_info[0]] - # number of particle types, ni - n_particle_types = int(float(next(wwinp))) + # extend the grid based on the next coarse bin endpoint, px + # and the number of fine bines in the coarse bin, sx + intervals = grid_info[1:].reshape(-1, 3) + for sx, px, qx in intervals: + coords += list(np.linspace(coords[-1], px, int(sx + 1)))[1:] - # read an indicator of the mesh type. - # this will be 10 if a rectilinear mesh - # and 16 for cylindrical or spherical meshes - mesh_chars = int(float(next(wwinp))) + grids.append(np.asarray(coords)) - if mesh_chars != 10: - # TODO: read the first entry by default and display a warning - raise NotImplementedError('Cylindrical and Spherical meshes ' - 'are not currently supported') - - # read the number of energy groups for each particle, ne - n_egroups = [int(next(wwinp)) for _ in range(n_particle_types)] - - # order that supported particle types will appear in the file - particle_types = ['neutron', 'photon'] - - # add particle to list if at least one energy group is present - particles = [p for e, p in zip(n_egroups, particle_types) if e > 0] - # truncate list of energy groups if needed - n_egroups = [e for e in n_egroups if e > 0] - - if n_particle_types > 2: - warnings.warn('More than two particle types are present. ' - 'Only neutron and photon weight windows will be read.') - - # read total number of fine mesh elements in each coarse - # element (nfx, nfy, nfz) - n_fine_x = int(float(next(wwinp))) - n_fine_y = int(float(next(wwinp))) - n_fine_z = int(float(next(wwinp))) - header_mesh_dims = (n_fine_x, n_fine_y, n_fine_z) - - # read the mesh origin: x0, y0, z0 - llc = tuple(float(next(wwinp)) for _ in range(3)) - - # read the number of coarse mesh elements (ncx, ncy, ncz) - n_coarse_x = int(float(next(wwinp))) - n_coarse_y = int(float(next(wwinp))) - n_coarse_z = int(float(next(wwinp))) - - # skip the value defining the geometry type, nwg, we already know this - # 1 - rectilinear mesh - # 2 - cylindrical mesh - # 3 - spherical mesh - mesh_type = int(float(next(wwinp))) - - if mesh_type != 1: - # TODO: support additional mesh types - raise NotImplementedError('Cylindrical and Spherical meshes ' - 'are not currently supported') - - # internal function for parsing mesh coordinates - def _read_mesh_coords(wwinp, n_coarse_bins): - coords = [float(next(wwinp))] - - for _ in range(n_coarse_bins): - # number of fine mesh elements in this coarse element, sx - sx = int(float(next(wwinp))) - # value of next coordinate, px - px = float(next(wwinp)) - # fine mesh ratio, qx (currently unused) - qx = next(wwinp) - # append the fine mesh coordinates for this coarse element - coords += list(np.linspace(coords[-1], px, sx + 1))[1:] - - return np.asarray(coords) - - # read the coordinates for each dimension into a rectilinear mesh mesh = RectilinearMesh() - mesh.x_grid = _read_mesh_coords(wwinp, n_coarse_x) - mesh.y_grid = _read_mesh_coords(wwinp, n_coarse_y) - mesh.z_grid = _read_mesh_coords(wwinp, n_coarse_z) + mesh.x_grid, mesh.y_grid, mesh.z_grid = grids - dims = ('x', 'y', 'z') - # check consistency of mesh coordinates - mesh_llc = mesh_val = (mesh.x_grid[0], mesh.y_grid[0], mesh.z_grid[0]) - for dim, header_val, mesh_val in zip(dims, llc, mesh_llc): - if header_val != mesh_val: - msg = ('The {} corner of the mesh ({}) does not match ' - 'the value read in block 1 of the wwinp file ({})') - raise ValueError(msg.format(dim, mesh_val, header_val)) - - # check total number of mesh elements in each direction - mesh_dims = mesh.dimension - for dim, header_val, mesh_val in zip(dims, header_mesh_dims, mesh_dims): - if header_val != mesh_val: - msg = ('Total number of mesh elements read in the {} ' - 'direction ({}) is inconsistent with the ' - 'number read in block 1 of the wwinp file ({})') - raise ValueError(msg.format(dim, mesh_val, header_val)) - - # read energy bins and weight window values for each particle + # create openmc weight window objects wws = [] - for particle, ne in zip(particles, n_egroups): - # read upper energy bounds - # it is implied that zero is always the first bound in MCNP - e_bounds = np.asarray([0.0] + [float(next(wwinp)) for _ in range(ne)]) - # adjust energy from MeV to eV - e_bounds *= 1e6 - - # create an array for weight window lower bounds - ww_lb = np.zeros((*mesh.dimension, ne)) - for ijk in mesh.indices: - # MCNP ordering for weight windows matches that of OpenMC - # ('xyz' with x changing fastest) - idx = tuple([v - 1 for v in ijk] + [slice(None)]) - ww_lb[idx] = [float(next(wwinp)) for _ in range(ne)] - - # create a WeightWindows object and add it to the output list + for data in particle_data: ww = WeightWindows(id=None, mesh=mesh, - lower_ww_bounds=ww_lb.flatten(), + lower_ww_bounds=data['ww_values'], upper_bound_ratio=5.0, - energy_bounds=e_bounds, - particle_type=particle) + energy_bounds=data['energy_bounds'], + particle_type=data['particle']) wws.append(ww) return wws From a29134ef430872f6d87ff282bcf67de28f8203b8 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 12:18:47 -0500 Subject: [PATCH 0107/2654] Test against flat array now that the attribute is shaped --- tests/unit_tests/weightwindows/test_wwinp_reader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index c225f12f2..9aeaa9f59 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -119,7 +119,7 @@ def test_wwinp_reader(wwinp_data, request): # a reversed array of the flat index into the numpy array n_wws = np.prod((*mesh.dimension, e_bounds.size - 1)) exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1] - np.testing.assert_array_equal(exp_ww_lb, ww.lower_ww_bounds) + np.testing.assert_array_equal(exp_ww_lb, ww.lower_ww_bounds.flatten()) # check expected failures From 5169f4df577a14ad730fda4653bd12447e09908a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 12:22:21 -0500 Subject: [PATCH 0108/2654] PEP8 updates --- openmc/weight_windows.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index c9c9be316..df716498c 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -475,7 +475,8 @@ def wwinp_to_wws(path): elif nr == 10: # read rectilinear data: # number of coarse mesh bins and mesh type - ncx, ncy, ncz, nwg = [int(x) for x in np.fromstring(wwinp.readline(), sep=' ')] + ncx, ncy, ncz, nwg = \ + [int(x) for x in np.fromstring(wwinp.readline(), sep=' ')] else: raise RuntimeError(f'Invalid mesh description (nr) found: {nr}') @@ -523,9 +524,11 @@ def wwinp_to_wws(path): np.insert(time_bounds, (0,), (0.0,)) start_idx = end_idx - # read energy boundaries and convert from MeV to eV + # read energy boundaries end_idx = start_idx + ne[p] - energy_bounds = 1e6 * np.insert(ww_data[start_idx:end_idx], (0,), (0.0,)) + energy_bounds = np.insert(ww_data[start_idx:end_idx], (0,), (0.0,)) + # convert from MeV to eV + energy_bounds *= 1e6 start_idx = end_idx # read weight window values From eaa556c2b61fb449b85ca96ebdbf6bb5fe085fef Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 12:30:26 -0500 Subject: [PATCH 0109/2654] Removing unused imports --- openmc/weight_windows.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index df716498c..2f2325bf4 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -1,8 +1,5 @@ from collections.abc import Iterable -import math -from multiprocessing.sharedctypes import Value from numbers import Real, Integral -import warnings from xml.etree import ElementTree as ET import numpy as np From 2186df8ed4be28f65cf95ec21ad91063fd79aa56 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 12:38:18 -0500 Subject: [PATCH 0110/2654] Comment updates --- openmc/weight_windows.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 2f2325bf4..4ba35bd91 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -515,7 +515,7 @@ def wwinp_to_wws(path): continue if iv > 1: - # unused for now + # time bins are parsed but unused for now end_idx = start_idx + nt[p] time_bounds = ww_data[start_idx:end_idx] np.insert(time_bounds, (0,), (0.0,)) @@ -551,7 +551,7 @@ def wwinp_to_wws(path): coords = [grid_info[0]] # extend the grid based on the next coarse bin endpoint, px - # and the number of fine bines in the coarse bin, sx + # and the number of fine bins in the coarse bin, sx intervals = grid_info[1:].reshape(-1, 3) for sx, px, qx in intervals: coords += list(np.linspace(coords[-1], px, int(sx + 1)))[1:] From a7ce3c92ca838620e198edcd01165b2dd3387045 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 16 Mar 2022 15:44:25 -0500 Subject: [PATCH 0111/2654] fix pugixml linking issue --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38069662a..1d60861d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,7 +446,7 @@ endif() # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES} - pugixml faddeeva xtensor gsl::gsl-lite-v1 fmt::fmt) + pugixml::pugixml faddeeva xtensor gsl::gsl-lite-v1 fmt::fmt) if(dagmc) target_compile_definitions(libopenmc PRIVATE DAGMC) From 387f86389d470e798c752bf8f6db5cdeeb6c6780 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 15:53:00 -0500 Subject: [PATCH 0112/2654] Adding mesh definition checks requested by @eepeterson --- openmc/weight_windows.py | 54 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 4ba35bd91..f4c53470b 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -483,16 +483,18 @@ def wwinp_to_wws(path): # extract mesh data from the ww_data array start_idx = 0 + # first values in the mesh definition arrays are the first + # coordinate of the grid end_idx = start_idx + 1 + 3 * ncx - x_vals = ww_data[start_idx:end_idx] + x0, x_vals = ww_data[start_idx], ww_data[start_idx+1:end_idx] start_idx = end_idx end_idx = start_idx + 1 + 3 * ncy - y_vals = ww_data[start_idx:end_idx] + y0, y_vals = ww_data[start_idx], ww_data[start_idx+1:end_idx] start_idx = end_idx end_idx = start_idx + 1 + 3 * ncz - z_vals = ww_data[start_idx:end_idx] + z0, z_vals = ww_data[start_idx], ww_data[start_idx+1:end_idx] start_idx = end_idx # mesh consistency checks @@ -500,10 +502,35 @@ def wwinp_to_wws(path): raise ValueError(f'Mesh description in header ({nr}) ' f'does not match the mesh type ({nwg})') - if not (xyz0 == (x_vals[0], y_vals[0], z_vals[0])).all(): + if not (xyz0 == (x0, y0, z0)).all(): raise ValueError(f'Mesh origin in the header ({xyz0}) ' f' does not match the origin in the mesh ' - f' description ({x_vals[0], y_vals[0], z_vals[0]})') + f' description ({x0, y0, z0})') + + # create openmc mesh object + grids = [] + mesh_definition = [(x0, x_vals, nfx), (y0, y_vals, nfy), (z0, z_vals, nfz)] + for grid0, grid_vals, n_pnts in mesh_definition: + # file spec checks for the mesh definition + if not all(grid_vals[2::3] == 1.0): + raise ValueError('One or more mesh ratio value, qx, ' + 'is not equal to one') + + if np.sum(grid_vals[::3]) != n_pnts: + raise ValueError('Sum of the fine bin entries, s, does ' + 'not match the number of fine bins') + + # extend the grid based on the next coarse bin endpoint, px + # and the number of fine bins in the coarse bin, sx + intervals = grid_vals.reshape(-1, 3) + coords = [grid0] + for sx, px, qx in intervals: + coords += list(np.linspace(coords[-1], px, int(sx + 1)))[1:] + + grids.append(np.array(coords)) + + mesh = RectilinearMesh() + mesh.x_grid, mesh.y_grid, mesh.z_grid = grids # extract weight window values from array particle_types = {0: 'neutron', 1: 'photon'} @@ -544,23 +571,6 @@ def wwinp_to_wws(path): 'ww_values': ww_values} particle_data.append(particle_dict) - # create openmc mesh object - grids = [] - for grid_info in [x_vals, y_vals, z_vals]: - # first value is the start of the grid - coords = [grid_info[0]] - - # extend the grid based on the next coarse bin endpoint, px - # and the number of fine bins in the coarse bin, sx - intervals = grid_info[1:].reshape(-1, 3) - for sx, px, qx in intervals: - coords += list(np.linspace(coords[-1], px, int(sx + 1)))[1:] - - grids.append(np.asarray(coords)) - - mesh = RectilinearMesh() - mesh.x_grid, mesh.y_grid, mesh.z_grid = grids - # create openmc weight window objects wws = [] for data in particle_data: From b0a4871710ad28720dc1b73301844fecf57104a2 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 22:51:47 -0500 Subject: [PATCH 0113/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/weight_windows.py | 10 +++++----- tests/unit_tests/weightwindows/test_wwinp_reader.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index f4c53470b..c820f3a41 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -452,14 +452,14 @@ def wwinp_to_wws(path): # read coarse mesh dimensions and lower left corner mesh_description = np.fromstring(wwinp.readline(), sep=' ') - nfx, nfy, nfz = [int(x) for x in mesh_description[:3]] + nfx, nfy, nfz = mesh_description[:3].astype(int) xyz0 = mesh_description[3:] # read cylindrical and spherical mesh vectors if present if nr == 16: # read number of coarse bins line_arr = np.fromstring(wwinp.readline(), sep=' ') - ncx, ncy, ncz = [int(x) for x in line_arr[:3]] + ncx, ncy, ncz = line_arr[:3].astype(int) # read polar vector (x1, y1, z1) xyz1 = line_arr[3:] - xyz0 polar_vec = xyz1 / np.linalg.norm(xyz1) @@ -502,7 +502,7 @@ def wwinp_to_wws(path): raise ValueError(f'Mesh description in header ({nr}) ' f'does not match the mesh type ({nwg})') - if not (xyz0 == (x0, y0, z0)).all(): + if (xyz0 != (x0, y0, z0)).any(): raise ValueError(f'Mesh origin in the header ({xyz0}) ' f' does not match the origin in the mesh ' f' description ({x0, y0, z0})') @@ -512,11 +512,11 @@ def wwinp_to_wws(path): mesh_definition = [(x0, x_vals, nfx), (y0, y_vals, nfy), (z0, z_vals, nfz)] for grid0, grid_vals, n_pnts in mesh_definition: # file spec checks for the mesh definition - if not all(grid_vals[2::3] == 1.0): + if (grid_vals[2::3] != 1.0).any(): raise ValueError('One or more mesh ratio value, qx, ' 'is not equal to one') - if np.sum(grid_vals[::3]) != n_pnts: + if grid_vals[::3].sum() != n_pnts: raise ValueError('Sum of the fine bin entries, s, does ' 'not match the number of fine bins') diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index 9aeaa9f59..434a36753 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -1,6 +1,6 @@ -import numpy as np from pathlib import Path +import numpy as np import openmc import pytest From a86c4720954cf34d00a6d6596bb4a9f0a7c03dec Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 16 Mar 2022 22:56:44 -0500 Subject: [PATCH 0114/2654] Replacing comprehension with numpy call --- openmc/weight_windows.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index c820f3a41..499772bcf 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -473,7 +473,7 @@ def wwinp_to_wws(path): # read rectilinear data: # number of coarse mesh bins and mesh type ncx, ncy, ncz, nwg = \ - [int(x) for x in np.fromstring(wwinp.readline(), sep=' ')] + np.fromstring(wwinp.readline(), sep=' ').astype(int) else: raise RuntimeError(f'Invalid mesh description (nr) found: {nr}') @@ -534,7 +534,7 @@ def wwinp_to_wws(path): # extract weight window values from array particle_types = {0: 'neutron', 1: 'photon'} - particle_data = [] + wws = [] for p in range(ni): # no information to read for this particle if # either the energy bins or time bins are empty @@ -565,21 +565,13 @@ def wwinp_to_wws(path): ww_values = np.swapaxes(ww_values, 2, 0) start_idx = end_idx - # gather particle data in container - particle_dict = {'particle': particle_types[p], - 'energy_bounds': energy_bounds, - 'ww_values': ww_values} - particle_data.append(particle_dict) - - # create openmc weight window objects - wws = [] - for data in particle_data: + # create a weight window object ww = WeightWindows(id=None, mesh=mesh, - lower_ww_bounds=data['ww_values'], + lower_ww_bounds=ww_values, upper_bound_ratio=5.0, - energy_bounds=data['energy_bounds'], - particle_type=data['particle']) + energy_bounds=energy_bounds, + particle_type=particle_types[p]) wws.append(ww) return wws From faa142c78d590a3bf27d39f816c670bf5244f182 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 17 Mar 2022 09:20:37 -0500 Subject: [PATCH 0115/2654] Apply suggestions from @eepeterson Co-authored-by: Ethan Peterson --- openmc/weight_windows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 499772bcf..f7963628d 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -525,7 +525,7 @@ def wwinp_to_wws(path): intervals = grid_vals.reshape(-1, 3) coords = [grid0] for sx, px, qx in intervals: - coords += list(np.linspace(coords[-1], px, int(sx + 1)))[1:] + coords += np.linspace(coords[-1], px, int(sx + 1)).tolist()[1:] grids.append(np.array(coords)) From 2ab0e23bc6efe37a62d10d9ba1140e608ef1b686 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 17 Mar 2022 10:10:49 -0500 Subject: [PATCH 0116/2654] Apply suggestions from code review - remove check for xtl Co-authored-by: Paul Romano --- CMakeLists.txt | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d60861d3..151e8e5a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,12 +77,6 @@ if(xtensor_FOUND) else() message(STATUS "Did not find xtensor, will use submodule instead") endif() -find_package(xtl QUIET NO_SYSTEM_ENVIRONMENT_PATH) -if(xtl_FOUND) - message(STATUS "Found xtl: ${xtl_DIR} (version ${xtl_VERSION})") -else() - message(STATUS "Did not find xtl, will use submodule instead") -endif() find_package(gsl-lite QUIET NO_SYSTEM_ENVIRONMENT_PATH) if(gsl-lite_FOUND) message(STATUS "Found gsl-lite: ${gsl-lite_DIR} (version ${gsl-lite_VERSION})") @@ -228,12 +222,9 @@ if (NOT (CMAKE_VERSION VERSION_LESS 3.13)) cmake_policy(SET CMP0079 NEW) endif() -if (NOT xtl_FOUND) +if (NOT xtensor_FOUND) add_subdirectory(vendor/xtl) set(xtl_DIR ${CMAKE_CURRENT_BINARY_DIR}/vendor/xtl) -endif() - -if (NOT xtensor_FOUND) add_subdirectory(vendor/xtensor) endif() From ad10441659f3592df23a5c13cef048fcc4245fe9 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 17 Mar 2022 10:18:15 -0500 Subject: [PATCH 0117/2654] different cases for linking pugixml depending on version --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 151e8e5a9..21e97f20b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -437,7 +437,13 @@ endif() # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES} - pugixml::pugixml faddeeva xtensor gsl::gsl-lite-v1 fmt::fmt) + faddeeva xtensor gsl::gsl-lite-v1 fmt::fmt) + +if(TARGET pugixml::pugixml) + target_link_libraries(libopenmc pugixml::pugixml) +else() + target_link_libraries(libopenmc pugixml) +endif() if(dagmc) target_compile_definitions(libopenmc PRIVATE DAGMC) From b4274724f36df89691e6452877e35139d0a459f2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 17 Mar 2022 10:58:49 -0500 Subject: [PATCH 0118/2654] explicitly include xmanipulation header for xt::flip --- src/plot.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plot.cpp b/src/plot.cpp index c24a023f2..b012ed131 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -6,6 +6,7 @@ #include #include "xtensor/xview.hpp" +#include "xtensor/xmanipulation.hpp" #include #include #ifdef USE_LIBPNG From ea551e3312838f73eca5eb3d1cc7b689e37dc279 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 17 Mar 2022 16:05:47 -0500 Subject: [PATCH 0119/2654] update versions of xtl and xtensor in vectfit ci build script to be consistent with vendored versions --- tools/ci/gha-install-vectfit.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci/gha-install-vectfit.sh b/tools/ci/gha-install-vectfit.sh index 343942e03..5884c6fac 100755 --- a/tools/ci/gha-install-vectfit.sh +++ b/tools/ci/gha-install-vectfit.sh @@ -4,10 +4,10 @@ set -ex PYBIND_BRANCH='master' PYBIND_REPO='https://github.com/pybind/pybind11' -XTL_BRANCH='0.6.9' +XTL_BRANCH='0.6.13' XTL_REPO='https://github.com/xtensor-stack/xtl' -XTENSOR_BRANCH='0.21.2' +XTENSOR_BRANCH='0.21.3' XTENSOR_REPO='https://github.com/xtensor-stack/xtensor' XTENSOR_PYTHON_BRANCH='0.24.1' From cfd6baf5ad4bbdfc6002914cbfbed4e9af16e170 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 17 Mar 2022 21:44:34 -0500 Subject: [PATCH 0120/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/weight_windows.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index f7963628d..cbc807d06 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -533,9 +533,8 @@ def wwinp_to_wws(path): mesh.x_grid, mesh.y_grid, mesh.z_grid = grids # extract weight window values from array - particle_types = {0: 'neutron', 1: 'photon'} wws = [] - for p in range(ni): + for ne_i, nt_i, particle_type in zip(ne, nt, ('neutron', 'photon')): # no information to read for this particle if # either the energy bins or time bins are empty if ne[p] == 0 or nt[p] == 0: From c53c60fd6196fbdf3f721bd3454794a6cdccc3f6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 17 Mar 2022 21:47:40 -0500 Subject: [PATCH 0121/2654] Updating variables in loop --- openmc/weight_windows.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index cbc807d06..fbd3c84ac 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -537,29 +537,29 @@ def wwinp_to_wws(path): for ne_i, nt_i, particle_type in zip(ne, nt, ('neutron', 'photon')): # no information to read for this particle if # either the energy bins or time bins are empty - if ne[p] == 0 or nt[p] == 0: + if ne_i == 0 or nt_i == 0: continue if iv > 1: # time bins are parsed but unused for now - end_idx = start_idx + nt[p] + end_idx = start_idx + nt_i time_bounds = ww_data[start_idx:end_idx] np.insert(time_bounds, (0,), (0.0,)) start_idx = end_idx # read energy boundaries - end_idx = start_idx + ne[p] + end_idx = start_idx + ne_i energy_bounds = np.insert(ww_data[start_idx:end_idx], (0,), (0.0,)) # convert from MeV to eV energy_bounds *= 1e6 start_idx = end_idx # read weight window values - end_idx = start_idx + (nfx * nfy * nfz) * nt[p] * ne[p] + end_idx = start_idx + (nfx * nfy * nfz) * nt_i * ne_i # read values and reshape according to ordering # slowest to fastest: z, y, x, e - ww_values = ww_data[start_idx:end_idx].reshape(nfz, nfy, nfx, ne[p]) + ww_values = ww_data[start_idx:end_idx].reshape(nfz, nfy, nfx, ne_i) # swap z and x axes for correct shape and (ijk, e) mesh indexing ww_values = np.swapaxes(ww_values, 2, 0) start_idx = end_idx @@ -570,7 +570,7 @@ def wwinp_to_wws(path): lower_ww_bounds=ww_values, upper_bound_ratio=5.0, energy_bounds=energy_bounds, - particle_type=particle_types[p]) + particle_type=particle_type) wws.append(ww) return wws From d39642136a4d1f7bff984dbae55d9e9bde270214 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 17 Mar 2022 22:03:10 -0500 Subject: [PATCH 0122/2654] Use macro in CMakeLists.txt to simplify dependency finding --- CMakeLists.txt | 51 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21e97f20b..81ef0c9d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,9 +43,23 @@ if(${CMAKE_CXX_COMPILER} MATCHES "(mpi[^/]*|CC)$") set(MPI_ENABLED TRUE) endif() +#=============================================================================== +# Helper macro for finding a dependency +#=============================================================================== + +macro(find_package_write_status pkg) + find_package(${pkg} QUIET NO_SYSTEM_ENVIRONMENT_PATH) + if(${pkg}_FOUND) + message(STATUS "Found ${pkg}: ${${pkg}_DIR} (version ${${pkg}_VERSION})") + else() + message(STATUS "Did not find ${pkg}, will use submodule instead") + endif() +endmacro() + #=============================================================================== # DAGMC Geometry Support - need DAGMC/MOAB #=============================================================================== + if(dagmc) find_package(DAGMC REQUIRED PATH_SUFFIXES lib/cmake) if (${DAGMC_VERSION} VERSION_LESS 3.2.0) @@ -54,38 +68,10 @@ if(dagmc) endif() endif() -#=============================================================================== -# Check for submodules perhaps already on system -#=============================================================================== - -# If not found, we just pull appropriate versions from github and build them. -find_package(fmt QUIET NO_SYSTEM_ENVIRONMENT_PATH) -if(fmt_FOUND) - message(STATUS "Found fmt: ${fmt_DIR} (version ${fmt_VERSION})") -else() - message(STATUS "Did not find fmt, will use submodule instead") -endif() -find_package(pugixml QUIET NO_SYSTEM_ENVIRONMENT_PATH) -if(pugixml_FOUND) - message(STATUS "Found pugixml: ${pugixml_DIR}") -else() - message(STATUS "Did not find pugixml, will use submodule instead") -endif() -find_package(xtensor QUIET NO_SYSTEM_ENVIRONMENT_PATH) -if(xtensor_FOUND) - message(STATUS "Found xtensor: ${xtensor_DIR} (version ${xtensor_VERSION})") -else() - message(STATUS "Did not find xtensor, will use submodule instead") -endif() -find_package(gsl-lite QUIET NO_SYSTEM_ENVIRONMENT_PATH) -if(gsl-lite_FOUND) - message(STATUS "Found gsl-lite: ${gsl-lite_DIR} (version ${gsl-lite_VERSION})") -else() - message(STATUS "Did not find gsl-lite, will use submodule instead") -endif() #=============================================================================== # libMesh Unstructured Mesh Support #=============================================================================== + if(libmesh) find_package(LIBMESH REQUIRED) endif() @@ -93,6 +79,7 @@ endif() #=============================================================================== # libpng #=============================================================================== + find_package(PNG) #=============================================================================== @@ -137,9 +124,9 @@ endif() if(NOT MSVC) if(openmp) - # Requires CMake 3.1+ find_package(OpenMP) if(OPENMP_FOUND) + # In CMake 3.9+, can use the OpenMP::OpenMP_CXX imported target list(APPEND cxxflags ${OpenMP_CXX_FLAGS}) list(APPEND ldflags ${OpenMP_CXX_FLAGS}) endif() @@ -199,6 +186,7 @@ endif() # pugixml library #=============================================================================== +find_package_write_status(pugixml) if (NOT pugixml_FOUND) add_subdirectory(vendor/pugixml) set_target_properties(pugixml PROPERTIES CXX_STANDARD 14 CXX_EXTENSIONS OFF) @@ -208,6 +196,7 @@ endif() # {fmt} library #=============================================================================== +find_package_write_status(fmt) if (NOT fmt_FOUND) set(FMT_INSTALL ON CACHE BOOL "Generate the install target.") add_subdirectory(vendor/fmt) @@ -222,6 +211,7 @@ if (NOT (CMAKE_VERSION VERSION_LESS 3.13)) cmake_policy(SET CMP0079 NEW) endif() +find_package_write_status(xtensor) if (NOT xtensor_FOUND) add_subdirectory(vendor/xtl) set(xtl_DIR ${CMAKE_CURRENT_BINARY_DIR}/vendor/xtl) @@ -232,6 +222,7 @@ endif() # GSL header-only library #=============================================================================== +find_package_write_status(gsl-lite) if (NOT gsl-lite_FOUND) add_subdirectory(vendor/gsl-lite) From 78885ce17c562a06d41d1374c96147d4965614e0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 17 Mar 2022 22:26:26 -0500 Subject: [PATCH 0123/2654] Add wwinp_to_wws to documentation --- docs/source/pythonapi/base.rst | 3 +-- openmc/weight_windows.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index 721f3d113..b471d12a8 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -27,14 +27,13 @@ Simulation Settings openmc.WeightWindows openmc.Settings -The following function can be used for generating a source file: - .. autosummary:: :toctree: generated :nosignatures: :template: myfunction.rst openmc.write_source_file + openmc.wwinp_to_wws Material Specification ---------------------- diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index fbd3c84ac..2e5b7d8e0 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -413,7 +413,7 @@ def wwinp_to_wws(path): Parameters ---------- - path : str or pathlib.Path object + path : str or pathlib.Path Path to the wwinp file Returns From 32da4f2504967c985f074cfe430e4a56fac2b995 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 21 Mar 2022 14:07:03 -0500 Subject: [PATCH 0124/2654] remove optimize and debug build options because they are redudant w/ cmake_build_type --- CMakeLists.txt | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81ef0c9d2..a047cc9a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,12 +27,12 @@ endif() option(openmp "Enable shared-memory parallelism with OpenMP" ON) option(profile "Compile with profiling flags" OFF) -option(debug "Compile with debug flags" OFF) -option(optimize "Turn on all compiler optimization flags" OFF) option(coverage "Compile with coverage analysis flags" OFF) option(dagmc "Enable support for DAGMC (CAD) geometry" OFF) option(libmesh "Enable support for libMesh unstructured mesh tallies" OFF) +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") + #=============================================================================== # MPI for distributed-memory parallelism #=============================================================================== @@ -134,18 +134,13 @@ endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND cxxflags -O2) -if(debug) - list(REMOVE_ITEM cxxflags -O2) - list(APPEND cxxflags -g -O0) +if (NOT ${CMAKE_BUILD_TYPE}) + add_compile_options(-O2) endif() + if(profile) list(APPEND cxxflags -g -fno-omit-frame-pointer) endif() -if(optimize) - list(REMOVE_ITEM cxxflags -O2) - list(APPEND cxxflags -O3) -endif() if(coverage) list(APPEND cxxflags --coverage) list(APPEND ldflags --coverage) From fcf25b5aba599c372eeeeb44570ddbdd017f63e2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 21 Mar 2022 15:39:31 -0500 Subject: [PATCH 0125/2654] set default build configuration to release --- CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a047cc9a6..27a8f06ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,13 @@ option(coverage "Compile with coverage analysis flags" OFF) option(dagmc "Enable support for DAGMC (CAD) geometry" OFF) option(libmesh "Enable support for libMesh unstructured mesh tallies" OFF) -message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +#=============================================================================== +# Set build configuration to Release if not set +#=============================================================================== + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() #=============================================================================== # MPI for distributed-memory parallelism @@ -134,10 +140,6 @@ endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) -if (NOT ${CMAKE_BUILD_TYPE}) - add_compile_options(-O2) -endif() - if(profile) list(APPEND cxxflags -g -fno-omit-frame-pointer) endif() From 0655e7392960758efa2791c80a245620b4590bb1 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 21 Mar 2022 15:51:19 -0500 Subject: [PATCH 0126/2654] removed debug and optimize options from install docs --- docs/source/usersguide/install.rst | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index fb721c7ce..ebcd20eb4 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -331,17 +331,9 @@ CMakeLists.txt Options The following options are available in the CMakeLists.txt file: -debug - Enables debugging when compiling. The flags added are dependent on which - compiler is used. - profile Enables profiling using the GNU profiler, gprof. -optimize - Enables high-optimization using compiler-dependent flags. For gcc and - Intel C++, this compiles with -O3. - openmp Enables shared-memory parallelism using the OpenMP API. The C++ compiler being used must support OpenMP. (Default: on) @@ -360,12 +352,12 @@ coverage Compile and link code instrumented for coverage analysis. This is typically used in conjunction with gcov_. -To set any of these options (e.g. turning on debug mode), the following form +To set any of these options (e.g. turning on profiling), the following form should be used: .. code-block:: sh - cmake -Ddebug=on /path/to/openmc + cmake -Dprofile=on /path/to/openmc .. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html From 733604216a161061cd6c7a13e16f2476b6f6e21f Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 21 Mar 2022 15:53:53 -0500 Subject: [PATCH 0127/2654] removed optimize and debug from dockerfile --- Dockerfile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 367777b6e..dc7d25f6c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -179,8 +179,6 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ && mkdir build && cd build ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ - -Doptimize=off \ - -Ddebug=off \ -DHDF5_PREFER_PARALLEL=on \ -Ddagmc=on \ -Dlibmesh=on \ @@ -188,24 +186,18 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ fi ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "off" ]; then \ cmake ../openmc \ - -Doptimize=off \ - -Ddebug=off \ -DHDF5_PREFER_PARALLEL=on \ -Ddagmc=ON \ -DCMAKE_PREFIX_PATH=${DAGMC_INSTALL_DIR} ; \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ - -Doptimize=off \ - -Ddebug=off \ -DHDF5_PREFER_PARALLEL=on \ -Dlibmesh=on \ -DCMAKE_PREFIX_PATH=${LIBMESH_INSTALL_DIR} ; \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "off" ]; then \ cmake ../openmc \ - -Doptimize=off \ - -Ddebug=off \ -DHDF5_PREFER_PARALLEL=on ; \ fi ; \ make 2>/dev/null -j${compile_cores} install \ From 643749a0a0c33addbc92bf12db41d09d4a4775e0 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 21 Mar 2022 15:56:27 -0500 Subject: [PATCH 0128/2654] specify debug with cmake_build_type --- tools/ci/gha-install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index 9c163c1dc..f22a74410 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -26,7 +26,7 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): os.chdir('build') # Build in debug mode by default - cmake_cmd = ['cmake', '-Ddebug=on'] + cmake_cmd = ['cmake', '-DCMAKE_BUILD_TYPE=Debug'] # Turn off OpenMP if specified if not omp: From dc18f59d828f1b77a29a9121d1586a482d4954d6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 22 Mar 2022 06:53:47 -0500 Subject: [PATCH 0129/2654] Allow user to override num processes used for depletion --- docs/source/pythonapi/deplete.rst | 6 ++++++ openmc/deplete/pool.py | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index d4a0f128f..383268f8b 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -166,6 +166,12 @@ with :func:`cram.CRAM48` being the default. :type: bool +.. data:: pool.NUM_PROCESSES + + Number of worker processes used for depletion calculations, which rely on the + :class:`multiprocessing.pool.Pool` class. If set to ``None`` (default), the + number returned by :func:`os.cpu_count` is used. + The following classes are used to help the :class:`openmc.deplete.Operator` compute quantities like effective fission yields, reaction rates, and total system energy. diff --git a/openmc/deplete/pool.py b/openmc/deplete/pool.py index 8360ef602..a3d37f79f 100644 --- a/openmc/deplete/pool.py +++ b/openmc/deplete/pool.py @@ -10,6 +10,10 @@ from multiprocessing import Pool # multiprocessing routines during depletion USE_MULTIPROCESSING = True +# Allow user to override the number of worker processes to use for depletion +# calculations +NUM_PROCESSES = None + def deplete(func, chain, x, rates, dt, matrix_func=None): """Deplete materials using given reaction rates for a specified time @@ -58,7 +62,7 @@ def deplete(func, chain, x, rates, dt, matrix_func=None): inputs = zip(matrices, x, repeat(dt)) if USE_MULTIPROCESSING: - with Pool() as pool: + with Pool(NUM_PROCESSES) as pool: x_result = list(pool.starmap(func, inputs)) else: x_result = list(starmap(func, inputs)) From 97bec2838031cf874a5f1fa6175c922dd0384b8b Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 22 Mar 2022 10:02:04 -0500 Subject: [PATCH 0130/2654] set default build with cache variable Co-authored-by: Paul Romano --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27a8f06ad..6a0066dc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ option(libmesh "Enable support for libMesh unstructured mesh tallies" OFF) #=============================================================================== if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build" FORCE) endif() #=============================================================================== From d24c1805927254d7964f614c48f8bdb182da7bc3 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 22 Mar 2022 10:46:34 -0500 Subject: [PATCH 0131/2654] update scripts with new cmake flag names --- CMakeLists.txt | 24 ++++++++++++------------ Dockerfile | 8 ++++---- tools/ci/gha-install.py | 8 ++++---- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a0066dc6..168309de8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,11 +25,11 @@ endif() # Command line options #=============================================================================== -option(openmp "Enable shared-memory parallelism with OpenMP" ON) -option(profile "Compile with profiling flags" OFF) -option(coverage "Compile with coverage analysis flags" OFF) -option(dagmc "Enable support for DAGMC (CAD) geometry" OFF) -option(libmesh "Enable support for libMesh unstructured mesh tallies" OFF) +option(OPENMC_ENABLE_PROFILE "Enable shared-memory parallelism with OpenMP" ON) +option(OPENMC_ENABLE_COVERAGE "Compile with profiling flags" OFF) +option(OPENMC_USE_OPENMP "Compile with coverage analysis flags" OFF) +option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) +option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) #=============================================================================== # Set build configuration to Release if not set @@ -66,7 +66,7 @@ endmacro() # DAGMC Geometry Support - need DAGMC/MOAB #=============================================================================== -if(dagmc) +if(OPENMC_USE_DAGMC) find_package(DAGMC REQUIRED PATH_SUFFIXES lib/cmake) if (${DAGMC_VERSION} VERSION_LESS 3.2.0) message(FATAL_ERROR "Discovered DAGMC Version: ${DAGMC_VERSION}. \ @@ -78,7 +78,7 @@ endif() # libMesh Unstructured Mesh Support #=============================================================================== -if(libmesh) +if(OPENMC_USE_LIBMESH) find_package(LIBMESH REQUIRED) endif() @@ -129,7 +129,7 @@ endif() # Skip for Visual Studio which has its own configurations through GUI if(NOT MSVC) -if(openmp) +if(OPENMC_USE_OPENMP) find_package(OpenMP) if(OPENMP_FOUND) # In CMake 3.9+, can use the OpenMP::OpenMP_CXX imported target @@ -140,10 +140,10 @@ endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) -if(profile) +if(OPENMC_ENABLE_PROFILE) list(APPEND cxxflags -g -fno-omit-frame-pointer) endif() -if(coverage) +if(OPENMC_ENABLE_COVERAGE) list(APPEND cxxflags --coverage) list(APPEND ldflags --coverage) endif() @@ -433,12 +433,12 @@ else() target_link_libraries(libopenmc pugixml) endif() -if(dagmc) +if(OPENMC_USE_DAGMC) target_compile_definitions(libopenmc PRIVATE DAGMC) target_link_libraries(libopenmc dagmc-shared uwuw-shared) endif() -if(libmesh) +if(OPENMC_USE_LIBMESH) target_compile_definitions(libopenmc PRIVATE LIBMESH) target_link_libraries(libopenmc PkgConfig::LIBMESH) endif() diff --git a/Dockerfile b/Dockerfile index dc7d25f6c..6a9b89009 100644 --- a/Dockerfile +++ b/Dockerfile @@ -180,20 +180,20 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ -DHDF5_PREFER_PARALLEL=on \ - -Ddagmc=on \ - -Dlibmesh=on \ + -DOPENMC_USE_DAGMC=on \ + -DOPENMC_USE_LIBMESH=on \ -DCMAKE_PREFIX_PATH="${DAGMC_INSTALL_DIR};${LIBMESH_INSTALL_DIR}" ; \ fi ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "off" ]; then \ cmake ../openmc \ -DHDF5_PREFER_PARALLEL=on \ - -Ddagmc=ON \ + -DOPENMC_USE_DAGMC=ON \ -DCMAKE_PREFIX_PATH=${DAGMC_INSTALL_DIR} ; \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ -DHDF5_PREFER_PARALLEL=on \ - -Dlibmesh=on \ + -DOPENMC_USE_LIBMESH=on \ -DCMAKE_PREFIX_PATH=${LIBMESH_INSTALL_DIR} ; \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "off" ]; then \ diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index f22a74410..4cc85671d 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -30,7 +30,7 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): # Turn off OpenMP if specified if not omp: - cmake_cmd.append('-Dopenmp=off') + cmake_cmd.append('-DOPENMC_USE_OPENMP=off') # Use MPI wrappers when building in parallel if mpi: @@ -46,16 +46,16 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): cmake_cmd.append('-DHDF5_PREFER_PARALLEL=OFF') if dagmc: - cmake_cmd.append('-Ddagmc=ON') + cmake_cmd.append('-DOPENMC_USE_DAGMC=ON') cmake_cmd.append('-DCMAKE_PREFIX_PATH=~/DAGMC') if libmesh: - cmake_cmd.append('-Dlibmesh=ON') + cmake_cmd.append('-DOPENMC_USE_LIBMESH=ON') libmesh_path = os.environ.get('HOME') + '/LIBMESH' cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + libmesh_path) # Build in coverage mode for coverage testing - cmake_cmd.append('-Dcoverage=on') + cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') # Build and install cmake_cmd.append('..') From 61ace1ab09ef6d1a2186dda663416c9699aa86b2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 22 Mar 2022 10:50:58 -0500 Subject: [PATCH 0132/2654] update documentation with new options names --- docs/source/usersguide/install.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index ebcd20eb4..7aa1fdcff 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -331,33 +331,33 @@ CMakeLists.txt Options The following options are available in the CMakeLists.txt file: -profile - Enables profiling using the GNU profiler, gprof. +OPENMC_ENABLE_PROFILE + Enables profiling using the GNU profiler, gprof. (Default: off) -openmp +OPENMC_USE_OPENMP Enables shared-memory parallelism using the OpenMP API. The C++ compiler being used must support OpenMP. (Default: on) -dagmc +OPENMC_USE_DAGMC Enables use of CAD-based DAGMC_ geometries and MOAB_ unstructured mesh tallies. Please see the note about DAGMC in the optional dependencies list for more information on this feature. The installation directory for DAGMC should also be defined as `DAGMC_ROOT` in the CMake configuration command. (Default: off) -libmesh +OPENMC_USE_LIBMESH Enables the use of unstructured mesh tallies with libMesh_. (Default: off) -coverage +OPENMC_ENABLE_COVERAGE Compile and link code instrumented for coverage analysis. This is typically - used in conjunction with gcov_. + used in conjunction with gcov_. (Default: off) To set any of these options (e.g. turning on profiling), the following form should be used: .. code-block:: sh - cmake -Dprofile=on /path/to/openmc + cmake -DOPENMC_ENABLE_PROFILE=on /path/to/openmc .. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html From d118617e292762989a0960f4b0a6cef4dd28d6d2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 22 Mar 2022 11:09:25 -0500 Subject: [PATCH 0133/2654] added section on build types to install doc --- docs/source/usersguide/install.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 7aa1fdcff..d5b1c7e41 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -363,6 +363,27 @@ should be used: .. _usersguide_compile_mpi: +Specifying the Build Type ++++++++++++++++++++++++++ + +OpenMC can be configured for debug, release, or release with debug info by setting +the `CMAKE_BUILD_TYPE` option. + +Debug + Enable debug compiler flags with no optimization `-O0 -g`. + +Release + Disable debug and enable optimization `-O3 -DNDEBUG`. + +RelWithDebInfo + (Default if no type is specified.) Enable optimization and debug `-O2 -g`. + +Example of configuring for Debug mode: + +.. code-block:: sh + + cmake -DCMAKE_BUILD_TYPE=Debug /path/to/openmc + Compiling with MPI ++++++++++++++++++ From 62bb9ebf990bf1062d6cf8f9137f535a1cbb0c44 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 22 Mar 2022 13:23:02 -0500 Subject: [PATCH 0134/2654] corrected install options in cmake config --- cmake/OpenMCConfig.cmake.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/OpenMCConfig.cmake.in b/cmake/OpenMCConfig.cmake.in index b12e95f23..8f7ae7193 100644 --- a/cmake/OpenMCConfig.cmake.in +++ b/cmake/OpenMCConfig.cmake.in @@ -5,11 +5,11 @@ find_package(gsl-lite REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../gsl-lite) find_package(pugixml REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../pugixml) find_package(xtl REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../xtl) find_package(xtensor REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../xtensor) -if(@dagmc@) +if(@OPENMC_USE_DAGMC@) find_package(DAGMC REQUIRED HINTS @DAGMC_DIR@) endif() -if(@libmesh@) +if(@OPENMC_USE_LIBMESH@) include(FindPkgConfig) list(APPEND CMAKE_PREFIX_PATH @LIBMESH_PREFIX@) set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH True) From 0e79264e7fb9e4e1b0c9fafb7b531c734cd2d493 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 22 Mar 2022 13:27:40 -0500 Subject: [PATCH 0135/2654] corrected install docs with new dagmc and libmess flags --- docs/source/usersguide/install.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index d5b1c7e41..dcf55948c 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -252,7 +252,7 @@ Prerequisites In addition to turning this option on, the path to the DAGMC installation should be specified as part of the ``CMAKE_PREFIX_PATH`` variable:: - cmake -Ddagmc=on -DCMAKE_PREFIX_PATH=/path/to/dagmc/installation + cmake -DOPENMC_USE_DAGMC=on -DCMAKE_PREFIX_PATH=/path/to/dagmc/installation * libMesh_ mesh library framework for numerical simulations of partial differential equations @@ -263,7 +263,7 @@ Prerequisites installation should be specified as part of the ``CMAKE_PREFIX_PATH`` variable.:: - CXX=mpicxx cmake -Dlibmesh=on -DCMAKE_PREFIX_PATH=/path/to/libmesh/installation + CXX=mpicxx cmake -DOPENMC_USE_LIBMESH=on -DCMAKE_PREFIX_PATH=/path/to/libmesh/installation Note that libMesh is most commonly compiled with MPI support. If that is the case, then OpenMC should be compiled with MPI support as well. From 3f2d85cad331f3db38cef5479b839dc3f5534f03 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 22 Mar 2022 14:34:26 -0500 Subject: [PATCH 0136/2654] fix order --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 168309de8..772256f84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,9 +25,9 @@ endif() # Command line options #=============================================================================== -option(OPENMC_ENABLE_PROFILE "Enable shared-memory parallelism with OpenMP" ON) -option(OPENMC_ENABLE_COVERAGE "Compile with profiling flags" OFF) -option(OPENMC_USE_OPENMP "Compile with coverage analysis flags" OFF) +option(OPENMC_USE_OPENMP "Enable shared-memory parallelism with OpenMP" ON) +option(OPENMC_ENABLE_PROFILE "Compile with profiling flags" OFF) +option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" OFF) option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) From 4f93bf22f566dbfab9cb2713681d57d411c9e31b Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 23 Mar 2022 09:53:50 -0500 Subject: [PATCH 0137/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- CMakeLists.txt | 3 ++- docs/source/usersguide/install.rst | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 772256f84..bc9e12c91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,8 @@ option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tall # Set build configuration to Release if not set #=============================================================================== -if (NOT CMAKE_BUILD_TYPE) +if(NOT CMAKE_BUILD_TYPE) + message(STATUS "No build type selected, defaulting to RelWithDebInfo") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build" FORCE) endif() diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index dcf55948c..42258b086 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -352,7 +352,7 @@ OPENMC_ENABLE_COVERAGE Compile and link code instrumented for coverage analysis. This is typically used in conjunction with gcov_. (Default: off) -To set any of these options (e.g. turning on profiling), the following form +To set any of these options (e.g., turning on profiling), the following form should be used: .. code-block:: sh From 094330ef12a2ff3a3d781204957d3400966a4081 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 23 Mar 2022 10:49:42 -0500 Subject: [PATCH 0138/2654] code review suggestions Co-authored-by: Paul Romano --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc9e12c91..ba8a79efa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) #=============================================================================== -# Set build configuration to Release if not set +# Set a default build configuration if not explicitly specified #=============================================================================== if(NOT CMAKE_BUILD_TYPE) From d74cf4fca765b7de3c09795671ca417a2b8e5809 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 24 Mar 2022 15:59:36 +0000 Subject: [PATCH 0139/2654] allow ci to be skipped for non code files --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e65e630b1..6c83cc669 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,11 @@ on: workflow_dispatch: pull_request: + paths-ignore: + - 'docs/**' + - '**.md' + - CODEOWNERS + - LICENSE branches: - develop - master From 67ffa58145ecce01741ba090b30c2b5bb1144e0d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 24 Mar 2022 16:05:18 +0000 Subject: [PATCH 0140/2654] added conda badge :snake: --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 186c1e5e0..bd7a8479a 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Code Coverage](https://coveralls.io/repos/github/openmc-dev/openmc/badge.svg?branch=develop)](https://coveralls.io/github/openmc-dev/openmc?branch=develop) [![dockerhub-publish-develop-dagmc](https://github.com/openmc-dev/openmc/workflows/dockerhub-publish-develop-dagmc/badge.svg)](https://github.com/openmc-dev/openmc/actions?query=workflow%3Adockerhub-publish-develop-dagmc) [![dockerhub-publish-develop](https://github.com/openmc-dev/openmc/workflows/dockerhub-publish-develop/badge.svg)](https://github.com/openmc-dev/openmc/actions?query=workflow%3Adockerhub-publish-develop) +[![conda-pacakge](https://anaconda.org/conda-forge/openmc/badges/version.svg)](https://anaconda.org/conda-forge/openmc) The OpenMC project aims to provide a fully-featured Monte Carlo particle transport code based on modern methods. It is a constructive solid geometry, From 9c683815ac4e6c87a720f77ceb1c453948b00a06 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 24 Mar 2022 15:04:59 -0500 Subject: [PATCH 0141/2654] moved faddeeva from vendored to external --- {vendor/faddeeva => include/openmc/external}/Faddeeva.hh | 0 {vendor/faddeeva => src/external}/Faddeeva.cc | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {vendor/faddeeva => include/openmc/external}/Faddeeva.hh (100%) rename {vendor/faddeeva => src/external}/Faddeeva.cc (99%) diff --git a/vendor/faddeeva/Faddeeva.hh b/include/openmc/external/Faddeeva.hh similarity index 100% rename from vendor/faddeeva/Faddeeva.hh rename to include/openmc/external/Faddeeva.hh diff --git a/vendor/faddeeva/Faddeeva.cc b/src/external/Faddeeva.cc similarity index 99% rename from vendor/faddeeva/Faddeeva.cc rename to src/external/Faddeeva.cc index 80e42228c..6a7051e24 100644 --- a/vendor/faddeeva/Faddeeva.cc +++ b/src/external/Faddeeva.cc @@ -157,7 +157,7 @@ #ifdef __cplusplus -# include "Faddeeva.hh" +# include "openmc/external/Faddeeva.hh" # include # include From 39a4daa20b8a86f5d3a3ab426e7a2fea186232c9 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 24 Mar 2022 15:07:12 -0500 Subject: [PATCH 0142/2654] don't compile faddeeva separately --- CMakeLists.txt | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba8a79efa..aa4499043 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,18 +258,6 @@ if("${isSystemDir}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") endif() -#=============================================================================== -# faddeeva library -#=============================================================================== - -add_library(faddeeva STATIC vendor/faddeeva/Faddeeva.cc) -target_include_directories(faddeeva - PUBLIC - $ - $ -) -target_compile_options(faddeeva PRIVATE ${cxxflags}) - #=============================================================================== # libopenmc #=============================================================================== @@ -372,7 +360,8 @@ list(APPEND libopenmc_SOURCES # Add bundled external dependencies list(APPEND libopenmc_SOURCES - src/external/quartic_solver.cpp) + src/external/quartic_solver.cpp + src/external/Faddeeva.cc) # For Visual Studio compilers if(MSVC) @@ -426,7 +415,7 @@ endif() # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES} - faddeeva xtensor gsl::gsl-lite-v1 fmt::fmt) + xtensor gsl::gsl-lite-v1 fmt::fmt) if(TARGET pugixml::pugixml) target_link_libraries(libopenmc pugixml::pugixml) @@ -460,7 +449,7 @@ target_link_libraries(openmc libopenmc) # Ensure C++14 standard is used. Starting with CMake 3.8, another way this could # be done is using the cxx_std_14 compiler feature. set_target_properties( - openmc libopenmc faddeeva + openmc libopenmc PROPERTIES CXX_STANDARD 14 CXX_EXTENSIONS OFF) #=============================================================================== @@ -481,7 +470,7 @@ configure_file(cmake/OpenMCConfig.cmake.in "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIR configure_file(cmake/OpenMCConfigVersion.cmake.in "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/OpenMCConfigVersion.cmake" @ONLY) set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/OpenMC) -install(TARGETS openmc libopenmc faddeeva +install(TARGETS openmc libopenmc EXPORT openmc-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -501,7 +490,3 @@ install(FILES man/man1/openmc.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) install(FILES LICENSE DESTINATION "${CMAKE_INSTALL_DOCDIR}" RENAME copyright) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(FILES "${CMAKE_BINARY_DIR}/include/openmc/version.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openmc) - -# Copy headers for vendored dependencies (note that all except faddeeva are handled -# separately since they are managed by CMake) -install(DIRECTORY vendor/faddeeva DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) From 7050b825efbde31fa37bab49437b0351b8165271 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 24 Mar 2022 15:08:32 -0500 Subject: [PATCH 0143/2654] updated fadeeva header location --- src/math_functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/math_functions.cpp b/src/math_functions.cpp index 32228bcdd..ba1c6c3db 100644 --- a/src/math_functions.cpp +++ b/src/math_functions.cpp @@ -1,6 +1,6 @@ #include "openmc/math_functions.h" -#include "Faddeeva.hh" +#include "openmc/external/Faddeeva.hh" #include "openmc/constants.h" #include "openmc/random_lcg.h" From eeed67c537e6d06e977cd7672403efa46b04af6f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 24 Mar 2022 22:34:37 +0000 Subject: [PATCH 0144/2654] added extra folders to ignored ci paths --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c83cc669..b6ab03830 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,8 @@ on: pull_request: paths-ignore: - 'docs/**' + - 'examples/**' + - 'man/**' - '**.md' - CODEOWNERS - LICENSE From aef22e48a775c72b4e21aacf8109eae7e1f281ea Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 25 Mar 2022 10:16:58 +0000 Subject: [PATCH 0145/2654] adding name space to import Co-authored-by: Paul Romano --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 75c04a637..da6ab3c46 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1,5 +1,5 @@ import os -import typing as typing # imported separately as py3.8 requires typing.Iterable +import typing # imported separately as py3.8 requires typing.Iterable from collections.abc import Iterable, Mapping, MutableSequence from enum import Enum from math import ceil From 350a347cf4f3aa6ee7243c91fd6d51ac20371731 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 25 Mar 2022 10:30:29 +0000 Subject: [PATCH 0146/2654] partly wrapped long line --- openmc/settings.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index da6ab3c46..d11a577d1 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -821,7 +821,9 @@ class Settings: self._resonance_scattering = res @volume_calculations.setter - def volume_calculations(self, vol_calcs: Union[VolumeCalculation, typing.Iterable[VolumeCalculation]]): + def volume_calculations( + self, vol_calcs: Union[VolumeCalculation, typing.Iterable[VolumeCalculation]] + ): if not isinstance(vol_calcs, MutableSequence): vol_calcs = [vol_calcs] self._volume_calculations = cv.CheckedList( From 1e6b953b4822e23572d9e92d33121b314ac890f6 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 25 Mar 2022 11:49:56 -0500 Subject: [PATCH 0147/2654] recursive include cc and hh files --- MANIFEST.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index c2789a152..d59628325 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -23,9 +23,11 @@ recursive-include examples *.cpp recursive-include examples *.py recursive-include examples *.xml recursive-include include *.h +recursive-include include *.hh recursive-include man *.1 recursive-include openmc *.pyx recursive-include openmc *.c +recursive-include src *.cc recursive-include src *.cpp recursive-include src *.rnc recursive-include src *.rng From f0683a616c5e66db3eceb6f0bb8e4e52de3297d5 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 25 Mar 2022 11:50:20 -0500 Subject: [PATCH 0148/2654] exclude external files from coverage --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e65e630b1..050c8e287 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,7 +120,7 @@ jobs: - name: after_success shell: bash run: | - cpp-coveralls -i src -i include --exclude-pattern "/usr/*" --dump cpp_cov.json + cpp-coveralls -i src -i include -e src/external --exclude-pattern "/usr/*" --dump cpp_cov.json coveralls --merge=cpp_cov.json --service=github finish: From 924147f9353ef971d5e6acbdde6c7e84a8084b7d Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 25 Mar 2022 14:28:52 -0500 Subject: [PATCH 0149/2654] alias targets --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba8a79efa..0c2f5cb43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -386,6 +386,8 @@ else() add_library(libopenmc SHARED ${libopenmc_SOURCES}) endif() +add_library(OpenMC::libopenmc ALIAS libopenmc) + # Avoid vs error lnk1149 :output filename matches input filename if(NOT MSVC) set_target_properties(libopenmc PROPERTIES OUTPUT_NAME openmc) @@ -453,6 +455,7 @@ endif() # openmc executable #=============================================================================== add_executable(openmc src/main.cpp) +add_executable(OpenMC::openmc ALIAS openmc) target_compile_options(openmc PRIVATE ${cxxflags}) target_include_directories(openmc PRIVATE ${CMAKE_BINARY_DIR}/include) target_link_libraries(openmc libopenmc) From 5f31e12443960f29a6b90290df642a88b11188ed Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Mar 2022 11:42:59 -0500 Subject: [PATCH 0150/2654] Add test for Region.from_expression case with )( --- tests/unit_tests/test_region.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit_tests/test_region.py b/tests/unit_tests/test_region.py index 8b2e06ad1..e75982760 100644 --- a/tests/unit_tests/test_region.py +++ b/tests/unit_tests/test_region.py @@ -200,3 +200,7 @@ def test_from_expression(reset): assert isinstance(r, openmc.Intersection) assert isinstance(r[1], openmc.Union) assert r[1][:] == [-s2, +s3] + + # Make sure ")(" is handled correctly + r = openmc.Region.from_expression('(-1|2)(2|-3)', surfs) + assert str(r) == '((-1 | 2) (2 | -3))' From f9ba350e1c433f71f73a851f2da2bd220e9af468 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Mar 2022 11:44:01 -0500 Subject: [PATCH 0151/2654] Add fix for Region.from_expression case with )( --- openmc/region.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openmc/region.py b/openmc/region.py index b252ff4a7..8efee7c4e 100644 --- a/openmc/region.py +++ b/openmc/region.py @@ -116,14 +116,20 @@ class Region(ABC): # For everything other than intersection, add the operator # to the list of tokens tokens.append(expression[i]) + + # If two parentheses appear immediately adjacent to one + # another, we need an intersection between them + if expression[i:i+2] == ')(': + tokens.append(' ') else: # Find next non-space character while expression[i+1] == ' ': i += 1 - # If previous token is a halfspace or right parenthesis and next token - # is not a left parenthese or union operator, that implies that the - # whitespace is to be interpreted as an intersection operator + # If previous token is a halfspace or right parenthesis and + # next token is not a left parenthesis or union operator, + # that implies that the whitespace is to be interpreted as + # an intersection operator if (i_start >= 0 or tokens[-1] == ')') and \ expression[i+1] not in ')|': tokens.append(' ') From 80829aefc7e44e5b36ad70ac5a569054966cf6a7 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Tue, 29 Mar 2022 09:01:08 -0500 Subject: [PATCH 0152/2654] Move lost particle reset from finalize() to reset(). Refs #2014 --- src/finalize.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/finalize.cpp b/src/finalize.cpp index bfcd77dda..5bfe8907c 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -121,7 +121,6 @@ int openmc_finalize() settings::write_initial_source = false; simulation::keff = 1.0; - simulation::n_lost_particles = 0; simulation::need_depletion_rx = false; simulation::total_gen = 0; @@ -174,6 +173,8 @@ int openmc_reset() settings::cmfd_run = false; + simulation::n_lost_particles = 0; + return 0; } From f72dbe68e16b72485e0322c611b9409939532d2d Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 30 Mar 2022 16:11:34 -0500 Subject: [PATCH 0153/2654] fix output variable type in docstring for HexLattice.from_hdf5 --- openmc/lattice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/lattice.py b/openmc/lattice.py index b6f1a2774..464daaf7e 100644 --- a/openmc/lattice.py +++ b/openmc/lattice.py @@ -2056,8 +2056,8 @@ class HexLattice(Lattice): Returns ------- - openmc.RectLattice - Rectangular lattice + openmc.HexLattice + Hexagonal lattice """ n_rings = group['n_rings'][()] From 48dbf1a4c3a83bf7abd0722ab868f532abc6b5bd Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 30 Mar 2022 16:18:12 -0500 Subject: [PATCH 0154/2654] fix axis spec in docstring for ZCone --- openmc/surface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/surface.py b/openmc/surface.py index f2b496f72..926b2fedc 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -1968,7 +1968,7 @@ class YCone(QuadricMixin, Surface): class ZCone(QuadricMixin, Surface): - """A cone parallel to the x-axis of the form :math:`(x - x_0)^2 + (y - y_0)^2 = + """A cone parallel to the z-axis of the form :math:`(x - x_0)^2 + (y - y_0)^2 = r^2 (z - z_0)^2`. Parameters From a61f3f534bf155143511cd603e770ad66bc1bbd1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 31 Mar 2022 14:45:59 -0500 Subject: [PATCH 0155/2654] Fix use of cwd in plot_inline and Plot.to_ipython_image --- openmc/executor.py | 4 ++-- openmc/plots.py | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index 63653f4d0..357fa64d5 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -166,13 +166,13 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.'): plots = [plots] # Create plots.xml - openmc.Plots(plots).export_to_xml() + openmc.Plots(plots).export_to_xml(cwd) # Run OpenMC in geometry plotting mode plot_geometry(False, openmc_exec, cwd) if plots is not None: - images = [_get_plot_image(p) for p in plots] + images = [_get_plot_image(p, cwd) for p in plots] display(*images) diff --git a/openmc/plots.py b/openmc/plots.py index 3599a3274..6bce8894c 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -164,16 +164,16 @@ _SVG_COLORS = { } -def _get_plot_image(plot): +def _get_plot_image(plot, cwd): from IPython.display import Image # Make sure .png file was created stem = plot.filename if plot.filename is not None else f'plot_{plot.id}' - png_file = f'{stem}.png' - if not Path(png_file).exists(): + png_file = Path(cwd) / f'{stem}.png' + if not png_file.exists(): raise FileNotFoundError(f"Could not find .png image for plot {plot.id}") - return Image(png_file) + return Image(str(png_file)) class Plot(IDManagerMixin): @@ -784,13 +784,13 @@ class Plot(IDManagerMixin): """ # Create plots.xml - Plots([self]).export_to_xml() + Plots([self]).export_to_xml(cwd) # Run OpenMC in geometry plotting mode openmc.plot_geometry(False, openmc_exec, cwd) # Return produced image - return _get_plot_image(self) + return _get_plot_image(self, cwd) class Plots(cv.CheckedList): From 412aa24727291eceb24a190c01bde57c317e2340 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 31 Mar 2022 14:47:14 -0500 Subject: [PATCH 0156/2654] Change Universe.plot to use openmc executable --- openmc/universe.py | 130 +++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 81 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index a7d7f096c..6604771cb 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -1,9 +1,10 @@ from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Iterable -from copy import copy, deepcopy +from copy import deepcopy from numbers import Real -import random +from pathlib import Path +from tempfile import TemporaryDirectory from xml.etree import ElementTree as ET import numpy as np @@ -267,13 +268,9 @@ class Universe(UniverseBase): def plot(self, origin=(0., 0., 0.), width=(1., 1.), pixels=(200, 200), basis='xy', color_by='cell', colors=None, seed=None, - **kwargs): + openmc_exec='openmc', **kwargs): """Display a slice plot of the universe. - To display or save the plot, call :func:`matplotlib.pyplot.show` or - :func:`matplotlib.pyplot.savefig`. In a Jupyter notebook, enabling the - matplotlib inline backend will show the plot inline. - Parameters ---------- origin : Iterable of float @@ -297,14 +294,14 @@ class Universe(UniverseBase): # Make water blue water = openmc.Cell(fill=h2o) universe.plot(..., colors={water: (0., 0., 1.)) + seed : int + Seed for the random number generator + openmc_exec : str + Path to OpenMC executable - seed : hashable object or None - Hashable object which is used to seed the random number generator - used to select colors. If None, the generator is seeded from the - current time. + .. versionadded:: 0.13.1 **kwargs - All keyword arguments are passed to - :func:`matplotlib.pyplot.imshow`. + Keyword arguments passed to :func:`matplotlib.pyplot.imshow` Returns ------- @@ -312,83 +309,54 @@ class Universe(UniverseBase): Resulting image """ + import matplotlib.image as mpimg import matplotlib.pyplot as plt - # Seed the random number generator - if seed is not None: - random.seed(seed) - - if colors is None: - # Create default dictionary if none supplied - colors = {} - else: - # Convert to RGBA if necessary - colors = copy(colors) - for obj, color in colors.items(): - if isinstance(color, str): - if color.lower() not in _SVG_COLORS: - raise ValueError(f"'{color}' is not a valid color.") - colors[obj] = [x/255 for x in - _SVG_COLORS[color.lower()]] + [1.0] - elif len(color) == 3: - colors[obj] = list(color) + [1.0] - + # Determine extents of plot if basis == 'xy': - x_min = origin[0] - 0.5*width[0] - x_max = origin[0] + 0.5*width[0] - y_min = origin[1] - 0.5*width[1] - y_max = origin[1] + 0.5*width[1] + x, y = 0, 1 elif basis == 'yz': - # The x-axis will correspond to physical y and the y-axis will - # correspond to physical z - x_min = origin[1] - 0.5*width[0] - x_max = origin[1] + 0.5*width[0] - y_min = origin[2] - 0.5*width[1] - y_max = origin[2] + 0.5*width[1] + x, y = 1, 2 elif basis == 'xz': - # The y-axis will correspond to physical z - x_min = origin[0] - 0.5*width[0] - x_max = origin[0] + 0.5*width[0] - y_min = origin[2] - 0.5*width[1] - y_max = origin[2] + 0.5*width[1] + x, y = 0, 2 + x_min = origin[x] - 0.5*width[0] + x_max = origin[x] + 0.5*width[0] + y_min = origin[y] - 0.5*width[1] + y_max = origin[y] + 0.5*width[1] - # Determine locations to determine cells at - x_coords = np.linspace(x_min, x_max, pixels[0], endpoint=False) + \ - 0.5*(x_max - x_min)/pixels[0] - y_coords = np.linspace(y_max, y_min, pixels[1], endpoint=False) - \ - 0.5*(y_max - y_min)/pixels[1] + with TemporaryDirectory() as tmpdir: + model = openmc.Model() + model.geometry = openmc.Geometry(self) + if seed is not None: + model.settings.seed = seed - # Initialize output image in RGBA format. Flip the pixels from - # traditional (x, y) to (y, x) used in graphics. - img = np.zeros((pixels[1], pixels[0], 4)) - for i, x in enumerate(x_coords): - for j, y in enumerate(y_coords): - if basis == 'xy': - path = self.find((x, y, origin[2])) - elif basis == 'yz': - path = self.find((origin[0], x, y)) - elif basis == 'xz': - path = self.find((x, origin[1], y)) + # Create plot object matching passed arguments + plot = openmc.Plot() + plot.origin = origin + plot.width = width + plot.pixels = pixels + plot.basis = basis + plot.color_by = color_by + plot.colors = colors + model.plots.append(plot) - if len(path) > 0: - try: - if color_by == 'cell': - obj = path[-1] - elif color_by == 'material': - if path[-1].fill_type == 'material': - obj = path[-1].fill - else: - continue - except AttributeError: - continue - if obj not in colors: - colors[obj] = (random.random(), random.random(), - random.random(), 1.0) - img[j, i, :] = colors[obj] + # Run OpenMC in geometry plotting mode + model.plot_geometry(False, cwd=tmpdir, openmc_exec=openmc_exec) - # Display image - return plt.imshow(img, extent=(x_min, x_max, y_min, y_max), - interpolation='nearest', **kwargs) + # Read image from file + img = mpimg.imread(Path(tmpdir) / f'plot_{plot.id}.png') + + # Create a figure sized such that the size of the axes within + # exactly matches the number of pixels specified + px = 1/plt.rcParams['figure.dpi'] + fig, ax = plt.subplots() + params = fig.subplotpars + width = pixels[0]*px/(params.right - params.left) + height = pixels[0]*px/(params.top - params.bottom) + fig.set_size_inches(width, height) + + # Plot image and return the axes + return ax.imshow(img, extent=(x_min, x_max, y_min, y_max), **kwargs) def add_cell(self, cell): """Add a cell to the universe. From 0dc6f463ed080cadc1cda9d44b5102ae4ae367de Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 31 Mar 2022 14:47:39 -0500 Subject: [PATCH 0157/2654] Change 'type' to 'from_mode' for decay sublibrary continuous spectra. Closes #2017 --- openmc/data/decay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index a0402b47d..5ca2b235a 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -442,7 +442,7 @@ class Decay(EqualityMixin): # Read continuous spectrum ci = {} params, ci['probability'] = get_tab1_record(file_obj) - ci['type'] = get_decay_modes(params[0]) + ci['from_mode'] = get_decay_modes(params[0]) # Read covariance (Ek, Fk) table LCOV = params[3] From 226065160a37858fefed3fa3a586dd2541cafe92 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 1 Apr 2022 07:29:36 -0500 Subject: [PATCH 0158/2654] Add ability to specify remove_surfs from Model.export_to_xml --- openmc/model/model.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 072c5ae73..3c94548fc 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -395,7 +395,7 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.'): + def export_to_xml(self, directory='.', remove_surfs=False): """Export model to XML files. Parameters @@ -403,7 +403,11 @@ class Model: directory : str Directory to write XML files to. If it doesn't exist already, it will be created. + remove_surfs : bool + Whether or not to remove redundant surfaces from the geometry when + exporting + .. versionadded:: 0.13.1 """ # Create directory if required d = Path(directory) @@ -411,7 +415,7 @@ class Model: d.mkdir(parents=True) self.settings.export_to_xml(d) - self.geometry.export_to_xml(d) + self.geometry.export_to_xml(d, remove_surfs=remove_surfs) # If a materials collection was specified, export it. Otherwise, look # for all materials in the geometry and use that to automatically build From 9350e99061bf8bd08935fef5c88d44272e3e997f Mon Sep 17 00:00:00 2001 From: yardasol Date: Fri, 1 Apr 2022 15:54:29 -0500 Subject: [PATCH 0159/2654] added CylinderSector composite surface --- openmc/model/surface_composite.py | 89 +++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 09a3c0170..0151d19e8 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -165,6 +165,95 @@ class RectangularParallelepiped(CompositeSurface): def __pos__(self): return -self.xmin | +self.xmax | -self.ymin | +self.ymax | -self.zmin | +self.zmax +class CylinderSector(CompositeSurface): + """Infinite cylindrical sector composite surface + + This class + acts as a proper surface, meaning that unary `+` and `-` operators applied + to it will produce a half-space. The negative side is defined to be the + region inside of the octogonal prism. + + Parameters + ---------- + center_axis : 2-tuple + (x,y), (x,z), or (y,z) coordiante of cylinders' central axes. + Defaults to (0,0) + r1, r2 : float + Inner and outer cylinder radii + alpha1, alpha2 : float + Angular segmentation in degrees relative to the x-, x-, or y-axis. + axis : {'z', 'y', 'x'} + Axes of the cylinders + **kwargs + Keyword arguments passed to underlying plane classes + + Attributes + ---------- + outer : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder + Outer cylinder surface + inner : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder + Inner cylinder surface + plane_1 : openmc.Plane + Segment plane corresponding to :attr:`alpha1` + plane_2 : openmc.Plane + Segmenting plane correspodning to :attr:`alpha2` + + """ + + _surface_names = ('outer','inner', + 'plane_a', 'plane_b') + + def __init__(self, center, r1, r2, alpha1, alpha2, **kwargs): + + alpha1 = np.pi / 180 * alpha1 + alpha2 = np.pi / 180 * alpha2 + # Coords for axis-perpendicular planes + p1 = np.array([0,0,1]) + + p2_plane1 = np.array([r1 * np.cos(alpha1), -r1 * np.sin(alpha1), 0]) + p3_plane1 = np.array([r2 * np.cos(alpha1), -r2 * np.sin(alpha1), 0]) + + p2_plane2 = np.array([r1 * np.cos(alpha2), r1 * np.sin(alpha2), 0]) + p3_plane2 = np.array([r2 * np.cos(alpha2), r2 * np.sin(alpha2), 0]) + + points = [p1, p2_plane1, p3_plane1, p2_plane2, p3_plane2] + if axis == 'x': + self.inner = openmc.XCylinder(*center_axis, r=r1, **kwargs) + self.outer = openmc.XCylinder(*center_axis, r=r2, **kwargs) + coord_map = [2,0,1] + elif axis == 'y': + self.inner = openmc.YCylinder(*center_axis, r=r1, **kwargs) + self.outer = openmc.YCylinder(*center_axis, r=r2, **kwargs) + coord_map = [0,2,1] + elif axis == 'z': + self.inner = openmc.ZCylinder(*center_axis, r=r1, **kwargs) + self.outer = openmc.ZCylinder(*center_axis, r=r2, **kwargs) + coord_map = [0,1,2] + + calibrated_points = [] + for p in points: + p_temp = [] + for i in coord_map: + p_temp += [p[i]] + calibrated_points += [np.array(p_temp)] + + p1, p2_plane1, p3_plane1, p2_plane2, p3_plane2 = calibrated_points + + plane1_params = _plane_from_points(p1, p2_plane1, p3_plane1) + plane2_params = _plane_from_points(p1, p2_plane2, p3_plane2) + + self.inner = openmc.ZCylinder(x0=x0, y0=y0, r=r1, **kwargs) + self.outer = openmc.ZCylinder(x0=x0, y0=y0, r=r2, **kwargs) + self.plane1 = openmc.Plane(*plane1_params, **kwargs) + self.plane2 = openmc.Plane(*plane2_params, **kwargs) + + + def __neg__(self): + return -self.outer & +self.inner & -self.plane1 & +self.plane2 + + + def __pos__(self): + return +self.outer | -self.inner | +self.plane1 | -self.plane2 class XConeOneSided(CompositeSurface): """One-sided cone parallel the x-axis From f787057c931cf921cb21a3680b0231ddc2996477 Mon Sep 17 00:00:00 2001 From: yardasol Date: Fri, 1 Apr 2022 16:13:00 -0500 Subject: [PATCH 0160/2654] Added Octagon composite surface --- openmc/model/surface_composite.py | 142 ++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 09a3c0170..31b6222a8 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -50,6 +50,148 @@ class CompositeSurface(ABC): def __neg__(self): """Return the negative half-space of the composite surface.""" +class Octagon(CompositeSurface): + """Infinite octogonal prism composite surface + + An octagonal prism is composed of eight surfaces. The prism is parallel to + the x, y, or z axis; two pars of surfaces are perpendicualr to the z and y, + x and z, or y and x axes, respectively. + + This class + acts as a proper surface, meaning that unary `+` and `-` operators applied + to it will produce a half-space. The negative side is defined to be the + region inside of the octogonal prism. + + Parameters + ---------- + center : 2-tuple + (q1,q2) coordinate for the center of the octagon. (q1,q2) pairs are + (x,y), (x,z), or (x,z). + r1 : float + Half-width of octagon across axis-perpendicualr sides + r2 : float + Half-width of octagon across off-axis sides + axis : {'x', 'y', 'z'} + Central axis of ocatgon. Defaults to 'z' + **kwargs + Keyword arguments passed to underlying cylinder and plane classes + + Attributes + ---------- + top : openmc.ZPlane or openmc.XPlane + Top planar surface of octagon + bottom : openmc.ZPlane or openmc.XPlane + Bottom planar surface of octagon + right: openmc.YPlane or openmc.ZPlane + Right planaer surface of octagon + left: openmc.YPlane or openmc.ZPlane + Left planar surface of octagon + upper_right : openmc.Plane + Upper right planar surface of octagon + lower_right : openmc.Plane + Lower right planar surface of octagon + lower_left : openmc.Plane + Lower left planar surface of octagon + upper_left : openmc.Plane + Upper left planar surface of octagon + + """ + + _surface_names = ('top', 'bottom', + 'upper_right', 'lower_left', + 'right', 'left', + 'lower_right', 'upper_left') + + def __init__(self, center, r1, r2, axis='z', **kwargs): + self._axis = axis + q1c, q2c = center + + # Coords for axis-perpendicular planes + ctop = q1c+r1 + cbottom = q1c-r1 + + cright= q2c+r1 + cleft = q2c-r1 + + # Side lengths + L_perp_ax1 = (r2 * np.sqrt(2) - r1) * 2 + L_perp_ax2 = (r1 * np.sqrt(2) - r2) * 2 + + # Coords for quadrant planes + p1_ur = [L_perp_ax1/2, r1, 0] + p2_ur = [r1, L_perp_ax1/2, 0] + p3_ur = [r1, L_perp_ax1/2, 1] + + p1_lr = [r1, -L_perp_ax1/2, 0] + p2_lr = [L_perp_ax1/2, -r1, 0] + p3_lr = [L_perp_ax1/2, -r1, 1] + + points = [p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr] + + # Orientation specific variables + if axis == 'z': + coord_map = [0,1,2] + self.top = openmc.YPlane(y0=ctop, **kwargs) + self.bottom = openmc.YPlane(y0=cbottom, **kwargs) + self.right = openmc.XPlane(x0=cright, **kwargs) + self.left = openmc.XPlane(x0=cleft, **kwargs) + elif axis == 'y': + coord_map = [0,2,1] + self.top = openmc.ZPlane(z0=ctop, **kwargs) + self.bottom = openmc.ZPlane(z0=cbottom, **kwargs) + self.right = openmc.XPlane(x0=cright, **kwargs) + self.left = openmc.XPlane(x0=cleft, **kwargs) + elif axis == 'x': + coord_map = [2,0,1] + self.top = openmc.ZPlane(z0=ctop, **kwargs) + self.bottom = openmc.ZPlane(z0=cbottom, **kwargs) + self.right = openmc.YPlane(y0=cright, **kwargs) + self.left = openmc.YPlane(y0=cleft, **kwargs) + + # Put our coordinates in (x,y,z) order + calibrated_points = [] + for p in points: + p_temp = [] + for i in coord_map: + p_temp += [p[i]] + calibrated_points += [np.array(p_temp)] + + p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points + + upper_right_params = _plane_from_points(p1_ur, p2_ur, p3_ur) + lower_right_params = _plane_from_points(p1_lr, p2_lr, p3_lr) + lower_left_params = _plane_from_points(-p1_ur, -p2_ur, -p3_ur) + upper_left_params = _plane_from_points(-p1_lr, -p2_lr, -p3_lr) + + self.upper_right = openmc.Plane(*tuple(upper_right_params), **kwargs) + self.lower_right = openmc.Plane(*tuple(lower_right_params), **kwargs) + self.lower_left = openmc.Plane(*tuple(lower_left_params), **kwargs) + self.upper_left = openmc.Plane(*tuple(upper_left_params), **kwargs) + + + def __neg__(self): + reg = -self.top & +self.bottom & -self.right & +self.left + if self._axis == 'y': + reg = reg & -self.upper_right & -self.lower_right & \ + +self.lower_left & +self.upper_left + else: + reg = reg & +self.upper_right & +self.lower_right & \ + -self.lower_left & -self.upper_left + + return reg + + + def __pos__(self): + reg = +self.top | -self.bottom | +self.right | -self.left + if self._axis == 'y': + reg = reg | +self.upper_right | +self.lower_right | \ + -self.lower_left | -self.upper_left + else: + reg = reg | -self.upper_right | -self.lower_right | \ + +self.lower_left | +self.upper_left + + return reg + class RightCircularCylinder(CompositeSurface): """Right circular cylinder composite surface From cbe9cc8c290d675b515fa40507fd4179c74a9b5b Mon Sep 17 00:00:00 2001 From: Joffrey Dorville Date: Fri, 1 Apr 2022 17:31:16 -0600 Subject: [PATCH 0161/2654] Kalbach-Mann slope calculation for ENDF files when the projectile is a neutron --- openmc/data/kalbach_mann.py | 528 ++++++++++++++++++++- openmc/data/njoy.py | 11 +- openmc/data/reaction.py | 29 +- tests/unit_tests/test_data_kalbach_mann.py | 280 +++++++++++ 4 files changed, 834 insertions(+), 14 deletions(-) create mode 100644 tests/unit_tests/test_data_kalbach_mann.py diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index f4c914d90..11e3acf40 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -5,6 +5,7 @@ from warnings import warn import numpy as np import openmc.checkvalue as cv +from openmc.mixin import EqualityMixin from openmc.stats import Tabular, Univariate, Discrete, Mixture from .function import Tabulated1D, INTERPOLATION_SCHEME from .angle_energy import AngleEnergy @@ -12,6 +13,468 @@ from .data import EV_PER_MEV from .endf import get_list_record, get_tab2_record +# Kalbach-Mann constants as defined in ENDF-6 manual BNL-203218-2018-INRE, +# Revision 215, File 6 description for LAW=1 and LANG=2. +_C1 = 0.04 # [1/MeV] +_C2 = 1.8E-6 # [1/MeV^3] +_C3 = 6.7E-7 # [1/MeV^4] +_ET1 = 130. # [MeV] +_ET3 = 41. # [MeV] +_M_NEUTRON = 1. +_M_PROTON = 1. +_M_DEUTERON = 1. +_M_TRITON = None +_M_3HE = None +_M_ALPHA = 0. +_SM_NEUTRON = 1/2. +_SM_PROTON = 1. +_SM_DEUTERON = 1. +_SM_TRITON = 1. +_SM_3HE = 1. +_SM_ALPHA = 2. + +# Kalbach-Mann M coefficients +_TABULATED_PARTICLE_M = { + 1: _M_NEUTRON, + 1001: _M_PROTON, + 1002: _M_DEUTERON, + 1003: _M_TRITON, + 2003: _M_3HE, + 2004: _M_ALPHA +} + +# Kalbach-Mann m coefficients +_TABULATED_PARTICLE_SM = { + 1: _SM_NEUTRON, + 1001: _SM_PROTON, + 1002: _SM_DEUTERON, + 1003: _SM_TRITON, + 2003: _SM_3HE, + 2004: _SM_ALPHA +} + +# Breaking energy as defined in ENDF-6 manual BNL-203218-2018-INRE, +# Revision 215, Appendix H, Table 3. +_BREAKING_ENERGY_NEUTRON = 0. +_BREAKING_ENERGY_PROTON = 0. +_BREAKING_ENERGY_DEUTERON = 2.224566 # [MeV] +_BREAKING_ENERGY_TRITON = 8.481798 # [MeV] +_BREAKING_ENERGY_3HE = 7.718043 # [MeV] +_BREAKING_ENERGY_ALPHA = 28.29566 # [MeV] + +_TABULATED_BREAKING_ENERGY = { + 1: _BREAKING_ENERGY_NEUTRON, + 1001: _BREAKING_ENERGY_PROTON, + 1002: _BREAKING_ENERGY_DEUTERON, + 1003: _BREAKING_ENERGY_TRITON, + 2003: _BREAKING_ENERGY_3HE, + 2004: _BREAKING_ENERGY_ALPHA +} + +# Abundant IZA translation in merged library +_IZA_TRANSLATION = { + 6000: 6012, +} + + +class AtomicRepresentation(EqualityMixin): + """Atomic representation of an isotope or a particle. + + Parameters + ---------- + z: int + Number of protons (atomic number) + a: int + Number of nucleons (mass number) + + Raises + ------ + IOError: + When the number of protons (z) declared is higher than the number + of nucleons (a) + + Attributes + ---------- + z: int + Number of protons (atomic number) + a: int + Number of nucleons (mass number) + n: int + Number of neutrons + breaking_energy: float + Energy required to break the isotope or particle into their + constituent nucleons from tabulated values + M: float + Kalbach-Mann M coefficient + m: float + Kalbach-Mann m coefficient + iza: int + ZA identifier defined as: + iza = Z x 1000 + A, + where Z is the number of protons and A the number of nucleons + + """ + def __init__(self, z, a): + self._consistency_check(z, a) + self._z = z + self._a = a + self.z = self._z + self.a = self._a + + def __add__(self, other): + """Adds two AtomicRepresentations. + + """ + z = self.z + other.z + a = self.a + other.a + return AtomicRepresentation(z=z, a=a) + + def __sub__(self, other): + """Substracts two AtomicRepresentations. + + """ + z = self.z - other.z + a = self.a - other.a + return AtomicRepresentation(z=z, a=a) + + @property + def a(self): + self._consistency_check(self._z, self._a) + return self._a + + @property + def z(self): + self._consistency_check(self._z, self._a) + return self._z + + @property + def n(self): + return self.a - self.z + + @property + def breaking_energy(self): + breaking_energy = None + if self.iza in _TABULATED_BREAKING_ENERGY: + breaking_energy = _TABULATED_BREAKING_ENERGY[self.iza] + return breaking_energy + + @property + def M(self): + M = None + if self.iza in _TABULATED_PARTICLE_M: + M = _TABULATED_PARTICLE_M[self.iza] + return M + + @property + def m(self): + m = None + if self.iza in _TABULATED_PARTICLE_SM: + m = _TABULATED_PARTICLE_SM[self.iza] + return m + + @property + def iza(self): + iza = self.z * 1000 + self.a + return iza + + @a.setter + def a(self, an): + cv.check_type('a', an, Integral) + cv.check_greater_than('a', an, 0, equality=True) + self._consistency_check(self._z, an) + self._a = an + + @z.setter + def z(self, zn): + cv.check_type('z', zn, Integral) + cv.check_greater_than('z', zn, 0, equality=True) + self._consistency_check(zn, self._a) + self._z = zn + + @staticmethod + def _consistency_check(z, a): + """Simple consistency check. + + Parameters + ---------- + z: int + Number of protons (atomic number) + a: int + Number of nucleons (mass number) + + Raises + ------ + IOError: + When the number of protons (z) declared is higher than the number + of nucleons (a) + + """ + if z > a: + raise IOError( + "Number of protons (%i) incompatible with number of " + "nucleons (%i)" % (z, a) + ) + + @classmethod + def from_iza(cls, iza): + """Instantiates an AtomicRepresentation from a ZA identifier. + + The ZA identifier is defined as: + iza = Z x 1000 + A, + where Z is the number of protons and A the number of nucleons. + + Parameters + ---------- + iza: int + ZA identifier + + Returns + ------- + AtomicRepresentation + Atomic representation of the isotope/particle + + """ + if iza in _IZA_TRANSLATION.keys(): + iza = _IZA_TRANSLATION[iza] + + z = int(iza/1000) + a = np.mod(iza, 1000) + + return cls(z, a) + + +def _calculate_separation_energy(compound, nucleus, particle): + """Calculates the separation energy as defined in ENDF-6 manual + BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 + and LANG=2. This function can be used for the incident or emitted + particle of the following reaction: A + a -> C -> B + b + + Parameters + ---------- + compound: AtomicRepresentation + Atomic representation of the compound (C) + nucleus: AtomicRepresentation + Atomic representation of the nucleus (A or B) + particle: AtomicRepresentation + Atomic representation of the particle (a or b) + + Returns + ------- + separation_energy: float + Separation energy in MeV + + """ + coef_1 = 15.68 * (compound.a - nucleus.a) + coef_2 = 28.07 * ((compound.n - compound.z)**2 / float(compound.a) - \ + (nucleus.n - nucleus.z)**2 / float(nucleus.a)) + coef_3 = 18.56 * (compound.a**(2./3.) - nucleus.a**(2./3.)) + coef_4 = 33.22 * ((compound.n - compound.z)**2 / float(compound.a)**(4./3.) - \ + (nucleus.n - nucleus.z)**2 / float(nucleus.a)**(4./3.)) + coef_5 = 0.717 * (compound.z**2 / float(compound.a)**(1./3.) - \ + nucleus.z**2 / float(nucleus.a)**(1./3.)) + coef_6 = 1.211 * (compound.z**2 / float(compound.a) - \ + nucleus.z**2 / float(nucleus.a)) + + separation_energy = coef_1 - coef_2 - coef_3 + coef_4 \ + - coef_5 + coef_6 - particle.breaking_energy + + return separation_energy + + +def _return_entrance_channel_energy(e_p, awr_t, awr_p): + """Returns the entrance channel energy as defined in ENDF-6 manual + BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 + and LANG=2. + + Parameters + ---------- + e_p: float + Energy of the incident projectile in the laboratory system in eV + awr_t: float + Atomic weight ratio of the target + awr_p: float + Atomic weight ratio of the projectile + + Returns + ------- + epsilon_p: float + Entrance channel energy in eV + + """ + epsilon_p = e_p * awr_t / (awr_t + awr_p) + return epsilon_p + + +def _return_emission_channel_energy(e_e, awr_r, awr_e): + """Returns the emission channel energy as defined in ENDF-6 manual + BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 + and LANG=2. + + Parameters + ---------- + e_e: float + Energy of the emitted particle in the center of mass system in eV + awr_r: float + Atomic weight ratio of the residual nucleus + awr_e: float + Atomic weight ratio of the emitted particle + + Returns + ------- + epsilon_e: float + Emission channel energy in eV + + """ + epsilon_e = e_e * (awr_r + awr_e) / awr_r + return epsilon_e + + +def _calculate_kalbach_slope(energy_projectile, + energy_emitted, + projectile, + target, + compound, + emitted, + residual): + """Calculate the Kalbach slope for projectiles other than photons + as defined in ENDF-6 manual BNL-203218-2018-INRE, Revision 215, + File 6 description for LAW=1 and LANG=2. + + The entrance and emission channel energies are not calculated with + the AWR number, but approximated with the number of mass instead. + + Parameters + ---------- + energy_projectile: float + Energy of the projectile in the laboratory system in eV + energy_emitted: float + Energy of the emitted particle in the center of mass system in eV + projectile: AtomicRepresentation + Atomic representation of the projectile + target: AtomicRepresentation + Atomic representation of the target + compound: AtomicRepresentation + Atomic representation of the compound + emitted: AtomicRepresentation + Atomic representation of the emitted particle + residual: AtomicRepresentation + Atomic representation of the residual nucleus + + Returns + ------- + slope: float + Kalbach-Mann slope + + """ + epsilon_a = _return_entrance_channel_energy( + energy_projectile, + target.a, + projectile.a + ) / EV_PER_MEV + epsilon_b = _return_emission_channel_energy( + energy_emitted, + residual.a, + emitted.a + ) / EV_PER_MEV + + s_a = _calculate_separation_energy(compound, target, projectile) + s_b = _calculate_separation_energy(compound, residual, emitted) + + e_a = epsilon_a + s_a + e_b = epsilon_b + s_b + + r_1 = min(e_a, _ET1) + r_3 = min(e_a, _ET3) + + x_1 = r_1 * e_b / e_a + x_3 = r_3 * e_b / e_a + + slope = _C1 * x_1 \ + + _C2 * x_1**3 \ + + _C3 * projectile.M * emitted.m * x_3**4 + + return slope + + +def return_kalbach_slope(energy_projectile, + energy_emitted, + iza_projectile, + iza_emitted, + iza_target): + """Returns Kalbach-Mann slope from calculations. + + The associated reaction is defined as: + A + a -> C -> B + b + + Where: + + - A is the targeted nucleus, + - a is the projectile, + - C is the compound, + - B is the residual nucleus, + - b is the emitted particle. + + This function uses the concept of ZA identifier defined as: + iza = Z x 1000 + A, + where Z is the number of protons and A the number of nucleons. + + The Kalbach-Mann slope calculation is done as defined in ENDF-6 manual + BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 and + LANG=2. One exception to this, is that the entrance and emission channel + energies are not calculated with the AWR number, but approximated with + the number of mass instead. + + Parameters + ---------- + energy_projectile: float + Energy of the projectile in the laboratory system in eV + energy_emitted: float + Energy of the emitted particle in the center of mass system in eV + iza_projectile: int + ZA identifier of the projectile + iza_emitted: int + ZA identifier of the emitted particle + iza_target: int + ZA identifier of the targeted nucleus + + Raises + ------ + NotImplementedError: + When the ZA identifier of the projectile is not equal to 1 + (ie. other than a neutron). + + Returns + ------- + slope: float + Kalbach-Mann slope given with the same format as ACE file. + + """ + # TODO: develop for photons as projectile + # TODO: test for other particles than neutron + if iza_projectile != 1: + raise NotImplementedError( + "Developed and tested for neutron projectile only." + ) + + projectile = AtomicRepresentation.from_iza(iza_projectile) + emitted = AtomicRepresentation.from_iza(iza_emitted) + target = AtomicRepresentation.from_iza(iza_target) + compound = projectile + target + residual = compound - emitted + + slope = _calculate_kalbach_slope( + energy_projectile, + energy_emitted, + projectile, + target, + compound, + emitted, + residual + ) + + return float("%7e" % slope) + + class KalbachMann(AngleEnergy): """Kalbach-Mann distribution @@ -319,7 +782,7 @@ class KalbachMann(AngleEnergy): n_energy_out = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 5*n_energy_out].copy() data.shape = (5, n_energy_out) - data[0,:] *= EV_PER_MEV + data[0, :] *= EV_PER_MEV # Create continuous distribution eout_continuous = Tabular(data[0][n_discrete_lines:], @@ -352,13 +815,28 @@ class KalbachMann(AngleEnergy): return cls(breakpoints, interpolation, energy, energy_out, km_r, km_a) @classmethod - def from_endf(cls, file_obj): - """Generate Kalbach-Mann distribution from an ENDF evaluation + def from_endf(cls, file_obj, iza_emitted, iza_target, projectile_mass): + """Generate Kalbach-Mann distribution from an ENDF evaluation. + + If the projectile is a neutron, the slope is calculated when it is + not given explicitly. Parameters ---------- file_obj : file-like object ENDF file positioned at the start of the Kalbach-Mann distribution + iza_emitted : int + ZA identifier of the emitted particle + iza_target : int + ZA identifier of the target + projectile_mass: float + Mass of the projectile + + Warns + ----- + UserWarning + If the mass of the projectile is not equal to 1 (other than + a neutron), the slope is not calculated and set to 0 if missing. Returns ------- @@ -374,6 +852,7 @@ class KalbachMann(AngleEnergy): energy_out = [] precompound = [] slope = [] + calculated_slope = [] for i in range(ne): items, values = get_list_record(file_obj) energy[i] = items[1] @@ -385,19 +864,46 @@ class KalbachMann(AngleEnergy): values.shape = (n_energy_out, n_angle + 2) # Outgoing energy distribution at the i-th incoming energy - eout_i = values[:,0] - eout_p_i = values[:,1] + eout_i = values[:, 0] + eout_p_i = values[:, 1] energy_out_i = Tabular(eout_i, eout_p_i, INTERPOLATION_SCHEME[lep]) energy_out.append(energy_out_i) - # Precompound and slope factors for Kalbach-Mann - r_i = values[:,2] + # Precompound factors for Kalbach-Mann + r_i = values[:, 2] + + # Slope factors for Kalbach-Mann if n_angle == 2: - a_i = values[:,3] + a_i = values[:, 3] + calculated_slope.append(False) else: - a_i = np.zeros_like(r_i) + # Check if the projectile is not a neutron + if not np.isclose(projectile_mass, 1.0, atol=1.0e-12, rtol=0.): + warn( + "Kalbach-Mann slope calculation is only available with " + "neutrons as projectile. Slope coefficients are set to 0." + ) + a_i = np.zeros_like(r_i) + calculated_slope.append(False) + + else: + # TODO: retrieve IZA of the projectile + iza_projectile = 1 + a_i = [return_kalbach_slope(energy_projectile=energy[i], + energy_emitted=e, + iza_projectile=iza_projectile, + iza_emitted=iza_emitted, + iza_target=iza_target) + for e in eout_i] + calculated_slope.append(True) + precompound.append(Tabulated1D(eout_i, r_i)) slope.append(Tabulated1D(eout_i, a_i)) - return cls(tab2.breakpoints, tab2.interpolation, energy, - energy_out, precompound, slope) + km_distribution = cls(tab2.breakpoints, tab2.interpolation, energy, + energy_out, precompound, slope) + + # List of bool to indicate slope calculation by OpenMC + km_distribution._calculated_slope = calculated_slope + + return km_distribution diff --git a/openmc/data/njoy.py b/openmc/data/njoy.py index 305edaf4f..fbb26be05 100644 --- a/openmc/data/njoy.py +++ b/openmc/data/njoy.py @@ -127,7 +127,7 @@ acer / %%%%%%%%%%%%%%%%%%%%%%%% Write out in ACE format %%%%%%%%%%%%%%%%%%%%%%%% 1 0 1 .{ext} / '{library}: {zsymam} at {temperature}'/ {mat} {temperature} -1 1/ +1 1 {ismoothing}/ / """ @@ -248,7 +248,8 @@ def make_pendf(filename, pendf='pendf', error=0.001, stdout=False): def make_ace(filename, temperatures=None, acer=True, xsdir=None, output_dir=None, pendf=False, error=0.001, broadr=True, - heatr=True, gaspr=True, purr=True, evaluation=None, **kwargs): + heatr=True, gaspr=True, purr=True, evaluation=None, + smoothing=True, **kwargs): """Generate incident neutron ACE file from an ENDF file File names can be passed to @@ -298,6 +299,8 @@ def make_ace(filename, temperatures=None, acer=True, xsdir=None, evaluation : openmc.data.endf.Evaluation, optional If the ENDF file contains multiple material evaluations, this argument indicates which evaluation should be used. + smoothing : bool, optional + If the smoothing option in ACER is on (1) or off (0) in the card 6. **kwargs Keyword arguments passed to :func:`openmc.data.njoy.run` @@ -380,6 +383,10 @@ def make_ace(filename, temperatures=None, acer=True, xsdir=None, # acer if acer: + if smoothing is True: + ismoothing = 1 + else: + ismoothing = 0 nacer_in = nlast for i, temperature in enumerate(temperatures): # Extend input with an ACER run for each temperature diff --git a/openmc/data/reaction.py b/openmc/data/reaction.py index 5e4287f16..42fc576da 100644 --- a/openmc/data/reaction.py +++ b/openmc/data/reaction.py @@ -80,6 +80,14 @@ def _get_products(ev, mt): mt : int The MT value of the reaction to get products for + Raises + ------ + IOError: + When the Kalbach-Mann systematics is used, but the product + is not defined in the 'center-of-mass' system. The breakup logic + is not implemented which can lead to this error being raised while + the definition of the product is correct. + Returns ------- products : list of openmc.data.Product @@ -141,7 +149,26 @@ def _get_products(ev, mt): if lang == 1: p.distribution = [CorrelatedAngleEnergy.from_endf(file_obj)] elif lang == 2: - p.distribution = [KalbachMann.from_endf(file_obj)] + # Products need to be described in the center-of-mass system + product_center_of_mass = False + if reference_frame == 'center-of-mass': + product_center_of_mass = True + elif reference_frame == 'light-heavy': + product_center_of_mass = (awr <= 4.0) + # TODO: 'breakup' logic not implemented + + if product_center_of_mass is False: + raise IOError( + "Kalbach-Mann representation must be defined in the " + "'center-of-mass' system" + ) + + zat = ev.target["atomic_number"] * 1000 + ev.target["mass_number"] + projectile_mass = ev.projectile["mass"] + p.distribution = [KalbachMann.from_endf(file_obj, + za, + zat, + projectile_mass)] elif law == 2: # Discrete two-body scattering diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py new file mode 100644 index 000000000..99869808d --- /dev/null +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -0,0 +1,280 @@ +"""Test of the Kalbach-Mann slope calculation when data are +retrieved from ENDF files.""" + +import os +import pytest +import numpy as np + +from openmc.data import IncidentNeutron +from openmc.data import AtomicRepresentation +from openmc.data.kalbach_mann import _BREAKING_ENERGY_TRITON +from openmc.data.kalbach_mann import _M_TRITON +from openmc.data.kalbach_mann import _SM_TRITON +from openmc.data.kalbach_mann import _calculate_separation_energy +from openmc.data.kalbach_mann import _return_emission_channel_energy +from openmc.data.kalbach_mann import _return_entrance_channel_energy +from openmc.data.kalbach_mann import _calculate_kalbach_slope +from openmc.data import return_kalbach_slope +from openmc.data import KalbachMann + +from . import needs_njoy + + +@pytest.fixture(scope='module') +def neutron(): + """Neutron AtomicRepresentation.""" + return AtomicRepresentation(z=0, a=1) + + +@pytest.fixture(scope='module') +def triton(): + """Triton AtomicRepresentation.""" + return AtomicRepresentation(z=1, a=3) + + +@pytest.fixture(scope='module') +def b10(): + """B10 AtomicRepresentation.""" + return AtomicRepresentation(z=5, a=10) + + +@pytest.fixture(scope='module') +def c12(): + """C12 AtomicRepresentation.""" + return AtomicRepresentation(z=6, a=12) + + +@pytest.fixture(scope='module') +def c13(): + """C13 AtomicRepresentation.""" + return AtomicRepresentation(z=6, a=13) + + +@pytest.fixture(scope='module') +def na23(): + """Na23 AtomicRepresentation.""" + return AtomicRepresentation(z=11, a=23) + + +def test_atomic_representation(neutron, triton, b10, c12, c13, na23): + """Test the AtomicRepresentation class.""" + # Test instanciation from_iza + assert b10 == AtomicRepresentation.from_iza(5010) + + # Test instanciation from_iza using IZA translation + assert c12 == AtomicRepresentation.from_iza(6000) + + # Test addition + assert c13 + b10 == na23 + + # Test substraction + assert c13 - c12 == neutron + assert c13 - b10 == triton + + # Test properties when no information for Kalbach-Mann are given + assert c13.a == 13 + assert c13.z == 6 + assert c13.n == 7 + assert c13.breaking_energy is None + assert c13.M is None + assert c13.m is None + assert c13.iza == 6013 + + # Test properties when information for Kalbach-Mann are given + assert triton.a == 3 + assert triton.z == 1 + assert triton.n == 2 + assert triton.breaking_energy == _BREAKING_ENERGY_TRITON + assert triton.M == _M_TRITON + assert triton.m == _SM_TRITON + assert triton.iza == 1003 + + # Test instanciation errors + with pytest.raises(IOError): + AtomicRepresentation(z=5, a=1) + with pytest.raises(ValueError): + AtomicRepresentation(z=-1, a=1) + with pytest.raises(IOError): + AtomicRepresentation(z=5, a=0) + with pytest.raises(IOError): + AtomicRepresentation(z=5, a=-2) + with pytest.raises(OSError): + neutron - triton + + +def test__calculate_separation_energy(triton, b10, c13): + """Comparison to hand-calculations on a simple example.""" + assert _calculate_separation_energy( + compound=c13, + nucleus=b10, + particle=triton + ) == pytest.approx(18.6880713) + + +def test__return_entrance_channel_energy(): + """Comparison to hand-calculations on a simple example.""" + assert _return_entrance_channel_energy( + e_p=5.2, + awr_t=13.7, + awr_p=7.2 + ) == pytest.approx(3.4086124) + + +def test__return_emission_channel_energy(): + """Comparison to hand-calculations on a simple example.""" + assert _return_emission_channel_energy( + e_e=6.8, + awr_r=49.2, + awr_e=5.4 + ) == pytest.approx(7.5463415) + + +def test__calculate_kalbach_slope(neutron, triton, b10, c12, c13): + """Comparison to hand-calculations for n + c12 -> c13 -> triton + b10.""" + energy_projectile = 10.2 # [eV] + energy_emitted = 5.4 # [eV] + + assert _calculate_kalbach_slope( + energy_projectile=energy_projectile, + energy_emitted=energy_emitted, + projectile=neutron, + target=c12, + compound=c13, + emitted=triton, + residual=b10 + ) == pytest.approx(0.8409921475) + + +def test_return_kalbach_slope(): + """Comparison to hand-calculations for n + c12 -> c13 -> triton + b10.""" + energy_projectile = 10.2 # [eV] + energy_emitted = 5.4 # [eV] + + # Check that NotImplementedError is raised if the projectile is not + # a neutron + with pytest.raises(NotImplementedError): + return_kalbach_slope( + energy_projectile=energy_projectile, + energy_emitted=energy_emitted, + iza_projectile=1000, + iza_emitted=1, + iza_target=6012 + ) + + assert return_kalbach_slope( + energy_projectile=energy_projectile, + energy_emitted=energy_emitted, + iza_projectile=1, + iza_emitted=1003, + iza_target=6012 + ) == pytest.approx(0.8409921475) + + +@pytest.mark.parametrize( + "hdf5_filename, endf_type, endf_filename", [ + ('O16.h5', 'neutrons', 'n-008_O_016.endf'), + ('Ca46.h5', 'neutrons', 'n-020_Ca_046.endf'), + ('Hg204.h5', 'neutrons', 'n-080_Hg_204.endf') + ] +) +def test_comparison_slope_hdf5(hdf5_filename, endf_type, endf_filename): + """Test the calculation of the Kalbach-Mann slope done by OpenMC + by comparing it to HDF5 data. The test is based on the first product + of MT=5 (neutron). The isotopes tested have been selected because the + corresponding products in ENDF/B-VII.1 are described using MF=6, LAW=1, + LANG=2 (ie. Kalbach-Mann systematics) and the slope is not given + explicitly. + + If an error occurs during the "validity check", this means that + the nuclear data evaluation has evolved and the distribution might + no longer be described using Kalbach-Mann systematics. Another + isotope needs to be identified and tested. + + Warning: This test is valid as long as ENDF files are not directly + used to generate the HDF5 files used in the tests. + + """ + # HDF5 data + hdf5_directory = os.path.dirname(os.environ['OPENMC_CROSS_SECTIONS']) + hdf5_path = os.path.join(hdf5_directory, hdf5_filename) + hdf5_data = IncidentNeutron.from_hdf5(hdf5_path) + hdf5_product = hdf5_data[5].products[0] + hdf5_distribution = hdf5_product.distribution[0] + + # ENDF data + endf_directory = os.environ['OPENMC_ENDF_DATA'] + endf_path = os.path.join(endf_directory, endf_type, endf_filename) + endf_data = IncidentNeutron.from_endf(endf_path) + endf_product = endf_data[5].products[0] + endf_distribution = endf_product.distribution[0] + + # Validity check + assert isinstance(endf_distribution, KalbachMann) + assert isinstance(hdf5_distribution, KalbachMann) + assert endf_product.particle == hdf5_product.particle + assert len(endf_distribution.slope) == len(hdf5_distribution.slope) + + # Results check + for i, hdf5_slope in enumerate(hdf5_distribution.slope): + + assert endf_distribution._calculated_slope[i] is True + + np.testing.assert_array_almost_equal( + endf_distribution.slope[i].y, + hdf5_slope.y, + decimal=6 + ) + + +@needs_njoy +@pytest.mark.parametrize( + "endf_type, endf_filename", [ + ('neutrons', 'n-008_O_016.endf'), + ('neutrons', 'n-020_Ca_046.endf'), + ('neutrons', 'n-080_Hg_204.endf') + ] +) +def test_comparison_slope_njoy(endf_type, endf_filename): + """Test the calculation of the Kalbach-Mann slope done by OpenMC + by comparing it to an NJOY calculation. The test is based on + the first product of MT=5 (neutron). The isotopes tested have + been selected because the corresponding products in ENDF/B-VII.1 + are described using MF=6, LAW=1, LANG=2 (ie. Kalbach-Mann + systematics) and the slope is not given explicitly. + + If an error occurs during the "validity check", this means that + the nuclear data evaluation has evolved and the distribution might + no longer be described using Kalbach-Mann systematics. Another + isotope needs to be identified and tested. + + """ + endf_directory = os.environ['OPENMC_ENDF_DATA'] + endf_path = os.path.join(endf_directory, endf_type, endf_filename) + + # ENDF data + endf_data = IncidentNeutron.from_endf(endf_path) + endf_product = endf_data[5].products[0] + endf_distribution = endf_product.distribution[0] + + # NJOY data + njoy_data = IncidentNeutron.from_njoy(endf_path, heatr=False, gaspr=False, + purr=False, smoothing=False) + njoy_product = njoy_data[5].products[0] + njoy_distribution = njoy_product.distribution[0] + + # Validity check + assert isinstance(endf_distribution, KalbachMann) + assert isinstance(njoy_distribution, KalbachMann) + assert endf_product.particle == njoy_product.particle + assert len(endf_distribution.slope) == len(njoy_distribution.slope) + + # Results check + for i, njoy_slope in enumerate(njoy_distribution.slope): + + assert endf_distribution._calculated_slope[i] is True + + np.testing.assert_array_almost_equal( + endf_distribution.slope[i].y, + njoy_slope.y, + decimal=6 + ) From 8f564052e5e6f818bd4d2b0e9ea20116c497622c Mon Sep 17 00:00:00 2001 From: Joffrey Dorville Date: Sat, 2 Apr 2022 00:05:32 -0600 Subject: [PATCH 0162/2654] Add the Kalbach-Mann slope documentation --- docs/source/pythonapi/data.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 95fdfeca9..471be43d8 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -24,6 +24,7 @@ and product yields. FissionProductYields WindowedMultipole ProbabilityTables + AtomicRepresentation The following classes are used for storing atomic data (incident photon cross sections, atomic relaxation): @@ -68,6 +69,7 @@ Core Functions thin water_density zam + return_kalbach_slope One-dimensional Functions ------------------------- From f266740bf0a6a99fc602f8f9384841d837b1b20d Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 12:27:45 -0500 Subject: [PATCH 0163/2654] added numpy imports, plane helper function --- openmc/model/surface_composite.py | 33 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 31b6222a8..deb8e9846 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -3,7 +3,18 @@ from copy import copy import openmc from openmc.checkvalue import check_greater_than, check_value +from numpy import sqrt, cross, dot, array +def _plane_from_points(p1, p2, p3): + # get plane from points p1, p2, p3 + n = cross(p2 - p1, p3 - p1) + n0 = -p1 + A = n[0] + B = n[1] + C = n[2] + D = dot(n, n0) + + return [A, B, C, -D] class CompositeSurface(ABC): """Multiple primitive surfaces combined into a composite surface""" @@ -114,8 +125,8 @@ class Octagon(CompositeSurface): cleft = q2c-r1 # Side lengths - L_perp_ax1 = (r2 * np.sqrt(2) - r1) * 2 - L_perp_ax2 = (r1 * np.sqrt(2) - r2) * 2 + L_perp_ax1 = (r2 * sqrt(2) - r1) * 2 + L_perp_ax2 = (r1 * sqrt(2) - r2) * 2 # Coords for quadrant planes p1_ur = [L_perp_ax1/2, r1, 0] @@ -154,7 +165,7 @@ class Octagon(CompositeSurface): p_temp = [] for i in coord_map: p_temp += [p[i]] - calibrated_points += [np.array(p_temp)] + calibrated_points += [array(p_temp)] p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points @@ -170,27 +181,27 @@ class Octagon(CompositeSurface): def __neg__(self): - reg = -self.top & +self.bottom & -self.right & +self.left + region1 = -self.top & +self.bottom & -self.right & +self.left if self._axis == 'y': - reg = reg & -self.upper_right & -self.lower_right & \ + region2 = -self.upper_right & -self.lower_right & \ +self.lower_left & +self.upper_left else: - reg = reg & +self.upper_right & +self.lower_right & \ + region2 = +self.upper_right & +self.lower_right & \ -self.lower_left & -self.upper_left - return reg + return region1 & region2 def __pos__(self): - reg = +self.top | -self.bottom | +self.right | -self.left + region1 = +self.top | -self.bottom | +self.right | -self.left if self._axis == 'y': - reg = reg | +self.upper_right | +self.lower_right | \ + region2 = +self.upper_right | +self.lower_right | \ -self.lower_left | -self.upper_left else: - reg = reg | -self.upper_right | -self.lower_right | \ + region2 = -self.upper_right | -self.lower_right | \ +self.lower_left | +self.upper_left - return reg + return region1 | region2 class RightCircularCylinder(CompositeSurface): From 1648b854a4f91a1efefd203620cfb19abf3e7d68 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 12:27:58 -0500 Subject: [PATCH 0164/2654] Added unit test for Octagon --- tests/unit_tests/test_surface_composite.py | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index a1a218311..d3ec10cf4 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -150,3 +150,75 @@ def test_cone_one_sided(axis, point_pos, point_neg, ll_true): # Make sure repr works repr(s) + + +@pytest.mark.parametrize( + "axis, plane_tb, plane_lr, axis_idx", [ + ("x", "Z", "Y", 0), + ("y", "Z", "X", 1), + ("z", "Y", "X", 2), + ] +) +def test_octagon(axis, plane_tb, plane_lr, axis_idx): + center = np.array([0.,0.]) + point_pos = np.array([0.8,0.8]) + point_neg = np.array([0.7,0.7]) + r1 = 1. + r2 = 1. + plane_top_bottom = getattr(openmc, plane_tb + "Plane") + plane_left_right = getattr(openmc, plane_lr + "Plane") + s = openmc.model.Octagon(center, r1, r2, axis=axis) + assert isinstance(s.top, plane_top_bottom) + assert isinstance(s.bottom, plane_top_bottom) + assert isinstance(s.right, plane_left_right) + assert isinstance(s.left, plane_left_right) + assert isinstance(s.upper_right, openmc.Plane) + assert isinstance(s.lower_right, openmc.Plane) + assert isinstance(s.upper_left, openmc.Plane) + assert isinstance(s.lower_left, openmc.Plane) + + # Make sure boundary condition propagates + s.boundary_type = 'reflective' + assert s.boundary_type == 'reflective' + assert s.top.boundary_type == 'reflective' + assert s.bottom.boundary_type == 'reflective' + assert s.right.boundary_type == 'reflective' + assert s.left.boundary_type == 'reflective' + assert s.upper_right.boundary_type == 'reflective' + assert s.lower_right.boundary_type == 'reflective' + assert s.lower_left.boundary_type == 'reflective' + assert s.upper_left.boundary_type == 'reflective' + + # Check bounding box + center = np.insert(center, axis_idx, np.inf) + xmax,ymax,zmax = center + r1 + coord_min = center - r1 + coord_min[axis_idx] *= -1 + xmin,ymin,zmin = coord_min + ll, ur = (+s).bounding_box + assert np.all(np.isinf(ll)) + assert np.all(np.isinf(ur)) + ll, ur = (-s).bounding_box + assert ur == pytest.approx((xmax, ymax, zmax)) + assert ll == pytest.approx((xmin, ymin, zmin)) + + # __contains__ on associated half-spaces + point_pos = np.insert(point_pos, axis_idx, 0) + point_neg = np.insert(point_neg, axis_idx, 0) + assert point_pos in +s + assert point_pos not in -s + assert point_neg in -s + assert point_neg not in +s + + # translate method + t = uniform(-5.0, 5.0) + s_t = s.translate((t, t, t)) + ll_t, ur_t = (-s_t).bounding_box + assert ur_t == pytest.approx(ur + t) + assert ll_t == pytest.approx(ll + t) + + # Make sure repr works + repr(s) + + + From 020ebb9374f65590b3094fd3eb14fe603f61ce08 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 12:47:23 -0500 Subject: [PATCH 0165/2654] fix typos in docstring for Octagon --- openmc/model/surface_composite.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index deb8e9846..be5736794 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -64,38 +64,37 @@ class CompositeSurface(ABC): class Octagon(CompositeSurface): """Infinite octogonal prism composite surface - An octagonal prism is composed of eight surfaces. The prism is parallel to - the x, y, or z axis; two pars of surfaces are perpendicualr to the z and y, - x and z, or y and x axes, respectively. + An octagonal prism is composed of eight planar surfaces. The prism is + parallel to the x, y, or z axis; two pars of surfaces are perpendicular to + the y and z, x and z, or x and y axes, respectively. - This class - acts as a proper surface, meaning that unary `+` and `-` operators applied - to it will produce a half-space. The negative side is defined to be the - region inside of the octogonal prism. + This class acts as a proper surface, meaning that unary `+` and `-` + operators applied to it will produce a half-space. The negative side is + defined to be the region inside of the octogonal prism. Parameters ---------- - center : 2-tuple - (q1,q2) coordinate for the center of the octagon. (q1,q2) pairs are - (x,y), (x,z), or (x,z). + center : iterable of float + (q1,q2) coordinate for the central axis of the octagon. (q1,q2) pairs + are (y,z), (x,z), or (x,y). r1 : float - Half-width of octagon across axis-perpendicualr sides + Half-width of octagon across axis-pendicular sides r2 : float Half-width of octagon across off-axis sides axis : {'x', 'y', 'z'} - Central axis of ocatgon. Defaults to 'z' + Central axis of octagon. Defaults to 'z' **kwargs Keyword arguments passed to underlying cylinder and plane classes Attributes ---------- - top : openmc.ZPlane or openmc.XPlane + top : openmc.ZPlane or openmc.YPlane Top planar surface of octagon - bottom : openmc.ZPlane or openmc.XPlane + bottom : openmc.ZPlane or openmc.YPlane Bottom planar surface of octagon - right: openmc.YPlane or openmc.ZPlane + right: openmc.YPlane or openmc.XPlane Right planaer surface of octagon - left: openmc.YPlane or openmc.ZPlane + left: openmc.YPlane or openmc.XPlane Left planar surface of octagon upper_right : openmc.Plane Upper right planar surface of octagon From 71e76b251e1f9724fab1461d7ff824ff18aaabd2 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 12:47:44 -0500 Subject: [PATCH 0166/2654] Add reference to Octagon in the Sphinx docs --- docs/source/pythonapi/model.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index a6c89be7c..2fc27d40e 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -30,6 +30,7 @@ Composite Surfaces openmc.model.XConeOneSided openmc.model.YConeOneSided openmc.model.ZConeOneSided + openmc.model.Octagon TRISO Fuel Modeling ------------------- From f7d304f7955e47a8d98aa52004225dccee8fa344 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 13:02:32 -0500 Subject: [PATCH 0167/2654] use existing openmc function instead of custom one for plane_from_points --- openmc/model/surface_composite.py | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index be5736794..02022fa3c 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -3,18 +3,8 @@ from copy import copy import openmc from openmc.checkvalue import check_greater_than, check_value -from numpy import sqrt, cross, dot, array - -def _plane_from_points(p1, p2, p3): - # get plane from points p1, p2, p3 - n = cross(p2 - p1, p3 - p1) - n0 = -p1 - A = n[0] - B = n[1] - C = n[2] - D = dot(n, n0) - - return [A, B, C, -D] +import openmc.Plane.from_points as plane_from_points +from numpy import sqrt class CompositeSurface(ABC): """Multiple primitive surfaces combined into a composite surface""" @@ -164,19 +154,14 @@ class Octagon(CompositeSurface): p_temp = [] for i in coord_map: p_temp += [p[i]] - calibrated_points += [array(p_temp)] + calibrated_points += [p_temp] p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points - upper_right_params = _plane_from_points(p1_ur, p2_ur, p3_ur) - lower_right_params = _plane_from_points(p1_lr, p2_lr, p3_lr) - lower_left_params = _plane_from_points(-p1_ur, -p2_ur, -p3_ur) - upper_left_params = _plane_from_points(-p1_lr, -p2_lr, -p3_lr) - - self.upper_right = openmc.Plane(*tuple(upper_right_params), **kwargs) - self.lower_right = openmc.Plane(*tuple(lower_right_params), **kwargs) - self.lower_left = openmc.Plane(*tuple(lower_left_params), **kwargs) - self.upper_left = openmc.Plane(*tuple(upper_left_params), **kwargs) + self.upper_right = plane_from_points(p1_ur, p2_ur, p3_ur, **kwargs) + self.lower_right = plane_from_points(p1_lr, p2_lr, p3_lr, **kwargs) + self.lower_left = plane_from_points(-p1_ur, -p2_ur, -p3_ur, **kwargs) + self.upper_left = plane_from_points(-p1_lr, -p2_lr, -p3_lr, **kwargs) def __neg__(self): From ab0fcc7ca4e8ef9241fd41e2746239541f0b3a91 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 13:03:12 -0500 Subject: [PATCH 0168/2654] put Octagon in alphabetical order --- docs/source/pythonapi/model.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index 2fc27d40e..6c707cbdc 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -25,12 +25,12 @@ Composite Surfaces :nosignatures: :template: myclass.rst + openmc.model.Octagon openmc.model.RectangularParallelepiped openmc.model.RightCircularCylinder openmc.model.XConeOneSided openmc.model.YConeOneSided openmc.model.ZConeOneSided - openmc.model.Octagon TRISO Fuel Modeling ------------------- From f4e96453ab10fa1000dcd8e3969ebee70410e11e Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 14:24:49 -0500 Subject: [PATCH 0169/2654] changed Octagon to IsogonalOctagon --- docs/source/pythonapi/model.rst | 2 +- openmc/model/surface_composite.py | 41 ++++++++++++++-------- tests/unit_tests/test_surface_composite.py | 4 +-- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index 6c707cbdc..145330127 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -25,7 +25,7 @@ Composite Surfaces :nosignatures: :template: myclass.rst - openmc.model.Octagon + openmc.model.IsogonalOctagon openmc.model.RectangularParallelepiped openmc.model.RightCircularCylinder openmc.model.XConeOneSided diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 02022fa3c..897ff0881 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -3,7 +3,6 @@ from copy import copy import openmc from openmc.checkvalue import check_greater_than, check_value -import openmc.Plane.from_points as plane_from_points from numpy import sqrt class CompositeSurface(ABC): @@ -51,12 +50,15 @@ class CompositeSurface(ABC): def __neg__(self): """Return the negative half-space of the composite surface.""" -class Octagon(CompositeSurface): - """Infinite octogonal prism composite surface +class IsogonalOctagon(CompositeSurface): + """Infinite isogonal octagon composite surface - An octagonal prism is composed of eight planar surfaces. The prism is - parallel to the x, y, or z axis; two pars of surfaces are perpendicular to - the y and z, x and z, or x and y axes, respectively. + An isogonal octagon is composed of eight planar surfaces. The prism is + parallel to the x, y, or z axis. The remaining two axes (y and z, x and z, + or x and y) serve as a basis for constructing the surfaces. Two surfaces + are parallel to the first basis axis, two surfaces are parallel + to the second basis axis, and the remaining four surfaces intersect both + basis axes at 45 degree angles. This class acts as a proper surface, meaning that unary `+` and `-` operators applied to it will produce a half-space. The negative side is @@ -65,16 +67,18 @@ class Octagon(CompositeSurface): Parameters ---------- center : iterable of float - (q1,q2) coordinate for the central axis of the octagon. (q1,q2) pairs - are (y,z), (x,z), or (x,y). + Coordinate for the central axis of the octagon in the + (y, z), (x, z), or (x, y) basis. r1 : float - Half-width of octagon across axis-pendicular sides + Half-width of octagon across its basis axis-parallel sides in units + of cm r2 : float - Half-width of octagon across off-axis sides + Half-width of octagon across its basis axis intersecting sides in + units of cm. Must be less than :math:`\sqrt{2} r_1`. axis : {'x', 'y', 'z'} Central axis of octagon. Defaults to 'z' **kwargs - Keyword arguments passed to underlying cylinder and plane classes + Keyword arguments passed to underlying plane classes Attributes ---------- @@ -114,6 +118,9 @@ class Octagon(CompositeSurface): cleft = q2c-r1 # Side lengths + if (r2 > r1 * sqrt(2)): + raise ValueError(f'r2 must be less than {sqrt(2) * r1}') + L_perp_ax1 = (r2 * sqrt(2) - r1) * 2 L_perp_ax2 = (r1 * sqrt(2) - r2) * 2 @@ -158,10 +165,14 @@ class Octagon(CompositeSurface): p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points - self.upper_right = plane_from_points(p1_ur, p2_ur, p3_ur, **kwargs) - self.lower_right = plane_from_points(p1_lr, p2_lr, p3_lr, **kwargs) - self.lower_left = plane_from_points(-p1_ur, -p2_ur, -p3_ur, **kwargs) - self.upper_left = plane_from_points(-p1_lr, -p2_lr, -p3_lr, **kwargs) + self.upper_right = openmc.Plane.from_points(p1_ur, p2_ur, p3_ur, + **kwargs) + self.lower_right = openmc.Plane.from_points(p1_lr, p2_lr, p3_lr, + **kwargs) + self.lower_left = openmc.Plane.from_points(-p1_ur, -p2_ur, -p3_ur, + **kwargs) + self.upper_left = openmc.Plane.from_points(-p1_lr, -p2_lr, -p3_lr, + **kwargs) def __neg__(self): diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index d3ec10cf4..c2620a92a 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -159,7 +159,7 @@ def test_cone_one_sided(axis, point_pos, point_neg, ll_true): ("z", "Y", "X", 2), ] ) -def test_octagon(axis, plane_tb, plane_lr, axis_idx): +def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): center = np.array([0.,0.]) point_pos = np.array([0.8,0.8]) point_neg = np.array([0.7,0.7]) @@ -167,7 +167,7 @@ def test_octagon(axis, plane_tb, plane_lr, axis_idx): r2 = 1. plane_top_bottom = getattr(openmc, plane_tb + "Plane") plane_left_right = getattr(openmc, plane_lr + "Plane") - s = openmc.model.Octagon(center, r1, r2, axis=axis) + s = openmc.model.IsogonalOctagon(center, r1, r2, axis=axis) assert isinstance(s.top, plane_top_bottom) assert isinstance(s.bottom, plane_top_bottom) assert isinstance(s.right, plane_left_right) From 0518bdcb7bb08a80f45829c2396c90ffc2fc059a Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 14:32:14 -0500 Subject: [PATCH 0170/2654] fix plane point calculation --- openmc/model/surface_composite.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 897ff0881..38b3800fa 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -3,7 +3,7 @@ from copy import copy import openmc from openmc.checkvalue import check_greater_than, check_value -from numpy import sqrt +from numpy import sqrt, array class CompositeSurface(ABC): """Multiple primitive surfaces combined into a composite surface""" @@ -161,18 +161,14 @@ class IsogonalOctagon(CompositeSurface): p_temp = [] for i in coord_map: p_temp += [p[i]] - calibrated_points += [p_temp] + calibrated_points += [array(p_temp)] p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points - self.upper_right = openmc.Plane.from_points(p1_ur, p2_ur, p3_ur, - **kwargs) - self.lower_right = openmc.Plane.from_points(p1_lr, p2_lr, p3_lr, - **kwargs) - self.lower_left = openmc.Plane.from_points(-p1_ur, -p2_ur, -p3_ur, - **kwargs) - self.upper_left = openmc.Plane.from_points(-p1_lr, -p2_lr, -p3_lr, - **kwargs) + self.upper_right = openmc.Plane.from_points(p1_ur, p2_ur, p3_ur, **kwargs) + self.lower_right = openmc.Plane.from_points(p1_lr, p2_lr, p3_lr, **kwargs) + self.lower_left = openmc.Plane.from_points(-p1_ur, -p2_ur, -p3_ur, **kwargs) + self.upper_left = openmc.Plane.from_points(-p1_lr, -p2_lr, -p3_lr, **kwargs) def __neg__(self): From 1cc80135f3158a8c9c51199ab282a546c554bc20 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 16:21:42 -0500 Subject: [PATCH 0171/2654] consitency changes to CylinderSector --- openmc/model/surface_composite.py | 89 ++++++++++++++++--------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 0151d19e8..9b674b494 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -2,6 +2,7 @@ from abc import ABC, abstractmethod from copy import copy import openmc +from math import sin, cos, sqrt from openmc.checkvalue import check_greater_than, check_value @@ -168,22 +169,24 @@ class RectangularParallelepiped(CompositeSurface): class CylinderSector(CompositeSurface): """Infinite cylindrical sector composite surface - This class - acts as a proper surface, meaning that unary `+` and `-` operators applied - to it will produce a half-space. The negative side is defined to be the - region inside of the octogonal prism. + This class acts as a proper surface, meaning that unary `+` and `-` + operators applied to it will produce a half-space. The negative + side is defined to be the region inside of the cylinder sector. Parameters ---------- - center_axis : 2-tuple - (x,y), (x,z), or (y,z) coordiante of cylinders' central axes. - Defaults to (0,0) + center : iterable of float + Coordinate for central axes of cylinders in the (y, z), (x,z), or + (x, y) basis. Defaults to (0,0) r1, r2 : float Inner and outer cylinder radii - alpha1, alpha2 : float - Angular segmentation in degrees relative to the x-, x-, or y-axis. + theta0 : float + Angular offset of the sector in degrees relative to the primary basis + axis (+y or +x). + theta : float + Angular width of the sector in degrees. axis : {'z', 'y', 'x'} - Axes of the cylinders + Central axis of the cylinders. Defaults to z **kwargs Keyword arguments passed to underlying plane classes @@ -193,67 +196,67 @@ class CylinderSector(CompositeSurface): Outer cylinder surface inner : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder Inner cylinder surface - plane_1 : openmc.Plane - Segment plane corresponding to :attr:`alpha1` - plane_2 : openmc.Plane - Segmenting plane correspodning to :attr:`alpha2` + plane0 : openmc.Plane + Plane at angle :math:`\theta_0` relative to the first basis axis + plane1 : openmc.Plane + Plane at angle :math:`\theta_0 + \theta` relative to the first + basis axis. """ _surface_names = ('outer','inner', - 'plane_a', 'plane_b') + 'plane0', 'plane1') - def __init__(self, center, r1, r2, alpha1, alpha2, **kwargs): + def __init__(self, center, r1, r2, theta0, theta, axis='z', **kwargs): + + theta0 = np.pi / 180 * theta0 + theta = np.pi / 180 * theta + theta1 = theta0 + theta - alpha1 = np.pi / 180 * alpha1 - alpha2 = np.pi / 180 * alpha2 # Coords for axis-perpendicular planes - p1 = np.array([0,0,1]) + p1 = np.array([0,0]) - p2_plane1 = np.array([r1 * np.cos(alpha1), -r1 * np.sin(alpha1), 0]) - p3_plane1 = np.array([r2 * np.cos(alpha1), -r2 * np.sin(alpha1), 0]) + p2_plane0 = np.array([r1 * cos(theta0), r1 * sin(theta0)]) + p3_plane0 = np.array([r2 * cos(theta0), r2 * sin(theta0)]) - p2_plane2 = np.array([r1 * np.cos(alpha2), r1 * np.sin(alpha2), 0]) - p3_plane2 = np.array([r2 * np.cos(alpha2), r2 * np.sin(alpha2), 0]) + p2_plane1 = np.array([r1 * cos(theta1), r1 * sin(theta1)]) + p3_plane1 = np.array([r2 * cos(theta1), r2 * sin(theta1)]) - points = [p1, p2_plane1, p3_plane1, p2_plane2, p3_plane2] + points = [p2_plane0, p3_plane0, p2_plane1, p3_plane1] if axis == 'x': - self.inner = openmc.XCylinder(*center_axis, r=r1, **kwargs) - self.outer = openmc.XCylinder(*center_axis, r=r2, **kwargs) - coord_map = [2,0,1] + self.inner = openmc.XCylinder(*center, r=r1, **kwargs) + self.outer = openmc.XCylinder(*center, r=r2, **kwargs) + axis_idx = 0 elif axis == 'y': - self.inner = openmc.YCylinder(*center_axis, r=r1, **kwargs) - self.outer = openmc.YCylinder(*center_axis, r=r2, **kwargs) - coord_map = [0,2,1] + self.inner = openmc.YCylinder(*center, r=r1, **kwargs) + self.outer = openmc.YCylinder(*center, r=r2, **kwargs) + axis_idx = 1 elif axis == 'z': - self.inner = openmc.ZCylinder(*center_axis, r=r1, **kwargs) - self.outer = openmc.ZCylinder(*center_axis, r=r2, **kwargs) - coord_map = [0,1,2] + self.inner = openmc.ZCylinder(*center, r=r1, **kwargs) + self.outer = openmc.ZCylinder(*center, r=r2, **kwargs) + axis_idx = 3 calibrated_points = [] for p in points: p_temp = [] for i in coord_map: - p_temp += [p[i]] - calibrated_points += [np.array(p_temp)] + calibrated_points += [np.insert(p, axis_idx, 0)] - p1, p2_plane1, p3_plane1, p2_plane2, p3_plane2 = calibrated_points - - plane1_params = _plane_from_points(p1, p2_plane1, p3_plane1) - plane2_params = _plane_from_points(p1, p2_plane2, p3_plane2) + p2_plane0, p3_plane0, p2_plane1, p3_plane1 = calibrated_points + p1 = np.insert(p1, axis_idx, 1) + self.plane0 = openmc.Plane.from_points(p1, p2_plane0, p3_plane0, **kwargs) + self.plane1 = openmc.Plane.from_points(p1, p2_plane1, p3_plane1, **kwargs) self.inner = openmc.ZCylinder(x0=x0, y0=y0, r=r1, **kwargs) self.outer = openmc.ZCylinder(x0=x0, y0=y0, r=r2, **kwargs) - self.plane1 = openmc.Plane(*plane1_params, **kwargs) - self.plane2 = openmc.Plane(*plane2_params, **kwargs) def __neg__(self): - return -self.outer & +self.inner & -self.plane1 & +self.plane2 + return -self.outer & +self.inner & -self.plane0 & +self.plane1 def __pos__(self): - return +self.outer | -self.inner | +self.plane1 | -self.plane2 + return +self.outer | -self.inner | +self.plane0 | -self.plane1 class XConeOneSided(CompositeSurface): """One-sided cone parallel the x-axis From ded546802c13706203ade8b9a08b0c523736c5b9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 16:33:12 -0500 Subject: [PATCH 0172/2654] fix import statements; relax the error to a warning --- openmc/model/surface_composite.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 38b3800fa..ba26a2157 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -1,9 +1,10 @@ from abc import ABC, abstractmethod from copy import copy +from math import sqrt +from numpy import array import openmc from openmc.checkvalue import check_greater_than, check_value -from numpy import sqrt, array class CompositeSurface(ABC): """Multiple primitive surfaces combined into a composite surface""" @@ -74,7 +75,7 @@ class IsogonalOctagon(CompositeSurface): of cm r2 : float Half-width of octagon across its basis axis intersecting sides in - units of cm. Must be less than :math:`\sqrt{2} r_1`. + units of cm. Assumed to be less than :math:`r_1\sqrt{2}`. axis : {'x', 'y', 'z'} Central axis of octagon. Defaults to 'z' **kwargs @@ -87,7 +88,7 @@ class IsogonalOctagon(CompositeSurface): bottom : openmc.ZPlane or openmc.YPlane Bottom planar surface of octagon right: openmc.YPlane or openmc.XPlane - Right planaer surface of octagon + Right planar surface of octagon left: openmc.YPlane or openmc.XPlane Left planar surface of octagon upper_right : openmc.Plane @@ -119,7 +120,8 @@ class IsogonalOctagon(CompositeSurface): # Side lengths if (r2 > r1 * sqrt(2)): - raise ValueError(f'r2 must be less than {sqrt(2) * r1}') + raise Warning(f'r2 is greater than {sqrt(2) * r1}. Octagon may' + 'be erroneous.') L_perp_ax1 = (r2 * sqrt(2) - r1) * 2 L_perp_ax2 = (r1 * sqrt(2) - r2) * 2 From e10e2bbcf02165db2a5f324f6a41761f56633724 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 16:47:06 -0500 Subject: [PATCH 0173/2654] streamline the remapping of coordinates --- openmc/model/surface_composite.py | 47 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 9b674b494..2b55615a1 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -1,8 +1,9 @@ from abc import ABC, abstractmethod from copy import copy +from math import sqrt, pi, sin, cos +from numpy import array import openmc -from math import sin, cos, sqrt from openmc.checkvalue import check_greater_than, check_value @@ -209,41 +210,39 @@ class CylinderSector(CompositeSurface): def __init__(self, center, r1, r2, theta0, theta, axis='z', **kwargs): - theta0 = np.pi / 180 * theta0 - theta = np.pi / 180 * theta + theta0 = pi / 180 * theta0 + theta = pi / 180 * theta theta1 = theta0 + theta # Coords for axis-perpendicular planes - p1 = np.array([0,0]) + p1 = array([0.,0.,1.]) - p2_plane0 = np.array([r1 * cos(theta0), r1 * sin(theta0)]) - p3_plane0 = np.array([r2 * cos(theta0), r2 * sin(theta0)]) + p2_plane0 = array([r1 * cos(theta0), r1 * sin(theta0), 0.]) + p3_plane0 = array([r2 * cos(theta0), r2 * sin(theta0), 0.]) - p2_plane1 = np.array([r1 * cos(theta1), r1 * sin(theta1)]) - p3_plane1 = np.array([r2 * cos(theta1), r2 * sin(theta1)]) + p2_plane1 = array([r1 * cos(theta1), r1 * sin(theta1), 0.]) + p3_plane1 = array([r2 * cos(theta1), r2 * sin(theta1), 0.]) - points = [p2_plane0, p3_plane0, p2_plane1, p3_plane1] - if axis == 'x': - self.inner = openmc.XCylinder(*center, r=r1, **kwargs) - self.outer = openmc.XCylinder(*center, r=r2, **kwargs) - axis_idx = 0 - elif axis == 'y': - self.inner = openmc.YCylinder(*center, r=r1, **kwargs) - self.outer = openmc.YCylinder(*center, r=r2, **kwargs) - axis_idx = 1 - elif axis == 'z': + points = [p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1] + if axis == 'z': + coord_map = [0,1,2] self.inner = openmc.ZCylinder(*center, r=r1, **kwargs) self.outer = openmc.ZCylinder(*center, r=r2, **kwargs) - axis_idx = 3 + + elif axis == 'y': + coord_map = [0,2,1] + self.inner = openmc.YCylinder(*center, r=r1, **kwargs) + self.outer = openmc.YCylinder(*center, r=r2, **kwargs) + elif axis == 'x': + coord_map = [2,0,1] + self.inner = openmc.XCylinder(*center, r=r1, **kwargs) + self.outer = openmc.XCylinder(*center, r=r2, **kwargs) calibrated_points = [] for p in points: - p_temp = [] - for i in coord_map: - calibrated_points += [np.insert(p, axis_idx, 0)] + calibrated_points += [p[coord_map]] - p2_plane0, p3_plane0, p2_plane1, p3_plane1 = calibrated_points - p1 = np.insert(p1, axis_idx, 1) + p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1 = calibrated_points self.plane0 = openmc.Plane.from_points(p1, p2_plane0, p3_plane0, **kwargs) self.plane1 = openmc.Plane.from_points(p1, p2_plane1, p3_plane1, **kwargs) From 24f4ceb132a44d3cf86adcf05543aeec6fb897ca Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 17:10:11 -0500 Subject: [PATCH 0174/2654] fix warnings, syntax errors --- openmc/model/surface_composite.py | 51 +++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index ba26a2157..ac53a6e72 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -4,6 +4,7 @@ from math import sqrt from numpy import array import openmc +import warnings from openmc.checkvalue import check_greater_than, check_value class CompositeSurface(ABC): @@ -72,7 +73,7 @@ class IsogonalOctagon(CompositeSurface): (y, z), (x, z), or (x, y) basis. r1 : float Half-width of octagon across its basis axis-parallel sides in units - of cm + of cm. Assumed to be less than :math:`r_2\sqrt{2}`. r2 : float Half-width of octagon across its basis axis intersecting sides in units of cm. Assumed to be less than :math:`r_1\sqrt{2}`. @@ -109,31 +110,34 @@ class IsogonalOctagon(CompositeSurface): def __init__(self, center, r1, r2, axis='z', **kwargs): self._axis = axis - q1c, q2c = center + c1, c2 = center # Coords for axis-perpendicular planes - ctop = q1c+r1 - cbottom = q1c-r1 + ctop = c1 + r1 + cbottom = c1 - r1 - cright= q2c+r1 - cleft = q2c-r1 + cright = c2 + r1 + cleft = c2 - r1 # Side lengths - if (r2 > r1 * sqrt(2)): - raise Warning(f'r2 is greater than {sqrt(2) * r1}. Octagon may' - 'be erroneous.') + if r2 > r1 * sqrt(2): + warnings.warn(f'r2 is greater than sqrt(2) * r1. Octagon may' + \ + ' be erroneous.') + if r1 > r2 * sqrt(2): + warnings.warn(f'r1 is greater than sqrt(2) * r2. Octagon may' + \ + ' be erroneous.') L_perp_ax1 = (r2 * sqrt(2) - r1) * 2 L_perp_ax2 = (r1 * sqrt(2) - r2) * 2 # Coords for quadrant planes - p1_ur = [L_perp_ax1/2, r1, 0] - p2_ur = [r1, L_perp_ax1/2, 0] - p3_ur = [r1, L_perp_ax1/2, 1] + p1_ur = array([L_perp_ax1/2, r1, 0.]) + p2_ur = array([r1, L_perp_ax1/2, 0.]) + p3_ur = array([r1, L_perp_ax1/2, 1.]) - p1_lr = [r1, -L_perp_ax1/2, 0] - p2_lr = [L_perp_ax1/2, -r1, 0] - p3_lr = [L_perp_ax1/2, -r1, 1] + p1_lr = array([r1, -L_perp_ax1/2, 0.]) + p2_lr = array([L_perp_ax1/2, -r1, 0.]) + p3_lr = array([L_perp_ax1/2, -r1, 1.]) points = [p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr] @@ -160,17 +164,18 @@ class IsogonalOctagon(CompositeSurface): # Put our coordinates in (x,y,z) order calibrated_points = [] for p in points: - p_temp = [] - for i in coord_map: - p_temp += [p[i]] - calibrated_points += [array(p_temp)] + calibrated_points += [p[coord_map]] p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points - self.upper_right = openmc.Plane.from_points(p1_ur, p2_ur, p3_ur, **kwargs) - self.lower_right = openmc.Plane.from_points(p1_lr, p2_lr, p3_lr, **kwargs) - self.lower_left = openmc.Plane.from_points(-p1_ur, -p2_ur, -p3_ur, **kwargs) - self.upper_left = openmc.Plane.from_points(-p1_lr, -p2_lr, -p3_lr, **kwargs) + self.upper_right = openmc.Plane.from_points(p1_ur, p2_ur, p3_ur, + **kwargs) + self.lower_right = openmc.Plane.from_points(p1_lr, p2_lr, p3_lr, + **kwargs) + self.lower_left = openmc.Plane.from_points(-p1_ur, -p2_ur, -p3_ur, + **kwargs) + self.upper_left = openmc.Plane.from_points(-p1_lr, -p2_lr, -p3_lr, + **kwargs) def __neg__(self): From 41460568a6a743051f90b8fc7b907e74303ca1e0 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 17:13:39 -0500 Subject: [PATCH 0175/2654] minor syntax fix --- openmc/model/surface_composite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 2b55615a1..1635e21b6 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -257,6 +257,7 @@ class CylinderSector(CompositeSurface): def __pos__(self): return +self.outer | -self.inner | +self.plane0 | -self.plane1 + class XConeOneSided(CompositeSurface): """One-sided cone parallel the x-axis From ae881a126d8239d64ff8b31a67342e121005dafa Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 18:05:40 -0500 Subject: [PATCH 0176/2654] Added unit test --- tests/unit_tests/test_surface_composite.py | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index a1a218311..bafff706e 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -150,3 +150,59 @@ def test_cone_one_sided(axis, point_pos, point_neg, ll_true): # Make sure repr works repr(s) + +@pytest.mark.parametrize( + "axis, indices", [ + ("X", [0, 1, 2]), + ("Y", [1, 2, 0]), + ("Z", [2, 0, 1]), + ] +) +def test_cylinder_sector(axis, indices): + center = [0., 0.] + r1, r2 = 0.5, 1.5 + d = (r2 - r1) / 2 + theta0 = -60. + theta = 120. + s = openmc.model.CylinderSector(center, r1, r2, theta0, theta, + axis=axis.lower()) + assert isinstance(s.outer_cyl, getattr(openmc, axis + "Cylinder")) + assert isinstance(s.inner_cyl, getattr(openmc, axis + "Cylinder")) + assert isinstance(s.plane0, openmc.Plane) + assert isinstance(s.plane1, openmc.Plane) + + # Make sure boundary condition propagates + s.boundary_type = 'reflective' + assert s.boundary_type == 'reflective' + assert s.outer_cyl.boundary_type == 'reflective' + assert s.inner_cyl.boundary_type == 'reflective' + assert s.plane0.boundary_type == 'reflective' + assert s.plane1.boundary_type == 'reflective' + + # Check bounding box + ll, ur = (+s).bounding_box + assert np.all(np.isinf(ll)) + assert np.all(np.isinf(ur)) + ll, ur = (-s).bounding_box + assert ll == pytest.approx(np.roll([-np.inf, -r2, -r2], indices[0])) + assert ur == pytest.approx(np.roll([np.inf, r2, r2], indices[0])) + + # __contains__ on associated half-spaces + point_pos = np.roll([0, r2 + 1, 0], indices[0]) + assert point_pos in +s + assert point_pos not in -s + point_neg = np.roll([0, r1 + d/2, r1 + d/2], indices[0]) + assert point_neg in -s + assert point_neg not in +s + + # translate method + t = uniform(-5.0, 5.0) + s_t = s.translate((t, t, t)) + ll_t, ur_t = (-s_t).bounding_box + assert ur_t == pytest.approx(ur + t) + assert ll_t == pytest.approx(ll + t) + + # Make sure repr works + repr(s) + + From 10123bf55a9c74df880f261460381af4092f975c Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 18:05:54 -0500 Subject: [PATCH 0177/2654] consistency changes --- openmc/model/surface_composite.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 1635e21b6..a7c8d173e 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -205,11 +205,12 @@ class CylinderSector(CompositeSurface): """ - _surface_names = ('outer','inner', + _surface_names = ('outer_cyl','inner_cyl', 'plane0', 'plane1') def __init__(self, center, r1, r2, theta0, theta, axis='z', **kwargs): + self._axis = axis theta0 = pi / 180 * theta0 theta = pi / 180 * theta theta1 = theta0 + theta @@ -226,17 +227,16 @@ class CylinderSector(CompositeSurface): points = [p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1] if axis == 'z': coord_map = [0,1,2] - self.inner = openmc.ZCylinder(*center, r=r1, **kwargs) - self.outer = openmc.ZCylinder(*center, r=r2, **kwargs) - + self.inner_cyl = openmc.ZCylinder(*center, r=r1, **kwargs) + self.outer_cyl = openmc.ZCylinder(*center, r=r2, **kwargs) elif axis == 'y': - coord_map = [0,2,1] - self.inner = openmc.YCylinder(*center, r=r1, **kwargs) - self.outer = openmc.YCylinder(*center, r=r2, **kwargs) + coord_map = [0,2,1] + self.inner_cyl = openmc.YCylinder(*center, r=r1, **kwargs) + self.outer_cyl = openmc.YCylinder(*center, r=r2, **kwargs) elif axis == 'x': coord_map = [2,0,1] - self.inner = openmc.XCylinder(*center, r=r1, **kwargs) - self.outer = openmc.XCylinder(*center, r=r2, **kwargs) + self.inner_cyl = openmc.XCylinder(*center, r=r1, **kwargs) + self.outer_cyl = openmc.XCylinder(*center, r=r2, **kwargs) calibrated_points = [] for p in points: @@ -246,16 +246,20 @@ class CylinderSector(CompositeSurface): self.plane0 = openmc.Plane.from_points(p1, p2_plane0, p3_plane0, **kwargs) self.plane1 = openmc.Plane.from_points(p1, p2_plane1, p3_plane1, **kwargs) - self.inner = openmc.ZCylinder(x0=x0, y0=y0, r=r1, **kwargs) - self.outer = openmc.ZCylinder(x0=x0, y0=y0, r=r2, **kwargs) def __neg__(self): - return -self.outer & +self.inner & -self.plane0 & +self.plane1 + if self._axis == 'y': + return -self.outer_cyl & +self.inner_cyl & +self.plane0 & -self.plane1 + else: + return -self.outer_cyl & +self.inner_cyl & -self.plane0 & +self.plane1 def __pos__(self): - return +self.outer | -self.inner | +self.plane0 | -self.plane1 + if self._axis == 'y': + return +self.outer_cyl | -self.inner_cyl | -self.plane0 | +self.plane1 + else: + return +self.outer_cyl | -self.inner_cyl | +self.plane0 | -self.plane1 class XConeOneSided(CompositeSurface): From 370625be5532050f8c8ac0f581b9e35f0575ab03 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 18:06:48 -0500 Subject: [PATCH 0178/2654] Added reference to CylinderSector in the sphinx documentation --- docs/source/pythonapi/model.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index a6c89be7c..686bc8d1c 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -25,6 +25,7 @@ Composite Surfaces :nosignatures: :template: myclass.rst + openmc.model.CylinderSector openmc.model.RectangularParallelepiped openmc.model.RightCircularCylinder openmc.model.XConeOneSided From 04d040b4a9df8363660f1f78a4a5012df2ac3383 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 22:11:51 -0500 Subject: [PATCH 0179/2654] use lat instead of rlat --- tests/unit_tests/test_lattice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_lattice.py b/tests/unit_tests/test_lattice.py index 28da217b7..b82c2399d 100644 --- a/tests/unit_tests/test_lattice.py +++ b/tests/unit_tests/test_lattice.py @@ -157,11 +157,11 @@ def hlat3(pincell1, pincell2, uo2, water, zr): def test_get_nuclides(rlat2, rlat3, hlat2, hlat3): for lat in (rlat2, hlat2): - nucs = rlat2.get_nuclides() + nucs = lat.get_nuclides() assert sorted(nucs) == ['H1', 'O16', 'U235', 'Zr90', 'Zr91', 'Zr92', 'Zr94', 'Zr96'] for lat in (rlat3, hlat3): - nucs = rlat3.get_nuclides() + nucs = lat.get_nuclides() assert sorted(nucs) == ['H1', 'H2', 'O16', 'U235', 'Zr90', 'Zr91', 'Zr92', 'Zr94', 'Zr96'] From ff67c85587689f15f4685307a2b7aa6f8ddd7ea3 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 4 Apr 2022 22:13:10 -0500 Subject: [PATCH 0180/2654] use the correct lines variables --- tests/unit_tests/test_lattice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_lattice.py b/tests/unit_tests/test_lattice.py index b82c2399d..99bc284b0 100644 --- a/tests/unit_tests/test_lattice.py +++ b/tests/unit_tests/test_lattice.py @@ -360,7 +360,7 @@ def test_show_indices(): lines = openmc.HexLattice.show_indices(i).split('\n') assert len(lines) == 4*i - 3 lines_x = openmc.HexLattice.show_indices(i, 'x').split('\n') - assert len(lines) == 4*i - 3 + assert len(lines_x) == 4*i - 3 def test_unset_universes(): From 4699732faa450c134ff0a960f8995675d531674c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 15 Feb 2022 15:36:55 -0600 Subject: [PATCH 0181/2654] Separating the universe classes into their own source and header file --- CMakeLists.txt | 1 + include/openmc/cell.h | 62 +---------- include/openmc/universe.h | 79 ++++++++++++++ src/cell.cpp | 207 ----------------------------------- src/universe.cpp | 221 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 302 insertions(+), 268 deletions(-) create mode 100644 include/openmc/universe.h create mode 100644 src/universe.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e972c4937..788e8c681 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,6 +351,7 @@ list(APPEND libopenmc_SOURCES src/timer.cpp src/thermal.cpp src/track_output.cpp + src/universe.cpp src/urr.cpp src/volume_calc.cpp src/weight_windows.cpp diff --git a/include/openmc/cell.h b/include/openmc/cell.h index afc9a33c5..d975750a1 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -17,6 +17,7 @@ #include "openmc/neighbor_list.h" #include "openmc/position.h" #include "openmc/surface.h" +#include "openmc/universe.h" #include "openmc/vector.h" namespace openmc { @@ -48,36 +49,8 @@ namespace model { extern std::unordered_map cell_map; extern vector> cells; -extern std::unordered_map universe_map; -extern vector> universes; } // namespace model -//============================================================================== -//! A geometry primitive that fills all space and contains cells. -//============================================================================== - -class Universe { -public: - int32_t id_; //!< Unique ID - vector cells_; //!< Cells within this universe - - //! \brief Write universe information to an HDF5 group. - //! \param group_id An HDF5 group id. - virtual void to_hdf5(hid_t group_id) const; - - virtual bool find_cell(Particle& p) const; - - BoundingBox bounding_box() const; - - const GeometryType& geom_type() const { return geom_type_; } - GeometryType& geom_type() { return geom_type_; } - - unique_ptr partitioner_; - -private: - GeometryType geom_type_ = GeometryType::CSG; -}; - //============================================================================== //============================================================================== @@ -296,35 +269,6 @@ protected: vector::iterator start, const vector& rpn); }; -//============================================================================== -//! Speeds up geometry searches by grouping cells in a search tree. -// -//! Currently this object only works with universes that are divided up by a -//! bunch of z-planes. It could be generalized to other planes, cylinders, -//! and spheres. -//============================================================================== - -class UniversePartitioner { -public: - explicit UniversePartitioner(const Universe& univ); - - //! Return the list of cells that could contain the given coordinates. - const vector& get_cells(Position r, Direction u) const; - -private: - //! A sorted vector of indices to surfaces that partition the universe - vector surfs_; - - //! Vectors listing the indices of the cells that lie within each partition - // - //! There are n+1 partitions with n surfaces. `partitions_.front()` gives the - //! cells that lie on the negative side of `surfs_.front()`. - //! `partitions_.back()` gives the cells that lie on the positive side of - //! `surfs_.back()`. Otherwise, `partitions_[i]` gives cells sandwiched - //! between `surfs_[i-1]` and `surfs_[i]`. - vector> partitions_; -}; - //============================================================================== //! Define an instance of a particular cell //============================================================================== @@ -356,9 +300,5 @@ struct CellInstanceHash { void read_cells(pugi::xml_node node); -#ifdef DAGMC -class DAGUniverse; -#endif - } // namespace openmc #endif // OPENMC_CELL_H diff --git a/include/openmc/universe.h b/include/openmc/universe.h new file mode 100644 index 000000000..b6ed3e724 --- /dev/null +++ b/include/openmc/universe.h @@ -0,0 +1,79 @@ +#ifndef OPENMC_UNIVERSE_H +#define OPENMC_UNIVERSE_H + +#include "openmc/cell.h" + +namespace openmc { + +#ifdef DAGMC +class DAGUniverse; +#endif + +class Universe; +class UniversePartitioner; + +namespace model { + +extern std::unordered_map universe_map; +extern vector> universes; + +} // namespace model + + +//============================================================================== +//! A geometry primitive that fills all space and contains cells. +//============================================================================== + +class Universe { +public: + int32_t id_; //!< Unique ID + vector cells_; //!< Cells within this universe + + //! \brief Write universe information to an HDF5 group. + //! \param group_id An HDF5 group id. + virtual void to_hdf5(hid_t group_id) const; + + virtual bool find_cell(Particle& p) const; + + BoundingBox bounding_box() const; + + const GeometryType& geom_type() const { return geom_type_; } + GeometryType& geom_type() { return geom_type_; } + + unique_ptr partitioner_; + +private: + GeometryType geom_type_ = GeometryType::CSG; +}; + +//============================================================================== +//! Speeds up geometry searches by grouping cells in a search tree. +// +//! Currently this object only works with universes that are divided up by a +//! bunch of z-planes. It could be generalized to other planes, cylinders, +//! and spheres. +//============================================================================== + +class UniversePartitioner { +public: + explicit UniversePartitioner(const Universe& univ); + + //! Return the list of cells that could contain the given coordinates. + const vector& get_cells(Position r, Direction u) const; + +private: + //! A sorted vector of indices to surfaces that partition the universe + vector surfs_; + + //! Vectors listing the indices of the cells that lie within each partition + // + //! There are n+1 partitions with n surfaces. `partitions_.front()` gives the + //! cells that lie on the negative side of `surfs_.front()`. + //! `partitions_.back()` gives the cells that lie on the positive side of + //! `surfs_.back()`. Otherwise, `partitions_[i]` gives cells sandwiched + //! between `surfs_[i-1]` and `surfs_[i]`. + vector> partitions_; +}; + +} // namespace openmc +#endif // OPENMC_UNIVERSE_H \ No newline at end of file diff --git a/src/cell.cpp b/src/cell.cpp index 2b6555d12..28be2c2cf 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -34,8 +34,6 @@ namespace model { std::unordered_map cell_map; vector> cells; -std::unordered_map universe_map; -vector> universes; } // namespace model //============================================================================== @@ -186,66 +184,6 @@ vector generate_rpn(int32_t cell_id, vector infix) return rpn; } -//============================================================================== -// Universe implementation -//============================================================================== - -void Universe::to_hdf5(hid_t universes_group) const -{ - // Create a group for this universe. - auto group = create_group(universes_group, fmt::format("universe {}", id_)); - - // Write the geometry representation type. - write_string(group, "geom_type", "csg", false); - - // Write the contained cells. - if (cells_.size() > 0) { - vector cell_ids; - for (auto i_cell : cells_) - cell_ids.push_back(model::cells[i_cell]->id_); - write_dataset(group, "cells", cell_ids); - } - - close_group(group); -} - -bool Universe::find_cell(Particle& p) const -{ - const auto& cells { - !partitioner_ ? cells_ : partitioner_->get_cells(p.r_local(), p.u_local())}; - - for (auto it = cells.begin(); it != cells.end(); it++) { - int32_t i_cell = *it; - int32_t i_univ = p.coord(p.n_coord() - 1).universe; - if (model::cells[i_cell]->universe_ != i_univ) - continue; - - // Check if this cell contains the particle; - Position r {p.r_local()}; - Direction u {p.u_local()}; - auto surf = p.surface(); - if (model::cells[i_cell]->contains(r, u, surf)) { - p.coord(p.n_coord() - 1).cell = i_cell; - return true; - } - } - return false; -} - -BoundingBox Universe::bounding_box() const -{ - BoundingBox bbox = {INFTY, -INFTY, INFTY, -INFTY, INFTY, -INFTY}; - if (cells_.size() == 0) { - return {}; - } else { - for (const auto& cell : cells_) { - auto& c = model::cells[cell]; - bbox |= c->bounding_box(); - } - } - return bbox; -} - //============================================================================== // Cell implementation //============================================================================== @@ -876,151 +814,6 @@ bool CSGCell::contains_complex( } } -//============================================================================== -// UniversePartitioner implementation -//============================================================================== - -UniversePartitioner::UniversePartitioner(const Universe& univ) -{ - // Define an ordered set of surface indices that point to z-planes. Use a - // functor to to order the set by the z0_ values of the corresponding planes. - struct compare_surfs { - bool operator()(const int32_t& i_surf, const int32_t& j_surf) const - { - const auto* surf = model::surfaces[i_surf].get(); - const auto* zplane = dynamic_cast(surf); - double zi = zplane->z0_; - surf = model::surfaces[j_surf].get(); - zplane = dynamic_cast(surf); - double zj = zplane->z0_; - return zi < zj; - } - }; - std::set surf_set; - - // Find all of the z-planes in this universe. A set is used here for the - // O(log(n)) insertions that will ensure entries are not repeated. - for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->rpn_) { - if (token < OP_UNION) { - auto i_surf = std::abs(token) - 1; - const auto* surf = model::surfaces[i_surf].get(); - if (const auto* zplane = dynamic_cast(surf)) - surf_set.insert(i_surf); - } - } - } - - // Populate the surfs_ vector from the ordered set. - surfs_.insert(surfs_.begin(), surf_set.begin(), surf_set.end()); - - // Populate the partition lists. - partitions_.resize(surfs_.size() + 1); - for (auto i_cell : univ.cells_) { - // It is difficult to determine the bounds of a complex cell, so add complex - // cells to all partitions. - if (!model::cells[i_cell]->simple_) { - for (auto& p : partitions_) - p.push_back(i_cell); - continue; - } - - // Find the tokens for bounding z-planes. - int32_t lower_token = 0, upper_token = 0; - double min_z, max_z; - for (auto token : model::cells[i_cell]->rpn_) { - if (token < OP_UNION) { - const auto* surf = model::surfaces[std::abs(token) - 1].get(); - if (const auto* zplane = dynamic_cast(surf)) { - if (lower_token == 0 || zplane->z0_ < min_z) { - lower_token = token; - min_z = zplane->z0_; - } - if (upper_token == 0 || zplane->z0_ > max_z) { - upper_token = token; - max_z = zplane->z0_; - } - } - } - } - - // If there are no bounding z-planes, add this cell to all partitions. - if (lower_token == 0) { - for (auto& p : partitions_) - p.push_back(i_cell); - continue; - } - - // Find the first partition this cell lies in. If the lower_token indicates - // a negative halfspace, then the cell is unbounded in the lower direction - // and it lies in the first partition onward. Otherwise, it is bounded by - // the positive halfspace given by the lower_token. - int first_partition = 0; - if (lower_token > 0) { - for (int i = 0; i < surfs_.size(); ++i) { - if (lower_token == surfs_[i] + 1) { - first_partition = i + 1; - break; - } - } - } - - // Find the last partition this cell lies in. The logic is analogous to the - // logic for first_partition. - int last_partition = surfs_.size(); - if (upper_token < 0) { - for (int i = first_partition; i < surfs_.size(); ++i) { - if (upper_token == -(surfs_[i] + 1)) { - last_partition = i; - break; - } - } - } - - // Add the cell to all relevant partitions. - for (int i = first_partition; i <= last_partition; ++i) { - partitions_[i].push_back(i_cell); - } - } -} - -const vector& UniversePartitioner::get_cells( - Position r, Direction u) const -{ - // Perform a binary search for the partition containing the given coordinates. - int left = 0; - int middle = (surfs_.size() - 1) / 2; - int right = surfs_.size() - 1; - while (true) { - // Check the sense of the coordinates for the current surface. - const auto& surf = *model::surfaces[surfs_[middle]]; - if (surf.sense(r, u)) { - // The coordinates lie in the positive halfspace. Recurse if there are - // more surfaces to check. Otherwise, return the cells on the positive - // side of this surface. - int right_leaf = right - (right - middle) / 2; - if (right_leaf != middle) { - left = middle + 1; - middle = right_leaf; - } else { - return partitions_[middle + 1]; - } - - } else { - // The coordinates lie in the negative halfspace. Recurse if there are - // more surfaces to check. Otherwise, return the cells on the negative - // side of this surface. - int left_leaf = left + (middle - left) / 2; - if (left_leaf != middle) { - right = middle - 1; - middle = left_leaf; - } else { - return partitions_[middle]; - } - } - } -} - //============================================================================== // Non-method functions //============================================================================== diff --git a/src/universe.cpp b/src/universe.cpp new file mode 100644 index 000000000..f4b5e7d29 --- /dev/null +++ b/src/universe.cpp @@ -0,0 +1,221 @@ +#include "openmc/universe.h" + +#include + +#include "openmc/hdf5_interface.h" + +namespace openmc { + +namespace model { + +std::unordered_map universe_map; +vector> universes; + +} // namespace model + +//============================================================================== +// Universe implementation +//============================================================================== + +void Universe::to_hdf5(hid_t universes_group) const +{ + // Create a group for this universe. + auto group = create_group(universes_group, fmt::format("universe {}", id_)); + + // Write the geometry representation type. + write_string(group, "geom_type", "csg", false); + + // Write the contained cells. + if (cells_.size() > 0) { + vector cell_ids; + for (auto i_cell : cells_) + cell_ids.push_back(model::cells[i_cell]->id_); + write_dataset(group, "cells", cell_ids); + } + + close_group(group); +} + +bool Universe::find_cell(Particle& p) const +{ + const auto& cells { + !partitioner_ ? cells_ : partitioner_->get_cells(p.r_local(), p.u_local())}; + + for (auto it = cells.begin(); it != cells.end(); it++) { + int32_t i_cell = *it; + int32_t i_univ = p.coord(p.n_coord() - 1).universe; + if (model::cells[i_cell]->universe_ != i_univ) + continue; + + // Check if this cell contains the particle; + Position r {p.r_local()}; + Direction u {p.u_local()}; + auto surf = p.surface(); + if (model::cells[i_cell]->contains(r, u, surf)) { + p.coord(p.n_coord() - 1).cell = i_cell; + return true; + } + } + return false; +} + +BoundingBox Universe::bounding_box() const +{ + BoundingBox bbox = {INFTY, -INFTY, INFTY, -INFTY, INFTY, -INFTY}; + if (cells_.size() == 0) { + return {}; + } else { + for (const auto& cell : cells_) { + auto& c = model::cells[cell]; + bbox |= c->bounding_box(); + } + } + return bbox; +} + +//============================================================================== +// UniversePartitioner implementation +//============================================================================== + +UniversePartitioner::UniversePartitioner(const Universe& univ) +{ + // Define an ordered set of surface indices that point to z-planes. Use a + // functor to to order the set by the z0_ values of the corresponding planes. + struct compare_surfs { + bool operator()(const int32_t& i_surf, const int32_t& j_surf) const + { + const auto* surf = model::surfaces[i_surf].get(); + const auto* zplane = dynamic_cast(surf); + double zi = zplane->z0_; + surf = model::surfaces[j_surf].get(); + zplane = dynamic_cast(surf); + double zj = zplane->z0_; + return zi < zj; + } + }; + std::set surf_set; + + // Find all of the z-planes in this universe. A set is used here for the + // O(log(n)) insertions that will ensure entries are not repeated. + for (auto i_cell : univ.cells_) { + for (auto token : model::cells[i_cell]->rpn_) { + if (token < OP_UNION) { + auto i_surf = std::abs(token) - 1; + const auto* surf = model::surfaces[i_surf].get(); + if (const auto* zplane = dynamic_cast(surf)) + surf_set.insert(i_surf); + } + } + } + + // Populate the surfs_ vector from the ordered set. + surfs_.insert(surfs_.begin(), surf_set.begin(), surf_set.end()); + + // Populate the partition lists. + partitions_.resize(surfs_.size() + 1); + for (auto i_cell : univ.cells_) { + // It is difficult to determine the bounds of a complex cell, so add complex + // cells to all partitions. + if (!model::cells[i_cell]->simple_) { + for (auto& p : partitions_) + p.push_back(i_cell); + continue; + } + + // Find the tokens for bounding z-planes. + int32_t lower_token = 0, upper_token = 0; + double min_z, max_z; + for (auto token : model::cells[i_cell]->rpn_) { + if (token < OP_UNION) { + const auto* surf = model::surfaces[std::abs(token) - 1].get(); + if (const auto* zplane = dynamic_cast(surf)) { + if (lower_token == 0 || zplane->z0_ < min_z) { + lower_token = token; + min_z = zplane->z0_; + } + if (upper_token == 0 || zplane->z0_ > max_z) { + upper_token = token; + max_z = zplane->z0_; + } + } + } + } + + // If there are no bounding z-planes, add this cell to all partitions. + if (lower_token == 0) { + for (auto& p : partitions_) + p.push_back(i_cell); + continue; + } + + // Find the first partition this cell lies in. If the lower_token indicates + // a negative halfspace, then the cell is unbounded in the lower direction + // and it lies in the first partition onward. Otherwise, it is bounded by + // the positive halfspace given by the lower_token. + int first_partition = 0; + if (lower_token > 0) { + for (int i = 0; i < surfs_.size(); ++i) { + if (lower_token == surfs_[i] + 1) { + first_partition = i + 1; + break; + } + } + } + + // Find the last partition this cell lies in. The logic is analogous to the + // logic for first_partition. + int last_partition = surfs_.size(); + if (upper_token < 0) { + for (int i = first_partition; i < surfs_.size(); ++i) { + if (upper_token == -(surfs_[i] + 1)) { + last_partition = i; + break; + } + } + } + + // Add the cell to all relevant partitions. + for (int i = first_partition; i <= last_partition; ++i) { + partitions_[i].push_back(i_cell); + } + } +} + +const vector& UniversePartitioner::get_cells( + Position r, Direction u) const +{ + // Perform a binary search for the partition containing the given coordinates. + int left = 0; + int middle = (surfs_.size() - 1) / 2; + int right = surfs_.size() - 1; + while (true) { + // Check the sense of the coordinates for the current surface. + const auto& surf = *model::surfaces[surfs_[middle]]; + if (surf.sense(r, u)) { + // The coordinates lie in the positive halfspace. Recurse if there are + // more surfaces to check. Otherwise, return the cells on the positive + // side of this surface. + int right_leaf = right - (right - middle) / 2; + if (right_leaf != middle) { + left = middle + 1; + middle = right_leaf; + } else { + return partitions_[middle + 1]; + } + + } else { + // The coordinates lie in the negative halfspace. Recurse if there are + // more surfaces to check. Otherwise, return the cells on the negative + // side of this surface. + int left_leaf = left + (middle - left) / 2; + if (left_leaf != middle) { + right = middle - 1; + middle = left_leaf; + } else { + return partitions_[middle]; + } + } + } +} + +} \ No newline at end of file From b9520580de58cce3d66c925fe741c5479d737aa1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 5 Apr 2022 08:55:41 -0500 Subject: [PATCH 0182/2654] Formatting updates --- include/openmc/universe.h | 3 +-- src/universe.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/openmc/universe.h b/include/openmc/universe.h index b6ed3e724..b98d2d57f 100644 --- a/include/openmc/universe.h +++ b/include/openmc/universe.h @@ -19,7 +19,6 @@ extern vector> universes; } // namespace model - //============================================================================== //! A geometry primitive that fills all space and contains cells. //============================================================================== @@ -76,4 +75,4 @@ private: }; } // namespace openmc -#endif // OPENMC_UNIVERSE_H \ No newline at end of file +#endif // OPENMC_UNIVERSE_H diff --git a/src/universe.cpp b/src/universe.cpp index f4b5e7d29..f3f9cf8e8 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -218,4 +218,4 @@ const vector& UniversePartitioner::get_cells( } } -} \ No newline at end of file +} // namespace openmc From a3ae1c254abcc1e798fcd17072ea2361fb1bdbca Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 5 Apr 2022 09:50:41 -0500 Subject: [PATCH 0183/2654] apply @paulromano's suggestions --- openmc/model/surface_composite.py | 38 ++++++++++------------ tests/unit_tests/test_surface_composite.py | 7 ++-- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index ac53a6e72..7a92a69ef 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -52,6 +52,7 @@ class CompositeSurface(ABC): def __neg__(self): """Return the negative half-space of the composite surface.""" + class IsogonalOctagon(CompositeSurface): """Infinite isogonal octagon composite surface @@ -143,30 +144,29 @@ class IsogonalOctagon(CompositeSurface): # Orientation specific variables if axis == 'z': - coord_map = [0,1,2] - self.top = openmc.YPlane(y0=ctop, **kwargs) - self.bottom = openmc.YPlane(y0=cbottom, **kwargs) - self.right = openmc.XPlane(x0=cright, **kwargs) - self.left = openmc.XPlane(x0=cleft, **kwargs) + coord_map = [0, 1, 2] + self.top = openmc.YPlane(ctop, **kwargs) + self.bottom = openmc.YPlane(cbottom, **kwargs) + self.right = openmc.XPlane(cright, **kwargs) + self.left = openmc.XPlane(cleft, **kwargs) elif axis == 'y': - coord_map = [0,2,1] - self.top = openmc.ZPlane(z0=ctop, **kwargs) - self.bottom = openmc.ZPlane(z0=cbottom, **kwargs) - self.right = openmc.XPlane(x0=cright, **kwargs) - self.left = openmc.XPlane(x0=cleft, **kwargs) + coord_map = [0, 2, 1] + self.top = openmc.ZPlane(ctop, **kwargs) + self.bottom = openmc.ZPlane(cbottom, **kwargs) + self.right = openmc.XPlane(cright, **kwargs) + self.left = openmc.XPlane(cleft, **kwargs) elif axis == 'x': - coord_map = [2,0,1] - self.top = openmc.ZPlane(z0=ctop, **kwargs) - self.bottom = openmc.ZPlane(z0=cbottom, **kwargs) - self.right = openmc.YPlane(y0=cright, **kwargs) - self.left = openmc.YPlane(y0=cleft, **kwargs) + coord_map = [2, 0, 1] + self.top = openmc.ZPlane(ctop, **kwargs) + self.bottom = openmc.ZPlane(cbottom, **kwargs) + self.right = openmc.YPlane(cright, **kwargs) + self.left = openmc.YPlane(cleft, **kwargs) # Put our coordinates in (x,y,z) order - calibrated_points = [] for p in points: - calibrated_points += [p[coord_map]] + p[:] = p[coord_map] - p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points + #p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points self.upper_right = openmc.Plane.from_points(p1_ur, p2_ur, p3_ur, **kwargs) @@ -177,7 +177,6 @@ class IsogonalOctagon(CompositeSurface): self.upper_left = openmc.Plane.from_points(-p1_lr, -p2_lr, -p3_lr, **kwargs) - def __neg__(self): region1 = -self.top & +self.bottom & -self.right & +self.left if self._axis == 'y': @@ -189,7 +188,6 @@ class IsogonalOctagon(CompositeSurface): return region1 & region2 - def __pos__(self): region1 = +self.top | -self.bottom | +self.right | -self.left if self._axis == 'y': diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index c2620a92a..0668e82ac 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -160,9 +160,9 @@ def test_cone_one_sided(axis, point_pos, point_neg, ll_true): ] ) def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): - center = np.array([0.,0.]) - point_pos = np.array([0.8,0.8]) - point_neg = np.array([0.7,0.7]) + center = np.array([0., 0.]) + point_pos = np.array([0.8, 0.8]) + point_neg = np.array([0.7, 0.7]) r1 = 1. r2 = 1. plane_top_bottom = getattr(openmc, plane_tb + "Plane") @@ -221,4 +221,3 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): repr(s) - From 0a3ac3dea129574fc0d360bf79260de6bafa4977 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 5 Apr 2022 10:11:41 -0500 Subject: [PATCH 0184/2654] switch ordering of coord_map in the y-axis case, remove unneeded if-statements, update docstring --- openmc/model/surface_composite.py | 46 ++++++++++++------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 7a92a69ef..25033ac4b 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -57,7 +57,7 @@ class IsogonalOctagon(CompositeSurface): """Infinite isogonal octagon composite surface An isogonal octagon is composed of eight planar surfaces. The prism is - parallel to the x, y, or z axis. The remaining two axes (y and z, x and z, + parallel to the x, y, or z axis. The remaining two axes (y and z, z and x, or x and y) serve as a basis for constructing the surfaces. Two surfaces are parallel to the first basis axis, two surfaces are parallel to the second basis axis, and the remaining four surfaces intersect both @@ -71,7 +71,7 @@ class IsogonalOctagon(CompositeSurface): ---------- center : iterable of float Coordinate for the central axis of the octagon in the - (y, z), (x, z), or (x, y) basis. + (y, z), (z, x), or (x, y) basis. r1 : float Half-width of octagon across its basis axis-parallel sides in units of cm. Assumed to be less than :math:`r_2\sqrt{2}`. @@ -85,13 +85,13 @@ class IsogonalOctagon(CompositeSurface): Attributes ---------- - top : openmc.ZPlane or openmc.YPlane + top : openmc.ZPlane, openmc.XPlane, or openmc.YPlane Top planar surface of octagon - bottom : openmc.ZPlane or openmc.YPlane + bottom : openmc.ZPlane, openmc.XPlane, or openmc.YPlane Bottom planar surface of octagon - right: openmc.YPlane or openmc.XPlane + right: openmc.YPlane, openmc.ZPlane, or openmc.XPlane Right planar surface of octagon - left: openmc.YPlane or openmc.XPlane + left: openmc.YPlane, openmc.ZPlane, or openmc.XPlane Left planar surface of octagon upper_right : openmc.Plane Upper right planar surface of octagon @@ -150,11 +150,11 @@ class IsogonalOctagon(CompositeSurface): self.right = openmc.XPlane(cright, **kwargs) self.left = openmc.XPlane(cleft, **kwargs) elif axis == 'y': - coord_map = [0, 2, 1] - self.top = openmc.ZPlane(ctop, **kwargs) - self.bottom = openmc.ZPlane(cbottom, **kwargs) - self.right = openmc.XPlane(cright, **kwargs) - self.left = openmc.XPlane(cleft, **kwargs) + coord_map = [1, 2, 0] + self.top = openmc.XPlane(ctop, **kwargs) + self.bottom = openmc.XPlane(cbottom, **kwargs) + self.right = openmc.ZPlane(cright, **kwargs) + self.left = openmc.ZPlane(cleft, **kwargs) elif axis == 'x': coord_map = [2, 0, 1] self.top = openmc.ZPlane(ctop, **kwargs) @@ -178,26 +178,14 @@ class IsogonalOctagon(CompositeSurface): **kwargs) def __neg__(self): - region1 = -self.top & +self.bottom & -self.right & +self.left - if self._axis == 'y': - region2 = -self.upper_right & -self.lower_right & \ - +self.lower_left & +self.upper_left - else: - region2 = +self.upper_right & +self.lower_right & \ - -self.lower_left & -self.upper_left - - return region1 & region2 + return -self.top & +self.bottom & -self.right & +self.left & \ + +self.upper_right & +self.lower_right & -self.lower_left & \ + -self.upper_left def __pos__(self): - region1 = +self.top | -self.bottom | +self.right | -self.left - if self._axis == 'y': - region2 = +self.upper_right | +self.lower_right | \ - -self.lower_left | -self.upper_left - else: - region2 = -self.upper_right | -self.lower_right | \ - +self.lower_left | +self.upper_left - - return region1 | region2 + return +self.top | -self.bottom | +self.right | -self.left | \ + -self.upper_right | -self.lower_right | +self.lower_left | \ + +self.upper_left class RightCircularCylinder(CompositeSurface): From a289cb73977abdbd15b9f50202f78d59ffd24025 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 5 Apr 2022 10:14:50 -0500 Subject: [PATCH 0185/2654] change warnings to exceptions; remove cruft comment --- openmc/model/surface_composite.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 25033ac4b..6ecdd3152 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -4,7 +4,6 @@ from math import sqrt from numpy import array import openmc -import warnings from openmc.checkvalue import check_greater_than, check_value class CompositeSurface(ABC): @@ -74,10 +73,10 @@ class IsogonalOctagon(CompositeSurface): (y, z), (z, x), or (x, y) basis. r1 : float Half-width of octagon across its basis axis-parallel sides in units - of cm. Assumed to be less than :math:`r_2\sqrt{2}`. + of cm. Must be less than :math:`r_2\sqrt{2}`. r2 : float Half-width of octagon across its basis axis intersecting sides in - units of cm. Assumed to be less than :math:`r_1\sqrt{2}`. + units of cm. Must be less than than :math:`r_1\sqrt{2}`. axis : {'x', 'y', 'z'} Central axis of octagon. Defaults to 'z' **kwargs @@ -122,11 +121,11 @@ class IsogonalOctagon(CompositeSurface): # Side lengths if r2 > r1 * sqrt(2): - warnings.warn(f'r2 is greater than sqrt(2) * r1. Octagon may' + \ - ' be erroneous.') + raise ValueError(f'r2 is greater than sqrt(2) * r1. Octagon' + \ + ' may be erroneous.') if r1 > r2 * sqrt(2): - warnings.warn(f'r1 is greater than sqrt(2) * r2. Octagon may' + \ - ' be erroneous.') + raise ValueError(f'r1 is greater than sqrt(2) * r2. Octagon' + \ + ' may be erroneous.') L_perp_ax1 = (r2 * sqrt(2) - r1) * 2 L_perp_ax2 = (r1 * sqrt(2) - r2) * 2 @@ -166,8 +165,6 @@ class IsogonalOctagon(CompositeSurface): for p in points: p[:] = p[coord_map] - #p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr = calibrated_points - self.upper_right = openmc.Plane.from_points(p1_ur, p2_ur, p3_ur, **kwargs) self.lower_right = openmc.Plane.from_points(p1_lr, p2_lr, p3_lr, From c1008a0d0fdc250b86b3906b50cdcb06c3643ade Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 5 Apr 2022 10:16:11 -0500 Subject: [PATCH 0186/2654] update unit test to match new basis for y case --- tests/unit_tests/test_surface_composite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 0668e82ac..3595c59e6 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -155,7 +155,7 @@ def test_cone_one_sided(axis, point_pos, point_neg, ll_true): @pytest.mark.parametrize( "axis, plane_tb, plane_lr, axis_idx", [ ("x", "Z", "Y", 0), - ("y", "Z", "X", 1), + ("y", "X", "Z", 1), ("z", "Y", "X", 2), ] ) From 5cbf23b48617c444b252bc54229fbdc5cbd7f17c Mon Sep 17 00:00:00 2001 From: yardasol <45364492+yardasol@users.noreply.github.com> Date: Tue, 5 Apr 2022 10:25:37 -0500 Subject: [PATCH 0187/2654] Remove unneeded attribute --- openmc/model/surface_composite.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 6ecdd3152..c61d3a3f9 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -109,7 +109,6 @@ class IsogonalOctagon(CompositeSurface): 'lower_right', 'upper_left') def __init__(self, center, r1, r2, axis='z', **kwargs): - self._axis = axis c1, c2 = center # Coords for axis-perpendicular planes From be6afdc3355bfa26ca3c093f3cab01842a14e7ea Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 5 Apr 2022 10:31:31 -0500 Subject: [PATCH 0188/2654] optimize implementation --- openmc/model/surface_composite.py | 178 ++++++++++++++---------------- 1 file changed, 84 insertions(+), 94 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index a7c8d173e..03595ff4b 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -53,6 +53,90 @@ class CompositeSurface(ABC): """Return the negative half-space of the composite surface.""" +class CylinderSector(CompositeSurface): + """Infinite cylindrical sector composite surface + + This class acts as a proper surface, meaning that unary `+` and `-` + operators applied to it will produce a half-space. The negative + side is defined to be the region inside of the cylinder sector. + + Parameters + ---------- + center : iterable of float + Coordinate for central axes of cylinders in the (y, z), (z, x), or + (x, y) basis. Defaults to (0,0) + r1, r2 : float + Inner and outer cylinder radii + theta0 : float + Angular offset of the sector in degrees relative to the primary basis + axis (+y, +z, or +x). + theta : float + Angular width of the sector in degrees. + axis : {'z', 'y', 'x'} + Central axis of the cylinders. Defaults to z + **kwargs + Keyword arguments passed to underlying plane classes + + Attributes + ---------- + outer : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder + Outer cylinder surface + inner : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder + Inner cylinder surface + plane0 : openmc.Plane + Plane at angle :math:`\theta_0` relative to the first basis axis + plane1 : openmc.Plane + Plane at angle :math:`\theta_0 + \theta` relative to the first + basis axis. + + """ + + _surface_names = ('outer_cyl','inner_cyl', + 'plane0', 'plane1') + + def __init__(self, center, r1, r2, theta0, theta, axis='z', **kwargs): + theta0 = pi / 180 * theta0 + theta = pi / 180 * theta + theta1 = theta0 + theta + + # Coords for axis-perpendicular planes + p1 = array([0.,0.,1.]) + + p2_plane0 = array([r1 * cos(theta0), r1 * sin(theta0), 0.]) + p3_plane0 = array([r2 * cos(theta0), r2 * sin(theta0), 0.]) + + p2_plane1 = array([r1 * cos(theta1), r1 * sin(theta1), 0.]) + p3_plane1 = array([r2 * cos(theta1), r2 * sin(theta1), 0.]) + + points = [p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1] + if axis == 'z': + coord_map = [0,1,2] + self.inner_cyl = openmc.ZCylinder(*center, r1, **kwargs) + self.outer_cyl = openmc.ZCylinder(*center, r2, **kwargs) + elif axis == 'y': + coord_map = [1,2,0] + self.inner_cyl = openmc.YCylinder(*center, r1, **kwargs) + self.outer_cyl = openmc.YCylinder(*center, r2, **kwargs) + elif axis == 'x': + coord_map = [2,0,1] + self.inner_cyl = openmc.XCylinder(*center, r1, **kwargs) + self.outer_cyl = openmc.XCylinder(*center, r2, **kwargs) + + for p in points: + p[:] = p[coord_map] + + self.plane0 = openmc.Plane.from_points(p1, p2_plane0, p3_plane0, + **kwargs) + self.plane1 = openmc.Plane.from_points(p1, p2_plane1, p3_plane1, + **kwargs) + + def __neg__(self): + return -self.outer_cyl & +self.inner_cyl & -self.plane0 & +self.plane1 + + def __pos__(self): + return +self.outer_cyl | -self.inner_cyl | +self.plane0 | -self.plane1 + + class RightCircularCylinder(CompositeSurface): """Right circular cylinder composite surface @@ -167,100 +251,6 @@ class RectangularParallelepiped(CompositeSurface): def __pos__(self): return -self.xmin | +self.xmax | -self.ymin | +self.ymax | -self.zmin | +self.zmax -class CylinderSector(CompositeSurface): - """Infinite cylindrical sector composite surface - - This class acts as a proper surface, meaning that unary `+` and `-` - operators applied to it will produce a half-space. The negative - side is defined to be the region inside of the cylinder sector. - - Parameters - ---------- - center : iterable of float - Coordinate for central axes of cylinders in the (y, z), (x,z), or - (x, y) basis. Defaults to (0,0) - r1, r2 : float - Inner and outer cylinder radii - theta0 : float - Angular offset of the sector in degrees relative to the primary basis - axis (+y or +x). - theta : float - Angular width of the sector in degrees. - axis : {'z', 'y', 'x'} - Central axis of the cylinders. Defaults to z - **kwargs - Keyword arguments passed to underlying plane classes - - Attributes - ---------- - outer : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder - Outer cylinder surface - inner : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder - Inner cylinder surface - plane0 : openmc.Plane - Plane at angle :math:`\theta_0` relative to the first basis axis - plane1 : openmc.Plane - Plane at angle :math:`\theta_0 + \theta` relative to the first - basis axis. - - """ - - _surface_names = ('outer_cyl','inner_cyl', - 'plane0', 'plane1') - - def __init__(self, center, r1, r2, theta0, theta, axis='z', **kwargs): - - self._axis = axis - theta0 = pi / 180 * theta0 - theta = pi / 180 * theta - theta1 = theta0 + theta - - # Coords for axis-perpendicular planes - p1 = array([0.,0.,1.]) - - p2_plane0 = array([r1 * cos(theta0), r1 * sin(theta0), 0.]) - p3_plane0 = array([r2 * cos(theta0), r2 * sin(theta0), 0.]) - - p2_plane1 = array([r1 * cos(theta1), r1 * sin(theta1), 0.]) - p3_plane1 = array([r2 * cos(theta1), r2 * sin(theta1), 0.]) - - points = [p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1] - if axis == 'z': - coord_map = [0,1,2] - self.inner_cyl = openmc.ZCylinder(*center, r=r1, **kwargs) - self.outer_cyl = openmc.ZCylinder(*center, r=r2, **kwargs) - elif axis == 'y': - coord_map = [0,2,1] - self.inner_cyl = openmc.YCylinder(*center, r=r1, **kwargs) - self.outer_cyl = openmc.YCylinder(*center, r=r2, **kwargs) - elif axis == 'x': - coord_map = [2,0,1] - self.inner_cyl = openmc.XCylinder(*center, r=r1, **kwargs) - self.outer_cyl = openmc.XCylinder(*center, r=r2, **kwargs) - - calibrated_points = [] - for p in points: - calibrated_points += [p[coord_map]] - - p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1 = calibrated_points - - self.plane0 = openmc.Plane.from_points(p1, p2_plane0, p3_plane0, **kwargs) - self.plane1 = openmc.Plane.from_points(p1, p2_plane1, p3_plane1, **kwargs) - - - def __neg__(self): - if self._axis == 'y': - return -self.outer_cyl & +self.inner_cyl & +self.plane0 & -self.plane1 - else: - return -self.outer_cyl & +self.inner_cyl & -self.plane0 & +self.plane1 - - - def __pos__(self): - if self._axis == 'y': - return +self.outer_cyl | -self.inner_cyl | -self.plane0 | +self.plane1 - else: - return +self.outer_cyl | -self.inner_cyl | +self.plane0 | -self.plane1 - class XConeOneSided(CompositeSurface): """One-sided cone parallel the x-axis From 01850016c6154841951b9de25ac153c79f845cbc Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 5 Apr 2022 15:32:43 -0500 Subject: [PATCH 0189/2654] use find_package(mpi) instead of relying on compilers set --- CMakeLists.txt | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e972c4937..511ce66b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) project(openmc C CXX) # Set version numbers @@ -30,6 +30,7 @@ option(OPENMC_ENABLE_PROFILE "Compile with profiling flags" option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" OFF) option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) +option(OPENMC_USE_MPI "Enable MPI" OFF) #=============================================================================== # Set a default build configuration if not explicitly specified @@ -44,10 +45,9 @@ endif() # MPI for distributed-memory parallelism #=============================================================================== -set(MPI_ENABLED FALSE) -if(${CMAKE_CXX_COMPILER} MATCHES "(mpi[^/]*|CC)$") - message(STATUS "Detected MPI wrapper: ${CMAKE_CXX_COMPILER}") - set(MPI_ENABLED TRUE) +if(OPENMC_USE_MPI) + find_package(MPI REQUIRED) + include_directories(${MPI_CXX_INCLUDE_DIRS}) endif() #=============================================================================== @@ -108,7 +108,7 @@ endif() find_package(HDF5 REQUIRED COMPONENTS C HL) if(HDF5_IS_PARALLEL) - if(NOT MPI_ENABLED) + if(NOT OPENMC_USE_MPI) message(FATAL_ERROR "Parallel HDF5 was detected, but the detected compiler,\ ${CMAKE_CXX_COMPILER}, does not support MPI. An MPI-capable compiler must \ be used with parallel HDF5.") @@ -141,9 +141,15 @@ endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) +if(OPENMC_USE_MPI) + list(APPEND cxxflags ${MPI_CXX_COMPILE_FLAGS}) + list(APPEND ldflags ${MPI_CXX_LINK_FLAGS}) +endif() + if(OPENMC_ENABLE_PROFILE) list(APPEND cxxflags -g -fno-omit-frame-pointer) endif() + if(OPENMC_ENABLE_COVERAGE) list(APPEND cxxflags --coverage) list(APPEND ldflags --coverage) @@ -398,7 +404,7 @@ target_include_directories(libopenmc PRIVATE ${CMAKE_BINARY_DIR}/include) if (HDF5_IS_PARALLEL) target_compile_definitions(libopenmc PRIVATE -DPHDF5) endif() -if (MPI_ENABLED) +if (OPENMC_USE_MPI) target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) endif() @@ -440,6 +446,10 @@ if (PNG_FOUND) target_link_libraries(libopenmc PNG::PNG) endif() +if (OPENMC_USE_MPI) + target_link_libraries(libopenmc MPI::MPI_CXX) +endif() + #=============================================================================== # openmc executable #=============================================================================== From 447e9cf02da322f40478420aab9d65b8450cb09c Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 5 Apr 2022 15:56:10 -0500 Subject: [PATCH 0190/2654] updated ci with new mpi flags --- tools/ci/gha-install.py | 2 +- tools/ci/gha-install.sh | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index 4cc85671d..4c69ba70b 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -34,7 +34,7 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): # Use MPI wrappers when building in parallel if mpi: - os.environ['CXX'] = 'mpicxx' + cmake_cmd.append('-DOPENMC_USE_MPI=on') # Tell CMake to prefer parallel HDF5 if specified if phdf5: diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index aa40eb90b..52e71b693 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -32,7 +32,6 @@ fi if [[ $MPI == 'y' ]]; then pip install --no-binary=mpi4py mpi4py - export CC=mpicc export HDF5_MPI=ON export HDF5_DIR=/usr/lib/x86_64-linux-gnu/hdf5/mpich pip install --no-binary=h5py h5py From 837ccc73af47e433287e24ec7601d763fb6de001 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 5 Apr 2022 15:59:09 -0500 Subject: [PATCH 0191/2654] updated documentation with new compile flag for mpi --- docs/source/usersguide/install.rst | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 42258b086..d7173e8c0 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -387,20 +387,11 @@ Example of configuring for Debug mode: Compiling with MPI ++++++++++++++++++ -To compile with MPI, set the :envvar:`CXX` environment variable to the path to -the MPI C++ wrapper. For example, in a bash shell: +To compile with MPI, use the `-DOPENMC_USE_MPI=on` cmake flag. For example, in a bash shell: .. code-block:: sh - export CXX=mpicxx - cmake /path/to/openmc - -Note that in many shells, environment variables can be set for a single command, -i.e. - -.. code-block:: sh - - CXX=mpicxx cmake /path/to/openmc + cmake -DOPENMC_USE_MPI=on /path/to/openmc Selecting HDF5 Installation +++++++++++++++++++++++++++ From 40294834939750dd67d48cf1538c4c7700d13f63 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 5 Apr 2022 15:59:41 -0500 Subject: [PATCH 0192/2654] wording --- docs/source/usersguide/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index d7173e8c0..53c06ab0a 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -387,7 +387,7 @@ Example of configuring for Debug mode: Compiling with MPI ++++++++++++++++++ -To compile with MPI, use the `-DOPENMC_USE_MPI=on` cmake flag. For example, in a bash shell: +To compile with MPI, use the `-DOPENMC_USE_MPI=on` cmake option. For example, in a bash shell: .. code-block:: sh From 20a18398bffcabf273df6b0f3c9cb2a68926bdd9 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Tue, 5 Apr 2022 16:19:32 -0500 Subject: [PATCH 0193/2654] export cc=mpicc apparently necessary for h5py --- tools/ci/gha-install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index 52e71b693..aa40eb90b 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -32,6 +32,7 @@ fi if [[ $MPI == 'y' ]]; then pip install --no-binary=mpi4py mpi4py + export CC=mpicc export HDF5_MPI=ON export HDF5_DIR=/usr/lib/x86_64-linux-gnu/hdf5/mpich pip install --no-binary=h5py h5py From 4f6001d574903fe728afda1f0a7b1fc181056253 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 09:28:02 -0500 Subject: [PATCH 0194/2654] updated method for setting mpi for regression tests --- tests/regression_tests/cpp_driver/test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/cpp_driver/test.py b/tests/regression_tests/cpp_driver/test.py index 0726e4c6e..6870cfe7d 100644 --- a/tests/regression_tests/cpp_driver/test.py +++ b/tests/regression_tests/cpp_driver/test.py @@ -33,12 +33,14 @@ def cpp_driver(request): os.chdir(str(local_builddir)) if config['mpi']: - os.environ['CXX'] = 'mpicxx' + mpi_arg = "On" + else: + mpi_arg = "Off" try: print("Building driver") # Run cmake/make to build the shared libary - subprocess.run(['cmake', os.path.pardir], check=True) + subprocess.run(['cmake', os.path.pardir, '-DOPENMC_USE_MPI=' + mpi_arg], check=True) subprocess.run(['make'], check=True) os.chdir(os.path.pardir) From 4010b32cffe11e4cf20be99ca9edb7861f49de3a Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 09:32:38 -0500 Subject: [PATCH 0195/2654] update mpi setting in another regression test --- tests/regression_tests/external_moab/test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/external_moab/test.py b/tests/regression_tests/external_moab/test.py index caff6b5db..da55c735a 100644 --- a/tests/regression_tests/external_moab/test.py +++ b/tests/regression_tests/external_moab/test.py @@ -49,12 +49,14 @@ def cpp_driver(request): os.chdir(str(local_builddir)) if config['mpi']: - os.environ['CXX'] = 'mpicxx' + mpi_arg = "On" + else: + mpi_arg = "Off" try: print("Building driver") # Run cmake/make to build the shared libary - subprocess.run(['cmake', os.path.pardir], check=True) + subprocess.run(['cmake', os.path.pardir, '-DOPENMC_USE_MPI=' + mpi_arg], check=True) subprocess.run(['make'], check=True) os.chdir(os.path.pardir) From ac607a83f94e6bca761eb62f635440467bb739c6 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 09:33:49 -0500 Subject: [PATCH 0196/2654] updated more mpi instances in install documentation --- docs/source/usersguide/install.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 53c06ab0a..1cb00ae55 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -203,7 +203,7 @@ Prerequisites respectively. To link against a parallel HDF5 library, make sure to set the HDF5_PREFER_PARALLEL CMake option, e.g.:: - CXX=mpicxx.mpich cmake -DHDF5_PREFER_PARALLEL=on .. + cmake -DHDF5_PREFER_PARALLEL=on -DOPENMC_USE_MPI=on .. Note that the exact package names may vary depending on your particular distribution and version. @@ -263,7 +263,7 @@ Prerequisites installation should be specified as part of the ``CMAKE_PREFIX_PATH`` variable.:: - CXX=mpicxx cmake -DOPENMC_USE_LIBMESH=on -DCMAKE_PREFIX_PATH=/path/to/libmesh/installation + cmake -DOPENMC_USE_LIBMESH=on -DOPENMC_USE_MPI=on -DCMAKE_PREFIX_PATH=/path/to/libmesh/installation Note that libMesh is most commonly compiled with MPI support. If that is the case, then OpenMC should be compiled with MPI support as well. From 0c4488c52e0b6aca1ba6ef319a4055b62741e4aa Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 09:36:31 -0500 Subject: [PATCH 0197/2654] update mpi setting in dockerfile --- Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6a9b89009..755d9f2a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,8 +59,7 @@ ENV LIBMESH_INSTALL_DIR=$HOME/LIBMESH ENV NJOY_REPO='https://github.com/njoy/NJOY2016' # Setup environment variables for Docker image -ENV CC=/usr/bin/mpicc CXX=/usr/bin/mpicxx \ - LD_LIBRARY_PATH=${DAGMC_INSTALL_DIR}/lib:$LD_LIBRARY_PATH \ +ENV LD_LIBRARY_PATH=${DAGMC_INSTALL_DIR}/lib:$LD_LIBRARY_PATH \ OPENMC_CROSS_SECTIONS=/root/nndc_hdf5/cross_sections.xml \ OPENMC_ENDF_DATA=/root/endf-b-vii.1 \ DEBIAN_FRONTEND=noninteractive @@ -179,6 +178,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ && mkdir build && cd build ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ + -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on \ -DOPENMC_USE_DAGMC=on \ -DOPENMC_USE_LIBMESH=on \ @@ -186,18 +186,21 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ fi ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "off" ]; then \ cmake ../openmc \ + -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on \ -DOPENMC_USE_DAGMC=ON \ -DCMAKE_PREFIX_PATH=${DAGMC_INSTALL_DIR} ; \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ + -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on \ -DOPENMC_USE_LIBMESH=on \ -DCMAKE_PREFIX_PATH=${LIBMESH_INSTALL_DIR} ; \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "off" ]; then \ cmake ../openmc \ + -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on ; \ fi ; \ make 2>/dev/null -j${compile_cores} install \ From eedbfdc2b1e80e60dc524e0d3283c214f19943f1 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 13:29:34 -0500 Subject: [PATCH 0198/2654] removed unneeded lines --- CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 511ce66b0..d5018163f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,6 @@ endif() if(OPENMC_USE_MPI) find_package(MPI REQUIRED) - include_directories(${MPI_CXX_INCLUDE_DIRS}) endif() #=============================================================================== @@ -141,11 +140,6 @@ endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) -if(OPENMC_USE_MPI) - list(APPEND cxxflags ${MPI_CXX_COMPILE_FLAGS}) - list(APPEND ldflags ${MPI_CXX_LINK_FLAGS}) -endif() - if(OPENMC_ENABLE_PROFILE) list(APPEND cxxflags -g -fno-omit-frame-pointer) endif() From 3bcc45c9bd2f41e571728f8a7d39957d32b61fb1 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 13:29:48 -0500 Subject: [PATCH 0199/2654] find mpi in cmake config --- cmake/OpenMCConfig.cmake.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/OpenMCConfig.cmake.in b/cmake/OpenMCConfig.cmake.in index 8f7ae7193..3279e5ba8 100644 --- a/cmake/OpenMCConfig.cmake.in +++ b/cmake/OpenMCConfig.cmake.in @@ -21,3 +21,7 @@ find_package(PNG) if(NOT TARGET OpenMC::libopenmc) include("${OpenMC_CMAKE_DIR}/OpenMCTargets.cmake") endif() + +if(@OPENMC_USE_MPI@) + find_package(MPI REQUIRED) +endif() From 3ba511c0566e5e26ab83a2c5c60ea261b3bdaf2e Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 13:41:44 -0500 Subject: [PATCH 0200/2654] update mpi options --- docs/source/usersguide/install.rst | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 1cb00ae55..9a705b5fa 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -352,8 +352,12 @@ OPENMC_ENABLE_COVERAGE Compile and link code instrumented for coverage analysis. This is typically used in conjunction with gcov_. (Default: off) +OPENMC_USE_MPI + Turns on compiling with MPI (default: off). For further information on MPI options, + please see the `FindMPI.cmake documentation `_. + To set any of these options (e.g., turning on profiling), the following form -should be used: +should be used:ß .. code-block:: sh @@ -382,16 +386,7 @@ Example of configuring for Debug mode: .. code-block:: sh - cmake -DCMAKE_BUILD_TYPE=Debug /path/to/openmc - -Compiling with MPI -++++++++++++++++++ - -To compile with MPI, use the `-DOPENMC_USE_MPI=on` cmake option. For example, in a bash shell: - -.. code-block:: sh - - cmake -DOPENMC_USE_MPI=on /path/to/openmc + cmake -DCMAKE_BUILD_TYPE=Debug /path/to/openmcß Selecting HDF5 Installation +++++++++++++++++++++++++++ From f960553bedc3a82712474d1fa5b07b6f21017ea2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 13:53:32 -0500 Subject: [PATCH 0201/2654] mpi_args formatting Co-authored-by: Paul Romano --- tests/regression_tests/cpp_driver/test.py | 2 +- tests/regression_tests/external_moab/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/cpp_driver/test.py b/tests/regression_tests/cpp_driver/test.py index 6870cfe7d..95912b3f7 100644 --- a/tests/regression_tests/cpp_driver/test.py +++ b/tests/regression_tests/cpp_driver/test.py @@ -40,7 +40,7 @@ def cpp_driver(request): try: print("Building driver") # Run cmake/make to build the shared libary - subprocess.run(['cmake', os.path.pardir, '-DOPENMC_USE_MPI=' + mpi_arg], check=True) + subprocess.run(['cmake', os.path.pardir, f'-DOPENMC_USE_MPI={mpi_arg}'], check=True) subprocess.run(['make'], check=True) os.chdir(os.path.pardir) diff --git a/tests/regression_tests/external_moab/test.py b/tests/regression_tests/external_moab/test.py index da55c735a..47e3ef80e 100644 --- a/tests/regression_tests/external_moab/test.py +++ b/tests/regression_tests/external_moab/test.py @@ -56,7 +56,7 @@ def cpp_driver(request): try: print("Building driver") # Run cmake/make to build the shared libary - subprocess.run(['cmake', os.path.pardir, '-DOPENMC_USE_MPI=' + mpi_arg], check=True) + subprocess.run(['cmake', os.path.pardir, f'-DOPENMC_USE_MPI={mpi_arg}'], check=True) subprocess.run(['make'], check=True) os.chdir(os.path.pardir) From 6208b4077021415249c7bf56d8a01df4108661ae Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 14:09:47 -0500 Subject: [PATCH 0202/2654] fixing a typo because I mix up control and command keys on macs still --- docs/source/usersguide/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 9a705b5fa..3277fc6e4 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -386,7 +386,7 @@ Example of configuring for Debug mode: .. code-block:: sh - cmake -DCMAKE_BUILD_TYPE=Debug /path/to/openmcß + cmake -DCMAKE_BUILD_TYPE=Debug /path/to/openmc Selecting HDF5 Installation +++++++++++++++++++++++++++ From ec4f1b71b54fabf9373e6d8b4e7a0d2add087865 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Apr 2022 14:14:12 -0500 Subject: [PATCH 0203/2654] fixing a typo because I mix up control and command keys on macs still - again --- docs/source/usersguide/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 3277fc6e4..3e3f7754a 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -357,7 +357,7 @@ OPENMC_USE_MPI please see the `FindMPI.cmake documentation `_. To set any of these options (e.g., turning on profiling), the following form -should be used:ß +should be used: .. code-block:: sh From 60608ade3c89c295eeb97e258be143aaabb4a2fd Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 10:12:01 -0500 Subject: [PATCH 0204/2654] apply @paulromano's suggestions --- openmc/model/surface_composite.py | 21 ++++++++++----------- tests/unit_tests/test_surface_composite.py | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index c61d3a3f9..aef379d22 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from copy import copy from math import sqrt -from numpy import array +import numpy as np import openmc from openmc.checkvalue import check_greater_than, check_value @@ -88,9 +88,9 @@ class IsogonalOctagon(CompositeSurface): Top planar surface of octagon bottom : openmc.ZPlane, openmc.XPlane, or openmc.YPlane Bottom planar surface of octagon - right: openmc.YPlane, openmc.ZPlane, or openmc.XPlane + right : openmc.YPlane, openmc.ZPlane, or openmc.XPlane Right planar surface of octagon - left: openmc.YPlane, openmc.ZPlane, or openmc.XPlane + left : openmc.YPlane, openmc.ZPlane, or openmc.XPlane Left planar surface of octagon upper_right : openmc.Plane Upper right planar surface of octagon @@ -126,17 +126,16 @@ class IsogonalOctagon(CompositeSurface): raise ValueError(f'r1 is greater than sqrt(2) * r2. Octagon' + \ ' may be erroneous.') - L_perp_ax1 = (r2 * sqrt(2) - r1) * 2 - L_perp_ax2 = (r1 * sqrt(2) - r2) * 2 + L_perp_ax1 = (r2 * sqrt(2) - r1) # Coords for quadrant planes - p1_ur = array([L_perp_ax1/2, r1, 0.]) - p2_ur = array([r1, L_perp_ax1/2, 0.]) - p3_ur = array([r1, L_perp_ax1/2, 1.]) + p1_ur = np.array([L_perp_ax1, r1, 0.]) + p2_ur = np.array([r1, L_perp_ax1, 0.]) + p3_ur = np.array([r1, L_perp_ax1, 1.]) - p1_lr = array([r1, -L_perp_ax1/2, 0.]) - p2_lr = array([L_perp_ax1/2, -r1, 0.]) - p3_lr = array([L_perp_ax1/2, -r1, 1.]) + p1_lr = np.array([r1, -L_perp_ax1, 0.]) + p2_lr = np.array([L_perp_ax1, -r1, 0.]) + p3_lr = np.array([L_perp_ax1, -r1, 1.]) points = [p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr] diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 3595c59e6..20670efcd 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -191,10 +191,10 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): # Check bounding box center = np.insert(center, axis_idx, np.inf) - xmax,ymax,zmax = center + r1 + xmax, ymax, zmax = center + r1 coord_min = center - r1 coord_min[axis_idx] *= -1 - xmin,ymin,zmin = coord_min + xmin, ymin, zmin = coord_min ll, ur = (+s).bounding_box assert np.all(np.isinf(ll)) assert np.all(np.isinf(ur)) From 018296d463dc8d0da0d34e760181bdca270a4f90 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 10:16:03 -0500 Subject: [PATCH 0205/2654] added unit test for checking invalud r1,r2 combos --- tests/unit_tests/test_surface_composite.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 20670efcd..0b1943137 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -217,6 +217,12 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): assert ur_t == pytest.approx(ur + t) assert ll_t == pytest.approx(ll + t) + # Check invalid r1, r2 combinations + with pytest.raises(ValueError): + openmc.model.IsogonalOctagon(center, r1=1.0, r2=10.) + with pytest.rasies(ValueError): + openmc.model.IsogonalOctagon(center, r1=10., r2=1.) + # Make sure repr works repr(s) From 16b894ffd84dd7dd4b7195396f94d4eff21cadf5 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 10:16:16 -0500 Subject: [PATCH 0206/2654] rename internal variable --- openmc/model/surface_composite.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index aef379d22..a34ce98cc 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -126,16 +126,16 @@ class IsogonalOctagon(CompositeSurface): raise ValueError(f'r1 is greater than sqrt(2) * r2. Octagon' + \ ' may be erroneous.') - L_perp_ax1 = (r2 * sqrt(2) - r1) + L_basis_ax = (r2 * sqrt(2) - r1) # Coords for quadrant planes - p1_ur = np.array([L_perp_ax1, r1, 0.]) - p2_ur = np.array([r1, L_perp_ax1, 0.]) - p3_ur = np.array([r1, L_perp_ax1, 1.]) + p1_ur = np.array([L_basis_ax, r1, 0.]) + p2_ur = np.array([r1, L_basis_ax, 0.]) + p3_ur = np.array([r1, L_basis_ax, 1.]) - p1_lr = np.array([r1, -L_perp_ax1, 0.]) - p2_lr = np.array([L_perp_ax1, -r1, 0.]) - p3_lr = np.array([L_perp_ax1, -r1, 1.]) + p1_lr = np.array([r1, -L_basis_ax, 0.]) + p2_lr = np.array([L_basis_ax, -r1, 0.]) + p3_lr = np.array([L_basis_ax, -r1, 1.]) points = [p1_ur, p2_ur, p3_ur, p1_lr, p2_lr, p3_lr] From af579895dd5933dc42c07bbd2c025e233c6abd8d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 7 Apr 2022 10:55:33 -0500 Subject: [PATCH 0207/2654] Refactor K-M slope calculation --- openmc/data/kalbach_mann.py | 317 +++++---------------- tests/unit_tests/test_data_kalbach_mann.py | 63 +--- 2 files changed, 80 insertions(+), 300 deletions(-) diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index 11e3acf40..5c0423f30 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -13,70 +13,6 @@ from .data import EV_PER_MEV from .endf import get_list_record, get_tab2_record -# Kalbach-Mann constants as defined in ENDF-6 manual BNL-203218-2018-INRE, -# Revision 215, File 6 description for LAW=1 and LANG=2. -_C1 = 0.04 # [1/MeV] -_C2 = 1.8E-6 # [1/MeV^3] -_C3 = 6.7E-7 # [1/MeV^4] -_ET1 = 130. # [MeV] -_ET3 = 41. # [MeV] -_M_NEUTRON = 1. -_M_PROTON = 1. -_M_DEUTERON = 1. -_M_TRITON = None -_M_3HE = None -_M_ALPHA = 0. -_SM_NEUTRON = 1/2. -_SM_PROTON = 1. -_SM_DEUTERON = 1. -_SM_TRITON = 1. -_SM_3HE = 1. -_SM_ALPHA = 2. - -# Kalbach-Mann M coefficients -_TABULATED_PARTICLE_M = { - 1: _M_NEUTRON, - 1001: _M_PROTON, - 1002: _M_DEUTERON, - 1003: _M_TRITON, - 2003: _M_3HE, - 2004: _M_ALPHA -} - -# Kalbach-Mann m coefficients -_TABULATED_PARTICLE_SM = { - 1: _SM_NEUTRON, - 1001: _SM_PROTON, - 1002: _SM_DEUTERON, - 1003: _SM_TRITON, - 2003: _SM_3HE, - 2004: _SM_ALPHA -} - -# Breaking energy as defined in ENDF-6 manual BNL-203218-2018-INRE, -# Revision 215, Appendix H, Table 3. -_BREAKING_ENERGY_NEUTRON = 0. -_BREAKING_ENERGY_PROTON = 0. -_BREAKING_ENERGY_DEUTERON = 2.224566 # [MeV] -_BREAKING_ENERGY_TRITON = 8.481798 # [MeV] -_BREAKING_ENERGY_3HE = 7.718043 # [MeV] -_BREAKING_ENERGY_ALPHA = 28.29566 # [MeV] - -_TABULATED_BREAKING_ENERGY = { - 1: _BREAKING_ENERGY_NEUTRON, - 1001: _BREAKING_ENERGY_PROTON, - 1002: _BREAKING_ENERGY_DEUTERON, - 1003: _BREAKING_ENERGY_TRITON, - 2003: _BREAKING_ENERGY_3HE, - 2004: _BREAKING_ENERGY_ALPHA -} - -# Abundant IZA translation in merged library -_IZA_TRANSLATION = { - 6000: 6012, -} - - class AtomicRepresentation(EqualityMixin): """Atomic representation of an isotope or a particle. @@ -151,27 +87,6 @@ class AtomicRepresentation(EqualityMixin): def n(self): return self.a - self.z - @property - def breaking_energy(self): - breaking_energy = None - if self.iza in _TABULATED_BREAKING_ENERGY: - breaking_energy = _TABULATED_BREAKING_ENERGY[self.iza] - return breaking_energy - - @property - def M(self): - M = None - if self.iza in _TABULATED_PARTICLE_M: - M = _TABULATED_PARTICLE_M[self.iza] - return M - - @property - def m(self): - m = None - if self.iza in _TABULATED_PARTICLE_SM: - m = _TABULATED_PARTICLE_SM[self.iza] - return m - @property def iza(self): iza = self.z * 1000 + self.a @@ -234,16 +149,11 @@ class AtomicRepresentation(EqualityMixin): Atomic representation of the isotope/particle """ - if iza in _IZA_TRANSLATION.keys(): - iza = _IZA_TRANSLATION[iza] - - z = int(iza/1000) - a = np.mod(iza, 1000) - + z, a = divmod(iza, 1000) return cls(z, a) -def _calculate_separation_energy(compound, nucleus, particle): +def _separation_energy(compound, nucleus, particle): """Calculates the separation energy as defined in ENDF-6 manual BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 and LANG=2. This function can be used for the incident or emitted @@ -251,158 +161,56 @@ def _calculate_separation_energy(compound, nucleus, particle): Parameters ---------- - compound: AtomicRepresentation + compound : AtomicRepresentation Atomic representation of the compound (C) - nucleus: AtomicRepresentation + nucleus : AtomicRepresentation Atomic representation of the nucleus (A or B) - particle: AtomicRepresentation + particle : AtomicRepresentation Atomic representation of the particle (a or b) Returns ------- - separation_energy: float + separation_energy : float Separation energy in MeV """ - coef_1 = 15.68 * (compound.a - nucleus.a) - coef_2 = 28.07 * ((compound.n - compound.z)**2 / float(compound.a) - \ - (nucleus.n - nucleus.z)**2 / float(nucleus.a)) - coef_3 = 18.56 * (compound.a**(2./3.) - nucleus.a**(2./3.)) - coef_4 = 33.22 * ((compound.n - compound.z)**2 / float(compound.a)**(4./3.) - \ - (nucleus.n - nucleus.z)**2 / float(nucleus.a)**(4./3.)) - coef_5 = 0.717 * (compound.z**2 / float(compound.a)**(1./3.) - \ - nucleus.z**2 / float(nucleus.a)**(1./3.)) - coef_6 = 1.211 * (compound.z**2 / float(compound.a) - \ - nucleus.z**2 / float(nucleus.a)) + # Determine A, Z, and N for compound and nucleus + A_c = compound.a + Z_c = compound.z + N_c = compound.n + A_a = nucleus.a + Z_a = nucleus.z + N_a = nucleus.n - separation_energy = coef_1 - coef_2 - coef_3 + coef_4 \ - - coef_5 + coef_6 - particle.breaking_energy + # Determine breakup energy of incident particle (ENDF-6 Formats Manual, + # Appendix H, Table 3) + iza_to_breaking_energy = { + 1: 0.0, + 1001: 0.0, + 1002: 2.224566, + 1003: 8.481798, + 2003: 7.718043, + 2004: 28.29566 + } + I_b = iza_to_breaking_energy[particle.iza] - return separation_energy + # Eq. 4 in in doi:10.1103/PhysRevC.37.2350 or ENDF-6 Formats Manual section + # 6.2.3.2 + return ( + 15.68 * (A_c - A_a) - + 28.07 * ((N_c - Z_c)**2 / A_c - (N_a - Z_a)**2 / A_a) - + 18.56 * (A_c**(2./3.) - A_a**(2./3.)) + + 33.22 * ((N_c - Z_c)**2 / A_c**(4./3.) - (N_a - Z_a)**2 / A_a**(4./3.)) - + 0.717 * (Z_c**2 / A_c**(1./3.) - Z_a**2 / A_a**(1./3.)) + + 1.211 * (Z_c**2 / A_c - Z_a**2 / A_a) - + I_b + ) -def _return_entrance_channel_energy(e_p, awr_t, awr_p): - """Returns the entrance channel energy as defined in ENDF-6 manual - BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 - and LANG=2. - - Parameters - ---------- - e_p: float - Energy of the incident projectile in the laboratory system in eV - awr_t: float - Atomic weight ratio of the target - awr_p: float - Atomic weight ratio of the projectile - - Returns - ------- - epsilon_p: float - Entrance channel energy in eV - - """ - epsilon_p = e_p * awr_t / (awr_t + awr_p) - return epsilon_p - - -def _return_emission_channel_energy(e_e, awr_r, awr_e): - """Returns the emission channel energy as defined in ENDF-6 manual - BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 - and LANG=2. - - Parameters - ---------- - e_e: float - Energy of the emitted particle in the center of mass system in eV - awr_r: float - Atomic weight ratio of the residual nucleus - awr_e: float - Atomic weight ratio of the emitted particle - - Returns - ------- - epsilon_e: float - Emission channel energy in eV - - """ - epsilon_e = e_e * (awr_r + awr_e) / awr_r - return epsilon_e - - -def _calculate_kalbach_slope(energy_projectile, - energy_emitted, - projectile, - target, - compound, - emitted, - residual): - """Calculate the Kalbach slope for projectiles other than photons - as defined in ENDF-6 manual BNL-203218-2018-INRE, Revision 215, - File 6 description for LAW=1 and LANG=2. - - The entrance and emission channel energies are not calculated with - the AWR number, but approximated with the number of mass instead. - - Parameters - ---------- - energy_projectile: float - Energy of the projectile in the laboratory system in eV - energy_emitted: float - Energy of the emitted particle in the center of mass system in eV - projectile: AtomicRepresentation - Atomic representation of the projectile - target: AtomicRepresentation - Atomic representation of the target - compound: AtomicRepresentation - Atomic representation of the compound - emitted: AtomicRepresentation - Atomic representation of the emitted particle - residual: AtomicRepresentation - Atomic representation of the residual nucleus - - Returns - ------- - slope: float - Kalbach-Mann slope - - """ - epsilon_a = _return_entrance_channel_energy( - energy_projectile, - target.a, - projectile.a - ) / EV_PER_MEV - epsilon_b = _return_emission_channel_energy( - energy_emitted, - residual.a, - emitted.a - ) / EV_PER_MEV - - s_a = _calculate_separation_energy(compound, target, projectile) - s_b = _calculate_separation_energy(compound, residual, emitted) - - e_a = epsilon_a + s_a - e_b = epsilon_b + s_b - - r_1 = min(e_a, _ET1) - r_3 = min(e_a, _ET3) - - x_1 = r_1 * e_b / e_a - x_3 = r_3 * e_b / e_a - - slope = _C1 * x_1 \ - + _C2 * x_1**3 \ - + _C3 * projectile.M * emitted.m * x_3**4 - - return slope - - -def return_kalbach_slope(energy_projectile, - energy_emitted, - iza_projectile, - iza_emitted, - iza_target): +def kalbach_slope(energy_projectile, energy_emitted, iza_projectile, + iza_emitted, iza_target): """Returns Kalbach-Mann slope from calculations. - + The associated reaction is defined as: A + a -> C -> B + b @@ -456,21 +264,42 @@ def return_kalbach_slope(energy_projectile, "Developed and tested for neutron projectile only." ) + # Special handling of elemental carbon + if iza_emitted == 6000: + iza_emitted = 6012 + if iza_target == 6000: + iza_target = 6012 + projectile = AtomicRepresentation.from_iza(iza_projectile) emitted = AtomicRepresentation.from_iza(iza_emitted) target = AtomicRepresentation.from_iza(iza_target) compound = projectile + target residual = compound - emitted - slope = _calculate_kalbach_slope( - energy_projectile, - energy_emitted, - projectile, - target, - compound, - emitted, - residual - ) + # Calculate entrance and emission channel energy in MeV, defined in section + # 6.2.3.2 in the ENDF-6 Formats Manual + epsilon_a = energy_projectile * target.a / (target.a + projectile.a) / EV_PER_MEV + epsilon_b = energy_emitted * (residual.a + emitted.a) \ + / (residual.a * EV_PER_MEV) + + # Calculate separation energies using Eq. 4 in doi:10.1103/PhysRevC.37.2350 + # or ENDF-6 Formats Manual section 6.2.3.2 + s_a = _separation_energy(compound, target, projectile) + s_b = _separation_energy(compound, residual, emitted) + + # See Eq. 10 in doi:10.1103/PhysRevC.37.2350 or section 6.2.3.2 in the + # ENDF-6 Formats Manual + iza_to_M = {1: 1.0, 1001: 1.0, 1002: 1.0, 2004: 0.0} + iza_to_m = {1: 0.5, 1001: 1.0, 1002: 1.0, 1003: 1.0, 2003: 1.0, 2004: 2.0} + M = iza_to_M[projectile.iza] + m = iza_to_m[emitted.iza] + e_a = epsilon_a + s_a + e_b = epsilon_b + s_b + r_1 = min(e_a, 130.) + r_3 = min(e_a, 41.) + x_1 = r_1 * e_b / e_a + x_3 = r_3 * e_b / e_a + slope = 0.04 * x_1 + 1.8e-6 * x_1**3 + 6.7e-7 * M * m * x_3**4 return float("%7e" % slope) @@ -889,11 +718,11 @@ class KalbachMann(AngleEnergy): else: # TODO: retrieve IZA of the projectile iza_projectile = 1 - a_i = [return_kalbach_slope(energy_projectile=energy[i], - energy_emitted=e, - iza_projectile=iza_projectile, - iza_emitted=iza_emitted, - iza_target=iza_target) + a_i = [kalbach_slope(energy_projectile=energy[i], + energy_emitted=e, + iza_projectile=iza_projectile, + iza_emitted=iza_emitted, + iza_target=iza_target) for e in eout_i] calculated_slope.append(True) diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py index 99869808d..643fffcfc 100644 --- a/tests/unit_tests/test_data_kalbach_mann.py +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -7,14 +7,8 @@ import numpy as np from openmc.data import IncidentNeutron from openmc.data import AtomicRepresentation -from openmc.data.kalbach_mann import _BREAKING_ENERGY_TRITON -from openmc.data.kalbach_mann import _M_TRITON -from openmc.data.kalbach_mann import _SM_TRITON -from openmc.data.kalbach_mann import _calculate_separation_energy -from openmc.data.kalbach_mann import _return_emission_channel_energy -from openmc.data.kalbach_mann import _return_entrance_channel_energy -from openmc.data.kalbach_mann import _calculate_kalbach_slope -from openmc.data import return_kalbach_slope +from openmc.data.kalbach_mann import _separation_energy +from openmc.data import kalbach_slope from openmc.data import KalbachMann from . import needs_njoy @@ -61,9 +55,6 @@ def test_atomic_representation(neutron, triton, b10, c12, c13, na23): # Test instanciation from_iza assert b10 == AtomicRepresentation.from_iza(5010) - # Test instanciation from_iza using IZA translation - assert c12 == AtomicRepresentation.from_iza(6000) - # Test addition assert c13 + b10 == na23 @@ -75,18 +66,12 @@ def test_atomic_representation(neutron, triton, b10, c12, c13, na23): assert c13.a == 13 assert c13.z == 6 assert c13.n == 7 - assert c13.breaking_energy is None - assert c13.M is None - assert c13.m is None assert c13.iza == 6013 # Test properties when information for Kalbach-Mann are given assert triton.a == 3 assert triton.z == 1 assert triton.n == 2 - assert triton.breaking_energy == _BREAKING_ENERGY_TRITON - assert triton.M == _M_TRITON - assert triton.m == _SM_TRITON assert triton.iza == 1003 # Test instanciation errors @@ -102,50 +87,16 @@ def test_atomic_representation(neutron, triton, b10, c12, c13, na23): neutron - triton -def test__calculate_separation_energy(triton, b10, c13): +def test_separation_energy(triton, b10, c13): """Comparison to hand-calculations on a simple example.""" - assert _calculate_separation_energy( + assert _separation_energy( compound=c13, nucleus=b10, particle=triton ) == pytest.approx(18.6880713) -def test__return_entrance_channel_energy(): - """Comparison to hand-calculations on a simple example.""" - assert _return_entrance_channel_energy( - e_p=5.2, - awr_t=13.7, - awr_p=7.2 - ) == pytest.approx(3.4086124) - - -def test__return_emission_channel_energy(): - """Comparison to hand-calculations on a simple example.""" - assert _return_emission_channel_energy( - e_e=6.8, - awr_r=49.2, - awr_e=5.4 - ) == pytest.approx(7.5463415) - - -def test__calculate_kalbach_slope(neutron, triton, b10, c12, c13): - """Comparison to hand-calculations for n + c12 -> c13 -> triton + b10.""" - energy_projectile = 10.2 # [eV] - energy_emitted = 5.4 # [eV] - - assert _calculate_kalbach_slope( - energy_projectile=energy_projectile, - energy_emitted=energy_emitted, - projectile=neutron, - target=c12, - compound=c13, - emitted=triton, - residual=b10 - ) == pytest.approx(0.8409921475) - - -def test_return_kalbach_slope(): +def test_kalbach_slope(): """Comparison to hand-calculations for n + c12 -> c13 -> triton + b10.""" energy_projectile = 10.2 # [eV] energy_emitted = 5.4 # [eV] @@ -153,7 +104,7 @@ def test_return_kalbach_slope(): # Check that NotImplementedError is raised if the projectile is not # a neutron with pytest.raises(NotImplementedError): - return_kalbach_slope( + kalbach_slope( energy_projectile=energy_projectile, energy_emitted=energy_emitted, iza_projectile=1000, @@ -161,7 +112,7 @@ def test_return_kalbach_slope(): iza_target=6012 ) - assert return_kalbach_slope( + assert kalbach_slope( energy_projectile=energy_projectile, energy_emitted=energy_emitted, iza_projectile=1, From e7595c32015e73671a96a3b2cec6ab9b8ca1c491 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 7 Apr 2022 10:58:15 -0500 Subject: [PATCH 0208/2654] Don't throw away precision on K-M slope calculation --- openmc/data/kalbach_mann.py | 4 +--- tests/unit_tests/test_data_kalbach_mann.py | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index 5c0423f30..932deea87 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -299,9 +299,7 @@ def kalbach_slope(energy_projectile, energy_emitted, iza_projectile, r_3 = min(e_a, 41.) x_1 = r_1 * e_b / e_a x_3 = r_3 * e_b / e_a - slope = 0.04 * x_1 + 1.8e-6 * x_1**3 + 6.7e-7 * M * m * x_3**4 - - return float("%7e" % slope) + return 0.04 * x_1 + 1.8e-6 * x_1**3 + 6.7e-7 * M * m * x_3**4 class KalbachMann(AngleEnergy): diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py index 643fffcfc..27890dacd 100644 --- a/tests/unit_tests/test_data_kalbach_mann.py +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -173,7 +173,7 @@ def test_comparison_slope_hdf5(hdf5_filename, endf_type, endf_filename): np.testing.assert_array_almost_equal( endf_distribution.slope[i].y, hdf5_slope.y, - decimal=6 + decimal=5 ) @@ -227,5 +227,5 @@ def test_comparison_slope_njoy(endf_type, endf_filename): np.testing.assert_array_almost_equal( endf_distribution.slope[i].y, njoy_slope.y, - decimal=6 + decimal=5 ) From a8fd1ddf7144b657d7050eba01a4bd4255aed406 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 7 Apr 2022 11:11:51 -0500 Subject: [PATCH 0209/2654] Change iza --> za --- openmc/data/kalbach_mann.py | 119 +++++++++------------ tests/unit_tests/test_data_kalbach_mann.py | 20 ++-- 2 files changed, 61 insertions(+), 78 deletions(-) diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index 932deea87..8d1a5c2e1 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -18,36 +18,28 @@ class AtomicRepresentation(EqualityMixin): Parameters ---------- - z: int + z : int Number of protons (atomic number) - a: int + a : int Number of nucleons (mass number) Raises ------ - IOError: + IOError When the number of protons (z) declared is higher than the number of nucleons (a) Attributes ---------- - z: int + z : int Number of protons (atomic number) - a: int + a : int Number of nucleons (mass number) - n: int + n : int Number of neutrons - breaking_energy: float - Energy required to break the isotope or particle into their - constituent nucleons from tabulated values - M: float - Kalbach-Mann M coefficient - m: float - Kalbach-Mann m coefficient - iza: int - ZA identifier defined as: - iza = Z x 1000 + A, - where Z is the number of protons and A the number of nucleons + za : int + ZA identifier, 1000*Z + A, where Z is the atomic number and A the mass + number """ def __init__(self, z, a): @@ -88,9 +80,8 @@ class AtomicRepresentation(EqualityMixin): return self.a - self.z @property - def iza(self): - iza = self.z * 1000 + self.a - return iza + def za(self): + return self.z * 1000 + self.a @a.setter def a(self, an): @@ -112,9 +103,9 @@ class AtomicRepresentation(EqualityMixin): Parameters ---------- - z: int + z : int Number of protons (atomic number) - a: int + a : int Number of nucleons (mass number) Raises @@ -131,17 +122,14 @@ class AtomicRepresentation(EqualityMixin): ) @classmethod - def from_iza(cls, iza): + def from_za(cls, za): """Instantiates an AtomicRepresentation from a ZA identifier. - The ZA identifier is defined as: - iza = Z x 1000 + A, - where Z is the number of protons and A the number of nucleons. - Parameters ---------- - iza: int - ZA identifier + za : int + ZA identifier, 1000*Z + A, where Z is the atomic number and A the + mass number Returns ------- @@ -149,7 +137,7 @@ class AtomicRepresentation(EqualityMixin): Atomic representation of the isotope/particle """ - z, a = divmod(iza, 1000) + z, a = divmod(za, 1000) return cls(z, a) @@ -184,7 +172,7 @@ def _separation_energy(compound, nucleus, particle): # Determine breakup energy of incident particle (ENDF-6 Formats Manual, # Appendix H, Table 3) - iza_to_breaking_energy = { + za_to_breaking_energy = { 1: 0.0, 1001: 0.0, 1002: 2.224566, @@ -192,7 +180,7 @@ def _separation_energy(compound, nucleus, particle): 2003: 7.718043, 2004: 28.29566 } - I_b = iza_to_breaking_energy[particle.iza] + I_b = za_to_breaking_energy[particle.za] # Eq. 4 in in doi:10.1103/PhysRevC.37.2350 or ENDF-6 Formats Manual section # 6.2.3.2 @@ -207,8 +195,8 @@ def _separation_energy(compound, nucleus, particle): ) -def kalbach_slope(energy_projectile, energy_emitted, iza_projectile, - iza_emitted, iza_target): +def kalbach_slope(energy_projectile, energy_emitted, za_projectile, + za_emitted, za_target): """Returns Kalbach-Mann slope from calculations. The associated reaction is defined as: @@ -222,10 +210,6 @@ def kalbach_slope(energy_projectile, energy_emitted, iza_projectile, - B is the residual nucleus, - b is the emitted particle. - This function uses the concept of ZA identifier defined as: - iza = Z x 1000 + A, - where Z is the number of protons and A the number of nucleons. - The Kalbach-Mann slope calculation is done as defined in ENDF-6 manual BNL-203218-2018-INRE, Revision 215, File 6 description for LAW=1 and LANG=2. One exception to this, is that the entrance and emission channel @@ -234,45 +218,44 @@ def kalbach_slope(energy_projectile, energy_emitted, iza_projectile, Parameters ---------- - energy_projectile: float + energy_projectile : float Energy of the projectile in the laboratory system in eV - energy_emitted: float + energy_emitted : float Energy of the emitted particle in the center of mass system in eV - iza_projectile: int + za_projectile : int ZA identifier of the projectile - iza_emitted: int + za_emitted : int ZA identifier of the emitted particle - iza_target: int + za_target : int ZA identifier of the targeted nucleus Raises ------ - NotImplementedError: - When the ZA identifier of the projectile is not equal to 1 - (ie. other than a neutron). + NotImplementedError + When the projectile is not a neutron Returns ------- - slope: float + slope : float Kalbach-Mann slope given with the same format as ACE file. """ # TODO: develop for photons as projectile # TODO: test for other particles than neutron - if iza_projectile != 1: + if za_projectile != 1: raise NotImplementedError( "Developed and tested for neutron projectile only." ) # Special handling of elemental carbon - if iza_emitted == 6000: - iza_emitted = 6012 - if iza_target == 6000: - iza_target = 6012 + if za_emitted == 6000: + za_emitted = 6012 + if za_target == 6000: + za_target = 6012 - projectile = AtomicRepresentation.from_iza(iza_projectile) - emitted = AtomicRepresentation.from_iza(iza_emitted) - target = AtomicRepresentation.from_iza(iza_target) + projectile = AtomicRepresentation.from_za(za_projectile) + emitted = AtomicRepresentation.from_za(za_emitted) + target = AtomicRepresentation.from_za(za_target) compound = projectile + target residual = compound - emitted @@ -289,10 +272,10 @@ def kalbach_slope(energy_projectile, energy_emitted, iza_projectile, # See Eq. 10 in doi:10.1103/PhysRevC.37.2350 or section 6.2.3.2 in the # ENDF-6 Formats Manual - iza_to_M = {1: 1.0, 1001: 1.0, 1002: 1.0, 2004: 0.0} - iza_to_m = {1: 0.5, 1001: 1.0, 1002: 1.0, 1003: 1.0, 2003: 1.0, 2004: 2.0} - M = iza_to_M[projectile.iza] - m = iza_to_m[emitted.iza] + za_to_M = {1: 1.0, 1001: 1.0, 1002: 1.0, 2004: 0.0} + za_to_m = {1: 0.5, 1001: 1.0, 1002: 1.0, 1003: 1.0, 2003: 1.0, 2004: 2.0} + M = za_to_M[projectile.za] + m = za_to_m[emitted.za] e_a = epsilon_a + s_a e_b = epsilon_b + s_b r_1 = min(e_a, 130.) @@ -642,7 +625,7 @@ class KalbachMann(AngleEnergy): return cls(breakpoints, interpolation, energy, energy_out, km_r, km_a) @classmethod - def from_endf(cls, file_obj, iza_emitted, iza_target, projectile_mass): + def from_endf(cls, file_obj, za_emitted, za_target, projectile_mass): """Generate Kalbach-Mann distribution from an ENDF evaluation. If the projectile is a neutron, the slope is calculated when it is @@ -652,11 +635,11 @@ class KalbachMann(AngleEnergy): ---------- file_obj : file-like object ENDF file positioned at the start of the Kalbach-Mann distribution - iza_emitted : int + za_emitted : int ZA identifier of the emitted particle - iza_target : int + za_target : int ZA identifier of the target - projectile_mass: float + projectile_mass : float Mass of the projectile Warns @@ -714,13 +697,13 @@ class KalbachMann(AngleEnergy): calculated_slope.append(False) else: - # TODO: retrieve IZA of the projectile - iza_projectile = 1 + # TODO: retrieve ZA of the projectile + za_projectile = 1 a_i = [kalbach_slope(energy_projectile=energy[i], energy_emitted=e, - iza_projectile=iza_projectile, - iza_emitted=iza_emitted, - iza_target=iza_target) + za_projectile=za_projectile, + za_emitted=za_emitted, + za_target=za_target) for e in eout_i] calculated_slope.append(True) diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py index 27890dacd..36282f7c5 100644 --- a/tests/unit_tests/test_data_kalbach_mann.py +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -52,8 +52,8 @@ def na23(): def test_atomic_representation(neutron, triton, b10, c12, c13, na23): """Test the AtomicRepresentation class.""" - # Test instanciation from_iza - assert b10 == AtomicRepresentation.from_iza(5010) + # Test instantiation from_za + assert b10 == AtomicRepresentation.from_za(5010) # Test addition assert c13 + b10 == na23 @@ -66,13 +66,13 @@ def test_atomic_representation(neutron, triton, b10, c12, c13, na23): assert c13.a == 13 assert c13.z == 6 assert c13.n == 7 - assert c13.iza == 6013 + assert c13.za == 6013 # Test properties when information for Kalbach-Mann are given assert triton.a == 3 assert triton.z == 1 assert triton.n == 2 - assert triton.iza == 1003 + assert triton.za == 1003 # Test instanciation errors with pytest.raises(IOError): @@ -107,17 +107,17 @@ def test_kalbach_slope(): kalbach_slope( energy_projectile=energy_projectile, energy_emitted=energy_emitted, - iza_projectile=1000, - iza_emitted=1, - iza_target=6012 + za_projectile=1000, + za_emitted=1, + za_target=6012 ) assert kalbach_slope( energy_projectile=energy_projectile, energy_emitted=energy_emitted, - iza_projectile=1, - iza_emitted=1003, - iza_target=6012 + za_projectile=1, + za_emitted=1003, + za_target=6012 ) == pytest.approx(0.8409921475) From aa233c80ddcec7df01c4883c3e54f11465e9a4e3 Mon Sep 17 00:00:00 2001 From: yardasol <45364492+yardasol@users.noreply.github.com> Date: Thu, 7 Apr 2022 11:15:25 -0500 Subject: [PATCH 0210/2654] fix typo in new unit test --- tests/unit_tests/test_surface_composite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 0b1943137..14a7c8d3d 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -220,7 +220,7 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): # Check invalid r1, r2 combinations with pytest.raises(ValueError): openmc.model.IsogonalOctagon(center, r1=1.0, r2=10.) - with pytest.rasies(ValueError): + with pytest.raises(ValueError): openmc.model.IsogonalOctagon(center, r1=10., r2=1.) # Make sure repr works From e341c20822b2cdadde9960b420ad619fa30eb2c7 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 11:36:04 -0500 Subject: [PATCH 0211/2654] pep8, consistency changes --- openmc/model/surface_composite.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 03595ff4b..7106730a8 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from copy import copy from math import sqrt, pi, sin, cos -from numpy import array +import numpy as np import openmc from openmc.checkvalue import check_greater_than, check_value @@ -72,16 +72,16 @@ class CylinderSector(CompositeSurface): axis (+y, +z, or +x). theta : float Angular width of the sector in degrees. - axis : {'z', 'y', 'x'} - Central axis of the cylinders. Defaults to z + axis : {'x', 'y', 'z'} + Central axis of the cylinders. Defaults to 'z'. **kwargs - Keyword arguments passed to underlying plane classes + Keyword arguments passed to underlying plane classes. Attributes ---------- - outer : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder + outer_cyl : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder Outer cylinder surface - inner : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder + inner_cyl : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder Inner cylinder surface plane0 : openmc.Plane Plane at angle :math:`\theta_0` relative to the first basis axis @@ -100,7 +100,7 @@ class CylinderSector(CompositeSurface): theta1 = theta0 + theta # Coords for axis-perpendicular planes - p1 = array([0.,0.,1.]) + p1 = array([0., 0., 1.]) p2_plane0 = array([r1 * cos(theta0), r1 * sin(theta0), 0.]) p3_plane0 = array([r2 * cos(theta0), r2 * sin(theta0), 0.]) @@ -110,15 +110,15 @@ class CylinderSector(CompositeSurface): points = [p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1] if axis == 'z': - coord_map = [0,1,2] + coord_map = [0, 1, 2] self.inner_cyl = openmc.ZCylinder(*center, r1, **kwargs) self.outer_cyl = openmc.ZCylinder(*center, r2, **kwargs) elif axis == 'y': - coord_map = [1,2,0] + coord_map = [1, 2, 0] self.inner_cyl = openmc.YCylinder(*center, r1, **kwargs) self.outer_cyl = openmc.YCylinder(*center, r2, **kwargs) elif axis == 'x': - coord_map = [2,0,1] + coord_map = [2, 0, 1] self.inner_cyl = openmc.XCylinder(*center, r1, **kwargs) self.outer_cyl = openmc.XCylinder(*center, r2, **kwargs) From 3340673dc58363e68d36c4f293698f48254dfe1a Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 12:42:56 -0500 Subject: [PATCH 0212/2654] fix array syntax --- openmc/model/surface_composite.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 7106730a8..c82200128 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -100,13 +100,13 @@ class CylinderSector(CompositeSurface): theta1 = theta0 + theta # Coords for axis-perpendicular planes - p1 = array([0., 0., 1.]) + p1 = np.array([0., 0., 1.]) - p2_plane0 = array([r1 * cos(theta0), r1 * sin(theta0), 0.]) - p3_plane0 = array([r2 * cos(theta0), r2 * sin(theta0), 0.]) + p2_plane0 = np.array([r1 * cos(theta0), r1 * sin(theta0), 0.]) + p3_plane0 = np.array([r2 * cos(theta0), r2 * sin(theta0), 0.]) - p2_plane1 = array([r1 * cos(theta1), r1 * sin(theta1), 0.]) - p3_plane1 = array([r2 * cos(theta1), r2 * sin(theta1), 0.]) + p2_plane1 = np.array([r1 * cos(theta1), r1 * sin(theta1), 0.]) + p3_plane1 = np.array([r2 * cos(theta1), r2 * sin(theta1), 0.]) points = [p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1] if axis == 'z': From 751d09836c5d0710552073f265694e14c8599a32 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 7 Apr 2022 13:20:56 -0500 Subject: [PATCH 0213/2654] Make 'a' and 'z' properties read-only --- openmc/data/kalbach_mann.py | 52 ++++------------------ tests/unit_tests/test_data_kalbach_mann.py | 8 ++-- 2 files changed, 13 insertions(+), 47 deletions(-) diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index 8d1a5c2e1..4c6b89e41 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -43,11 +43,17 @@ class AtomicRepresentation(EqualityMixin): """ def __init__(self, z, a): - self._consistency_check(z, a) + # Sanity checks on values + cv.check_type('z', z, Integral) + cv.check_greater_than('z', z, 0, equality=True) + cv.check_type('a', a, Integral) + cv.check_greater_than('a', a, 0, equality=True) + if z > a: + raise ValueError(f"Number of protons ({z}) must be less than or " + f"equal to number of nucleons ({a}).") + self._z = z self._a = a - self.z = self._z - self.a = self._a def __add__(self, other): """Adds two AtomicRepresentations. @@ -67,12 +73,10 @@ class AtomicRepresentation(EqualityMixin): @property def a(self): - self._consistency_check(self._z, self._a) return self._a @property def z(self): - self._consistency_check(self._z, self._a) return self._z @property @@ -83,44 +87,6 @@ class AtomicRepresentation(EqualityMixin): def za(self): return self.z * 1000 + self.a - @a.setter - def a(self, an): - cv.check_type('a', an, Integral) - cv.check_greater_than('a', an, 0, equality=True) - self._consistency_check(self._z, an) - self._a = an - - @z.setter - def z(self, zn): - cv.check_type('z', zn, Integral) - cv.check_greater_than('z', zn, 0, equality=True) - self._consistency_check(zn, self._a) - self._z = zn - - @staticmethod - def _consistency_check(z, a): - """Simple consistency check. - - Parameters - ---------- - z : int - Number of protons (atomic number) - a : int - Number of nucleons (mass number) - - Raises - ------ - IOError: - When the number of protons (z) declared is higher than the number - of nucleons (a) - - """ - if z > a: - raise IOError( - "Number of protons (%i) incompatible with number of " - "nucleons (%i)" % (z, a) - ) - @classmethod def from_za(cls, za): """Instantiates an AtomicRepresentation from a ZA identifier. diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py index 36282f7c5..bd540addb 100644 --- a/tests/unit_tests/test_data_kalbach_mann.py +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -75,15 +75,15 @@ def test_atomic_representation(neutron, triton, b10, c12, c13, na23): assert triton.za == 1003 # Test instanciation errors - with pytest.raises(IOError): + with pytest.raises(ValueError): AtomicRepresentation(z=5, a=1) with pytest.raises(ValueError): AtomicRepresentation(z=-1, a=1) - with pytest.raises(IOError): + with pytest.raises(ValueError): AtomicRepresentation(z=5, a=0) - with pytest.raises(IOError): + with pytest.raises(ValueError): AtomicRepresentation(z=5, a=-2) - with pytest.raises(OSError): + with pytest.raises(ValueError): neutron - triton From e505032a4f2352d35aeb61e2b820fa2236367784 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 7 Apr 2022 13:23:12 -0500 Subject: [PATCH 0214/2654] Add punctuation on docstrings --- openmc/model/model.py | 2 +- openmc/universe.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 3c94548fc..52c52154e 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -405,7 +405,7 @@ class Model: will be created. remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when - exporting + exporting. .. versionadded:: 0.13.1 """ diff --git a/openmc/universe.py b/openmc/universe.py index 6604771cb..5b8c2bc8a 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -297,7 +297,7 @@ class Universe(UniverseBase): seed : int Seed for the random number generator openmc_exec : str - Path to OpenMC executable + Path to OpenMC executable. .. versionadded:: 0.13.1 **kwargs From d08f2afa1c3bbc0cb3019523d07eba69bae60c82 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 13:32:58 -0500 Subject: [PATCH 0215/2654] docstring typo fixes --- openmc/model/surface_composite.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index c82200128..ec4143912 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -65,8 +65,10 @@ class CylinderSector(CompositeSurface): center : iterable of float Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) basis. Defaults to (0,0) - r1, r2 : float - Inner and outer cylinder radii + r1 : float + Inner cylinder radii + r2 : float + Outer cylinder radii theta0 : float Angular offset of the sector in degrees relative to the primary basis axis (+y, +z, or +x). @@ -84,9 +86,9 @@ class CylinderSector(CompositeSurface): inner_cyl : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder Inner cylinder surface plane0 : openmc.Plane - Plane at angle :math:`\theta_0` relative to the first basis axis + Plane at angle :math:`\\theta_0` relative to the first basis axis plane1 : openmc.Plane - Plane at angle :math:`\theta_0 + \theta` relative to the first + Plane at angle :math:`\\theta_0 + \\theta` relative to the first basis axis. """ From 8e1880b01cb0039272eb063c9f82a501d3ee8d18 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 19:00:57 -0500 Subject: [PATCH 0216/2654] formatting fixes --- openmc/model/surface_composite.py | 9 ++++----- tests/unit_tests/test_surface_composite.py | 10 ++++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 70cdb33e1..e1696edce 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -58,10 +58,10 @@ class CylinderSector(CompositeSurface): This class acts as a proper surface, meaning that unary `+` and `-` operators applied to it will produce a half-space. The negative side is defined to be the region inside of the cylinder sector. - + Parameters ---------- - center : iterable of float + center : iterable of float Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) basis. Defaults to (0,0) r1 : float @@ -136,8 +136,8 @@ class CylinderSector(CompositeSurface): def __pos__(self): return +self.outer_cyl | -self.inner_cyl | +self.plane0 | -self.plane1 - - + + class IsogonalOctagon(CompositeSurface): """Infinite isogonal octagon composite surface @@ -155,7 +155,6 @@ class IsogonalOctagon(CompositeSurface): Parameters ---------- center : iterable of float - Coordinate for the central axis of the octagon in the (y, z), (z, x), or (x, y) basis. r1 : float diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index f7dbeca4e..6b9b6c7a5 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -171,7 +171,7 @@ def test_cylinder_sector(axis, indices): assert isinstance(s.inner_cyl, getattr(openmc, axis + "Cylinder")) assert isinstance(s.plane0, openmc.Plane) assert isinstance(s.plane1, openmc.Plane) - + # Make sure boundary condition propagates s.boundary_type = 'reflective' assert s.boundary_type == 'reflective' @@ -179,7 +179,7 @@ def test_cylinder_sector(axis, indices): assert s.inner_cyl.boundary_type == 'reflective' assert s.plane0.boundary_type == 'reflective' assert s.plane1.boundary_type == 'reflective' - + # Check bounding box ll, ur = (+s).bounding_box assert np.all(np.isinf(ll)) @@ -237,7 +237,7 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): assert isinstance(s.lower_right, openmc.Plane) assert isinstance(s.upper_left, openmc.Plane) assert isinstance(s.lower_left, openmc.Plane) - + # Make sure boundary condition propagates s.boundary_type = 'reflective' assert s.boundary_type == 'reflective' @@ -285,4 +285,6 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): openmc.model.IsogonalOctagon(center, r1=10., r2=1.) # Make sure repr works - repr(s) \ No newline at end of file + repr(s) + + From e53be38712630b684019469cafd25497716ece48 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Apr 2022 19:01:09 -0500 Subject: [PATCH 0217/2654] pep8 fixes --- openmc/model/surface_composite.py | 9 +++++---- tests/unit_tests/test_surface_composite.py | 5 ++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index e1696edce..e3ac7e345 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -6,6 +6,7 @@ import numpy as np import openmc from openmc.checkvalue import check_greater_than, check_value + class CompositeSurface(ABC): """Multiple primitive surfaces combined into a composite surface""" @@ -92,7 +93,7 @@ class CylinderSector(CompositeSurface): """ - _surface_names = ('outer_cyl','inner_cyl', + _surface_names = ('outer_cyl', 'inner_cyl', 'plane0', 'plane1') def __init__(self, center, r1, r2, theta0, theta, axis='z', **kwargs): @@ -132,7 +133,7 @@ class CylinderSector(CompositeSurface): **kwargs) def __neg__(self): - return -self.outer_cyl & +self.inner_cyl & -self.plane0 & +self.plane1 + return -self.outer_cyl & +self.inner_cyl & -self.plane0 & +self.plane1 def __pos__(self): return +self.outer_cyl | -self.inner_cyl | +self.plane0 | -self.plane1 @@ -206,10 +207,10 @@ class IsogonalOctagon(CompositeSurface): # Side lengths if r2 > r1 * sqrt(2): - raise ValueError(f'r2 is greater than sqrt(2) * r1. Octagon' + \ + raise ValueError(f'r2 is greater than sqrt(2) * r1. Octagon' + ' may be erroneous.') if r1 > r2 * sqrt(2): - raise ValueError(f'r1 is greater than sqrt(2) * r2. Octagon' + \ + raise ValueError(f'r1 is greater than sqrt(2) * r2. Octagon' + ' may be erroneous.') L_basis_ax = (r2 * sqrt(2) - r1) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 6b9b6c7a5..7985a2aae 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -12,7 +12,8 @@ def test_rectangular_parallelepiped(): ymax = ymin + uniform(0., 5.) zmin = uniform(-5., 5.) zmax = zmin + uniform(0., 5.) - s = openmc.model.RectangularParallelepiped(xmin, xmax, ymin, ymax, zmin, zmax) + s = openmc.model.RectangularParallelepiped( + xmin, xmax, ymin, ymax, zmin, zmax) assert isinstance(s.xmin, openmc.XPlane) assert isinstance(s.xmax, openmc.XPlane) assert isinstance(s.ymin, openmc.YPlane) @@ -286,5 +287,3 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): # Make sure repr works repr(s) - - From 827343c52b69e01263a782c0c4fca7227006f317 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 19 Apr 2022 06:51:02 -0500 Subject: [PATCH 0218/2654] Fix colors assignment in Universe.plot --- openmc/universe.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 5b8c2bc8a..f3f95aebb 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -337,7 +337,8 @@ class Universe(UniverseBase): plot.pixels = pixels plot.basis = basis plot.color_by = color_by - plot.colors = colors + if colors is not None: + plot.colors = colors model.plots.append(plot) # Run OpenMC in geometry plotting mode From be61af3c0456826f44b109d45e49846764bff48e Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Thu, 7 Apr 2022 15:34:10 +0100 Subject: [PATCH 0219/2654] Refactor dagmc initialisation into a function --- include/openmc/dagmc.h | 4 ++ src/dagmc.cpp | 92 ++++++++++++++++++++++-------------------- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 64bf4d209..887810fd3 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -22,6 +22,7 @@ void check_dagmc_root_univ(); #ifdef DAGMC #include "DagMC.hpp" +#include "dagmcmetadata.hpp" #include "openmc/cell.h" #include "openmc/particle.h" @@ -139,10 +140,13 @@ public: bool has_graveyard() const { return has_graveyard_; } private: + void init_dagmc(); + std::string filename_; //!< Name of the DAGMC file used to create this universe std::shared_ptr uwuw_; //!< Pointer to the UWUW instance for this universe + std::unique_ptr dmd_ptr; //! Pointer to DAGMC metadata object bool adjust_geometry_ids_; //!< Indicates whether or not to automatically //!< generate new cell and surface IDs for the //!< universe diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 9b894d3bb..5b6d17e37 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -12,7 +12,6 @@ #include "openmc/string_utils.h" #ifdef DAGMC -#include "dagmcmetadata.hpp" #include "uwuw.hpp" #endif #include @@ -89,7 +88,7 @@ DAGUniverse::DAGUniverse( void DAGUniverse::initialize() { geom_type() = GeometryType::DAG; - + // determine the next cell id int32_t next_cell_id = 0; for (const auto& c : model::cells) { @@ -108,45 +107,10 @@ void DAGUniverse::initialize() surf_idx_offset_ = model::surfaces.size(); next_surf_id++; - // create a new DAGMC instance - dagmc_instance_ = std::make_shared(); - - // --- Materials --- - - // read any UWUW materials from the file - read_uwuw_materials(); - - // check for uwuw material definitions - bool using_uwuw = uses_uwuw(); - - // notify user if UWUW materials are going to be used - if (using_uwuw) { - write_message("Found UWUW Materials in the DAGMC geometry file.", 6); - } - - // load the DAGMC geometry - filename_ = settings::path_input + filename_; - if (!file_exists(filename_)) { - fatal_error("Geometry DAGMC file '" + filename_ + "' does not exist!"); - } - moab::ErrorCode rval = dagmc_instance_->load_file(filename_.c_str()); - MB_CHK_ERR_CONT(rval); - - // initialize acceleration data structures - rval = dagmc_instance_->init_OBBTree(); - MB_CHK_ERR_CONT(rval); - - // parse model metadata - dagmcMetaData DMD(dagmc_instance_.get(), false, false); - DMD.load_property_data(); - - std::vector keywords {"temp"}; - std::map dum; - std::string delimiters = ":/"; - rval = dagmc_instance_->parse_properties(keywords, dum, delimiters.c_str()); - MB_CHK_ERR_CONT(rval); + init_dagmc(); // --- Cells (Volumes) --- + moab::ErrorCode rval; // initialize cell objects int n_cells = dagmc_instance_->num_entities(3); @@ -175,7 +139,7 @@ void DAGUniverse::initialize() // --- Materials --- // determine volume material assignment - std::string mat_str = DMD.get_volume_property("material", vol_handle); + std::string mat_str = dmd_ptr->get_volume_property("material", vol_handle); if (mat_str.empty()) { fatal_error(fmt::format("Volume {} has no material assignment.", c->id_)); @@ -191,9 +155,9 @@ void DAGUniverse::initialize() if (mat_str == "void" || mat_str == "vacuum" || mat_str == "graveyard") { c->material_.push_back(MATERIAL_VOID); } else { - if (using_uwuw) { + if (uses_uwuw()) { // lookup material in uwuw if present - std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle]; + std::string uwuw_mat = dmd_ptr->volume_material_property_data_eh[vol_handle]; if (uwuw_->material_library.count(uwuw_mat) != 0) { // Note: material numbers are set by UWUW int mat_number = uwuw_->material_library.get_material(uwuw_mat) @@ -256,7 +220,7 @@ void DAGUniverse::initialize() : dagmc_instance_->id_by_index(2, i + 1); // set BCs - std::string bc_value = DMD.get_surface_property("boundary", surf_handle); + std::string bc_value = dmd_ptr->get_surface_property("boundary", surf_handle); to_lower(bc_value); if (bc_value.empty() || bc_value == "transmit" || bc_value == "transmission") { @@ -302,6 +266,48 @@ void DAGUniverse::initialize() } // end surface loop } +void DAGUniverse::init_dagmc() +{ + + // create a new DAGMC instance + dagmc_instance_ = std::make_shared(); + + // --- Materials --- + + // read any UWUW materials from the file + read_uwuw_materials(); + + // check for uwuw material definitions + bool using_uwuw = uses_uwuw(); + + // notify user if UWUW materials are going to be used + if (using_uwuw) { + write_message("Found UWUW Materials in the DAGMC geometry file.", 6); + } + + // load the DAGMC geometry + filename_ = settings::path_input + filename_; + if (!file_exists(filename_)) { + fatal_error("Geometry DAGMC file '" + filename_ + "' does not exist!"); + } + moab::ErrorCode rval = dagmc_instance_->load_file(filename_.c_str()); + MB_CHK_ERR_CONT(rval); + + // initialize acceleration data structures + rval = dagmc_instance_->init_OBBTree(); + MB_CHK_ERR_CONT(rval); + + // parse model metadata + dmd_ptr = std::make_unique(dagmc_instance_.get(), false, false); + dmd_ptr->load_property_data(); + + std::vector keywords {"temp"}; + std::map dum; + std::string delimiters = ":/"; + rval = dagmc_instance_->parse_properties(keywords, dum, delimiters.c_str()); + MB_CHK_ERR_CONT(rval); +} + std::string DAGUniverse::dagmc_ids_for_dim(int dim) const { // generate a vector of ids From 290e2fba075eac057a0a1c07b00622e3c2e0ef12 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Thu, 7 Apr 2022 16:04:00 +0100 Subject: [PATCH 0220/2654] Refactor initialize of dagmc universe --- include/openmc/dagmc.h | 3 + src/dagmc.cpp | 128 ++++++++++++++++++++++------------------- 2 files changed, 73 insertions(+), 58 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 887810fd3..8b26b6224 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -141,6 +141,8 @@ public: private: void init_dagmc(); + void init_cells(); + void init_surfaces(); std::string filename_; //!< Name of the DAGMC file used to create this universe @@ -154,6 +156,7 @@ private: //!< generate new material IDs for the universe bool has_graveyard_; //!< Indicates if the DAGMC geometry has a "graveyard" //!< volume + moab::EntityHandle graveyard; //! MOAB index for graveyard }; //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 5b6d17e37..c28b0ec9a 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -88,7 +88,60 @@ DAGUniverse::DAGUniverse( void DAGUniverse::initialize() { geom_type() = GeometryType::DAG; - + + init_dagmc(); + + init_cells(); + + init_surfaces(); +} + +void DAGUniverse::init_dagmc() +{ + + // create a new DAGMC instance + dagmc_instance_ = std::make_shared(); + + // --- Materials --- + + // read any UWUW materials from the file + read_uwuw_materials(); + + // check for uwuw material definitions + bool using_uwuw = uses_uwuw(); + + // notify user if UWUW materials are going to be used + if (using_uwuw) { + write_message("Found UWUW Materials in the DAGMC geometry file.", 6); + } + + // load the DAGMC geometry + filename_ = settings::path_input + filename_; + if (!file_exists(filename_)) { + fatal_error("Geometry DAGMC file '" + filename_ + "' does not exist!"); + } + moab::ErrorCode rval = dagmc_instance_->load_file(filename_.c_str()); + MB_CHK_ERR_CONT(rval); + + // initialize acceleration data structures + rval = dagmc_instance_->init_OBBTree(); + MB_CHK_ERR_CONT(rval); + + // parse model metadata + dmd_ptr = std::make_unique(dagmc_instance_.get(), false, false); + dmd_ptr->load_property_data(); + + std::vector keywords {"temp"}; + std::map dum; + std::string delimiters = ":/"; + rval = dagmc_instance_->parse_properties(keywords, dum, delimiters.c_str()); + MB_CHK_ERR_CONT(rval); +} + +void DAGUniverse::init_cells() +{ + moab::ErrorCode rval; + // determine the next cell id int32_t next_cell_id = 0; for (const auto& c : model::cells) { @@ -98,23 +151,9 @@ void DAGUniverse::initialize() cell_idx_offset_ = model::cells.size(); next_cell_id++; - // determine the next surface id - int32_t next_surf_id = 0; - for (const auto& s : model::surfaces) { - if (s->id_ > next_surf_id) - next_surf_id = s->id_; - } - surf_idx_offset_ = model::surfaces.size(); - next_surf_id++; - - init_dagmc(); - - // --- Cells (Volumes) --- - moab::ErrorCode rval; - // initialize cell objects int n_cells = dagmc_instance_->num_entities(3); - moab::EntityHandle graveyard = 0; + graveyard = 0; for (int i = 0; i < n_cells; i++) { moab::EntityHandle vol_handle = dagmc_instance_->entity_by_index(3, i + 1); @@ -207,7 +246,20 @@ void DAGUniverse::initialize() has_graveyard_ = graveyard; - // --- Surfaces --- +} + +void DAGUniverse::init_surfaces() +{ + moab::ErrorCode rval; + + // determine the next surface id + int32_t next_surf_id = 0; + for (const auto& s : model::surfaces) { + if (s->id_ > next_surf_id) + next_surf_id = s->id_; + } + surf_idx_offset_ = model::surfaces.size(); + next_surf_id++; // initialize surface objects int n_surfaces = dagmc_instance_->num_entities(2); @@ -264,49 +316,9 @@ void DAGUniverse::initialize() model::surfaces.emplace_back(std::move(s)); } // end surface loop + } -void DAGUniverse::init_dagmc() -{ - - // create a new DAGMC instance - dagmc_instance_ = std::make_shared(); - - // --- Materials --- - - // read any UWUW materials from the file - read_uwuw_materials(); - - // check for uwuw material definitions - bool using_uwuw = uses_uwuw(); - - // notify user if UWUW materials are going to be used - if (using_uwuw) { - write_message("Found UWUW Materials in the DAGMC geometry file.", 6); - } - - // load the DAGMC geometry - filename_ = settings::path_input + filename_; - if (!file_exists(filename_)) { - fatal_error("Geometry DAGMC file '" + filename_ + "' does not exist!"); - } - moab::ErrorCode rval = dagmc_instance_->load_file(filename_.c_str()); - MB_CHK_ERR_CONT(rval); - - // initialize acceleration data structures - rval = dagmc_instance_->init_OBBTree(); - MB_CHK_ERR_CONT(rval); - - // parse model metadata - dmd_ptr = std::make_unique(dagmc_instance_.get(), false, false); - dmd_ptr->load_property_data(); - - std::vector keywords {"temp"}; - std::map dum; - std::string delimiters = ":/"; - rval = dagmc_instance_->parse_properties(keywords, dum, delimiters.c_str()); - MB_CHK_ERR_CONT(rval); -} std::string DAGUniverse::dagmc_ids_for_dim(int dim) const { From d3b4cb7fd3d40160b0ce6071e9c9bef380552fbc Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Fri, 8 Apr 2022 12:13:58 +0100 Subject: [PATCH 0221/2654] More refactoring in DAGUniverse --- include/openmc/dagmc.h | 9 +++++---- src/dagmc.cpp | 27 ++++++++++++--------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 8b26b6224..1fcbb04a0 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -140,9 +140,10 @@ public: bool has_graveyard() const { return has_graveyard_; } private: - void init_dagmc(); - void init_cells(); - void init_surfaces(); + void set_id(); //!< Deduce the universe id from model::universes + void init_dagmc(); //!< Create and initialise DAGMC pointer + void init_cells(); //!< Create cells from DAGMC volumes + void init_surfaces(); //!< Create surfaces from DAGMC surfaces std::string filename_; //!< Name of the DAGMC file used to create this universe @@ -156,7 +157,7 @@ private: //!< generate new material IDs for the universe bool has_graveyard_; //!< Indicates if the DAGMC geometry has a "graveyard" //!< volume - moab::EntityHandle graveyard; //! MOAB index for graveyard + moab::EntityHandle graveyard; //!< MOAB index for graveyard }; //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index c28b0ec9a..260f58ebb 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -70,6 +70,13 @@ DAGUniverse::DAGUniverse( const std::string& filename, bool auto_geom_ids, bool auto_mat_ids) : filename_(filename), adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) +{ + set_id(); + + initialize(); +} + +void DAGUniverse::set_id() { // determine the next universe id int32_t next_univ_id = 0; @@ -81,8 +88,6 @@ DAGUniverse::DAGUniverse( // set the universe id id_ = next_univ_id; - - initialize(); } void DAGUniverse::initialize() @@ -91,6 +96,8 @@ void DAGUniverse::initialize() init_dagmc(); + read_uwuw_materials(); + init_cells(); init_surfaces(); @@ -102,19 +109,6 @@ void DAGUniverse::init_dagmc() // create a new DAGMC instance dagmc_instance_ = std::make_shared(); - // --- Materials --- - - // read any UWUW materials from the file - read_uwuw_materials(); - - // check for uwuw material definitions - bool using_uwuw = uses_uwuw(); - - // notify user if UWUW materials are going to be used - if (using_uwuw) { - write_message("Found UWUW Materials in the DAGMC geometry file.", 6); - } - // load the DAGMC geometry filename_ = settings::path_input + filename_; if (!file_exists(filename_)) { @@ -514,6 +508,9 @@ void DAGUniverse::read_uwuw_materials() if (mat_lib.size() == 0) return; + // notify user if UWUW materials are going to be used + write_message("Found UWUW Materials in the DAGMC geometry file.", 6); + // if we're using automatic IDs, update the UWUW material metadata if (adjust_material_ids_) { for (auto& mat : uwuw_->material_library) { From 05577e6a2e174c621145951ff6b737c25ccbda83 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Fri, 8 Apr 2022 14:06:46 +0100 Subject: [PATCH 0222/2654] Add new DAGUniverse constructor from external DAGMC --- include/openmc/dagmc.h | 5 +++++ src/dagmc.cpp | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 1fcbb04a0..959ed7149 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -88,6 +88,11 @@ public: explicit DAGUniverse(const std::string& filename, bool auto_geom_ids = false, bool auto_mat_ids = false); + //! Alternative DAGMC universe constructor for external DAGMC + explicit DAGUniverse(std::shared_ptr external_dagmc_ptr, + bool auto_geom_ids = false, + bool auto_mat_ids = false); + //! Initialize the DAGMC accel. data structures, indices, material //! assignments, etc. void initialize(); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 260f58ebb..d3a34ca18 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -76,6 +76,14 @@ DAGUniverse::DAGUniverse( initialize(); } +DAGUniverse::DAGUniverse(std::shared_ptr external_dagmc_ptr, + bool auto_geom_ids, bool auto_mat_ids) + : dagmc_instance_(external_dagmc_ptr), filename_(""), + adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) +{ + set_id(); +} + void DAGUniverse::set_id() { // determine the next universe id From cc6c3ac9e69b82d120dd00cf56f23e87934e4bc5 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Wed, 13 Apr 2022 12:58:33 +0100 Subject: [PATCH 0223/2654] More refactoring of DAGMC universe metadata; allow external setting of material temperature and population of universes' cells --- include/openmc/cell.h | 3 +++ include/openmc/dagmc.h | 10 +++++++-- include/openmc/material.h | 3 +++ src/cell.cpp | 23 ++++++++++++-------- src/dagmc.cpp | 44 +++++++++++++++++++++------------------ 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index d975750a1..01f037586 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -300,5 +300,8 @@ struct CellInstanceHash { void read_cells(pugi::xml_node node); +//! Add cells to universes +void populate_universes(); + } // namespace openmc #endif // OPENMC_CELL_H diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 959ed7149..4b7a6c45d 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -90,6 +90,7 @@ public: //! Alternative DAGMC universe constructor for external DAGMC explicit DAGUniverse(std::shared_ptr external_dagmc_ptr, + const std::string& filename, bool auto_geom_ids = false, bool auto_mat_ids = false); @@ -97,6 +98,13 @@ public: //! assignments, etc. void initialize(); + //! When providing an external DAGMC instance, the user will need to call + //! these methods manually + void init_metadata(); //!< Create and initialise dagmcMetaData pointer + void init_uwuw(); //!< Create UWUW pointer + void init_cells(); //!< Create cells from DAGMC volumes + void init_surfaces(); //!< Create surfaces from DAGMC surfaces + //! Reads UWUW materials and returns an ID map void read_uwuw_materials(); //! Indicates whether or not UWUW materials are present @@ -147,8 +155,6 @@ public: private: void set_id(); //!< Deduce the universe id from model::universes void init_dagmc(); //!< Create and initialise DAGMC pointer - void init_cells(); //!< Create cells from DAGMC volumes - void init_surfaces(); //!< Create surfaces from DAGMC surfaces std::string filename_; //!< Name of the DAGMC file used to create this universe diff --git a/include/openmc/material.h b/include/openmc/material.h index 709d20573..b251a3ca8 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -113,6 +113,9 @@ public: //! \param[in] units Units of density void set_density(double density, gsl::cstring_span units); + //! Set temperature of the material + void set_temperature(double temperature) { temperature_ = temperature; }; + //! Get nuclides in material //! \return Indices into the global nuclides vector gsl::span nuclides() const diff --git a/src/cell.cpp b/src/cell.cpp index 28be2c2cf..f9786ce3e 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -846,6 +846,20 @@ void read_cells(pugi::xml_node node) read_dagmc_universes(node); + populate_universes(); + + // Allocate the cell overlap count if necessary. + if (settings::check_overlaps) { + model::overlap_check_count.resize(model::cells.size(), 0); + } + + if (model::cells.size() == 0) { + fatal_error("No cells were found in the geometry.xml file"); + } +} + +void populate_universes() +{ // Populate the Universe vector and map. for (int i = 0; i < model::cells.size(); i++) { int32_t uid = model::cells[i]->universe_; @@ -860,15 +874,6 @@ void read_cells(pugi::xml_node node) } } model::universes.shrink_to_fit(); - - // Allocate the cell overlap count if necessary. - if (settings::check_overlaps) { - model::overlap_check_count.resize(model::cells.size(), 0); - } - - if (model::cells.size() == 0) { - fatal_error("No cells were found in the geometry.xml file"); - } } //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index d3a34ca18..4c72779ce 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -77,8 +77,9 @@ DAGUniverse::DAGUniverse( } DAGUniverse::DAGUniverse(std::shared_ptr external_dagmc_ptr, + const std::string& filename, bool auto_geom_ids, bool auto_mat_ids) - : dagmc_instance_(external_dagmc_ptr), filename_(""), + : dagmc_instance_(external_dagmc_ptr), filename_(filename), adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) { set_id(); @@ -104,6 +105,10 @@ void DAGUniverse::initialize() init_dagmc(); + init_metadata(); + + init_uwuw(); + read_uwuw_materials(); init_cells(); @@ -128,7 +133,10 @@ void DAGUniverse::init_dagmc() // initialize acceleration data structures rval = dagmc_instance_->init_OBBTree(); MB_CHK_ERR_CONT(rval); +} +void DAGUniverse::init_metadata() +{ // parse model metadata dmd_ptr = std::make_unique(dagmc_instance_.get(), false, false); dmd_ptr->load_property_data(); @@ -136,6 +144,7 @@ void DAGUniverse::init_dagmc() std::vector keywords {"temp"}; std::map dum; std::string delimiters = ":/"; + moab::ErrorCode rval; rval = dagmc_instance_->parse_properties(keywords, dum, delimiters.c_str()); MB_CHK_ERR_CONT(rval); } @@ -502,38 +511,33 @@ void DAGUniverse::legacy_assign_material( } } +void DAGUniverse::init_uwuw() +{ + uwuw_ = std::make_shared(filename_.c_str()); +} + void DAGUniverse::read_uwuw_materials() { - - int32_t next_material_id = 0; - for (const auto& m : model::materials) { - next_material_id = std::max(m->id_, next_material_id); - } - next_material_id++; - - uwuw_ = std::make_shared(filename_.c_str()); - const auto& mat_lib = uwuw_->material_library; - if (mat_lib.size() == 0) + if (!uses_uwuw()) return; - // notify user if UWUW materials are going to be used + // Notify user if UWUW materials are going to be used write_message("Found UWUW Materials in the DAGMC geometry file.", 6); // if we're using automatic IDs, update the UWUW material metadata if (adjust_material_ids_) { + int32_t next_material_id = 0; + for (const auto& m : model::materials) { + next_material_id = std::max(m->id_, next_material_id); + } + next_material_id++; + for (auto& mat : uwuw_->material_library) { mat.second->metadata["mat_number"] = next_material_id++; } } - std::stringstream ss; - ss << "\n"; - ss << "\n"; - for (auto mat : mat_lib) { - ss << mat.second->openmc("atom"); - } - ss << ""; - std::string mat_xml_string = ss.str(); + std::string mat_xml_string = get_uwuw_materials_xml(); // create a pugi XML document from this string pugi::xml_document doc; From fb9c12bd14aff9c0d1b32ec6ab304658cdc382c1 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Thu, 14 Apr 2022 13:08:16 +0100 Subject: [PATCH 0224/2654] Add switch to disable uwuw in DAGUniverse with external DAG --- include/openmc/dagmc.h | 1 + src/dagmc.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 4b7a6c45d..4c4e7f8c4 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -161,6 +161,7 @@ private: std::shared_ptr uwuw_; //!< Pointer to the UWUW instance for this universe std::unique_ptr dmd_ptr; //! Pointer to DAGMC metadata object + bool uwuw_disabled; //!< Switch to disable UWUW materials bool adjust_geometry_ids_; //!< Indicates whether or not to automatically //!< generate new cell and surface IDs for the //!< universe diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 4c72779ce..061c04f87 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -83,6 +83,7 @@ DAGUniverse::DAGUniverse(std::shared_ptr external_dagmc_ptr, adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) { set_id(); + uwuw_disabled = (filename==""); } void DAGUniverse::set_id() @@ -102,6 +103,7 @@ void DAGUniverse::set_id() void DAGUniverse::initialize() { geom_type() = GeometryType::DAG; + uwuw_disabled = false; init_dagmc(); @@ -424,7 +426,8 @@ void DAGUniverse::to_hdf5(hid_t universes_group) const bool DAGUniverse::uses_uwuw() const { - return !uwuw_->material_library.empty(); + if (uwuw_disabled) return false; + else return !uwuw_->material_library.empty(); } std::string DAGUniverse::get_uwuw_materials_xml() const @@ -513,6 +516,7 @@ void DAGUniverse::legacy_assign_material( void DAGUniverse::init_uwuw() { + if (uwuw_disabled) return; uwuw_ = std::make_shared(filename_.c_str()); } From 5dd6da91c5ce40894877fc216d664838f77d5c33 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Tue, 19 Apr 2022 15:50:34 +0100 Subject: [PATCH 0225/2654] Only expose methods that are needed externally --- include/openmc/dagmc.h | 10 ++-------- src/dagmc.cpp | 33 ++++++++++++--------------------- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 4c4e7f8c4..2fa0919e5 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -98,13 +98,6 @@ public: //! assignments, etc. void initialize(); - //! When providing an external DAGMC instance, the user will need to call - //! these methods manually - void init_metadata(); //!< Create and initialise dagmcMetaData pointer - void init_uwuw(); //!< Create UWUW pointer - void init_cells(); //!< Create cells from DAGMC volumes - void init_surfaces(); //!< Create surfaces from DAGMC surfaces - //! Reads UWUW materials and returns an ID map void read_uwuw_materials(); //! Indicates whether or not UWUW materials are present @@ -155,6 +148,8 @@ public: private: void set_id(); //!< Deduce the universe id from model::universes void init_dagmc(); //!< Create and initialise DAGMC pointer + void init_metadata(); //!< Create and initialise dagmcMetaData pointer + void init_geometry(); //!< Create cells and surfaces from DAGMC entities std::string filename_; //!< Name of the DAGMC file used to create this universe @@ -169,7 +164,6 @@ private: //!< generate new material IDs for the universe bool has_graveyard_; //!< Indicates if the DAGMC geometry has a "graveyard" //!< volume - moab::EntityHandle graveyard; //!< MOAB index for graveyard }; //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 061c04f87..2d0bab86e 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -83,7 +83,9 @@ DAGUniverse::DAGUniverse(std::shared_ptr external_dagmc_ptr, adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) { set_id(); - uwuw_disabled = (filename==""); + init_metadata(); + read_uwuw_materials(); + init_geometry(); } void DAGUniverse::set_id() @@ -103,19 +105,14 @@ void DAGUniverse::set_id() void DAGUniverse::initialize() { geom_type() = GeometryType::DAG; - uwuw_disabled = false; init_dagmc(); init_metadata(); - init_uwuw(); - read_uwuw_materials(); - init_cells(); - - init_surfaces(); + init_geometry(); } void DAGUniverse::init_dagmc() @@ -151,7 +148,7 @@ void DAGUniverse::init_metadata() MB_CHK_ERR_CONT(rval); } -void DAGUniverse::init_cells() +void DAGUniverse::init_geometry() { moab::ErrorCode rval; @@ -166,7 +163,7 @@ void DAGUniverse::init_cells() // initialize cell objects int n_cells = dagmc_instance_->num_entities(3); - graveyard = 0; + moab::EntityHandle graveyard = 0; for (int i = 0; i < n_cells; i++) { moab::EntityHandle vol_handle = dagmc_instance_->entity_by_index(3, i + 1); @@ -259,12 +256,6 @@ void DAGUniverse::init_cells() has_graveyard_ = graveyard; -} - -void DAGUniverse::init_surfaces() -{ - moab::ErrorCode rval; - // determine the next surface id int32_t next_surf_id = 0; for (const auto& s : model::surfaces) { @@ -514,14 +505,14 @@ void DAGUniverse::legacy_assign_material( } } -void DAGUniverse::init_uwuw() -{ - if (uwuw_disabled) return; - uwuw_ = std::make_shared(filename_.c_str()); -} - void DAGUniverse::read_uwuw_materials() { + // If no filename was provided, disable read UWUW materials + uwuw_disabled = (filename_==""); + + if (uwuw_disabled) return; + uwuw_ = std::make_shared(filename_.c_str()); + if (!uses_uwuw()) return; From 03ee3d6e779247b4afcca88473efc023086ca0b2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Apr 2022 09:53:50 -0500 Subject: [PATCH 0226/2654] Fix equations in docstrings for a few depletion integrations --- openmc/deplete/integrators.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/openmc/deplete/integrators.py b/openmc/deplete/integrators.py index 49d1d62d7..c19ef076a 100644 --- a/openmc/deplete/integrators.py +++ b/openmc/deplete/integrators.py @@ -124,13 +124,13 @@ class CF4Integrator(Integrator): .. math:: \begin{aligned} - \mathbf{A}_1 &= h\mathbf{A}(\mathbf{n}_0) \\ - \hat{\mathbf{n}}_1 &= \exp \left ( \frac{\mathbf{A}_1}{2} \right ) \\ + \mathbf{A}_1 &= h\mathbf{A}(\mathbf{n}_i) \\ + \hat{\mathbf{n}}_1 &= \exp \left ( \frac{\mathbf{A}_1}{2} \right ) \mathbf{n}_i \\ \mathbf{A}_2 &= h\mathbf{A}(\hat{\mathbf{n}}_1) \\ - \hat{\mathbf{n}}_2 &= \exp \left ( \frac{\mathbf{A}_2}{2} \right ) \\ + \hat{\mathbf{n}}_2 &= \exp \left ( \frac{\mathbf{A}_2}{2} \right ) \mathbf{n}_i \\ \mathbf{A}_3 &= h \mathbf{A}(\hat{\mathbf{n}}_2) \\ \hat{\mathbf{n}}_3 &= \exp \left ( -\frac{\mathbf{A}_1}{2} + \mathbf{A}_3 - \right ) \\ + \right ) \hat{\mathbf{n}}_1 \\ \mathbf{A}_4 &= h\mathbf{A}(\hat{\mathbf{n}}_3) \\ \mathbf{n}_{i+1} &= \exp \left ( \frac{\mathbf{A}_1}{4} + \frac{\mathbf{A}_2}{6} + \frac{\mathbf{A}_3}{6} - \frac{\mathbf{A}_4}{12} \right ) @@ -207,7 +207,8 @@ class CELIIntegrator(Integrator): .. math:: \begin{aligned} - \mathbf{n}_{i+1}^p &= \exp \left ( h \mathbf{A}(\mathbf{n}_i ) \right ) \\ + \mathbf{n}_{i+1}^p &= \exp \left ( h \mathbf{A}(\mathbf{n}_i ) \right ) + \mathbf{n}_i \\ \mathbf{n}_{i+1} &= \exp \left( \frac{h}{12} \mathbf{A}(\mathbf{n}_i) + \frac{5h}{12} \mathbf{A}(\mathbf{n}_{i+1}^p) \right) \exp \left( \frac{5h}{12} \mathbf{A}(\mathbf{n}_i) + @@ -268,12 +269,12 @@ class EPCRK4Integrator(Integrator): .. math:: \begin{aligned} - \mathbf{A}_1 &= h\mathbf{A}(\mathbf{n}_0) \\ - \hat{\mathbf{n}}_1 &= \exp \left ( \frac{\mathbf{A}_1}{2} \right ) \\ + \mathbf{A}_1 &= h\mathbf{A}(\mathbf{n}_i) \\ + \hat{\mathbf{n}}_1 &= \exp \left ( \frac{\mathbf{A}_1}{2} \right ) \mathbf{n}_i \\ \mathbf{A}_2 &= h\mathbf{A}(\hat{\mathbf{n}}_1) \\ - \hat{\mathbf{n}}_2 &= \exp \left ( \frac{\mathbf{A}_2}{2} \right ) \\ + \hat{\mathbf{n}}_2 &= \exp \left ( \frac{\mathbf{A}_2}{2} \right ) \mathbf{n}_i \\ \mathbf{A}_3 &= h \mathbf{A}(\hat{\mathbf{n}}_2) \\ - \hat{\mathbf{n}}_3 &= \exp \left ( \mathbf{A}_3 \right ) \\ + \hat{\mathbf{n}}_3 &= \exp \left ( \mathbf{A}_3 \right ) \mathbf{n}_i \\ \mathbf{A}_4 &= h\mathbf{A}(\hat{\mathbf{n}}_3) \\ \mathbf{n}_{i+1} &= \exp \left ( \frac{\mathbf{A}_1}{6} + \frac{\mathbf{A}_2}{3} + \frac{\mathbf{A}_3}{3} + \frac{\mathbf{A}_4}{6} \right ) \mathbf{n}_i. From 371f4746c20aefb920415669c5239be43d2adc54 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Apr 2022 14:31:40 -0500 Subject: [PATCH 0227/2654] Add minimal output to Integrator.integrate --- openmc/deplete/abc.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 3c7a13687..0d1e8ad41 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -851,7 +851,7 @@ class Integrator(ABC): return (self.operator.prev_res[-1].time[-1], len(self.operator.prev_res) - 1) - def integrate(self, final_step=True): + def integrate(self, final_step=True, output=True): """Perform the entire depletion process across all steps Parameters @@ -861,12 +861,18 @@ class Integrator(ABC): of the last timestep. .. versionadded:: 0.12.1 + output : bool, optional + Indicate whether to display information about progress + .. versionadded:: 0.13.1 """ with self.operator as conc: t, self._i_res = self._get_start_data() for i, (dt, source_rate) in enumerate(self): + if output: + print(f"[openmc.deplete] t={t} s, dt={dt} s, source={source_rate}") + # Solve transport equation (or obtain result from restart) if i > 0 or self.operator.prev_res is None: conc, res = self._get_bos_data_from_operator(i, source_rate, conc) @@ -892,6 +898,8 @@ class Integrator(ABC): # source rate is passed to the transport operator (which knows to # just return zero reaction rates without actually doing a transport # solve) + if output and final_step: + print(f"[openmc.deplete] t={t} (final operator evaluation)") res_list = [self.operator(conc, source_rate if final_step else 0.0)] Results.save(self.operator, [conc], res_list, [t, t], source_rate, self._i_res + len(self), proc_time) @@ -1004,12 +1012,23 @@ class SIIntegrator(Integrator): self.operator.settings.particles //= self.n_steps return inherited - def integrate(self): - """Perform the entire depletion process across all steps""" + def integrate(self, output=True): + """Perform the entire depletion process across all steps + + Parameters + ---------- + output : bool, optional + Indicate whether to display information about progress + + .. versionadded:: 0.13.1 + """ with self.operator as conc: t, self._i_res = self._get_start_data() for i, (dt, p) in enumerate(self): + if output: + print(f"[openmc.deplete] t={t} s, dt={dt} s, source={p}") + if i == 0: if self.operator.prev_res is None: conc, res = self._get_bos_data_from_operator(i, p, conc) From d95903783b76e27b9484456ee0a1f02e23b1d6db Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Apr 2022 14:32:29 -0500 Subject: [PATCH 0228/2654] Add get_atom_densities method in AtomNumber class --- openmc/deplete/atom_number.py | 63 ++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/openmc/deplete/atom_number.py b/openmc/deplete/atom_number.py index e4982f872..5430ddc35 100644 --- a/openmc/deplete/atom_number.py +++ b/openmc/deplete/atom_number.py @@ -6,6 +6,8 @@ from collections import OrderedDict import numpy as np +from openmc import Material + class AtomNumber: """Stores local material compositions (atoms of each nuclide). @@ -58,6 +60,12 @@ class AtomNumber: self.number = np.zeros((len(local_mats), len(nuclides))) + def _get_mat_index(self, mat): + """Helper method for getting material index""" + if isinstance(mat, Material): + mat = str(mat.id) + return self.index_mat[mat] if isinstance(mat, str) else mat + def __getitem__(self, pos): """Retrieves total atom number from AtomNumber. @@ -75,8 +83,7 @@ class AtomNumber: """ mat, nuc = pos - if isinstance(mat, str): - mat = self.index_mat[mat] + mat = self._get_mat_index(mat) if isinstance(nuc, str): nuc = self.index_nuc[nuc] @@ -96,8 +103,7 @@ class AtomNumber: """ mat, nuc = pos - if isinstance(mat, str): - mat = self.index_mat[mat] + mat = self._get_mat_index(mat) if isinstance(nuc, str): nuc = self.index_nuc[nuc] @@ -121,11 +127,11 @@ class AtomNumber: if ind < self.n_nuc_burn] def get_atom_density(self, mat, nuc): - """Accesses atom density instead of total number. + """Return atom density of given material and nuclide Parameters ---------- - mat : str, int or slice + mat : str, int, openmc.Material or slice Material index. nuc : str, int or slice Nuclide index. @@ -136,19 +142,43 @@ class AtomNumber: Density in [atom/cm^3] """ - if isinstance(mat, str): - mat = self.index_mat[mat] + mat = self._get_mat_index(mat) if isinstance(nuc, str): nuc = self.index_nuc[nuc] return self[mat, nuc] / self.volume[mat] + def get_atom_densities(self, mat, units='atom/b-cm'): + """Return atom densities for a given material + + Parameters + ---------- + mat : str, int, openmc.Material or slice + Material index. + units : {"atom/b-cm", "atom/cm3"}, optional + Units for the returned concentration. Default is ``"atom/b-cm"`` + + .. versionadded:: 0.13.1 + + Returns + ------- + dict + Dictionary mapping nuclides to atom densities + + """ + mat = self._get_mat_index(mat) + normalization = (1.0e-24 if units == 'atom/b-cm' else 1.0) / self.volume[mat] + return { + name: normalization * self[mat, nuc] + for name, nuc in self.index_nuc.items() + } + def set_atom_density(self, mat, nuc, val): """Sets atom density instead of total number. Parameters ---------- - mat : str, int or slice + mat : str, int, openmc.Material or slice Material index. nuc : str, int or slice Nuclide index. @@ -156,8 +186,7 @@ class AtomNumber: Array of densities to set in [atom/cm^3] """ - if isinstance(mat, str): - mat = self.index_mat[mat] + mat = self._get_mat_index(mat) if isinstance(nuc, str): nuc = self.index_nuc[nuc] @@ -168,7 +197,7 @@ class AtomNumber: Parameters ---------- - mat : str, int or slice + mat : str, int, openmc.Material or slice Material index. Returns @@ -177,9 +206,7 @@ class AtomNumber: The slice requested in [atom]. """ - if isinstance(mat, str): - mat = self.index_mat[mat] - + mat = self._get_mat_index(mat) return self[mat, :self.n_nuc_burn] def set_mat_slice(self, mat, val): @@ -187,15 +214,13 @@ class AtomNumber: Parameters ---------- - mat : str, int or slice + mat : str, int, openmc.Material, or slice Material index. val : numpy.ndarray The slice to set in [atom] """ - if isinstance(mat, str): - mat = self.index_mat[mat] - + mat = self._get_mat_index(mat) self[mat, :self.n_nuc_burn] = val def set_density(self, total_density): From 3024d6d55adeeb089af34af9b4cc2b705d11300e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Apr 2022 14:32:41 -0500 Subject: [PATCH 0229/2654] Add deplete.Nuclide.__repr__ method --- openmc/deplete/nuclide.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py index 992248246..d637edcfa 100644 --- a/openmc/deplete/nuclide.py +++ b/openmc/deplete/nuclide.py @@ -123,6 +123,11 @@ class Nuclide: # Neutron fission yields, if present self._yield_data = None + def __repr__(self): + return "".format( + self.name, self.n_decay_modes, self.n_reaction_paths + ) + @property def n_decay_modes(self): return len(self.decay_modes) From 4cc243b154ea721d6b1df7768104d8d15979f2ff Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Apr 2022 14:33:01 -0500 Subject: [PATCH 0230/2654] Make sure `diff_burnable_mats` updates materials appropriately --- openmc/deplete/operator.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index b5e377bed..337e8f8c0 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -84,11 +84,11 @@ class Operator(TransportOperator): .. versionchanged:: 0.13.0 The geometry and settings parameters have been replaced with a - model parameter that takes an openmc.Model object + model parameter that takes a :class:`~openmc.model.Model` object Parameters ---------- - model : openmc.Model + model : openmc.model.Model OpenMC model object chain_file : str, optional Path to the depletion chain XML file. Defaults to the file @@ -163,7 +163,7 @@ class Operator(TransportOperator): Attributes ---------- - model : openmc.Model + model : openmc.model.Model OpenMC model object geometry : openmc.Geometry OpenMC geometry object @@ -195,8 +195,6 @@ class Operator(TransportOperator): prev_res : ResultsList or None Results from a previous depletion calculation. ``None`` if no results are to be used. - diff_burnable_mats : bool - Whether to differentiate burnable materials with multiple instances cleanup_when_done : bool Whether to finalize and clear the shared library memory when the depletion operation is complete. Defaults to clearing the library. @@ -248,7 +246,6 @@ class Operator(TransportOperator): ) self.materials = model.materials - self.diff_burnable_mats = diff_burnable_mats self.cleanup_when_done = True # Reduce the chain before we create more materials @@ -262,8 +259,11 @@ class Operator(TransportOperator): self.chain = self.chain.reduce(all_isotopes, reduce_chain_level) # Differentiate burnable materials with multiple instances - if self.diff_burnable_mats: + if diff_burnable_mats: self._differentiate_burnable_mats() + self.materials = openmc.Materials( + model.geometry.get_all_materials().values() + ) # Clear out OpenMC, create task lists, distribute openmc.reset_auto_ids() From e8b9e85084adb8abefd4e17a1324e27cc98183d5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Apr 2022 14:33:18 -0500 Subject: [PATCH 0231/2654] Flush output from results --- src/output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/output.cpp b/src/output.cpp index 58f081f67..6565a9e67 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -545,7 +545,7 @@ void print_results() fmt::print(" Leakage Fraction = {:.5f}\n", gt(GlobalTally::LEAKAGE, TallyResult::SUM) / n); } - fmt::print("\n"); + std::cout << std::endl; } //============================================================================== From bd707de9200fe1af5ee420aa8b3f0a2356daeca6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 22 Apr 2022 07:17:10 -0500 Subject: [PATCH 0232/2654] Use f-string in deplete.Nuclide.__repr__ --- openmc/deplete/nuclide.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py index d637edcfa..7b6ddd788 100644 --- a/openmc/deplete/nuclide.py +++ b/openmc/deplete/nuclide.py @@ -124,9 +124,8 @@ class Nuclide: self._yield_data = None def __repr__(self): - return "".format( - self.name, self.n_decay_modes, self.n_reaction_paths - ) + n_modes, n_rx = self.n_decay_modes, self.n_reaction_paths + return f"" @property def n_decay_modes(self): From 2e326732abcb8f9df6c830416eb095396bbef647 Mon Sep 17 00:00:00 2001 From: April Novak Date: Mon, 25 Apr 2022 12:13:20 -0500 Subject: [PATCH 0233/2654] Allow control of C++ standard. Refs #2039 --- CMakeLists.txt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cf5ce6d8..28f917956 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,11 +454,9 @@ target_compile_options(openmc PRIVATE ${cxxflags}) target_include_directories(openmc PRIVATE ${CMAKE_BINARY_DIR}/include) target_link_libraries(openmc libopenmc) -# Ensure C++14 standard is used. Starting with CMake 3.8, another way this could -# be done is using the cxx_std_14 compiler feature. -set_target_properties( - openmc libopenmc - PROPERTIES CXX_STANDARD 14 CXX_EXTENSIONS OFF) +# Ensure C++14 standard is used +target_compile_features(openmc PUBLIC cxx_std_14) +target_compile_features(libopenmc PUBLIC cxx_std_14) #=============================================================================== # Python package From 575a678207712e04e940c89f89431da4cc02120a Mon Sep 17 00:00:00 2001 From: April Novak Date: Tue, 26 Apr 2022 11:06:28 -0500 Subject: [PATCH 0234/2654] Adjust C++ standard for Moab test. Refs #2039 --- tests/regression_tests/external_moab/test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/regression_tests/external_moab/test.py b/tests/regression_tests/external_moab/test.py index 47e3ef80e..b9d307239 100644 --- a/tests/regression_tests/external_moab/test.py +++ b/tests/regression_tests/external_moab/test.py @@ -37,8 +37,7 @@ def cpp_driver(request): add_executable(main main.cpp) find_package(OpenMC REQUIRED HINTS {}) target_link_libraries(main OpenMC::libopenmc) - set_target_properties(main PROPERTIES CXX_STANDARD - 14 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO) + target_compile_features(main PUBLIC cxx_std_14) set(CMAKE_CXX_FLAGS "-pedantic-errors") add_compile_definitions(DAGMC=1) """.format(openmc_dir))) From 3c2f0c03ffdce64c72b51202c089cc804b82df7b Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 26 Apr 2022 13:32:14 -0500 Subject: [PATCH 0235/2654] apply feedback from @paulromano: add checks for sector bounds; make variables less ambiguous --- openmc/model/surface_composite.py | 59 ++++++++++++---------- tests/unit_tests/test_surface_composite.py | 20 +++++--- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index e3ac7e345..7a6a50ba4 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -66,16 +66,18 @@ class CylinderSector(CompositeSurface): Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) basis. Defaults to (0,0) r1 : float - Inner cylinder radii + Inner radius of sector. Must be less than r2. r2 : float - Outer cylinder radii - theta0 : float - Angular offset of the sector in degrees relative to the primary basis - axis (+y, +z, or +x). - theta : float - Angular width of the sector in degrees. + Outer radius of sector. Must be greater than r1. + central_angle : float + Central angle, :math:`\\theta`, of the sector in degrees. Must be greater + that 0 and less than 360. + alpha : float + Angular offset of the clockwise-most side of the sector in degrees + relative to the primary basis axis (+y, +z, or +x). axis : {'x', 'y', 'z'} - Central axis of the cylinders. Defaults to 'z'. + Central axis of the cylinders defining the inner and outer surfaces + of the sector. Defaults to 'z'. **kwargs Keyword arguments passed to underlying plane classes. @@ -85,32 +87,37 @@ class CylinderSector(CompositeSurface): Outer cylinder surface inner_cyl : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder Inner cylinder surface - plane0 : openmc.Plane - Plane at angle :math:`\\theta_0` relative to the first basis axis plane1 : openmc.Plane - Plane at angle :math:`\\theta_0 + \\theta` relative to the first + Plane at angle :math:`\\phi_1 = \\alpha` relative to the first basis axis + plane2 : openmc.Plane + Plane at angle :math:`\\phi_2 = \\alpha + \\theta` relative to the first basis axis. """ - _surface_names = ('outer_cyl', 'inner_cyl', - 'plane0', 'plane1') + _surface_names = ('outer_cyl', 'inner_cyl', 'plane1', 'plane2') - def __init__(self, center, r1, r2, theta0, theta, axis='z', **kwargs): - theta0 = pi / 180 * theta0 - theta = pi / 180 * theta - theta1 = theta0 + theta + def __init__(self, center, r1, r2, central_angle, alpha, axis='z', **kwargs): + + if r2 <= r1 * sqrt(2): + raise ValueError(f'r2 must be greater than r1.') + + if central_angle >= 360. or central_angle <= 0: + raise ValueError(f'theta must be less than 360.') + + phi1 = pi / 180 * alpha + phi2 = pi / 180 * (alpha + central_angle) # Coords for axis-perpendicular planes p1 = np.array([0., 0., 1.]) - p2_plane0 = np.array([r1 * cos(theta0), r1 * sin(theta0), 0.]) - p3_plane0 = np.array([r2 * cos(theta0), r2 * sin(theta0), 0.]) + p2_plane1 = np.array([r1 * cos(phi1), r1 * sin(phi1), 0.]) + p3_plane1 = np.array([r2 * cos(phi1), r2 * sin(phi1), 0.]) - p2_plane1 = np.array([r1 * cos(theta1), r1 * sin(theta1), 0.]) - p3_plane1 = np.array([r2 * cos(theta1), r2 * sin(theta1), 0.]) + p2_plane2 = np.array([r1 * cos(phi2), r1 * sin(phi2), 0.]) + p3_plane2 = np.array([r2 * cos(phi2), r2 * sin(phi2), 0.]) - points = [p1, p2_plane0, p3_plane0, p2_plane1, p3_plane1] + points = [p1, p2_plane1, p3_plane1, p2_plane2, p3_plane2] if axis == 'z': coord_map = [0, 1, 2] self.inner_cyl = openmc.ZCylinder(*center, r1, **kwargs) @@ -127,16 +134,16 @@ class CylinderSector(CompositeSurface): for p in points: p[:] = p[coord_map] - self.plane0 = openmc.Plane.from_points(p1, p2_plane0, p3_plane0, - **kwargs) self.plane1 = openmc.Plane.from_points(p1, p2_plane1, p3_plane1, **kwargs) + self.plane2 = openmc.Plane.from_points(p1, p2_plane2, p3_plane2, + **kwargs) def __neg__(self): - return -self.outer_cyl & +self.inner_cyl & -self.plane0 & +self.plane1 + return -self.outer_cyl & +self.inner_cyl & -self.plane1 & +self.plane2 def __pos__(self): - return +self.outer_cyl | -self.inner_cyl | +self.plane0 | -self.plane1 + return +self.outer_cyl | -self.inner_cyl | +self.plane1 | -self.plane2 class IsogonalOctagon(CompositeSurface): diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 7985a2aae..00e51e6d9 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -164,22 +164,22 @@ def test_cylinder_sector(axis, indices): center = [0., 0.] r1, r2 = 0.5, 1.5 d = (r2 - r1) / 2 - theta0 = -60. - theta = 120. - s = openmc.model.CylinderSector(center, r1, r2, theta0, theta, + central_angle = 120. + alpha = -60. + s = openmc.model.CylinderSector(center, r1, r2, central_angle, alpha, axis=axis.lower()) assert isinstance(s.outer_cyl, getattr(openmc, axis + "Cylinder")) assert isinstance(s.inner_cyl, getattr(openmc, axis + "Cylinder")) - assert isinstance(s.plane0, openmc.Plane) assert isinstance(s.plane1, openmc.Plane) + assert isinstance(s.plane2, openmc.Plane) # Make sure boundary condition propagates s.boundary_type = 'reflective' assert s.boundary_type == 'reflective' assert s.outer_cyl.boundary_type == 'reflective' assert s.inner_cyl.boundary_type == 'reflective' - assert s.plane0.boundary_type == 'reflective' assert s.plane1.boundary_type == 'reflective' + assert s.plane2.boundary_type == 'reflective' # Check bounding box ll, ur = (+s).bounding_box @@ -193,7 +193,7 @@ def test_cylinder_sector(axis, indices): point_pos = np.roll([0, r2 + 1, 0], indices[0]) assert point_pos in +s assert point_pos not in -s - point_neg = np.roll([0, r1 + d/2, r1 + d/2], indices[0]) + point_neg = np.roll([0, r1 + d, r1 + d], indices[0]) assert point_neg in -s assert point_neg not in +s @@ -206,9 +206,13 @@ def test_cylinder_sector(axis, indices): # Check invalid r1, r2 combinations with pytest.raises(ValueError): - openmc.model.IsogonalOctagon(center, r1=1.0, r2=10.) + openmc.model.CylinderSector(center, 10., 1., central_angle, alpha) + + # Check invalid sector width with pytest.raises(ValueError): - openmc.model.IsogonalOctagon(center, r1=10., r2=1.) + openmc.model.CylinderSector(center, 1., 10., 360, alpha) + with pytest.raises(ValueError): + openmc.model.CylinderSector(center, 1., 10., -1, alpha) # Make sure repr works repr(s) From 020e0bd945ee9ac3a385c6ae02cf25239cbd7dae Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 26 Apr 2022 13:33:04 -0500 Subject: [PATCH 0236/2654] minor docstring addition --- openmc/model/surface_composite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 7a6a50ba4..3b4a1f42f 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -73,7 +73,7 @@ class CylinderSector(CompositeSurface): Central angle, :math:`\\theta`, of the sector in degrees. Must be greater that 0 and less than 360. alpha : float - Angular offset of the clockwise-most side of the sector in degrees + Angular offset, :math:`\\alpha`, of the clockwise-most side of the sector in degrees relative to the primary basis axis (+y, +z, or +x). axis : {'x', 'y', 'z'} Central axis of the cylinders defining the inner and outer surfaces From be97beb1c44ed4f46c175454a940a4e15a80f696 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 26 Apr 2022 13:41:50 -0500 Subject: [PATCH 0237/2654] make description of 'first basis axis' consistent' --- openmc/model/surface_composite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 3b4a1f42f..9a44d1955 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -74,7 +74,7 @@ class CylinderSector(CompositeSurface): that 0 and less than 360. alpha : float Angular offset, :math:`\\alpha`, of the clockwise-most side of the sector in degrees - relative to the primary basis axis (+y, +z, or +x). + relative to the first basis axis (+y, +z, or +x). axis : {'x', 'y', 'z'} Central axis of the cylinders defining the inner and outer surfaces of the sector. Defaults to 'z'. From 5abd01d4df7534b7be6aee8723791c6706afdd80 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 26 Apr 2022 13:49:21 -0500 Subject: [PATCH 0238/2654] add description of surfaces --- openmc/model/surface_composite.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 9a44d1955..c39439ed3 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -56,6 +56,10 @@ class CompositeSurface(ABC): class CylinderSector(CompositeSurface): """Infinite cylindrical sector composite surface + A cylinder sector is composed of two cylindrical and two planar surfaces. + The cylindrical surfaces are concentric, and the planar surfaces intersect + the central axis of the cylindrical surfaces. + This class acts as a proper surface, meaning that unary `+` and `-` operators applied to it will produce a half-space. The negative side is defined to be the region inside of the cylinder sector. From 09711e9672cbdd50682c20af8575da2db5e8c541 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 26 Apr 2022 14:05:47 -0500 Subject: [PATCH 0239/2654] alpha -> ccw_offset; consistency changes --- openmc/model/surface_composite.py | 25 +++++++++++++++------- tests/unit_tests/test_surface_composite.py | 10 ++++----- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index c39439ed3..5ad87d719 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -74,11 +74,13 @@ class CylinderSector(CompositeSurface): r2 : float Outer radius of sector. Must be greater than r1. central_angle : float - Central angle, :math:`\\theta`, of the sector in degrees. Must be greater - that 0 and less than 360. - alpha : float - Angular offset, :math:`\\alpha`, of the clockwise-most side of the sector in degrees - relative to the first basis axis (+y, +z, or +x). + Central angle, :math:`\\theta`, of the sector in degrees. Must be + greater that 0 and less than 360. + ccw_offset : float + Angular offset, :math:`\\alpha`, in the counter-clockwise direction + with respect to the first basis axis (+y, +z, or +x) of the + clockwise-most side of the sector in degrees. Note that negative values + translate to a clockwise offset. axis : {'x', 'y', 'z'} Central axis of the cylinders defining the inner and outer surfaces of the sector. Defaults to 'z'. @@ -101,7 +103,14 @@ class CylinderSector(CompositeSurface): _surface_names = ('outer_cyl', 'inner_cyl', 'plane1', 'plane2') - def __init__(self, center, r1, r2, central_angle, alpha, axis='z', **kwargs): + def __init__(self, + center, + r1, + r2, + central_angle, + ccw_offset, + axis='z', + **kwargs): if r2 <= r1 * sqrt(2): raise ValueError(f'r2 must be greater than r1.') @@ -109,8 +118,8 @@ class CylinderSector(CompositeSurface): if central_angle >= 360. or central_angle <= 0: raise ValueError(f'theta must be less than 360.') - phi1 = pi / 180 * alpha - phi2 = pi / 180 * (alpha + central_angle) + phi1 = pi / 180 * ccw_offset + phi2 = pi / 180 * (ccw_offset + central_angle) # Coords for axis-perpendicular planes p1 = np.array([0., 0., 1.]) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 00e51e6d9..458f11c60 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -165,8 +165,8 @@ def test_cylinder_sector(axis, indices): r1, r2 = 0.5, 1.5 d = (r2 - r1) / 2 central_angle = 120. - alpha = -60. - s = openmc.model.CylinderSector(center, r1, r2, central_angle, alpha, + ccw_offset = -60. + s = openmc.model.CylinderSector(center, r1, r2, central_angle, ccw_offset, axis=axis.lower()) assert isinstance(s.outer_cyl, getattr(openmc, axis + "Cylinder")) assert isinstance(s.inner_cyl, getattr(openmc, axis + "Cylinder")) @@ -206,13 +206,13 @@ def test_cylinder_sector(axis, indices): # Check invalid r1, r2 combinations with pytest.raises(ValueError): - openmc.model.CylinderSector(center, 10., 1., central_angle, alpha) + openmc.model.CylinderSector(center, 10., 1., central_angle, ccw_offset) # Check invalid sector width with pytest.raises(ValueError): - openmc.model.CylinderSector(center, 1., 10., 360, alpha) + openmc.model.CylinderSector(center, 1., 10., 360, ccw_offset) with pytest.raises(ValueError): - openmc.model.CylinderSector(center, 1., 10., -1, alpha) + openmc.model.CylinderSector(center, 1., 10., -1, ccw_offset) # Make sure repr works repr(s) From 3cb3f9e673bca24a95f3c35aab65a415e3ba0905 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 26 Apr 2022 14:26:11 -0500 Subject: [PATCH 0240/2654] clean up run-on sentence for ccw_offset; fix formatting in description for center --- openmc/model/surface_composite.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 5ad87d719..0f62c07ac 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -67,8 +67,8 @@ class CylinderSector(CompositeSurface): Parameters ---------- center : iterable of float - Coordinate for central axes of cylinders in the (y, z), (z, x), or - (x, y) basis. Defaults to (0,0) + Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) + basis. Defaults to (0,0) r1 : float Inner radius of sector. Must be less than r2. r2 : float @@ -77,13 +77,13 @@ class CylinderSector(CompositeSurface): Central angle, :math:`\\theta`, of the sector in degrees. Must be greater that 0 and less than 360. ccw_offset : float - Angular offset, :math:`\\alpha`, in the counter-clockwise direction - with respect to the first basis axis (+y, +z, or +x) of the - clockwise-most side of the sector in degrees. Note that negative values - translate to a clockwise offset. + Angular offset, :math:`\\alpha`, of the clockwise-most side of the + sector in degrees. The offset is in the counter-clockwise direction + with respect to the first basis axis (+y, +z, or +x). Note that + negative values translate to an offset in the clockwise direction. axis : {'x', 'y', 'z'} - Central axis of the cylinders defining the inner and outer surfaces - of the sector. Defaults to 'z'. + Central axis of the cylinders defining the inner and outer surfaces of + the sector. Defaults to 'z'. **kwargs Keyword arguments passed to underlying plane classes. From fc3809c2df6d5705b5167276a39dd0cd98faf199 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 26 Apr 2022 14:28:08 -0500 Subject: [PATCH 0241/2654] add periods --- openmc/model/surface_composite.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 0f62c07ac..af84670cf 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -54,7 +54,7 @@ class CompositeSurface(ABC): class CylinderSector(CompositeSurface): - """Infinite cylindrical sector composite surface + """Infinite cylindrical sector composite surface. A cylinder sector is composed of two cylindrical and two planar surfaces. The cylindrical surfaces are concentric, and the planar surfaces intersect @@ -68,7 +68,7 @@ class CylinderSector(CompositeSurface): ---------- center : iterable of float Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) - basis. Defaults to (0,0) + basis. Defaults to (0,0). r1 : float Inner radius of sector. Must be less than r2. r2 : float @@ -90,11 +90,11 @@ class CylinderSector(CompositeSurface): Attributes ---------- outer_cyl : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder - Outer cylinder surface + Outer cylinder surface. inner_cyl : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder - Inner cylinder surface + Inner cylinder surface. plane1 : openmc.Plane - Plane at angle :math:`\\phi_1 = \\alpha` relative to the first basis axis + Plane at angle :math:`\\phi_1 = \\alpha` relative to the first basis axis. plane2 : openmc.Plane Plane at angle :math:`\\phi_2 = \\alpha + \\theta` relative to the first basis axis. From f6858279123e7ed413df405f22e0cefb1274462c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 26 Apr 2022 16:41:49 -0500 Subject: [PATCH 0242/2654] Make AtomicRepresentation private (leading underscore) --- docs/source/pythonapi/data.rst | 3 +-- openmc/data/kalbach_mann.py | 26 +++++++++++----------- tests/unit_tests/test_data_kalbach_mann.py | 25 ++++++++++----------- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 471be43d8..a07fa9bc3 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -24,7 +24,6 @@ and product yields. FissionProductYields WindowedMultipole ProbabilityTables - AtomicRepresentation The following classes are used for storing atomic data (incident photon cross sections, atomic relaxation): @@ -65,11 +64,11 @@ Core Functions dose_coefficients gnd_name isotopes + kalbach_slope linearize thin water_density zam - return_kalbach_slope One-dimensional Functions ------------------------- diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index 4c6b89e41..10c002234 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -13,7 +13,7 @@ from .data import EV_PER_MEV from .endf import get_list_record, get_tab2_record -class AtomicRepresentation(EqualityMixin): +class _AtomicRepresentation(EqualityMixin): """Atomic representation of an isotope or a particle. Parameters @@ -56,20 +56,20 @@ class AtomicRepresentation(EqualityMixin): self._a = a def __add__(self, other): - """Adds two AtomicRepresentations. + """Adds two _AtomicRepresentations. """ z = self.z + other.z a = self.a + other.a - return AtomicRepresentation(z=z, a=a) + return _AtomicRepresentation(z=z, a=a) def __sub__(self, other): - """Substracts two AtomicRepresentations. + """Substracts two _AtomicRepresentations. """ z = self.z - other.z a = self.a - other.a - return AtomicRepresentation(z=z, a=a) + return _AtomicRepresentation(z=z, a=a) @property def a(self): @@ -89,7 +89,7 @@ class AtomicRepresentation(EqualityMixin): @classmethod def from_za(cls, za): - """Instantiates an AtomicRepresentation from a ZA identifier. + """Instantiate an _AtomicRepresentation from a ZA identifier. Parameters ---------- @@ -99,7 +99,7 @@ class AtomicRepresentation(EqualityMixin): Returns ------- - AtomicRepresentation + _AtomicRepresentation Atomic representation of the isotope/particle """ @@ -115,11 +115,11 @@ def _separation_energy(compound, nucleus, particle): Parameters ---------- - compound : AtomicRepresentation + compound : _AtomicRepresentation Atomic representation of the compound (C) - nucleus : AtomicRepresentation + nucleus : _AtomicRepresentation Atomic representation of the nucleus (A or B) - particle : AtomicRepresentation + particle : _AtomicRepresentation Atomic representation of the particle (a or b) Returns @@ -219,9 +219,9 @@ def kalbach_slope(energy_projectile, energy_emitted, za_projectile, if za_target == 6000: za_target = 6012 - projectile = AtomicRepresentation.from_za(za_projectile) - emitted = AtomicRepresentation.from_za(za_emitted) - target = AtomicRepresentation.from_za(za_target) + projectile = _AtomicRepresentation.from_za(za_projectile) + emitted = _AtomicRepresentation.from_za(za_emitted) + target = _AtomicRepresentation.from_za(za_target) compound = projectile + target residual = compound - emitted diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py index bd540addb..2a579b703 100644 --- a/tests/unit_tests/test_data_kalbach_mann.py +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -6,8 +6,7 @@ import pytest import numpy as np from openmc.data import IncidentNeutron -from openmc.data import AtomicRepresentation -from openmc.data.kalbach_mann import _separation_energy +from openmc.data.kalbach_mann import _separation_energy, _AtomicRepresentation from openmc.data import kalbach_slope from openmc.data import KalbachMann @@ -17,43 +16,43 @@ from . import needs_njoy @pytest.fixture(scope='module') def neutron(): """Neutron AtomicRepresentation.""" - return AtomicRepresentation(z=0, a=1) + return _AtomicRepresentation(z=0, a=1) @pytest.fixture(scope='module') def triton(): """Triton AtomicRepresentation.""" - return AtomicRepresentation(z=1, a=3) + return _AtomicRepresentation(z=1, a=3) @pytest.fixture(scope='module') def b10(): """B10 AtomicRepresentation.""" - return AtomicRepresentation(z=5, a=10) + return _AtomicRepresentation(z=5, a=10) @pytest.fixture(scope='module') def c12(): """C12 AtomicRepresentation.""" - return AtomicRepresentation(z=6, a=12) + return _AtomicRepresentation(z=6, a=12) @pytest.fixture(scope='module') def c13(): """C13 AtomicRepresentation.""" - return AtomicRepresentation(z=6, a=13) + return _AtomicRepresentation(z=6, a=13) @pytest.fixture(scope='module') def na23(): """Na23 AtomicRepresentation.""" - return AtomicRepresentation(z=11, a=23) + return _AtomicRepresentation(z=11, a=23) def test_atomic_representation(neutron, triton, b10, c12, c13, na23): """Test the AtomicRepresentation class.""" # Test instantiation from_za - assert b10 == AtomicRepresentation.from_za(5010) + assert b10 == _AtomicRepresentation.from_za(5010) # Test addition assert c13 + b10 == na23 @@ -76,13 +75,13 @@ def test_atomic_representation(neutron, triton, b10, c12, c13, na23): # Test instanciation errors with pytest.raises(ValueError): - AtomicRepresentation(z=5, a=1) + _AtomicRepresentation(z=5, a=1) with pytest.raises(ValueError): - AtomicRepresentation(z=-1, a=1) + _AtomicRepresentation(z=-1, a=1) with pytest.raises(ValueError): - AtomicRepresentation(z=5, a=0) + _AtomicRepresentation(z=5, a=0) with pytest.raises(ValueError): - AtomicRepresentation(z=5, a=-2) + _AtomicRepresentation(z=5, a=-2) with pytest.raises(ValueError): neutron - triton From 7ca7b1c7cffd2c7469fc2c869857f6c14bcc133a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 26 Apr 2022 16:53:17 -0500 Subject: [PATCH 0243/2654] Fix some docstrings --- openmc/data/kalbach_mann.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index 10c002234..02403b3cc 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -25,7 +25,7 @@ class _AtomicRepresentation(EqualityMixin): Raises ------ - IOError + ValueError When the number of protons (z) declared is higher than the number of nucleons (a) @@ -56,17 +56,13 @@ class _AtomicRepresentation(EqualityMixin): self._a = a def __add__(self, other): - """Adds two _AtomicRepresentations. - - """ + """Add two _AtomicRepresentations""" z = self.z + other.z a = self.a + other.a return _AtomicRepresentation(z=z, a=a) def __sub__(self, other): - """Substracts two _AtomicRepresentations. - - """ + """Substract two _AtomicRepresentations""" z = self.z - other.z a = self.a - other.a return _AtomicRepresentation(z=z, a=a) From cdc1bd02179f9df7379225cf80af801ed6d5c679 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 26 Apr 2022 17:00:11 -0500 Subject: [PATCH 0244/2654] Changes in njoy.py --- openmc/data/njoy.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openmc/data/njoy.py b/openmc/data/njoy.py index fbb26be05..70351a772 100644 --- a/openmc/data/njoy.py +++ b/openmc/data/njoy.py @@ -300,7 +300,7 @@ def make_ace(filename, temperatures=None, acer=True, xsdir=None, If the ENDF file contains multiple material evaluations, this argument indicates which evaluation should be used. smoothing : bool, optional - If the smoothing option in ACER is on (1) or off (0) in the card 6. + If the smoothing option (ACER card 6) is on (True) or off (False). **kwargs Keyword arguments passed to :func:`openmc.data.njoy.run` @@ -383,10 +383,7 @@ def make_ace(filename, temperatures=None, acer=True, xsdir=None, # acer if acer: - if smoothing is True: - ismoothing = 1 - else: - ismoothing = 0 + ismoothing = int(smoothing) nacer_in = nlast for i, temperature in enumerate(temperatures): # Extend input with an ACER run for each temperature From f4d0440d4f72e911ee59b82665de88336fef07f0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 26 Apr 2022 17:07:25 -0500 Subject: [PATCH 0245/2654] Remove KM slope NJOY test, other small changes --- tests/unit_tests/test_data_kalbach_mann.py | 80 ++++------------------ 1 file changed, 13 insertions(+), 67 deletions(-) diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py index 2a579b703..931e236bd 100644 --- a/tests/unit_tests/test_data_kalbach_mann.py +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -2,7 +2,9 @@ retrieved from ENDF files.""" import os +from pathlib import Path import pytest + import numpy as np from openmc.data import IncidentNeutron @@ -50,7 +52,7 @@ def na23(): def test_atomic_representation(neutron, triton, b10, c12, c13, na23): - """Test the AtomicRepresentation class.""" + """Test the _AtomicRepresentation class.""" # Test instantiation from_za assert b10 == _AtomicRepresentation.from_za(5010) @@ -121,10 +123,10 @@ def test_kalbach_slope(): @pytest.mark.parametrize( - "hdf5_filename, endf_type, endf_filename", [ - ('O16.h5', 'neutrons', 'n-008_O_016.endf'), - ('Ca46.h5', 'neutrons', 'n-020_Ca_046.endf'), - ('Hg204.h5', 'neutrons', 'n-080_Hg_204.endf') + "hdf5_filename, endf_filename", [ + ('O16.h5', 'n-008_O_016.endf'), + ('Ca46.h5', 'n-020_Ca_046.endf'), + ('Hg204.h5', 'n-080_Hg_204.endf') ] ) def test_comparison_slope_hdf5(hdf5_filename, endf_type, endf_filename): @@ -132,7 +134,7 @@ def test_comparison_slope_hdf5(hdf5_filename, endf_type, endf_filename): by comparing it to HDF5 data. The test is based on the first product of MT=5 (neutron). The isotopes tested have been selected because the corresponding products in ENDF/B-VII.1 are described using MF=6, LAW=1, - LANG=2 (ie. Kalbach-Mann systematics) and the slope is not given + LANG=2 (i.e., Kalbach-Mann systematics) and the slope is not given explicitly. If an error occurs during the "validity check", this means that @@ -145,15 +147,14 @@ def test_comparison_slope_hdf5(hdf5_filename, endf_type, endf_filename): """ # HDF5 data - hdf5_directory = os.path.dirname(os.environ['OPENMC_CROSS_SECTIONS']) - hdf5_path = os.path.join(hdf5_directory, hdf5_filename) - hdf5_data = IncidentNeutron.from_hdf5(hdf5_path) + hdf5_directory = Path(os.environ['OPENMC_CROSS_SECTIONS']).parent + hdf5_data = IncidentNeutron.from_hdf5(hdf5_directory / hdf5_filename) hdf5_product = hdf5_data[5].products[0] hdf5_distribution = hdf5_product.distribution[0] # ENDF data - endf_directory = os.environ['OPENMC_ENDF_DATA'] - endf_path = os.path.join(endf_directory, endf_type, endf_filename) + endf_directory = Path(os.environ['OPENMC_ENDF_DATA']) + endf_path = endf_directory / 'neutrons' / endf_filename endf_data = IncidentNeutron.from_endf(endf_path) endf_product = endf_data[5].products[0] endf_distribution = endf_product.distribution[0] @@ -166,65 +167,10 @@ def test_comparison_slope_hdf5(hdf5_filename, endf_type, endf_filename): # Results check for i, hdf5_slope in enumerate(hdf5_distribution.slope): - - assert endf_distribution._calculated_slope[i] is True + assert endf_distribution._calculated_slope[i] np.testing.assert_array_almost_equal( endf_distribution.slope[i].y, hdf5_slope.y, decimal=5 ) - - -@needs_njoy -@pytest.mark.parametrize( - "endf_type, endf_filename", [ - ('neutrons', 'n-008_O_016.endf'), - ('neutrons', 'n-020_Ca_046.endf'), - ('neutrons', 'n-080_Hg_204.endf') - ] -) -def test_comparison_slope_njoy(endf_type, endf_filename): - """Test the calculation of the Kalbach-Mann slope done by OpenMC - by comparing it to an NJOY calculation. The test is based on - the first product of MT=5 (neutron). The isotopes tested have - been selected because the corresponding products in ENDF/B-VII.1 - are described using MF=6, LAW=1, LANG=2 (ie. Kalbach-Mann - systematics) and the slope is not given explicitly. - - If an error occurs during the "validity check", this means that - the nuclear data evaluation has evolved and the distribution might - no longer be described using Kalbach-Mann systematics. Another - isotope needs to be identified and tested. - - """ - endf_directory = os.environ['OPENMC_ENDF_DATA'] - endf_path = os.path.join(endf_directory, endf_type, endf_filename) - - # ENDF data - endf_data = IncidentNeutron.from_endf(endf_path) - endf_product = endf_data[5].products[0] - endf_distribution = endf_product.distribution[0] - - # NJOY data - njoy_data = IncidentNeutron.from_njoy(endf_path, heatr=False, gaspr=False, - purr=False, smoothing=False) - njoy_product = njoy_data[5].products[0] - njoy_distribution = njoy_product.distribution[0] - - # Validity check - assert isinstance(endf_distribution, KalbachMann) - assert isinstance(njoy_distribution, KalbachMann) - assert endf_product.particle == njoy_product.particle - assert len(endf_distribution.slope) == len(njoy_distribution.slope) - - # Results check - for i, njoy_slope in enumerate(njoy_distribution.slope): - - assert endf_distribution._calculated_slope[i] is True - - np.testing.assert_array_almost_equal( - endf_distribution.slope[i].y, - njoy_slope.y, - decimal=5 - ) From e5016ac96355eb17d5b7c6c3421444ae5041a8f6 Mon Sep 17 00:00:00 2001 From: shimwell Date: Wed, 27 Apr 2022 15:48:07 +0100 Subject: [PATCH 0246/2654] added scale 44 group structure --- openmc/mgxs/__init__.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index 00b644050..386ae9fa8 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -13,10 +13,12 @@ GROUP_STRUCTURES = {} - "XMAS-172_" designed for LWR analysis ([SAR1990]_, [SAN2004]_) - "SHEM-361_" designed for LWR analysis to eliminate self-shielding calculations of thermal resonances ([HFA2005]_, [SAN2007]_, [HEB2008]_) +- "SCALE-44" designed for criticality analysis ([ZAL1999]_) - activation_ energy group structures "VITAMIN-J-42", "VITAMIN-J-175", "TRIPOLI-315", "CCFE-709_" and "UKAEA-1102_" .. _CASMO: https://www.studsvik.com/SharepointFiles/CASMO-5%20Development%20and%20Applications.pdf +.. _SCALE: https://www-nds.iaea.org/publications/indc/indc-czr-0001.pdf .. _XMAS-172: https://www-nds.iaea.org/wimsd/energy.htm .. _SHEM-361: https://www.polymtl.ca/merlin/downloads/FP214.pdf .. _activation: https://fispact.ukaea.uk/wiki/Keyword:GETXS @@ -41,6 +43,8 @@ GROUP_STRUCTURES = {} .. [HEB2008] Hébert, Alain & Santamarina, Alain. (2008). Refinement of the Santamarina-Hfaiedh energy mesh between 22.5 eV and 11.4 keV. International Conference on the Physics of Reactors 2008, PHYSOR 08. 2. 929-938. +.. [ZAL1999] K. Záleský and L. Marková (1999), Assessment of Nuclear Data Needs + for Broad-Group SCALE Library Related to VVER Spent Fuel Applications, IAEA. """ GROUP_STRUCTURES['CASMO-2'] = np.array([ @@ -67,7 +71,12 @@ GROUP_STRUCTURES['VITAMIN-J-42'] = np.array([ 0.2e6, 0.3e6, 0.4e6, 0.45e6, 0.51e6, 0.512e6, 0.6e6, 0.7e6, 0.8e6, 1.e6, 1.33e6, 1.34e6, 1.5e6, 1.66e6, 2.e6, 2.5e6, 3.e6, 3.5e6, 4.e6, 4.5e6, 5.e6, 5.5e6, 6.e6, 6.5e6, 7.e6, 7.5e6, 8.e6, 10.e6, 12.e6, 14.e6, 20.e6, 30.e6, - 50.e6]) + 50.e6]), +GROUP_STRUCTURES['SCALE-44'] = np.array([3.e-3, 7.5e-3, 1.e-2, 2.53e-2, 3.e-2, + 4.e-2, 5e-2, 7.e-2, 1.e-1, 1.5e-1, 2.e-1, 2.25e-1, 2.5e-1, 2.75e-1, + 3.25e-1, 3.5e-1, 3.75e-1, 4.e-1, 6.25e-1, 1., 1.77, 3., 4.75, 6., 8.1, + 1.e1, 3.e1, 1.e2, 5.5e2, 3.e3, 1.7e4, 2.5e4, 1.e5, 4.e5, 9.e5, 1.4e6, + 1.85e6, 2.354e6, 2.479e6, 3.e6, 4.8e6, 6.434e6, 8.1873e6, 2.e7]), GROUP_STRUCTURES['CASMO-70'] = np.array([ 0., 5.e-3, 1.e-2, 1.5e-2, 2.e-2, 2.5e-2, 3.e-2, 3.5e-2, 4.2e-2, 5.e-2, 5.8e-2, 6.7e-2, 8.e-2, 1.e-1, 1.4e-1, 1.8e-1, 2.2e-1, From 252ddc17b0dac598729483e7a8c17d32940b7c9a Mon Sep 17 00:00:00 2001 From: shimwell Date: Wed, 27 Apr 2022 17:30:38 +0100 Subject: [PATCH 0247/2654] trailing comma and lower bound fixes --- openmc/mgxs/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index 386ae9fa8..133b4c257 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -71,12 +71,12 @@ GROUP_STRUCTURES['VITAMIN-J-42'] = np.array([ 0.2e6, 0.3e6, 0.4e6, 0.45e6, 0.51e6, 0.512e6, 0.6e6, 0.7e6, 0.8e6, 1.e6, 1.33e6, 1.34e6, 1.5e6, 1.66e6, 2.e6, 2.5e6, 3.e6, 3.5e6, 4.e6, 4.5e6, 5.e6, 5.5e6, 6.e6, 6.5e6, 7.e6, 7.5e6, 8.e6, 10.e6, 12.e6, 14.e6, 20.e6, 30.e6, - 50.e6]), -GROUP_STRUCTURES['SCALE-44'] = np.array([3.e-3, 7.5e-3, 1.e-2, 2.53e-2, 3.e-2, - 4.e-2, 5e-2, 7.e-2, 1.e-1, 1.5e-1, 2.e-1, 2.25e-1, 2.5e-1, 2.75e-1, + 50.e6]) +GROUP_STRUCTURES['SCALE-44'] = np.array([1e-5, 3.e-3, 7.5e-3, 1.e-2, 2.53e-2, + 3.e-2, 4.e-2, 5e-2, 7.e-2, 1.e-1, 1.5e-1, 2.e-1, 2.25e-1, 2.5e-1, 2.75e-1, 3.25e-1, 3.5e-1, 3.75e-1, 4.e-1, 6.25e-1, 1., 1.77, 3., 4.75, 6., 8.1, 1.e1, 3.e1, 1.e2, 5.5e2, 3.e3, 1.7e4, 2.5e4, 1.e5, 4.e5, 9.e5, 1.4e6, - 1.85e6, 2.354e6, 2.479e6, 3.e6, 4.8e6, 6.434e6, 8.1873e6, 2.e7]), + 1.85e6, 2.354e6, 2.479e6, 3.e6, 4.8e6, 6.434e6, 8.1873e6, 2.e7]) GROUP_STRUCTURES['CASMO-70'] = np.array([ 0., 5.e-3, 1.e-2, 1.5e-2, 2.e-2, 2.5e-2, 3.e-2, 3.5e-2, 4.2e-2, 5.e-2, 5.8e-2, 6.7e-2, 8.e-2, 1.e-1, 1.4e-1, 1.8e-1, 2.2e-1, From 41e18a0893ea6ed96ef43c5da1f5fd6d5033d889 Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Wed, 27 Apr 2022 12:29:09 -0500 Subject: [PATCH 0248/2654] Making MGXS.print_xs (and inheriting classes) use hdf5_key for the printed reaction type when using print_xs as that is more descriptive --- openmc/mgxs/mdgxs.py | 4 ++-- openmc/mgxs/mgxs.py | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 13aa924a1..96c687cec 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -605,7 +605,7 @@ class MDGXS(MGXS): # Build header for string with type and domain info string = 'Multi-Delayed-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) @@ -2477,7 +2477,7 @@ class MatrixMDGXS(MDGXS): # Build header for string with type and domain info string = 'Multi-Delayed-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index fe8883135..55d401e5e 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -1725,7 +1725,7 @@ class MGXS: # Build header for string with type and domain info string = 'Multi-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) @@ -2534,7 +2534,7 @@ class MatrixMGXS(MGXS): # Build header for string with type and domain info string = 'Multi-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) @@ -5195,9 +5195,9 @@ class ScatterMatrixXS(MatrixMGXS): cv.check_value('xs_type', xs_type, ['macro', 'micro']) if self.correction != 'P0' and self.scatter_format == SCATTER_LEGENDRE: - rxn_type = '{0} (P{1})'.format(self.rxn_type, moment) + rxn_type = '{0} (P{1})'.format(self.hdf5_key, moment) else: - rxn_type = self.rxn_type + rxn_type = self.hdf5_key # Build header for string with type and domain info string = 'Multi-Group XS\n' @@ -5953,10 +5953,6 @@ class Chi(MGXS): num_azimuthal=1): super().__init__(domain, domain_type, groups, by_nuclide, name, num_polar, num_azimuthal) - if not prompt: - self._rxn_type = 'chi' - else: - self._rxn_type = 'chi-prompt' self._estimator = 'analog' self._valid_estimators = ['analog'] self.prompt = prompt @@ -6031,10 +6027,10 @@ class Chi(MGXS): cv.check_type('prompt', prompt, bool) self._prompt = prompt if not self.prompt: - self._rxn_type = 'nu-fission' + self._rxn_type = 'chi' self._hdf5_key = 'chi' else: - self._rxn_type = 'prompt-nu-fission' + self._rxn_type = 'chi-prompt' self._hdf5_key = 'chi-prompt' def get_homogenized_mgxs(self, other_mgxs): From 51e5d1ccd2ce7b08953c4bb24314e884345e352d Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 27 Apr 2022 12:56:39 -0500 Subject: [PATCH 0249/2654] make theta1,theta2 formulation the default; add alternate constructor for theta,alpha formulation --- openmc/model/surface_composite.py | 102 ++++++++++++++++----- tests/unit_tests/test_surface_composite.py | 36 ++++++-- 2 files changed, 106 insertions(+), 32 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index af84670cf..d4b25436d 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -66,26 +66,27 @@ class CylinderSector(CompositeSurface): Parameters ---------- - center : iterable of float - Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) - basis. Defaults to (0,0). r1 : float Inner radius of sector. Must be less than r2. r2 : float Outer radius of sector. Must be greater than r1. - central_angle : float - Central angle, :math:`\\theta`, of the sector in degrees. Must be - greater that 0 and less than 360. - ccw_offset : float - Angular offset, :math:`\\alpha`, of the clockwise-most side of the - sector in degrees. The offset is in the counter-clockwise direction - with respect to the first basis axis (+y, +z, or +x). Note that - negative values translate to an offset in the clockwise direction. + theta1 : float + Clockwise-most bound of sector in degrees. Assumed to be in the + counterclockwise direction with respect to the first basis axis + (+y, +z, or +x). Must be less than :attr:`theta2`. + theta2 : float + Counterclockwise-most bound of sector in degrees. Assumed to be in the + counterclockwise direction with respect to the first basis axis + (+y, +z, or +x). Must be greater than :attr:`theta1`. + center : iterable of float + Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) + basis. Defaults to (0,0). + axis : {'x', 'y', 'z'} Central axis of the cylinders defining the inner and outer surfaces of the sector. Defaults to 'z'. - **kwargs - Keyword arguments passed to underlying plane classes. + kwargs : dict + Keyword arguments passed to the :class:`Cylinder` and :class:`Plane` constructors. Attributes ---------- @@ -94,32 +95,34 @@ class CylinderSector(CompositeSurface): inner_cyl : openmc.ZCylinder, openmc.YCylinder, or openmc.XCylinder Inner cylinder surface. plane1 : openmc.Plane - Plane at angle :math:`\\phi_1 = \\alpha` relative to the first basis axis. + Plane at angle :math:`\\theta_1` relative to the first basis axis. plane2 : openmc.Plane - Plane at angle :math:`\\phi_2 = \\alpha + \\theta` relative to the first - basis axis. + Plane at angle :math:`\\theta_2` relative to the first basis axis. """ _surface_names = ('outer_cyl', 'inner_cyl', 'plane1', 'plane2') def __init__(self, - center, r1, r2, - central_angle, - ccw_offset, + theta1, + theta2, + center=(0.,0.), axis='z', **kwargs): if r2 <= r1 * sqrt(2): raise ValueError(f'r2 must be greater than r1.') - if central_angle >= 360. or central_angle <= 0: - raise ValueError(f'theta must be less than 360.') + if theta2 <= theta1: + raise ValueError(f'theta2 must be greater than theta1.') - phi1 = pi / 180 * ccw_offset - phi2 = pi / 180 * (ccw_offset + central_angle) + self._theta1 = theta1 + self._theta2 = theta2 + + phi1 = pi / 180 * theta1 + phi2 = pi / 180 * theta2 # Coords for axis-perpendicular planes p1 = np.array([0., 0., 1.]) @@ -152,6 +155,59 @@ class CylinderSector(CompositeSurface): self.plane2 = openmc.Plane.from_points(p1, p2_plane2, p3_plane2, **kwargs) + @classmethod + def from_theta_alpha(cls, + r1, + r2, + theta, + alpha, + center = (0.,0.), + axis='z', + **kwargs): + """Alternate constructor for :attr:`CylinderSector`. Returns an + :attr:`CylinderSector` object based on a central angle :math:`\\theta` + and an angular offset :math:`\\alpha`. Note that + :math:`\\theta_1 = \\alpha` and :math:`\\theta_2 = \\alpha + \\theta`. + + Parameters + ---------- + r1 : float + Inner radius of sector. Must be less than r2. + r2 : float + Outer radius of sector. Must be greater than r1. + theta : float + Central angle, :math:`\\theta`, of the sector in degrees. Must be + greater that 0 and less than 360. + alpha : float + Angular offset, :math:`\\alpha`, of sector in degrees. + The offset is in the counter-clockwise direction + with respect to the first basis axis (+y, +z, or +x). Note that + negative values translate to an offset in the clockwise direction. + center : iterable of float + Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) + basis. Defaults to (0,0). + + axis : {'x', 'y', 'z'} + Central axis of the cylinders defining the inner and outer surfaces of + the sector. Defaults to 'z'. + + kwargs : dict + Keyword arguments passed to the :class:`Cylinder` and :class:`Plane` constructors. + + Returns + ------- + CylinderSector + CylinderSector with the given central angle at the given + offset. + """ + if theta >= 360. or theta <= 0: + raise ValueError(f'theta must be less than 360 and greater than 0.') + + theta1 = alpha + theta2 = alpha + theta + + return cls(r1, r2, theta1, theta2, center=center, axis=axis, **kwargs) + def __neg__(self): return -self.outer_cyl & +self.inner_cyl & -self.plane1 & +self.plane2 diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 458f11c60..d4c180d26 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -161,12 +161,11 @@ def test_cone_one_sided(axis, point_pos, point_neg, ll_true): ] ) def test_cylinder_sector(axis, indices): - center = [0., 0.] r1, r2 = 0.5, 1.5 d = (r2 - r1) / 2 - central_angle = 120. - ccw_offset = -60. - s = openmc.model.CylinderSector(center, r1, r2, central_angle, ccw_offset, + phi1 = -60. + phi2 = 60 + s = openmc.model.CylinderSector(r1, r2, phi1, phi2, axis=axis.lower()) assert isinstance(s.outer_cyl, getattr(openmc, axis + "Cylinder")) assert isinstance(s.inner_cyl, getattr(openmc, axis + "Cylinder")) @@ -206,18 +205,37 @@ def test_cylinder_sector(axis, indices): # Check invalid r1, r2 combinations with pytest.raises(ValueError): - openmc.model.CylinderSector(center, 10., 1., central_angle, ccw_offset) + openmc.model.CylinderSector(r2, r1, phi1, phi2) - # Check invalid sector width + # Check invalid angles with pytest.raises(ValueError): - openmc.model.CylinderSector(center, 1., 10., 360, ccw_offset) - with pytest.raises(ValueError): - openmc.model.CylinderSector(center, 1., 10., -1, ccw_offset) + openmc.model.CylinderSector(r1, r2, phi2, phi1) # Make sure repr works repr(s) +def test_cylinder_sector_from_theta_alpha(): + r1, r2 = 0.5, 1.5 + d = (r2 - r1) / 2 + theta = 120. + alpha = -60. + s = openmc.model.CylinderSector.from_theta_alpha(r1, + r2, + theta, + alpha) + + # Check that the angles are correct + assert s._theta1 == alpha + assert s._theta2 == alpha + theta + + # Check invalid sector width + with pytest.raises(ValueError): + openmc.model.CylinderSector.from_theta_alpha(r1, r2, 360, alpha) + with pytest.raises(ValueError): + openmc.model.CylinderSector.from_theta_alpha(r1, r2, -1, alpha) + + @pytest.mark.parametrize( "axis, plane_tb, plane_lr, axis_idx", [ ("x", "Z", "Y", 0), From deae584408a45dd4ec6fa19fad7fa6e92f87a4c7 Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Wed, 27 Apr 2022 12:58:41 -0500 Subject: [PATCH 0250/2654] Renaming MGXS.hdf5_key to MGXS.mgxs_type and adding a deprecation warning for MGXS.hdf5_key by using a property which gives the warning then uses MGXS.mgxs_type --- openmc/mgxs/mdgxs.py | 74 +++++++++++-- openmc/mgxs/mgxs.py | 254 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 276 insertions(+), 52 deletions(-) diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 96c687cec..c59c8ff5c 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -120,8 +120,16 @@ class MDGXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -605,7 +613,7 @@ class MDGXS(MGXS): # Build header for string with type and domain info string = 'Multi-Delayed-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.mgxs_type) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) @@ -1000,8 +1008,16 @@ class ChiDelayed(MDGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -1516,8 +1532,16 @@ class DelayedNuFissionXS(MDGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -1652,8 +1676,16 @@ class Beta(MDGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -1842,8 +1874,16 @@ class DecayRate(MDGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -2152,8 +2192,16 @@ class MatrixMDGXS(MDGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -2477,7 +2525,7 @@ class MatrixMDGXS(MDGXS): # Build header for string with type and domain info string = 'Multi-Delayed-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.mgxs_type) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) @@ -2748,8 +2796,16 @@ class DelayedNuFissionMatrixXS(MatrixMDGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 55d401e5e..ff55b882a 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -237,8 +237,16 @@ class MGXS: Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -266,7 +274,7 @@ class MGXS: self._sparse = False self._loaded_sp = False self._derived = False - self._hdf5_key = None + self._mgxs_type = None self._valid_estimators = ESTIMATOR_TYPES self.name = name @@ -305,7 +313,7 @@ class MGXS: clone._sparse = self.sparse clone._loaded_sp = self._loaded_sp clone._derived = self.derived - clone._hdf5_key = self._hdf5_key + clone._mgxs_type = self._mgxs_type clone._tallies = OrderedDict() for tally_type, tally in self.tallies.items(): @@ -609,12 +617,20 @@ class MGXS: return self._derived @property - def hdf5_key(self): - if self._hdf5_key is not None: - return self._hdf5_key + def mgxs_type(self): + if self._mgxs_type is not None: + return self._mgxs_type else: return self._rxn_type + @property + def hdf5_key(self): + warnings.warn( + f'The {type(self).__name__}.hdf5_key attribute will be removed ' + f'in the future! Use {type(self).__name__}.mgxs_type instead', + DeprecationWarning) + return self.mgxs_type + @name.setter def name(self, name): cv.check_type('name', name, str) @@ -1725,7 +1741,7 @@ class MGXS: # Build header for string with type and domain info string = 'Multi-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.mgxs_type) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) @@ -1912,7 +1928,7 @@ class MGXS: subdomain_group = domain_group # Create a separate HDF5 group for this cross section - rxn_group = subdomain_group.require_group(self.hdf5_key) + rxn_group = subdomain_group.require_group(self.mgxs_type) # Create a separate HDF5 group for each nuclide for j, nuclide in enumerate(nuclides): @@ -2238,8 +2254,16 @@ class MatrixMGXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @property @@ -2534,7 +2558,7 @@ class MatrixMGXS(MGXS): # Build header for string with type and domain info string = 'Multi-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.hdf5_key) + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.mgxs_type) string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) @@ -2732,8 +2756,16 @@ class TotalXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -2870,8 +2902,16 @@ class TransportXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -3108,8 +3148,16 @@ class DiffusionCoefficient(TransportXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -3291,8 +3339,16 @@ class AbsorptionXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -3417,8 +3473,16 @@ class CaptureXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -3570,8 +3634,16 @@ class FissionXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -3738,8 +3810,16 @@ class KappaFissionXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -3869,8 +3949,16 @@ class ScatterXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -4013,8 +4101,16 @@ class ArbitraryXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -4145,8 +4241,16 @@ class ArbitraryMatrixXS(MatrixMGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -4347,8 +4451,16 @@ class ScatterMatrixXS(MatrixMGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -4705,17 +4817,17 @@ class ScatterMatrixXS(MatrixMGXS): if self.formulation == 'simple': if not nu: self._rxn_type = 'scatter' - self._hdf5_key = 'scatter matrix' + self._mgxs_type = 'scatter matrix' else: self._rxn_type = 'nu-scatter' - self._hdf5_key = 'nu-scatter matrix' + self._mgxs_type = 'nu-scatter matrix' else: if not nu: self._rxn_type = 'scatter' - self._hdf5_key = 'consistent scatter matrix' + self._mgxs_type = 'consistent scatter matrix' else: self._rxn_type = 'nu-scatter' - self._hdf5_key = 'consistent nu-scatter matrix' + self._mgxs_type = 'consistent nu-scatter matrix' @formulation.setter def formulation(self, formulation): @@ -4725,15 +4837,15 @@ class ScatterMatrixXS(MatrixMGXS): if self.formulation == 'simple': self._valid_estimators = ['analog'] if not self.nu: - self._hdf5_key = 'scatter matrix' + self._mgxs_type = 'scatter matrix' else: - self._hdf5_key = 'nu-scatter matrix' + self._mgxs_type = 'nu-scatter matrix' else: self._valid_estimators = ['tracklength'] if not self.nu: - self._hdf5_key = 'consistent scatter matrix' + self._mgxs_type = 'consistent scatter matrix' else: - self._hdf5_key = 'consistent nu-scatter matrix' + self._mgxs_type = 'consistent nu-scatter matrix' @correction.setter def correction(self, correction): @@ -5195,9 +5307,9 @@ class ScatterMatrixXS(MatrixMGXS): cv.check_value('xs_type', xs_type, ['macro', 'micro']) if self.correction != 'P0' and self.scatter_format == SCATTER_LEGENDRE: - rxn_type = '{0} (P{1})'.format(self.hdf5_key, moment) + rxn_type = '{0} (P{1})'.format(self.mgxs_type, moment) else: - rxn_type = self.hdf5_key + rxn_type = self.mgxs_type # Build header for string with type and domain info string = 'Multi-Group XS\n' @@ -5434,8 +5546,16 @@ class MultiplicityMatrixXS(MatrixMGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -5607,8 +5727,16 @@ class ScatterProbabilityMatrix(MatrixMGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -5622,7 +5750,7 @@ class ScatterProbabilityMatrix(MatrixMGXS): super().__init__(domain, domain_type, groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'scatter' - self._hdf5_key = 'scatter probability matrix' + self._mgxs_type = 'scatter probability matrix' self._estimator = 'analog' self._valid_estimators = ['analog'] @@ -5780,8 +5908,16 @@ class NuFissionMatrixXS(MatrixMGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -5792,10 +5928,10 @@ class NuFissionMatrixXS(MatrixMGXS): num_polar, num_azimuthal) if not prompt: self._rxn_type = 'nu-fission' - self._hdf5_key = 'nu-fission matrix' + self._mgxs_type = 'nu-fission matrix' else: self._rxn_type = 'prompt-nu-fission' - self._hdf5_key = 'prompt-nu-fission matrix' + self._mgxs_type = 'prompt-nu-fission matrix' self._estimator = 'analog' self._valid_estimators = ['analog'] self.prompt = prompt @@ -5938,8 +6074,16 @@ class Chi(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -6028,10 +6172,10 @@ class Chi(MGXS): self._prompt = prompt if not self.prompt: self._rxn_type = 'chi' - self._hdf5_key = 'chi' + self._mgxs_type = 'chi' else: self._rxn_type = 'chi-prompt' - self._hdf5_key = 'chi-prompt' + self._mgxs_type = 'chi-prompt' def get_homogenized_mgxs(self, other_mgxs): """Construct a homogenized mgxs with other MGXS objects. @@ -6461,8 +6605,16 @@ class InverseVelocity(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ @@ -6580,8 +6732,16 @@ class MeshSurfaceMGXS(MGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ def __init__(self, domain=None, domain_type=None, energy_groups=None, @@ -6966,8 +7126,16 @@ class Current(MeshSurfaceMGXS): Whether or not a statepoint file has been loaded with tally data derived : bool Whether or not the MGXS is merged from one or more other MGXS + mgxs_type : str + The name of this MGXS type, to be used when printing and + indexing in an HDF5 data store + + .. versionadded:: 0.14 hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store + The key used to index multi-group cross sections in an HDF5 data store. + This will be replaced by mgxs_type in the future. + + .. deprecated:: 0.13.0 """ def __init__(self, domain=None, domain_type=None, From ee37d8e2bf1aa558584968971e4da888d8a7e13c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 27 Apr 2022 23:35:54 -0500 Subject: [PATCH 0251/2654] Add time_units argument to ResultsList.get_eigenvalue --- openmc/deplete/results_list.py | 47 +++++++++++--------- tests/unit_tests/test_deplete_resultslist.py | 2 + 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index a9e55c177..3265f22f8 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -14,6 +14,17 @@ from openmc.exceptions import DataError, InvalidArgumentError __all__ = ["ResultsList"] +def _get_time_as(seconds, units): + if units == "d": + return seconds / (60 * 60 * 24) + elif units == "h": + return seconds / (60 * 60) + elif units == "min": + return seconds / 60 + else: + return seconds + + class ResultsList(list): """A list of openmc.deplete.Results objects @@ -99,13 +110,7 @@ class ResultsList(list): concentrations[i] = result[0, mat_id, nuc] # Unit conversions - if time_units == "d": - times /= (60 * 60 * 24) - elif time_units == "h": - times /= (60 * 60) - elif time_units == "min": - times /= 60 - + times = _get_time_as(times, time_units) if nuc_units != "atoms": # Divide by volume to get density concentrations /= self[0].volume[mat_id] @@ -160,19 +165,26 @@ class ResultsList(list): return times, rates - def get_eigenvalue(self): + def get_eigenvalue(self, time_units='s'): """Evaluates the eigenvalue from a results list. + Parameters + ---------- + time_units : {"s", "d", "h", "min"}, optional + Desired units for the times array + Returns ------- times : numpy.ndarray - Array of times in [s] + Array of times in specified units eigenvalues : numpy.ndarray k-eigenvalue at each time. Column 0 contains the eigenvalue, while column 1 contains the associated uncertainty """ + cv.check_value("time_units", time_units, {"s", "d", "min", "h"}) + times = np.empty_like(self, dtype=float) eigenvalues = np.empty((len(self), 2), dtype=float) @@ -181,6 +193,8 @@ class ResultsList(list): times[i] = result.time[0] eigenvalues[i] = result.k[0] + # Convert time units if necessary + times = _get_time_as(times, time_units) return times, eigenvalues def get_depletion_time(self): @@ -230,7 +244,7 @@ class ResultsList(list): 1-D vector of time points """ - cv.check_type("time_units", time_units, str) + cv.check_value("time_units", time_units, {"s", "d", "min", "h"}) times = np.fromiter( (r.time[0] for r in self), @@ -238,18 +252,7 @@ class ResultsList(list): count=len(self), ) - if time_units == "d": - times /= (60 * 60 * 24) - elif time_units == "h": - times /= (60 * 60) - elif time_units == "min": - times /= 60 - elif time_units != "s": - raise ValueError( - 'Unable to set "time_units" to {} since it is not ' - 'in ("s", "d", "min", "h")'.format(time_units) - ) - return times + return _get_time_as(times, time_units) def get_step_where( self, time, time_units="d", atol=1e-6, rtol=1e-3 diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 5d8fb11e4..96a16cf4d 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -58,12 +58,14 @@ def test_get_reaction_rate(res): def test_get_eigenvalue(res): """Tests evaluating eigenvalue.""" t, k = res.get_eigenvalue() + t_min, k = res.get_eigenvalue(time_units='min') t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] k_ref = [1.21409662, 1.16518654, 1.25357797, 1.22611968] u_ref = [0.0278795195, 0.0233141097, 0.0167899218, 0.0246734716] np.testing.assert_allclose(t, t_ref) + np.testing.assert_allclose(t_min * 60, t_ref) np.testing.assert_allclose(k[:, 0], k_ref) np.testing.assert_allclose(k[:, 1], u_ref) From 94c282670c0eeacf95e965c06e195559c4c7a9d3 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 28 Apr 2022 15:13:12 +0100 Subject: [PATCH 0252/2654] removed typo in group name --- openmc/mgxs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index 133b4c257..938dd8c7a 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -154,7 +154,7 @@ GROUP_STRUCTURES['VITAMIN-J-175'] = np.array([ 1.1052e7, 1.1618e7, 1.2214e7, 1.2523e7, 1.2840e7, 1.3499e7, 1.3840e7, 1.4191e7, 1.4550e7, 1.4918e7, 1.5683e7, 1.6487e7, 1.6905e7, 1.7332e7, 1.9640e7]) -GROUP_STRUCTURES['TRIPOLI-315,'] = np.array([ +GROUP_STRUCTURES['TRIPOLI-315'] = np.array([ 1.0e-5, 1.1e-4, 3.000e-3, 5.500e-3, 1.000e-2, 1.500e-2, 2.000e-2, 3.000e-2, 3.200e-2, 3.238e-2, 4.300e-2, 5.900e-2, 7.700e-2, 9.500e-2, 1.000e-1, 1.150e-1, 1.340e-1, 1.600e-1, 1.890e-1, 2.200e-1, 2.480e-1, 2.825e-1, From 1d7265de3ea1012bfa935a48ec96384897847b03 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 28 Apr 2022 10:24:31 -0500 Subject: [PATCH 0253/2654] check surface coefficients match between CylinderSector objects from different constructors --- tests/unit_tests/test_surface_composite.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index d4c180d26..4d680ae7c 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -220,14 +220,19 @@ def test_cylinder_sector_from_theta_alpha(): d = (r2 - r1) / 2 theta = 120. alpha = -60. - s = openmc.model.CylinderSector.from_theta_alpha(r1, + theta1 = alpha + theta2 = alpha + theta + s = openmc.model.CylinderSector(r1, r2, theta1, theta2) + s_alt = openmc.model.CylinderSector.from_theta_alpha(r1, r2, theta, alpha) # Check that the angles are correct - assert s._theta1 == alpha - assert s._theta2 == alpha + theta + assert s.plane1.coefficients == s_alt.plane1.coefficients + assert s.plane2.coefficients == s_alt.plane2.coefficients + assert s.inner_cyl.coefficients == s_alt.inner_cyl.coefficients + assert s.outer_cyl.coefficients == s_alt.outer_cyl.coefficients # Check invalid sector width with pytest.raises(ValueError): From 2cccc1b788d8dfee99b805e05eab089ff895f4f4 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 28 Apr 2022 10:26:58 -0500 Subject: [PATCH 0254/2654] docstring fixes for from_theta_alpha; remove cruft attributes --- openmc/model/surface_composite.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index d4b25436d..590fe13a4 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -112,15 +112,12 @@ class CylinderSector(CompositeSurface): axis='z', **kwargs): - if r2 <= r1 * sqrt(2): + if r2 <= r1: raise ValueError(f'r2 must be greater than r1.') if theta2 <= theta1: raise ValueError(f'theta2 must be greater than theta1.') - self._theta1 = theta1 - self._theta2 = theta2 - phi1 = pi / 180 * theta1 phi2 = pi / 180 * theta2 @@ -164,10 +161,10 @@ class CylinderSector(CompositeSurface): center = (0.,0.), axis='z', **kwargs): - """Alternate constructor for :attr:`CylinderSector`. Returns an - :attr:`CylinderSector` object based on a central angle :math:`\\theta` - and an angular offset :math:`\\alpha`. Note that - :math:`\\theta_1 = \\alpha` and :math:`\\theta_2 = \\alpha + \\theta`. + r"""Alternate constructor for :class:`CylinderSector`. Returns a + :class:`CylinderSector` object based on a central angle :math:`\theta` + and an angular offset :math:`\alpha`. Note that + :math:`\theta_1 = \alpha` and :math:`\theta_2 = \alpha + \theta`. Parameters ---------- @@ -176,22 +173,20 @@ class CylinderSector(CompositeSurface): r2 : float Outer radius of sector. Must be greater than r1. theta : float - Central angle, :math:`\\theta`, of the sector in degrees. Must be + Central angle, :math:`\theta`, of the sector in degrees. Must be greater that 0 and less than 360. alpha : float - Angular offset, :math:`\\alpha`, of sector in degrees. + Angular offset, :math:`\alpha`, of sector in degrees. The offset is in the counter-clockwise direction with respect to the first basis axis (+y, +z, or +x). Note that negative values translate to an offset in the clockwise direction. center : iterable of float Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) basis. Defaults to (0,0). - axis : {'x', 'y', 'z'} Central axis of the cylinders defining the inner and outer surfaces of the sector. Defaults to 'z'. - - kwargs : dict + **kwargs : dict Keyword arguments passed to the :class:`Cylinder` and :class:`Plane` constructors. Returns From 77b4ec564718e8c876ac1ec4dbc83c9adc2d5921 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 28 Apr 2022 10:30:47 -0500 Subject: [PATCH 0255/2654] pep8 and consistency fixes in docstring --- openmc/model/surface_composite.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 590fe13a4..74f64c54a 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -81,12 +81,12 @@ class CylinderSector(CompositeSurface): center : iterable of float Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) basis. Defaults to (0,0). - axis : {'x', 'y', 'z'} Central axis of the cylinders defining the inner and outer surfaces of the sector. Defaults to 'z'. - kwargs : dict - Keyword arguments passed to the :class:`Cylinder` and :class:`Plane` constructors. + **kwargs : dict + Keyword arguments passed to the :class:`Cylinder` and + :class:`Plane` constructors. Attributes ---------- @@ -184,10 +184,11 @@ class CylinderSector(CompositeSurface): Coordinate for central axes of cylinders in the (y, z), (z, x), or (x, y) basis. Defaults to (0,0). axis : {'x', 'y', 'z'} - Central axis of the cylinders defining the inner and outer surfaces of - the sector. Defaults to 'z'. + Central axis of the cylinders defining the inner and outer surfaces + of the sector. Defaults to 'z'. **kwargs : dict - Keyword arguments passed to the :class:`Cylinder` and :class:`Plane` constructors. + Keyword arguments passed to the :class:`Cylinder` and + :class:`Plane` constructors. Returns ------- From f8f788352f51b4d454792b4610eee209bc87de9a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 29 Apr 2022 06:48:55 -0500 Subject: [PATCH 0256/2654] Fix IO format documentation for surf_source_read/write --- docs/source/io_formats/settings.rst | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index d1d9e69fa..d2c15c56f 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -731,27 +731,26 @@ attributes/sub-elements: *Default*: false ---------------------------- -```` Element ---------------------------- +------------------------------ +```` Element +------------------------------ -The ```` element specifies a surface source file for OpenMC to -read source bank for initializing histories. -This element has the following attributes/sub-elements: +The ```` element specifies a surface source file for OpenMC to +read source bank for initializing histories. This element has the following +attributes/sub-elements: :path: Absolute or relative path to a surface source file to read in source bank. *Default*: ``surface_source.h5`` in current working directory ----------------------------- -```` Element ----------------------------- +------------------------------- +```` Element +------------------------------- -The ```` element triggers OpenMC to bank particles crossing +The ```` element triggers OpenMC to bank particles crossing certain surfaces and write out the source bank in a separate file called -``surface_source.h5``. -This element has the following attributes/sub-elements: +``surface_source.h5``. This element has the following attributes/sub-elements: :surface_ids: A list of integers separated by spaces indicating the unique IDs of surfaces From d76434379af9a56cfe60ad4b49b29982af1e9d6b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 29 Apr 2022 19:25:01 -0500 Subject: [PATCH 0257/2654] Make sure basis gets set in Plot.from_geometry --- openmc/plots.py | 1 + tests/unit_tests/test_plots.py | 1 + 2 files changed, 2 insertions(+) diff --git a/openmc/plots.py b/openmc/plots.py index 6bce8894c..5e9c48413 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -512,6 +512,7 @@ class Plot(IDManagerMixin): plot.origin = np.insert((lower_left + upper_right)/2, slice_index, slice_coord) plot.width = upper_right - lower_left + plot.basis = basis return plot def colorize(self, geometry, seed=1): diff --git a/tests/unit_tests/test_plots.py b/tests/unit_tests/test_plots.py index 3288617b0..718f098ba 100644 --- a/tests/unit_tests/test_plots.py +++ b/tests/unit_tests/test_plots.py @@ -58,6 +58,7 @@ def test_from_geometry(): plot = openmc.Plot.from_geometry(geom, basis) assert plot.origin == pytest.approx((0., 0., 0.)) assert plot.width == pytest.approx((width, width)) + assert plot.basis == basis def test_highlight_domains(): From 45a6b31c8f505092ee88d96ab5363b83529d9a8b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Apr 2022 15:43:42 -0500 Subject: [PATCH 0258/2654] Change StatePoint.k_combined -> keff, ResultsList.get_eigenvalue -> get_keff --- docs/source/usersguide/depletion.rst | 2 +- docs/source/usersguide/troubleshoot.rst | 2 +- examples/jezebel/jezebel.py | 2 +- examples/pincell_depletion/restart_depletion.py | 14 +++++++------- examples/pincell_depletion/run_depletion.py | 13 ++++++------- openmc/deplete/operator.py | 4 ++-- openmc/deplete/results.py | 4 ++-- openmc/deplete/results_list.py | 16 +++++++++++----- openmc/mgxs/library.py | 2 +- openmc/search.py | 2 +- openmc/statepoint.py | 16 +++++++++++++++- tests/regression_tests/deplete/test.py | 8 ++++---- tests/regression_tests/entropy/test.py | 2 +- tests/regression_tests/mg_convert/test.py | 2 +- .../trigger_statepoint_restart/test.py | 8 ++++---- tests/testing_harness.py | 2 +- tests/unit_tests/test_deplete_resultslist.py | 8 ++++---- tests/unit_tests/test_model.py | 4 ++-- tests/unit_tests/test_temp_interp.py | 2 +- tests/unit_tests/test_torus.py | 2 +- 20 files changed, 67 insertions(+), 48 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 6fa2b89c9..78a12c4ca 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -54,7 +54,7 @@ easy retrieval of k-effective, nuclide concentrations, and reaction rates over time:: results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") - time, keff = results.get_eigenvalue() + time, keff = results.get_keff() Note that the coupling between the transport solver and the transmutation solver happens in-memory rather than by reading/writing files on disk. diff --git a/docs/source/usersguide/troubleshoot.rst b/docs/source/usersguide/troubleshoot.rst index 888158837..b1cd80f3e 100644 --- a/docs/source/usersguide/troubleshoot.rst +++ b/docs/source/usersguide/troubleshoot.rst @@ -81,7 +81,7 @@ it is recommended that data be extracted from statepoint files in a context mana .. code-block:: python with openmc.StatePoint('statepoint.10.h5') as sp: - k_eff = sp.k_combined + k_eff = sp.keff or that the :meth:`StatePoint.close` method is called before executing a subsequent OpenMC run. diff --git a/examples/jezebel/jezebel.py b/examples/jezebel/jezebel.py index 5114ac714..83b47a5e9 100644 --- a/examples/jezebel/jezebel.py +++ b/examples/jezebel/jezebel.py @@ -29,5 +29,5 @@ openmc.run() # Get the resulting k-effective value n = settings.batches with openmc.StatePoint(f'statepoint.{n}.h5') as sp: - keff = sp.k_combined + keff = sp.keff print(f'Final k-effective = {keff}') diff --git a/examples/pincell_depletion/restart_depletion.py b/examples/pincell_depletion/restart_depletion.py index 991120399..72209d2ab 100644 --- a/examples/pincell_depletion/restart_depletion.py +++ b/examples/pincell_depletion/restart_depletion.py @@ -59,33 +59,33 @@ integrator.integrate() results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") # Obtain K_eff as a function of time -time, keff = results.get_eigenvalue() +time, keff = results.get_keff(time_units='d') # Obtain U235 concentration as a function of time -time, n_U235 = results.get_atoms(uo2, 'U235') +uo2 = geometry.get_all_material_cells()[1] +_, n_U235 = results.get_atoms(uo2, 'U235') # Obtain Xe135 capture reaction rate as a function of time -time, Xe_capture = results.get_reaction_rate(uo2, 'Xe135', '(n,gamma)') +_, Xe_capture = results.get_reaction_rate(uo2, 'Xe135', '(n,gamma)') ############################################################################### # Generate plots ############################################################################### -days = 24*60*60 fig, ax = plt.subplots() -ax.errorbar(time/days, keff[:, 0], keff[:, 1], label="K-effective") +ax.errorbar(time, keff[:, 0], keff[:, 1], label="K-effective") ax.set_xlabel("Time [d]") ax.set_ylabel("Keff") plt.show() fig, ax = plt.subplots() -ax.plot(time/days, n_U235, label="U235") +ax.plot(time, n_U235, label="U235") ax.set_xlabel("Time [d]") ax.set_ylabel("U235 atoms") plt.show() fig, ax = plt.subplots() -ax.plot(time/days, Xe_capture, label="Xe135 capture") +ax.plot(time, Xe_capture, label="Xe135 capture") ax.set_xlabel("Time [d]") ax.set_ylabel("Xe135 capture rate") plt.show() diff --git a/examples/pincell_depletion/run_depletion.py b/examples/pincell_depletion/run_depletion.py index 75bc3b542..53b0614d1 100644 --- a/examples/pincell_depletion/run_depletion.py +++ b/examples/pincell_depletion/run_depletion.py @@ -104,33 +104,32 @@ integrator.integrate() results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") # Obtain K_eff as a function of time -time, keff = results.get_eigenvalue() +time, keff = results.get_keff(time_units='d') # Obtain U235 concentration as a function of time -time, n_U235 = results.get_atoms(uo2, 'U235') +_, n_U235 = results.get_atoms(uo2, 'U235') # Obtain Xe135 capture reaction rate as a function of time -time, Xe_capture = results.get_reaction_rate(uo2, 'Xe135', '(n,gamma)') +_, Xe_capture = results.get_reaction_rate(uo2, 'Xe135', '(n,gamma)') ############################################################################### # Generate plots ############################################################################### -days = 24*60*60 fig, ax = plt.subplots() -ax.errorbar(time/days, keff[:, 0], keff[:, 1], label="K-effective") +ax.errorbar(time, keff[:, 0], keff[:, 1], label="K-effective") ax.set_xlabel("Time [d]") ax.set_ylabel("Keff") plt.show() fig, ax = plt.subplots() -ax.plot(time/days, n_U235, label="U235") +ax.plot(time, n_U235, label="U235") ax.set_xlabel("Time [d]") ax.set_ylabel("U235 atoms") plt.show() fig, ax = plt.subplots() -ax.plot(time/days, Xe_capture, label="Xe135 capture") +ax.plot(time, Xe_capture, label="Xe135 capture") ax.set_xlabel("Time [d]") ax.set_ylabel("Xe135 capture rate") plt.show() diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 337e8f8c0..1f31a22b6 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -725,7 +725,7 @@ class Operator(TransportOperator): rates.fill(0.0) # Get k and uncertainty - k_combined = ufloat(*openmc.lib.keff()) + keff = ufloat(*openmc.lib.keff()) # Extract tally bins nuclides = self._rate_helper.nuclides @@ -779,7 +779,7 @@ class Operator(TransportOperator): # Store new fission yields on the chain self.chain.fission_yields = fission_yields - return OperatorResult(k_combined, rates) + return OperatorResult(keff, rates) def _get_nuclides_with_data(self, cross_sections): """Loads cross_sections.xml file to find nuclides with neutron data""" diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 89c6f8874..3916fb4d7 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -50,7 +50,7 @@ class Results: Number of stages in simulation. data : numpy.ndarray Atom quantity, stored by stage, mat, then by nuclide. - proc_time: int + proc_time : int Average time spent depleting a material across all materials and processes @@ -518,4 +518,4 @@ class Results: for material in materials: if material.depletable: - material.volume = self.volume[str(material.id)] \ No newline at end of file + material.volume = self.volume[str(material.id)] diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 3265f22f8..f2f2be0ab 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -1,6 +1,7 @@ import numbers import bisect import math +from warnings import warn import h5py import numpy as np @@ -165,7 +166,7 @@ class ResultsList(list): return times, rates - def get_eigenvalue(self, time_units='s'): + def get_keff(self, time_units='s'): """Evaluates the eigenvalue from a results list. Parameters @@ -197,14 +198,19 @@ class ResultsList(list): times = _get_time_as(times, time_units) return times, eigenvalues + def get_eigenvalue(self, time_units='s'): + warn("The get_eigenvalue(...) function has been renamed get_keff and " + "will be removed in a future version of OpenMC.", FutureWarning) + return self.get_keff(time_units) + + def get_depletion_time(self): """Return an array of the average time to deplete a material .. note:: - - Will have one fewer row than number of other methods, - like :meth:`get_eigenvalues`, because no depletion - is performed at the final transport stage + The return value will have one fewer values than several other + methods, such as :meth:`get_keff`, because no depletion is performed + at the final transport stage. Returns ------- diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 5c7072033..efe8dbe84 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -593,7 +593,7 @@ class Library: self._nuclides = statepoint.summary.nuclides if statepoint.run_mode == 'eigenvalue': - self._keff = statepoint.k_combined.n + self._keff = statepoint.keff.n # Load tallies for each MGXS for each domain and mgxs type for domain in self.domains: diff --git a/openmc/search.py b/openmc/search.py index ee5dd1f07..9db37da1c 100644 --- a/openmc/search.py +++ b/openmc/search.py @@ -53,7 +53,7 @@ def _search_keff(guess, target, model_builder, model_args, print_iterations, # Run the model and obtain keff sp_filepath = model.run(output=print_output) with openmc.StatePoint(sp_filepath) as sp: - keff = sp.k_combined + keff = sp.keff # Record the history guesses.append(guess) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 894730cbe..630675816 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -63,6 +63,8 @@ class StatePoint: datatype has fields 'name', 'sum', 'sum_sq', 'mean', and 'std_dev'. k_combined : uncertainties.UFloat Combined estimator for k-effective + + .. deprecated:: 0.13.1 k_col_abs : float Cross-product of collision and absorption estimates of k-effective k_col_tra : float @@ -71,6 +73,10 @@ class StatePoint: Cross-product of absorption and tracklength estimates of k-effective k_generation : numpy.ndarray Estimate of k-effective for each batch/generation + keff : uncertainties.UFloat + Combined estimator for k-effective + + .. versionadded:: 0.13.1 meshes : dict Dictionary whose keys are mesh IDs and whose values are MeshBase objects n_batches : int @@ -260,12 +266,20 @@ class StatePoint: return None @property - def k_combined(self): + def keff(self): if self.run_mode == 'eigenvalue': return ufloat(*self._f['k_combined'][()]) else: return None + @property + def k_combined(self): + warnings.warn( + "The 'k_combined' property has been renamed to 'keff' and will be " + "removed in a future version of OpenMC.", FutureWarning + ) + return self.keff + @property def k_col_abs(self): if self.run_mode == 'eigenvalue': diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index fccd50493..4f0e738a3 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -115,16 +115,16 @@ def test_full(run_in_tmpdir, problem, multiproc): # Compare statepoint files with depletion results - t_test, k_test = res_test.get_eigenvalue() - t_ref, k_ref = res_ref.get_eigenvalue() + t_test, k_test = res_test.get_keff() + t_ref, k_ref = res_ref.get_keff() k_state = np.empty_like(k_ref) n_tallies = np.empty(N + 1, dtype=int) # Get statepoint files for all BOS points and EOL for n in range(N + 1): - statepoint = openmc.StatePoint("openmc_simulation_n{}.h5".format(n)) - k_n = statepoint.k_combined + statepoint = openmc.StatePoint(f"openmc_simulation_n{n}.h5") + k_n = statepoint.keff k_state[n] = [k_n.nominal_value, k_n.std_dev] n_tallies[n] = len(statepoint.tallies) # Look for exact match pulling from statepoint and depletion_results diff --git a/tests/regression_tests/entropy/test.py b/tests/regression_tests/entropy/test.py index 10a11e300..af1fbd56a 100644 --- a/tests/regression_tests/entropy/test.py +++ b/tests/regression_tests/entropy/test.py @@ -14,7 +14,7 @@ class EntropyTestHarness(TestHarness): with StatePoint(statepoint) as sp: # Write out k-combined. outstr = 'k-combined:\n' - outstr += '{:12.6E} {:12.6E}\n'.format(sp.k_combined.n, sp.k_combined.s) + outstr += '{:12.6E} {:12.6E}\n'.format(sp.keff.n, sp.keff.s) # Write out entropy data. outstr += 'entropy:\n' diff --git a/tests/regression_tests/mg_convert/test.py b/tests/regression_tests/mg_convert/test.py index f22c15dc0..c6ab485ea 100755 --- a/tests/regression_tests/mg_convert/test.py +++ b/tests/regression_tests/mg_convert/test.py @@ -145,7 +145,7 @@ class MGXSTestHarness(PyAPITestHarness): # Write out k-combined. outstr += 'k-combined:\n' form = '{:12.6E} {:12.6E}\n' - outstr += form.format(sp.k_combined.n, sp.k_combined.s) + outstr += form.format(sp.keff.n, sp.keff.s) return outstr diff --git a/tests/regression_tests/trigger_statepoint_restart/test.py b/tests/regression_tests/trigger_statepoint_restart/test.py index 8d4d56192..8144c1d0b 100644 --- a/tests/regression_tests/trigger_statepoint_restart/test.py +++ b/tests/regression_tests/trigger_statepoint_restart/test.py @@ -90,7 +90,7 @@ class TriggerStatepointRestartTestHarness(PyAPITestHarness): assert spfile with openmc.StatePoint(spfile) as sp: sp_batchno_1 = sp.current_batch - k_combined_1 = sp.k_combined + keff_1 = sp.keff assert sp_batchno_1 > 5 print('Last batch no = %d' % sp_batchno_1) self._write_inputs(self._get_inputs()) @@ -108,13 +108,13 @@ class TriggerStatepointRestartTestHarness(PyAPITestHarness): assert spfile with openmc.StatePoint(spfile) as sp: sp_batchno_2 = sp.current_batch - k_combined_2 = sp.k_combined + keff_2 = sp.keff assert sp_batchno_2 > 5 assert sp_batchno_1 == sp_batchno_2, \ 'Different final batch number after restart' # need str() here as uncertainties.ufloat instances are always different - assert str(k_combined_1) == str(k_combined_2), \ - 'Different final k_combined after restart' + assert str(keff_1) == str(keff_2), \ + 'Different final keff after restart' self._write_inputs(self._get_inputs()) self._compare_inputs() self._test_output_created() diff --git a/tests/testing_harness.py b/tests/testing_harness.py index ba65ba5a6..9a6db2a2e 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -92,7 +92,7 @@ class TestHarness: # Write out k-combined. outstr += 'k-combined:\n' form = '{0:12.6E} {1:12.6E}\n' - outstr += form.format(sp.k_combined.n, sp.k_combined.s) + outstr += form.format(sp.keff.n, sp.keff.s) # Write out tally data. for i, tally_ind in enumerate(sp.tallies): diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 96a16cf4d..03e7c3eb0 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -55,10 +55,10 @@ def test_get_reaction_rate(res): np.testing.assert_allclose(r, np.array(n_ref) * xs_ref) -def test_get_eigenvalue(res): - """Tests evaluating eigenvalue.""" - t, k = res.get_eigenvalue() - t_min, k = res.get_eigenvalue(time_units='min') +def test_get_keff(res): + """Tests evaluating keff.""" + t, k = res.get_keff() + t_min, k = res.get_keff(time_units='min') t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] k_ref = [1.21409662, 1.16518654, 1.25357797, 1.22611968] diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index ff446a83d..10417b20e 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -293,14 +293,14 @@ def test_run(run_in_tmpdir, pin_model_attributes, mpi_intracomm): # C API execution modes and ensuring they give the same result. sp_path = test_model.run(output=False) with openmc.StatePoint(sp_path) as sp: - cli_keff = sp.k_combined + cli_keff = sp.keff cli_flux = sp.get_tally(id=1).get_values(scores=['flux'])[0, 0, 0] cli_fiss = sp.get_tally(id=1).get_values(scores=['fission'])[0, 0, 0] test_model.init_lib(output=False, intracomm=mpi_intracomm) sp_path = test_model.run(output=False) with openmc.StatePoint(sp_path) as sp: - lib_keff = sp.k_combined + lib_keff = sp.keff lib_flux = sp.get_tally(id=1).get_values(scores=['flux'])[0, 0, 0] lib_fiss = sp.get_tally(id=1).get_values(scores=['fission'])[0, 0, 0] diff --git a/tests/unit_tests/test_temp_interp.py b/tests/unit_tests/test_temp_interp.py index 6cbe2f63f..f87d52961 100644 --- a/tests/unit_tests/test_temp_interp.py +++ b/tests/unit_tests/test_temp_interp.py @@ -147,7 +147,7 @@ def test_interpolation(model, method, temperature, fission_expected): assert abs(nu_fission_mean - nu*fission_expected) < 3*nu_fission_unc # Check that k-effective value matches expected - k = sp.k_combined + k = sp.keff if isnan(k.s): assert k.n == pytest.approx(nu*fission_expected) else: diff --git a/tests/unit_tests/test_torus.py b/tests/unit_tests/test_torus.py index a5f49faae..ba92860e7 100644 --- a/tests/unit_tests/test_torus.py +++ b/tests/unit_tests/test_torus.py @@ -24,7 +24,7 @@ def get_torus_keff(cls, R, r, center=(0, 0, 0)): sp_path = model.run() with openmc.StatePoint(sp_path) as sp: - return sp.k_combined + return sp.keff @pytest.mark.parametrize("R,r", [(2.1, 2.0), (3.0, 1.0)]) From 4d3aac7f63d00cdcd69beafe840cd2bd7cda9299 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 29 Apr 2022 07:03:14 -0500 Subject: [PATCH 0259/2654] Change print_output argument in search_for_keff to more general run_args --- openmc/search.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/openmc/search.py b/openmc/search.py index 9db37da1c..7f6b3b5b9 100644 --- a/openmc/search.py +++ b/openmc/search.py @@ -12,7 +12,7 @@ _SCALAR_BRACKETED_METHODS = ['brentq', 'brenth', 'ridder', 'bisect'] def _search_keff(guess, target, model_builder, model_args, print_iterations, - print_output, guesses, results): + run_args, guesses, results): """Function which will actually create our model, run the calculation, and obtain the result. This function will be passed to the root finding algorithm @@ -31,8 +31,8 @@ def _search_keff(guess, target, model_builder, model_args, print_iterations, print_iterations : bool Whether or not to print the guess and the resultant keff during the iteration process. - print_output : bool - Whether or not to print the OpenMC output during the iterations. + run_args : dict + Keyword arguments to pass to :meth:`openmc.Model.run`. guesses : Iterable of Real Running list of guesses thus far, to be updated during the execution of this function. @@ -51,7 +51,7 @@ def _search_keff(guess, target, model_builder, model_args, print_iterations, model = model_builder(guess, **model_args) # Run the model and obtain keff - sp_filepath = model.run(output=print_output) + sp_filepath = model.run(**run_args) with openmc.StatePoint(sp_filepath) as sp: keff = sp.keff @@ -70,7 +70,7 @@ def _search_keff(guess, target, model_builder, model_args, print_iterations, def search_for_keff(model_builder, initial_guess=None, target=1.0, bracket=None, model_args=None, tol=None, bracketed_method='bisect', print_iterations=False, - print_output=False, **kwargs): + run_args=None, **kwargs): """Function to perform a keff search by modifying a model parametrized by a single independent variable. @@ -102,9 +102,11 @@ def search_for_keff(model_builder, initial_guess=None, target=1.0, print_iterations : bool Whether or not to print the guess and the result during the iteration process. Defaults to False. - print_output : bool - Whether or not to print the OpenMC output during the iterations. - Defaults to False. + run_args : dict, optional + Keyword arguments to pass to :meth:`openmc.Model.run`. Defaults to no + arguments. + + .. versionadded:: 0.13.1 **kwargs All remaining keyword arguments are passed to the root-finding method. @@ -137,7 +139,10 @@ def search_for_keff(model_builder, initial_guess=None, target=1.0, cv.check_value('bracketed_method', bracketed_method, _SCALAR_BRACKETED_METHODS) cv.check_type('print_iterations', print_iterations, bool) - cv.check_type('print_output', print_output, bool) + if run_args is None: + run_args = {} + else: + cv.check_type('run_args', run_args, dict) cv.check_type('model_builder', model_builder, Callable) # Run the model builder function once to make sure it provides the correct @@ -188,7 +193,7 @@ def search_for_keff(model_builder, initial_guess=None, target=1.0, # Add information to be passed to the searching function args['args'] = (target, model_builder, model_args, print_iterations, - print_output, guesses, results) + run_args, guesses, results) # Create a new dictionary with the arguments from args and kwargs args.update(kwargs) From f9027893dd6a75b3bace2c363d5144436a596ac5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 2 May 2022 22:07:56 -0500 Subject: [PATCH 0260/2654] Add test with large major radii (currently segfaults) --- .../torus/large_major/__init__.py | 0 .../torus/large_major/inputs_true.dat | 37 +++++++++++++++++ .../torus/large_major/results_true.dat | 3 ++ .../torus/large_major/test.py | 41 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 tests/regression_tests/torus/large_major/__init__.py create mode 100644 tests/regression_tests/torus/large_major/inputs_true.dat create mode 100644 tests/regression_tests/torus/large_major/results_true.dat create mode 100644 tests/regression_tests/torus/large_major/test.py diff --git a/tests/regression_tests/torus/large_major/__init__.py b/tests/regression_tests/torus/large_major/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/torus/large_major/inputs_true.dat b/tests/regression_tests/torus/large_major/inputs_true.dat new file mode 100644 index 000000000..ae3f72d0f --- /dev/null +++ b/tests/regression_tests/torus/large_major/inputs_true.dat @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + -1000.0 0 0 + + + + + + + flux + + diff --git a/tests/regression_tests/torus/large_major/results_true.dat b/tests/regression_tests/torus/large_major/results_true.dat new file mode 100644 index 000000000..cb9f54970 --- /dev/null +++ b/tests/regression_tests/torus/large_major/results_true.dat @@ -0,0 +1,3 @@ +tally 1: +9.675396E+02 +9.363406E+04 diff --git a/tests/regression_tests/torus/large_major/test.py b/tests/regression_tests/torus/large_major/test.py new file mode 100644 index 000000000..256716f4e --- /dev/null +++ b/tests/regression_tests/torus/large_major/test.py @@ -0,0 +1,41 @@ +import openmc +import pytest + +from tests.testing_harness import PyAPITestHarness + + +@pytest.fixture +def model(): + model = openmc.Model() + tungsten = openmc.Material() + tungsten.set_density('g/cm3', 1.0) + tungsten.add_nuclide('W184', 1.0) + ss = openmc.Material() + ss.set_density('g/cm3', 5.0) + ss.add_nuclide('Fe56', 1.0) + model.materials.extend([tungsten, ss]) + + # Create nested torii with very large major radii + R = 1000.0 + vacuum = openmc.ZTorus(a=R, b=30.0, c=30.0) + first_wall = openmc.ZTorus(a=R, b=35.0, c=35.0) + vessel = openmc.ZTorus(a=R, b=40.0, c=40.0, boundary_type='vacuum') + cell1 = openmc.Cell(region=-vacuum) + cell2 = openmc.Cell(fill=tungsten, region=+vacuum & -first_wall) + cell3 = openmc.Cell(fill=ss, region=+first_wall & -vessel) + model.geometry = openmc.Geometry([cell1, cell2, cell3]) + + model.settings.run_mode ='fixed source' + model.settings.particles = 1000 + model.settings.batches = 10 + model.settings.source = openmc.Source(space=openmc.stats.Point((-R, 0, 0,))) + + tally = openmc.Tally() + tally.scores = ['flux'] + model.tallies.append(tally) + return model + + +def test_torus_large_major(model): + harness = PyAPITestHarness('statepoint.10.h5', model) + harness.main() From 01f26d607143fa1b81cefadeb932d8457f7bab8a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 2 May 2022 22:09:06 -0500 Subject: [PATCH 0261/2654] Fix bug with torus distance when particle is coincident --- src/surface.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/surface.cpp b/src/surface.cpp index dbfa0bf3d..c0b3f0a59 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -1026,9 +1026,11 @@ double torus_distance(double x1, double x2, double x3, double u1, double u2, double c1p = 2 * four_A2 * (u1 * x1 + u2 * x2); double c0p = four_A2 * (x1 * x1 + x2 * x2); - // Coefficient for equation: a t^4 + b t^3 + c t^2 + d t + e = 0 + // Coefficient for equation: a t^4 + b t^3 + c t^2 + d t + e = 0. If the point + // is coincident, the 'e' coefficient should be zero. Explicitly setting it to + // zero helps avoid numerical issues below with root finding. double coeff[5]; - coeff[0] = c0 * c0 - c0p; + coeff[0] = coincident ? 0.0 : c0 * c0 - c0p; coeff[1] = 2 * c0 * c1 - c1p; coeff[2] = c1 * c1 + 2 * c0 * c2 - c2p; coeff[3] = 2 * c1 * c2; From 41ae16c032eb80c632a88505f520528ad6a3a721 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 3 May 2022 17:17:12 -0500 Subject: [PATCH 0262/2654] Allow for use of redundant fission when adjusting KERMA in from_njoy --- openmc/data/neutron.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py index 47ebfabf8..db78ce27b 100644 --- a/openmc/data/neutron.py +++ b/openmc/data/neutron.py @@ -877,7 +877,7 @@ class IncidentNeutron(EqualityMixin): if f is not None: # Replace fission KERMA with (EFR + EB)*sigma_f - fission = data.reactions[18].xs[temp] + fission = data[18].xs[temp] kerma_fission = get_file3_xs(ev, 318, E) kerma.y = kerma.y - kerma_fission + ( f.fragments(E) + f.betas(E)) * fission(E) From ef3019a140d7e9b511f7e09bfb029c2b1e1e4015 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 5 Apr 2022 12:49:48 -0500 Subject: [PATCH 0263/2654] Add merge classmethod on openmc.stats.Discrete --- openmc/stats/univariate.py | 31 +++++++++++++++++++++++++++++++ tests/unit_tests/test_stats.py | 23 +++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index f8e50044f..53b19713b 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -1,5 +1,7 @@ from abc import ABC, abstractmethod +from collections import defaultdict from collections.abc import Iterable +from functools import reduce from numbers import Real from xml.etree import ElementTree as ET @@ -156,6 +158,35 @@ class Discrete(Univariate): p = params[len(params)//2:] return cls(x, p) + @classmethod + def merge(cls, dists, probs): + """Merge multiple discrete distributions into a single distribution + + Parameters + ---------- + dists : iterable of openmc.stats.Discrete + Discrete distributions to combine + probs : iterable of float + Probability of each distribution + + Returns + ------- + openmc.stats.Discrete + Combined discrete distribution + + """ + # Combine distributions accounting for duplicate x values + x_merged = set() + p_merged = defaultdict(float) + for dist, p_dist in zip(dists, probs): + for x, p in zip(dist.x, dist.p): + x_merged.add(x) + p_merged[x] += p*p_dist + + # Create values and probabilities as arrays + x_arr = np.array(sorted(x_merged)) + p_arr = np.array([p_merged[x] for x in x_arr]) + return cls(x_arr, p_arr) class Uniform(Univariate): """Distribution with constant probability over a finite interval [a,b] diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index bbcb12ff1..51a561bd3 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -27,6 +27,29 @@ def test_discrete(): assert len(d2) == 1 +def test_merge_discrete(): + x1 = [0.0, 1.0, 10.0] + p1 = [0.3, 0.2, 0.5] + d1 = openmc.stats.Discrete(x1, p1) + + x2 = [0.5, 1.0, 5.0] + p2 = [0.4, 0.5, 0.1] + d2 = openmc.stats.Discrete(x2, p2) + + # Merged distribution should have x values sorted and probabilities + # appropriately combined. Duplicate x values should appear once. + merged = openmc.stats.Discrete.merge([d1, d2], [0.6, 0.4]) + assert merged.x == pytest.approx([0.0, 0.5, 1.0, 5.0, 10.0]) + assert merged.p == pytest.approx( + [0.6*0.3, 0.4*0.4, 0.6*0.2 + 0.4*0.5, 0.4*0.1, 0.6*0.5]) + + # Probabilities add up but are not normalized + d1 = openmc.stats.Discrete([3.0], [1.0]) + triple = openmc.stats.Discrete.merge([d1, d1, d1], [1.0, 2.0, 3.0]) + assert triple.x == pytest.approx([3.0]) + assert triple.p == pytest.approx([6.0]) + + def test_uniform(): a, b = 10.0, 20.0 d = openmc.stats.Uniform(a, b) From 6f1f42e5c5965ade345b0b0924cf725ad8d48bae Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 4 May 2022 07:05:10 -0500 Subject: [PATCH 0264/2654] Fix docstring for IsogonalOctagon (missing 'r' for raw) --- openmc/model/surface_composite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 74f64c54a..6271154fb 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -212,7 +212,7 @@ class CylinderSector(CompositeSurface): class IsogonalOctagon(CompositeSurface): - """Infinite isogonal octagon composite surface + r"""Infinite isogonal octagon composite surface An isogonal octagon is composed of eight planar surfaces. The prism is parallel to the x, y, or z axis. The remaining two axes (y and z, z and x, From cf665d076fa5d43cd157a70b73b48e7bf3648924 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 4 May 2022 12:34:04 -0500 Subject: [PATCH 0265/2654] Remove unused import in univariate.py Co-authored-by: Ethan Peterson --- openmc/stats/univariate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 53b19713b..c9f314793 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -1,7 +1,6 @@ from abc import ABC, abstractmethod from collections import defaultdict from collections.abc import Iterable -from functools import reduce from numbers import Real from xml.etree import ElementTree as ET From ee5697e8585700771c1e9e05994dfccd13d20df7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 5 May 2022 22:11:29 -0500 Subject: [PATCH 0266/2654] Add error message if user tries WMP + photon transport --- src/settings.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/settings.cpp b/src/settings.cpp index 795b164ec..e2bce94d7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -802,6 +802,12 @@ void read_settings_xml() } if (check_for_node(root, "temperature_multipole")) { temperature_multipole = get_node_value_bool(root, "temperature_multipole"); + + // Multipole currently doesn't work with photon transport + if (temperature_multipole && photon_transport) { + fatal_error("Multipole data cannot currently be used in conjunction with " + "photon transport."); + } } if (check_for_node(root, "temperature_range")) { auto range = get_node_array(root, "temperature_range"); From 806367c124dcab180cdc056e3ff69c5adaf6bfd1 Mon Sep 17 00:00:00 2001 From: cpf Date: Fri, 6 May 2022 10:19:16 +0200 Subject: [PATCH 0267/2654] Uniform distribution of cos(theta) in SphericalIndependent --- src/distribution_spatial.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 66430ddff..6a15992e1 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -172,10 +172,14 @@ Position SphericalIndependent::sample(uint64_t* seed) const { double r = r_->sample(seed); double theta = theta_->sample(seed); + // To distribute the points uniformly in the sphere, we must ensure that + // cos(theta) and not theta is uniformly distributed. + // This is done with theta_cos. + double theta_cos = std::acos((theta / (0.5 * PI)) - 1); double phi = phi_->sample(seed); - double x = r * sin(theta) * cos(phi) + origin_.x; - double y = r * sin(theta) * sin(phi) + origin_.y; - double z = r * cos(theta) + origin_.z; + double x = r * sin(theta_cos) * cos(phi) + origin_.x; + double y = r * sin(theta_cos) * sin(phi) + origin_.y; + double z = r * cos(theta_cos) + origin_.z; return {x, y, z}; } From baf35e74cad2c61ac1b4324f75002e1b63f90dcb Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Fri, 6 May 2022 06:29:27 -0500 Subject: [PATCH 0268/2654] Resolved versionadded/deprecated versions per @paulromano comments and fixed failing test: missed one legacy _hdf5_key in DelayedNuFissionMatrixXS! I guess that shows the new parameter works, so, yeah, totally on purpose --- openmc/mgxs/mdgxs.py | 30 ++++++++-------- openmc/mgxs/mgxs.py | 82 ++++++++++++++++++++++---------------------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index c59c8ff5c..ca8992212 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -124,12 +124,12 @@ class MDGXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -1012,12 +1012,12 @@ class ChiDelayed(MDGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -1536,12 +1536,12 @@ class DelayedNuFissionXS(MDGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -1680,12 +1680,12 @@ class Beta(MDGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -1878,12 +1878,12 @@ class DecayRate(MDGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -2196,12 +2196,12 @@ class MatrixMDGXS(MDGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -2800,12 +2800,12 @@ class DelayedNuFissionMatrixXS(MatrixMDGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -2815,6 +2815,6 @@ class DelayedNuFissionMatrixXS(MatrixMDGXS): super().__init__(domain, domain_type, energy_groups, delayed_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'delayed-nu-fission' - self._hdf5_key = 'delayed-nu-fission matrix' + self._mgxs_type = 'delayed-nu-fission matrix' self._estimator = 'analog' self._valid_estimators = ['analog'] diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index ff55b882a..4211e9fb7 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -241,12 +241,12 @@ class MGXS: The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -628,7 +628,7 @@ class MGXS: warnings.warn( f'The {type(self).__name__}.hdf5_key attribute will be removed ' f'in the future! Use {type(self).__name__}.mgxs_type instead', - DeprecationWarning) + FutureWarning) return self.mgxs_type @name.setter @@ -2258,12 +2258,12 @@ class MatrixMGXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @property @@ -2760,12 +2760,12 @@ class TotalXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -2906,12 +2906,12 @@ class TransportXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -3152,12 +3152,12 @@ class DiffusionCoefficient(TransportXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -3343,12 +3343,12 @@ class AbsorptionXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -3477,12 +3477,12 @@ class CaptureXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -3638,12 +3638,12 @@ class FissionXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -3814,12 +3814,12 @@ class KappaFissionXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -3953,12 +3953,12 @@ class ScatterXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -4105,12 +4105,12 @@ class ArbitraryXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -4245,12 +4245,12 @@ class ArbitraryMatrixXS(MatrixMGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -4455,12 +4455,12 @@ class ScatterMatrixXS(MatrixMGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -5550,12 +5550,12 @@ class MultiplicityMatrixXS(MatrixMGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -5731,12 +5731,12 @@ class ScatterProbabilityMatrix(MatrixMGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -5912,12 +5912,12 @@ class NuFissionMatrixXS(MatrixMGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -6078,12 +6078,12 @@ class Chi(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -6609,12 +6609,12 @@ class InverseVelocity(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ @@ -6736,12 +6736,12 @@ class MeshSurfaceMGXS(MGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ def __init__(self, domain=None, domain_type=None, energy_groups=None, @@ -7130,12 +7130,12 @@ class Current(MeshSurfaceMGXS): The name of this MGXS type, to be used when printing and indexing in an HDF5 data store - .. versionadded:: 0.14 + .. versionadded:: 0.13.1 hdf5_key : str The key used to index multi-group cross sections in an HDF5 data store. This will be replaced by mgxs_type in the future. - .. deprecated:: 0.13.0 + .. deprecated:: 0.13.1 """ def __init__(self, domain=None, domain_type=None, From 9888d9163bbb4f1f4acedc22de284c8afd7fa9b0 Mon Sep 17 00:00:00 2001 From: Hunter Belanger Date: Sat, 7 May 2022 11:57:32 +0200 Subject: [PATCH 0269/2654] Places configured version.h in source dir, for building with FetchContent --- .gitignore | 1 + CMakeLists.txt | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 88e59895d..b4ed5552f 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ src/CMakeFiles/ src/bin/ src/cmake_install.cmake src/install_manifest.txt +include/openmc/version.h # Nuclear data scripts/nndc diff --git a/CMakeLists.txt b/CMakeLists.txt index 28f917956..0e5063c39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(OPENMC_VERSION_MAJOR 0) set(OPENMC_VERSION_MINOR 13) set(OPENMC_VERSION_RELEASE 1) set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) -configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) +configure_file(include/openmc/version.h.in "${CMAKE_CURRENT_SOURCE_DIR}/include/openmc/version.h" @ONLY) # Setup output directories set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -495,4 +495,3 @@ install(FILES install(FILES man/man1/openmc.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) install(FILES LICENSE DESTINATION "${CMAKE_INSTALL_DOCDIR}" RENAME copyright) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(FILES "${CMAKE_BINARY_DIR}/include/openmc/version.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openmc) From 21930fa795fc443ccaf0d3f034cda314926a692f Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Mon, 9 May 2022 10:22:28 -0500 Subject: [PATCH 0270/2654] Removing hdf5_key, and thus not keeping it as a deprecated interface to mgxs_type --- openmc/mgxs/mdgxs.py | 35 -------------- openmc/mgxs/mgxs.py | 108 ------------------------------------------- 2 files changed, 143 deletions(-) diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index ca8992212..287a2961d 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -125,11 +125,6 @@ class MDGXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -1013,11 +1008,6 @@ class ChiDelayed(MDGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -1537,11 +1527,6 @@ class DelayedNuFissionXS(MDGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -1681,11 +1666,6 @@ class Beta(MDGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -1879,11 +1859,6 @@ class DecayRate(MDGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -2197,11 +2172,6 @@ class MatrixMDGXS(MDGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -2801,11 +2771,6 @@ class DelayedNuFissionMatrixXS(MatrixMDGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 4211e9fb7..453c1d099 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -242,11 +242,6 @@ class MGXS: indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -623,14 +618,6 @@ class MGXS: else: return self._rxn_type - @property - def hdf5_key(self): - warnings.warn( - f'The {type(self).__name__}.hdf5_key attribute will be removed ' - f'in the future! Use {type(self).__name__}.mgxs_type instead', - FutureWarning) - return self.mgxs_type - @name.setter def name(self, name): cv.check_type('name', name, str) @@ -2259,11 +2246,6 @@ class MatrixMGXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @property @@ -2761,11 +2743,6 @@ class TotalXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -2907,11 +2884,6 @@ class TransportXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -3153,11 +3125,6 @@ class DiffusionCoefficient(TransportXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -3344,11 +3311,6 @@ class AbsorptionXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -3478,11 +3440,6 @@ class CaptureXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -3639,11 +3596,6 @@ class FissionXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -3815,11 +3767,6 @@ class KappaFissionXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -3954,11 +3901,6 @@ class ScatterXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -4106,11 +4048,6 @@ class ArbitraryXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -4246,11 +4183,6 @@ class ArbitraryMatrixXS(MatrixMGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -4456,11 +4388,6 @@ class ScatterMatrixXS(MatrixMGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -5551,11 +5478,6 @@ class MultiplicityMatrixXS(MatrixMGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -5732,11 +5654,6 @@ class ScatterProbabilityMatrix(MatrixMGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -5913,11 +5830,6 @@ class NuFissionMatrixXS(MatrixMGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -6079,11 +5991,6 @@ class Chi(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -6610,11 +6517,6 @@ class InverseVelocity(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ @@ -6737,11 +6639,6 @@ class MeshSurfaceMGXS(MGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ def __init__(self, domain=None, domain_type=None, energy_groups=None, @@ -7131,11 +7028,6 @@ class Current(MeshSurfaceMGXS): indexing in an HDF5 data store .. versionadded:: 0.13.1 - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store. - This will be replaced by mgxs_type in the future. - - .. deprecated:: 0.13.1 """ def __init__(self, domain=None, domain_type=None, From 021215a2b9fc9194cf42dc152e7ca6246fac3c87 Mon Sep 17 00:00:00 2001 From: cpf Date: Mon, 9 May 2022 20:03:28 +0200 Subject: [PATCH 0271/2654] included paulromanos suggestions --- docs/source/io_formats/settings.rst | 7 ++++--- openmc/stats/multivariate.py | 24 ++++++++++++------------ src/distribution_spatial.cpp | 25 +++++++++++-------------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index d2c15c56f..a5cf36ece 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -490,9 +490,10 @@ attributes/sub-elements: independent distributions of r-, phi-, and z-coordinates where phi is the azimuthal angle and the origin for the cylindrical coordinate system is specified by origin. A "spherical" spatial distribution specifies - independent distributions of r-, theta-, and phi-coordinates where theta - is the angle with respect to the z-axis, phi is the azimuthal angle, and - the sphere is centered on the coordinate (x0,y0,z0). + independent distributions of r-, cos_theta-, and phi-coordinates where + cos_theta is the cosinus of the angle with respect to the z-axis, phi is + the azimuthal angle, and the sphere is centered on the coordinate + (x0,y0,z0). *Default*: None diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 8635bcd71..c1de22bb6 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -399,9 +399,9 @@ class SphericalIndependent(Spatial): ---------- r : openmc.stats.Univariate Distribution of r-coordinates in the local reference frame - theta : openmc.stats.Univariate - Distribution of theta-coordinates (angle relative to the z-axis) in the - local reference frame + cos_theta : openmc.stats.Univariate + Distribution of the cosinus of the theta-coordinates (angle relative to + the z-axis) in the local reference frame phi : openmc.stats.Univariate Distribution of phi-coordinates (azimuthal angle) in the local reference frame @@ -411,9 +411,9 @@ class SphericalIndependent(Spatial): """ - def __init__(self, r, theta, phi, origin=(0.0, 0.0, 0.0)): + def __init__(self, r, cos_theta, phi, origin=(0.0, 0.0, 0.0)): self.r = r - self.theta = theta + self.cos_theta = cos_theta self.phi = phi self.origin = origin @@ -422,8 +422,8 @@ class SphericalIndependent(Spatial): return self._r @property - def theta(self): - return self._theta + def cos_theta(self): + return self._cos_theta @property def phi(self): @@ -438,10 +438,10 @@ class SphericalIndependent(Spatial): cv.check_type('r coordinate', r, Univariate) self._r = r - @theta.setter - def theta(self, theta): - cv.check_type('theta coordinate', theta, Univariate) - self._theta = theta + @cos_theta.setter + def cos_theta(self, cos_theta): + cv.check_type('cos_theta coordinate', cos_theta, Univariate) + self._cos_theta = cos_theta @phi.setter def phi(self, phi): @@ -466,7 +466,7 @@ class SphericalIndependent(Spatial): element = ET.Element('space') element.set('type', 'spherical') element.append(self.r.to_xml_element('r')) - element.append(self.theta.to_xml_element('theta')) + element.append(self.cos_theta.to_xml_element('cos_theta')) element.append(self.phi.to_xml_element('phi')) element.set("origin", ' '.join(map(str, self.origin))) return element diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 6a15992e1..2542842c3 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -132,15 +132,15 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node) r_ = make_unique(x, p, 1); } - // Read distribution for theta-coordinate - if (check_for_node(node, "theta")) { - pugi::xml_node node_dist = node.child("theta"); - theta_ = distribution_from_xml(node_dist); + // Read distribution for cos_theta-coordinate + if (check_for_node(node, "cos_theta")) { + pugi::xml_node node_dist = node.child("cos_theta"); + cos_theta_ = distribution_from_xml(node_dist); } else { - // If no distribution was specified, default to a single point at theta=0 + // If no distribution was specified, default to a single point at cos_theta=0 double x[] {0.0}; double p[] {1.0}; - theta_ = make_unique(x, p, 1); + cos_theta_ = make_unique(x, p, 1); } // Read distribution for phi-coordinate @@ -171,15 +171,12 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node) Position SphericalIndependent::sample(uint64_t* seed) const { double r = r_->sample(seed); - double theta = theta_->sample(seed); - // To distribute the points uniformly in the sphere, we must ensure that - // cos(theta) and not theta is uniformly distributed. - // This is done with theta_cos. - double theta_cos = std::acos((theta / (0.5 * PI)) - 1); + double cos_theta = cos_theta_->sample(seed); double phi = phi_->sample(seed); - double x = r * sin(theta_cos) * cos(phi) + origin_.x; - double y = r * sin(theta_cos) * sin(phi) + origin_.y; - double z = r * cos(theta_cos) + origin_.z; + // sin(theta) by sin**2 + cos**2 = 1 + double x = r * std::pow(1 - std::pow(cos_theta, 2.0), 0.5) * cos(phi) + origin_.x; + double y = r * std::pow(1 - std::pow(cos_theta, 2.0), 0.5) * sin(phi) + origin_.y; + double z = r * cos_theta + origin_.z; return {x, y, z}; } From b9b119bc736b3802ff947bc39f79e9ca37978d50 Mon Sep 17 00:00:00 2001 From: cpf Date: Mon, 9 May 2022 20:09:28 +0200 Subject: [PATCH 0272/2654] changed theta to cos_theta in .h file --- include/openmc/distribution_spatial.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 9cceee184..5e426b878 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -70,7 +70,7 @@ private: }; //============================================================================== -//! Distribution of points specified by spherical coordinates r,theta,phi +//! Distribution of points specified by spherical coordinates r,cos_theta,phi //============================================================================== class SphericalIndependent : public SpatialDistribution { @@ -83,15 +83,15 @@ public: Position sample(uint64_t* seed) const; Distribution* r() const { return r_.get(); } - Distribution* theta() const { return theta_.get(); } + Distribution* cos_theta() const { return cos_theta_.get(); } Distribution* phi() const { return phi_.get(); } Position origin() const { return origin_; } private: - UPtrDist r_; //!< Distribution of r coordinates - UPtrDist theta_; //!< Distribution of theta coordinates - UPtrDist phi_; //!< Distribution of phi coordinates - Position origin_; //!< Cartesian coordinates of the sphere center + UPtrDist r_; //!< Distribution of r coordinates + UPtrDist cos_theta_; //!< Distribution of cos_theta coordinates + UPtrDist phi_; //!< Distribution of phi coordinates + Position origin_; //!< Cartesian coordinates of the sphere center }; //============================================================================== From 31648dd1a28cc7d4c7859dc35c6be509ef795487 Mon Sep 17 00:00:00 2001 From: cpf Date: Mon, 9 May 2022 20:23:18 +0200 Subject: [PATCH 0273/2654] some more theta -> cos_theta --- openmc/stats/multivariate.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index c1de22bb6..53ff06ad9 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -375,8 +375,8 @@ class SphericalIndependent(Spatial): r"""Spatial distribution represented in spherical coordinates. This distribution allows one to specify coordinates whose :math:`r`, - :math:`\theta`, and :math:`\phi` components are sampled independently from - one another and centered on the coordinates (x0, y0, z0). + :math:`\cos_theta`, and :math:`\phi` components are sampled independently + from one another and centered on the coordinates (x0, y0, z0). .. versionadded: 0.12 @@ -385,9 +385,9 @@ class SphericalIndependent(Spatial): r : openmc.stats.Univariate Distribution of r-coordinates in a reference frame specified by the origin parameter - theta : openmc.stats.Univariate - Distribution of theta-coordinates (angle relative to the z-axis) in a - reference frame specified by the origin parameter + cos_theta : openmc.stats.Univariate + Distribution of the cosinus of the theta-coordinates (angle relative to + the z-axis) in a reference frame specified by the origin parameter phi : openmc.stats.Univariate Distribution of phi-coordinates (azimuthal angle) in a reference frame specified by the origin parameter @@ -487,10 +487,10 @@ class SphericalIndependent(Spatial): """ r = Univariate.from_xml_element(elem.find('r')) - theta = Univariate.from_xml_element(elem.find('theta')) + cos_theta = Univariate.from_xml_element(elem.find('cos_theta')) phi = Univariate.from_xml_element(elem.find('phi')) origin = [float(x) for x in elem.get('origin').split()] - return cls(r, theta, phi, origin=origin) + return cls(r, cos_theta, phi, origin=origin) class CylindricalIndependent(Spatial): From 198eb76cab1e25a5a50c026cec9e520fd7ebead9 Mon Sep 17 00:00:00 2001 From: Hunter Belanger Date: Mon, 9 May 2022 21:20:08 +0200 Subject: [PATCH 0274/2654] Revert "Places configured version.h in source dir, for building with FetchContent" This reverts commit 9888d9163bbb4f1f4acedc22de284c8afd7fa9b0. --- .gitignore | 1 - CMakeLists.txt | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b4ed5552f..88e59895d 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,6 @@ src/CMakeFiles/ src/bin/ src/cmake_install.cmake src/install_manifest.txt -include/openmc/version.h # Nuclear data scripts/nndc diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e5063c39..28f917956 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(OPENMC_VERSION_MAJOR 0) set(OPENMC_VERSION_MINOR 13) set(OPENMC_VERSION_RELEASE 1) set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) -configure_file(include/openmc/version.h.in "${CMAKE_CURRENT_SOURCE_DIR}/include/openmc/version.h" @ONLY) +configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) # Setup output directories set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -495,3 +495,4 @@ install(FILES install(FILES man/man1/openmc.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) install(FILES LICENSE DESTINATION "${CMAKE_INSTALL_DOCDIR}" RENAME copyright) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(FILES "${CMAKE_BINARY_DIR}/include/openmc/version.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openmc) From bd3fe3a893fa91eabc8ff1e0f0990228697248f3 Mon Sep 17 00:00:00 2001 From: Hunter Belanger Date: Mon, 9 May 2022 21:22:19 +0200 Subject: [PATCH 0275/2654] Makes modification to build includes suggested by @paulromano --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28f917956..3f0d4807a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -394,7 +394,8 @@ target_include_directories(libopenmc target_compile_options(libopenmc PRIVATE ${cxxflags}) # Add include directory for configured version file -target_include_directories(libopenmc PRIVATE ${CMAKE_BINARY_DIR}/include) +target_include_directories(libopenmc + PUBLIC $) if (HDF5_IS_PARALLEL) target_compile_definitions(libopenmc PRIVATE -DPHDF5) From df30923a338561f3e8e5bcea6893f352b508c7b5 Mon Sep 17 00:00:00 2001 From: Hunter Belanger Date: Mon, 9 May 2022 21:47:06 +0200 Subject: [PATCH 0276/2654] Adds include guards to version.h.in --- include/openmc/version.h.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index 2933746e2..e1c2b0541 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -1,3 +1,6 @@ +#ifndef OPENMC_VERSION_H +#define OPENMC_VERSION_H + #include "openmc/array.h" namespace openmc { @@ -12,3 +15,5 @@ constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELE // clang-format on } // namespace openmc + +#endif // OPENMC_VERSION_H From 8ec37d80d22d4d8ea1fc25caa29c96086397cf46 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Tue, 10 May 2022 09:17:01 +0200 Subject: [PATCH 0277/2654] Update docs/source/io_formats/settings.rst Co-authored-by: Paul Romano --- docs/source/io_formats/settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index a5cf36ece..1a8f63716 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -491,7 +491,7 @@ attributes/sub-elements: azimuthal angle and the origin for the cylindrical coordinate system is specified by origin. A "spherical" spatial distribution specifies independent distributions of r-, cos_theta-, and phi-coordinates where - cos_theta is the cosinus of the angle with respect to the z-axis, phi is + cos_theta is the cosine of the angle with respect to the z-axis, phi is the azimuthal angle, and the sphere is centered on the coordinate (x0,y0,z0). From 6ba42d2cc436d6ee285c1a2a12fcf12971bbbbb4 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Tue, 10 May 2022 09:17:23 +0200 Subject: [PATCH 0278/2654] Update openmc/stats/multivariate.py Co-authored-by: Paul Romano --- openmc/stats/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 53ff06ad9..e0de89a56 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -386,7 +386,7 @@ class SphericalIndependent(Spatial): Distribution of r-coordinates in a reference frame specified by the origin parameter cos_theta : openmc.stats.Univariate - Distribution of the cosinus of the theta-coordinates (angle relative to + Distribution of the cosine of the theta-coordinates (angle relative to the z-axis) in a reference frame specified by the origin parameter phi : openmc.stats.Univariate Distribution of phi-coordinates (azimuthal angle) in a reference frame From 06d85de2c32ff8581e41e9251d022242ed217025 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Tue, 10 May 2022 09:17:34 +0200 Subject: [PATCH 0279/2654] Update openmc/stats/multivariate.py Co-authored-by: Paul Romano --- openmc/stats/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index e0de89a56..42cbc74c6 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -375,7 +375,7 @@ class SphericalIndependent(Spatial): r"""Spatial distribution represented in spherical coordinates. This distribution allows one to specify coordinates whose :math:`r`, - :math:`\cos_theta`, and :math:`\phi` components are sampled independently + :math:`\theta`, and :math:`\phi` components are sampled independently from one another and centered on the coordinates (x0, y0, z0). .. versionadded: 0.12 From 31ebeb13275868c085e599eac4d22a0afe4826aa Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Tue, 10 May 2022 09:17:40 +0200 Subject: [PATCH 0280/2654] Update openmc/stats/multivariate.py Co-authored-by: Paul Romano --- openmc/stats/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 42cbc74c6..6c41bfbbd 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -400,7 +400,7 @@ class SphericalIndependent(Spatial): r : openmc.stats.Univariate Distribution of r-coordinates in the local reference frame cos_theta : openmc.stats.Univariate - Distribution of the cosinus of the theta-coordinates (angle relative to + Distribution of the cosine of the theta-coordinates (angle relative to the z-axis) in the local reference frame phi : openmc.stats.Univariate Distribution of phi-coordinates (azimuthal angle) in the local From 9073aa5f72998ea40e137ccaa3a236f789866662 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Tue, 10 May 2022 09:17:50 +0200 Subject: [PATCH 0281/2654] Update src/distribution_spatial.cpp Co-authored-by: Paul Romano --- src/distribution_spatial.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 2542842c3..a06f84d80 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -174,8 +174,8 @@ Position SphericalIndependent::sample(uint64_t* seed) const double cos_theta = cos_theta_->sample(seed); double phi = phi_->sample(seed); // sin(theta) by sin**2 + cos**2 = 1 - double x = r * std::pow(1 - std::pow(cos_theta, 2.0), 0.5) * cos(phi) + origin_.x; - double y = r * std::pow(1 - std::pow(cos_theta, 2.0), 0.5) * sin(phi) + origin_.y; + double x = r * std::sqrt(1 - cos_theta * cos_theta) * cos(phi) + origin_.x; + double y = r * std::sqrt(1 - cos_theta * cos_theta) * sin(phi) + origin_.y; double z = r * cos_theta + origin_.z; return {x, y, z}; } From a8f1d476620fbf0ffec62ab33d6c50f6c3ea9829 Mon Sep 17 00:00:00 2001 From: cpf Date: Tue, 10 May 2022 15:40:37 +0200 Subject: [PATCH 0282/2654] added a spherical source as a helping class --- openmc/stats/multivariate.py | 139 ++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 3 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 6c41bfbbd..22b1a8bba 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -208,7 +208,6 @@ class Monodirectional(UnitSphere): """ - def __init__(self, reference_uvw=[1., 0., 0.]): super().__init__(reference_uvw) @@ -272,6 +271,8 @@ class Spatial(ABC): return SphericalIndependent.from_xml_element(elem) elif distribution == 'box' or distribution == 'fission': return Box.from_xml_element(elem) + elif distribution == 'sphericalshell': + return SphericalShell.from_xml_element(elem) elif distribution == 'point': return Point.from_xml_element(elem) @@ -375,7 +376,7 @@ class SphericalIndependent(Spatial): r"""Spatial distribution represented in spherical coordinates. This distribution allows one to specify coordinates whose :math:`r`, - :math:`\theta`, and :math:`\phi` components are sampled independently + :math:`\cos_theta`, and :math:`\phi` components are sampled independently from one another and centered on the coordinates (x0, y0, z0). .. versionadded: 0.12 @@ -640,7 +641,6 @@ class Box(Spatial): """ - def __init__(self, lower_left, upper_right, only_fissionable=False): self.lower_left = lower_left self.upper_right = upper_right @@ -779,3 +779,136 @@ class Point(Spatial): """ xyz = [float(x) for x in get_text(elem, 'parameters').split()] return cls(xyz) + + +class SphericalShell(Spatial): + r"""Spatial distribution for points in a spherical shell. + + This distribution is a helper that creates points uniformly distributed in + a spherical shell using the class SphericalIndependent. + + It allows one to sample points independly in a spherical shell, specified + by (r1, r2), (theta1, theta2), (phi1, phi2) centered on the coordinates + (x0, y0, z0). + + .. versionadded: 0.13 + + Parameters + ---------- + radii : Iterable of float + Inner radius r1 and outer radius r2 of the spherical shell. + thetas : Iterable of float + Start theta1 and end theta2 of the theta-coordinates (angle relative to + the z-axis) in a reference frame specified by the origin parameter + phis : Iterable of float + Start phi1 and end phi2 of the phi-coordinates (azimuthal angle) in a + reference frame specified by the origin parameter + origin: Iterable of float, optional + coordinates (x0, y0, z0) of the center of the spherical reference frame + for the source. Defaults to (0.0, 0.0, 0.0) + + Attributes + ---------- + radii : Iterable of float + Inner radius r1 and outer radius r2 of the spherical shell. + thetas : Iterable of float + Start theta1 and end theta2 of the theta-coordinates (angle relative to + the z-axis) in a reference frame specified by the origin parameter + phis : Iterable of float + Start phi1 and end phi2 of the phi-coordinates (azimuthal angle) in a + reference frame specified by the origin parameter + origin: Iterable of float, optional + coordinates (x0, y0, z0) of the center of the spherical reference frame + for the source. Defaults to (0.0, 0.0, 0.0) + + """ + + def __init__(self, radii, thetas, phis, origin=(0.0, 0.0, 0.0)): + self.radii = radii + self.thetas = thetas + self.phis = phis + self.origin = origin + + @property + def radii(self): + return self._radii + + @property + def thetas(self): + return self._thetas + + @property + def phis(self): + return self._phis + + @property + def origin(self): + return self._origin + + @radii.setter + def radii(self, radii): + cv.check_type('radii values', radii, Iterable, Real) + self._radii = radii + + @thetas.setter + def thetas(self, thetas): + cv.check_type('thetas values', thetas, Iterable, Real) + self._thetas = thetas + + @phis.setter + def phis(self, phis): + cv.check_type('phis values', phis, Iterable, Real) + self._phis = phis + + @origin.setter + def origin(self, origin): + cv.check_type('origin coordinates', origin, Iterable, Real) + origin = np.asarray(origin) + self._origin = origin + + def to_xml_element(self): + """Return XML representation of the spatial distribution + + Returns + ------- + element : xml.etree.ElementTree.Element + XML element containing spatial distribution data + + """ + element = ET.Element('space') + element.set('type', 'spherical') + sub_element_radii = ET.SubElement(element, 'r') + # the 2.0 is necessary to define the radius in the power law + sub_element_radii.set('parameters', ' '.join(map(str, self.radii))+' 2.0') + sub_element_radii.set('type', 'powerlaw') + sub_element_thetas = ET.SubElement(element, 'cos_theta') + # the sphericalIndependent class takes the arccos of theta + cos_thetas = np.cos(self.thetas) + sub_element_thetas.set('parameters', ' '.join(map(str, cos_thetas))) + sub_element_thetas.set('type', 'uniform') + sub_element_phis = ET.SubElement(element, 'phi') + sub_element_phis.set('parameters', ' '.join(map(str, self.phis))) + sub_element_phis.set('type', 'uniform') + element.set('origin', ' '.join(map(str, self.origin))) + return element + + @classmethod + def from_xml_element(cls, elem): + """Generate spatial distribution from an XML element + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + XML element + + Returns + ------- + openmc.stats.SphericalIndependent + Spatial distribution generated from XML element + + """ + r = Univariate.from_xml_element(elem.find('r')) + cos_theta = Univariate.from_xml_element(elem.find('cos_theta')) + phi = Univariate.from_xml_element(elem.find('phi')) + origin = [float(x) for x in elem.get('origin').split()] + return cls(r, cos_theta, phi, origin=origin) From 178adb084319827c09e7ceac76368a1da829adc1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 11 May 2022 14:47:07 -0500 Subject: [PATCH 0283/2654] Consistency check in Discrete.merge method --- openmc/stats/univariate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index c9f314793..e4a9b8f92 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -174,6 +174,9 @@ class Discrete(Univariate): Combined discrete distribution """ + if len(dists) != len(probs): + raise ValueError("Number of distributions and probabilities must match.") + # Combine distributions accounting for duplicate x values x_merged = set() p_merged = defaultdict(float) From fc454abcd1a98dd796623f16dc6d32b4fce7aa63 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 12 May 2022 13:18:53 -0500 Subject: [PATCH 0284/2654] updated conda install to specify using mamba instead --- docs/source/quickinstall.rst | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index e3138a53b..f3225191e 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -8,13 +8,15 @@ This quick install guide outlines the basic steps needed to install OpenMC on your computer. For more detailed instructions on configuring and installing OpenMC, see :ref:`usersguide_install` in the User's Manual. ----------------------------------------- -Installing on Linux/Mac with conda-forge ----------------------------------------- +-------------------------------------------------- +Installing on Linux/Mac with Mamba and conda-forge +-------------------------------------------------- -`Conda `_ is an open source package management -system and environment management system for installing multiple versions of -software packages and their dependencies and switching easily between them. If +`Conda `_ and `Mamba `_ +are an open source package management systems and environments management +system for installing multiple versions of software packages and their +dependencies and switching easily between them. +All conda packages can be installed with If you have `conda` installed on your system, OpenMC can be installed via the `conda-forge` channel. First, add the `conda-forge` channel with: @@ -22,6 +24,12 @@ you have `conda` installed on your system, OpenMC can be installed via the conda config --add channels conda-forge +Then install `mamba`, which will later be used to install OpenMC in the conda environment. + +.. code-block:: sh + + conda install mamba + To list the versions of OpenMC that are available on the `conda-forge` channel, in your terminal window or an Anaconda Prompt run: @@ -33,7 +41,7 @@ OpenMC can then be installed with: .. code-block:: sh - conda create -n openmc-env openmc + mamba create -n openmc-env openmc This will install OpenMC in a conda environment called `openmc-env`. To activate the environment, run: @@ -42,6 +50,10 @@ the environment, run: conda activate openmc-env +.. note:: If you are already familiar with conda for package management, + please note that OpenMC is currently only supported to be installed + with `mamba` and not `conda` (ie, `conda install openmc` may not work). + ------------------------------------------- Installing on Linux/Mac/Windows with Docker ------------------------------------------- From ea74bf0e4ae30819299fcaa9e6ea08fdd83d3683 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 12 May 2022 13:20:40 -0500 Subject: [PATCH 0285/2654] typo --- docs/source/quickinstall.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index f3225191e..cd848d395 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -15,9 +15,8 @@ Installing on Linux/Mac with Mamba and conda-forge `Conda `_ and `Mamba `_ are an open source package management systems and environments management system for installing multiple versions of software packages and their -dependencies and switching easily between them. -All conda packages can be installed with If -you have `conda` installed on your system, OpenMC can be installed via the +dependencies and switching easily between them. If you have `conda` installed +on your system, OpenMC can be installed via the `conda-forge` channel. First, add the `conda-forge` channel with: .. code-block:: sh From d8dc09e3153a860523134b566a3a1ec728948fc2 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 12 May 2022 13:29:00 -0500 Subject: [PATCH 0286/2654] mamba create -n opemnc actually still uses conda install, so updated to make it two different steps to avoid failure --- docs/source/quickinstall.rst | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index cd848d395..57ff2b479 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -34,20 +34,22 @@ in your terminal window or an Anaconda Prompt run: .. code-block:: sh - conda search openmc + mamba search openmc + +First create and activate a new conda enviroment called `openmc-env` in which to install OpenMC. + +.. code-block:: sh + + conda create -n openmc-env + conda activate openmc-env OpenMC can then be installed with: .. code-block:: sh - mamba create -n openmc-env openmc + mamba install openmc -This will install OpenMC in a conda environment called `openmc-env`. To activate -the environment, run: - -.. code-block:: sh - - conda activate openmc-env +You are now in a conda environment called `openmc-env` that has OpenMC installed. .. note:: If you are already familiar with conda for package management, please note that OpenMC is currently only supported to be installed From 0ba342c88475300998542266f66476e49f420321 Mon Sep 17 00:00:00 2001 From: cpf Date: Fri, 13 May 2022 21:14:44 +0200 Subject: [PATCH 0287/2654] Define function spherical_uniform instead of class SphericalIndependent --- openmc/stats/multivariate.py | 121 +++-------------------------------- 1 file changed, 10 insertions(+), 111 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 22b1a8bba..67337f2d6 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -8,7 +8,7 @@ import numpy as np import openmc.checkvalue as cv from .._xml import get_text -from .univariate import Univariate, Uniform +from .univariate import Univariate, Uniform, PowerLaw class UnitSphere(ABC): @@ -271,8 +271,6 @@ class Spatial(ABC): return SphericalIndependent.from_xml_element(elem) elif distribution == 'box' or distribution == 'fission': return Box.from_xml_element(elem) - elif distribution == 'sphericalshell': - return SphericalShell.from_xml_element(elem) elif distribution == 'point': return Point.from_xml_element(elem) @@ -781,11 +779,11 @@ class Point(Spatial): return cls(xyz) -class SphericalShell(Spatial): - r"""Spatial distribution for points in a spherical shell. - - This distribution is a helper that creates points uniformly distributed in - a spherical shell using the class SphericalIndependent. +def spherical_uniform(r_outer, r_inner=0.0, thetas=(0., pi), phis=(0., 2*pi), + origin=(0., 0., 0.)): + r""" + This function is a helper that makes it easier to create points uniformly + distributed in a spherical shell using the class SphericalIndependent. It allows one to sample points independly in a spherical shell, specified by (r1, r2), (theta1, theta2), (phi1, phi2) centered on the coordinates @@ -806,109 +804,10 @@ class SphericalShell(Spatial): origin: Iterable of float, optional coordinates (x0, y0, z0) of the center of the spherical reference frame for the source. Defaults to (0.0, 0.0, 0.0) - - Attributes - ---------- - radii : Iterable of float - Inner radius r1 and outer radius r2 of the spherical shell. - thetas : Iterable of float - Start theta1 and end theta2 of the theta-coordinates (angle relative to - the z-axis) in a reference frame specified by the origin parameter - phis : Iterable of float - Start phi1 and end phi2 of the phi-coordinates (azimuthal angle) in a - reference frame specified by the origin parameter - origin: Iterable of float, optional - coordinates (x0, y0, z0) of the center of the spherical reference frame - for the source. Defaults to (0.0, 0.0, 0.0) - """ - def __init__(self, radii, thetas, phis, origin=(0.0, 0.0, 0.0)): - self.radii = radii - self.thetas = thetas - self.phis = phis - self.origin = origin + r_dist = PowerLaw(r_inner, r_outer, 2) + cos_thetas_dist = Uniform(np.cos(thetas[0]), np.cos(thetas[1])) + phis_dist = Uniform(phis[0], phis[1]) - @property - def radii(self): - return self._radii - - @property - def thetas(self): - return self._thetas - - @property - def phis(self): - return self._phis - - @property - def origin(self): - return self._origin - - @radii.setter - def radii(self, radii): - cv.check_type('radii values', radii, Iterable, Real) - self._radii = radii - - @thetas.setter - def thetas(self, thetas): - cv.check_type('thetas values', thetas, Iterable, Real) - self._thetas = thetas - - @phis.setter - def phis(self, phis): - cv.check_type('phis values', phis, Iterable, Real) - self._phis = phis - - @origin.setter - def origin(self, origin): - cv.check_type('origin coordinates', origin, Iterable, Real) - origin = np.asarray(origin) - self._origin = origin - - def to_xml_element(self): - """Return XML representation of the spatial distribution - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing spatial distribution data - - """ - element = ET.Element('space') - element.set('type', 'spherical') - sub_element_radii = ET.SubElement(element, 'r') - # the 2.0 is necessary to define the radius in the power law - sub_element_radii.set('parameters', ' '.join(map(str, self.radii))+' 2.0') - sub_element_radii.set('type', 'powerlaw') - sub_element_thetas = ET.SubElement(element, 'cos_theta') - # the sphericalIndependent class takes the arccos of theta - cos_thetas = np.cos(self.thetas) - sub_element_thetas.set('parameters', ' '.join(map(str, cos_thetas))) - sub_element_thetas.set('type', 'uniform') - sub_element_phis = ET.SubElement(element, 'phi') - sub_element_phis.set('parameters', ' '.join(map(str, self.phis))) - sub_element_phis.set('type', 'uniform') - element.set('origin', ' '.join(map(str, self.origin))) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate spatial distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.SphericalIndependent - Spatial distribution generated from XML element - - """ - r = Univariate.from_xml_element(elem.find('r')) - cos_theta = Univariate.from_xml_element(elem.find('cos_theta')) - phi = Univariate.from_xml_element(elem.find('phi')) - origin = [float(x) for x in elem.get('origin').split()] - return cls(r, cos_theta, phi, origin=origin) + return SphericalIndependent(r_dist, cos_thetas_dist, phis_dist, origin) From 0def5bf655944af815ce6c73af22be5cffd10997 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Sat, 14 May 2022 09:08:54 +0200 Subject: [PATCH 0288/2654] Update openmc/stats/multivariate.py Co-authored-by: Paul Romano --- openmc/stats/multivariate.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 67337f2d6..1649d45a1 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -781,15 +781,13 @@ class Point(Spatial): def spherical_uniform(r_outer, r_inner=0.0, thetas=(0., pi), phis=(0., 2*pi), origin=(0., 0., 0.)): - r""" - This function is a helper that makes it easier to create points uniformly - distributed in a spherical shell using the class SphericalIndependent. + """Return a uniform spatial distribution over a spherical shell. - It allows one to sample points independly in a spherical shell, specified - by (r1, r2), (theta1, theta2), (phi1, phi2) centered on the coordinates - (x0, y0, z0). + This function provides a uniform spatial distribution over a spherical + shell between `r_inner` and `r_outer`. Optionally, the range of angles + can be restricted by the `thetas` and `phis` arguments. - .. versionadded: 0.13 + .. versionadded: 0.13.1 Parameters ---------- From 7bcad5e7b6948c841cb155190698a4449efff447 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Sat, 14 May 2022 09:09:21 +0200 Subject: [PATCH 0289/2654] Update openmc/stats/multivariate.py Co-authored-by: Paul Romano --- openmc/stats/multivariate.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 1649d45a1..bbd11a15e 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -791,17 +791,24 @@ def spherical_uniform(r_outer, r_inner=0.0, thetas=(0., pi), phis=(0., 2*pi), Parameters ---------- - radii : Iterable of float - Inner radius r1 and outer radius r2 of the spherical shell. - thetas : Iterable of float - Start theta1 and end theta2 of the theta-coordinates (angle relative to - the z-axis) in a reference frame specified by the origin parameter - phis : Iterable of float - Start phi1 and end phi2 of the phi-coordinates (azimuthal angle) in a - reference frame specified by the origin parameter - origin: Iterable of float, optional - coordinates (x0, y0, z0) of the center of the spherical reference frame - for the source. Defaults to (0.0, 0.0, 0.0) + r_outer : float + Outer radius of the spherical shell in [cm] + r_inner : float, optional + Inner radius of the spherical shell in [cm] + thetas : iterable of float, optional + Starting and ending theta coordinates (angle relative to + the z-axis) in radius in a reference frame centered at `origin` + phis : iterable of float, optional + Starting and ending phi coordinates (azimuthal angle) in + radians in a reference frame centered at `origin` + origin: iterable of float, optional + Coordinates (x0, y0, z0) of the center of the spherical + reference frame for the distribution. + + Returns + ------- + openmc.stats.SphericalIndependent + Uniform distribution over the spherical shell """ r_dist = PowerLaw(r_inner, r_outer, 2) From 6806f73bd43d36bb6cb378de69d90b6eef8c828c Mon Sep 17 00:00:00 2001 From: cpf Date: Sat, 14 May 2022 09:12:07 +0200 Subject: [PATCH 0290/2654] missing import --- openmc/stats/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index bbd11a15e..56f682056 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -1,6 +1,6 @@ from abc import ABC, abstractmethod from collections.abc import Iterable -from math import pi +from math import pi, cos from numbers import Real from xml.etree import ElementTree as ET From dba3a0be2f128792bcd20936e67f52c819b32389 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 14 May 2022 18:44:57 -0500 Subject: [PATCH 0291/2654] Err msg for missing DAGMC file --- src/dagmc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 9b894d3bb..8131c9929 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -50,6 +50,9 @@ DAGUniverse::DAGUniverse(pugi::xml_node node) if (check_for_node(node, "filename")) { filename_ = get_node_value(node, "filename"); + if (!file_exists(filename_)) { + fatal_error(fmt::format("DAGMC file '{}' could not be found", filename_)); + } } else { fatal_error("Must specify a file for the DAGMC universe"); } From 8b62ee36350a9ed5c813a1583c0382ae28f3758e Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Mon, 16 May 2022 14:38:46 +0200 Subject: [PATCH 0292/2654] Update openmc/stats/multivariate.py Co-authored-by: Paul Romano --- openmc/stats/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 56f682056..228bdf9ea 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -812,7 +812,7 @@ def spherical_uniform(r_outer, r_inner=0.0, thetas=(0., pi), phis=(0., 2*pi), """ r_dist = PowerLaw(r_inner, r_outer, 2) - cos_thetas_dist = Uniform(np.cos(thetas[0]), np.cos(thetas[1])) + cos_thetas_dist = Uniform(cos(thetas[1]), cos(thetas[0])) phis_dist = Uniform(phis[0], phis[1]) return SphericalIndependent(r_dist, cos_thetas_dist, phis_dist, origin) From 44d591ff48ffe3cde7a758290a396c4ba741e7c4 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Mon, 16 May 2022 14:39:28 +0200 Subject: [PATCH 0293/2654] Update openmc/stats/multivariate.py Co-authored-by: Paul Romano --- openmc/stats/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 228bdf9ea..98c76ea67 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -374,7 +374,7 @@ class SphericalIndependent(Spatial): r"""Spatial distribution represented in spherical coordinates. This distribution allows one to specify coordinates whose :math:`r`, - :math:`\cos_theta`, and :math:`\phi` components are sampled independently + :math:`\theta`, and :math:`\phi` components are sampled independently from one another and centered on the coordinates (x0, y0, z0). .. versionadded: 0.12 From 4efb74317951f13571867d97f9171dbe3a59ebab Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 16 May 2022 11:29:14 -0500 Subject: [PATCH 0294/2654] reorder mamba install instructions --- docs/source/quickinstall.rst | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index 57ff2b479..db2d464b3 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -17,13 +17,22 @@ are an open source package management systems and environments management system for installing multiple versions of software packages and their dependencies and switching easily between them. If you have `conda` installed on your system, OpenMC can be installed via the -`conda-forge` channel. First, add the `conda-forge` channel with: +`conda-forge` channel. + +First, add the `conda-forge` channel with: .. code-block:: sh conda config --add channels conda-forge -Then install `mamba`, which will later be used to install OpenMC in the conda environment. +Then create and activate a new conda enviroment called `openmc-env` in which to install OpenMC. + +.. code-block:: sh + + conda create -n openmc-env + conda activate openmc-env + +Then install `mamba`, which will be used to install OpenMC. .. code-block:: sh @@ -36,13 +45,6 @@ in your terminal window or an Anaconda Prompt run: mamba search openmc -First create and activate a new conda enviroment called `openmc-env` in which to install OpenMC. - -.. code-block:: sh - - conda create -n openmc-env - conda activate openmc-env - OpenMC can then be installed with: .. code-block:: sh @@ -51,10 +53,6 @@ OpenMC can then be installed with: You are now in a conda environment called `openmc-env` that has OpenMC installed. -.. note:: If you are already familiar with conda for package management, - please note that OpenMC is currently only supported to be installed - with `mamba` and not `conda` (ie, `conda install openmc` may not work). - ------------------------------------------- Installing on Linux/Mac/Windows with Docker ------------------------------------------- From 3a44e1fce9bff829d759865c1f79c0e5a435f086 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 16 May 2022 11:39:40 -0500 Subject: [PATCH 0295/2654] more details on mamba vs conda --- docs/source/quickinstall.rst | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index db2d464b3..81a442f47 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -12,12 +12,17 @@ OpenMC, see :ref:`usersguide_install` in the User's Manual. Installing on Linux/Mac with Mamba and conda-forge -------------------------------------------------- -`Conda `_ and `Mamba `_ -are an open source package management systems and environments management -system for installing multiple versions of software packages and their -dependencies and switching easily between them. If you have `conda` installed -on your system, OpenMC can be installed via the -`conda-forge` channel. +`Conda `_ is an open source package management +systems and environments management system for installing multiple versions of +software packages and their dependencies and switching easily between them. +`Mamba `_ is a cross-platform package +manager and is compatible with `conda` packages. +OpenMC can be installed in a `conda` environment with `mamba`. +First, `conda` should be installed with one of the following installers: +`Miniconda `_, +`Anaconda `_, or `Miniforge `_. +Once you have `conda` installed on your system, OpenMC can be installed via the +`conda-forge` channel with `mamba`. First, add the `conda-forge` channel with: @@ -25,7 +30,8 @@ First, add the `conda-forge` channel with: conda config --add channels conda-forge -Then create and activate a new conda enviroment called `openmc-env` in which to install OpenMC. +Then create and activate a new conda enviroment called `openmc-env` in +which to install OpenMC. .. code-block:: sh From 2b779091daabc71a982727fb9d482f5611588ae0 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 16 May 2022 11:41:03 -0500 Subject: [PATCH 0296/2654] update same info in install.rst --- docs/source/usersguide/install.rst | 49 ++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 3e3f7754a..d05c00bb3 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -8,39 +8,56 @@ Installation and Configuration .. _install_conda: ----------------------------------------- -Installing on Linux/Mac with conda-forge ----------------------------------------- +-------------------------------------------------- +Installing on Linux/Mac with Mamba and conda-forge +-------------------------------------------------- -Conda_ is an open source package management system and environment management -system for installing multiple versions of software packages and their -dependencies and switching easily between them. If you have `conda` installed on -your system, OpenMC can be installed via the `conda-forge` channel. First, add -the `conda-forge` channel with: +`Conda `_ is an open source package management +systems and environments management system for installing multiple versions of +software packages and their dependencies and switching easily between them. +`Mamba `_ is a cross-platform package +manager and is compatible with `conda` packages. +OpenMC can be installed in a `conda` environment with `mamba`. +First, `conda` should be installed with one of the following installers: +`Miniconda `_, +`Anaconda `_, or `Miniforge `_. +Once you have `conda` installed on your system, OpenMC can be installed via the +`conda-forge` channel with `mamba`. + +First, add the `conda-forge` channel with: .. code-block:: sh conda config --add channels conda-forge +Then create and activate a new conda enviroment called `openmc-env` in +which to install OpenMC. + +.. code-block:: sh + + conda create -n openmc-env + conda activate openmc-env + +Then install `mamba`, which will be used to install OpenMC. + +.. code-block:: sh + + conda install mamba + To list the versions of OpenMC that are available on the `conda-forge` channel, in your terminal window or an Anaconda Prompt run: .. code-block:: sh - conda search openmc + mamba search openmc OpenMC can then be installed with: .. code-block:: sh - conda create -n openmc-env openmc + mamba install openmc -This will install OpenMC in a conda environment called `openmc-env`. To activate -the environment, run: - -.. code-block:: sh - - conda activate openmc-env +You are now in a conda environment called `openmc-env` that has OpenMC installed. ------------------------------------------- Installing on Linux/Mac/Windows with Docker From a6bd42ee8ebaf4d317da79c5e7770c99f5db58b4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 12 May 2022 12:45:20 -0500 Subject: [PATCH 0297/2654] Expand Particle::tracks_ to include full state --- include/openmc/particle_data.h | 21 ++++++++++++++++++++- src/particle_data.cpp | 18 ++++++++++++++++++ src/track_output.cpp | 8 ++++---- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index ddf072517..8c1f4deab 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -56,6 +56,18 @@ struct SourceSite { int64_t progeny_id; }; +//! State of a particle used for particle track files +struct TrackState { + Position r; + Direction u; + double E; + double time {0.0}; + double wgt {1.0}; + int cell_id; + int material_id {-1}; + ParticleType particle; +}; + //! Saved ("banked") state of a particle, for nu-fission tallying struct NuBank { double E; //!< particle energy @@ -290,7 +302,7 @@ private: vector filter_matches_; // tally filter matches - vector> tracks_; // tracks for outputting to file + vector> tracks_; // tracks for outputting to file vector nu_bank_; // bank of most recently fissioned particles @@ -342,6 +354,9 @@ public: const LocalCoord& coord(int i) const { return coord_[i]; } const vector& coord() const { return coord_; } + LocalCoord& lowest_coord() { return coord_[n_coord_ - 1]; } + const LocalCoord& lowest_coord() const { return coord_[n_coord_ - 1]; } + int& n_coord_last() { return n_coord_last_; } const int& n_coord_last() const { return n_coord_last_; } int& cell_last(int i) { return cell_last_[i]; } @@ -357,6 +372,7 @@ public: const int& g_last() const { return g_last_; } double& wgt() { return wgt_; } + double wgt() const { return wgt_; } double& mu() { return mu_; } const double& mu() const { return mu_; } double& time() { return time_; } @@ -479,6 +495,9 @@ public: n_coord_ = 1; } + //! Get track information based on particle's current state + TrackState get_track_state() const; + void zero_delayed_bank() { for (int& n : n_delayed_bank_) { diff --git a/src/particle_data.cpp b/src/particle_data.cpp index 701e6cbc0..be34fbc9b 100644 --- a/src/particle_data.cpp +++ b/src/particle_data.cpp @@ -1,6 +1,8 @@ #include "openmc/particle_data.h" +#include "openmc/cell.h" #include "openmc/geometry.h" +#include "openmc/material.h" #include "openmc/nuclide.h" #include "openmc/photon.h" #include "openmc/settings.h" @@ -53,4 +55,20 @@ ParticleData::ParticleData() photon_xs_.resize(data::elements.size()); } +TrackState ParticleData::get_track_state() const +{ + TrackState state; + state.r = this->r(); + state.u = this->u(); + state.E = this->E(); + state.time = this->time(); + state.wgt = this->wgt(); + state.cell_id = model::cells[this->lowest_coord().cell]->id_; + if (this->material() != MATERIAL_VOID) { + state.material_id = model::materials[material()]->id_; + } + state.particle = this->type(); + return state; +} + } // namespace openmc diff --git a/src/track_output.cpp b/src/track_output.cpp index 065c2d465..7d4dff124 100644 --- a/src/track_output.cpp +++ b/src/track_output.cpp @@ -30,7 +30,7 @@ void add_particle_track(Particle& p) void write_particle_track(Particle& p) { - p.tracks().back().push_back(p.r()); + p.tracks().back().push_back(p.get_track_state()); } void finalize_particle_track(Particle& p) @@ -57,9 +57,9 @@ void finalize_particle_track(Particle& p) size_t n = t.size(); xt::xtensor data({n, 3}); for (int j = 0; j < n; ++j) { - data(j, 0) = t[j].x; - data(j, 1) = t[j].y; - data(j, 2) = t[j].z; + data(j, 0) = t[j].r.x; + data(j, 1) = t[j].r.y; + data(j, 2) = t[j].r.z; } std::string name = fmt::format("coordinates_{}", i); write_dataset(file_id, name.c_str(), data); From 8b270dd59b465e88f41f75a7f9864c23e8f72353 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 12 May 2022 17:17:20 -0500 Subject: [PATCH 0298/2654] Change track file format to include all information --- scripts/openmc-track-to-vtk | 24 +++----- src/track_output.cpp | 65 ++++++++++++++++----- tests/regression_tests/track_output/test.py | 1 - 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index 3c781d19e..d1b2f828a 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -4,9 +4,7 @@ """ -import os import argparse -import struct import h5py import vtk @@ -38,28 +36,24 @@ def main(): # Initialize data arrays and offset. points = vtk.vtkPoints() cells = vtk.vtkCellArray() - point_offset = 0 for fname in args.input: # Write coordinate values to points array. track = h5py.File(fname) - n_particles = track.attrs['n_particles'] - n_coords = track.attrs['n_coords'] - coords = [] - for i in range(n_particles): - coords.append(track['coordinates_' + str(i + 1)][()]) - for j in range(n_coords[i]): - points.InsertNextPoint(coords[i][j,:]) + offsets = track.attrs['offsets'] + for start, end in zip(offsets[:-1], offsets[1:]): + tracks = track['tracks'][start:end] + for arr in tracks: + points.InsertNextPoint(arr['r']) - for i in range(n_particles): + for start, end in zip(offsets[:-1], offsets[1:]): # Create VTK line and assign points to line. line = vtk.vtkPolyLine() - line.GetPointIds().SetNumberOfIds(n_coords[i]) - for j in range(n_coords[i]): - line.GetPointIds().SetId(j, point_offset + j) + line.GetPointIds().SetNumberOfIds(end - start) + for j in range(end - start): + line.GetPointIds().SetId(j, start + j) # Add line to cell array cells.InsertNextCell(line) - point_offset += n_coords[i] data = vtk.vtkPolyData() data.SetPoints(points) diff --git a/src/track_output.cpp b/src/track_output.cpp index 7d4dff124..3d04a73ba 100644 --- a/src/track_output.cpp +++ b/src/track_output.cpp @@ -33,6 +33,31 @@ void write_particle_track(Particle& p) p.tracks().back().push_back(p.get_track_state()); } +hid_t trackstate_type() +{ + // Create compound type for Position + hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(struct Position)); + H5Tinsert(postype, "x", HOFFSET(Position, x), H5T_NATIVE_DOUBLE); + H5Tinsert(postype, "y", HOFFSET(Position, y), H5T_NATIVE_DOUBLE); + H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE); + + // Create compound type for TrackState + hid_t tracktype = H5Tcreate(H5T_COMPOUND, sizeof(struct TrackState)); + H5Tinsert(tracktype, "r", HOFFSET(TrackState, r), postype); + H5Tinsert(tracktype, "u", HOFFSET(TrackState, u), postype); + H5Tinsert(tracktype, "E", HOFFSET(TrackState, E), H5T_NATIVE_DOUBLE); + H5Tinsert(tracktype, "time", HOFFSET(TrackState, time), H5T_NATIVE_DOUBLE); + H5Tinsert(tracktype, "wgt", HOFFSET(TrackState, wgt), H5T_NATIVE_DOUBLE); + H5Tinsert(tracktype, "cell_id", HOFFSET(TrackState, cell_id), H5T_NATIVE_INT); + H5Tinsert( + tracktype, "material_id", HOFFSET(TrackState, material_id), H5T_NATIVE_INT); + H5Tinsert( + tracktype, "particle", HOFFSET(TrackState, particle), H5T_NATIVE_INT); + + H5Tclose(postype); + return tracktype; +} + void finalize_particle_track(Particle& p) { std::string filename = @@ -40,10 +65,15 @@ void finalize_particle_track(Particle& p) simulation::current_batch, simulation::current_gen, p.id()); // Determine number of coordinates for each particle - vector n_coords; - for (auto& coords : p.tracks()) { - n_coords.push_back(coords.size()); + vector offsets; + vector tracks; + int offset = 0; + for (auto& track_i : p.tracks()) { + offsets.push_back(offset); + offset += track_i.size(); + tracks.insert(tracks.end(), track_i.begin(), track_i.end()); } + offsets.push_back(offset); #pragma omp critical(FinalizeParticleTrack) { @@ -51,19 +81,22 @@ void finalize_particle_track(Particle& p) write_attribute(file_id, "filetype", "track"); write_attribute(file_id, "version", VERSION_TRACK); write_attribute(file_id, "n_particles", p.tracks().size()); - write_attribute(file_id, "n_coords", n_coords); - for (auto i = 1; i <= p.tracks().size(); ++i) { - const auto& t {p.tracks()[i - 1]}; - size_t n = t.size(); - xt::xtensor data({n, 3}); - for (int j = 0; j < n; ++j) { - data(j, 0) = t[j].r.x; - data(j, 1) = t[j].r.y; - data(j, 2) = t[j].r.z; - } - std::string name = fmt::format("coordinates_{}", i); - write_dataset(file_id, name.c_str(), data); - } + write_attribute(file_id, "offsets", offsets); + + // Create HDF5 datatype for TrackState + hid_t track_type = trackstate_type(); + + // Write array of TrackState to file + hsize_t dims[] {static_cast(tracks.size())}; + hid_t dspace = H5Screate_simple(1, dims, nullptr); + hid_t dset = H5Dcreate(file_id, "tracks", track_type, dspace, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dset, track_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, tracks.data()); + + // Free resources + H5Dclose(dset); + H5Sclose(dspace); + H5Tclose(track_type); file_close(file_id); } diff --git a/tests/regression_tests/track_output/test.py b/tests/regression_tests/track_output/test.py index a5300a4ae..1501d3fd6 100644 --- a/tests/regression_tests/track_output/test.py +++ b/tests/regression_tests/track_output/test.py @@ -1,7 +1,6 @@ import glob import os from subprocess import call -import shutil import pytest From 452a24c8ce78aea4f4d02e55a92bb2930b524960 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 May 2022 07:17:15 -0500 Subject: [PATCH 0299/2654] Fix writing final position of each particle to track file --- src/particle.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/particle.cpp b/src/particle.cpp index b622a4d69..78139079e 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -337,6 +337,11 @@ void Particle::event_revive_from_secondary() // Check for secondary particles if this particle is dead if (!alive()) { + // Write final position for this particle + if (write_track()) { + write_particle_track(*this); + } + // If no secondary particles, break out of event loop if (secondary_bank().empty()) return; @@ -359,7 +364,6 @@ void Particle::event_death() // Finish particle track output. if (write_track()) { - write_particle_track(*this); finalize_particle_track(*this); } From b32d4b5ed3b82b25d5f86cb22b0aaf079ae35f10 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 May 2022 07:18:34 -0500 Subject: [PATCH 0300/2654] Write particle types separately for track files --- include/openmc/particle_data.h | 7 ++++++- src/particle_data.cpp | 1 - src/track_output.cpp | 12 +++++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 8c1f4deab..3e6c8515c 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -65,7 +65,12 @@ struct TrackState { double wgt {1.0}; int cell_id; int material_id {-1}; +}; + +//! Full history of a single particle's track states +struct TrackStateHistory { ParticleType particle; + std::vector states; }; //! Saved ("banked") state of a particle, for nu-fission tallying @@ -302,7 +307,7 @@ private: vector filter_matches_; // tally filter matches - vector> tracks_; // tracks for outputting to file + vector tracks_; // tracks for outputting to file vector nu_bank_; // bank of most recently fissioned particles diff --git a/src/particle_data.cpp b/src/particle_data.cpp index be34fbc9b..4206d9cd9 100644 --- a/src/particle_data.cpp +++ b/src/particle_data.cpp @@ -67,7 +67,6 @@ TrackState ParticleData::get_track_state() const if (this->material() != MATERIAL_VOID) { state.material_id = model::materials[material()]->id_; } - state.particle = this->type(); return state; } diff --git a/src/track_output.cpp b/src/track_output.cpp index 3d04a73ba..5a7aff834 100644 --- a/src/track_output.cpp +++ b/src/track_output.cpp @@ -26,11 +26,12 @@ namespace openmc { void add_particle_track(Particle& p) { p.tracks().emplace_back(); + p.tracks().back().particle = p.type(); } void write_particle_track(Particle& p) { - p.tracks().back().push_back(p.get_track_state()); + p.tracks().back().states.push_back(p.get_track_state()); } hid_t trackstate_type() @@ -51,8 +52,6 @@ hid_t trackstate_type() H5Tinsert(tracktype, "cell_id", HOFFSET(TrackState, cell_id), H5T_NATIVE_INT); H5Tinsert( tracktype, "material_id", HOFFSET(TrackState, material_id), H5T_NATIVE_INT); - H5Tinsert( - tracktype, "particle", HOFFSET(TrackState, particle), H5T_NATIVE_INT); H5Tclose(postype); return tracktype; @@ -66,12 +65,14 @@ void finalize_particle_track(Particle& p) // Determine number of coordinates for each particle vector offsets; + vector particles; vector tracks; int offset = 0; for (auto& track_i : p.tracks()) { offsets.push_back(offset); - offset += track_i.size(); - tracks.insert(tracks.end(), track_i.begin(), track_i.end()); + particles.push_back(static_cast(track_i.particle)); + offset += track_i.states.size(); + tracks.insert(tracks.end(), track_i.states.begin(), track_i.states.end()); } offsets.push_back(offset); @@ -82,6 +83,7 @@ void finalize_particle_track(Particle& p) write_attribute(file_id, "version", VERSION_TRACK); write_attribute(file_id, "n_particles", p.tracks().size()); write_attribute(file_id, "offsets", offsets); + write_attribute(file_id, "particles", particles); // Create HDF5 datatype for TrackState hid_t track_type = trackstate_type(); From 2e9560a72c8a606cc1199aca4232780358169629 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 May 2022 12:04:20 -0500 Subject: [PATCH 0301/2654] Add TrackFile Python class for parsing track files --- docs/source/pythonapi/base.rst | 1 + openmc/__init__.py | 1 + openmc/source.py | 4 ++ openmc/trackfile.py | 72 ++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 openmc/trackfile.py diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index b471d12a8..fdd89b844 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -187,6 +187,7 @@ Post-processing openmc.Particle openmc.StatePoint openmc.Summary + openmc.TrackFile The following classes and functions are used for functional expansion reconstruction. diff --git a/openmc/__init__.py b/openmc/__init__.py index 0a11fbf53..91af25a5f 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -30,6 +30,7 @@ from openmc.mixin import * from openmc.plotter import * from openmc.search import * from openmc.polynomial import * +from openmc.trackfile import * from . import examples # Import a few names from the model module diff --git a/openmc/source.py b/openmc/source.py index 1abe01f65..572333e37 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -298,6 +298,10 @@ class SourceParticle: self.surf_id = surf_id self.particle = particle + def __repr__(self): + name = self.particle.name.lower() + return f'' + def to_tuple(self): """Return source particle attributes as a tuple diff --git a/openmc/trackfile.py b/openmc/trackfile.py new file mode 100644 index 000000000..ab2b81a54 --- /dev/null +++ b/openmc/trackfile.py @@ -0,0 +1,72 @@ +from collections import namedtuple + +import h5py + +from .source import SourceParticle, ParticleType + + +TrackHistory = namedtuple('TrackHistory', ['particle', 'states']) + + +class TrackFile: + """Particle track output + + Parameters + ---------- + filepath : str or pathlib.Path + Path of file to load + + Attributes + ---------- + sources : list + List of :class:`SourceParticle` representing each primary/secondary + particle + tracks : list + List of tuples containing (particle type, array of track states) + + """ + + def __init__(self, filepath): + # Read data from track file + with h5py.File(filepath, 'r') as fh: + offsets = fh.attrs['offsets'] + tracks = fh['tracks'][()] + particles = fh.attrs['particles'] + + # Construct list of track histories + tracks_list = [] + for particle, start, end in zip(particles, offsets[:-1], offsets[1:]): + ptype = ParticleType(particle) + tracks_list.append(TrackHistory(ptype, tracks[start:end])) + self.tracks = tracks_list + + def __repr__(self): + return f'' + + def plot(self): + """Produce a 3D plot of particle tracks""" + import matplotlib.pyplot as plt + fig = plt.figure() + ax = plt.axes(projection='3d') + for _, states in self.tracks: + r = states['r'] + ax.plot3D(r['x'], r['y'], r['z']) + ax.set_xlabel('x [cm]') + ax.set_ylabel('y [cm]') + ax.set_zlabel('z [cm]') + plt.show() + + @property + def sources(self): + sources = [] + for track_history in self.tracks: + particle_type = ParticleType(track_history.particle) + state = track_history.states[0] + sources.append( + SourceParticle( + r=state['r'], u=state['u'], E=state['E'], + time=state['time'], wgt=state['wgt'], + particle=particle_type + ) + ) + return sources From 365aa0b0eb187210666c1f946d4cbbd89b3f0289 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 May 2022 07:33:55 -0400 Subject: [PATCH 0302/2654] Write all tracks to a single file --- docs/source/pythonapi/base.rst | 1 + include/openmc/track_output.h | 17 +++++++++ openmc/trackfile.py | 65 ++++++++++++++++++++++++--------- scripts/openmc-track-to-vtk | 33 ++++++++--------- src/simulation.cpp | 10 ++++++ src/track_output.cpp | 66 +++++++++++++++++++--------------- 6 files changed, 130 insertions(+), 62 deletions(-) diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index fdd89b844..a54d2ff35 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -187,6 +187,7 @@ Post-processing openmc.Particle openmc.StatePoint openmc.Summary + openmc.Track openmc.TrackFile The following classes and functions are used for functional expansion reconstruction. diff --git a/include/openmc/track_output.h b/include/openmc/track_output.h index fc65a2eaa..c4641af2b 100644 --- a/include/openmc/track_output.h +++ b/include/openmc/track_output.h @@ -9,8 +9,25 @@ namespace openmc { // Non-member functions //============================================================================== +//! Open HDF5 track file for writing and create track datatype +void open_track_file(); + +//! Close HDF5 resources for track file +void close_track_file(); + +//! Create a new track state history for a primary/secondary particle +// +//! \param[in] p Current particle void add_particle_track(Particle& p); + +//! Store particle's current state +// +//! \param[in] p Current particle void write_particle_track(Particle& p); + +//! Write full particle state history to HDF5 track file +// +//! \param[in] p Current particle void finalize_particle_track(Particle& p); } // namespace openmc diff --git a/openmc/trackfile.py b/openmc/trackfile.py index ab2b81a54..4eaa72f4d 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -5,50 +5,57 @@ import h5py from .source import SourceParticle, ParticleType -TrackHistory = namedtuple('TrackHistory', ['particle', 'states']) +ParticleTrack = namedtuple('ParticleTrack', ['particle', 'states']) -class TrackFile: - """Particle track output +def _identifier(dset_name): + """Return (batch, gen, particle) tuple given dataset name""" + _, batch, gen, particle = dset_name.split('_') + return (int(batch), int(gen), int(particle)) + + +class Track: + """Tracks resulting from a single source particle Parameters ---------- - filepath : str or pathlib.Path - Path of file to load + dset : h5py.Dataset + Dataset to read track data from Attributes ---------- + identifier : tuple + Tuple of (batch, generation, particle number) + particles : list + List of tuples containing (particle type, array of track states) sources : list List of :class:`SourceParticle` representing each primary/secondary particle - tracks : list - List of tuples containing (particle type, array of track states) """ - def __init__(self, filepath): - # Read data from track file - with h5py.File(filepath, 'r') as fh: - offsets = fh.attrs['offsets'] - tracks = fh['tracks'][()] - particles = fh.attrs['particles'] + def __init__(self, dset): + tracks = dset[()] + offsets = dset.attrs['offsets'] + particles = dset.attrs['particles'] + self.identifier = _identifier(dset.name) # Construct list of track histories tracks_list = [] for particle, start, end in zip(particles, offsets[:-1], offsets[1:]): ptype = ParticleType(particle) - tracks_list.append(TrackHistory(ptype, tracks[start:end])) - self.tracks = tracks_list + tracks_list.append(ParticleTrack(ptype, tracks[start:end])) + self.particles = tracks_list def __repr__(self): - return f'' + return f'' def plot(self): """Produce a 3D plot of particle tracks""" import matplotlib.pyplot as plt fig = plt.figure() ax = plt.axes(projection='3d') - for _, states in self.tracks: + for _, states in self.particles: r = states['r'] ax.plot3D(r['x'], r['y'], r['z']) ax.set_xlabel('x [cm]') @@ -70,3 +77,27 @@ class TrackFile: ) ) return sources + + +class TrackFile(list): + """Collection of particle tracks + + Parameters + ---------- + filepath : str or pathlib.Path + Path of file to load + + Attributes + ---------- + tracks : list + List of :class:`Track` objects + + """ + + def __init__(self, filepath): + # Read data from track file + with h5py.File(filepath, 'r') as fh: + + for dset_name in sorted(fh, key=_identifier): + dset = fh[dset_name] + self.append(Track(dset)) diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index d1b2f828a..7959ad35d 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -6,14 +6,14 @@ import argparse -import h5py +import openmc import vtk def _parse_args(): # Create argument parser. parser = argparse.ArgumentParser( - description='Convert particle track file to a .pvtp file.') + description='Convert particle track file(s) to a .pvtp file.') parser.add_argument('input', metavar='IN', type=str, nargs='+', help='Input particle track data filename(s).') parser.add_argument('-o', '--out', metavar='OUT', type=str, dest='out', @@ -36,24 +36,25 @@ def main(): # Initialize data arrays and offset. points = vtk.vtkPoints() cells = vtk.vtkCellArray() + point_offset = 0 for fname in args.input: # Write coordinate values to points array. - track = h5py.File(fname) - offsets = track.attrs['offsets'] - for start, end in zip(offsets[:-1], offsets[1:]): - tracks = track['tracks'][start:end] - for arr in tracks: - points.InsertNextPoint(arr['r']) + track_file = openmc.TrackFile(fname) + for track in track_file: + for particle in track.particles: + for state in particle.states: + points.InsertNextPoint(state['r']) - for start, end in zip(offsets[:-1], offsets[1:]): - # Create VTK line and assign points to line. - line = vtk.vtkPolyLine() - line.GetPointIds().SetNumberOfIds(end - start) - for j in range(end - start): - line.GetPointIds().SetId(j, start + j) + # Create VTK line and assign points to line. + n = particle.states.size + line = vtk.vtkPolyLine() + line.GetPointIds().SetNumberOfIds(n) + for i in range(n): + line.GetPointIds().SetId(i, point_offset + i) + point_offset += n - # Add line to cell array - cells.InsertNextCell(line) + # Add line to cell array + cells.InsertNextCell(line) data = vtk.vtkPolyData() data.SetPoints(points) diff --git a/src/simulation.cpp b/src/simulation.cpp index b7f5b58f1..728de8a85 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -82,6 +82,11 @@ int openmc_simulation_init() // Allocate source, fission and surface source banks. allocate_banks(); + // Create track file if needed + if (!settings::track_identifiers.empty() || settings::write_all_tracks) { + open_track_file(); + } + // If doing an event-based simulation, intialize the particle buffer // and event queues if (settings::event_based) { @@ -152,6 +157,11 @@ int openmc_simulation_finalize() mat->mat_nuclide_index_.clear(); } + // Close track file if open + if (!settings::track_identifiers.empty() || settings::write_all_tracks) { + close_track_file(); + } + // Increment total number of generations simulation::total_gen += simulation::current_batch * settings::gen_per_batch; diff --git a/src/track_output.cpp b/src/track_output.cpp index 5a7aff834..c75468b1f 100644 --- a/src/track_output.cpp +++ b/src/track_output.cpp @@ -9,6 +9,7 @@ #include "xtensor/xtensor.hpp" #include +#include #include // for size_t #include @@ -19,6 +20,9 @@ namespace openmc { // Global variables //============================================================================== +hid_t track_file; //! HDF5 identifier for track file +hid_t track_dtype; //! HDF5 identifier for track datatype + //============================================================================== // Non-member functions //============================================================================== @@ -34,8 +38,14 @@ void write_particle_track(Particle& p) p.tracks().back().states.push_back(p.get_track_state()); } -hid_t trackstate_type() +void open_track_file() { + // Open file and write filetype/version + std::string filename = fmt::format("{}tracks.h5", settings::path_output); + track_file = file_open(filename, 'w'); + write_attribute(track_file, "filetype", "track"); + write_attribute(track_file, "version", VERSION_TRACK); + // Create compound type for Position hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(struct Position)); H5Tinsert(postype, "x", HOFFSET(Position, x), H5T_NATIVE_DOUBLE); @@ -43,26 +53,27 @@ hid_t trackstate_type() H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE); // Create compound type for TrackState - hid_t tracktype = H5Tcreate(H5T_COMPOUND, sizeof(struct TrackState)); - H5Tinsert(tracktype, "r", HOFFSET(TrackState, r), postype); - H5Tinsert(tracktype, "u", HOFFSET(TrackState, u), postype); - H5Tinsert(tracktype, "E", HOFFSET(TrackState, E), H5T_NATIVE_DOUBLE); - H5Tinsert(tracktype, "time", HOFFSET(TrackState, time), H5T_NATIVE_DOUBLE); - H5Tinsert(tracktype, "wgt", HOFFSET(TrackState, wgt), H5T_NATIVE_DOUBLE); - H5Tinsert(tracktype, "cell_id", HOFFSET(TrackState, cell_id), H5T_NATIVE_INT); + track_dtype = H5Tcreate(H5T_COMPOUND, sizeof(struct TrackState)); + H5Tinsert(track_dtype, "r", HOFFSET(TrackState, r), postype); + H5Tinsert(track_dtype, "u", HOFFSET(TrackState, u), postype); + H5Tinsert(track_dtype, "E", HOFFSET(TrackState, E), H5T_NATIVE_DOUBLE); + H5Tinsert(track_dtype, "time", HOFFSET(TrackState, time), H5T_NATIVE_DOUBLE); + H5Tinsert(track_dtype, "wgt", HOFFSET(TrackState, wgt), H5T_NATIVE_DOUBLE); H5Tinsert( - tracktype, "material_id", HOFFSET(TrackState, material_id), H5T_NATIVE_INT); - + track_dtype, "cell_id", HOFFSET(TrackState, cell_id), H5T_NATIVE_INT); + H5Tinsert(track_dtype, "material_id", HOFFSET(TrackState, material_id), + H5T_NATIVE_INT); H5Tclose(postype); - return tracktype; +} + +void close_track_file() +{ + H5Tclose(track_dtype); + file_close(track_file); } void finalize_particle_track(Particle& p) { - std::string filename = - fmt::format("{}track_{}_{}_{}.h5", settings::path_output, - simulation::current_batch, simulation::current_gen, p.id()); - // Determine number of coordinates for each particle vector offsets; vector particles; @@ -78,28 +89,25 @@ void finalize_particle_track(Particle& p) #pragma omp critical(FinalizeParticleTrack) { - hid_t file_id = file_open(filename, 'w'); - write_attribute(file_id, "filetype", "track"); - write_attribute(file_id, "version", VERSION_TRACK); - write_attribute(file_id, "n_particles", p.tracks().size()); - write_attribute(file_id, "offsets", offsets); - write_attribute(file_id, "particles", particles); - - // Create HDF5 datatype for TrackState - hid_t track_type = trackstate_type(); + // Create name for dataset + std::string dset_name = fmt::format("track_{}_{}_{}", + simulation::current_batch, simulation::current_gen, p.id()); // Write array of TrackState to file hsize_t dims[] {static_cast(tracks.size())}; hid_t dspace = H5Screate_simple(1, dims, nullptr); - hid_t dset = H5Dcreate(file_id, "tracks", track_type, dspace, H5P_DEFAULT, - H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dset, track_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, tracks.data()); + hid_t dset = H5Dcreate(track_file, dset_name.c_str(), track_dtype, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dset, track_dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, tracks.data()); + + // Write attributes + write_attribute(dset, "n_particles", p.tracks().size()); + write_attribute(dset, "offsets", offsets); + write_attribute(dset, "particles", particles); // Free resources H5Dclose(dset); H5Sclose(dspace); - H5Tclose(track_type); - file_close(file_id); } // Clear particle tracks From b7415162793f5d502ea57562cd8830a00b2f3b6c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 May 2022 07:50:36 -0400 Subject: [PATCH 0303/2654] Add plot method for TrackFile --- openmc/trackfile.py | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 4eaa72f4d..38b777cf6 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -50,18 +50,33 @@ class Track: def __repr__(self): return f'' - def plot(self): - """Produce a 3D plot of particle tracks""" + def plot(self, axes=None): + """Produce a 3D plot of particle tracks + + Parameters + ---------- + axes : matplotlib.pyplot.Axes, optional + Axes for plot + """ import matplotlib.pyplot as plt - fig = plt.figure() - ax = plt.axes(projection='3d') + + # Setup axes is one wasn't passed + if axes is None: + fig = plt.figure() + ax = plt.axes(projection='3d') + ax.set_xlabel('x [cm]') + ax.set_ylabel('y [cm]') + ax.set_zlabel('z [cm]') + else: + ax = axes + + # Plot each particle track for _, states in self.particles: r = states['r'] ax.plot3D(r['x'], r['y'], r['z']) - ax.set_xlabel('x [cm]') - ax.set_ylabel('y [cm]') - ax.set_zlabel('z [cm]') - plt.show() + + if axes is None: + plt.show() @property def sources(self): @@ -101,3 +116,11 @@ class TrackFile(list): for dset_name in sorted(fh, key=_identifier): dset = fh[dset_name] self.append(Track(dset)) + + def plot(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = plt.axes(projection='3d') + for track in self: + track.plot(ax) + plt.show() From b786ad4c9ffe1fd9e5a5f7e967477261ebd318a0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 May 2022 09:33:57 -0400 Subject: [PATCH 0304/2654] Write separate track files for multiple MPI ranks --- docs/source/usersguide/scripts.rst | 11 +++++++++ scripts/openmc-track-combine | 37 ++++++++++++++++++++++++++++++ src/track_output.cpp | 13 ++++++++++- 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100755 scripts/openmc-track-combine diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst index 963e91cf2..f38e1fd16 100644 --- a/docs/source/usersguide/scripts.rst +++ b/docs/source/usersguide/scripts.rst @@ -114,6 +114,17 @@ tallies. The path to the statepoint file can be provided as an optional arugment .. _scripts_track: +------------------------ +``openmc-track-combine`` +------------------------ + +This script combines multiple HDF5 :ref:`particle track files +` into a single HDF5 particle track file. The filenames of the +particle track files should be given as posititional arguments. The output +filename can also be changed with the ``-o`` flag: + +-o OUT, --out OUT Output HDF5 particle track file + ----------------------- ``openmc-track-to-vtk`` ----------------------- diff --git a/scripts/openmc-track-combine b/scripts/openmc-track-combine new file mode 100755 index 000000000..4bd2fb082 --- /dev/null +++ b/scripts/openmc-track-combine @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +"""Combine multiple HDF5 particle track files. + +""" + +import argparse + +import h5py + + +def main(): + # Parse command-line arguments + parser = argparse.ArgumentParser( + description='Combine particle track files into a single .h5 file.') + parser.add_argument('input', metavar='IN', nargs='+', + help='Input HDF5 particle track filename(s).') + parser.add_argument('-o', '--out', metavar='OUT', default='tracks.h5', + help='Output HDF5 particle track file.') + + args = parser.parse_args() + + with h5py.File(args.out, 'w') as h5_out: + for i, fname in enumerate(args.input): + with h5py.File(fname, 'r') as h5_in: + # Copy file attributes for first file + if i == 0: + h5_out.attrs['filetype'] = h5_in.attrs['filetype'] + h5_out.attrs['version'] = h5_in.attrs['version'] + + # Copy each 'track_*' dataset from input file + for dset in h5_in: + h5_in.copy(dset, h5_out) + + +if __name__ == '__main__': + main() diff --git a/src/track_output.cpp b/src/track_output.cpp index c75468b1f..a5d4e6c2f 100644 --- a/src/track_output.cpp +++ b/src/track_output.cpp @@ -2,6 +2,7 @@ #include "openmc/constants.h" #include "openmc/hdf5_interface.h" +#include "openmc/message_passing.h" #include "openmc/position.h" #include "openmc/settings.h" #include "openmc/simulation.h" @@ -40,8 +41,18 @@ void write_particle_track(Particle& p) void open_track_file() { - // Open file and write filetype/version + // Open file and write filetype/version -- when MPI is enabled and there is + // more than one rank, each rank writes its own file +#ifdef OPENMC_MPI + std::string filename; + if (mpi::n_procs > 1) { + filename = fmt::format("{}tracks_p{}.h5", settings::path_output, mpi::rank); + } else { + filename = fmt::format("{}tracks.h5", settings::path_output); + } +#else std::string filename = fmt::format("{}tracks.h5", settings::path_output); +#endif track_file = file_open(filename, 'w'); write_attribute(track_file, "filetype", "track"); write_attribute(track_file, "version", VERSION_TRACK); From 93e7471132f70b18e18ffd3f2bac9c1aadadd081 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 May 2022 12:54:44 -0400 Subject: [PATCH 0305/2654] Update io_formats documentation for track files (and file version) --- docs/source/io_formats/track.rst | 23 ++++++++++++++++------- include/openmc/constants.h | 2 +- openmc/trackfile.py | 6 ++++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/docs/source/io_formats/track.rst b/docs/source/io_formats/track.rst index c617cd73e..113f0cf14 100644 --- a/docs/source/io_formats/track.rst +++ b/docs/source/io_formats/track.rst @@ -4,18 +4,27 @@ Track File Format ================= -The current revision of the particle track file format is 2.0. +The current revision of the particle track file format is 3.0. **/** :Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - **version** (*int[2]*) -- Major and minor version of the track file format. - - **n_particles** (*int*) -- Number of particles for which tracks - are recorded. - - **n_coords** (*int[]*) -- Number of coordinates for each - particle. :Datasets: - - **coordinates_** (*double[][3]*) -- (x,y,z) coordinates for the - *i*-th particle. + - **track___

** (Compound type) -- Particle track information + for source particle in batch *b*, generation *g*, and particle + number *p*. particle. The compound type has fields ``r``, ``u``, + ``E``, ``time``, ``wgt``, ``cell_id``, and ``material_id``, which + represent the position (each coordinate in [cm]), direction, energy + in [eV], time in [s], weight, cell ID, and material ID, + respectively. + + :Attributes: - **n_particles** (*int*) -- Number of + primary/secondary particles for the source history. + - **offsets** (*int[]*) Offset into the array for each + primary/secondary particle. + - **particles** (*int[]*) -- Particle type for each + primary/secondary particle (0=neutron, 1=photon, + 2=electron, 3=positron). diff --git a/include/openmc/constants.h b/include/openmc/constants.h index 8427c2d55..73f96ff95 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -26,7 +26,7 @@ constexpr int HDF5_VERSION[] {3, 0}; // Version numbers for binary files constexpr array VERSION_STATEPOINT {17, 0}; constexpr array VERSION_PARTICLE_RESTART {2, 0}; -constexpr array VERSION_TRACK {2, 0}; +constexpr array VERSION_TRACK {3, 0}; constexpr array VERSION_SUMMARY {6, 0}; constexpr array VERSION_VOLUME {1, 0}; constexpr array VERSION_VOXEL {2, 0}; diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 38b777cf6..51527818c 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -2,11 +2,14 @@ from collections import namedtuple import h5py +from .checkvalue import check_filetype_version from .source import SourceParticle, ParticleType ParticleTrack = namedtuple('ParticleTrack', ['particle', 'states']) +_VERSION_TRACK = 3 + def _identifier(dset_name): """Return (batch, gen, particle) tuple given dataset name""" @@ -112,12 +115,15 @@ class TrackFile(list): def __init__(self, filepath): # Read data from track file with h5py.File(filepath, 'r') as fh: + # Check filetype and version + check_filetype_version(fh, 'track', _VERSION_TRACK) for dset_name in sorted(fh, key=_identifier): dset = fh[dset_name] self.append(Track(dset)) def plot(self): + """Produce a 3D plot of particle tracks""" import matplotlib.pyplot as plt fig = plt.figure() ax = plt.axes(projection='3d') From 8d9b34df861d107a5938b786a0256459ea1c67a0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 May 2022 13:08:29 -0400 Subject: [PATCH 0306/2654] Fix track_output regression test to work with MPI --- tests/regression_tests/track_output/test.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/track_output/test.py b/tests/regression_tests/track_output/test.py index 1501d3fd6..6fe2b52cc 100644 --- a/tests/regression_tests/track_output/test.py +++ b/tests/regression_tests/track_output/test.py @@ -1,10 +1,11 @@ import glob import os +from pathlib import Path from subprocess import call import pytest -from tests.testing_harness import TestHarness +from tests.testing_harness import TestHarness, config class TrackTestHarness(TestHarness): @@ -12,17 +13,20 @@ class TrackTestHarness(TestHarness): """Make sure statepoint.* and track* have been created.""" TestHarness._test_output_created(self) - outputs = glob.glob('track_1_1_*.h5') - assert len(outputs) == 2, 'Expected two track files.' + if config['mpi'] and int(config['mpi_np']) > 1: + outputs = Path.cwd().glob('tracks_p*.h5') + assert len(list(outputs)) == int(config['mpi_np']) + else: + assert Path('tracks.h5').is_file() def _get_results(self): """Digest info in the statepoint and return as a string.""" # Run the track-to-vtk conversion script. call(['../../../scripts/openmc-track-to-vtk', '-o', 'poly'] + - glob.glob('track_1_1_*.h5')) + glob.glob('tracks*.h5')) # Make sure the vtk file was created then return it's contents. - assert os.path.isfile('poly.pvtp'), 'poly.pvtp file not found.' + assert Path('poly.pvtp').is_file(), 'poly.pvtp file not found.' with open('poly.pvtp', 'r') as fin: outstr = fin.read() @@ -31,7 +35,7 @@ class TrackTestHarness(TestHarness): def _cleanup(self): TestHarness._cleanup(self) - output = glob.glob('track*') + glob.glob('poly*') + output = glob.glob('tracks*') + glob.glob('poly*') for f in output: if os.path.exists(f): os.remove(f) From e2de81045f54bed2db815e613c31b6aa41945f44 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 May 2022 13:27:02 -0400 Subject: [PATCH 0307/2654] Update track_output regression test --- .../track_output/results_true.dat | 183 +++++++++++++++++- .../track_output/settings.xml | 3 +- tests/regression_tests/track_output/test.py | 21 +- 3 files changed, 189 insertions(+), 18 deletions(-) diff --git a/tests/regression_tests/track_output/results_true.dat b/tests/regression_tests/track_output/results_true.dat index 1d0ca8039..981625bf7 100644 --- a/tests/regression_tests/track_output/results_true.dat +++ b/tests/regression_tests/track_output/results_true.dat @@ -1,9 +1,174 @@ - - - - - - - - - +[ParticleTrack(particle=, states=array([((-9.663085e-01, -6.616522e-01, -9.863690e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 0.000000e+00, 1.000000e+00, 23, 1), + ((-1.281491e+00, -4.879529e-01, -7.708709e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.323629e-10, 1.000000e+00, 22, 3), + ((-1.368452e+00, -4.400285e-01, -7.114141e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.688824e-10, 1.000000e+00, 21, 2), + ((-2.150539e+00, -9.015151e-03, -1.766823e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 4.973246e-10, 1.000000e+00, 22, 3), + ((-2.237499e+00, 3.890922e-02, -1.172255e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 5.338441e-10, 1.000000e+00, 23, 1), + ((-2.453640e+00, 1.580257e-01, 3.055504e-02), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 6.246136e-10, 1.000000e+00, 23, 1), + ((-2.767485e+00, 3.309877e-01, 2.451383e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 7.564146e-10, 1.000000e+00, 22, 3), + ((-2.825099e+00, 3.627392e-01, 2.845305e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 7.806100e-10, 1.000000e+00, 22, 3), + ((-3.274427e+00, 6.029890e-01, 6.987901e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 9.878481e-10, 1.000000e+00, 23, 1), + ((-3.676327e+00, 8.178800e-01, 1.069324e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.173212e-09, 1.000000e+00, 23, 1), + ((-4.089400e+00, 1.038745e+00, 1.450158e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.363728e-09, 1.000000e+00, 23, 1), + ((-4.456639e+00, 1.235102e+00, 1.788735e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.533105e-09, 1.000000e+00, 22, 3), + ((-4.536974e+00, 1.278056e+00, 1.862800e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.570157e-09, 1.000000e+00, 21, 2), + ((-5.410401e+00, 1.745067e+00, 2.668060e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.972998e-09, 1.000000e+00, 22, 3), + ((-5.490736e+00, 1.788021e+00, 2.742125e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 2.010050e-09, 1.000000e+00, 23, 1), + ((-5.576301e+00, 1.833771e+00, 2.821012e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.049514e-09, 1.000000e+00, 23, 1), + ((-5.725160e+00, 1.896661e+00, 2.330311e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.227030e-09, 1.000000e+00, 23, 1), + ((-6.116514e+00, 2.061999e+00, 1.040248e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.693724e-09, 1.000000e+00, 22, 3), + ((-6.534762e+00, 2.238699e+00, -3.384686e-01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.192489e-09, 1.000000e+00, 23, 1), + ((-7.043525e+00, 2.453640e+00, -2.015560e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.799195e-09, 1.000000e+00, 23, 1), + ((-7.360920e+00, 2.587732e+00, -3.061825e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 4.177692e-09, 1.000000e+00, 11, 1), + ((-8.996680e+00, 3.278803e+00, -8.453960e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.128354e-09, 1.000000e+00, 23, 1), + ((-9.220205e+00, 3.373238e+00, -9.190791e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.394910e-09, 1.000000e+00, 22, 3), + ((-9.320244e+00, 3.415502e+00, -9.520561e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.514208e-09, 1.000000e+00, 21, 2), + ((-1.005591e+01, 3.726304e+00, -1.194562e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.391498e-09, 1.000000e+00, 22, 3), + ((-1.015595e+01, 3.768569e+00, -1.227539e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.510796e-09, 1.000000e+00, 23, 1), + ((-1.062054e+01, 3.964848e+00, -1.380687e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.064826e-09, 1.000000e+00, 23, 1), + ((-1.063244e+01, 3.969501e+00, -1.382484e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.072756e-09, 1.000000e+00, 23, 1), + ((-1.093907e+01, 4.089400e+00, -1.428802e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.277097e-09, 1.000000e+00, 23, 1), + ((-1.108410e+01, 4.146112e+00, -1.450710e+01), (4.855193e-01, 3.316053e-01, -8.088937e-01), 8.856868e+05, 8.373750e-09, 1.000000e+00, 23, 1), + ((-1.080173e+01, 4.338973e+00, -1.497755e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 8.820862e-09, 1.000000e+00, 23, 1), + ((-1.063244e+01, 4.371524e+00, -1.555290e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 9.317522e-09, 1.000000e+00, 23, 1), + ((-1.041266e+01, 4.413783e+00, -1.629984e+01), (2.686183e-01, -3.269476e-01, -9.060626e-01), 6.562001e+05, 9.962308e-09, 1.000000e+00, 23, 1), + ((-1.016754e+01, 4.115428e+00, -1.712667e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.077718e-08, 1.000000e+00, 23, 1), + ((-1.019064e+01, 4.089400e+00, -1.713747e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.087569e-08, 1.000000e+00, 23, 1), + ((-1.024915e+01, 4.023496e+00, -1.716481e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.112511e-08, 1.000000e+00, 23, 1), + ((-1.018199e+01, 3.749638e+00, -1.740047e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.276389e-08, 1.000000e+00, 22, 3), + ((-1.015866e+01, 3.654498e+00, -1.748234e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.333321e-08, 1.000000e+00, 21, 2), + ((-1.009978e+01, 3.414404e+00, -1.768895e+01), (1.735861e-01, -9.678731e-01, 1.819053e-01), 2.620416e+04, 1.476994e-08, 1.000000e+00, 21, 2), + ((-9.994809e+00, 2.829099e+00, -1.757894e+01), (4.635724e-01, 5.558106e-01, 6.900545e-01), 2.214649e+04, 1.747088e-08, 1.000000e+00, 21, 2), + ((-9.553365e+00, 3.358379e+00, -1.692183e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.209726e-08, 1.000000e+00, 21, 2), + ((-1.011854e+01, 3.687059e+00, -1.760205e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.716243e-08, 1.000000e+00, 22, 3), + ((-1.020058e+01, 3.734765e+00, -1.770077e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.789760e-08, 1.000000e+00, 23, 1), + ((-1.063244e+01, 3.985917e+00, -1.822054e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.176800e-08, 1.000000e+00, 23, 1), + ((-1.081038e+01, 4.089400e+00, -1.843470e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.336273e-08, 1.000000e+00, 23, 1), + ((-1.081564e+01, 4.092455e+00, -1.844103e+01), (-6.690877e-01, 6.718700e-01, -3.176671e-01), 1.355236e+04, 3.340982e-08, 1.000000e+00, 23, 1), + ((-1.096190e+01, 4.239327e+00, -1.851047e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.476743e-08, 1.000000e+00, 23, 1), + ((-1.109457e+01, 4.420404e+00, -1.850054e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.628014e-08, 1.000000e+00, 22, 3), + ((-1.113484e+01, 4.475368e+00, -1.849752e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.673931e-08, 1.000000e+00, 22, 3), + ((-1.117187e+01, 4.372425e+00, -1.850142e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.748914e-08, 1.000000e+00, 23, 1), + ((-1.127367e+01, 4.089400e+00, -1.851213e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.955064e-08, 1.000000e+00, 23, 1), + ((-1.135375e+01, 3.866733e+00, -1.852056e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.117251e-08, 1.000000e+00, 22, 3), + ((-1.138419e+01, 3.782113e+00, -1.852377e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.178887e-08, 1.000000e+00, 21, 2), + ((-1.172456e+01, 2.835777e+00, -1.855959e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.868184e-08, 1.000000e+00, 22, 3), + ((-1.175499e+01, 2.751157e+00, -1.856280e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.929820e-08, 1.000000e+00, 23, 1), + ((-1.179525e+01, 2.639224e+00, -1.856703e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.011351e-08, 1.000000e+00, 23, 1), + ((-1.190609e+01, 2.453640e+00, -1.847770e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.190861e-08, 1.000000e+00, 23, 1), + ((-1.222017e+01, 1.927741e+00, -1.822457e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.699551e-08, 1.000000e+00, 23, 1), + ((-1.226820e+01, 1.951470e+00, -1.815983e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.888995e-08, 1.000000e+00, 23, 1), + ((-1.236181e+01, 1.997712e+00, -1.803368e+01), (1.748787e-01, 6.613493e-01, 7.294070e-01), 4.250133e+02, 6.258186e-08, 1.000000e+00, 23, 1), + ((-1.234968e+01, 2.043587e+00, -1.798308e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 6.501444e-08, 1.000000e+00, 23, 1), + ((-1.276513e+01, 2.146245e+00, -1.744506e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 8.979603e-08, 1.000000e+00, 22, 3), + ((-1.313233e+01, 2.236980e+00, -1.696953e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 1.116994e-07, 1.000000e+00, 23, 1), + ((-1.318468e+01, 2.249916e+00, -1.690173e+01), (-8.862976e-01, -6.402442e-02, 4.586692e-01), 3.113244e+02, 1.148223e-07, 1.000000e+00, 23, 1), + ((-1.363685e+01, 2.217253e+00, -1.666773e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.357269e-07, 1.000000e+00, 23, 1), + ((-1.334593e+01, 2.453640e+00, -1.709033e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.617034e-07, 1.000000e+00, 23, 1), + ((-1.308145e+01, 2.668542e+00, -1.747452e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.853189e-07, 1.000000e+00, 22, 3), + ((-1.304150e+01, 2.701005e+00, -1.753256e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.888862e-07, 1.000000e+00, 22, 3), + ((-1.304665e+01, 2.669815e+00, -1.753058e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.903682e-07, 1.000000e+00, 23, 1), + ((-1.308231e+01, 2.453640e+00, -1.751686e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.006392e-07, 1.000000e+00, 23, 1), + ((-1.311790e+01, 2.237916e+00, -1.750317e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.108888e-07, 1.000000e+00, 22, 3), + ((-1.313266e+01, 2.148507e+00, -1.749750e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.151369e-07, 1.000000e+00, 21, 2), + ((-1.320190e+01, 1.728791e+00, -1.747087e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.350787e-07, 1.000000e+00, 21, 2), + ((-1.309582e+01, 2.150526e+00, -1.834143e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.808996e-07, 1.000000e+00, 22, 3), + ((-1.307365e+01, 2.238628e+00, -1.852329e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.904717e-07, 1.000000e+00, 23, 1), + ((-1.301957e+01, 2.453640e+00, -1.896713e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 3.138324e-07, 1.000000e+00, 23, 1), + ((-1.297913e+01, 2.614390e+00, -1.929896e+01), (6.012134e-01, 7.985735e-01, -2.868317e-02), 4.041011e+01, 3.312976e-07, 1.000000e+00, 23, 1), + ((-1.295975e+01, 2.640133e+00, -1.929988e+01), (6.762805e-01, -5.875192e-01, 4.443713e-01), 3.527833e+01, 3.349640e-07, 1.000000e+00, 23, 1), + ((-1.282907e+01, 2.526604e+00, -1.921402e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.584852e-07, 1.000000e+00, 23, 1), + ((-1.284217e+01, 2.453640e+00, -1.921346e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.799102e-07, 1.000000e+00, 23, 1), + ((-1.288683e+01, 2.204886e+00, -1.921158e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.529534e-07, 1.000000e+00, 22, 3), + ((-1.290264e+01, 2.116831e+00, -1.921091e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.788097e-07, 1.000000e+00, 21, 2), + ((-1.308145e+01, 1.120923e+00, -1.920338e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.712448e-07, 1.000000e+00, 22, 3), + ((-1.309726e+01, 1.032868e+00, -1.920271e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.971010e-07, 1.000000e+00, 23, 1), + ((-1.312690e+01, 8.677798e-01, -1.920146e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.455768e-07, 1.000000e+00, 23, 1), + ((-1.316626e+01, 8.178800e-01, -1.918559e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.693415e-07, 1.000000e+00, 23, 1), + ((-1.324019e+01, 7.241633e-01, -1.915578e+01), (-9.367321e-01, -1.471894e-01, -3.175976e-01), 2.365289e+00, 9.139738e-07, 1.000000e+00, 23, 1), + ((-1.348497e+01, 6.857011e-01, -1.923877e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.036815e-06, 1.000000e+00, 23, 1), + ((-1.390396e+01, 7.859275e-01, -1.924890e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.269071e-06, 1.000000e+00, 23, 1), + ((-1.403754e+01, 8.178800e-01, -1.925212e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.343115e-06, 1.000000e+00, 23, 1), + ((-1.504223e+01, 1.058212e+00, -1.927640e+01), (-4.085804e-01, -2.719942e-01, -8.712526e-01), 1.628266e+00, 1.900041e-06, 1.000000e+00, 23, 1), + ((-1.523744e+01, 9.282558e-01, -1.969268e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.170751e-06, 1.000000e+00, 23, 1), + ((-1.553972e+01, 1.106680e+00, -1.997974e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.636878e-06, 1.000000e+00, 23, 1), + ((-1.585973e+01, 1.295571e+00, -2.028364e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.130348e-06, 1.000000e+00, 22, 3), + ((-1.593583e+01, 1.340489e+00, -2.035590e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.247693e-06, 1.000000e+00, 21, 2), + ((-1.647184e+01, 1.656882e+00, -2.086494e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 4.074258e-06, 1.000000e+00, 21, 2), + ((-1.585080e+01, 1.545037e+00, -2.159072e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.061748e-06, 1.000000e+00, 22, 3), + ((-1.576406e+01, 1.529415e+00, -2.169209e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.199673e-06, 1.000000e+00, 23, 1), + ((-1.553972e+01, 1.489015e+00, -2.195425e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.556377e-06, 1.000000e+00, 23, 1), + ((-1.546081e+01, 1.474803e+00, -2.204648e+01), (3.257038e-01, -9.420596e-01, -8.025439e-02), 3.076319e-01, 5.681852e-06, 1.000000e+00, 23, 1), + ((-1.543563e+01, 1.401988e+00, -2.205268e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 5.782605e-06, 1.000000e+00, 23, 1), + ((-1.553972e+01, 1.153338e+00, -2.213907e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 6.487752e-06, 1.000000e+00, 23, 1), + ((-1.565955e+01, 8.670807e-01, -2.223854e+01), (1.611814e-01, 2.692337e-01, -9.494913e-01), 8.559448e-02, 7.299552e-06, 1.000000e+00, 23, 1), + ((-1.563263e+01, 9.120446e-01, -2.239711e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 7.712256e-06, 1.000000e+00, 23, 1), + ((-1.592604e+01, 1.214620e+00, -2.249695e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.406031e-06, 1.000000e+00, 22, 3), + ((-1.598742e+01, 1.277922e+00, -2.251784e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.760391e-06, 1.000000e+00, 21, 2), + ((-1.670388e+01, 2.016770e+00, -2.276163e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.389636e-05, 1.000000e+00, 22, 3), + ((-1.676526e+01, 2.080073e+00, -2.278252e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.425072e-05, 1.000000e+00, 23, 1), + ((-1.681575e+01, 2.132139e+00, -2.279970e+01), (4.286076e-02, -9.409799e-01, -3.357375e-01), 1.813618e-02, 1.454218e-05, 1.000000e+00, 23, 1), + ((-1.681374e+01, 2.087933e+00, -2.281547e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.479439e-05, 1.000000e+00, 23, 1), + ((-1.682083e+01, 2.021795e+00, -2.287841e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.532970e-05, 1.000000e+00, 22, 3), + ((-1.684417e+01, 1.804084e+00, -2.308558e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.709182e-05, 1.000000e+00, 21, 2), + ((-1.686879e+01, 1.574384e+00, -2.330417e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.895097e-05, 1.000000e+00, 22, 3), + ((-1.689212e+01, 1.356673e+00, -2.351134e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 2.071309e-05, 1.000000e+00, 23, 1), + ((-1.689233e+01, 1.354754e+00, -2.351317e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.072862e-05, 1.000000e+00, 23, 1), + ((-1.689148e+01, 1.355453e+00, -2.351229e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.073958e-05, 1.000000e+00, 22, 3), + ((-1.682182e+01, 1.413107e+00, -2.343954e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.164421e-05, 1.000000e+00, 21, 2), + ((-1.636364e+01, 1.792326e+00, -2.296107e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 2.759442e-05, 1.000000e+00, 21, 2), + ((-1.598564e+01, 1.746738e+00, -2.286758e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 3.079609e-05, 0.000000e+00, 21, 2)], + dtype=[('r', [('x', ', states=array([((-9.469716e-01, -2.580266e-01, 1.414357e-01), (1.438873e-01, 2.365819e-01, 9.608983e-01), 9.724461e+05, 0.000000e+00, 1.000000e+00, 23, 1), + ((-9.064818e-01, -1.914524e-01, 4.118326e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 2.064696e-10, 1.000000e+00, 23, 1), + ((-8.178800e-01, -1.616918e-01, 4.336377e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 3.725262e-10, 1.000000e+00, 11, 1), + ((-3.834875e-01, -1.578285e-02, 5.405432e-01), (-5.547498e-01, -6.358598e-02, 8.295839e-01), 1.474011e+05, 1.186660e-09, 1.000000e+00, 11, 1), + ((-7.999329e-01, -6.351625e-02, 1.163304e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.600465e-09, 1.000000e+00, 11, 1), + ((-8.178800e-01, -6.341842e-02, 1.190721e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.662321e-09, 1.000000e+00, 23, 1), + ((-1.035984e+00, -6.222961e-02, 1.523906e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.414026e-09, 1.000000e+00, 22, 3), + ((-1.124618e+00, -6.174649e-02, 1.659308e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.719509e-09, 1.000000e+00, 21, 2), + ((-1.705404e+00, -5.858082e-02, 2.546543e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 5.721217e-09, 1.000000e+00, 21, 2), + ((-1.851116e+00, -4.676544e-01, 2.685103e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.583734e-09, 1.000000e+00, 22, 3), + ((-1.880791e+00, -5.509662e-01, 2.713322e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.759394e-09, 1.000000e+00, 23, 1), + ((-1.948026e+00, -7.397227e-01, 2.777257e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.157380e-09, 1.000000e+00, 23, 1), + ((-2.068870e+00, -8.178800e-01, 2.735799e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.598974e-09, 1.000000e+00, 23, 1), + ((-2.111345e+00, -8.453511e-01, 2.721228e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 7.754188e-09, 1.000000e+00, 23, 1), + ((-2.453640e+00, -1.161216e+00, 3.335542e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.421339e-08, 1.000000e+00, 23, 1), + ((-2.715369e+00, -1.402736e+00, 3.805265e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.915229e-08, 1.000000e+00, 22, 3), + ((-2.785083e+00, -1.467067e+00, 3.930380e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 2.046780e-08, 1.000000e+00, 21, 2), + ((-2.940196e+00, -1.610203e+00, 4.208760e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 2.339483e-08, 1.000000e+00, 21, 2), + ((-3.600602e+00, -1.239800e+00, 3.812386e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.112139e-08, 1.000000e+00, 22, 3), + ((-3.682067e+00, -1.194109e+00, 3.763490e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.207450e-08, 1.000000e+00, 23, 1), + ((-4.089400e+00, -9.656478e-01, 3.519009e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.684019e-08, 1.000000e+00, 23, 1), + ((-4.185927e+00, -9.115084e-01, 3.461074e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 3.796953e-08, 1.000000e+00, 23, 1), + ((-4.089400e+00, -9.150200e-01, 3.260397e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 6.996444e-08, 1.000000e+00, 23, 1), + ((-3.920090e+00, -9.211794e-01, 2.908406e+00), (9.094673e-01, -3.659267e-01, -1.974002e-01), 9.547085e+00, 1.260840e-07, 1.000000e+00, 23, 1), + ((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 1), + ((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 1)], + dtype=[('r', [('x', ', states=array([((-9.896300e-01, -6.241550e-01, 7.890184e-01), (-4.012123e-01, 9.073327e-01, 1.256028e-01), 4.434429e+05, 0.000000e+00, 1.000000e+00, 23, 1), + ((-1.124354e+00, -3.194804e-01, 8.311948e-01), (-4.012123e-01, 9.073327e-01, 1.256028e-01), 4.434429e+05, 3.646971e-10, 1.000000e+00, 22, 3), + ((-1.169278e+00, -2.178843e-01, 8.452588e-01), (-4.012123e-01, 9.073327e-01, 1.256028e-01), 4.434429e+05, 4.863081e-10, 1.000000e+00, 21, 2), + ((-1.200617e+00, -1.470127e-01, 8.550696e-01), (4.985110e-01, -3.420076e-01, -7.965661e-01), 4.374324e+05, 5.711419e-10, 1.000000e+00, 21, 2), + ((-1.153218e+00, -1.795315e-01, 7.793306e-01), (4.985110e-01, -3.420076e-01, -7.965661e-01), 4.374324e+05, 6.751152e-10, 1.000000e+00, 22, 3), + ((-1.078639e+00, -2.306964e-01, 6.601629e-01), (4.985110e-01, -3.420076e-01, -7.965661e-01), 4.374324e+05, 8.387067e-10, 1.000000e+00, 23, 1), + ((-8.498389e-01, -3.876669e-01, 2.945646e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 1.340594e-09, 1.000000e+00, 23, 1), + ((-8.178800e-01, -6.225680e-01, 3.627213e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 2.978729e-09, 1.000000e+00, 11, 1), + ((-7.913073e-01, -8.178800e-01, 4.193912e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 4.340781e-09, 1.000000e+00, 23, 1), + ((-5.687582e-01, -2.453640e+00, 8.940079e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 1.574812e-08, 1.000000e+00, 23, 1), + ((-5.396956e-01, -2.667253e+00, 9.559878e-01), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 1.723779e-08, 1.000000e+00, 23, 1), + ((-2.229408e-01, -2.711251e+00, 1.160371e+00), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 2.412440e-08, 1.000000e+00, 22, 3), + ((3.672002e-01, -2.793223e+00, 1.541154e+00), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 3.695471e-08, 1.000000e+00, 23, 1), + ((8.178800e-01, -2.855823e+00, 1.831950e+00), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 4.675299e-08, 1.000000e+00, 23, 1), + ((8.973133e-01, -2.866857e+00, 1.883204e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 4.847996e-08, 1.000000e+00, 23, 1), + ((1.109695e+00, -2.976801e+00, 1.896325e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 5.375585e-08, 1.000000e+00, 22, 3), + ((1.188016e+00, -3.017346e+00, 1.901163e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 5.570149e-08, 1.000000e+00, 21, 2), + ((2.101785e+00, -3.490379e+00, 1.957615e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 7.840096e-08, 1.000000e+00, 22, 3), + ((2.180107e+00, -3.530924e+00, 1.962454e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 8.034660e-08, 1.000000e+00, 23, 1), + ((2.331655e+00, -3.609377e+00, 1.971817e+00), (5.352328e-01, -1.825854e-01, 8.247353e-01), 3.972292e+02, 8.411129e-08, 1.000000e+00, 23, 1), + ((2.453640e+00, -3.650990e+00, 2.159783e+00), (5.352328e-01, -1.825854e-01, 8.247353e-01), 3.972292e+02, 9.237876e-08, 1.000000e+00, 11, 1), + ((3.052522e+00, -3.855288e+00, 3.082595e+00), (-6.240259e-01, 3.743550e-01, 6.858936e-01), 7.908847e+00, 1.329675e-07, 1.000000e+00, 11, 1), + ((2.955791e+00, -3.797259e+00, 3.188916e+00), (-8.018916e-01, -4.124485e-01, 4.322686e-01), 3.121121e+00, 1.728180e-07, 1.000000e+00, 11, 1), + ((2.937908e+00, -3.806457e+00, 3.198556e+00), (-4.476221e-02, -9.803939e-01, -1.918959e-01), 1.564715e+00, 1.819446e-07, 1.000000e+00, 11, 1), + ((2.924989e+00, -4.089400e+00, 3.143175e+00), (-4.476221e-02, -9.803939e-01, -1.918959e-01), 1.564715e+00, 3.487493e-07, 1.000000e+00, 23, 1), + ((2.922113e+00, -4.152398e+00, 3.130844e+00), (-4.476221e-02, -9.803939e-01, -1.918959e-01), 1.564715e+00, 3.858887e-07, 0.000000e+00, 23, 1)], + dtype=[('r', [('x', ' 1 1 1 - 1 1 2 + 1 1 30 + 1 1 60 diff --git a/tests/regression_tests/track_output/test.py b/tests/regression_tests/track_output/test.py index 6fe2b52cc..06c7e15f5 100644 --- a/tests/regression_tests/track_output/test.py +++ b/tests/regression_tests/track_output/test.py @@ -3,6 +3,8 @@ import os from pathlib import Path from subprocess import call +import numpy as np +import openmc import pytest from tests.testing_harness import TestHarness, config @@ -20,16 +22,19 @@ class TrackTestHarness(TestHarness): assert Path('tracks.h5').is_file() def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Run the track-to-vtk conversion script. - call(['../../../scripts/openmc-track-to-vtk', '-o', 'poly'] + - glob.glob('tracks*.h5')) + """Get data from track file and return as a string.""" - # Make sure the vtk file was created then return it's contents. - assert Path('poly.pvtp').is_file(), 'poly.pvtp file not found.' + # For MPI mode, combine track files + if config['mpi']: + call(['../../../scripts/openmc-track-combine', '-o', 'tracks.h5'] + + glob.glob('tracks_p*.h5')) - with open('poly.pvtp', 'r') as fin: - outstr = fin.read() + # Get string of track file information + outstr = '' + tracks = openmc.TrackFile('tracks.h5') + for track in tracks: + with np.printoptions(formatter={'float_kind': '{:.6e}'.format}): + outstr += str(track.particles) + '\n' return outstr From 8ecfdf079675cb694e524614536740ee04387f55 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 May 2022 14:15:37 -0500 Subject: [PATCH 0308/2654] Update Settings.track to be list of 3-tuple --- openmc/settings.py | 25 +++++++++++++------------ openmc/trackfile.py | 6 +++--- tests/unit_tests/test_settings.py | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index d11a577d1..8d8e2eba9 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -2,6 +2,7 @@ import os import typing # imported separately as py3.8 requires typing.Iterable from collections.abc import Iterable, Mapping, MutableSequence from enum import Enum +import itertools from math import ceil from numbers import Integral, Real from pathlib import Path @@ -187,7 +188,7 @@ class Settings: integers: the batch number, generation number, and particle number track : tuple or list Specify particles for which track files should be written. Each particle - is identified by a triplet with the batch number, generation number, and + is identified by a tuple with the batch number, generation number, and particle number. trigger_active : bool Indicate whether tally triggers are used @@ -776,16 +777,15 @@ class Settings: self._trace = trace @track.setter - def track(self, track: typing.Iterable[int]): - cv.check_type('track', track, Iterable, Integral) - if len(track) % 3 != 0: - msg = f'Unable to set the track to "{track}" since its length is ' \ - 'not a multiple of 3' - raise ValueError(msg) - for t in zip(track[::3], track[1::3], track[2::3]): + def track(self, track: typing.Iterable[typing.Iterable[int]]): + cv.check_type('track', track, Iterable) + for t in track: + if len(t) != 3: + msg = f'Unable to set the track to "{t}" since its length is not 3' + raise ValueError(msg) cv.check_greater_than('track batch', t[0], 0) - cv.check_greater_than('track generation', t[0], 0) - cv.check_greater_than('track particle', t[0], 0) + cv.check_greater_than('track generation', t[1], 0) + cv.check_greater_than('track particle', t[2], 0) self._track = track @ufs_mesh.setter @@ -1110,7 +1110,7 @@ class Settings: def _create_track_subelement(self, root): if self._track is not None: element = ET.SubElement(root, "track") - element.text = ' '.join(map(str, self._track)) + element.text = ' '.join(map(str, itertools.chain(*self._track))) def _create_ufs_mesh_subelement(self, root): if self.ufs_mesh is not None: @@ -1424,7 +1424,8 @@ class Settings: def _track_from_xml_element(self, root): text = get_text(root, 'track') if text is not None: - self.track = [int(x) for x in text.split()] + values = [int(x) for x in text.split()] + self.track = list(zip(values[::3], values[1::3], values[2::3])) def _ufs_mesh_from_xml_element(self, root): text = get_text(root, 'ufs_mesh') diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 51527818c..8c2d02cd1 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -84,9 +84,9 @@ class Track: @property def sources(self): sources = [] - for track_history in self.tracks: - particle_type = ParticleType(track_history.particle) - state = track_history.states[0] + for particle_track in self.particles: + particle_type = ParticleType(particle_track.particle) + state = particle_track.states[0] sources.append( SourceParticle( r=state['r'], u=state['u'], E=state['E'], diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index e2c7259e7..72b930b29 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -42,7 +42,7 @@ def test_export_to_xml(run_in_tmpdir): s.temperature = {'default': 293.6, 'method': 'interpolation', 'multipole': True, 'range': (200., 1000.)} s.trace = (10, 1, 20) - s.track = [1, 1, 1, 2, 1, 1] + s.track = [(1, 1, 1), (2, 1, 1)] s.ufs_mesh = mesh s.resonance_scattering = {'enable': True, 'method': 'rvs', 'energy_min': 1.0, 'energy_max': 1000.0, @@ -99,7 +99,7 @@ def test_export_to_xml(run_in_tmpdir): assert s.temperature == {'default': 293.6, 'method': 'interpolation', 'multipole': True, 'range': [200., 1000.]} assert s.trace == [10, 1, 20] - assert s.track == [1, 1, 1, 2, 1, 1] + assert s.track == [(1, 1, 1), (2, 1, 1)] assert isinstance(s.ufs_mesh, openmc.RegularMesh) assert s.ufs_mesh.lower_left == [-10., -10., -10.] assert s.ufs_mesh.upper_right == [10., 10., 10.] From 583d864f08c820c5a31d6095e540e01b605c2a62 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 May 2022 17:10:27 -0500 Subject: [PATCH 0309/2654] Put track file combining logic in TrackFile.combine staticmethod --- openmc/trackfile.py | 24 ++++++++++++++++++++++++ scripts/openmc-track-combine | 19 +++---------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 8c2d02cd1..64ed5b707 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -130,3 +130,27 @@ class TrackFile(list): for track in self: track.plot(ax) plt.show() + + @staticmethod + def combine(track_files, path='tracks.h5'): + """Combine multiple track files into a single track file + + Parameters + ---------- + track_files : list of path-like + Paths to track files to combine + path : path-like + Path of combined track file to create + + """ + with h5py.File(path, 'w') as h5_out: + for i, fname in enumerate(track_files): + with h5py.File(fname, 'r') as h5_in: + # Copy file attributes for first file + if i == 0: + h5_out.attrs['filetype'] = h5_in.attrs['filetype'] + h5_out.attrs['version'] = h5_in.attrs['version'] + + # Copy each 'track_*' dataset from input file + for dset in h5_in: + h5_in.copy(dset, h5_out) diff --git a/scripts/openmc-track-combine b/scripts/openmc-track-combine index 4bd2fb082..155fe9b54 100755 --- a/scripts/openmc-track-combine +++ b/scripts/openmc-track-combine @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -"""Combine multiple HDF5 particle track files. - -""" +"""Combine multiple HDF5 particle track files.""" import argparse -import h5py +import openmc def main(): @@ -19,18 +17,7 @@ def main(): help='Output HDF5 particle track file.') args = parser.parse_args() - - with h5py.File(args.out, 'w') as h5_out: - for i, fname in enumerate(args.input): - with h5py.File(fname, 'r') as h5_in: - # Copy file attributes for first file - if i == 0: - h5_out.attrs['filetype'] = h5_in.attrs['filetype'] - h5_out.attrs['version'] = h5_in.attrs['version'] - - # Copy each 'track_*' dataset from input file - for dset in h5_in: - h5_in.copy(dset, h5_out) + openmc.TrackFile.combine(args.input, args.out) if __name__ == '__main__': From 4f1e8f46f51aa3435e109bae85556b15c924138b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 May 2022 17:27:47 -0500 Subject: [PATCH 0310/2654] Add unit tests for TrackFile class --- tests/unit_tests/test_tracks.py | 81 +++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/unit_tests/test_tracks.py diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py new file mode 100644 index 000000000..a8b406c9c --- /dev/null +++ b/tests/unit_tests/test_tracks.py @@ -0,0 +1,81 @@ +from pathlib import Path + +import numpy as np +import openmc +import pytest + +from tests.testing_harness import config + + +@pytest.fixture +def sphere_model(): + mat = openmc.Material() + mat.add_nuclide('Zr90', 1.0) + mat.set_density('g/cm3', 1.0) + + model = openmc.Model() + sph = openmc.Sphere(r=25.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sph) + model.geometry = openmc.Geometry([cell]) + + model.settings.run_mode = 'fixed source' + model.settings.batches = 1 + model.settings.particles = 100 + model.settings.track = [(1, 1, 1), (1, 1, 10), (1, 1, 75)] + + return model + + +def test_tracks(sphere_model, run_in_tmpdir): + # If running in MPI mode, setup proper keyword arguments for run() + kwargs = {'openmc_exec': config['exe']} + if config['mpi']: + kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']] + sphere_model.run(**kwargs) + + if config['mpi'] and int(config['mpi_np']) > 1: + # With MPI, we need to combine track files + track_files = Path.cwd().glob('tracks_p*.h5') + openmc.TrackFile.combine(track_files, 'tracks.h5') + else: + track_file = Path('tracks.h5') + assert track_file.is_file() + + # Open track file and make sure we have correct number of tracks + tracks = openmc.TrackFile('tracks.h5') + assert len(tracks) == len(sphere_model.settings.track) + + for track, identifier in zip(tracks, sphere_model.settings.track): + # Check attributes on Track object + assert isinstance(track, openmc.Track) + assert track.identifier == identifier + assert isinstance(track.particles, list) + assert len(track.particles) == 1 + + # Check attributes on ParticleTrack object + particle_track = track.particles[0] + assert isinstance(particle_track, openmc.ParticleTrack) + assert particle_track.particle == openmc.ParticleType.NEUTRON + assert isinstance(particle_track.states, np.ndarray) + + # Sanity checks on actual data + for state in particle_track.states: + assert np.linalg.norm([*state['r']]) <= 25.0001 + assert np.linalg.norm([*state['u']]) == pytest.approx(1.0) + assert 0.0 <= state['E'] <= 20.0e6 + assert state['time'] >= 0.0 + assert 0.0 <= state['wgt'] <= 1.0 + assert state['cell_id'] == 1 + assert state['material_id'] == 1 + + # Checks on 'sources' property + sources = track.sources + assert len(sources) == 1 + x = sources[0] + state = particle_track.states[0] + assert x.r == (*state['r'],) + assert x.u == (*state['u'],) + assert x.E == state['E'] + assert x.time == state['time'] + assert x.wgt == state['wgt'] + assert x.particle == particle_track.particle From e34bf445f06fd724ca03aa69cd647b16a0ed4743 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 May 2022 07:25:10 -0500 Subject: [PATCH 0311/2654] Add max_tracks setting (maximum number of tracks per process) --- include/openmc/settings.h | 1 + include/openmc/track_output.h | 6 ++++++ openmc/settings.py | 29 +++++++++++++++++++++++++++- src/finalize.cpp | 1 + src/settings.cpp | 5 +++++ src/simulation.cpp | 13 +------------ src/track_output.cpp | 32 +++++++++++++++++++++++++++++-- tests/unit_tests/test_settings.py | 2 ++ tests/unit_tests/test_tracks.py | 29 ++++++++++++++++++++++++---- 9 files changed, 99 insertions(+), 19 deletions(-) diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 50be80a50..1e061b235 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -88,6 +88,7 @@ extern int max_order; //!< Maximum Legendre order for multigroup data extern int n_log_bins; //!< number of bins for logarithmic energy grid extern int n_batches; //!< number of (inactive+active) batches extern int n_max_batches; //!< Maximum number of batches +extern int max_tracks; //!< Maximum number of particle tracks written to file extern ResScatMethod res_scat_method; //!< resonance upscattering method extern double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering extern double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering diff --git a/include/openmc/track_output.h b/include/openmc/track_output.h index c4641af2b..2380fe440 100644 --- a/include/openmc/track_output.h +++ b/include/openmc/track_output.h @@ -15,6 +15,12 @@ void open_track_file(); //! Close HDF5 resources for track file void close_track_file(); +//! Determine whether a given particle should collect/write track information +// +//! \param[in] p Current particle +//! \return Whether to collect/write track information +bool check_track_criteria(const Particle& p); + //! Create a new track state history for a primary/secondary particle // //! \param[in] p Current particle diff --git a/openmc/settings.py b/openmc/settings.py index 8d8e2eba9..641e68524 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -105,6 +105,10 @@ class Settings: Maximum number of times a particle can split during a history .. versionadded:: 0.13 + max_tracks : int + Maximum number of tracks written to a track file (per MPI process). + + .. versionadded:: 0.13.1 no_reduce : bool Indicate that all user-defined and global tallies should not be reduced across processes in a parallel calculation. @@ -291,6 +295,7 @@ class Settings: self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows') self._weight_windows_on = None self._max_splits = None + self._max_tracks = None @property def run_mode(self): @@ -476,6 +481,10 @@ class Settings: def max_splits(self): return self._max_splits + @property + def max_tracks(self): + return self._max_tracks + @run_mode.setter def run_mode(self, run_mode: str): cv.check_value('run mode', run_mode, {x.value for x in RunMode}) @@ -881,9 +890,15 @@ class Settings: @max_splits.setter def max_splits(self, value: int): cv.check_type('maximum particle splits', value, Integral) - cv.check_greater_than('max particles in flight', value, 0) + cv.check_greater_than('max particle splits', value, 0) self._max_splits = value + @max_tracks.setter + def max_tracks(self, value: int): + cv.check_type('maximum particle tracks', value, Integral) + cv.check_greater_than('maximum particle tracks', value, 0, True) + self._max_tracks = value + def _create_run_mode_subelement(self, root): elem = ET.SubElement(root, "run_mode") elem.text = self._run_mode.value @@ -1196,6 +1211,11 @@ class Settings: elem = ET.SubElement(root, "max_splits") elem.text = str(self._max_splits) + def _create_max_tracks_subelement(self, root): + if self._max_tracks is not None: + elem = ET.SubElement(root, "max_tracks") + elem.text = str(self._max_tracks) + def _eigenvalue_from_xml_element(self, root): elem = root.find('eigenvalue') if elem is not None: @@ -1499,6 +1519,11 @@ class Settings: if text is not None: self.max_splits = int(text) + def _max_tracks_from_xml_element(self, root): + text = get_text(root, 'max_tracks') + if text is not None: + self.max_tracks = int(text) + def export_to_xml(self, path: Union[str, os.PathLike] = 'settings.xml'): """Export simulation settings to an XML file. @@ -1555,6 +1580,7 @@ class Settings: self._create_write_initial_source_subelement(root_element) self._create_weight_windows_subelement(root_element) self._create_max_splits_subelement(root_element) + self._create_max_tracks_subelement(root_element) # Clean the indentation in the file to be user-readable clean_indentation(root_element) @@ -1634,6 +1660,7 @@ class Settings: settings._write_initial_source_from_xml_element(root) settings._weight_windows_from_xml_element(root) settings._max_splits_from_xml_element(root) + settings._max_tracks_from_xml_element(root) # TODO: Get volume calculations diff --git a/src/finalize.cpp b/src/finalize.cpp index 5bfe8907c..812483368 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -85,6 +85,7 @@ int openmc_finalize() settings::material_cell_offsets = true; settings::max_particles_in_flight = 100000; settings::max_splits = 1000; + settings::max_tracks = std::numeric_limits::max(); settings::n_inactive = 0; settings::n_particles = -1; settings::output_summary = true; diff --git a/src/settings.cpp b/src/settings.cpp index e2bce94d7..ecc1787c3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -95,6 +95,7 @@ int n_log_bins {8000}; int n_batches; int n_max_batches; int max_splits {1000}; +int max_tracks {std::numeric_limits::max()}; ResScatMethod res_scat_method {ResScatMethod::rvs}; double res_scat_energy_min {0.01}; double res_scat_energy_max {1000.0}; @@ -877,6 +878,10 @@ void read_settings_xml() if (check_for_node(root, "max_splits")) { settings::max_splits = std::stoi(get_node_value(root, "max_splits")); } + + if (check_for_node(root, "max_tracks")) { + settings::max_tracks = std::stoi(get_node_value(root, "max_tracks")); + } } void free_memory_settings() diff --git a/src/simulation.cpp b/src/simulation.cpp index 728de8a85..b70535c33 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -517,18 +517,7 @@ void initialize_history(Particle& p, int64_t index_source) p.trace() = true; // Set particle track. - p.write_track() = false; - if (settings::write_all_tracks) { - p.write_track() = true; - } else if (settings::track_identifiers.size() > 0) { - for (const auto& t : settings::track_identifiers) { - if (simulation::current_batch == t[0] && - simulation::current_gen == t[1] && p.id() == t[2]) { - p.write_track() = true; - break; - } - } - } + p.write_track() = check_track_criteria(p); // Display message if high verbosity or trace is on if (settings::verbosity >= 9 || p.trace()) { diff --git a/src/track_output.cpp b/src/track_output.cpp index a5d4e6c2f..f74920bbe 100644 --- a/src/track_output.cpp +++ b/src/track_output.cpp @@ -21,8 +21,9 @@ namespace openmc { // Global variables //============================================================================== -hid_t track_file; //! HDF5 identifier for track file -hid_t track_dtype; //! HDF5 identifier for track datatype +hid_t track_file; //! HDF5 identifier for track file +hid_t track_dtype; //! HDF5 identifier for track datatype +int n_tracks_written; //! Number of tracks written //============================================================================== // Non-member functions @@ -81,6 +82,33 @@ void close_track_file() { H5Tclose(track_dtype); file_close(track_file); + + // Reset number of tracks written + n_tracks_written = 0; +} + +bool check_track_criteria(const Particle& p) +{ + if (settings::write_all_tracks) { + // Increment number of tracks written and get previous value + int n; +#pragma omp atomic capture + n = n_tracks_written++; + + // Indicate that track should be written for this particle + return n < settings::max_tracks; + } + + // Check for match from explicit track identifiers + if (settings::track_identifiers.size() > 0) { + for (const auto& t : settings::track_identifiers) { + if (simulation::current_batch == t[0] && + simulation::current_gen == t[1] && p.id() == t[2]) { + return true; + } + } + } + return false; } void finalize_particle_track(Particle& p) diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 72b930b29..b21c036fa 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -14,6 +14,7 @@ def test_export_to_xml(run_in_tmpdir): s.keff_trigger = {'type': 'std_dev', 'threshold': 0.001} s.energy_mode = 'continuous-energy' s.max_order = 5 + s.max_tracks = 1234 s.source = openmc.Source(space=openmc.stats.Point()) s.output = {'summary': True, 'tallies': False, 'path': 'here'} s.verbosity = 7 @@ -71,6 +72,7 @@ def test_export_to_xml(run_in_tmpdir): assert s.keff_trigger == {'type': 'std_dev', 'threshold': 0.001} assert s.energy_mode == 'continuous-energy' assert s.max_order == 5 + assert s.max_tracks == 1234 assert isinstance(s.source[0], openmc.Source) assert isinstance(s.source[0].space, openmc.stats.Point) assert s.output == {'summary': True, 'tallies': False, 'path': 'here'} diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index a8b406c9c..b82ea8459 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -21,17 +21,16 @@ def sphere_model(): model.settings.run_mode = 'fixed source' model.settings.batches = 1 model.settings.particles = 100 - model.settings.track = [(1, 1, 1), (1, 1, 10), (1, 1, 75)] return model -def test_tracks(sphere_model, run_in_tmpdir): +def generate_track_file(model, **kwargs): # If running in MPI mode, setup proper keyword arguments for run() - kwargs = {'openmc_exec': config['exe']} + kwargs.setdefault('openmc_exec', config['exe']) if config['mpi']: kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']] - sphere_model.run(**kwargs) + model.run(**kwargs) if config['mpi'] and int(config['mpi_np']) > 1: # With MPI, we need to combine track files @@ -41,6 +40,14 @@ def test_tracks(sphere_model, run_in_tmpdir): track_file = Path('tracks.h5') assert track_file.is_file() + +def test_tracks(sphere_model, run_in_tmpdir): + # Set track identifiers + sphere_model.settings.track = [(1, 1, 1), (1, 1, 10), (1, 1, 75)] + + # Run OpenMC to generate tracks.h5 file + generate_track_file(sphere_model) + # Open track file and make sure we have correct number of tracks tracks = openmc.TrackFile('tracks.h5') assert len(tracks) == len(sphere_model.settings.track) @@ -79,3 +86,17 @@ def test_tracks(sphere_model, run_in_tmpdir): assert x.time == state['time'] assert x.wgt == state['wgt'] assert x.particle == particle_track.particle + + +def test_max_tracks(sphere_model, run_in_tmpdir): + # Set maximum number of tracks per process to write + sphere_model.settings.max_tracks = expected_num_tracks = 10 + if config['mpi']: + expected_num_tracks *= int(config['mpi_np']) + + # Run OpenMC to generate tracks.h5 file + generate_track_file(sphere_model, tracks=True) + + # Open track file and make sure we have correct number of tracks + tracks = openmc.TrackFile('tracks.h5') + assert len(tracks) == expected_num_tracks From e056180f7335a1734072c618a8635adb9fc6920e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 May 2022 10:41:38 -0500 Subject: [PATCH 0312/2654] Add doc section on particle track files to user's guide --- docs/source/pythonapi/base.rst | 1 + docs/source/usersguide/settings.rst | 76 ++++++++++++++++++++++++++++- openmc/trackfile.py | 24 ++++++--- 3 files changed, 94 insertions(+), 7 deletions(-) diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index a54d2ff35..bc4325ae5 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -185,6 +185,7 @@ Post-processing :template: myclass.rst openmc.Particle + openmc.ParticleTrack openmc.StatePoint openmc.Summary openmc.Track diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index dabad32bd..9802a93e3 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -514,4 +514,78 @@ As an example, to write a statepoint file every five batches:: settings.batches = n settings.statepoint = {'batches': range(5, n + 5, 5)} -.. _NIST ESTAR database: https://physics.nist.gov/PhysRefData/Star/Text/ESTAR.html +Particle Track Files +-------------------- + +OpenMC can generate a particle track file that contains track information +(position, direction, energy, time, weight, cell ID, and material ID) for each +state along a particle's history. There are two ways to indicate which particles +and/or how many particles should have their tracks written. First, you can +identify specific source particles by their batch, generation, and particle ID +numbers:: + + settings.tracks = [ + (1, 1, 50), + (2, 1, 30), + (5, 1, 75) + ] + +In this example, track information would be written for the 50th particle in the +1st generation of batch 1, the 30th particle in the first generation of batch 2, +and the 75th particle in the 1st generation of batch 5. Unless you are using +more than one generation per batch (see :ref:`usersguide_particles`), the +generation number should be 1. Alternatively, you can run OpenMC in a mode where +track information is written for *all* particles, up to a user-specified limit:: + + openmc.run(tracks=True) + +In this case, you can control the maximum number of source particles for which +tracks will be written as follows:: + + settings.max_tracks = 1000 + +Particle track information is written to the ``tracks.h5`` file, which can be +analyzed using the :class:`~openmc.TrackFile` class:: + + >>> tracks = openmc.TrackFile('tracks.h5') + >>> tracks + [, + , + ] + +Each :class:`~openmc.Track` object stores a list of track information for every +primary/secondary particle. In the above example, the first source particle +produced 150 secondary particles for a total of 151 particles. Information for +each primary/secondary particle can be accessed using the +:attr:`~openmc.Track.particles` attribute:: + + >>> first_track = tracks[0] + >>> len(first_track.particles) + 151 + >>> photon = first_track.particles[10] + ParticleTrack(particle=, states=array([...])) + +The :class:`~openmc.ParticleTrack` class is a named tuple indicating the particle +type and then a NumPy array of the "states". The states array is a compound type +with a field for each physical quantity (position, direction, energy, time, +weight, cell ID, and material ID). For example, to get the position for the +above particle track:: + + >>> photon.states['r'] + array([(-11.92987939, -12.28467295, 0.67837495), + (-11.95213726, -12.2682 , 0.68783964), + (-12.2682 , -12.03428339, 0.82223855), + (-12.5913778 , -11.79510096, 0.95966298), + (-12.6622572 , -11.74264344, 0.98980293), + (-12.6907775 , -11.7215357 , 1.00193058)], + dtype=[('x', ' Date: Fri, 20 May 2022 12:59:50 -0500 Subject: [PATCH 0313/2654] Mention multiple track files when run with MPI in documentation --- docs/source/usersguide/scripts.rst | 4 +++- docs/source/usersguide/settings.rst | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst index f38e1fd16..50d51a5b3 100644 --- a/docs/source/usersguide/scripts.rst +++ b/docs/source/usersguide/scripts.rst @@ -112,7 +112,7 @@ otherwise. tallies. The path to the statepoint file can be provided as an optional arugment (if omitted, a file dialog will be presented). -.. _scripts_track: +.. _scripts_track_combine: ------------------------ ``openmc-track-combine`` @@ -125,6 +125,8 @@ filename can also be changed with the ``-o`` flag: -o OUT, --out OUT Output HDF5 particle track file +.. _scripts_track: + ----------------------- ``openmc-track-to-vtk`` ----------------------- diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index 9802a93e3..db06d8a0e 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -589,3 +589,13 @@ The full list of fields is as follows: :wgt: Weight :cell_id: Cell ID :material_id: Material ID + +.. note:: If you are using an MPI-enabled install of OpenMC and run a simulation + with more than one process, a separate track file will be written for + each MPI process with the filename ``tracks_p#.h5`` where # is the + rank of the corresponding process. Multiple track files can be + combined with the :ref:`scripts_track_combine` script: + + .. code-block:: sh + + openmc-track-combine tracks_p*.h5 --out tracks.h5 From c73a4d2e158214477f1100751bcfef0da5ae6089 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 May 2022 13:01:09 -0500 Subject: [PATCH 0314/2654] Make sure track file unit test uses reproducible cell/material IDs --- tests/unit_tests/test_tracks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index b82ea8459..11febea26 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -9,6 +9,7 @@ from tests.testing_harness import config @pytest.fixture def sphere_model(): + openmc.reset_auto_ids() mat = openmc.Material() mat.add_nuclide('Zr90', 1.0) mat.set_density('g/cm3', 1.0) From 2e0472d57c6731b61ec20cf828c075f8c03b8f19 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 23 May 2022 12:28:28 -0500 Subject: [PATCH 0315/2654] Respond to @shimwell comments on #2071 --- docs/source/io_formats/track.rst | 12 +- include/openmc/particle_data.h | 14 +- openmc/settings.py | 3 + openmc/source.py | 2 +- openmc/trackfile.py | 23 ++- .../track_output/results_true.dat | 147 ++++++++++++++---- .../track_output/settings.xml | 2 +- tests/unit_tests/test_tracks.py | 20 ++- 8 files changed, 174 insertions(+), 49 deletions(-) diff --git a/docs/source/io_formats/track.rst b/docs/source/io_formats/track.rst index 113f0cf14..59947ef22 100644 --- a/docs/source/io_formats/track.rst +++ b/docs/source/io_formats/track.rst @@ -19,12 +19,18 @@ The current revision of the particle track file format is 3.0. ``E``, ``time``, ``wgt``, ``cell_id``, and ``material_id``, which represent the position (each coordinate in [cm]), direction, energy in [eV], time in [s], weight, cell ID, and material ID, - respectively. + respectively. When the particle is present in a cell with no + material assigned, the material ID is given as -1. Note that this + array contains information for one or more primary/secondary + particles originating. The starting index for each + primary/secondary particle is given by the ``offsets`` attribute. :Attributes: - **n_particles** (*int*) -- Number of primary/secondary particles for the source history. - - **offsets** (*int[]*) Offset into the array for each - primary/secondary particle. + - **offsets** (*int[]*) Offset (starting index) into + the array for each primary/secondary particle. The + last offset should match the total size of the + array. - **particles** (*int[]*) -- Particle type for each primary/secondary particle (0=neutron, 1=photon, 2=electron, 3=positron). diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 3e6c8515c..434d58c23 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -58,13 +58,13 @@ struct SourceSite { //! State of a particle used for particle track files struct TrackState { - Position r; - Direction u; - double E; - double time {0.0}; - double wgt {1.0}; - int cell_id; - int material_id {-1}; + Position r; //!< Position in [cm] + Direction u; //!< Direction + double E; //!< Energy in [eV] + double time {0.0}; //!< Time in [s] + double wgt {1.0}; //!< Weight + int cell_id; //!< Cell ID + int material_id {-1}; //!< Material ID (default value indicates void) }; //! Full history of a single particle's track states diff --git a/openmc/settings.py b/openmc/settings.py index 641e68524..2d8121659 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -795,6 +795,9 @@ class Settings: cv.check_greater_than('track batch', t[0], 0) cv.check_greater_than('track generation', t[1], 0) cv.check_greater_than('track particle', t[2], 0) + cv.check_type('track batch', t[0], Integral) + cv.check_type('track generation', t[1], Integral) + cv.check_type('track particle', t[2], Integral) self._track = track @ufs_mesh.setter diff --git a/openmc/source.py b/openmc/source.py index 572333e37..bd4c28ba4 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -300,7 +300,7 @@ class SourceParticle: def __repr__(self): name = self.particle.name.lower() - return f'' + return f'' def to_tuple(self): """Return source particle attributes as a tuple diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 94e9aeb75..6c94b6a04 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -74,6 +74,12 @@ class Track: ---------- axes : matplotlib.axes.Axes, optional Axes for plot + + Returns + ------- + axes : matplotlib.axes.Axes + Axes for plot + """ import matplotlib.pyplot as plt @@ -92,8 +98,7 @@ class Track: r = states['r'] ax.plot3D(r['x'], r['y'], r['z']) - if axes is None: - plt.show() + return ax @property def sources(self): @@ -135,13 +140,23 @@ class TrackFile(list): self.append(Track(dset)) def plot(self): - """Produce a 3D plot of particle tracks""" + """Produce a 3D plot of particle tracks + + Returns + ------- + matplotlib.axes.Axes + Axes for plot + + """ import matplotlib.pyplot as plt fig = plt.figure() ax = plt.axes(projection='3d') + ax.set_xlabel('x [cm]') + ax.set_ylabel('y [cm]') + ax.set_zlabel('z [cm]') for track in self: track.plot(ax) - plt.show() + return ax @staticmethod def combine(track_files, path='tracks.h5'): diff --git a/tests/regression_tests/track_output/results_true.dat b/tests/regression_tests/track_output/results_true.dat index 981625bf7..ee8913019 100644 --- a/tests/regression_tests/track_output/results_true.dat +++ b/tests/regression_tests/track_output/results_true.dat @@ -145,30 +145,125 @@ ((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 1), ((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 1)], dtype=[('r', [('x', ', states=array([((-9.896300e-01, -6.241550e-01, 7.890184e-01), (-4.012123e-01, 9.073327e-01, 1.256028e-01), 4.434429e+05, 0.000000e+00, 1.000000e+00, 23, 1), - ((-1.124354e+00, -3.194804e-01, 8.311948e-01), (-4.012123e-01, 9.073327e-01, 1.256028e-01), 4.434429e+05, 3.646971e-10, 1.000000e+00, 22, 3), - ((-1.169278e+00, -2.178843e-01, 8.452588e-01), (-4.012123e-01, 9.073327e-01, 1.256028e-01), 4.434429e+05, 4.863081e-10, 1.000000e+00, 21, 2), - ((-1.200617e+00, -1.470127e-01, 8.550696e-01), (4.985110e-01, -3.420076e-01, -7.965661e-01), 4.374324e+05, 5.711419e-10, 1.000000e+00, 21, 2), - ((-1.153218e+00, -1.795315e-01, 7.793306e-01), (4.985110e-01, -3.420076e-01, -7.965661e-01), 4.374324e+05, 6.751152e-10, 1.000000e+00, 22, 3), - ((-1.078639e+00, -2.306964e-01, 6.601629e-01), (4.985110e-01, -3.420076e-01, -7.965661e-01), 4.374324e+05, 8.387067e-10, 1.000000e+00, 23, 1), - ((-8.498389e-01, -3.876669e-01, 2.945646e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 1.340594e-09, 1.000000e+00, 23, 1), - ((-8.178800e-01, -6.225680e-01, 3.627213e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 2.978729e-09, 1.000000e+00, 11, 1), - ((-7.913073e-01, -8.178800e-01, 4.193912e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 4.340781e-09, 1.000000e+00, 23, 1), - ((-5.687582e-01, -2.453640e+00, 8.940079e-01), (1.295621e-01, -9.522956e-01, 2.763092e-01), 1.185198e+04, 1.574812e-08, 1.000000e+00, 23, 1), - ((-5.396956e-01, -2.667253e+00, 9.559878e-01), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 1.723779e-08, 1.000000e+00, 23, 1), - ((-2.229408e-01, -2.711251e+00, 1.160371e+00), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 2.412440e-08, 1.000000e+00, 22, 3), - ((3.672002e-01, -2.793223e+00, 1.541154e+00), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 3.695471e-08, 1.000000e+00, 23, 1), - ((8.178800e-01, -2.855823e+00, 1.831950e+00), (8.346010e-01, -1.159281e-01, 5.385183e-01), 1.587581e+03, 4.675299e-08, 1.000000e+00, 23, 1), - ((8.973133e-01, -2.866857e+00, 1.883204e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 4.847996e-08, 1.000000e+00, 23, 1), - ((1.109695e+00, -2.976801e+00, 1.896325e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 5.375585e-08, 1.000000e+00, 22, 3), - ((1.188016e+00, -3.017346e+00, 1.901163e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 5.570149e-08, 1.000000e+00, 21, 2), - ((2.101785e+00, -3.490379e+00, 1.957615e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 7.840096e-08, 1.000000e+00, 22, 3), - ((2.180107e+00, -3.530924e+00, 1.962454e+00), (8.867277e-01, -4.590349e-01, 5.478139e-02), 1.077251e+03, 8.034660e-08, 1.000000e+00, 23, 1), - ((2.331655e+00, -3.609377e+00, 1.971817e+00), (5.352328e-01, -1.825854e-01, 8.247353e-01), 3.972292e+02, 8.411129e-08, 1.000000e+00, 23, 1), - ((2.453640e+00, -3.650990e+00, 2.159783e+00), (5.352328e-01, -1.825854e-01, 8.247353e-01), 3.972292e+02, 9.237876e-08, 1.000000e+00, 11, 1), - ((3.052522e+00, -3.855288e+00, 3.082595e+00), (-6.240259e-01, 3.743550e-01, 6.858936e-01), 7.908847e+00, 1.329675e-07, 1.000000e+00, 11, 1), - ((2.955791e+00, -3.797259e+00, 3.188916e+00), (-8.018916e-01, -4.124485e-01, 4.322686e-01), 3.121121e+00, 1.728180e-07, 1.000000e+00, 11, 1), - ((2.937908e+00, -3.806457e+00, 3.198556e+00), (-4.476221e-02, -9.803939e-01, -1.918959e-01), 1.564715e+00, 1.819446e-07, 1.000000e+00, 11, 1), - ((2.924989e+00, -4.089400e+00, 3.143175e+00), (-4.476221e-02, -9.803939e-01, -1.918959e-01), 1.564715e+00, 3.487493e-07, 1.000000e+00, 23, 1), - ((2.922113e+00, -4.152398e+00, 3.130844e+00), (-4.476221e-02, -9.803939e-01, -1.918959e-01), 1.564715e+00, 3.858887e-07, 0.000000e+00, 23, 1)], +[ParticleTrack(particle=, states=array([((6.474155e+00, -5.192870e+00, 5.413003e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2), + ((6.467293e+00, -5.416535e+00, 5.441544e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450870e-05, 1.000000e+00, 22, 3), + ((6.464574e+00, -5.505149e+00, 5.452851e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450874e-05, 1.000000e+00, 23, 1), + ((6.461877e+00, -5.593034e+00, 5.464065e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450879e-05, 1.000000e+00, 23, 1), + ((6.570892e+00, -5.725160e+00, 5.464970e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450891e-05, 1.000000e+00, 32, 1), + ((6.821003e+00, -6.028296e+00, 5.467047e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450917e-05, 1.000000e+00, 31, 4), + ((7.101210e+00, -6.367908e+00, 5.469374e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450947e-05, 1.000000e+00, 32, 1), + ((7.360920e+00, -6.682677e+00, 5.471531e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450975e-05, 1.000000e+00, 23, 1), + ((7.833926e+00, -7.255962e+00, 5.475459e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451025e-05, 1.000000e+00, 23, 1), + ((8.142528e+00, -7.144944e+00, 5.464309e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451091e-05, 1.000000e+00, 22, 3), + ((8.590199e+00, -6.983897e+00, 5.448136e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451187e-05, 1.000000e+00, 23, 1), + ((8.682515e+00, -6.950687e+00, 5.444801e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451207e-05, 1.000000e+00, 23, 1), + ((8.996680e+00, -6.629985e+00, 5.450966e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451307e-05, 1.000000e+00, 23, 1), + ((9.231138e+00, -6.390649e+00, 5.455567e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451382e-05, 1.000000e+00, 22, 3), + ((9.650189e+00, -5.962879e+00, 5.463790e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451516e-05, 1.000000e+00, 23, 1), + ((9.721007e+00, -5.890588e+00, 5.465180e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451539e-05, 1.000000e+00, 23, 1), + ((9.939012e+00, -5.953026e+00, 5.222655e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451775e-05, 1.000000e+00, 22, 3), + ((1.002133e+01, -5.976602e+00, 5.131083e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451864e-05, 1.000000e+00, 23, 1), + ((1.020258e+01, -6.028514e+00, 4.929446e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452060e-05, 1.000000e+00, 23, 1), + ((1.063244e+01, -6.047973e+00, 4.703991e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452432e-05, 1.000000e+00, 23, 1), + ((1.084241e+01, -6.057477e+00, 4.593868e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452614e-05, 1.000000e+00, 23, 1), + ((1.107130e+01, -6.074053e+00, 4.699070e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452930e-05, 1.000000e+00, 22, 3), + ((1.121611e+01, -6.084540e+00, 4.765623e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453130e-05, 1.000000e+00, 21, 2), + ((1.174815e+01, -6.123069e+00, 5.010155e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453866e-05, 1.000000e+00, 22, 3), + ((1.189296e+01, -6.133556e+00, 5.076709e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.454067e-05, 1.000000e+00, 23, 1), + ((1.221698e+01, -6.157021e+00, 5.225634e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454515e-05, 1.000000e+00, 23, 1), + ((1.226820e+01, -6.225607e+00, 5.179351e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454893e-05, 1.000000e+00, 23, 1), + ((1.230378e+01, -6.273253e+00, 5.147199e+00), (9.203567e-01, -2.667811e-01, -2.859569e-01), 2.269067e+02, 4.455157e-05, 1.000000e+00, 23, 1), + ((1.237909e+01, -6.295083e+00, 5.123800e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.455549e-05, 1.000000e+00, 23, 1), + ((1.250758e+01, -6.372926e+00, 5.147974e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456396e-05, 1.000000e+00, 22, 3), + ((1.258603e+01, -6.420455e+00, 5.162734e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456914e-05, 1.000000e+00, 21, 2), + ((1.264082e+01, -6.453648e+00, 5.173042e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.457275e-05, 1.000000e+00, 21, 2), + ((1.288240e+01, -7.015898e+00, 5.025449e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.460837e-05, 1.000000e+00, 22, 3), + ((1.292943e+01, -7.125332e+00, 4.996722e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.461530e-05, 1.000000e+00, 23, 1), + ((1.303065e+01, -7.360920e+00, 4.934879e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.463022e-05, 1.000000e+00, 23, 1), + ((1.309295e+01, -7.505897e+00, 4.896822e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.463941e-05, 1.000000e+00, 23, 1), + ((1.311741e+01, -7.576618e+00, 4.913644e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.464426e-05, 1.000000e+00, 22, 3), + ((1.314895e+01, -7.667795e+00, 4.935331e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.465052e-05, 1.000000e+00, 21, 2), + ((1.345125e+01, -8.541749e+00, 5.143210e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471053e-05, 1.000000e+00, 22, 3), + ((1.348278e+01, -8.632925e+00, 5.164897e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471679e-05, 1.000000e+00, 23, 1), + ((1.356121e+01, -8.859646e+00, 5.218825e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.473236e-05, 1.000000e+00, 23, 1), + ((1.361604e+01, -8.996680e+00, 5.275368e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.474248e-05, 1.000000e+00, 23, 1), + ((1.390396e+01, -9.716172e+00, 5.572247e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.479558e-05, 1.000000e+00, 23, 1), + ((1.399742e+01, -9.949713e+00, 5.668611e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.481282e-05, 1.000000e+00, 23, 1), + ((1.390396e+01, -1.004824e+01, 5.750282e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.483180e-05, 1.000000e+00, 23, 1), + ((1.334984e+01, -1.063244e+01, 6.234531e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.494435e-05, 1.000000e+00, 23, 1), + ((1.317711e+01, -1.081455e+01, 6.385480e+00), (-4.211158e-01, -4.515418e-01, 7.866203e-01), 3.302717e+01, 4.497943e-05, 1.000000e+00, 23, 1), + ((1.316679e+01, -1.082561e+01, 6.404749e+00), (-5.182259e-01, 3.860612e-01, 7.631505e-01), 1.437084e+01, 4.498251e-05, 1.000000e+00, 23, 1), + ((1.292206e+01, -1.064329e+01, 6.765147e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.507257e-05, 1.000000e+00, 23, 1), + ((1.286229e+01, -1.063244e+01, 6.805923e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.508772e-05, 1.000000e+00, 23, 1), + ((1.284917e+01, -1.063006e+01, 6.814880e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509105e-05, 1.000000e+00, 23, 1), + ((1.284547e+01, -1.063244e+01, 6.820442e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509285e-05, 1.000000e+00, 23, 1), + ((1.249929e+01, -1.085555e+01, 7.341246e+00), (-1.520079e-01, -3.513652e-01, 9.238161e-01), 7.069024e+00, 4.526201e-05, 1.000000e+00, 23, 1), + ((1.240103e+01, -1.108268e+01, 7.938428e+00), (-7.405967e-01, -3.230926e-01, 5.891754e-01), 4.460475e+00, 4.543779e-05, 1.000000e+00, 23, 1), + ((1.229354e+01, -1.112958e+01, 8.023945e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.548748e-05, 1.000000e+00, 23, 1), + ((1.226820e+01, -1.110933e+01, 8.041241e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.550624e-05, 1.000000e+00, 23, 1), + ((1.198501e+01, -1.088299e+01, 8.234567e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.571593e-05, 1.000000e+00, 23, 1), + ((1.156403e+01, -1.063244e+01, 8.480859e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.600087e-05, 1.000000e+00, 23, 1), + ((1.150264e+01, -1.059590e+01, 8.516776e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.604243e-05, 1.000000e+00, 23, 1), + ((1.121659e+01, -1.063244e+01, 8.744860e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.623561e-05, 1.000000e+00, 23, 1), + ((1.063244e+01, -1.070706e+01, 9.210632e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.663011e-05, 1.000000e+00, 23, 1), + ((1.035391e+01, -1.074263e+01, 9.432717e+00), (-4.847677e-01, -8.685325e-01, -1.032060e-01), 5.647686e-01, 4.681821e-05, 1.000000e+00, 23, 1), + ((1.031409e+01, -1.081397e+01, 9.424239e+00), (-4.227592e-01, -9.022601e-01, -8.486053e-02), 5.651902e-01, 4.689723e-05, 1.000000e+00, 23, 1), + ((1.028497e+01, -1.087614e+01, 9.418392e+00), (1.549579e-01, -4.270887e-01, 8.908329e-01), 5.395517e-01, 4.696349e-05, 1.000000e+00, 23, 1), + ((1.034128e+01, -1.103135e+01, 9.742126e+00), (5.631544e-01, 4.925564e-01, 6.635098e-01), 2.637257e-01, 4.732118e-05, 1.000000e+00, 23, 1), + ((1.044415e+01, -1.094137e+01, 9.863334e+00), (-1.034377e-01, 7.912271e-01, 6.027108e-01), 1.474934e-01, 4.757836e-05, 1.000000e+00, 23, 1), + ((1.043959e+01, -1.090643e+01, 9.889950e+00), (1.163182e-01, 9.160889e-01, -3.837331e-01), 1.522434e-01, 4.766149e-05, 1.000000e+00, 23, 1), + ((1.045733e+01, -1.076664e+01, 9.831395e+00), (-8.136862e-01, 9.805444e-02, -5.729748e-01), 3.341488e-02, 4.794423e-05, 1.000000e+00, 23, 1), + ((1.044231e+01, -1.076483e+01, 9.820815e+00), (-8.437241e-01, 5.222731e-01, -1.239373e-01), 3.874838e-02, 4.801727e-05, 1.000000e+00, 23, 1), + ((1.028725e+01, -1.066884e+01, 9.798037e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.869227e-05, 1.000000e+00, 23, 1), + ((1.021310e+01, -1.063244e+01, 9.757708e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.902498e-05, 1.000000e+00, 23, 1), + ((1.012717e+01, -1.059025e+01, 9.710967e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 4.941058e-05, 1.000000e+00, 23, 1), + ((1.001043e+01, -1.038486e+01, 9.645483e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 5.039049e-05, 1.000000e+00, 22, 3), + ((9.971285e+00, -1.031600e+01, 9.623530e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.071901e-05, 1.000000e+00, 22, 3), + ((1.002723e+01, -1.037881e+01, 9.564267e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.116633e-05, 1.000000e+00, 23, 1), + ((1.025152e+01, -1.063060e+01, 9.326683e+00), (-8.159392e-01, -4.792697e-03, 5.781179e-01), 2.920905e-02, 5.295966e-05, 1.000000e+00, 23, 1), + ((1.000779e+01, -1.063203e+01, 9.499373e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422329e-05, 1.000000e+00, 23, 1), + ((1.000721e+01, -1.063244e+01, 9.498835e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422746e-05, 1.000000e+00, 23, 1), + ((9.852478e+00, -1.074269e+01, 9.354584e+00), (-6.686452e-01, -2.988396e-01, 6.808880e-01), 2.993224e-02, 5.534454e-05, 1.000000e+00, 23, 1), + ((9.765042e+00, -1.078177e+01, 9.443621e+00), (7.712484e-01, -5.215773e-01, 3.648739e-01), 3.590785e-02, 5.589099e-05, 1.000000e+00, 23, 1), + ((9.798992e+00, -1.080472e+01, 9.459682e+00), (-4.563170e-01, 8.081811e-01, -3.723144e-01), 2.674168e-02, 5.605894e-05, 1.000000e+00, 23, 1), + ((9.792857e+00, -1.079386e+01, 9.454677e+00), (-9.080336e-01, 4.172659e-01, 3.693418e-02), 9.753404e-03, 5.611838e-05, 1.000000e+00, 23, 1), + ((9.653805e+00, -1.072996e+01, 9.460332e+00), (-3.727950e-01, 2.889342e-01, -8.817828e-01), 1.781716e-02, 5.723944e-05, 1.000000e+00, 23, 1), + ((9.628677e+00, -1.071048e+01, 9.400895e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.760453e-05, 1.000000e+00, 23, 1), + ((9.563380e+00, -1.063244e+01, 9.395105e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.815928e-05, 1.000000e+00, 23, 1), + ((9.411305e+00, -1.045068e+01, 9.381621e+00), (3.205568e-01, -1.311309e-02, -9.471385e-01), 2.153422e-02, 5.945128e-05, 1.000000e+00, 23, 1), + ((9.860026e+00, -1.046903e+01, 8.055798e+00), (6.278124e-01, 1.023095e-01, -7.716115e-01), 2.013742e-02, 6.634788e-05, 1.000000e+00, 23, 1), + ((1.007604e+01, -1.043383e+01, 7.790303e+00), (6.790346e-01, 5.167838e-01, 5.213891e-01), 1.340865e-02, 6.810089e-05, 1.000000e+00, 23, 1), + ((1.008869e+01, -1.042421e+01, 7.800011e+00), (2.792456e-01, 1.367953e-01, 9.504257e-01), 8.576635e-03, 6.821715e-05, 1.000000e+00, 23, 1), + ((1.017046e+01, -1.038415e+01, 8.078330e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.050324e-05, 1.000000e+00, 23, 1), + ((1.008276e+01, -1.035463e+01, 8.083559e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.070353e-05, 1.000000e+00, 22, 3), + ((9.952201e+00, -1.031068e+01, 8.091343e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.100170e-05, 1.000000e+00, 21, 2), + ((9.404929e+00, -1.012646e+01, 8.123973e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.225157e-05, 1.000000e+00, 22, 3), + ((9.274369e+00, -1.008251e+01, 8.131758e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.254974e-05, 1.000000e+00, 23, 1), + ((9.126730e+00, -1.003281e+01, 8.140560e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.288692e-05, 1.000000e+00, 23, 1), + ((8.996680e+00, -1.006767e+01, 8.217365e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.321528e-05, 1.000000e+00, 23, 1), + ((8.694758e+00, -1.014859e+01, 8.395674e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.397758e-05, 1.000000e+00, 23, 1), + ((8.996680e+00, -9.720167e+00, 8.656770e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.511228e-05, 1.000000e+00, 23, 1), + ((9.263031e+00, -9.342216e+00, 8.887105e+00), (5.734531e-01, -5.017666e-01, 6.475970e-01), 9.798082e-02, 7.611330e-05, 1.000000e+00, 23, 1), + ((9.334809e+00, -9.405021e+00, 8.968164e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.640240e-05, 1.000000e+00, 23, 1), + ((9.335117e+00, -9.448857e+00, 8.932084e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.651925e-05, 1.000000e+00, 22, 3), + ((9.336345e+00, -9.623801e+00, 8.788098e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.698556e-05, 1.000000e+00, 21, 2), + ((9.339070e+00, -1.001201e+01, 8.468584e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.802034e-05, 1.000000e+00, 22, 3), + ((9.340298e+00, -1.018696e+01, 8.324598e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.848665e-05, 1.000000e+00, 23, 1), + ((9.343193e+00, -1.059945e+01, 7.985097e+00), (1.798796e-01, 3.522536e-02, -9.830577e-01), 1.283272e-01, 7.958616e-05, 1.000000e+00, 23, 1), + ((9.397753e+00, -1.058877e+01, 7.686922e+00), (6.459563e-01, 7.279465e-03, -7.633397e-01), 1.319449e-01, 8.019832e-05, 1.000000e+00, 23, 1), + ((9.462343e+00, -1.058804e+01, 7.610595e+00), (-5.748716e-01, 5.760301e-01, -5.811299e-01), 8.880732e-02, 8.039733e-05, 1.000000e+00, 23, 1), + ((9.287877e+00, -1.041322e+01, 7.434230e+00), (-4.932135e-03, 1.668926e-01, 9.859627e-01), 3.503028e-02, 8.113361e-05, 1.000000e+00, 23, 1), + ((9.286930e+00, -1.038117e+01, 7.623600e+00), (-9.325544e-02, -9.933000e-01, -6.825369e-02), 3.173764e-02, 8.187553e-05, 1.000000e+00, 23, 1), + ((9.283901e+00, -1.041342e+01, 7.621384e+00), (-4.235208e-01, -5.129112e-01, 7.466942e-01), 4.258127e-02, 8.200731e-05, 1.000000e+00, 23, 1), + ((9.264517e+00, -1.043690e+01, 7.655560e+00), (-7.165846e-01, 3.926265e-01, 5.764988e-01), 4.485063e-02, 8.216767e-05, 1.000000e+00, 23, 1), + ((9.256348e+00, -1.043242e+01, 7.662132e+00), (1.703748e-01, -9.175599e-01, -3.592441e-01), 3.521226e-02, 8.220659e-05, 1.000000e+00, 23, 1), + ((9.284015e+00, -1.058143e+01, 7.603793e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.283227e-05, 1.000000e+00, 23, 1), + ((9.309126e+00, -1.063244e+01, 7.631745e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.309804e-05, 1.000000e+00, 23, 1), + ((9.317824e+00, -1.065011e+01, 7.641427e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.319011e-05, 1.000000e+00, 23, 1), + ((9.459378e+00, -1.063244e+01, 7.505770e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.403060e-05, 1.000000e+00, 23, 1), + ((9.492454e+00, -1.062831e+01, 7.474071e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.422700e-05, 1.000000e+00, 23, 1), + ((9.492472e+00, -1.063244e+01, 7.472688e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.424159e-05, 1.000000e+00, 23, 1), + ((9.492761e+00, -1.069927e+01, 7.450302e+00), (9.457151e-01, -1.928731e-01, 2.615777e-01), 4.542312e-02, 8.447773e-05, 1.000000e+00, 23, 1), + ((9.890524e+00, -1.078039e+01, 7.560320e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.590450e-05, 1.000000e+00, 23, 1), + ((1.004645e+01, -1.080498e+01, 7.439717e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.651090e-05, 0.000000e+00, 23, 1)], dtype=[('r', [('x', ' 1 1 1 1 1 30 - 1 1 60 + 2 1 60 diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index 11febea26..fa3640f34 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -20,8 +20,8 @@ def sphere_model(): model.geometry = openmc.Geometry([cell]) model.settings.run_mode = 'fixed source' - model.settings.batches = 1 - model.settings.particles = 100 + model.settings.batches = 2 + model.settings.particles = 50 return model @@ -42,9 +42,13 @@ def generate_track_file(model, **kwargs): assert track_file.is_file() -def test_tracks(sphere_model, run_in_tmpdir): +@pytest.mark.parametrize("particle", ["neutron", "photon"]) +def test_tracks(sphere_model, particle, run_in_tmpdir): # Set track identifiers - sphere_model.settings.track = [(1, 1, 1), (1, 1, 10), (1, 1, 75)] + sphere_model.settings.track = [(1, 1, 1), (1, 1, 10), (2, 1, 15)] + + # Set source particle + sphere_model.settings.source = openmc.Source(particle=particle) # Run OpenMC to generate tracks.h5 file generate_track_file(sphere_model) @@ -58,12 +62,14 @@ def test_tracks(sphere_model, run_in_tmpdir): assert isinstance(track, openmc.Track) assert track.identifier == identifier assert isinstance(track.particles, list) - assert len(track.particles) == 1 + if particle == 'neutron': + assert len(track.particles) == 1 # Check attributes on ParticleTrack object particle_track = track.particles[0] assert isinstance(particle_track, openmc.ParticleTrack) - assert particle_track.particle == openmc.ParticleType.NEUTRON + + assert particle_track.particle.name.lower() == particle assert isinstance(particle_track.states, np.ndarray) # Sanity checks on actual data @@ -78,7 +84,7 @@ def test_tracks(sphere_model, run_in_tmpdir): # Checks on 'sources' property sources = track.sources - assert len(sources) == 1 + assert len(sources) == len(track.particles) x = sources[0] state = particle_track.states[0] assert x.r == (*state['r'],) From 6865b03d35e54a3e9a3704584ee467494d6156b0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 23 May 2022 12:33:12 -0500 Subject: [PATCH 0316/2654] Disabled GNU extensions for openmc, libopenmc CMake targets --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f0d4807a..3cf72db20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -455,9 +455,10 @@ target_compile_options(openmc PRIVATE ${cxxflags}) target_include_directories(openmc PRIVATE ${CMAKE_BINARY_DIR}/include) target_link_libraries(openmc libopenmc) -# Ensure C++14 standard is used +# Ensure C++14 standard is used and turn off GNU extensions target_compile_features(openmc PUBLIC cxx_std_14) target_compile_features(libopenmc PUBLIC cxx_std_14) +set_target_properties(openmc libopenmc PROPERTIES CXX_EXTENSIONS OFF) #=============================================================================== # Python package From d20064945cad54e2b9e3c27844046ccd8cf14ae5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 07:11:37 -0500 Subject: [PATCH 0317/2654] Read in color specification in Plot.from_xml_element --- openmc/plots.py | 32 +++++++++++++++++++------------- tests/unit_tests/test_plots.py | 2 ++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/openmc/plots.py b/openmc/plots.py index 5e9c48413..a1933cb5c 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -213,8 +213,8 @@ class Plot(IDManagerMixin): The basis directions for the plot background : Iterable of int or str Color of the background - mask_components : Iterable of openmc.Cell or openmc.Material - The cells or materials to plot + mask_components : Iterable of openmc.Cell or openmc.Material or int + The cells or materials (or corresponding IDs) to mask mask_background : Iterable of int or str Color to apply to all cells/materials not listed in mask_components show_overlaps : bool @@ -222,8 +222,10 @@ class Plot(IDManagerMixin): overlap_color : Iterable of int or str Color to apply to overlapping regions colors : dict - Dictionary indicating that certain cells/materials (keys) should be - displayed with a particular color. + Dictionary indicating that certain cells/materials should be + displayed with a particular color. The keys can be of type + :class:`~openmc.Cell`, :class:`~openmc.Material`, or int (ID for a + cell/material). level : int Universe depth to plot at meshlines : dict @@ -373,14 +375,15 @@ class Plot(IDManagerMixin): def colors(self, colors): cv.check_type('plot colors', colors, Mapping) for key, value in colors.items(): - cv.check_type('plot color key', key, (openmc.Cell, openmc.Material)) + cv.check_type('plot color key', key, + (openmc.Cell, openmc.Material, Integral)) self._check_color('plot color value', value) self._colors = colors @mask_components.setter def mask_components(self, mask_components): cv.check_type('plot mask components', mask_components, Iterable, - (openmc.Cell, openmc.Material)) + (openmc.Cell, openmc.Material, Integral)) self._mask_components = mask_components @mask_background.setter @@ -634,11 +637,15 @@ class Plot(IDManagerMixin): color = _SVG_COLORS[color.lower()] subelement.text = ' '.join(str(x) for x in color) + # Helper function to handle either int or Cell/Material + def get_id(domain): + return getattr(domain, 'id', domain) + if self._colors: for domain, color in sorted(self._colors.items(), - key=lambda x: x[0].id): + key=lambda x: get_id(x[0])): subelement = ET.SubElement(element, "color") - subelement.set("id", str(domain.id)) + subelement.set("id", str(get_id(domain))) if isinstance(color, str): color = _SVG_COLORS[color.lower()] subelement.set("rgb", ' '.join(str(x) for x in color)) @@ -646,7 +653,7 @@ class Plot(IDManagerMixin): if self._mask_components is not None: subelement = ET.SubElement(element, "mask") subelement.set("components", ' '.join( - str(d.id) for d in self._mask_components)) + str(get_id(d)) for d in self._mask_components)) color = self._mask_background if color is not None: if isinstance(color, str): @@ -720,15 +727,14 @@ class Plot(IDManagerMixin): # Set plot colors colors = {} for color_elem in elem.findall("color"): - uid = color_elem.get("id") + uid = int(color_elem.get("id")) colors[uid] = tuple([int(x) for x in color_elem.get("rgb").split()]) - # TODO: set colors (needs geometry information) + plot.colors = colors # Set masking information mask_elem = elem.find("mask") if mask_elem is not None: - mask_components = [int(x) for x in mask_elem.get("components").split()] - # TODO: set mask components (needs geometry information) + plot.mask_components = [int(x) for x in mask_elem.get("components").split()] background = mask_elem.get("background") if background is not None: plot.mask_background = tuple([int(x) for x in background.split()]) diff --git a/tests/unit_tests/test_plots.py b/tests/unit_tests/test_plots.py index 718f098ba..f61b52604 100644 --- a/tests/unit_tests/test_plots.py +++ b/tests/unit_tests/test_plots.py @@ -92,6 +92,7 @@ def test_xml_element(myplot): def test_plots(run_in_tmpdir): p1 = openmc.Plot(name='plot1') p1.origin = (5., 5., 5.) + p1.colors = {10: (255, 100, 0)} p2 = openmc.Plot(name='plot2') p2.origin = (-3., -3., -3.) plots = openmc.Plots([p1, p2]) @@ -107,4 +108,5 @@ def test_plots(run_in_tmpdir): new_plots = openmc.Plots.from_xml() assert len(plots) assert plots[0].origin == p1.origin + assert plots[0].colors == p1.colors assert plots[1].origin == p2.origin From 321de2a4d106d50ff712b22e35e71e47e6dae5ef Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 09:09:51 -0500 Subject: [PATCH 0318/2654] Fix reading rotation matrix from XML --- openmc/cell.py | 5 ++++- tests/unit_tests/test_cell.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/openmc/cell.py b/openmc/cell.py index feba18da5..103a34fe6 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -690,7 +690,10 @@ class Cell(IDManagerMixin): for key in ('temperature', 'rotation', 'translation'): value = get_text(elem, key) if value is not None: - setattr(c, key, [float(x) for x in value.split()]) + values = [float(x) for x in value.split()] + if key == 'rotation' and len(values) == 9: + values = np.array(values).reshape(3, 3) + setattr(c, key, values) # Add this cell to appropriate universe univ_id = int(get_text(elem, 'universe', 0)) diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 9234e7e4b..faecf0b63 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -297,3 +297,20 @@ def test_to_xml_element(cell_with_lattice): elem = c.create_xml_subelement(root) assert elem.get('region') == str(c.region) assert elem.get('temperature') == str(c.temperature) + + +@pytest.mark.parametrize("rotation", [ + (90, 45, 0), + [[1.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, -1.0, 0.0]] +]) +def test_rotation_from_xml(rotation): + # Make sure rotation attribute (matrix) round trips through XML correctly + s = openmc.ZCylinder(r=10.0) + cell = openmc.Cell(region=-s) + cell.rotation = rotation + root = ET.Element('geometry') + elem = cell.create_xml_subelement(root) + new_cell = openmc.Cell.from_xml_element( + elem, {s.id: s}, {'void': None}, openmc.Universe + ) + np.testing.assert_allclose(new_cell.rotation, cell.rotation) From 773749c2b67447dc31f0ded6a2e26f9f15daf707 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 10:57:09 -0500 Subject: [PATCH 0319/2654] Mention units in surface docstrings --- openmc/surface.py | 204 +++++++++++++++++++++++----------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/openmc/surface.py b/openmc/surface.py index 926b2fedc..b3bcebb11 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -760,7 +760,7 @@ class XPlane(PlaneMixin, Surface): Parameters ---------- x0 : float, optional - Location of the plane. Defaults to 0. + Location of the plane in [cm]. Defaults to 0. boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles @@ -775,7 +775,7 @@ class XPlane(PlaneMixin, Surface): Attributes ---------- x0 : float - Location of the plane + Location of the plane in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -819,7 +819,7 @@ class YPlane(PlaneMixin, Surface): Parameters ---------- y0 : float, optional - Location of the plane + Location of the plane in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles @@ -834,7 +834,7 @@ class YPlane(PlaneMixin, Surface): Attributes ---------- y0 : float - Location of the plane + Location of the plane in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -878,7 +878,7 @@ class ZPlane(PlaneMixin, Surface): Parameters ---------- z0 : float, optional - Location of the plane. Defaults to 0. + Location of the plane in [cm]. Defaults to 0. boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles @@ -893,7 +893,7 @@ class ZPlane(PlaneMixin, Surface): Attributes ---------- z0 : float - Location of the plane + Location of the plane in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -991,8 +991,8 @@ class QuadricMixin: Parameters ---------- point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. + The Cartesian coordinates, :math:`(x',y',z')`, in [cm] at which the + surface equation should be evaluated. Returns ------- @@ -1106,13 +1106,13 @@ class Cylinder(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate for the origin of the Cylinder. Defaults to 0 + x-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 y0 : float, optional - y-coordinate for the origin of the Cylinder. Defaults to 0 + y-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 z0 : float, optional - z-coordinate for the origin of the Cylinder. Defaults to 0 + z-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 r : float, optional - Radius of the cylinder. Defaults to 1. + Radius of the cylinder in [cm]. Defaults to 1. dx : float, optional x-component of the vector representing the axis of the cylinder. Defaults to 0. @@ -1136,13 +1136,13 @@ class Cylinder(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate for the origin of the Cylinder + x-coordinate for the origin of the Cylinder in [cm] y0 : float - y-coordinate for the origin of the Cylinder + y-coordinate for the origin of the Cylinder in [cm] z0 : float - z-coordinate for the origin of the Cylinder + z-coordinate for the origin of the Cylinder in [cm] r : float - Radius of the cylinder + Radius of the cylinder in [cm] dx : float x-component of the vector representing the axis of the cylinder dy : float @@ -1243,7 +1243,7 @@ class Cylinder(QuadricMixin, Surface): p1, p2 : 3-tuples Points that pass through the plane, p1 will be used as (x0, y0, z0) r : float, optional - Radius of the cylinder. Defaults to 1. + Radius of the cylinder in [cm]. Defaults to 1. kwargs : dict Keyword arguments passed to the :class:`Cylinder` constructor @@ -1288,11 +1288,11 @@ class XCylinder(QuadricMixin, Surface): Parameters ---------- y0 : float, optional - y-coordinate for the origin of the Cylinder. Defaults to 0 + y-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 z0 : float, optional - z-coordinate for the origin of the Cylinder. Defaults to 0 + z-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 r : float, optional - Radius of the cylinder. Defaults to 1. + Radius of the cylinder in [cm]. Defaults to 1. boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles @@ -1307,11 +1307,11 @@ class XCylinder(QuadricMixin, Surface): Attributes ---------- y0 : float - y-coordinate for the origin of the Cylinder + y-coordinate for the origin of the Cylinder in [cm] z0 : float - z-coordinate for the origin of the Cylinder + z-coordinate for the origin of the Cylinder in [cm] r : float - Radius of the cylinder + Radius of the cylinder in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -1379,11 +1379,11 @@ class YCylinder(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate for the origin of the Cylinder. Defaults to 0 + x-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 z0 : float, optional - z-coordinate for the origin of the Cylinder. Defaults to 0 + z-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 r : float, optional - Radius of the cylinder. Defaults to 1. + Radius of the cylinder in [cm]. Defaults to 1. boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles @@ -1398,11 +1398,11 @@ class YCylinder(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate for the origin of the Cylinder + x-coordinate for the origin of the Cylinder in [cm] z0 : float - z-coordinate for the origin of the Cylinder + z-coordinate for the origin of the Cylinder in [cm] r : float - Radius of the cylinder + Radius of the cylinder in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -1470,11 +1470,11 @@ class ZCylinder(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate for the origin of the Cylinder. Defaults to 0 + x-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 y0 : float, optional - y-coordinate for the origin of the Cylinder. Defaults to 0 + y-coordinate for the origin of the Cylinder in [cm]. Defaults to 0 r : float, optional - Radius of the cylinder. Defaults to 1. + Radius of the cylinder in [cm]. Defaults to 1. boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles @@ -1489,11 +1489,11 @@ class ZCylinder(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate for the origin of the Cylinder + x-coordinate for the origin of the Cylinder in [cm] y0 : float - y-coordinate for the origin of the Cylinder + y-coordinate for the origin of the Cylinder in [cm] r : float - Radius of the cylinder + Radius of the cylinder in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -1560,13 +1560,13 @@ class Sphere(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate of the center of the sphere. Defaults to 0. + x-coordinate of the center of the sphere in [cm]. Defaults to 0. y0 : float, optional - y-coordinate of the center of the sphere. Defaults to 0. + y-coordinate of the center of the sphere in [cm]. Defaults to 0. z0 : float, optional - z-coordinate of the center of the sphere. Defaults to 0. + z-coordinate of the center of the sphere in [cm]. Defaults to 0. r : float, optional - Radius of the sphere. Defaults to 1. + Radius of the sphere in [cm]. Defaults to 1. boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles @@ -1580,13 +1580,13 @@ class Sphere(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate of the center of the sphere + x-coordinate of the center of the sphere in [cm] y0 : float - y-coordinate of the center of the sphere + y-coordinate of the center of the sphere in [cm] z0 : float - z-coordinate of the center of the sphere + z-coordinate of the center of the sphere in [cm] r : float - Radius of the sphere + Radius of the sphere in [cm] boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -1653,11 +1653,11 @@ class Cone(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate of the apex. Defaults to 0. + x-coordinate of the apex in [cm]. Defaults to 0. y0 : float, optional - y-coordinate of the apex. Defaults to 0. + y-coordinate of the apex in [cm]. Defaults to 0. z0 : float, optional - z-coordinate of the apex. Defaults to 0. + z-coordinate of the apex in [cm]. Defaults to 0. r2 : float, optional Parameter related to the aperature. Defaults to 1. dx : float, optional @@ -1682,11 +1682,11 @@ class Cone(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate of the apex + x-coordinate of the apex in [cm] y0 : float - y-coordinate of the apex + y-coordinate of the apex in [cm] z0 : float - z-coordinate of the apex + z-coordinate of the apex in [cm] r2 : float Parameter related to the aperature dx : float @@ -1796,11 +1796,11 @@ class XCone(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate of the apex. Defaults to 0. + x-coordinate of the apex in [cm]. Defaults to 0. y0 : float, optional - y-coordinate of the apex. Defaults to 0. + y-coordinate of the apex in [cm]. Defaults to 0. z0 : float, optional - z-coordinate of the apex. Defaults to 0. + z-coordinate of the apex in [cm]. Defaults to 0. r2 : float, optional Parameter related to the aperature. Defaults to 1. boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional @@ -1816,11 +1816,11 @@ class XCone(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate of the apex + x-coordinate of the apex in [cm] y0 : float - y-coordinate of the apex + y-coordinate of the apex in [cm] z0 : float - z-coordinate of the apex + z-coordinate of the apex in [cm] r2 : float Parameter related to the aperature boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} @@ -1885,11 +1885,11 @@ class YCone(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate of the apex. Defaults to 0. + x-coordinate of the apex in [cm]. Defaults to 0. y0 : float, optional - y-coordinate of the apex. Defaults to 0. + y-coordinate of the apex in [cm]. Defaults to 0. z0 : float, optional - z-coordinate of the apex. Defaults to 0. + z-coordinate of the apex in [cm]. Defaults to 0. r2 : float, optional Parameter related to the aperature. Defaults to 1. boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional @@ -1905,11 +1905,11 @@ class YCone(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate of the apex + x-coordinate of the apex in [cm] y0 : float - y-coordinate of the apex + y-coordinate of the apex in [cm] z0 : float - z-coordinate of the apex + z-coordinate of the apex in [cm] r2 : float Parameter related to the aperature boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} @@ -1974,11 +1974,11 @@ class ZCone(QuadricMixin, Surface): Parameters ---------- x0 : float, optional - x-coordinate of the apex. Defaults to 0. + x-coordinate of the apex in [cm]. Defaults to 0. y0 : float, optional - y-coordinate of the apex. Defaults to 0. + y-coordinate of the apex in [cm]. Defaults to 0. z0 : float, optional - z-coordinate of the apex. Defaults to 0. + z-coordinate of the apex in [cm]. Defaults to 0. r2 : float, optional Parameter related to the aperature. Defaults to 1. boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional @@ -1994,11 +1994,11 @@ class ZCone(QuadricMixin, Surface): Attributes ---------- x0 : float - x-coordinate of the apex + x-coordinate of the apex in [cm] y0 : float - y-coordinate of the apex + y-coordinate of the apex in [cm] z0 : float - z-coordinate of the apex + z-coordinate of the apex in [cm] r2 : float Parameter related to the aperature boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} @@ -2198,34 +2198,34 @@ class XTorus(TorusMixin, Surface): Parameters ---------- x0 : float - x-coordinate of the center of the axis of revolution + x-coordinate of the center of the axis of revolution in [cm] y0 : float - y-coordinate of the center of the axis of revolution + y-coordinate of the center of the axis of revolution in [cm] z0 : float - z-coordinate of the center of the axis of revolution + z-coordinate of the center of the axis of revolution in [cm] a : float - Major radius of the torus + Major radius of the torus in [cm] b : float - Minor radius of the torus (parallel to axis of revolution) + Minor radius of the torus in [cm] (parallel to axis of revolution) c : float - Minor radius of the torus (perpendicular to axis of revolution) + Minor radius of the torus in [cm] (perpendicular to axis of revolution) kwargs : dict Keyword arguments passed to the :class:`Surface` constructor Attributes ---------- x0 : float - x-coordinate of the center of the axis of revolution + x-coordinate of the center of the axis of revolution in [cm] y0 : float - y-coordinate of the center of the axis of revolution + y-coordinate of the center of the axis of revolution in [cm] z0 : float - z-coordinate of the center of the axis of revolution + z-coordinate of the center of the axis of revolution in [cm] a : float - Major radius of the torus + Major radius of the torus in [cm] b : float - Minor radius of the torus (parallel to axis of revolution) + Minor radius of the torus in [cm] (parallel to axis of revolution) c : float - Minor radius of the torus (perpendicular to axis of revolution) + Minor radius of the torus in [cm] (perpendicular to axis of revolution) boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} Boundary condition that defines the behavior for particles hitting the surface. @@ -2269,32 +2269,32 @@ class YTorus(TorusMixin, Surface): Parameters ---------- x0 : float - x-coordinate of the center of the axis of revolution + x-coordinate of the center of the axis of revolution in [cm] y0 : float - y-coordinate of the center of the axis of revolution + y-coordinate of the center of the axis of revolution in [cm] z0 : float - z-coordinate of the center of the axis of revolution + z-coordinate of the center of the axis of revolution in [cm] a : float - Major radius of the torus + Major radius of the torus in [cm] b : float - Minor radius of the torus (parallel to axis of revolution) + Minor radius of the torus in [cm] (parallel to axis of revolution) c : float - Minor radius of the torus (perpendicular to axis of revolution) + Minor radius of the torus in [cm] (perpendicular to axis of revolution) kwargs : dict Keyword arguments passed to the :class:`Surface` constructor Attributes ---------- x0 : float - x-coordinate of the center of the axis of revolution + x-coordinate of the center of the axis of revolution in [cm] y0 : float - y-coordinate of the center of the axis of revolution + y-coordinate of the center of the axis of revolution in [cm] z0 : float - z-coordinate of the center of the axis of revolution + z-coordinate of the center of the axis of revolution in [cm] a : float - Major radius of the torus + Major radius of the torus in [cm] b : float - Minor radius of the torus (parallel to axis of revolution) + Minor radius of the torus in [cm] (parallel to axis of revolution) c : float Minor radius of the torus (perpendicular to axis of revolution) boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} @@ -2340,34 +2340,34 @@ class ZTorus(TorusMixin, Surface): Parameters ---------- x0 : float - x-coordinate of the center of the axis of revolution + x-coordinate of the center of the axis of revolution in [cm] y0 : float - y-coordinate of the center of the axis of revolution + y-coordinate of the center of the axis of revolution in [cm] z0 : float - z-coordinate of the center of the axis of revolution + z-coordinate of the center of the axis of revolution in [cm] a : float - Major radius of the torus + Major radius of the torus in [cm] b : float - Minor radius of the torus (parallel to axis of revolution) + Minor radius of the torus in [cm] (parallel to axis of revolution) c : float - Minor radius of the torus (perpendicular to axis of revolution) + Minor radius of the torus in [cm] (perpendicular to axis of revolution) kwargs : dict Keyword arguments passed to the :class:`Surface` constructor Attributes ---------- x0 : float - x-coordinate of the center of the axis of revolution + x-coordinate of the center of the axis of revolution in [cm] y0 : float - y-coordinate of the center of the axis of revolution + y-coordinate of the center of the axis of revolution in [cm] z0 : float - z-coordinate of the center of the axis of revolution + z-coordinate of the center of the axis of revolution in [cm] a : float - Major radius of the torus + Major radius of the torus in [cm] b : float - Minor radius of the torus (parallel to axis of revolution) + Minor radius of the torus in [cm] (parallel to axis of revolution) c : float - Minor radius of the torus (perpendicular to axis of revolution) + Minor radius of the torus in [cm] (perpendicular to axis of revolution) boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} Boundary condition that defines the behavior for particles hitting the surface. From 66051251c00ebef8a873feab0bf3192b1724152e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 11:01:10 -0500 Subject: [PATCH 0320/2654] Fix method links in Material docstring --- openmc/material.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index e5c3f8e4b..de1b2187b 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -29,9 +29,9 @@ class Material(IDManagerMixin): To create a material, one should create an instance of this class, add nuclides or elements with :meth:`Material.add_nuclide` or - `Material.add_element`, respectively, and set the total material density - with `Material.set_density()`. The material can then be assigned to a cell - using the :attr:`Cell.fill` attribute. + :meth:`Material.add_element`, respectively, and set the total material + density with :meth:`Material.set_density()`. The material can then be + assigned to a cell using the :attr:`Cell.fill` attribute. Parameters ---------- From 90126846f44d4d90aee0eb487af4f27e497a5174 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 16 Mar 2022 13:30:54 -0400 Subject: [PATCH 0321/2654] adding centroids and meshgrid methods --- openmc/mesh.py | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 584ea81ce..76a527357 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -244,6 +244,70 @@ class RegularMesh(MeshBase): nx, = self.dimension return ((x,) for x in range(1, nx + 1)) + @property + def meshgrid(self): + """Return coordinates of mesh vertices + + Returns + ------- + coordinates : numpy.ndarray or tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + vertex coordinates. Each array has an identical shape equal to + (nx + 1, ny + 1, nz + 1) where nx, ny, nz = dimension. + + """ + ndim = len(self._dimension) + if ndim == 3: + x0, y0, z0 = self.lower_left + x1, y1, z1 = self.upper_right + nx, ny, nz = self.dimension + xarr = np.linspace(x0, x1, nx + 1) + yarr = np.linspace(y0, y1, ny + 1) + zarr = np.linspace(z0, z1, nz + 1) + return np.meshgrid(xarr, yarr, zarr, indexing='ij') + elif ndim == 2: + x0, y0 = self.lower_left + x1, y1 = self.upper_right + nx, ny = self.dimension + xarr = np.linspace(x0, x1, nx + 1) + yarr = np.linspace(y0, y1, ny + 1) + return np.meshgrid(xarr, yarr, indexing='ij') + else: + nx, = self.dimension + x0, = self.lower_left + x1, = self.upper_right + return np.linspace(x0, x1, nx + 1) + + @property + def centroids(self): + """Return coordinates of mesh element centroids + + Returns + ------- + coordinates : numpy.ndarray or tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + element centroid coordinates. Each array has an identical shape + equal to (nx, ny, nz) where nx, ny, nz = n_dimension. + + """ + ndim = len(self._dimension) + meshgrid = self.meshgrid + if ndim == 3: + xarr, yarr, zarr = meshgrid + xc = (xarr[:-1, :-1, :-1] + xarr[1:, 1:, 1:]) / 2 + yc = (yarr[:-1, :-1, :-1] + yarr[1:, 1:, 1:]) / 2 + zc = (zarr[:-1, :-1, :-1] + zarr[1:, 1:, 1:]) / 2 + return xc, yc, zc + elif ndim == 2: + xarr, yarr = meshgrid + xc = (xarr[:-1, :-1] + xarr[1:, 1:]) / 2 + yc = (yarr[:-1, :-1] + yarr[1:, 1:]) / 2 + return xc, yc + else: + xarr = meshgrid + xc = (xarr[:-1] + xarr[1:]) / 2 + return xc + @dimension.setter def dimension(self, dimension): cv.check_type('mesh dimension', dimension, Iterable, Integral) @@ -629,6 +693,38 @@ class RectilinearMesh(MeshBase): for y in range(1, ny + 1) for x in range(1, nx + 1)) + @property + def meshgrid(self): + """Return coordinates of mesh vertices + + Returns + ------- + coordinates : 3-tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + vertex coordinates. Each array has an identical shape equal to + (nx + 1, ny + 1, nz + 1) where nx, ny, nz = dimension. + + """ + return np.meshgrid(self.x_grid, self.y_grid, self.z_grid, indexing='ij') + + @property + def centroids(self): + """Return coordinates of mesh element centroids + + Returns + ------- + coordinates : 3-tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + element centroid coordinates. Each array has an identical shape + equal to (nx, ny, nz) where nx, ny, nz = n_dimension. + + """ + xx, yy, zz = self.meshgrid + xc = (xx[:-1, :-1, :-1] + xx[1:, 1:, 1:]) / 2 + yc = (yy[:-1, :-1, :-1] + yy[1:, 1:, 1:]) / 2 + zc = (zz[:-1, :-1, :-1] + zz[1:, 1:, 1:]) / 2 + return xc, yc, zc + @x_grid.setter def x_grid(self, grid): cv.check_type('mesh x_grid', grid, Iterable, Real) @@ -799,6 +895,38 @@ class CylindricalMesh(MeshBase): for p in range(1, np + 1) for r in range(1, nr + 1)) + @property + def meshgrid(self): + """Return coordinates of mesh vertices + + Returns + ------- + coordinates : 3-tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + vertex coordinates. Each array has an identical shape equal to + (nr + 1, nphi + 1, nz + 1) where nr, nphi, nz = dimension. + + """ + return np.meshgrid(self.r_grid, self.phi_grid, self.z_grid, indexing='ij') + + @property + def centroids(self): + """Return coordinates of mesh element centroids + + Returns + ------- + coordinates : 3-tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + element centroid coordinates. Each array has an identical shape + equal to (nx, nphi, nz) where nx, nphi, nz = n_dimension. + + """ + rr, pp, zz = self.meshgrid + rc = (rr[:-1, :-1, :-1] + rr[1:, 1:, 1:]) / 2 + pc = (pp[:-1, :-1, :-1] + pp[1:, 1:, 1:]) / 2 + zc = (zz[:-1, :-1, :-1] + zz[1:, 1:, 1:]) / 2 + return rc, pc, zc + @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) @@ -987,6 +1115,38 @@ class SphericalMesh(MeshBase): for t in range(1, nt + 1) for r in range(1, nr + 1)) + @property + def meshgrid(self): + """Return coordinates of mesh vertices + + Returns + ------- + coordinates : 3-tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + vertex coordinates. Each array has an identical shape equal to + (nr + 1, ntheta + 1, nphi + 1) where nr, ntheta, nphi = dimension. + + """ + return np.meshgrid(self.r_grid, self.phi_grid, self.z_grid, indexing='ij') + + @property + def centroids(self): + """Return coordinates of mesh element centroids + + Returns + ------- + coordinates : 3-tuple of numpy.ndarray + Returns a numpy.ndarray for each dimension representing the mesh + element centroid coordinates. Each array has an identical shape + equal to (nx, ntheta, nphi) where nx, ntheta, nphi = n_dimension. + + """ + rr, tt, pp = self.meshgrid + rc = (rr[:-1, :-1, :-1] + rr[1:, 1:, 1:]) / 2 + tc = (tt[:-1, :-1, :-1] + tt[1:, 1:, 1:]) / 2 + pc = (pp[:-1, :-1, :-1] + pp[1:, 1:, 1:]) / 2 + return rc, tc, pc + @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) From a93751ce7bcc5589a1dfa1c187c50f9ce6451c42 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 17 Mar 2022 10:39:22 -0400 Subject: [PATCH 0322/2654] changing meshgrid to vertices --- openmc/mesh.py | 85 ++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 76a527357..056dd34ac 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -245,15 +245,16 @@ class RegularMesh(MeshBase): return ((x,) for x in range(1, nx + 1)) @property - def meshgrid(self): + def vertices(self): """Return coordinates of mesh vertices Returns ------- - coordinates : numpy.ndarray or tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - vertex coordinates. Each array has an identical shape equal to - (nx + 1, ny + 1, nz + 1) where nx, ny, nz = dimension. + vertices : numpy.ndarray + Returns a numpy.ndarray representing the coordinates of mesh + vertices with a shape equal to (nx + 1, ny + 1, nz + 1, 3) + where nx, ny, nz = dimension in 3D. For 2D the shape is + (nx + 1, ny + 1, 2), and for 1D the shape is (nx,). """ ndim = len(self._dimension) @@ -264,14 +265,16 @@ class RegularMesh(MeshBase): xarr = np.linspace(x0, x1, nx + 1) yarr = np.linspace(y0, y1, ny + 1) zarr = np.linspace(z0, z1, nz + 1) - return np.meshgrid(xarr, yarr, zarr, indexing='ij') + xx, yy, zz = np.meshgrid(xarr, yarr, zarr, indexing='ij') + return np.stack((xx, yy, zz), axis=-1) elif ndim == 2: x0, y0 = self.lower_left x1, y1 = self.upper_right nx, ny = self.dimension xarr = np.linspace(x0, x1, nx + 1) yarr = np.linspace(y0, y1, ny + 1) - return np.meshgrid(xarr, yarr, indexing='ij') + xx, yy = np.meshgrid(xarr, yarr, indexing='ij') + return np.stack((xx, yy), axis=-1) else: nx, = self.dimension x0, = self.lower_left @@ -291,22 +294,13 @@ class RegularMesh(MeshBase): """ ndim = len(self._dimension) - meshgrid = self.meshgrid + vertices = self.vertices if ndim == 3: - xarr, yarr, zarr = meshgrid - xc = (xarr[:-1, :-1, :-1] + xarr[1:, 1:, 1:]) / 2 - yc = (yarr[:-1, :-1, :-1] + yarr[1:, 1:, 1:]) / 2 - zc = (zarr[:-1, :-1, :-1] + zarr[1:, 1:, 1:]) / 2 - return xc, yc, zc + return (vertices[:-1, :-1, :-1, :] + vertices[1:, 1:, 1:, :]) / 2 elif ndim == 2: - xarr, yarr = meshgrid - xc = (xarr[:-1, :-1] + xarr[1:, 1:]) / 2 - yc = (yarr[:-1, :-1] + yarr[1:, 1:]) / 2 - return xc, yc + return (vertices[:-1, :-1, :] + vertices[1:, 1:, :]) / 2 else: - xarr = meshgrid - xc = (xarr[:-1] + xarr[1:]) / 2 - return xc + return (vertices[:-1] + vertices[1:]) / 2 @dimension.setter def dimension(self, dimension): @@ -694,18 +688,19 @@ class RectilinearMesh(MeshBase): for x in range(1, nx + 1)) @property - def meshgrid(self): + def vertices(self): """Return coordinates of mesh vertices Returns ------- - coordinates : 3-tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - vertex coordinates. Each array has an identical shape equal to - (nx + 1, ny + 1, nz + 1) where nx, ny, nz = dimension. + vertices : numpy.ndarray + Returns a numpy.ndarray representing the coordinates of mesh + vertices with a shape equal to (nx + 1, ny + 1, nz + 1, 3) + where nx, ny, nz = dimension. """ - return np.meshgrid(self.x_grid, self.y_grid, self.z_grid, indexing='ij') + xx, yy, zz = np.meshgrid(self.x_grid, self.y_grid, self.z_grid, indexing='ij') + return np.stack((xx, yy, zz), axis=-1) @property def centroids(self): @@ -719,7 +714,7 @@ class RectilinearMesh(MeshBase): equal to (nx, ny, nz) where nx, ny, nz = n_dimension. """ - xx, yy, zz = self.meshgrid + xx, yy, zz = self.vertices xc = (xx[:-1, :-1, :-1] + xx[1:, 1:, 1:]) / 2 yc = (yy[:-1, :-1, :-1] + yy[1:, 1:, 1:]) / 2 zc = (zz[:-1, :-1, :-1] + zz[1:, 1:, 1:]) / 2 @@ -885,6 +880,10 @@ class CylindricalMesh(MeshBase): def z_grid(self): return self._z_grid + @property + def grids(self): + return (self.r_grid, self.phi_grid, self.z_grid) + @property def indices(self): nr, np, nz = self.dimension @@ -896,18 +895,18 @@ class CylindricalMesh(MeshBase): for r in range(1, nr + 1)) @property - def meshgrid(self): + def vertices(self): """Return coordinates of mesh vertices Returns ------- - coordinates : 3-tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - vertex coordinates. Each array has an identical shape equal to - (nr + 1, nphi + 1, nz + 1) where nr, nphi, nz = dimension. + vertices : numpy.ndarray + Returns a numpy.ndarray representing the coordinates of mesh + vertices with a shape equal to (nr + 1, nphi + 1, nz + 1, 3) + where nr, nphi, nz = dimension. """ - return np.meshgrid(self.r_grid, self.phi_grid, self.z_grid, indexing='ij') + return np.stack(np.meshgrid(*self.grids, indexing='ij'), axis=-1) @property def centroids(self): @@ -921,7 +920,7 @@ class CylindricalMesh(MeshBase): equal to (nx, nphi, nz) where nx, nphi, nz = n_dimension. """ - rr, pp, zz = self.meshgrid + rr, pp, zz = self.vertices rc = (rr[:-1, :-1, :-1] + rr[1:, 1:, 1:]) / 2 pc = (pp[:-1, :-1, :-1] + pp[1:, 1:, 1:]) / 2 zc = (zz[:-1, :-1, :-1] + zz[1:, 1:, 1:]) / 2 @@ -1116,18 +1115,22 @@ class SphericalMesh(MeshBase): for r in range(1, nr + 1)) @property - def meshgrid(self): + def vertices(self): """Return coordinates of mesh vertices Returns ------- - coordinates : 3-tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - vertex coordinates. Each array has an identical shape equal to - (nr + 1, ntheta + 1, nphi + 1) where nr, ntheta, nphi = dimension. + vertices : numpy.ndarray + Returns a numpy.ndarray representing the coordinates of mesh + vertices with a shape equal to (nr + 1, ntheta + 1, nphi + 1, 3) + where nr, ntheta, nphi = dimension. """ - return np.meshgrid(self.r_grid, self.phi_grid, self.z_grid, indexing='ij') + rr, tt, pp = np.meshgrid(self.r_grid, + self.theta_grid, + self.phi_grid, + indexing='ij') + return np.stack((rr, tt, pp), axis=-1) @property def centroids(self): @@ -1141,7 +1144,7 @@ class SphericalMesh(MeshBase): equal to (nx, ntheta, nphi) where nx, ntheta, nphi = n_dimension. """ - rr, tt, pp = self.meshgrid + rr, tt, pp = self.vertices rc = (rr[:-1, :-1, :-1] + rr[1:, 1:, 1:]) / 2 tc = (tt[:-1, :-1, :-1] + tt[1:, 1:, 1:]) / 2 pc = (pp[:-1, :-1, :-1] + pp[1:, 1:, 1:]) / 2 From 6167ae84dc57e3263cca79233a7b886ffae83849 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 17 Mar 2022 13:55:29 -0400 Subject: [PATCH 0323/2654] trying to define a clearer interface --- openmc/mesh.py | 198 +++++++++++++++---------------------------------- 1 file changed, 58 insertions(+), 140 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 056dd34ac..d81afb725 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -45,6 +45,51 @@ class MeshBase(IDManagerMixin, ABC): def name(self): return self._name + @property + @abstractmethod + def dimension(self): + pass + + @property + @abstractmethod + def n_dimension(self): + pass + + @property + @abstractmethod + def _grids(self): + pass + + @property + def vertices(self): + """Return coordinates of mesh vertices. + + Returns + ------- + vertices : numpy.ndarray + Returns a numpy.ndarray representing the coordinates of the mesh + vertices with a shape equal to (dim1 + 1, ..., dimn + 1, ndim). + + """ + return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) + + @property + def centroids(self): + """Return coordinates of mesh element centroids. + + Returns + ------- + centroids : numpy.ndarray + Returns a numpy.ndarray representing the mesh element centroid + coordinates with a shape equal to (dim1, ..., dimn, ndim). + + """ + ndim = len(self.dimension) + vertices = self.vertices + s0 = (slice(0, -1),)*ndim + (slice(None),) + s1 = (slice(1, None),)*ndim + (slice(None),) + return (vertices[s0] + vertices[s1]) / 2 + @name.setter def name(self, name): if name is not None: @@ -245,18 +290,7 @@ class RegularMesh(MeshBase): return ((x,) for x in range(1, nx + 1)) @property - def vertices(self): - """Return coordinates of mesh vertices - - Returns - ------- - vertices : numpy.ndarray - Returns a numpy.ndarray representing the coordinates of mesh - vertices with a shape equal to (nx + 1, ny + 1, nz + 1, 3) - where nx, ny, nz = dimension in 3D. For 2D the shape is - (nx + 1, ny + 1, 2), and for 1D the shape is (nx,). - - """ + def _grids(self): ndim = len(self._dimension) if ndim == 3: x0, y0, z0 = self.lower_left @@ -265,42 +299,19 @@ class RegularMesh(MeshBase): xarr = np.linspace(x0, x1, nx + 1) yarr = np.linspace(y0, y1, ny + 1) zarr = np.linspace(z0, z1, nz + 1) - xx, yy, zz = np.meshgrid(xarr, yarr, zarr, indexing='ij') - return np.stack((xx, yy, zz), axis=-1) + return (xarr, yarr, zarr) elif ndim == 2: x0, y0 = self.lower_left x1, y1 = self.upper_right nx, ny = self.dimension xarr = np.linspace(x0, x1, nx + 1) yarr = np.linspace(y0, y1, ny + 1) - xx, yy = np.meshgrid(xarr, yarr, indexing='ij') - return np.stack((xx, yy), axis=-1) + return (xarr, yarr) else: nx, = self.dimension x0, = self.lower_left x1, = self.upper_right - return np.linspace(x0, x1, nx + 1) - - @property - def centroids(self): - """Return coordinates of mesh element centroids - - Returns - ------- - coordinates : numpy.ndarray or tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - element centroid coordinates. Each array has an identical shape - equal to (nx, ny, nz) where nx, ny, nz = n_dimension. - - """ - ndim = len(self._dimension) - vertices = self.vertices - if ndim == 3: - return (vertices[:-1, :-1, :-1, :] + vertices[1:, 1:, 1:, :]) / 2 - elif ndim == 2: - return (vertices[:-1, :-1, :] + vertices[1:, 1:, :]) / 2 - else: - return (vertices[:-1] + vertices[1:]) / 2 + return (np.linspace(x0, x1, nx + 1),) @dimension.setter def dimension(self, dimension): @@ -656,6 +667,10 @@ class RectilinearMesh(MeshBase): def z_grid(self): return self._z_grid + @property + def _grids(self): + return (self.x_grid, self.y_grid, self.z_grid) + @property def volumes(self): """Return Volumes for every mesh cell @@ -687,39 +702,6 @@ class RectilinearMesh(MeshBase): for y in range(1, ny + 1) for x in range(1, nx + 1)) - @property - def vertices(self): - """Return coordinates of mesh vertices - - Returns - ------- - vertices : numpy.ndarray - Returns a numpy.ndarray representing the coordinates of mesh - vertices with a shape equal to (nx + 1, ny + 1, nz + 1, 3) - where nx, ny, nz = dimension. - - """ - xx, yy, zz = np.meshgrid(self.x_grid, self.y_grid, self.z_grid, indexing='ij') - return np.stack((xx, yy, zz), axis=-1) - - @property - def centroids(self): - """Return coordinates of mesh element centroids - - Returns - ------- - coordinates : 3-tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - element centroid coordinates. Each array has an identical shape - equal to (nx, ny, nz) where nx, ny, nz = n_dimension. - - """ - xx, yy, zz = self.vertices - xc = (xx[:-1, :-1, :-1] + xx[1:, 1:, 1:]) / 2 - yc = (yy[:-1, :-1, :-1] + yy[1:, 1:, 1:]) / 2 - zc = (zz[:-1, :-1, :-1] + zz[1:, 1:, 1:]) / 2 - return xc, yc, zc - @x_grid.setter def x_grid(self, grid): cv.check_type('mesh x_grid', grid, Iterable, Real) @@ -881,7 +863,7 @@ class CylindricalMesh(MeshBase): return self._z_grid @property - def grids(self): + def _grids(self): return (self.r_grid, self.phi_grid, self.z_grid) @property @@ -894,38 +876,6 @@ class CylindricalMesh(MeshBase): for p in range(1, np + 1) for r in range(1, nr + 1)) - @property - def vertices(self): - """Return coordinates of mesh vertices - - Returns - ------- - vertices : numpy.ndarray - Returns a numpy.ndarray representing the coordinates of mesh - vertices with a shape equal to (nr + 1, nphi + 1, nz + 1, 3) - where nr, nphi, nz = dimension. - - """ - return np.stack(np.meshgrid(*self.grids, indexing='ij'), axis=-1) - - @property - def centroids(self): - """Return coordinates of mesh element centroids - - Returns - ------- - coordinates : 3-tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - element centroid coordinates. Each array has an identical shape - equal to (nx, nphi, nz) where nx, nphi, nz = n_dimension. - - """ - rr, pp, zz = self.vertices - rc = (rr[:-1, :-1, :-1] + rr[1:, 1:, 1:]) / 2 - pc = (pp[:-1, :-1, :-1] + pp[1:, 1:, 1:]) / 2 - zc = (zz[:-1, :-1, :-1] + zz[1:, 1:, 1:]) / 2 - return rc, pc, zc - @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) @@ -1104,6 +1054,10 @@ class SphericalMesh(MeshBase): def phi_grid(self): return self._phi_grid + @property + def _grids(self): + return (self.r_grid, self.theta_grid, self.phi_grid) + @property def indices(self): nr, nt, np = self.dimension @@ -1114,42 +1068,6 @@ class SphericalMesh(MeshBase): for t in range(1, nt + 1) for r in range(1, nr + 1)) - @property - def vertices(self): - """Return coordinates of mesh vertices - - Returns - ------- - vertices : numpy.ndarray - Returns a numpy.ndarray representing the coordinates of mesh - vertices with a shape equal to (nr + 1, ntheta + 1, nphi + 1, 3) - where nr, ntheta, nphi = dimension. - - """ - rr, tt, pp = np.meshgrid(self.r_grid, - self.theta_grid, - self.phi_grid, - indexing='ij') - return np.stack((rr, tt, pp), axis=-1) - - @property - def centroids(self): - """Return coordinates of mesh element centroids - - Returns - ------- - coordinates : 3-tuple of numpy.ndarray - Returns a numpy.ndarray for each dimension representing the mesh - element centroid coordinates. Each array has an identical shape - equal to (nx, ntheta, nphi) where nx, ntheta, nphi = n_dimension. - - """ - rr, tt, pp = self.vertices - rc = (rr[:-1, :-1, :-1] + rr[1:, 1:, 1:]) / 2 - tc = (tt[:-1, :-1, :-1] + tt[1:, 1:, 1:]) / 2 - pc = (pp[:-1, :-1, :-1] + pp[1:, 1:, 1:]) / 2 - return rc, tc, pc - @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) From b5ed2b985f5142f985a04c152d707bb13d3f3f7b Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 4 May 2022 13:47:40 -0400 Subject: [PATCH 0324/2654] cleaning up a few syntax things --- openmc/mesh.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d81afb725..c6fa7bb99 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1,4 +1,4 @@ -from abc import ABC +from abc import ABC, abstractmethod from collections.abc import Iterable from math import pi from numbers import Real, Integral @@ -61,6 +61,7 @@ class MeshBase(IDManagerMixin, ABC): pass @property + @abstractmethod def vertices(self): """Return coordinates of mesh vertices. @@ -74,6 +75,7 @@ class MeshBase(IDManagerMixin, ABC): return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) @property + @abstractmethod def centroids(self): """Return coordinates of mesh element centroids. @@ -84,7 +86,7 @@ class MeshBase(IDManagerMixin, ABC): coordinates with a shape equal to (dim1, ..., dimn, ndim). """ - ndim = len(self.dimension) + ndim = self.n_dimension vertices = self.vertices s0 = (slice(0, -1),)*ndim + (slice(None),) s1 = (slice(1, None),)*ndim + (slice(None),) @@ -105,7 +107,7 @@ class MeshBase(IDManagerMixin, ABC): return string def _volume_dim_check(self): - if len(self.dimension) != 3 or \ + if self.n_dimension != 3 or \ any([d == 0 for d in self.dimension]): raise RuntimeError(f'Mesh {self.id} is not 3D. ' 'Volumes cannot be provided.') @@ -509,7 +511,7 @@ class RegularMesh(MeshBase): for entry in bc: cv.check_value('bc', entry, _BOUNDARY_TYPES) - n_dim = len(self.dimension) + n_dim = self.n_dimension # Build the cell which will contain the lattice xplanes = [openmc.XPlane(self.lower_left[0], boundary_type=bc[0]), @@ -1227,7 +1229,7 @@ class UnstructuredMesh(MeshBase): (1.0, 1.0, 1.0), ...] """ def __init__(self, filename, library, mesh_id=None, name='', - length_multiplier=1.0): + length_multiplier=1.0): super().__init__(mesh_id, name) self.filename = filename self._volumes = None @@ -1322,6 +1324,19 @@ class UnstructuredMesh(MeshBase): Real) self._length_multiplier = length_multiplier + @property + def dimension(self): + return self.n_elements + + @property + def n_dimension(self): + return 3 + + @property + def vertices(self): + raise NotImplementedError("Vertices for UnstructuredMesh objects are " + "not yet available") + def __repr__(self): string = super().__repr__() string += '{: <16}=\t{}\n'.format('\tFilename', self.filename) @@ -1452,7 +1467,7 @@ class UnstructuredMesh(MeshBase): subelement.text = self.filename if self._length_multiplier != 1.0: - element.set("length_multiplier", str(self.length_multiplier)) + element.set("length_multiplier", str(self.length_multiplier)) return element From 606d9bf03eb967064e0c0235b486f4cca479c896 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 4 May 2022 14:04:15 -0400 Subject: [PATCH 0325/2654] fixed abstractmethod error --- openmc/mesh.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index c6fa7bb99..491419778 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -61,7 +61,6 @@ class MeshBase(IDManagerMixin, ABC): pass @property - @abstractmethod def vertices(self): """Return coordinates of mesh vertices. @@ -75,7 +74,6 @@ class MeshBase(IDManagerMixin, ABC): return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) @property - @abstractmethod def centroids(self): """Return coordinates of mesh element centroids. From 45cb513b15cc1ec3c4fb80104dfaca3853b53ac0 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 24 May 2022 16:08:42 -0400 Subject: [PATCH 0326/2654] adding ABC for structured mesh --- openmc/mesh.py | 116 +++++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 491419778..3ae5ee43d 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -45,51 +45,6 @@ class MeshBase(IDManagerMixin, ABC): def name(self): return self._name - @property - @abstractmethod - def dimension(self): - pass - - @property - @abstractmethod - def n_dimension(self): - pass - - @property - @abstractmethod - def _grids(self): - pass - - @property - def vertices(self): - """Return coordinates of mesh vertices. - - Returns - ------- - vertices : numpy.ndarray - Returns a numpy.ndarray representing the coordinates of the mesh - vertices with a shape equal to (dim1 + 1, ..., dimn + 1, ndim). - - """ - return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) - - @property - def centroids(self): - """Return coordinates of mesh element centroids. - - Returns - ------- - centroids : numpy.ndarray - Returns a numpy.ndarray representing the mesh element centroid - coordinates with a shape equal to (dim1, ..., dimn, ndim). - - """ - ndim = self.n_dimension - vertices = self.vertices - s0 = (slice(0, -1),)*ndim + (slice(None),) - s1 = (slice(1, None),)*ndim + (slice(None),) - return (vertices[s0] + vertices[s1]) / 2 - @name.setter def name(self, name): if name is not None: @@ -171,7 +126,76 @@ class MeshBase(IDManagerMixin, ABC): raise ValueError(f'Unrecognized mesh type "{mesh_type}" found.') -class RegularMesh(MeshBase): +class StructuredMesh(ABC): + """A mixin for structured mesh functionality + + Parameters + ---------- + mesh_id : int + Unique identifier for the mesh + name : str + Name of the mesh + + Attributes + ---------- + id : int + Unique identifier for the mesh + name : str + Name of the mesh + + """ + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + @property + @abstractmethod + def dimension(self): + pass + + @property + @abstractmethod + def n_dimension(self): + pass + + @property + @abstractmethod + def _grids(self): + pass + + @property + def vertices(self): + """Return coordinates of mesh vertices. + + Returns + ------- + vertices : numpy.ndarray + Returns a numpy.ndarray representing the coordinates of the mesh + vertices with a shape equal to (dim1 + 1, ..., dimn + 1, ndim). + + """ + return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) + + @property + def centroids(self): + """Return coordinates of mesh element centroids. + + Returns + ------- + centroids : numpy.ndarray + Returns a numpy.ndarray representing the mesh element centroid + coordinates with a shape equal to (dim1, ..., dimn, ndim). + + """ + ndim = self.n_dimension + vertices = self.vertices + s0 = (slice(0, -1),)*ndim + (slice(None),) + s1 = (slice(1, None),)*ndim + (slice(None),) + return (vertices[s0] + vertices[s1]) / 2 + + + +class RegularMesh(StructuredMesh, MeshBase): """A regular Cartesian mesh in one, two, or three dimensions Parameters From 86e44c4e4a60db49365b8958128fcabd7cc8ba12 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Wed, 20 Apr 2022 10:55:15 +0100 Subject: [PATCH 0327/2654] Add regression test for new DAGUniverse constructor --- .../dagmc/external/__init__.py | 0 .../regression_tests/dagmc/external/dagmc.h5m | 1 + .../dagmc/external/inputs_true.dat | 39 ++++++ .../regression_tests/dagmc/external/main.cpp | 80 +++++++++++ .../dagmc/external/results_true.dat | 5 + tests/regression_tests/dagmc/external/test.py | 127 ++++++++++++++++++ 6 files changed, 252 insertions(+) create mode 100644 tests/regression_tests/dagmc/external/__init__.py create mode 120000 tests/regression_tests/dagmc/external/dagmc.h5m create mode 100644 tests/regression_tests/dagmc/external/inputs_true.dat create mode 100644 tests/regression_tests/dagmc/external/main.cpp create mode 100644 tests/regression_tests/dagmc/external/results_true.dat create mode 100644 tests/regression_tests/dagmc/external/test.py diff --git a/tests/regression_tests/dagmc/external/__init__.py b/tests/regression_tests/dagmc/external/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/dagmc/external/dagmc.h5m b/tests/regression_tests/dagmc/external/dagmc.h5m new file mode 120000 index 000000000..92c41719c --- /dev/null +++ b/tests/regression_tests/dagmc/external/dagmc.h5m @@ -0,0 +1 @@ +../legacy/dagmc.h5m \ No newline at end of file diff --git a/tests/regression_tests/dagmc/external/inputs_true.dat b/tests/regression_tests/dagmc/external/inputs_true.dat new file mode 100644 index 000000000..2f5641046 --- /dev/null +++ b/tests/regression_tests/dagmc/external/inputs_true.dat @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 0 + + + -4 -4 -4 4 4 4 + + + + + + + 1 + + + 1 + total + + diff --git a/tests/regression_tests/dagmc/external/main.cpp b/tests/regression_tests/dagmc/external/main.cpp new file mode 100644 index 000000000..87b1fcc8c --- /dev/null +++ b/tests/regression_tests/dagmc/external/main.cpp @@ -0,0 +1,80 @@ +#include "openmc/capi.h" +#include "openmc/cross_sections.h" +#include "openmc/dagmc.h" +#include "openmc/error.h" +#include "openmc/geometry.h" +#include "openmc/geometry_aux.h" +#include "openmc/nuclide.h" +#include + +int main(int argc, char* argv[]) +{ + using namespace openmc; + int openmc_err; + + // Initialise OpenMC + openmc_err = openmc_init(argc, argv, nullptr); + if (openmc_err == -1) { + // This happens for the -h and -v flags + return EXIT_SUCCESS; + } else if (openmc_err) { + fatal_error(openmc_err_msg); + } + + // Create DAGMC ptr + std::string filename = "dagmc.h5m"; + std::shared_ptr dag_ptr = std::make_shared(); + moab::ErrorCode rval = dag_ptr->load_file(filename.c_str()); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to load file"); + } + + // Initialize acceleration data structures + rval = dag_ptr->init_OBBTree(); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to initialise OBB tree"); + } + + // Get rid of existing geometry + std::unordered_map nuclide_map_copy = + openmc::data::nuclide_map; + openmc::data::nuclides.clear(); + openmc::data::nuclide_map = nuclide_map_copy; + openmc::model::surfaces.clear(); + openmc::model::surface_map.clear(); + openmc::model::cells.clear(); + openmc::model::cell_map.clear(); + openmc::model::universes.clear(); + openmc::model::universe_map.clear(); + + // Create new DAGMC universe + openmc::model::universes.push_back( + std::make_unique(dag_ptr, "")); + model::universe_map[model::universes.back()->id_] = + model::universes.size() - 1; + + // Add cells to universes + openmc::populate_universes(); + + // Set root universe + openmc::model::root_universe = openmc::find_root_universe(); + openmc::check_dagmc_root_univ(); + + // Final geometry setup and assign temperatures + openmc::finalize_geometry(); + + // Finalize cross sections having assigned temperatures + openmc::finalize_cross_sections(); + + // Run OpenMC + openmc_err = openmc_run(); + if (openmc_err) + fatal_error(openmc_err_msg); + + // Deallocate memory + openmc_err = openmc_finalize(); + if (openmc_err) + fatal_error(openmc_err_msg); + + return EXIT_SUCCESS; +} diff --git a/tests/regression_tests/dagmc/external/results_true.dat b/tests/regression_tests/dagmc/external/results_true.dat new file mode 100644 index 000000000..e5127c827 --- /dev/null +++ b/tests/regression_tests/dagmc/external/results_true.dat @@ -0,0 +1,5 @@ +k-combined: +8.426936E-01 5.715847E-02 +tally 1: +8.093843E+00 +1.328829E+01 diff --git a/tests/regression_tests/dagmc/external/test.py b/tests/regression_tests/dagmc/external/test.py new file mode 100644 index 000000000..c31d81440 --- /dev/null +++ b/tests/regression_tests/dagmc/external/test.py @@ -0,0 +1,127 @@ +from pathlib import Path +import os +import shutil +import subprocess +from subprocess import CalledProcessError +import textwrap +import glob +from itertools import product + +import openmc +import openmc.lib +import numpy as np +import pytest + +from tests.regression_tests import config +from tests.testing_harness import PyAPITestHarness + +pytestmark = pytest.mark.skipif( + not openmc.lib._dagmc_enabled(), + reason="DAGMC is not enabled.") + +TETS_PER_VOXEL = 12 + +# Test that an external DAGMC instance can be passed in through the C API + +@pytest.fixture +def cpp_driver(request): + """Compile the external source""" + + # Get build directory and write CMakeLists.txt file + openmc_dir = Path(str(request.config.rootdir)) / 'build' + with open('CMakeLists.txt', 'w') as f: + f.write(textwrap.dedent(""" + cmake_minimum_required(VERSION 3.3 FATAL_ERROR) + project(openmc_cpp_driver CXX) + add_executable(main main.cpp) + find_package(OpenMC REQUIRED HINTS {}) + target_link_libraries(main OpenMC::libopenmc) + set_target_properties(main PROPERTIES CXX_STANDARD + 14 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO) + set(CMAKE_CXX_FLAGS "-pedantic-errors") + add_compile_definitions(DAGMC=1) + """.format(openmc_dir))) + + # Create temporary build directory and change to there + local_builddir = Path('build') + local_builddir.mkdir(exist_ok=True) + os.chdir(str(local_builddir)) + + if config['mpi']: + os.environ['CXX'] = 'mpicxx' + + try: + print("Building driver") + # Run cmake/make to build the shared libary + subprocess.run(['cmake', os.path.pardir], check=True) + subprocess.run(['make'], check=True) + os.chdir(os.path.pardir) + + yield "./build/main" + + finally: + # Remove local build directory when test is complete + shutil.rmtree('build') + os.remove('CMakeLists.txt') + +@pytest.fixture +def model(): + model = openmc.model.Model() + + # Settings + model.settings.batches = 5 + model.settings.inactive = 0 + model.settings.particles = 100 + source_box = openmc.stats.Box([-4, -4, -4], + [ 4, 4, 4]) + source = openmc.Source(space=source_box) + model.settings.source = source + #model.settings.dagmc = True + + # Geometry + dag_univ = openmc.DAGMCUniverse("dagmc.h5m") + model.geometry = openmc.Geometry(dag_univ) + + # Tallies + tally = openmc.Tally() + tally.scores = ['total'] + tally.filters = [openmc.CellFilter(1)] + model.tallies = [tally] + + # Materials + u235 = openmc.Material(name="no-void fuel") + u235.add_nuclide('U235', 1.0, 'ao') + u235.set_density('g/cc', 11) + u235.id = 40 + water = openmc.Material(name="water") + water.add_nuclide('H1', 2.0, 'ao') + water.add_nuclide('O16', 1.0, 'ao') + water.set_density('g/cc', 1.0) + water.add_s_alpha_beta('c_H_in_H2O') + water.id = 41 + mats = openmc.Materials([u235, water]) + model.materials = mats + + return model + +class ExternalDAGMCTest(PyAPITestHarness): + def __init__(self, executable, statepoint_name, model): + super().__init__(statepoint_name, model) + self.executable = executable + + def _run_openmc(self): + if config['update']: + # Generate the results file with internal python API + openmc.run(openmc_exec=config['exe'], event_based=config['event']) + elif config['mpi']: + mpi_args = [config['mpiexec'], '-n', config['mpi_np']] + openmc.run(openmc_exec=self.executable, + mpi_args=mpi_args, + event_based=config['event']) + else: + openmc.run(openmc_exec=self.executable, + event_based=config['event']) + +def test_external_dagmc(cpp_driver, model): + harness = ExternalDAGMCTest(cpp_driver,'statepoint.5.h5',model) + harness.main() From c35b710a1560857fe24c0ec5418f8aef1c1152f5 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Wed, 20 Apr 2022 14:35:51 +0100 Subject: [PATCH 0328/2654] Update external dagmc regression test to include an update of material temperatures --- tests/regression_tests/dagmc/external/inputs_true.dat | 1 + tests/regression_tests/dagmc/external/main.cpp | 9 +++++++++ tests/regression_tests/dagmc/external/test.py | 6 +++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/regression_tests/dagmc/external/inputs_true.dat b/tests/regression_tests/dagmc/external/inputs_true.dat index 2f5641046..dd75bbdbd 100644 --- a/tests/regression_tests/dagmc/external/inputs_true.dat +++ b/tests/regression_tests/dagmc/external/inputs_true.dat @@ -26,6 +26,7 @@ -4 -4 -4 4 4 4 + 293 diff --git a/tests/regression_tests/dagmc/external/main.cpp b/tests/regression_tests/dagmc/external/main.cpp index 87b1fcc8c..6d9c97f59 100644 --- a/tests/regression_tests/dagmc/external/main.cpp +++ b/tests/regression_tests/dagmc/external/main.cpp @@ -4,6 +4,7 @@ #include "openmc/error.h" #include "openmc/geometry.h" #include "openmc/geometry_aux.h" +#include "openmc/material.h" #include "openmc/nuclide.h" #include @@ -66,6 +67,14 @@ int main(int argc, char* argv[]) // Finalize cross sections having assigned temperatures openmc::finalize_cross_sections(); + // Check that we correctly assigned cell temperatures with non-void fill + for (auto& cell_ptr : openmc::model::cells) { + if (cell_ptr->material_.front() != openmc::C_NONE && + cell_ptr->temperature() != 300) { + fatal_error("Failed to set cell temperature"); + } + } + // Run OpenMC openmc_err = openmc_run(); if (openmc_err) diff --git a/tests/regression_tests/dagmc/external/test.py b/tests/regression_tests/dagmc/external/test.py index c31d81440..a9fa9e3ee 100644 --- a/tests/regression_tests/dagmc/external/test.py +++ b/tests/regression_tests/dagmc/external/test.py @@ -64,7 +64,7 @@ def cpp_driver(request): shutil.rmtree('build') os.remove('CMakeLists.txt') -@pytest.fixture +@pytest.fixture def model(): model = openmc.model.Model() @@ -76,7 +76,7 @@ def model(): [ 4, 4, 4]) source = openmc.Source(space=source_box) model.settings.source = source - #model.settings.dagmc = True + model.settings.temperature['default'] = 293 # Geometry dag_univ = openmc.DAGMCUniverse("dagmc.h5m") @@ -103,7 +103,7 @@ def model(): model.materials = mats return model - + class ExternalDAGMCTest(PyAPITestHarness): def __init__(self, executable, statepoint_name, model): super().__init__(statepoint_name, model) From 751e92f63b79e3c2027be4e31469337c3192e336 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Wed, 20 Apr 2022 15:48:39 +0100 Subject: [PATCH 0329/2654] Run clang-format --- include/openmc/dagmc.h | 17 ++++++++--------- src/dagmc.cpp | 27 +++++++++++++++------------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 2fa0919e5..f50133105 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -90,9 +90,8 @@ public: //! Alternative DAGMC universe constructor for external DAGMC explicit DAGUniverse(std::shared_ptr external_dagmc_ptr, - const std::string& filename, - bool auto_geom_ids = false, - bool auto_mat_ids = false); + const std::string& filename, bool auto_geom_ids = false, + bool auto_mat_ids = false); //! Initialize the DAGMC accel. data structures, indices, material //! assignments, etc. @@ -146,17 +145,17 @@ public: bool has_graveyard() const { return has_graveyard_; } private: - void set_id(); //!< Deduce the universe id from model::universes - void init_dagmc(); //!< Create and initialise DAGMC pointer - void init_metadata(); //!< Create and initialise dagmcMetaData pointer - void init_geometry(); //!< Create cells and surfaces from DAGMC entities + void set_id(); //!< Deduce the universe id from model::universes + void init_dagmc(); //!< Create and initialise DAGMC pointer + void init_metadata(); //!< Create and initialise dagmcMetaData pointer + void init_geometry(); //!< Create cells and surfaces from DAGMC entities std::string filename_; //!< Name of the DAGMC file used to create this universe std::shared_ptr - uwuw_; //!< Pointer to the UWUW instance for this universe + uwuw_; //!< Pointer to the UWUW instance for this universe std::unique_ptr dmd_ptr; //! Pointer to DAGMC metadata object - bool uwuw_disabled; //!< Switch to disable UWUW materials + bool uwuw_disabled; //!< Switch to disable UWUW materials bool adjust_geometry_ids_; //!< Indicates whether or not to automatically //!< generate new cell and surface IDs for the //!< universe diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 2d0bab86e..2154db363 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -77,10 +77,9 @@ DAGUniverse::DAGUniverse( } DAGUniverse::DAGUniverse(std::shared_ptr external_dagmc_ptr, - const std::string& filename, - bool auto_geom_ids, bool auto_mat_ids) + const std::string& filename, bool auto_geom_ids, bool auto_mat_ids) : dagmc_instance_(external_dagmc_ptr), filename_(filename), - adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) + adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) { set_id(); init_metadata(); @@ -137,7 +136,8 @@ void DAGUniverse::init_dagmc() void DAGUniverse::init_metadata() { // parse model metadata - dmd_ptr = std::make_unique(dagmc_instance_.get(), false, false); + dmd_ptr = + std::make_unique(dagmc_instance_.get(), false, false); dmd_ptr->load_property_data(); std::vector keywords {"temp"}; @@ -206,7 +206,8 @@ void DAGUniverse::init_geometry() } else { if (uses_uwuw()) { // lookup material in uwuw if present - std::string uwuw_mat = dmd_ptr->volume_material_property_data_eh[vol_handle]; + std::string uwuw_mat = + dmd_ptr->volume_material_property_data_eh[vol_handle]; if (uwuw_->material_library.count(uwuw_mat) != 0) { // Note: material numbers are set by UWUW int mat_number = uwuw_->material_library.get_material(uwuw_mat) @@ -276,7 +277,8 @@ void DAGUniverse::init_geometry() : dagmc_instance_->id_by_index(2, i + 1); // set BCs - std::string bc_value = dmd_ptr->get_surface_property("boundary", surf_handle); + std::string bc_value = + dmd_ptr->get_surface_property("boundary", surf_handle); to_lower(bc_value); if (bc_value.empty() || bc_value == "transmit" || bc_value == "transmission") { @@ -320,10 +322,8 @@ void DAGUniverse::init_geometry() model::surfaces.emplace_back(std::move(s)); } // end surface loop - } - std::string DAGUniverse::dagmc_ids_for_dim(int dim) const { // generate a vector of ids @@ -417,8 +417,10 @@ void DAGUniverse::to_hdf5(hid_t universes_group) const bool DAGUniverse::uses_uwuw() const { - if (uwuw_disabled) return false; - else return !uwuw_->material_library.empty(); + if (uwuw_disabled) + return false; + else + return !uwuw_->material_library.empty(); } std::string DAGUniverse::get_uwuw_materials_xml() const @@ -508,9 +510,10 @@ void DAGUniverse::legacy_assign_material( void DAGUniverse::read_uwuw_materials() { // If no filename was provided, disable read UWUW materials - uwuw_disabled = (filename_==""); + uwuw_disabled = (filename_ == ""); - if (uwuw_disabled) return; + if (uwuw_disabled) + return; uwuw_ = std::make_shared(filename_.c_str()); if (!uses_uwuw()) From 116c7c33c070ce27156efefaf01aff7a9e405390 Mon Sep 17 00:00:00 2001 From: helen-brooks <67463845+helen-brooks@users.noreply.github.com> Date: Wed, 25 May 2022 09:39:34 +0100 Subject: [PATCH 0330/2654] Apply suggestions from paulromano review Co-authored-by: Paul Romano --- tests/regression_tests/dagmc/external/test.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/tests/regression_tests/dagmc/external/test.py b/tests/regression_tests/dagmc/external/test.py index a9fa9e3ee..938e262ff 100644 --- a/tests/regression_tests/dagmc/external/test.py +++ b/tests/regression_tests/dagmc/external/test.py @@ -2,14 +2,10 @@ from pathlib import Path import os import shutil import subprocess -from subprocess import CalledProcessError import textwrap -import glob -from itertools import product import openmc import openmc.lib -import numpy as np import pytest from tests.regression_tests import config @@ -19,8 +15,6 @@ pytestmark = pytest.mark.skipif( not openmc.lib._dagmc_enabled(), reason="DAGMC is not enabled.") -TETS_PER_VOXEL = 12 - # Test that an external DAGMC instance can be passed in through the C API @pytest.fixture @@ -36,8 +30,7 @@ def cpp_driver(request): add_executable(main main.cpp) find_package(OpenMC REQUIRED HINTS {}) target_link_libraries(main OpenMC::libopenmc) - set_target_properties(main PROPERTIES CXX_STANDARD - 14 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO) + target_compile_features(main PUBLIC cxx_std_14) set(CMAKE_CXX_FLAGS "-pedantic-errors") add_compile_definitions(DAGMC=1) """.format(openmc_dir))) @@ -45,15 +38,13 @@ def cpp_driver(request): # Create temporary build directory and change to there local_builddir = Path('build') local_builddir.mkdir(exist_ok=True) - os.chdir(str(local_builddir)) + os.chdir(local_builddir) - if config['mpi']: - os.environ['CXX'] = 'mpicxx' + mpi_arg = "On" if config['mpi'] else "Off" try: - print("Building driver") # Run cmake/make to build the shared libary - subprocess.run(['cmake', os.path.pardir], check=True) + subprocess.run(['cmake', os.path.pardir, f'-DOPENMC_USE_MPI={mpi_arg}'], check=True) subprocess.run(['make'], check=True) os.chdir(os.path.pardir) @@ -123,5 +114,5 @@ class ExternalDAGMCTest(PyAPITestHarness): event_based=config['event']) def test_external_dagmc(cpp_driver, model): - harness = ExternalDAGMCTest(cpp_driver,'statepoint.5.h5',model) + harness = ExternalDAGMCTest(cpp_driver, 'statepoint.5.h5', model) harness.main() From d9498216dd12c26c5f873453aa4efdb9408e9fe9 Mon Sep 17 00:00:00 2001 From: helen-brooks <67463845+helen-brooks@users.noreply.github.com> Date: Wed, 25 May 2022 10:36:40 +0100 Subject: [PATCH 0331/2654] Apply minor changes from pshriwise code review Co-authored-by: Patrick Shriwise --- include/openmc/dagmc.h | 2 +- src/dagmc.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index f50133105..0a74928b8 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -88,7 +88,7 @@ public: explicit DAGUniverse(const std::string& filename, bool auto_geom_ids = false, bool auto_mat_ids = false); - //! Alternative DAGMC universe constructor for external DAGMC + //! Alternative DAGMC universe constructor for external DAGMC instance explicit DAGUniverse(std::shared_ptr external_dagmc_ptr, const std::string& filename, bool auto_geom_ids = false, bool auto_mat_ids = false); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 2154db363..887669031 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -72,13 +72,12 @@ DAGUniverse::DAGUniverse( adjust_material_ids_(auto_mat_ids) { set_id(); - initialize(); } -DAGUniverse::DAGUniverse(std::shared_ptr external_dagmc_ptr, +DAGUniverse::DAGUniverse(std::shared_ptr dagmc_ptr, const std::string& filename, bool auto_geom_ids, bool auto_mat_ids) - : dagmc_instance_(external_dagmc_ptr), filename_(filename), + : dagmc_instance_(dagmc_ptr), filename_(filename), adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) { set_id(); From 8bf7de39ca64eadca38d2a6769e552307e8868d1 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Wed, 25 May 2022 10:47:37 +0100 Subject: [PATCH 0332/2654] Add empty string default argument for external DAGMC Universe constructor --- include/openmc/dagmc.h | 2 +- tests/regression_tests/dagmc/external/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 0a74928b8..5bf264b43 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -90,7 +90,7 @@ public: //! Alternative DAGMC universe constructor for external DAGMC instance explicit DAGUniverse(std::shared_ptr external_dagmc_ptr, - const std::string& filename, bool auto_geom_ids = false, + const std::string& filename = "", bool auto_geom_ids = false, bool auto_mat_ids = false); //! Initialize the DAGMC accel. data structures, indices, material diff --git a/tests/regression_tests/dagmc/external/main.cpp b/tests/regression_tests/dagmc/external/main.cpp index 6d9c97f59..9f5c1ceeb 100644 --- a/tests/regression_tests/dagmc/external/main.cpp +++ b/tests/regression_tests/dagmc/external/main.cpp @@ -50,7 +50,7 @@ int main(int argc, char* argv[]) // Create new DAGMC universe openmc::model::universes.push_back( - std::make_unique(dag_ptr, "")); + std::make_unique(dag_ptr)); model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; From 4d52218178fc8310e9da2891fda662649254de4c Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Wed, 25 May 2022 13:17:14 +0100 Subject: [PATCH 0333/2654] Remove redundant uwuw_disabled boolean member in DAGUniverse --- include/openmc/dagmc.h | 1 - src/dagmc.cpp | 12 ++++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 5bf264b43..993076347 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -155,7 +155,6 @@ private: std::shared_ptr uwuw_; //!< Pointer to the UWUW instance for this universe std::unique_ptr dmd_ptr; //! Pointer to DAGMC metadata object - bool uwuw_disabled; //!< Switch to disable UWUW materials bool adjust_geometry_ids_; //!< Indicates whether or not to automatically //!< generate new cell and surface IDs for the //!< universe diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 887669031..bb88f6488 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -416,10 +416,7 @@ void DAGUniverse::to_hdf5(hid_t universes_group) const bool DAGUniverse::uses_uwuw() const { - if (uwuw_disabled) - return false; - else - return !uwuw_->material_library.empty(); + return uwuw_ && !uwuw_->material_library.empty(); } std::string DAGUniverse::get_uwuw_materials_xml() const @@ -508,11 +505,10 @@ void DAGUniverse::legacy_assign_material( void DAGUniverse::read_uwuw_materials() { - // If no filename was provided, disable read UWUW materials - uwuw_disabled = (filename_ == ""); - - if (uwuw_disabled) + // If no filename was provided, don't read UWUW materials + if (filename_ == "") return; + uwuw_ = std::make_shared(filename_.c_str()); if (!uses_uwuw()) From 687d43b0ab6e3e3ddfe867767c210f0a1cfb38a7 Mon Sep 17 00:00:00 2001 From: Patrick Myers Date: Wed, 25 May 2022 09:06:53 -0500 Subject: [PATCH 0334/2654] added external xtensor within PhotonInteraction for all shell photoelectric xs to utilize contiguous memory in calculate_xs --- include/openmc/photon.h | 2 +- src/photon.cpp | 26 +++++++++++--------------- src/physics.cpp | 6 +++--- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/include/openmc/photon.h b/include/openmc/photon.h index e8ec82d10..50ee228c4 100644 --- a/include/openmc/photon.h +++ b/include/openmc/photon.h @@ -36,7 +36,6 @@ public: int threshold; double n_electrons; double binding_energy; - xt::xtensor cross_section; vector transitions; }; @@ -82,6 +81,7 @@ public: // Photoionization and atomic relaxation data vector shells_; + xt::xtensor cross_sections_; // Compton profile data xt::xtensor profile_pdf_; diff --git a/src/photon.cpp b/src/photon.cpp index b0cd8aa87..3f9ff6dbf 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -16,6 +16,9 @@ #include "xtensor/xbuilder.hpp" #include "xtensor/xoperation.hpp" #include "xtensor/xview.hpp" +#include "xtensor/xmath.hpp" +#include "xtensor/xslice.hpp" +#include "xtensor/xtensor_forward.hpp" #include #include @@ -125,6 +128,7 @@ PhotonInteraction::PhotonInteraction(hid_t group) } shells_.resize(n_shell); + cross_sections_.resize({energy_.size(), n_shell}); // Create mapping from designator to index std::unordered_map shell_map; @@ -155,13 +159,14 @@ PhotonInteraction::PhotonInteraction(hid_t group) read_attribute(tgroup, "num_electrons", shell.n_electrons); // Read subshell cross section + xt::xtensor xs; dset = open_dataset(tgroup, "xs"); read_attribute(dset, "threshold_idx", shell.threshold); close_dataset(dset); - read_dataset(tgroup, "xs", shell.cross_section); + read_dataset(tgroup, "xs", xs); - auto& xs = shell.cross_section; - xs = xt::where(xs > 0.0, xt::log(xs), -500.0); + auto cross_section = xt::view(cross_sections_, xt::range(shell.threshold, shell.threshold + xs.size()), i); + cross_section = xt::where(xs > 0.0, xt::log(xs), -500.0); if (object_exists(tgroup, "transitions")) { // Determine dimensions of transitions @@ -565,19 +570,10 @@ void PhotonInteraction::calculate_xs(Particle& p) const incoherent_(i_grid) + f * (incoherent_(i_grid + 1) - incoherent_(i_grid))); // Calculate microscopic photoelectric cross section - xs.photoelectric = 0.0; - for (const auto& shell : shells_) { - // Check threshold of reaction - int i_start = shell.threshold; - if (i_grid < i_start) - continue; + const auto& xs_upper = xt::row(cross_sections_, i_grid); + const auto& xs_lower = xt::row(cross_sections_, i_grid + 1); - // Evaluation subshell photoionization cross section - xs.photoelectric += - std::exp(shell.cross_section(i_grid - i_start) + - f * (shell.cross_section(i_grid + 1 - i_start) - - shell.cross_section(i_grid - i_start))); - } + xs.photoelectric = xt::sum(xt::exp(xs_upper + f * (xs_upper - xs_lower)))[0]; // Calculate microscopic pair production cross section xs.pair_production = std::exp( diff --git a/src/physics.cpp b/src/physics.cpp index 13dd063de..38d74dbed 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -358,9 +358,9 @@ void sample_photon_reaction(Particle& p) continue; // Evaluation subshell photoionization cross section - double xs = std::exp(shell.cross_section(i_grid - i_start) + - f * (shell.cross_section(i_grid + 1 - i_start) - - shell.cross_section(i_grid - i_start))); + double xs = std::exp(element.cross_sections_(i_grid - i_start) + + f * (element.cross_sections_(i_grid + 1 - i_start) - + element.cross_sections_(i_grid - i_start))); prob += xs; if (prob > cutoff) { From 82a7ccb16db4c11641f80d86fecfbe46a007b0d4 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Wed, 25 May 2022 15:10:50 +0100 Subject: [PATCH 0335/2654] Something weird happened during rebase - add back some lines which got removed --- tests/regression_tests/dagmc/external/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/regression_tests/dagmc/external/main.cpp b/tests/regression_tests/dagmc/external/main.cpp index 9f5c1ceeb..42f7d97c9 100644 --- a/tests/regression_tests/dagmc/external/main.cpp +++ b/tests/regression_tests/dagmc/external/main.cpp @@ -48,6 +48,11 @@ int main(int argc, char* argv[]) openmc::model::universes.clear(); openmc::model::universe_map.clear(); + // Update materials (emulate an external program) + for (auto& mat_ptr : openmc::model::materials) { + mat_ptr->set_temperature(300); + } + // Create new DAGMC universe openmc::model::universes.push_back( std::make_unique(dag_ptr)); From 6df0286b2e20e39b4eff8d93b262821086a9304f Mon Sep 17 00:00:00 2001 From: Patrick Myers Date: Wed, 25 May 2022 09:14:10 -0500 Subject: [PATCH 0336/2654] added clang-format --- src/photon.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/photon.cpp b/src/photon.cpp index 3f9ff6dbf..1be515a62 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -14,11 +14,11 @@ #include "openmc/settings.h" #include "xtensor/xbuilder.hpp" -#include "xtensor/xoperation.hpp" -#include "xtensor/xview.hpp" #include "xtensor/xmath.hpp" +#include "xtensor/xoperation.hpp" #include "xtensor/xslice.hpp" #include "xtensor/xtensor_forward.hpp" +#include "xtensor/xview.hpp" #include #include @@ -165,7 +165,8 @@ PhotonInteraction::PhotonInteraction(hid_t group) close_dataset(dset); read_dataset(tgroup, "xs", xs); - auto cross_section = xt::view(cross_sections_, xt::range(shell.threshold, shell.threshold + xs.size()), i); + auto cross_section = xt::view(cross_sections_, + xt::range(shell.threshold, shell.threshold + xs.size()), i); cross_section = xt::where(xs > 0.0, xt::log(xs), -500.0); if (object_exists(tgroup, "transitions")) { From f1f215bdbb6c1fb0fee53b78878ab565cd8f335e Mon Sep 17 00:00:00 2001 From: cpf Date: Wed, 25 May 2022 16:39:42 +0200 Subject: [PATCH 0337/2654] change theta to cos_theta in regression test --- tests/regression_tests/source/test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/regression_tests/source/test.py b/tests/regression_tests/source/test.py index 31debde47..e6a5bcf70 100644 --- a/tests/regression_tests/source/test.py +++ b/tests/regression_tests/source/test.py @@ -1,4 +1,4 @@ -from math import pi +from math import pi, cos import numpy as np import openmc @@ -32,19 +32,19 @@ class SourceTestHarness(PyAPITestHarness): r_dist = openmc.stats.Uniform(2., 3.) r_dist1 = openmc.stats.PowerLaw(2., 3., 1.) r_dist2 = openmc.stats.PowerLaw(2., 3., 2.) - theta_dist = openmc.stats.Discrete([pi/4, pi/2, 3*pi/4], - [0.3, 0.4, 0.3]) + cos_theta_dist = openmc.stats.Discrete([cos(pi/4), 0.0, cos(3*pi/4)], + [0.3, 0.4, 0.3]) phi_dist = openmc.stats.Uniform(0.0, 2*pi) spatial1 = openmc.stats.CartesianIndependent(x_dist, y_dist, z_dist) spatial2 = openmc.stats.Box([-4., -4., -4.], [4., 4., 4.]) spatial3 = openmc.stats.Point([1.2, -2.3, 0.781]) - spatial4 = openmc.stats.SphericalIndependent(r_dist, theta_dist, + spatial4 = openmc.stats.SphericalIndependent(r_dist, cos_theta_dist, phi_dist, origin=(1., 1., 0.)) spatial5 = openmc.stats.CylindricalIndependent(r_dist, phi_dist, z_dist, origin=(1., 1., 0.)) - spatial6 = openmc.stats.SphericalIndependent(r_dist2, theta_dist, + spatial6 = openmc.stats.SphericalIndependent(r_dist2, cos_theta_dist, phi_dist, origin=(1., 1., 0.)) spatial7 = openmc.stats.CylindricalIndependent(r_dist1, phi_dist, From 86ec0658c57a84019f0ef1c59f53671a2836a60e Mon Sep 17 00:00:00 2001 From: cpf Date: Wed, 25 May 2022 17:30:13 +0200 Subject: [PATCH 0338/2654] test spherical_uniform --- tests/unit_tests/test_source.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_source.py b/tests/unit_tests/test_source.py index d4d17a3da..f186437e4 100644 --- a/tests/unit_tests/test_source.py +++ b/tests/unit_tests/test_source.py @@ -1,6 +1,6 @@ import openmc import openmc.stats - +from math import pi, cos def test_source(): space = openmc.stats.Point() @@ -26,6 +26,22 @@ def test_source(): assert src.strength == 1.0 +def test_spherical_uniform(): + r_outer = 2.0 + r_inner = 1.0 + thetas = (0.0, pi/2) + phis = (0.0, pi) + origin = (0.0, 1.0, 2.0) + + sph_indep_function = openmc.stats.spherical_uniform(r_outer, + r_inner, + thetas, + phis, + origin) + + assert isinstance(sph_indep_function, openmc.stats.SphericalIndependent) + + def test_source_file(): filename = 'source.h5' src = openmc.Source(filename=filename) @@ -35,6 +51,7 @@ def test_source_file(): assert 'strength' in elem.attrib assert 'file' in elem.attrib + def test_source_dlopen(): library = './libsource.so' src = openmc.Source(library=library) From ccda2d3af374e9fc30e79b86da3dc15628196bbc Mon Sep 17 00:00:00 2001 From: cpf Date: Wed, 25 May 2022 17:32:34 +0200 Subject: [PATCH 0339/2654] removed import cos --- tests/unit_tests/test_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_source.py b/tests/unit_tests/test_source.py index f186437e4..dbcf49efc 100644 --- a/tests/unit_tests/test_source.py +++ b/tests/unit_tests/test_source.py @@ -1,6 +1,6 @@ import openmc import openmc.stats -from math import pi, cos +from math import pi def test_source(): space = openmc.stats.Point() From 84a4eb57fbb39938b09a5d91cdcbbd7b08bc8ad8 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 25 May 2022 13:35:00 -0500 Subject: [PATCH 0340/2654] Update docs/source/quickinstall.rst Co-authored-by: Paul Romano --- docs/source/quickinstall.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index 81a442f47..480db5be6 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -13,7 +13,7 @@ Installing on Linux/Mac with Mamba and conda-forge -------------------------------------------------- `Conda `_ is an open source package management -systems and environments management system for installing multiple versions of +system and environments management system for installing multiple versions of software packages and their dependencies and switching easily between them. `Mamba `_ is a cross-platform package manager and is compatible with `conda` packages. From 22bc340f9d42591fcdfa0b900dd159766217d2ae Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 May 2022 14:52:44 -0500 Subject: [PATCH 0341/2654] Rename Track.particles --> Track.particle_tracks --- openmc/trackfile.py | 29 +- .../track_output/results_true.dat | 535 +++++++++--------- tests/regression_tests/track_output/test.py | 3 +- tests/unit_tests/test_tracks.py | 8 +- 4 files changed, 295 insertions(+), 280 deletions(-) diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 6c94b6a04..16cb84c92 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -1,4 +1,5 @@ from collections import namedtuple +from collections.abc import Sequence import h5py @@ -21,6 +22,11 @@ states : numpy.ndarray (weight), ``cell_id`` (cell ID) , and ``material_id`` (material ID). """ +def _particle_track_repr(self): + name = self.particle.name.lower() + return f"" +ParticleTrack.__repr__ = _particle_track_repr + _VERSION_TRACK = 3 @@ -31,9 +37,14 @@ def _identifier(dset_name): return (int(batch), int(gen), int(particle)) -class Track: +class Track(Sequence): """Tracks resulting from a single source particle + This class stores information for all tracks resulting from a primary source + particle and any secondary particles that it created. The track for each + primary/secondary particle is stored in the :attr:`particle_tracks` + attribute. + Parameters ---------- dset : h5py.Dataset @@ -43,7 +54,7 @@ class Track: ---------- identifier : tuple Tuple of (batch, generation, particle number) - particles : list + particle_tracks : list List of tuples containing (particle type, array of track states) sources : list List of :class:`SourceParticle` representing each primary/secondary @@ -62,10 +73,16 @@ class Track: for particle, start, end in zip(particles, offsets[:-1], offsets[1:]): ptype = ParticleType(particle) tracks_list.append(ParticleTrack(ptype, tracks[start:end])) - self.particles = tracks_list + self.particle_tracks = tracks_list def __repr__(self): - return f'' + return f'' + + def __getitem__(self, index): + return self.particle_tracks[index] + + def __len__(self): + return len(self.particle_tracks) def plot(self, axes=None): """Produce a 3D plot of particle tracks @@ -94,7 +111,7 @@ class Track: ax = axes # Plot each particle track - for _, states in self.particles: + for _, states in self: r = states['r'] ax.plot3D(r['x'], r['y'], r['z']) @@ -103,7 +120,7 @@ class Track: @property def sources(self): sources = [] - for particle_track in self.particles: + for particle_track in self: particle_type = ParticleType(particle_track.particle) state = particle_track.states[0] sources.append( diff --git a/tests/regression_tests/track_output/results_true.dat b/tests/regression_tests/track_output/results_true.dat index ee8913019..d36aee6ed 100644 --- a/tests/regression_tests/track_output/results_true.dat +++ b/tests/regression_tests/track_output/results_true.dat @@ -1,269 +1,266 @@ -[ParticleTrack(particle=, states=array([((-9.663085e-01, -6.616522e-01, -9.863690e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 0.000000e+00, 1.000000e+00, 23, 1), - ((-1.281491e+00, -4.879529e-01, -7.708709e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.323629e-10, 1.000000e+00, 22, 3), - ((-1.368452e+00, -4.400285e-01, -7.114141e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.688824e-10, 1.000000e+00, 21, 2), - ((-2.150539e+00, -9.015151e-03, -1.766823e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 4.973246e-10, 1.000000e+00, 22, 3), - ((-2.237499e+00, 3.890922e-02, -1.172255e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 5.338441e-10, 1.000000e+00, 23, 1), - ((-2.453640e+00, 1.580257e-01, 3.055504e-02), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 6.246136e-10, 1.000000e+00, 23, 1), - ((-2.767485e+00, 3.309877e-01, 2.451383e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 7.564146e-10, 1.000000e+00, 22, 3), - ((-2.825099e+00, 3.627392e-01, 2.845305e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 7.806100e-10, 1.000000e+00, 22, 3), - ((-3.274427e+00, 6.029890e-01, 6.987901e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 9.878481e-10, 1.000000e+00, 23, 1), - ((-3.676327e+00, 8.178800e-01, 1.069324e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.173212e-09, 1.000000e+00, 23, 1), - ((-4.089400e+00, 1.038745e+00, 1.450158e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.363728e-09, 1.000000e+00, 23, 1), - ((-4.456639e+00, 1.235102e+00, 1.788735e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.533105e-09, 1.000000e+00, 22, 3), - ((-4.536974e+00, 1.278056e+00, 1.862800e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.570157e-09, 1.000000e+00, 21, 2), - ((-5.410401e+00, 1.745067e+00, 2.668060e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.972998e-09, 1.000000e+00, 22, 3), - ((-5.490736e+00, 1.788021e+00, 2.742125e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 2.010050e-09, 1.000000e+00, 23, 1), - ((-5.576301e+00, 1.833771e+00, 2.821012e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.049514e-09, 1.000000e+00, 23, 1), - ((-5.725160e+00, 1.896661e+00, 2.330311e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.227030e-09, 1.000000e+00, 23, 1), - ((-6.116514e+00, 2.061999e+00, 1.040248e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.693724e-09, 1.000000e+00, 22, 3), - ((-6.534762e+00, 2.238699e+00, -3.384686e-01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.192489e-09, 1.000000e+00, 23, 1), - ((-7.043525e+00, 2.453640e+00, -2.015560e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.799195e-09, 1.000000e+00, 23, 1), - ((-7.360920e+00, 2.587732e+00, -3.061825e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 4.177692e-09, 1.000000e+00, 11, 1), - ((-8.996680e+00, 3.278803e+00, -8.453960e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.128354e-09, 1.000000e+00, 23, 1), - ((-9.220205e+00, 3.373238e+00, -9.190791e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.394910e-09, 1.000000e+00, 22, 3), - ((-9.320244e+00, 3.415502e+00, -9.520561e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.514208e-09, 1.000000e+00, 21, 2), - ((-1.005591e+01, 3.726304e+00, -1.194562e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.391498e-09, 1.000000e+00, 22, 3), - ((-1.015595e+01, 3.768569e+00, -1.227539e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.510796e-09, 1.000000e+00, 23, 1), - ((-1.062054e+01, 3.964848e+00, -1.380687e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.064826e-09, 1.000000e+00, 23, 1), - ((-1.063244e+01, 3.969501e+00, -1.382484e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.072756e-09, 1.000000e+00, 23, 1), - ((-1.093907e+01, 4.089400e+00, -1.428802e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.277097e-09, 1.000000e+00, 23, 1), - ((-1.108410e+01, 4.146112e+00, -1.450710e+01), (4.855193e-01, 3.316053e-01, -8.088937e-01), 8.856868e+05, 8.373750e-09, 1.000000e+00, 23, 1), - ((-1.080173e+01, 4.338973e+00, -1.497755e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 8.820862e-09, 1.000000e+00, 23, 1), - ((-1.063244e+01, 4.371524e+00, -1.555290e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 9.317522e-09, 1.000000e+00, 23, 1), - ((-1.041266e+01, 4.413783e+00, -1.629984e+01), (2.686183e-01, -3.269476e-01, -9.060626e-01), 6.562001e+05, 9.962308e-09, 1.000000e+00, 23, 1), - ((-1.016754e+01, 4.115428e+00, -1.712667e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.077718e-08, 1.000000e+00, 23, 1), - ((-1.019064e+01, 4.089400e+00, -1.713747e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.087569e-08, 1.000000e+00, 23, 1), - ((-1.024915e+01, 4.023496e+00, -1.716481e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.112511e-08, 1.000000e+00, 23, 1), - ((-1.018199e+01, 3.749638e+00, -1.740047e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.276389e-08, 1.000000e+00, 22, 3), - ((-1.015866e+01, 3.654498e+00, -1.748234e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.333321e-08, 1.000000e+00, 21, 2), - ((-1.009978e+01, 3.414404e+00, -1.768895e+01), (1.735861e-01, -9.678731e-01, 1.819053e-01), 2.620416e+04, 1.476994e-08, 1.000000e+00, 21, 2), - ((-9.994809e+00, 2.829099e+00, -1.757894e+01), (4.635724e-01, 5.558106e-01, 6.900545e-01), 2.214649e+04, 1.747088e-08, 1.000000e+00, 21, 2), - ((-9.553365e+00, 3.358379e+00, -1.692183e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.209726e-08, 1.000000e+00, 21, 2), - ((-1.011854e+01, 3.687059e+00, -1.760205e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.716243e-08, 1.000000e+00, 22, 3), - ((-1.020058e+01, 3.734765e+00, -1.770077e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.789760e-08, 1.000000e+00, 23, 1), - ((-1.063244e+01, 3.985917e+00, -1.822054e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.176800e-08, 1.000000e+00, 23, 1), - ((-1.081038e+01, 4.089400e+00, -1.843470e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.336273e-08, 1.000000e+00, 23, 1), - ((-1.081564e+01, 4.092455e+00, -1.844103e+01), (-6.690877e-01, 6.718700e-01, -3.176671e-01), 1.355236e+04, 3.340982e-08, 1.000000e+00, 23, 1), - ((-1.096190e+01, 4.239327e+00, -1.851047e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.476743e-08, 1.000000e+00, 23, 1), - ((-1.109457e+01, 4.420404e+00, -1.850054e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.628014e-08, 1.000000e+00, 22, 3), - ((-1.113484e+01, 4.475368e+00, -1.849752e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.673931e-08, 1.000000e+00, 22, 3), - ((-1.117187e+01, 4.372425e+00, -1.850142e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.748914e-08, 1.000000e+00, 23, 1), - ((-1.127367e+01, 4.089400e+00, -1.851213e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.955064e-08, 1.000000e+00, 23, 1), - ((-1.135375e+01, 3.866733e+00, -1.852056e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.117251e-08, 1.000000e+00, 22, 3), - ((-1.138419e+01, 3.782113e+00, -1.852377e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.178887e-08, 1.000000e+00, 21, 2), - ((-1.172456e+01, 2.835777e+00, -1.855959e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.868184e-08, 1.000000e+00, 22, 3), - ((-1.175499e+01, 2.751157e+00, -1.856280e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.929820e-08, 1.000000e+00, 23, 1), - ((-1.179525e+01, 2.639224e+00, -1.856703e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.011351e-08, 1.000000e+00, 23, 1), - ((-1.190609e+01, 2.453640e+00, -1.847770e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.190861e-08, 1.000000e+00, 23, 1), - ((-1.222017e+01, 1.927741e+00, -1.822457e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.699551e-08, 1.000000e+00, 23, 1), - ((-1.226820e+01, 1.951470e+00, -1.815983e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.888995e-08, 1.000000e+00, 23, 1), - ((-1.236181e+01, 1.997712e+00, -1.803368e+01), (1.748787e-01, 6.613493e-01, 7.294070e-01), 4.250133e+02, 6.258186e-08, 1.000000e+00, 23, 1), - ((-1.234968e+01, 2.043587e+00, -1.798308e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 6.501444e-08, 1.000000e+00, 23, 1), - ((-1.276513e+01, 2.146245e+00, -1.744506e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 8.979603e-08, 1.000000e+00, 22, 3), - ((-1.313233e+01, 2.236980e+00, -1.696953e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 1.116994e-07, 1.000000e+00, 23, 1), - ((-1.318468e+01, 2.249916e+00, -1.690173e+01), (-8.862976e-01, -6.402442e-02, 4.586692e-01), 3.113244e+02, 1.148223e-07, 1.000000e+00, 23, 1), - ((-1.363685e+01, 2.217253e+00, -1.666773e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.357269e-07, 1.000000e+00, 23, 1), - ((-1.334593e+01, 2.453640e+00, -1.709033e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.617034e-07, 1.000000e+00, 23, 1), - ((-1.308145e+01, 2.668542e+00, -1.747452e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.853189e-07, 1.000000e+00, 22, 3), - ((-1.304150e+01, 2.701005e+00, -1.753256e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.888862e-07, 1.000000e+00, 22, 3), - ((-1.304665e+01, 2.669815e+00, -1.753058e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.903682e-07, 1.000000e+00, 23, 1), - ((-1.308231e+01, 2.453640e+00, -1.751686e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.006392e-07, 1.000000e+00, 23, 1), - ((-1.311790e+01, 2.237916e+00, -1.750317e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.108888e-07, 1.000000e+00, 22, 3), - ((-1.313266e+01, 2.148507e+00, -1.749750e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.151369e-07, 1.000000e+00, 21, 2), - ((-1.320190e+01, 1.728791e+00, -1.747087e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.350787e-07, 1.000000e+00, 21, 2), - ((-1.309582e+01, 2.150526e+00, -1.834143e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.808996e-07, 1.000000e+00, 22, 3), - ((-1.307365e+01, 2.238628e+00, -1.852329e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.904717e-07, 1.000000e+00, 23, 1), - ((-1.301957e+01, 2.453640e+00, -1.896713e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 3.138324e-07, 1.000000e+00, 23, 1), - ((-1.297913e+01, 2.614390e+00, -1.929896e+01), (6.012134e-01, 7.985735e-01, -2.868317e-02), 4.041011e+01, 3.312976e-07, 1.000000e+00, 23, 1), - ((-1.295975e+01, 2.640133e+00, -1.929988e+01), (6.762805e-01, -5.875192e-01, 4.443713e-01), 3.527833e+01, 3.349640e-07, 1.000000e+00, 23, 1), - ((-1.282907e+01, 2.526604e+00, -1.921402e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.584852e-07, 1.000000e+00, 23, 1), - ((-1.284217e+01, 2.453640e+00, -1.921346e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.799102e-07, 1.000000e+00, 23, 1), - ((-1.288683e+01, 2.204886e+00, -1.921158e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.529534e-07, 1.000000e+00, 22, 3), - ((-1.290264e+01, 2.116831e+00, -1.921091e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.788097e-07, 1.000000e+00, 21, 2), - ((-1.308145e+01, 1.120923e+00, -1.920338e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.712448e-07, 1.000000e+00, 22, 3), - ((-1.309726e+01, 1.032868e+00, -1.920271e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.971010e-07, 1.000000e+00, 23, 1), - ((-1.312690e+01, 8.677798e-01, -1.920146e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.455768e-07, 1.000000e+00, 23, 1), - ((-1.316626e+01, 8.178800e-01, -1.918559e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.693415e-07, 1.000000e+00, 23, 1), - ((-1.324019e+01, 7.241633e-01, -1.915578e+01), (-9.367321e-01, -1.471894e-01, -3.175976e-01), 2.365289e+00, 9.139738e-07, 1.000000e+00, 23, 1), - ((-1.348497e+01, 6.857011e-01, -1.923877e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.036815e-06, 1.000000e+00, 23, 1), - ((-1.390396e+01, 7.859275e-01, -1.924890e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.269071e-06, 1.000000e+00, 23, 1), - ((-1.403754e+01, 8.178800e-01, -1.925212e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.343115e-06, 1.000000e+00, 23, 1), - ((-1.504223e+01, 1.058212e+00, -1.927640e+01), (-4.085804e-01, -2.719942e-01, -8.712526e-01), 1.628266e+00, 1.900041e-06, 1.000000e+00, 23, 1), - ((-1.523744e+01, 9.282558e-01, -1.969268e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.170751e-06, 1.000000e+00, 23, 1), - ((-1.553972e+01, 1.106680e+00, -1.997974e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.636878e-06, 1.000000e+00, 23, 1), - ((-1.585973e+01, 1.295571e+00, -2.028364e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.130348e-06, 1.000000e+00, 22, 3), - ((-1.593583e+01, 1.340489e+00, -2.035590e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.247693e-06, 1.000000e+00, 21, 2), - ((-1.647184e+01, 1.656882e+00, -2.086494e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 4.074258e-06, 1.000000e+00, 21, 2), - ((-1.585080e+01, 1.545037e+00, -2.159072e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.061748e-06, 1.000000e+00, 22, 3), - ((-1.576406e+01, 1.529415e+00, -2.169209e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.199673e-06, 1.000000e+00, 23, 1), - ((-1.553972e+01, 1.489015e+00, -2.195425e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.556377e-06, 1.000000e+00, 23, 1), - ((-1.546081e+01, 1.474803e+00, -2.204648e+01), (3.257038e-01, -9.420596e-01, -8.025439e-02), 3.076319e-01, 5.681852e-06, 1.000000e+00, 23, 1), - ((-1.543563e+01, 1.401988e+00, -2.205268e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 5.782605e-06, 1.000000e+00, 23, 1), - ((-1.553972e+01, 1.153338e+00, -2.213907e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 6.487752e-06, 1.000000e+00, 23, 1), - ((-1.565955e+01, 8.670807e-01, -2.223854e+01), (1.611814e-01, 2.692337e-01, -9.494913e-01), 8.559448e-02, 7.299552e-06, 1.000000e+00, 23, 1), - ((-1.563263e+01, 9.120446e-01, -2.239711e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 7.712256e-06, 1.000000e+00, 23, 1), - ((-1.592604e+01, 1.214620e+00, -2.249695e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.406031e-06, 1.000000e+00, 22, 3), - ((-1.598742e+01, 1.277922e+00, -2.251784e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.760391e-06, 1.000000e+00, 21, 2), - ((-1.670388e+01, 2.016770e+00, -2.276163e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.389636e-05, 1.000000e+00, 22, 3), - ((-1.676526e+01, 2.080073e+00, -2.278252e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.425072e-05, 1.000000e+00, 23, 1), - ((-1.681575e+01, 2.132139e+00, -2.279970e+01), (4.286076e-02, -9.409799e-01, -3.357375e-01), 1.813618e-02, 1.454218e-05, 1.000000e+00, 23, 1), - ((-1.681374e+01, 2.087933e+00, -2.281547e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.479439e-05, 1.000000e+00, 23, 1), - ((-1.682083e+01, 2.021795e+00, -2.287841e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.532970e-05, 1.000000e+00, 22, 3), - ((-1.684417e+01, 1.804084e+00, -2.308558e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.709182e-05, 1.000000e+00, 21, 2), - ((-1.686879e+01, 1.574384e+00, -2.330417e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.895097e-05, 1.000000e+00, 22, 3), - ((-1.689212e+01, 1.356673e+00, -2.351134e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 2.071309e-05, 1.000000e+00, 23, 1), - ((-1.689233e+01, 1.354754e+00, -2.351317e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.072862e-05, 1.000000e+00, 23, 1), - ((-1.689148e+01, 1.355453e+00, -2.351229e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.073958e-05, 1.000000e+00, 22, 3), - ((-1.682182e+01, 1.413107e+00, -2.343954e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.164421e-05, 1.000000e+00, 21, 2), - ((-1.636364e+01, 1.792326e+00, -2.296107e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 2.759442e-05, 1.000000e+00, 21, 2), - ((-1.598564e+01, 1.746738e+00, -2.286758e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 3.079609e-05, 0.000000e+00, 21, 2)], - dtype=[('r', [('x', ', states=array([((-9.469716e-01, -2.580266e-01, 1.414357e-01), (1.438873e-01, 2.365819e-01, 9.608983e-01), 9.724461e+05, 0.000000e+00, 1.000000e+00, 23, 1), - ((-9.064818e-01, -1.914524e-01, 4.118326e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 2.064696e-10, 1.000000e+00, 23, 1), - ((-8.178800e-01, -1.616918e-01, 4.336377e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 3.725262e-10, 1.000000e+00, 11, 1), - ((-3.834875e-01, -1.578285e-02, 5.405432e-01), (-5.547498e-01, -6.358598e-02, 8.295839e-01), 1.474011e+05, 1.186660e-09, 1.000000e+00, 11, 1), - ((-7.999329e-01, -6.351625e-02, 1.163304e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.600465e-09, 1.000000e+00, 11, 1), - ((-8.178800e-01, -6.341842e-02, 1.190721e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.662321e-09, 1.000000e+00, 23, 1), - ((-1.035984e+00, -6.222961e-02, 1.523906e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.414026e-09, 1.000000e+00, 22, 3), - ((-1.124618e+00, -6.174649e-02, 1.659308e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.719509e-09, 1.000000e+00, 21, 2), - ((-1.705404e+00, -5.858082e-02, 2.546543e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 5.721217e-09, 1.000000e+00, 21, 2), - ((-1.851116e+00, -4.676544e-01, 2.685103e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.583734e-09, 1.000000e+00, 22, 3), - ((-1.880791e+00, -5.509662e-01, 2.713322e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.759394e-09, 1.000000e+00, 23, 1), - ((-1.948026e+00, -7.397227e-01, 2.777257e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.157380e-09, 1.000000e+00, 23, 1), - ((-2.068870e+00, -8.178800e-01, 2.735799e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.598974e-09, 1.000000e+00, 23, 1), - ((-2.111345e+00, -8.453511e-01, 2.721228e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 7.754188e-09, 1.000000e+00, 23, 1), - ((-2.453640e+00, -1.161216e+00, 3.335542e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.421339e-08, 1.000000e+00, 23, 1), - ((-2.715369e+00, -1.402736e+00, 3.805265e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.915229e-08, 1.000000e+00, 22, 3), - ((-2.785083e+00, -1.467067e+00, 3.930380e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 2.046780e-08, 1.000000e+00, 21, 2), - ((-2.940196e+00, -1.610203e+00, 4.208760e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 2.339483e-08, 1.000000e+00, 21, 2), - ((-3.600602e+00, -1.239800e+00, 3.812386e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.112139e-08, 1.000000e+00, 22, 3), - ((-3.682067e+00, -1.194109e+00, 3.763490e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.207450e-08, 1.000000e+00, 23, 1), - ((-4.089400e+00, -9.656478e-01, 3.519009e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.684019e-08, 1.000000e+00, 23, 1), - ((-4.185927e+00, -9.115084e-01, 3.461074e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 3.796953e-08, 1.000000e+00, 23, 1), - ((-4.089400e+00, -9.150200e-01, 3.260397e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 6.996444e-08, 1.000000e+00, 23, 1), - ((-3.920090e+00, -9.211794e-01, 2.908406e+00), (9.094673e-01, -3.659267e-01, -1.974002e-01), 9.547085e+00, 1.260840e-07, 1.000000e+00, 23, 1), - ((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 1), - ((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 1)], - dtype=[('r', [('x', ', states=array([((6.474155e+00, -5.192870e+00, 5.413003e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2), - ((6.467293e+00, -5.416535e+00, 5.441544e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450870e-05, 1.000000e+00, 22, 3), - ((6.464574e+00, -5.505149e+00, 5.452851e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450874e-05, 1.000000e+00, 23, 1), - ((6.461877e+00, -5.593034e+00, 5.464065e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450879e-05, 1.000000e+00, 23, 1), - ((6.570892e+00, -5.725160e+00, 5.464970e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450891e-05, 1.000000e+00, 32, 1), - ((6.821003e+00, -6.028296e+00, 5.467047e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450917e-05, 1.000000e+00, 31, 4), - ((7.101210e+00, -6.367908e+00, 5.469374e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450947e-05, 1.000000e+00, 32, 1), - ((7.360920e+00, -6.682677e+00, 5.471531e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450975e-05, 1.000000e+00, 23, 1), - ((7.833926e+00, -7.255962e+00, 5.475459e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451025e-05, 1.000000e+00, 23, 1), - ((8.142528e+00, -7.144944e+00, 5.464309e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451091e-05, 1.000000e+00, 22, 3), - ((8.590199e+00, -6.983897e+00, 5.448136e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451187e-05, 1.000000e+00, 23, 1), - ((8.682515e+00, -6.950687e+00, 5.444801e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451207e-05, 1.000000e+00, 23, 1), - ((8.996680e+00, -6.629985e+00, 5.450966e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451307e-05, 1.000000e+00, 23, 1), - ((9.231138e+00, -6.390649e+00, 5.455567e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451382e-05, 1.000000e+00, 22, 3), - ((9.650189e+00, -5.962879e+00, 5.463790e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451516e-05, 1.000000e+00, 23, 1), - ((9.721007e+00, -5.890588e+00, 5.465180e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451539e-05, 1.000000e+00, 23, 1), - ((9.939012e+00, -5.953026e+00, 5.222655e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451775e-05, 1.000000e+00, 22, 3), - ((1.002133e+01, -5.976602e+00, 5.131083e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451864e-05, 1.000000e+00, 23, 1), - ((1.020258e+01, -6.028514e+00, 4.929446e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452060e-05, 1.000000e+00, 23, 1), - ((1.063244e+01, -6.047973e+00, 4.703991e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452432e-05, 1.000000e+00, 23, 1), - ((1.084241e+01, -6.057477e+00, 4.593868e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452614e-05, 1.000000e+00, 23, 1), - ((1.107130e+01, -6.074053e+00, 4.699070e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452930e-05, 1.000000e+00, 22, 3), - ((1.121611e+01, -6.084540e+00, 4.765623e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453130e-05, 1.000000e+00, 21, 2), - ((1.174815e+01, -6.123069e+00, 5.010155e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453866e-05, 1.000000e+00, 22, 3), - ((1.189296e+01, -6.133556e+00, 5.076709e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.454067e-05, 1.000000e+00, 23, 1), - ((1.221698e+01, -6.157021e+00, 5.225634e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454515e-05, 1.000000e+00, 23, 1), - ((1.226820e+01, -6.225607e+00, 5.179351e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454893e-05, 1.000000e+00, 23, 1), - ((1.230378e+01, -6.273253e+00, 5.147199e+00), (9.203567e-01, -2.667811e-01, -2.859569e-01), 2.269067e+02, 4.455157e-05, 1.000000e+00, 23, 1), - ((1.237909e+01, -6.295083e+00, 5.123800e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.455549e-05, 1.000000e+00, 23, 1), - ((1.250758e+01, -6.372926e+00, 5.147974e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456396e-05, 1.000000e+00, 22, 3), - ((1.258603e+01, -6.420455e+00, 5.162734e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456914e-05, 1.000000e+00, 21, 2), - ((1.264082e+01, -6.453648e+00, 5.173042e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.457275e-05, 1.000000e+00, 21, 2), - ((1.288240e+01, -7.015898e+00, 5.025449e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.460837e-05, 1.000000e+00, 22, 3), - ((1.292943e+01, -7.125332e+00, 4.996722e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.461530e-05, 1.000000e+00, 23, 1), - ((1.303065e+01, -7.360920e+00, 4.934879e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.463022e-05, 1.000000e+00, 23, 1), - ((1.309295e+01, -7.505897e+00, 4.896822e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.463941e-05, 1.000000e+00, 23, 1), - ((1.311741e+01, -7.576618e+00, 4.913644e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.464426e-05, 1.000000e+00, 22, 3), - ((1.314895e+01, -7.667795e+00, 4.935331e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.465052e-05, 1.000000e+00, 21, 2), - ((1.345125e+01, -8.541749e+00, 5.143210e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471053e-05, 1.000000e+00, 22, 3), - ((1.348278e+01, -8.632925e+00, 5.164897e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471679e-05, 1.000000e+00, 23, 1), - ((1.356121e+01, -8.859646e+00, 5.218825e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.473236e-05, 1.000000e+00, 23, 1), - ((1.361604e+01, -8.996680e+00, 5.275368e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.474248e-05, 1.000000e+00, 23, 1), - ((1.390396e+01, -9.716172e+00, 5.572247e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.479558e-05, 1.000000e+00, 23, 1), - ((1.399742e+01, -9.949713e+00, 5.668611e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.481282e-05, 1.000000e+00, 23, 1), - ((1.390396e+01, -1.004824e+01, 5.750282e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.483180e-05, 1.000000e+00, 23, 1), - ((1.334984e+01, -1.063244e+01, 6.234531e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.494435e-05, 1.000000e+00, 23, 1), - ((1.317711e+01, -1.081455e+01, 6.385480e+00), (-4.211158e-01, -4.515418e-01, 7.866203e-01), 3.302717e+01, 4.497943e-05, 1.000000e+00, 23, 1), - ((1.316679e+01, -1.082561e+01, 6.404749e+00), (-5.182259e-01, 3.860612e-01, 7.631505e-01), 1.437084e+01, 4.498251e-05, 1.000000e+00, 23, 1), - ((1.292206e+01, -1.064329e+01, 6.765147e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.507257e-05, 1.000000e+00, 23, 1), - ((1.286229e+01, -1.063244e+01, 6.805923e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.508772e-05, 1.000000e+00, 23, 1), - ((1.284917e+01, -1.063006e+01, 6.814880e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509105e-05, 1.000000e+00, 23, 1), - ((1.284547e+01, -1.063244e+01, 6.820442e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509285e-05, 1.000000e+00, 23, 1), - ((1.249929e+01, -1.085555e+01, 7.341246e+00), (-1.520079e-01, -3.513652e-01, 9.238161e-01), 7.069024e+00, 4.526201e-05, 1.000000e+00, 23, 1), - ((1.240103e+01, -1.108268e+01, 7.938428e+00), (-7.405967e-01, -3.230926e-01, 5.891754e-01), 4.460475e+00, 4.543779e-05, 1.000000e+00, 23, 1), - ((1.229354e+01, -1.112958e+01, 8.023945e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.548748e-05, 1.000000e+00, 23, 1), - ((1.226820e+01, -1.110933e+01, 8.041241e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.550624e-05, 1.000000e+00, 23, 1), - ((1.198501e+01, -1.088299e+01, 8.234567e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.571593e-05, 1.000000e+00, 23, 1), - ((1.156403e+01, -1.063244e+01, 8.480859e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.600087e-05, 1.000000e+00, 23, 1), - ((1.150264e+01, -1.059590e+01, 8.516776e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.604243e-05, 1.000000e+00, 23, 1), - ((1.121659e+01, -1.063244e+01, 8.744860e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.623561e-05, 1.000000e+00, 23, 1), - ((1.063244e+01, -1.070706e+01, 9.210632e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.663011e-05, 1.000000e+00, 23, 1), - ((1.035391e+01, -1.074263e+01, 9.432717e+00), (-4.847677e-01, -8.685325e-01, -1.032060e-01), 5.647686e-01, 4.681821e-05, 1.000000e+00, 23, 1), - ((1.031409e+01, -1.081397e+01, 9.424239e+00), (-4.227592e-01, -9.022601e-01, -8.486053e-02), 5.651902e-01, 4.689723e-05, 1.000000e+00, 23, 1), - ((1.028497e+01, -1.087614e+01, 9.418392e+00), (1.549579e-01, -4.270887e-01, 8.908329e-01), 5.395517e-01, 4.696349e-05, 1.000000e+00, 23, 1), - ((1.034128e+01, -1.103135e+01, 9.742126e+00), (5.631544e-01, 4.925564e-01, 6.635098e-01), 2.637257e-01, 4.732118e-05, 1.000000e+00, 23, 1), - ((1.044415e+01, -1.094137e+01, 9.863334e+00), (-1.034377e-01, 7.912271e-01, 6.027108e-01), 1.474934e-01, 4.757836e-05, 1.000000e+00, 23, 1), - ((1.043959e+01, -1.090643e+01, 9.889950e+00), (1.163182e-01, 9.160889e-01, -3.837331e-01), 1.522434e-01, 4.766149e-05, 1.000000e+00, 23, 1), - ((1.045733e+01, -1.076664e+01, 9.831395e+00), (-8.136862e-01, 9.805444e-02, -5.729748e-01), 3.341488e-02, 4.794423e-05, 1.000000e+00, 23, 1), - ((1.044231e+01, -1.076483e+01, 9.820815e+00), (-8.437241e-01, 5.222731e-01, -1.239373e-01), 3.874838e-02, 4.801727e-05, 1.000000e+00, 23, 1), - ((1.028725e+01, -1.066884e+01, 9.798037e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.869227e-05, 1.000000e+00, 23, 1), - ((1.021310e+01, -1.063244e+01, 9.757708e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.902498e-05, 1.000000e+00, 23, 1), - ((1.012717e+01, -1.059025e+01, 9.710967e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 4.941058e-05, 1.000000e+00, 23, 1), - ((1.001043e+01, -1.038486e+01, 9.645483e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 5.039049e-05, 1.000000e+00, 22, 3), - ((9.971285e+00, -1.031600e+01, 9.623530e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.071901e-05, 1.000000e+00, 22, 3), - ((1.002723e+01, -1.037881e+01, 9.564267e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.116633e-05, 1.000000e+00, 23, 1), - ((1.025152e+01, -1.063060e+01, 9.326683e+00), (-8.159392e-01, -4.792697e-03, 5.781179e-01), 2.920905e-02, 5.295966e-05, 1.000000e+00, 23, 1), - ((1.000779e+01, -1.063203e+01, 9.499373e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422329e-05, 1.000000e+00, 23, 1), - ((1.000721e+01, -1.063244e+01, 9.498835e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422746e-05, 1.000000e+00, 23, 1), - ((9.852478e+00, -1.074269e+01, 9.354584e+00), (-6.686452e-01, -2.988396e-01, 6.808880e-01), 2.993224e-02, 5.534454e-05, 1.000000e+00, 23, 1), - ((9.765042e+00, -1.078177e+01, 9.443621e+00), (7.712484e-01, -5.215773e-01, 3.648739e-01), 3.590785e-02, 5.589099e-05, 1.000000e+00, 23, 1), - ((9.798992e+00, -1.080472e+01, 9.459682e+00), (-4.563170e-01, 8.081811e-01, -3.723144e-01), 2.674168e-02, 5.605894e-05, 1.000000e+00, 23, 1), - ((9.792857e+00, -1.079386e+01, 9.454677e+00), (-9.080336e-01, 4.172659e-01, 3.693418e-02), 9.753404e-03, 5.611838e-05, 1.000000e+00, 23, 1), - ((9.653805e+00, -1.072996e+01, 9.460332e+00), (-3.727950e-01, 2.889342e-01, -8.817828e-01), 1.781716e-02, 5.723944e-05, 1.000000e+00, 23, 1), - ((9.628677e+00, -1.071048e+01, 9.400895e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.760453e-05, 1.000000e+00, 23, 1), - ((9.563380e+00, -1.063244e+01, 9.395105e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.815928e-05, 1.000000e+00, 23, 1), - ((9.411305e+00, -1.045068e+01, 9.381621e+00), (3.205568e-01, -1.311309e-02, -9.471385e-01), 2.153422e-02, 5.945128e-05, 1.000000e+00, 23, 1), - ((9.860026e+00, -1.046903e+01, 8.055798e+00), (6.278124e-01, 1.023095e-01, -7.716115e-01), 2.013742e-02, 6.634788e-05, 1.000000e+00, 23, 1), - ((1.007604e+01, -1.043383e+01, 7.790303e+00), (6.790346e-01, 5.167838e-01, 5.213891e-01), 1.340865e-02, 6.810089e-05, 1.000000e+00, 23, 1), - ((1.008869e+01, -1.042421e+01, 7.800011e+00), (2.792456e-01, 1.367953e-01, 9.504257e-01), 8.576635e-03, 6.821715e-05, 1.000000e+00, 23, 1), - ((1.017046e+01, -1.038415e+01, 8.078330e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.050324e-05, 1.000000e+00, 23, 1), - ((1.008276e+01, -1.035463e+01, 8.083559e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.070353e-05, 1.000000e+00, 22, 3), - ((9.952201e+00, -1.031068e+01, 8.091343e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.100170e-05, 1.000000e+00, 21, 2), - ((9.404929e+00, -1.012646e+01, 8.123973e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.225157e-05, 1.000000e+00, 22, 3), - ((9.274369e+00, -1.008251e+01, 8.131758e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.254974e-05, 1.000000e+00, 23, 1), - ((9.126730e+00, -1.003281e+01, 8.140560e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.288692e-05, 1.000000e+00, 23, 1), - ((8.996680e+00, -1.006767e+01, 8.217365e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.321528e-05, 1.000000e+00, 23, 1), - ((8.694758e+00, -1.014859e+01, 8.395674e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.397758e-05, 1.000000e+00, 23, 1), - ((8.996680e+00, -9.720167e+00, 8.656770e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.511228e-05, 1.000000e+00, 23, 1), - ((9.263031e+00, -9.342216e+00, 8.887105e+00), (5.734531e-01, -5.017666e-01, 6.475970e-01), 9.798082e-02, 7.611330e-05, 1.000000e+00, 23, 1), - ((9.334809e+00, -9.405021e+00, 8.968164e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.640240e-05, 1.000000e+00, 23, 1), - ((9.335117e+00, -9.448857e+00, 8.932084e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.651925e-05, 1.000000e+00, 22, 3), - ((9.336345e+00, -9.623801e+00, 8.788098e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.698556e-05, 1.000000e+00, 21, 2), - ((9.339070e+00, -1.001201e+01, 8.468584e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.802034e-05, 1.000000e+00, 22, 3), - ((9.340298e+00, -1.018696e+01, 8.324598e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.848665e-05, 1.000000e+00, 23, 1), - ((9.343193e+00, -1.059945e+01, 7.985097e+00), (1.798796e-01, 3.522536e-02, -9.830577e-01), 1.283272e-01, 7.958616e-05, 1.000000e+00, 23, 1), - ((9.397753e+00, -1.058877e+01, 7.686922e+00), (6.459563e-01, 7.279465e-03, -7.633397e-01), 1.319449e-01, 8.019832e-05, 1.000000e+00, 23, 1), - ((9.462343e+00, -1.058804e+01, 7.610595e+00), (-5.748716e-01, 5.760301e-01, -5.811299e-01), 8.880732e-02, 8.039733e-05, 1.000000e+00, 23, 1), - ((9.287877e+00, -1.041322e+01, 7.434230e+00), (-4.932135e-03, 1.668926e-01, 9.859627e-01), 3.503028e-02, 8.113361e-05, 1.000000e+00, 23, 1), - ((9.286930e+00, -1.038117e+01, 7.623600e+00), (-9.325544e-02, -9.933000e-01, -6.825369e-02), 3.173764e-02, 8.187553e-05, 1.000000e+00, 23, 1), - ((9.283901e+00, -1.041342e+01, 7.621384e+00), (-4.235208e-01, -5.129112e-01, 7.466942e-01), 4.258127e-02, 8.200731e-05, 1.000000e+00, 23, 1), - ((9.264517e+00, -1.043690e+01, 7.655560e+00), (-7.165846e-01, 3.926265e-01, 5.764988e-01), 4.485063e-02, 8.216767e-05, 1.000000e+00, 23, 1), - ((9.256348e+00, -1.043242e+01, 7.662132e+00), (1.703748e-01, -9.175599e-01, -3.592441e-01), 3.521226e-02, 8.220659e-05, 1.000000e+00, 23, 1), - ((9.284015e+00, -1.058143e+01, 7.603793e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.283227e-05, 1.000000e+00, 23, 1), - ((9.309126e+00, -1.063244e+01, 7.631745e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.309804e-05, 1.000000e+00, 23, 1), - ((9.317824e+00, -1.065011e+01, 7.641427e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.319011e-05, 1.000000e+00, 23, 1), - ((9.459378e+00, -1.063244e+01, 7.505770e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.403060e-05, 1.000000e+00, 23, 1), - ((9.492454e+00, -1.062831e+01, 7.474071e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.422700e-05, 1.000000e+00, 23, 1), - ((9.492472e+00, -1.063244e+01, 7.472688e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.424159e-05, 1.000000e+00, 23, 1), - ((9.492761e+00, -1.069927e+01, 7.450302e+00), (9.457151e-01, -1.928731e-01, 2.615777e-01), 4.542312e-02, 8.447773e-05, 1.000000e+00, 23, 1), - ((9.890524e+00, -1.078039e+01, 7.560320e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.590450e-05, 1.000000e+00, 23, 1), - ((1.004645e+01, -1.080498e+01, 7.439717e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.651090e-05, 0.000000e+00, 23, 1)], - dtype=[('r', [('x', ' Date: Wed, 25 May 2022 22:39:17 +0200 Subject: [PATCH 0342/2654] changed theta cos_theta --- tests/regression_tests/source/inputs_true.dat | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/source/inputs_true.dat b/tests/regression_tests/source/inputs_true.dat index 131d20ac1..c9c9c4277 100644 --- a/tests/regression_tests/source/inputs_true.dat +++ b/tests/regression_tests/source/inputs_true.dat @@ -53,9 +53,9 @@ - - 0.7853981633974483 1.5707963267948966 2.356194490192345 0.3 0.4 0.3 - + + 0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3 + @@ -102,9 +102,9 @@ - - 0.7853981633974483 1.5707963267948966 2.356194490192345 0.3 0.4 0.3 - + + 0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3 + From 7b0862c4dcbcfcb1e4a08e6d70aa088e9df89ca1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 May 2022 16:47:25 -0500 Subject: [PATCH 0343/2654] Add filter method to TrackFile and Track classes --- openmc/trackfile.py | 83 +++++++++++++++++++++++++++++++++ tests/unit_tests/test_tracks.py | 32 +++++++++++++ 2 files changed, 115 insertions(+) diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 16cb84c92..179371260 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -84,6 +84,62 @@ class Track(Sequence): def __len__(self): return len(self.particle_tracks) + def filter(self, particle=None, state_filter=None): + """Filter particle tracks by given criteria + + Parameters + ---------- + particle : {'neutron', 'photon', 'electron', 'positron'} + Matching particle type + state_filter : function + Function that takes a state (structured datatype) and returns a bool + depending on some criteria. + + Returns + ------- + list + List of :class:`openmc.ParticleTrack` objects + + Examples + -------- + Get all particle tracks for photons: + + >>> track.filter(particle='photon') + + Get all particle tracks that entered cell with ID=15: + + >>> track.filter(state_filter=lambda s: s['cell_id'] == 15) + + Get all particle tracks in entered material with ID=2: + + >>> track.filter(state_filter=lambda s: s['material_id'] == 2) + + See Also + -------- + openmc.ParticleTrack + + """ + matching = [] + for t in self: + # Check for matching particle + if particle is not None: + if t.particle.name.lower() != particle: + continue + + # Apply arbitrary state filter + match = True + if state_filter is not None: + for state in t.states: + if state_filter(state): + break + else: + match = False + + if match: + matching.append(t) + + return matching + def plot(self, axes=None): """Produce a 3D plot of particle tracks @@ -156,6 +212,33 @@ class TrackFile(list): dset = fh[dset_name] self.append(Track(dset)) + def filter(self, particle=None, state_filter=None): + """Filter tracks by given criteria + + Parameters + ---------- + particle : {'neutron', 'photon', 'electron', 'positron'} + Matching particle type + state_filter : function + Function that takes a state (structured datatype) and returns a bool + depending on some criteria. + + Returns + ------- + list + List of :class:`openmc.Track` objects + + See Also + -------- + openmc.Track.filter + + """ + matching = [] + for track in self: + if track.filter(particle, state_filter): + matching.append(track) + return matching + def plot(self): """Produce a 3D plot of particle tracks diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index 8365ae054..4c820724d 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -107,3 +107,35 @@ def test_max_tracks(sphere_model, run_in_tmpdir): # Open track file and make sure we have correct number of tracks tracks = openmc.TrackFile('tracks.h5') assert len(tracks) == expected_num_tracks + + +def test_filter(sphere_model, run_in_tmpdir): + # Set maximum number of tracks per process to write + sphere_model.settings.max_tracks = 25 + sphere_model.settings.photon_transport = True + + # Run OpenMC to generate tracks.h5 file + generate_track_file(sphere_model, tracks=True) + + tracks = openmc.TrackFile('tracks.h5') + for track in tracks: + # Test filtering by particle + matches = track.filter(particle='photon') + for x in matches: + assert x.particle == openmc.ParticleType.PHOTON + + # Test general state filter + matches = track.filter(state_filter=lambda s: s['cell_id'] == 1) + assert matches == track.particle_tracks + matches = track.filter(state_filter=lambda s: s['cell_id'] == 2) + assert matches == [] + matches = track.filter(state_filter=lambda s: s['E'] < 0.0) + assert matches == [] + + # Test filter method on TrackFile + matches = tracks.filter(particle='neutron') + assert matches == tracks + matches = tracks.filter(state_filter=lambda s: s['E'] > 0.0) + assert matches == tracks + matches = tracks.filter(particle='bunnytron') + assert matches == [] From 2e54c31915ceb05ade36575f87f9a51f4a982343 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 May 2022 16:58:20 -0500 Subject: [PATCH 0344/2654] Rename TrackFile --> Tracks --- docs/source/pythonapi/base.rst | 2 +- docs/source/usersguide/settings.rst | 30 ++++++++++++--------- openmc/trackfile.py | 4 +-- scripts/openmc-track-combine | 2 +- scripts/openmc-track-to-vtk | 2 +- tests/regression_tests/track_output/test.py | 2 +- tests/unit_tests/test_tracks.py | 10 +++---- 7 files changed, 29 insertions(+), 23 deletions(-) diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index bc4325ae5..076b02722 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -189,7 +189,7 @@ Post-processing openmc.StatePoint openmc.Summary openmc.Track - openmc.TrackFile + openmc.Tracks The following classes and functions are used for functional expansion reconstruction. diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index db06d8a0e..d1242f70c 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -545,9 +545,9 @@ tracks will be written as follows:: settings.max_tracks = 1000 Particle track information is written to the ``tracks.h5`` file, which can be -analyzed using the :class:`~openmc.TrackFile` class:: +analyzed using the :class:`~openmc.Tracks` class:: - >>> tracks = openmc.TrackFile('tracks.h5') + >>> tracks = openmc.Tracks('tracks.h5') >>> tracks [, , @@ -557,19 +557,25 @@ Each :class:`~openmc.Track` object stores a list of track information for every primary/secondary particle. In the above example, the first source particle produced 150 secondary particles for a total of 151 particles. Information for each primary/secondary particle can be accessed using the -:attr:`~openmc.Track.particles` attribute:: +:attr:`~openmc.Track.particle_tracks` attribute:: >>> first_track = tracks[0] - >>> len(first_track.particles) - 151 - >>> photon = first_track.particles[10] - ParticleTrack(particle=, states=array([...])) + >>> first_track.particle_tracks + [, + , + , + , + , + ... + , + ] + >>> photon = first_track.particle_tracks[1] -The :class:`~openmc.ParticleTrack` class is a named tuple indicating the particle -type and then a NumPy array of the "states". The states array is a compound type -with a field for each physical quantity (position, direction, energy, time, -weight, cell ID, and material ID). For example, to get the position for the -above particle track:: +The :class:`~openmc.ParticleTrack` class is a named tuple indicating the +particle type and then a NumPy array of the "states". The states array is a +compound type with a field for each physical quantity (position, direction, +energy, time, weight, cell ID, and material ID). For example, to get the +position for the above particle track:: >>> photon.states['r'] array([(-11.92987939, -12.28467295, 0.67837495), diff --git a/openmc/trackfile.py b/openmc/trackfile.py index 179371260..b3bf2e904 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -189,7 +189,7 @@ class Track(Sequence): return sources -class TrackFile(list): +class Tracks(list): """Collection of particle tracks This class behaves like a list and can be indexed using the normal subscript @@ -202,7 +202,7 @@ class TrackFile(list): """ - def __init__(self, filepath): + def __init__(self, filepath='tracks.h5'): # Read data from track file with h5py.File(filepath, 'r') as fh: # Check filetype and version diff --git a/scripts/openmc-track-combine b/scripts/openmc-track-combine index 155fe9b54..f69f2151c 100755 --- a/scripts/openmc-track-combine +++ b/scripts/openmc-track-combine @@ -17,7 +17,7 @@ def main(): help='Output HDF5 particle track file.') args = parser.parse_args() - openmc.TrackFile.combine(args.input, args.out) + openmc.Tracks.combine(args.input, args.out) if __name__ == '__main__': diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index 7959ad35d..2624ad239 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -39,7 +39,7 @@ def main(): point_offset = 0 for fname in args.input: # Write coordinate values to points array. - track_file = openmc.TrackFile(fname) + track_file = openmc.Tracks(fname) for track in track_file: for particle in track.particles: for state in particle.states: diff --git a/tests/regression_tests/track_output/test.py b/tests/regression_tests/track_output/test.py index 49dfcefe3..62526117d 100644 --- a/tests/regression_tests/track_output/test.py +++ b/tests/regression_tests/track_output/test.py @@ -31,7 +31,7 @@ class TrackTestHarness(TestHarness): # Get string of track file information outstr = '' - tracks = openmc.TrackFile('tracks.h5') + tracks = openmc.Tracks('tracks.h5') for track in tracks: with np.printoptions(formatter={'float_kind': '{:.6e}'.format}): for ptrack in track: diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index 4c820724d..bf54e700f 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -36,7 +36,7 @@ def generate_track_file(model, **kwargs): if config['mpi'] and int(config['mpi_np']) > 1: # With MPI, we need to combine track files track_files = Path.cwd().glob('tracks_p*.h5') - openmc.TrackFile.combine(track_files, 'tracks.h5') + openmc.Tracks.combine(track_files, 'tracks.h5') else: track_file = Path('tracks.h5') assert track_file.is_file() @@ -54,7 +54,7 @@ def test_tracks(sphere_model, particle, run_in_tmpdir): generate_track_file(sphere_model) # Open track file and make sure we have correct number of tracks - tracks = openmc.TrackFile('tracks.h5') + tracks = openmc.Tracks('tracks.h5') assert len(tracks) == len(sphere_model.settings.track) for track, identifier in zip(tracks, sphere_model.settings.track): @@ -105,7 +105,7 @@ def test_max_tracks(sphere_model, run_in_tmpdir): generate_track_file(sphere_model, tracks=True) # Open track file and make sure we have correct number of tracks - tracks = openmc.TrackFile('tracks.h5') + tracks = openmc.Tracks('tracks.h5') assert len(tracks) == expected_num_tracks @@ -117,7 +117,7 @@ def test_filter(sphere_model, run_in_tmpdir): # Run OpenMC to generate tracks.h5 file generate_track_file(sphere_model, tracks=True) - tracks = openmc.TrackFile('tracks.h5') + tracks = openmc.Tracks('tracks.h5') for track in tracks: # Test filtering by particle matches = track.filter(particle='photon') @@ -132,7 +132,7 @@ def test_filter(sphere_model, run_in_tmpdir): matches = track.filter(state_filter=lambda s: s['E'] < 0.0) assert matches == [] - # Test filter method on TrackFile + # Test filter method on Tracks matches = tracks.filter(particle='neutron') assert matches == tracks matches = tracks.filter(state_filter=lambda s: s['E'] > 0.0) From c2a0599b23da1bcc6f607935d3286af6514cc454 Mon Sep 17 00:00:00 2001 From: cpf Date: Thu, 26 May 2022 00:07:36 +0200 Subject: [PATCH 0345/2654] update criticality by different distribution --- tests/regression_tests/source/results_true.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/source/results_true.dat b/tests/regression_tests/source/results_true.dat index 62eaf6eff..bfc387065 100644 --- a/tests/regression_tests/source/results_true.dat +++ b/tests/regression_tests/source/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.865754E-01 6.762423E-03 +2.865449E-01 6.769564E-03 From 53d7c848ea1d43d37b55f0f2b8d61338dbe30e2e Mon Sep 17 00:00:00 2001 From: cpf Date: Thu, 26 May 2022 00:17:03 +0200 Subject: [PATCH 0346/2654] use of testing cross sections --- tests/regression_tests/source/results_true.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/source/results_true.dat b/tests/regression_tests/source/results_true.dat index bfc387065..62eaf6eff 100644 --- a/tests/regression_tests/source/results_true.dat +++ b/tests/regression_tests/source/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.865449E-01 6.769564E-03 +2.865754E-01 6.762423E-03 From ae849c584287657534b97dcca074ae7d5e5b7c51 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 May 2022 22:12:44 -0500 Subject: [PATCH 0347/2654] Have filter methods return new Track/Tracks objects --- docs/source/usersguide/settings.rst | 13 +++++++++++++ openmc/trackfile.py | 17 ++++++++++++----- tests/unit_tests/test_tracks.py | 8 +++++--- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index d1242f70c..f73967ad9 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -596,6 +596,19 @@ The full list of fields is as follows: :cell_id: Cell ID :material_id: Material ID +Both the :class:`~openmc.Tracks` and :class:`~openmc.Track` classes have a +``filter`` method that allows you to get a subset of tracks that meet a given +criteria. For example, to get all tracks that involved a photon:: + + >>> tracks.filter(particle='photon') + [, + , + ] + +The :meth:`openmc.Tracks.filter` method returns a new :class:`~openmc.Tracks` +instance, whereas the :meth:`openmc.Track.filter` method returns a new +:class:`~openmc.Track` instance. + .. note:: If you are using an MPI-enabled install of OpenMC and run a simulation with more than one process, a separate track file will be written for each MPI process with the filename ``tracks_p#.h5`` where # is the diff --git a/openmc/trackfile.py b/openmc/trackfile.py index b3bf2e904..b8b479cc6 100644 --- a/openmc/trackfile.py +++ b/openmc/trackfile.py @@ -97,8 +97,8 @@ class Track(Sequence): Returns ------- - list - List of :class:`openmc.ParticleTrack` objects + Track + New instance with only matching :class:`openmc.ParticleTrack` objects Examples -------- @@ -138,7 +138,11 @@ class Track(Sequence): if match: matching.append(t) - return matching + # Return new Track instance with only matching particle tracks + track = type(self).__new__(type(self)) + track.identifier = self.identifier + track.particle_tracks = matching + return track def plot(self, axes=None): """Produce a 3D plot of particle tracks @@ -225,7 +229,7 @@ class Tracks(list): Returns ------- - list + Tracks List of :class:`openmc.Track` objects See Also @@ -233,7 +237,10 @@ class Tracks(list): openmc.Track.filter """ - matching = [] + # Create a new Tracks instance but avoid call to __init__ + matching = type(self).__new__(type(self)) + + # Append matching Track objects for track in self: if track.filter(particle, state_filter): matching.append(track) diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index bf54e700f..e18015d81 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -126,14 +126,16 @@ def test_filter(sphere_model, run_in_tmpdir): # Test general state filter matches = track.filter(state_filter=lambda s: s['cell_id'] == 1) - assert matches == track.particle_tracks + assert isinstance(matches, openmc.Track) + assert matches.particle_tracks == track.particle_tracks matches = track.filter(state_filter=lambda s: s['cell_id'] == 2) - assert matches == [] + assert matches.particle_tracks == [] matches = track.filter(state_filter=lambda s: s['E'] < 0.0) - assert matches == [] + assert matches.particle_tracks == [] # Test filter method on Tracks matches = tracks.filter(particle='neutron') + assert isinstance(matches, openmc.Tracks) assert matches == tracks matches = tracks.filter(state_filter=lambda s: s['E'] > 0.0) assert matches == tracks From 4a13b39224a9bc0e294c87c3738665a2e71e0d67 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 May 2022 22:13:20 -0500 Subject: [PATCH 0348/2654] Rename trackfile.py --> tracks.py --- openmc/__init__.py | 2 +- openmc/{trackfile.py => tracks.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename openmc/{trackfile.py => tracks.py} (100%) diff --git a/openmc/__init__.py b/openmc/__init__.py index 91af25a5f..e63e9e4d1 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -30,7 +30,7 @@ from openmc.mixin import * from openmc.plotter import * from openmc.search import * from openmc.polynomial import * -from openmc.trackfile import * +from openmc.tracks import * from . import examples # Import a few names from the model module diff --git a/openmc/trackfile.py b/openmc/tracks.py similarity index 100% rename from openmc/trackfile.py rename to openmc/tracks.py From 9704aa0ed48e1838465de4a7b926d98f64e48b09 Mon Sep 17 00:00:00 2001 From: cpf Date: Thu, 26 May 2022 14:20:12 +0200 Subject: [PATCH 0349/2654] change theta cos_theta in test unstructured_mesh --- tests/regression_tests/unstructured_mesh/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/test.py b/tests/regression_tests/unstructured_mesh/test.py index c921a7848..daebe7948 100644 --- a/tests/regression_tests/unstructured_mesh/test.py +++ b/tests/regression_tests/unstructured_mesh/test.py @@ -228,10 +228,10 @@ def test_unstructured_mesh(test_opts): # source setup r = openmc.stats.Uniform(a=0.0, b=0.0) - theta = openmc.stats.Discrete(x=[0.0], p=[1.0]) + cos_theta = openmc.stats.Discrete(x=[1.0], p=[1.0]) phi = openmc.stats.Discrete(x=[0.0], p=[1.0]) - space = openmc.stats.SphericalIndependent(r, theta, phi) + space = openmc.stats.SphericalIndependent(r, cos_theta, phi) energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) source = openmc.Source(space=space, energy=energy) settings.source = source From be006abf1767e8053954300a96c5af92e8766dba Mon Sep 17 00:00:00 2001 From: cpf Date: Thu, 26 May 2022 16:13:37 +0200 Subject: [PATCH 0350/2654] change input_true in unstructured_mesh --- tests/regression_tests/unstructured_mesh/inputs_true0.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true1.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true10.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true11.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true12.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true13.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true14.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true15.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true2.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true3.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true4.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true5.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true6.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true7.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true8.dat | 6 +++--- tests/regression_tests/unstructured_mesh/inputs_true9.dat | 6 +++--- 16 files changed, 48 insertions(+), 48 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/inputs_true0.dat index 7411e9b94..1ed60d507 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true0.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/inputs_true1.dat index e85aab119..67dde56a9 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true1.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true10.dat b/tests/regression_tests/unstructured_mesh/inputs_true10.dat index 628e5e7bc..9ca47a356 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true10.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true10.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true11.dat b/tests/regression_tests/unstructured_mesh/inputs_true11.dat index 1c0a579e5..683e1fade 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true11.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true11.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true12.dat b/tests/regression_tests/unstructured_mesh/inputs_true12.dat index a75344435..8ce9f3cf2 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true12.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true12.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true13.dat b/tests/regression_tests/unstructured_mesh/inputs_true13.dat index c62c3c911..bca0bee4c 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true13.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true13.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true14.dat b/tests/regression_tests/unstructured_mesh/inputs_true14.dat index b7ac4c048..226331ba8 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true14.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true14.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true15.dat b/tests/regression_tests/unstructured_mesh/inputs_true15.dat index 1d96efc7d..a6a084165 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true15.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true15.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true2.dat b/tests/regression_tests/unstructured_mesh/inputs_true2.dat index a2a2d4a27..4b442c757 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true2.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true2.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true3.dat b/tests/regression_tests/unstructured_mesh/inputs_true3.dat index c96f90201..52e53498e 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true3.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true3.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true4.dat b/tests/regression_tests/unstructured_mesh/inputs_true4.dat index a39452da7..995a1828f 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true4.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true4.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true5.dat b/tests/regression_tests/unstructured_mesh/inputs_true5.dat index 288b7d1fc..60229e5e5 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true5.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true5.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true6.dat b/tests/regression_tests/unstructured_mesh/inputs_true6.dat index 883e6cbf4..7a9257cb7 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true6.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true6.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true7.dat b/tests/regression_tests/unstructured_mesh/inputs_true7.dat index 267966e3c..52802febf 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true7.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true7.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true8.dat b/tests/regression_tests/unstructured_mesh/inputs_true8.dat index 9a7ad5711..e484c95a2 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true8.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true8.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/inputs_true9.dat b/tests/regression_tests/unstructured_mesh/inputs_true9.dat index 8aedad237..5e83d71bd 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true9.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true9.dat @@ -50,9 +50,9 @@ - - 0.0 1.0 - + + 1.0 1.0 + 0.0 1.0 From cc338c98d5a9d7ce707eb57aaacb6a681dfdd9b0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 26 May 2022 09:42:03 -0500 Subject: [PATCH 0351/2654] Add mask_components in Plots -> XML round trip unit test --- tests/unit_tests/test_plots.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/test_plots.py b/tests/unit_tests/test_plots.py index f61b52604..2db396cd5 100644 --- a/tests/unit_tests/test_plots.py +++ b/tests/unit_tests/test_plots.py @@ -93,6 +93,7 @@ def test_plots(run_in_tmpdir): p1 = openmc.Plot(name='plot1') p1.origin = (5., 5., 5.) p1.colors = {10: (255, 100, 0)} + p1.mask_components = [2, 4, 6] p2 = openmc.Plot(name='plot2') p2.origin = (-3., -3., -3.) plots = openmc.Plots([p1, p2]) @@ -109,4 +110,5 @@ def test_plots(run_in_tmpdir): assert len(plots) assert plots[0].origin == p1.origin assert plots[0].colors == p1.colors + assert plots[0].mask_components == p1.mask_components assert plots[1].origin == p2.origin From 67d54491275baf9d3d5a8c8701e5e3fb266ed1f6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 12 May 2022 10:19:02 -0500 Subject: [PATCH 0352/2654] After exhaustive find cell search following surface crossing, set surface on particle --- src/particle.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/particle.cpp b/src/particle.cpp index b622a4d69..8738fac2b 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -455,6 +455,7 @@ void Particle::cross_surface() // COULDN'T FIND PARTICLE IN NEIGHBORING CELLS, SEARCH ALL CELLS // Remove lower coordinate levels and assignment of surface + auto surface_index = surface(); surface() = 0; n_coord() = 1; bool found = exhaustive_find_cell(*this); @@ -478,6 +479,9 @@ void Particle::cross_surface() return; } } + + // Reassign surface to avoid tracking errors + surface() = surface_index; } void Particle::cross_vacuum_bc(const Surface& surf) From 256078ef10399836eb1579b0221822be7882f85c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 26 May 2022 10:01:15 -0500 Subject: [PATCH 0353/2654] Don't initially reset surface when doing exhaustive find cell search --- src/particle.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/particle.cpp b/src/particle.cpp index 8738fac2b..972ef2575 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -454,9 +454,7 @@ void Particle::cross_surface() // ========================================================================== // COULDN'T FIND PARTICLE IN NEIGHBORING CELLS, SEARCH ALL CELLS - // Remove lower coordinate levels and assignment of surface - auto surface_index = surface(); - surface() = 0; + // Remove lower coordinate levels n_coord() = 1; bool found = exhaustive_find_cell(*this); @@ -466,6 +464,7 @@ void Particle::cross_surface() // the particle is really traveling tangent to a surface, if we move it // forward a tiny bit it should fix the problem. + surface() = 0; n_coord() = 1; r() += TINY_BIT * u(); @@ -479,9 +478,6 @@ void Particle::cross_surface() return; } } - - // Reassign surface to avoid tracking errors - surface() = surface_index; } void Particle::cross_vacuum_bc(const Surface& surf) From e1d91bb4c624034e7c8c28a7e41a88b16129e0ce Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 26 May 2022 12:59:31 -0400 Subject: [PATCH 0354/2654] Update openmc/mesh.py Co-authored-by: Patrick Shriwise --- openmc/mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 3ae5ee43d..d812f27ac 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -145,8 +145,8 @@ class StructuredMesh(ABC): """ - def __init__(self, **kwargs): - super().__init__(**kwargs) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) @property @abstractmethod From 33ded6d2d324eb03f1531bea9d5a97a65d5e36b2 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Fri, 27 May 2022 09:09:55 +0100 Subject: [PATCH 0355/2654] Additional comments in test --- tests/regression_tests/dagmc/external/test.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/regression_tests/dagmc/external/test.py b/tests/regression_tests/dagmc/external/test.py index 938e262ff..2671f9a84 100644 --- a/tests/regression_tests/dagmc/external/test.py +++ b/tests/regression_tests/dagmc/external/test.py @@ -101,15 +101,25 @@ class ExternalDAGMCTest(PyAPITestHarness): self.executable = executable def _run_openmc(self): + """ + Just test if results generated with the external C++ API are + self-consistent with the internal python API. + We generate the "truth" results with the python API but + the main test produces the results file by running the + executable compiled from main.cpp. This future-proofs + the test - we only care that the two routes are equivalent. + """ if config['update']: # Generate the results file with internal python API openmc.run(openmc_exec=config['exe'], event_based=config['event']) elif config['mpi']: mpi_args = [config['mpiexec'], '-n', config['mpi_np']] + # Run main cpp executable with MPI openmc.run(openmc_exec=self.executable, mpi_args=mpi_args, event_based=config['event']) else: + # Run main cpp executable openmc.run(openmc_exec=self.executable, event_based=config['event']) From 88eb73688486c03c5960369bac2c911e543f581a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 27 May 2022 06:55:55 -0500 Subject: [PATCH 0356/2654] Respond to @pshriwise comment on #2074 --- openmc/plots.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openmc/plots.py b/openmc/plots.py index a1933cb5c..b22ee9125 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -637,9 +637,10 @@ class Plot(IDManagerMixin): color = _SVG_COLORS[color.lower()] subelement.text = ' '.join(str(x) for x in color) - # Helper function to handle either int or Cell/Material + # Helper function that returns the domain ID given either a + # Cell/Material object or the domain ID itself def get_id(domain): - return getattr(domain, 'id', domain) + return domain if isinstance(domain, Integral) else domain.id if self._colors: for domain, color in sorted(self._colors.items(), From bfa4b575b62b3f6be6e51ebc763384b53a0fb163 Mon Sep 17 00:00:00 2001 From: helen-brooks Date: Tue, 31 May 2022 09:14:51 +0100 Subject: [PATCH 0357/2654] Forgot the indent on docstring --- tests/regression_tests/dagmc/external/test.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/regression_tests/dagmc/external/test.py b/tests/regression_tests/dagmc/external/test.py index 2671f9a84..93123ae1e 100644 --- a/tests/regression_tests/dagmc/external/test.py +++ b/tests/regression_tests/dagmc/external/test.py @@ -101,14 +101,14 @@ class ExternalDAGMCTest(PyAPITestHarness): self.executable = executable def _run_openmc(self): - """ - Just test if results generated with the external C++ API are - self-consistent with the internal python API. - We generate the "truth" results with the python API but - the main test produces the results file by running the - executable compiled from main.cpp. This future-proofs - the test - we only care that the two routes are equivalent. - """ + """ + Just test if results generated with the external C++ API are + self-consistent with the internal python API. + We generate the "truth" results with the python API but + the main test produces the results file by running the + executable compiled from main.cpp. This future-proofs + the test - we only care that the two routes are equivalent. + """ if config['update']: # Generate the results file with internal python API openmc.run(openmc_exec=config['exe'], event_based=config['event']) From 8fdbbd2c43ce639c8d7ef9cff3c1b2ebd0f89695 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 31 May 2022 07:32:29 -0500 Subject: [PATCH 0358/2654] Set default max_tracks to 1000 --- docs/source/usersguide/scripts.rst | 2 +- man/man1/openmc.1 | 2 +- src/finalize.cpp | 2 +- src/output.cpp | 3 ++- src/settings.cpp | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst index 50d51a5b3..f2ba81605 100644 --- a/docs/source/usersguide/scripts.rst +++ b/docs/source/usersguide/scripts.rst @@ -47,7 +47,7 @@ flags: -r, --restart file Restart a previous run from a state point or a particle restart file -s, --threads N Run with *N* OpenMP threads --t, --track Write tracks for all particles +-t, --track Write tracks for all particles (up to max_tracks) -v, --version Show version information -h, --help Show help message diff --git a/man/man1/openmc.1 b/man/man1/openmc.1 index 460dbd358..6310750a2 100644 --- a/man/man1/openmc.1 +++ b/man/man1/openmc.1 @@ -34,7 +34,7 @@ Restart a previous run from a state point or a particle restart file named Use \fIN\fP OpenMP threads. .TP .B "\-t\fR, \fP\-\-track" -Write tracks for all particles. +Write tracks for all particles (up to max_tracks). .TP .B "\-v\fR, \fP\-\-version" Show version information. diff --git a/src/finalize.cpp b/src/finalize.cpp index 812483368..0c2c62310 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -85,7 +85,7 @@ int openmc_finalize() settings::material_cell_offsets = true; settings::max_particles_in_flight = 100000; settings::max_splits = 1000; - settings::max_tracks = std::numeric_limits::max(); + settings::max_tracks = 1000; settings::n_inactive = 0; settings::n_particles = -1; settings::output_summary = true; diff --git a/src/output.cpp b/src/output.cpp index 6565a9e67..ece475de0 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -318,7 +318,8 @@ void print_usage() " -r, --restart Restart a previous run from a state point\n" " or a particle restart file\n" " -s, --threads Number of OpenMP threads\n" - " -t, --track Write tracks for all particles\n" + " -t, --track Write tracks for all particles (up to " + "max_tracks)\n" " -e, --event Run using event-based parallelism\n" " -v, --version Show version information\n" " -h, --help Show this message\n"); diff --git a/src/settings.cpp b/src/settings.cpp index ecc1787c3..eb0d4936c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -95,7 +95,7 @@ int n_log_bins {8000}; int n_batches; int n_max_batches; int max_splits {1000}; -int max_tracks {std::numeric_limits::max()}; +int max_tracks {1000}; ResScatMethod res_scat_method {ResScatMethod::rvs}; double res_scat_energy_min {0.01}; double res_scat_energy_max {1000.0}; From fbfdf8227c607d231d6a18570374b059bf83ac16 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 31 May 2022 07:32:49 -0500 Subject: [PATCH 0359/2654] Fix loop in openmc-track-to-vtk --- scripts/openmc-track-to-vtk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index 2624ad239..3b3507974 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -41,7 +41,7 @@ def main(): # Write coordinate values to points array. track_file = openmc.Tracks(fname) for track in track_file: - for particle in track.particles: + for particle in track: for state in particle.states: points.InsertNextPoint(state['r']) From bf6e26600914320b0a5c2a4eb766d8faa01cbec8 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 31 May 2022 10:34:19 -0400 Subject: [PATCH 0360/2654] changed to single inheritance --- openmc/mesh.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d812f27ac..7f7b07879 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -126,8 +126,8 @@ class MeshBase(IDManagerMixin, ABC): raise ValueError(f'Unrecognized mesh type "{mesh_type}" found.') -class StructuredMesh(ABC): - """A mixin for structured mesh functionality +class StructuredMesh(MeshBase): + """A base class for structured mesh functionality Parameters ---------- @@ -194,8 +194,7 @@ class StructuredMesh(ABC): return (vertices[s0] + vertices[s1]) / 2 - -class RegularMesh(StructuredMesh, MeshBase): +class RegularMesh(StructuredMesh): """A regular Cartesian mesh in one, two, or three dimensions Parameters @@ -630,7 +629,7 @@ def Mesh(*args, **kwargs): return RegularMesh(*args, **kwargs) -class RectilinearMesh(MeshBase): +class RectilinearMesh(StructuredMesh): """A 3D rectilinear Cartesian mesh Parameters @@ -823,7 +822,7 @@ class RectilinearMesh(MeshBase): return element -class CylindricalMesh(MeshBase): +class CylindricalMesh(StructuredMesh): """A 3D cylindrical mesh Parameters @@ -1014,7 +1013,7 @@ class CylindricalMesh(MeshBase): return np.multiply.outer(np.outer(V_r, V_p), V_z) -class SphericalMesh(MeshBase): +class SphericalMesh(StructuredMesh): """A 3D spherical mesh Parameters From 6c07553b8953b5082a3f179d0d73b58f96e80851 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 31 May 2022 17:08:40 -0500 Subject: [PATCH 0361/2654] Add cell instance to particle track file (thanks @pshriwise for suggestion) --- docs/source/io_formats/track.rst | 17 +- docs/source/usersguide/settings.rst | 1 + include/openmc/particle_data.h | 1 + openmc/tracks.py | 3 +- src/particle_data.cpp | 1 + src/track_output.cpp | 2 + .../track_output/results_true.dat | 532 +++++++++--------- 7 files changed, 282 insertions(+), 275 deletions(-) diff --git a/docs/source/io_formats/track.rst b/docs/source/io_formats/track.rst index 59947ef22..a97d75e58 100644 --- a/docs/source/io_formats/track.rst +++ b/docs/source/io_formats/track.rst @@ -16,14 +16,15 @@ The current revision of the particle track file format is 3.0. - **track___

** (Compound type) -- Particle track information for source particle in batch *b*, generation *g*, and particle number *p*. particle. The compound type has fields ``r``, ``u``, - ``E``, ``time``, ``wgt``, ``cell_id``, and ``material_id``, which - represent the position (each coordinate in [cm]), direction, energy - in [eV], time in [s], weight, cell ID, and material ID, - respectively. When the particle is present in a cell with no - material assigned, the material ID is given as -1. Note that this - array contains information for one or more primary/secondary - particles originating. The starting index for each - primary/secondary particle is given by the ``offsets`` attribute. + ``E``, ``time``, ``wgt``, ``cell_id``, ``cell_instance``, and + ``material_id``, which represent the position (each coordinate in + [cm]), direction, energy in [eV], time in [s], weight, cell ID, + cell instance, and material ID, respectively. When the particle is + present in a cell with no material assigned, the material ID is + given as -1. Note that this array contains information for one or + more primary/secondary particles originating. The starting index + for each primary/secondary particle is given by the ``offsets`` + attribute. :Attributes: - **n_particles** (*int*) -- Number of primary/secondary particles for the source history. diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index f73967ad9..336982ac6 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -594,6 +594,7 @@ The full list of fields is as follows: :time: Time in [s] :wgt: Weight :cell_id: Cell ID + :cell_instance: Cell instance :material_id: Material ID Both the :class:`~openmc.Tracks` and :class:`~openmc.Track` classes have a diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 434d58c23..d3d00571a 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -64,6 +64,7 @@ struct TrackState { double time {0.0}; //!< Time in [s] double wgt {1.0}; //!< Weight int cell_id; //!< Cell ID + int cell_instance; //!< Cell instance int material_id {-1}; //!< Material ID (default value indicates void) }; diff --git a/openmc/tracks.py b/openmc/tracks.py index b8b479cc6..e9097e8ee 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -19,7 +19,8 @@ states : numpy.ndarray Structured array containing each state of the particle. The structured array contains the following fields: ``r`` (position; each direction in [cm]), ``u`` (direction), ``E`` (energy in [eV]), ``time`` (time in [s]), ``wgt`` - (weight), ``cell_id`` (cell ID) , and ``material_id`` (material ID). + (weight), ``cell_id`` (cell ID) , ``cell_instance`` (cell instance), and + ``material_id`` (material ID). """ def _particle_track_repr(self): diff --git a/src/particle_data.cpp b/src/particle_data.cpp index 4206d9cd9..a2be72084 100644 --- a/src/particle_data.cpp +++ b/src/particle_data.cpp @@ -64,6 +64,7 @@ TrackState ParticleData::get_track_state() const state.time = this->time(); state.wgt = this->wgt(); state.cell_id = model::cells[this->lowest_coord().cell]->id_; + state.cell_instance = this->cell_instance(); if (this->material() != MATERIAL_VOID) { state.material_id = model::materials[material()]->id_; } diff --git a/src/track_output.cpp b/src/track_output.cpp index f74920bbe..5c1436de7 100644 --- a/src/track_output.cpp +++ b/src/track_output.cpp @@ -73,6 +73,8 @@ void open_track_file() H5Tinsert(track_dtype, "wgt", HOFFSET(TrackState, wgt), H5T_NATIVE_DOUBLE); H5Tinsert( track_dtype, "cell_id", HOFFSET(TrackState, cell_id), H5T_NATIVE_INT); + H5Tinsert(track_dtype, "cell_instance", HOFFSET(TrackState, cell_instance), + H5T_NATIVE_INT); H5Tinsert(track_dtype, "material_id", HOFFSET(TrackState, material_id), H5T_NATIVE_INT); H5Tclose(postype); diff --git a/tests/regression_tests/track_output/results_true.dat b/tests/regression_tests/track_output/results_true.dat index d36aee6ed..756226d10 100644 --- a/tests/regression_tests/track_output/results_true.dat +++ b/tests/regression_tests/track_output/results_true.dat @@ -1,266 +1,266 @@ -ParticleType.NEUTRON [((-9.663085e-01, -6.616522e-01, -9.863690e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 0.000000e+00, 1.000000e+00, 23, 1) - ((-1.281491e+00, -4.879529e-01, -7.708709e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.323629e-10, 1.000000e+00, 22, 3) - ((-1.368452e+00, -4.400285e-01, -7.114141e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.688824e-10, 1.000000e+00, 21, 2) - ((-2.150539e+00, -9.015151e-03, -1.766823e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 4.973246e-10, 1.000000e+00, 22, 3) - ((-2.237499e+00, 3.890922e-02, -1.172255e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 5.338441e-10, 1.000000e+00, 23, 1) - ((-2.453640e+00, 1.580257e-01, 3.055504e-02), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 6.246136e-10, 1.000000e+00, 23, 1) - ((-2.767485e+00, 3.309877e-01, 2.451383e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 7.564146e-10, 1.000000e+00, 22, 3) - ((-2.825099e+00, 3.627392e-01, 2.845305e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 7.806100e-10, 1.000000e+00, 22, 3) - ((-3.274427e+00, 6.029890e-01, 6.987901e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 9.878481e-10, 1.000000e+00, 23, 1) - ((-3.676327e+00, 8.178800e-01, 1.069324e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.173212e-09, 1.000000e+00, 23, 1) - ((-4.089400e+00, 1.038745e+00, 1.450158e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.363728e-09, 1.000000e+00, 23, 1) - ((-4.456639e+00, 1.235102e+00, 1.788735e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.533105e-09, 1.000000e+00, 22, 3) - ((-4.536974e+00, 1.278056e+00, 1.862800e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.570157e-09, 1.000000e+00, 21, 2) - ((-5.410401e+00, 1.745067e+00, 2.668060e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.972998e-09, 1.000000e+00, 22, 3) - ((-5.490736e+00, 1.788021e+00, 2.742125e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 2.010050e-09, 1.000000e+00, 23, 1) - ((-5.576301e+00, 1.833771e+00, 2.821012e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.049514e-09, 1.000000e+00, 23, 1) - ((-5.725160e+00, 1.896661e+00, 2.330311e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.227030e-09, 1.000000e+00, 23, 1) - ((-6.116514e+00, 2.061999e+00, 1.040248e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.693724e-09, 1.000000e+00, 22, 3) - ((-6.534762e+00, 2.238699e+00, -3.384686e-01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.192489e-09, 1.000000e+00, 23, 1) - ((-7.043525e+00, 2.453640e+00, -2.015560e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.799195e-09, 1.000000e+00, 23, 1) - ((-7.360920e+00, 2.587732e+00, -3.061825e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 4.177692e-09, 1.000000e+00, 11, 1) - ((-8.996680e+00, 3.278803e+00, -8.453960e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.128354e-09, 1.000000e+00, 23, 1) - ((-9.220205e+00, 3.373238e+00, -9.190791e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.394910e-09, 1.000000e+00, 22, 3) - ((-9.320244e+00, 3.415502e+00, -9.520561e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.514208e-09, 1.000000e+00, 21, 2) - ((-1.005591e+01, 3.726304e+00, -1.194562e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.391498e-09, 1.000000e+00, 22, 3) - ((-1.015595e+01, 3.768569e+00, -1.227539e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.510796e-09, 1.000000e+00, 23, 1) - ((-1.062054e+01, 3.964848e+00, -1.380687e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.064826e-09, 1.000000e+00, 23, 1) - ((-1.063244e+01, 3.969501e+00, -1.382484e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.072756e-09, 1.000000e+00, 23, 1) - ((-1.093907e+01, 4.089400e+00, -1.428802e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.277097e-09, 1.000000e+00, 23, 1) - ((-1.108410e+01, 4.146112e+00, -1.450710e+01), (4.855193e-01, 3.316053e-01, -8.088937e-01), 8.856868e+05, 8.373750e-09, 1.000000e+00, 23, 1) - ((-1.080173e+01, 4.338973e+00, -1.497755e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 8.820862e-09, 1.000000e+00, 23, 1) - ((-1.063244e+01, 4.371524e+00, -1.555290e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 9.317522e-09, 1.000000e+00, 23, 1) - ((-1.041266e+01, 4.413783e+00, -1.629984e+01), (2.686183e-01, -3.269476e-01, -9.060626e-01), 6.562001e+05, 9.962308e-09, 1.000000e+00, 23, 1) - ((-1.016754e+01, 4.115428e+00, -1.712667e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.077718e-08, 1.000000e+00, 23, 1) - ((-1.019064e+01, 4.089400e+00, -1.713747e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.087569e-08, 1.000000e+00, 23, 1) - ((-1.024915e+01, 4.023496e+00, -1.716481e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.112511e-08, 1.000000e+00, 23, 1) - ((-1.018199e+01, 3.749638e+00, -1.740047e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.276389e-08, 1.000000e+00, 22, 3) - ((-1.015866e+01, 3.654498e+00, -1.748234e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.333321e-08, 1.000000e+00, 21, 2) - ((-1.009978e+01, 3.414404e+00, -1.768895e+01), (1.735861e-01, -9.678731e-01, 1.819053e-01), 2.620416e+04, 1.476994e-08, 1.000000e+00, 21, 2) - ((-9.994809e+00, 2.829099e+00, -1.757894e+01), (4.635724e-01, 5.558106e-01, 6.900545e-01), 2.214649e+04, 1.747088e-08, 1.000000e+00, 21, 2) - ((-9.553365e+00, 3.358379e+00, -1.692183e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.209726e-08, 1.000000e+00, 21, 2) - ((-1.011854e+01, 3.687059e+00, -1.760205e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.716243e-08, 1.000000e+00, 22, 3) - ((-1.020058e+01, 3.734765e+00, -1.770077e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.789760e-08, 1.000000e+00, 23, 1) - ((-1.063244e+01, 3.985917e+00, -1.822054e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.176800e-08, 1.000000e+00, 23, 1) - ((-1.081038e+01, 4.089400e+00, -1.843470e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.336273e-08, 1.000000e+00, 23, 1) - ((-1.081564e+01, 4.092455e+00, -1.844103e+01), (-6.690877e-01, 6.718700e-01, -3.176671e-01), 1.355236e+04, 3.340982e-08, 1.000000e+00, 23, 1) - ((-1.096190e+01, 4.239327e+00, -1.851047e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.476743e-08, 1.000000e+00, 23, 1) - ((-1.109457e+01, 4.420404e+00, -1.850054e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.628014e-08, 1.000000e+00, 22, 3) - ((-1.113484e+01, 4.475368e+00, -1.849752e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.673931e-08, 1.000000e+00, 22, 3) - ((-1.117187e+01, 4.372425e+00, -1.850142e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.748914e-08, 1.000000e+00, 23, 1) - ((-1.127367e+01, 4.089400e+00, -1.851213e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.955064e-08, 1.000000e+00, 23, 1) - ((-1.135375e+01, 3.866733e+00, -1.852056e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.117251e-08, 1.000000e+00, 22, 3) - ((-1.138419e+01, 3.782113e+00, -1.852377e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.178887e-08, 1.000000e+00, 21, 2) - ((-1.172456e+01, 2.835777e+00, -1.855959e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.868184e-08, 1.000000e+00, 22, 3) - ((-1.175499e+01, 2.751157e+00, -1.856280e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.929820e-08, 1.000000e+00, 23, 1) - ((-1.179525e+01, 2.639224e+00, -1.856703e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.011351e-08, 1.000000e+00, 23, 1) - ((-1.190609e+01, 2.453640e+00, -1.847770e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.190861e-08, 1.000000e+00, 23, 1) - ((-1.222017e+01, 1.927741e+00, -1.822457e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.699551e-08, 1.000000e+00, 23, 1) - ((-1.226820e+01, 1.951470e+00, -1.815983e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.888995e-08, 1.000000e+00, 23, 1) - ((-1.236181e+01, 1.997712e+00, -1.803368e+01), (1.748787e-01, 6.613493e-01, 7.294070e-01), 4.250133e+02, 6.258186e-08, 1.000000e+00, 23, 1) - ((-1.234968e+01, 2.043587e+00, -1.798308e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 6.501444e-08, 1.000000e+00, 23, 1) - ((-1.276513e+01, 2.146245e+00, -1.744506e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 8.979603e-08, 1.000000e+00, 22, 3) - ((-1.313233e+01, 2.236980e+00, -1.696953e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 1.116994e-07, 1.000000e+00, 23, 1) - ((-1.318468e+01, 2.249916e+00, -1.690173e+01), (-8.862976e-01, -6.402442e-02, 4.586692e-01), 3.113244e+02, 1.148223e-07, 1.000000e+00, 23, 1) - ((-1.363685e+01, 2.217253e+00, -1.666773e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.357269e-07, 1.000000e+00, 23, 1) - ((-1.334593e+01, 2.453640e+00, -1.709033e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.617034e-07, 1.000000e+00, 23, 1) - ((-1.308145e+01, 2.668542e+00, -1.747452e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.853189e-07, 1.000000e+00, 22, 3) - ((-1.304150e+01, 2.701005e+00, -1.753256e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.888862e-07, 1.000000e+00, 22, 3) - ((-1.304665e+01, 2.669815e+00, -1.753058e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.903682e-07, 1.000000e+00, 23, 1) - ((-1.308231e+01, 2.453640e+00, -1.751686e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.006392e-07, 1.000000e+00, 23, 1) - ((-1.311790e+01, 2.237916e+00, -1.750317e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.108888e-07, 1.000000e+00, 22, 3) - ((-1.313266e+01, 2.148507e+00, -1.749750e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.151369e-07, 1.000000e+00, 21, 2) - ((-1.320190e+01, 1.728791e+00, -1.747087e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.350787e-07, 1.000000e+00, 21, 2) - ((-1.309582e+01, 2.150526e+00, -1.834143e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.808996e-07, 1.000000e+00, 22, 3) - ((-1.307365e+01, 2.238628e+00, -1.852329e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.904717e-07, 1.000000e+00, 23, 1) - ((-1.301957e+01, 2.453640e+00, -1.896713e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 3.138324e-07, 1.000000e+00, 23, 1) - ((-1.297913e+01, 2.614390e+00, -1.929896e+01), (6.012134e-01, 7.985735e-01, -2.868317e-02), 4.041011e+01, 3.312976e-07, 1.000000e+00, 23, 1) - ((-1.295975e+01, 2.640133e+00, -1.929988e+01), (6.762805e-01, -5.875192e-01, 4.443713e-01), 3.527833e+01, 3.349640e-07, 1.000000e+00, 23, 1) - ((-1.282907e+01, 2.526604e+00, -1.921402e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.584852e-07, 1.000000e+00, 23, 1) - ((-1.284217e+01, 2.453640e+00, -1.921346e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.799102e-07, 1.000000e+00, 23, 1) - ((-1.288683e+01, 2.204886e+00, -1.921158e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.529534e-07, 1.000000e+00, 22, 3) - ((-1.290264e+01, 2.116831e+00, -1.921091e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.788097e-07, 1.000000e+00, 21, 2) - ((-1.308145e+01, 1.120923e+00, -1.920338e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.712448e-07, 1.000000e+00, 22, 3) - ((-1.309726e+01, 1.032868e+00, -1.920271e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.971010e-07, 1.000000e+00, 23, 1) - ((-1.312690e+01, 8.677798e-01, -1.920146e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.455768e-07, 1.000000e+00, 23, 1) - ((-1.316626e+01, 8.178800e-01, -1.918559e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.693415e-07, 1.000000e+00, 23, 1) - ((-1.324019e+01, 7.241633e-01, -1.915578e+01), (-9.367321e-01, -1.471894e-01, -3.175976e-01), 2.365289e+00, 9.139738e-07, 1.000000e+00, 23, 1) - ((-1.348497e+01, 6.857011e-01, -1.923877e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.036815e-06, 1.000000e+00, 23, 1) - ((-1.390396e+01, 7.859275e-01, -1.924890e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.269071e-06, 1.000000e+00, 23, 1) - ((-1.403754e+01, 8.178800e-01, -1.925212e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.343115e-06, 1.000000e+00, 23, 1) - ((-1.504223e+01, 1.058212e+00, -1.927640e+01), (-4.085804e-01, -2.719942e-01, -8.712526e-01), 1.628266e+00, 1.900041e-06, 1.000000e+00, 23, 1) - ((-1.523744e+01, 9.282558e-01, -1.969268e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.170751e-06, 1.000000e+00, 23, 1) - ((-1.553972e+01, 1.106680e+00, -1.997974e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.636878e-06, 1.000000e+00, 23, 1) - ((-1.585973e+01, 1.295571e+00, -2.028364e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.130348e-06, 1.000000e+00, 22, 3) - ((-1.593583e+01, 1.340489e+00, -2.035590e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.247693e-06, 1.000000e+00, 21, 2) - ((-1.647184e+01, 1.656882e+00, -2.086494e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 4.074258e-06, 1.000000e+00, 21, 2) - ((-1.585080e+01, 1.545037e+00, -2.159072e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.061748e-06, 1.000000e+00, 22, 3) - ((-1.576406e+01, 1.529415e+00, -2.169209e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.199673e-06, 1.000000e+00, 23, 1) - ((-1.553972e+01, 1.489015e+00, -2.195425e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.556377e-06, 1.000000e+00, 23, 1) - ((-1.546081e+01, 1.474803e+00, -2.204648e+01), (3.257038e-01, -9.420596e-01, -8.025439e-02), 3.076319e-01, 5.681852e-06, 1.000000e+00, 23, 1) - ((-1.543563e+01, 1.401988e+00, -2.205268e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 5.782605e-06, 1.000000e+00, 23, 1) - ((-1.553972e+01, 1.153338e+00, -2.213907e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 6.487752e-06, 1.000000e+00, 23, 1) - ((-1.565955e+01, 8.670807e-01, -2.223854e+01), (1.611814e-01, 2.692337e-01, -9.494913e-01), 8.559448e-02, 7.299552e-06, 1.000000e+00, 23, 1) - ((-1.563263e+01, 9.120446e-01, -2.239711e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 7.712256e-06, 1.000000e+00, 23, 1) - ((-1.592604e+01, 1.214620e+00, -2.249695e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.406031e-06, 1.000000e+00, 22, 3) - ((-1.598742e+01, 1.277922e+00, -2.251784e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.760391e-06, 1.000000e+00, 21, 2) - ((-1.670388e+01, 2.016770e+00, -2.276163e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.389636e-05, 1.000000e+00, 22, 3) - ((-1.676526e+01, 2.080073e+00, -2.278252e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.425072e-05, 1.000000e+00, 23, 1) - ((-1.681575e+01, 2.132139e+00, -2.279970e+01), (4.286076e-02, -9.409799e-01, -3.357375e-01), 1.813618e-02, 1.454218e-05, 1.000000e+00, 23, 1) - ((-1.681374e+01, 2.087933e+00, -2.281547e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.479439e-05, 1.000000e+00, 23, 1) - ((-1.682083e+01, 2.021795e+00, -2.287841e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.532970e-05, 1.000000e+00, 22, 3) - ((-1.684417e+01, 1.804084e+00, -2.308558e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.709182e-05, 1.000000e+00, 21, 2) - ((-1.686879e+01, 1.574384e+00, -2.330417e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.895097e-05, 1.000000e+00, 22, 3) - ((-1.689212e+01, 1.356673e+00, -2.351134e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 2.071309e-05, 1.000000e+00, 23, 1) - ((-1.689233e+01, 1.354754e+00, -2.351317e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.072862e-05, 1.000000e+00, 23, 1) - ((-1.689148e+01, 1.355453e+00, -2.351229e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.073958e-05, 1.000000e+00, 22, 3) - ((-1.682182e+01, 1.413107e+00, -2.343954e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.164421e-05, 1.000000e+00, 21, 2) - ((-1.636364e+01, 1.792326e+00, -2.296107e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 2.759442e-05, 1.000000e+00, 21, 2) - ((-1.598564e+01, 1.746738e+00, -2.286758e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 3.079609e-05, 0.000000e+00, 21, 2)] -ParticleType.NEUTRON [((-9.469716e-01, -2.580266e-01, 1.414357e-01), (1.438873e-01, 2.365819e-01, 9.608983e-01), 9.724461e+05, 0.000000e+00, 1.000000e+00, 23, 1) - ((-9.064818e-01, -1.914524e-01, 4.118326e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 2.064696e-10, 1.000000e+00, 23, 1) - ((-8.178800e-01, -1.616918e-01, 4.336377e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 3.725262e-10, 1.000000e+00, 11, 1) - ((-3.834875e-01, -1.578285e-02, 5.405432e-01), (-5.547498e-01, -6.358598e-02, 8.295839e-01), 1.474011e+05, 1.186660e-09, 1.000000e+00, 11, 1) - ((-7.999329e-01, -6.351625e-02, 1.163304e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.600465e-09, 1.000000e+00, 11, 1) - ((-8.178800e-01, -6.341842e-02, 1.190721e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.662321e-09, 1.000000e+00, 23, 1) - ((-1.035984e+00, -6.222961e-02, 1.523906e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.414026e-09, 1.000000e+00, 22, 3) - ((-1.124618e+00, -6.174649e-02, 1.659308e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.719509e-09, 1.000000e+00, 21, 2) - ((-1.705404e+00, -5.858082e-02, 2.546543e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 5.721217e-09, 1.000000e+00, 21, 2) - ((-1.851116e+00, -4.676544e-01, 2.685103e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.583734e-09, 1.000000e+00, 22, 3) - ((-1.880791e+00, -5.509662e-01, 2.713322e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.759394e-09, 1.000000e+00, 23, 1) - ((-1.948026e+00, -7.397227e-01, 2.777257e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.157380e-09, 1.000000e+00, 23, 1) - ((-2.068870e+00, -8.178800e-01, 2.735799e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.598974e-09, 1.000000e+00, 23, 1) - ((-2.111345e+00, -8.453511e-01, 2.721228e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 7.754188e-09, 1.000000e+00, 23, 1) - ((-2.453640e+00, -1.161216e+00, 3.335542e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.421339e-08, 1.000000e+00, 23, 1) - ((-2.715369e+00, -1.402736e+00, 3.805265e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.915229e-08, 1.000000e+00, 22, 3) - ((-2.785083e+00, -1.467067e+00, 3.930380e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 2.046780e-08, 1.000000e+00, 21, 2) - ((-2.940196e+00, -1.610203e+00, 4.208760e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 2.339483e-08, 1.000000e+00, 21, 2) - ((-3.600602e+00, -1.239800e+00, 3.812386e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.112139e-08, 1.000000e+00, 22, 3) - ((-3.682067e+00, -1.194109e+00, 3.763490e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.207450e-08, 1.000000e+00, 23, 1) - ((-4.089400e+00, -9.656478e-01, 3.519009e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.684019e-08, 1.000000e+00, 23, 1) - ((-4.185927e+00, -9.115084e-01, 3.461074e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 3.796953e-08, 1.000000e+00, 23, 1) - ((-4.089400e+00, -9.150200e-01, 3.260397e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 6.996444e-08, 1.000000e+00, 23, 1) - ((-3.920090e+00, -9.211794e-01, 2.908406e+00), (9.094673e-01, -3.659267e-01, -1.974002e-01), 9.547085e+00, 1.260840e-07, 1.000000e+00, 23, 1) - ((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 1) - ((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 1)] -ParticleType.NEUTRON [((6.474155e+00, -5.192870e+00, 5.413003e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2) - ((6.467293e+00, -5.416535e+00, 5.441544e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450870e-05, 1.000000e+00, 22, 3) - ((6.464574e+00, -5.505149e+00, 5.452851e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450874e-05, 1.000000e+00, 23, 1) - ((6.461877e+00, -5.593034e+00, 5.464065e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450879e-05, 1.000000e+00, 23, 1) - ((6.570892e+00, -5.725160e+00, 5.464970e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450891e-05, 1.000000e+00, 32, 1) - ((6.821003e+00, -6.028296e+00, 5.467047e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450917e-05, 1.000000e+00, 31, 4) - ((7.101210e+00, -6.367908e+00, 5.469374e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450947e-05, 1.000000e+00, 32, 1) - ((7.360920e+00, -6.682677e+00, 5.471531e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450975e-05, 1.000000e+00, 23, 1) - ((7.833926e+00, -7.255962e+00, 5.475459e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451025e-05, 1.000000e+00, 23, 1) - ((8.142528e+00, -7.144944e+00, 5.464309e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451091e-05, 1.000000e+00, 22, 3) - ((8.590199e+00, -6.983897e+00, 5.448136e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451187e-05, 1.000000e+00, 23, 1) - ((8.682515e+00, -6.950687e+00, 5.444801e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451207e-05, 1.000000e+00, 23, 1) - ((8.996680e+00, -6.629985e+00, 5.450966e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451307e-05, 1.000000e+00, 23, 1) - ((9.231138e+00, -6.390649e+00, 5.455567e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451382e-05, 1.000000e+00, 22, 3) - ((9.650189e+00, -5.962879e+00, 5.463790e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451516e-05, 1.000000e+00, 23, 1) - ((9.721007e+00, -5.890588e+00, 5.465180e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451539e-05, 1.000000e+00, 23, 1) - ((9.939012e+00, -5.953026e+00, 5.222655e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451775e-05, 1.000000e+00, 22, 3) - ((1.002133e+01, -5.976602e+00, 5.131083e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451864e-05, 1.000000e+00, 23, 1) - ((1.020258e+01, -6.028514e+00, 4.929446e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452060e-05, 1.000000e+00, 23, 1) - ((1.063244e+01, -6.047973e+00, 4.703991e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452432e-05, 1.000000e+00, 23, 1) - ((1.084241e+01, -6.057477e+00, 4.593868e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452614e-05, 1.000000e+00, 23, 1) - ((1.107130e+01, -6.074053e+00, 4.699070e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452930e-05, 1.000000e+00, 22, 3) - ((1.121611e+01, -6.084540e+00, 4.765623e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453130e-05, 1.000000e+00, 21, 2) - ((1.174815e+01, -6.123069e+00, 5.010155e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453866e-05, 1.000000e+00, 22, 3) - ((1.189296e+01, -6.133556e+00, 5.076709e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.454067e-05, 1.000000e+00, 23, 1) - ((1.221698e+01, -6.157021e+00, 5.225634e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454515e-05, 1.000000e+00, 23, 1) - ((1.226820e+01, -6.225607e+00, 5.179351e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454893e-05, 1.000000e+00, 23, 1) - ((1.230378e+01, -6.273253e+00, 5.147199e+00), (9.203567e-01, -2.667811e-01, -2.859569e-01), 2.269067e+02, 4.455157e-05, 1.000000e+00, 23, 1) - ((1.237909e+01, -6.295083e+00, 5.123800e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.455549e-05, 1.000000e+00, 23, 1) - ((1.250758e+01, -6.372926e+00, 5.147974e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456396e-05, 1.000000e+00, 22, 3) - ((1.258603e+01, -6.420455e+00, 5.162734e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456914e-05, 1.000000e+00, 21, 2) - ((1.264082e+01, -6.453648e+00, 5.173042e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.457275e-05, 1.000000e+00, 21, 2) - ((1.288240e+01, -7.015898e+00, 5.025449e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.460837e-05, 1.000000e+00, 22, 3) - ((1.292943e+01, -7.125332e+00, 4.996722e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.461530e-05, 1.000000e+00, 23, 1) - ((1.303065e+01, -7.360920e+00, 4.934879e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.463022e-05, 1.000000e+00, 23, 1) - ((1.309295e+01, -7.505897e+00, 4.896822e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.463941e-05, 1.000000e+00, 23, 1) - ((1.311741e+01, -7.576618e+00, 4.913644e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.464426e-05, 1.000000e+00, 22, 3) - ((1.314895e+01, -7.667795e+00, 4.935331e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.465052e-05, 1.000000e+00, 21, 2) - ((1.345125e+01, -8.541749e+00, 5.143210e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471053e-05, 1.000000e+00, 22, 3) - ((1.348278e+01, -8.632925e+00, 5.164897e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471679e-05, 1.000000e+00, 23, 1) - ((1.356121e+01, -8.859646e+00, 5.218825e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.473236e-05, 1.000000e+00, 23, 1) - ((1.361604e+01, -8.996680e+00, 5.275368e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.474248e-05, 1.000000e+00, 23, 1) - ((1.390396e+01, -9.716172e+00, 5.572247e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.479558e-05, 1.000000e+00, 23, 1) - ((1.399742e+01, -9.949713e+00, 5.668611e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.481282e-05, 1.000000e+00, 23, 1) - ((1.390396e+01, -1.004824e+01, 5.750282e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.483180e-05, 1.000000e+00, 23, 1) - ((1.334984e+01, -1.063244e+01, 6.234531e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.494435e-05, 1.000000e+00, 23, 1) - ((1.317711e+01, -1.081455e+01, 6.385480e+00), (-4.211158e-01, -4.515418e-01, 7.866203e-01), 3.302717e+01, 4.497943e-05, 1.000000e+00, 23, 1) - ((1.316679e+01, -1.082561e+01, 6.404749e+00), (-5.182259e-01, 3.860612e-01, 7.631505e-01), 1.437084e+01, 4.498251e-05, 1.000000e+00, 23, 1) - ((1.292206e+01, -1.064329e+01, 6.765147e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.507257e-05, 1.000000e+00, 23, 1) - ((1.286229e+01, -1.063244e+01, 6.805923e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.508772e-05, 1.000000e+00, 23, 1) - ((1.284917e+01, -1.063006e+01, 6.814880e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509105e-05, 1.000000e+00, 23, 1) - ((1.284547e+01, -1.063244e+01, 6.820442e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509285e-05, 1.000000e+00, 23, 1) - ((1.249929e+01, -1.085555e+01, 7.341246e+00), (-1.520079e-01, -3.513652e-01, 9.238161e-01), 7.069024e+00, 4.526201e-05, 1.000000e+00, 23, 1) - ((1.240103e+01, -1.108268e+01, 7.938428e+00), (-7.405967e-01, -3.230926e-01, 5.891754e-01), 4.460475e+00, 4.543779e-05, 1.000000e+00, 23, 1) - ((1.229354e+01, -1.112958e+01, 8.023945e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.548748e-05, 1.000000e+00, 23, 1) - ((1.226820e+01, -1.110933e+01, 8.041241e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.550624e-05, 1.000000e+00, 23, 1) - ((1.198501e+01, -1.088299e+01, 8.234567e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.571593e-05, 1.000000e+00, 23, 1) - ((1.156403e+01, -1.063244e+01, 8.480859e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.600087e-05, 1.000000e+00, 23, 1) - ((1.150264e+01, -1.059590e+01, 8.516776e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.604243e-05, 1.000000e+00, 23, 1) - ((1.121659e+01, -1.063244e+01, 8.744860e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.623561e-05, 1.000000e+00, 23, 1) - ((1.063244e+01, -1.070706e+01, 9.210632e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.663011e-05, 1.000000e+00, 23, 1) - ((1.035391e+01, -1.074263e+01, 9.432717e+00), (-4.847677e-01, -8.685325e-01, -1.032060e-01), 5.647686e-01, 4.681821e-05, 1.000000e+00, 23, 1) - ((1.031409e+01, -1.081397e+01, 9.424239e+00), (-4.227592e-01, -9.022601e-01, -8.486053e-02), 5.651902e-01, 4.689723e-05, 1.000000e+00, 23, 1) - ((1.028497e+01, -1.087614e+01, 9.418392e+00), (1.549579e-01, -4.270887e-01, 8.908329e-01), 5.395517e-01, 4.696349e-05, 1.000000e+00, 23, 1) - ((1.034128e+01, -1.103135e+01, 9.742126e+00), (5.631544e-01, 4.925564e-01, 6.635098e-01), 2.637257e-01, 4.732118e-05, 1.000000e+00, 23, 1) - ((1.044415e+01, -1.094137e+01, 9.863334e+00), (-1.034377e-01, 7.912271e-01, 6.027108e-01), 1.474934e-01, 4.757836e-05, 1.000000e+00, 23, 1) - ((1.043959e+01, -1.090643e+01, 9.889950e+00), (1.163182e-01, 9.160889e-01, -3.837331e-01), 1.522434e-01, 4.766149e-05, 1.000000e+00, 23, 1) - ((1.045733e+01, -1.076664e+01, 9.831395e+00), (-8.136862e-01, 9.805444e-02, -5.729748e-01), 3.341488e-02, 4.794423e-05, 1.000000e+00, 23, 1) - ((1.044231e+01, -1.076483e+01, 9.820815e+00), (-8.437241e-01, 5.222731e-01, -1.239373e-01), 3.874838e-02, 4.801727e-05, 1.000000e+00, 23, 1) - ((1.028725e+01, -1.066884e+01, 9.798037e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.869227e-05, 1.000000e+00, 23, 1) - ((1.021310e+01, -1.063244e+01, 9.757708e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.902498e-05, 1.000000e+00, 23, 1) - ((1.012717e+01, -1.059025e+01, 9.710967e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 4.941058e-05, 1.000000e+00, 23, 1) - ((1.001043e+01, -1.038486e+01, 9.645483e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 5.039049e-05, 1.000000e+00, 22, 3) - ((9.971285e+00, -1.031600e+01, 9.623530e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.071901e-05, 1.000000e+00, 22, 3) - ((1.002723e+01, -1.037881e+01, 9.564267e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.116633e-05, 1.000000e+00, 23, 1) - ((1.025152e+01, -1.063060e+01, 9.326683e+00), (-8.159392e-01, -4.792697e-03, 5.781179e-01), 2.920905e-02, 5.295966e-05, 1.000000e+00, 23, 1) - ((1.000779e+01, -1.063203e+01, 9.499373e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422329e-05, 1.000000e+00, 23, 1) - ((1.000721e+01, -1.063244e+01, 9.498835e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422746e-05, 1.000000e+00, 23, 1) - ((9.852478e+00, -1.074269e+01, 9.354584e+00), (-6.686452e-01, -2.988396e-01, 6.808880e-01), 2.993224e-02, 5.534454e-05, 1.000000e+00, 23, 1) - ((9.765042e+00, -1.078177e+01, 9.443621e+00), (7.712484e-01, -5.215773e-01, 3.648739e-01), 3.590785e-02, 5.589099e-05, 1.000000e+00, 23, 1) - ((9.798992e+00, -1.080472e+01, 9.459682e+00), (-4.563170e-01, 8.081811e-01, -3.723144e-01), 2.674168e-02, 5.605894e-05, 1.000000e+00, 23, 1) - ((9.792857e+00, -1.079386e+01, 9.454677e+00), (-9.080336e-01, 4.172659e-01, 3.693418e-02), 9.753404e-03, 5.611838e-05, 1.000000e+00, 23, 1) - ((9.653805e+00, -1.072996e+01, 9.460332e+00), (-3.727950e-01, 2.889342e-01, -8.817828e-01), 1.781716e-02, 5.723944e-05, 1.000000e+00, 23, 1) - ((9.628677e+00, -1.071048e+01, 9.400895e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.760453e-05, 1.000000e+00, 23, 1) - ((9.563380e+00, -1.063244e+01, 9.395105e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.815928e-05, 1.000000e+00, 23, 1) - ((9.411305e+00, -1.045068e+01, 9.381621e+00), (3.205568e-01, -1.311309e-02, -9.471385e-01), 2.153422e-02, 5.945128e-05, 1.000000e+00, 23, 1) - ((9.860026e+00, -1.046903e+01, 8.055798e+00), (6.278124e-01, 1.023095e-01, -7.716115e-01), 2.013742e-02, 6.634788e-05, 1.000000e+00, 23, 1) - ((1.007604e+01, -1.043383e+01, 7.790303e+00), (6.790346e-01, 5.167838e-01, 5.213891e-01), 1.340865e-02, 6.810089e-05, 1.000000e+00, 23, 1) - ((1.008869e+01, -1.042421e+01, 7.800011e+00), (2.792456e-01, 1.367953e-01, 9.504257e-01), 8.576635e-03, 6.821715e-05, 1.000000e+00, 23, 1) - ((1.017046e+01, -1.038415e+01, 8.078330e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.050324e-05, 1.000000e+00, 23, 1) - ((1.008276e+01, -1.035463e+01, 8.083559e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.070353e-05, 1.000000e+00, 22, 3) - ((9.952201e+00, -1.031068e+01, 8.091343e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.100170e-05, 1.000000e+00, 21, 2) - ((9.404929e+00, -1.012646e+01, 8.123973e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.225157e-05, 1.000000e+00, 22, 3) - ((9.274369e+00, -1.008251e+01, 8.131758e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.254974e-05, 1.000000e+00, 23, 1) - ((9.126730e+00, -1.003281e+01, 8.140560e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.288692e-05, 1.000000e+00, 23, 1) - ((8.996680e+00, -1.006767e+01, 8.217365e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.321528e-05, 1.000000e+00, 23, 1) - ((8.694758e+00, -1.014859e+01, 8.395674e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.397758e-05, 1.000000e+00, 23, 1) - ((8.996680e+00, -9.720167e+00, 8.656770e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.511228e-05, 1.000000e+00, 23, 1) - ((9.263031e+00, -9.342216e+00, 8.887105e+00), (5.734531e-01, -5.017666e-01, 6.475970e-01), 9.798082e-02, 7.611330e-05, 1.000000e+00, 23, 1) - ((9.334809e+00, -9.405021e+00, 8.968164e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.640240e-05, 1.000000e+00, 23, 1) - ((9.335117e+00, -9.448857e+00, 8.932084e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.651925e-05, 1.000000e+00, 22, 3) - ((9.336345e+00, -9.623801e+00, 8.788098e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.698556e-05, 1.000000e+00, 21, 2) - ((9.339070e+00, -1.001201e+01, 8.468584e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.802034e-05, 1.000000e+00, 22, 3) - ((9.340298e+00, -1.018696e+01, 8.324598e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.848665e-05, 1.000000e+00, 23, 1) - ((9.343193e+00, -1.059945e+01, 7.985097e+00), (1.798796e-01, 3.522536e-02, -9.830577e-01), 1.283272e-01, 7.958616e-05, 1.000000e+00, 23, 1) - ((9.397753e+00, -1.058877e+01, 7.686922e+00), (6.459563e-01, 7.279465e-03, -7.633397e-01), 1.319449e-01, 8.019832e-05, 1.000000e+00, 23, 1) - ((9.462343e+00, -1.058804e+01, 7.610595e+00), (-5.748716e-01, 5.760301e-01, -5.811299e-01), 8.880732e-02, 8.039733e-05, 1.000000e+00, 23, 1) - ((9.287877e+00, -1.041322e+01, 7.434230e+00), (-4.932135e-03, 1.668926e-01, 9.859627e-01), 3.503028e-02, 8.113361e-05, 1.000000e+00, 23, 1) - ((9.286930e+00, -1.038117e+01, 7.623600e+00), (-9.325544e-02, -9.933000e-01, -6.825369e-02), 3.173764e-02, 8.187553e-05, 1.000000e+00, 23, 1) - ((9.283901e+00, -1.041342e+01, 7.621384e+00), (-4.235208e-01, -5.129112e-01, 7.466942e-01), 4.258127e-02, 8.200731e-05, 1.000000e+00, 23, 1) - ((9.264517e+00, -1.043690e+01, 7.655560e+00), (-7.165846e-01, 3.926265e-01, 5.764988e-01), 4.485063e-02, 8.216767e-05, 1.000000e+00, 23, 1) - ((9.256348e+00, -1.043242e+01, 7.662132e+00), (1.703748e-01, -9.175599e-01, -3.592441e-01), 3.521226e-02, 8.220659e-05, 1.000000e+00, 23, 1) - ((9.284015e+00, -1.058143e+01, 7.603793e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.283227e-05, 1.000000e+00, 23, 1) - ((9.309126e+00, -1.063244e+01, 7.631745e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.309804e-05, 1.000000e+00, 23, 1) - ((9.317824e+00, -1.065011e+01, 7.641427e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.319011e-05, 1.000000e+00, 23, 1) - ((9.459378e+00, -1.063244e+01, 7.505770e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.403060e-05, 1.000000e+00, 23, 1) - ((9.492454e+00, -1.062831e+01, 7.474071e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.422700e-05, 1.000000e+00, 23, 1) - ((9.492472e+00, -1.063244e+01, 7.472688e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.424159e-05, 1.000000e+00, 23, 1) - ((9.492761e+00, -1.069927e+01, 7.450302e+00), (9.457151e-01, -1.928731e-01, 2.615777e-01), 4.542312e-02, 8.447773e-05, 1.000000e+00, 23, 1) - ((9.890524e+00, -1.078039e+01, 7.560320e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.590450e-05, 1.000000e+00, 23, 1) - ((1.004645e+01, -1.080498e+01, 7.439717e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.651090e-05, 0.000000e+00, 23, 1)] +ParticleType.NEUTRON [((-9.663085e-01, -6.616522e-01, -9.863690e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 0.000000e+00, 1.000000e+00, 23, 2403, 1) + ((-1.281491e+00, -4.879529e-01, -7.708709e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.323629e-10, 1.000000e+00, 22, 2403, 3) + ((-1.368452e+00, -4.400285e-01, -7.114141e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.688824e-10, 1.000000e+00, 21, 2403, 2) + ((-2.150539e+00, -9.015151e-03, -1.766823e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 4.973246e-10, 1.000000e+00, 22, 2403, 3) + ((-2.237499e+00, 3.890922e-02, -1.172255e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 5.338441e-10, 1.000000e+00, 23, 2403, 1) + ((-2.453640e+00, 1.580257e-01, 3.055504e-02), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 6.246136e-10, 1.000000e+00, 23, 2402, 1) + ((-2.767485e+00, 3.309877e-01, 2.451383e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 7.564146e-10, 1.000000e+00, 22, 2402, 3) + ((-2.825099e+00, 3.627392e-01, 2.845305e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 7.806100e-10, 1.000000e+00, 22, 2402, 3) + ((-3.274427e+00, 6.029890e-01, 6.987901e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 9.878481e-10, 1.000000e+00, 23, 2402, 1) + ((-3.676327e+00, 8.178800e-01, 1.069324e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.173212e-09, 1.000000e+00, 23, 2416, 1) + ((-4.089400e+00, 1.038745e+00, 1.450158e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.363728e-09, 1.000000e+00, 23, 2415, 1) + ((-4.456639e+00, 1.235102e+00, 1.788735e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.533105e-09, 1.000000e+00, 22, 2415, 3) + ((-4.536974e+00, 1.278056e+00, 1.862800e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.570157e-09, 1.000000e+00, 21, 2415, 2) + ((-5.410401e+00, 1.745067e+00, 2.668060e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.972998e-09, 1.000000e+00, 22, 2415, 3) + ((-5.490736e+00, 1.788021e+00, 2.742125e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 2.010050e-09, 1.000000e+00, 23, 2415, 1) + ((-5.576301e+00, 1.833771e+00, 2.821012e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.049514e-09, 1.000000e+00, 23, 2415, 1) + ((-5.725160e+00, 1.896661e+00, 2.330311e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.227030e-09, 1.000000e+00, 23, 2414, 1) + ((-6.116514e+00, 2.061999e+00, 1.040248e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.693724e-09, 1.000000e+00, 22, 2414, 3) + ((-6.534762e+00, 2.238699e+00, -3.384686e-01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.192489e-09, 1.000000e+00, 23, 2414, 1) + ((-7.043525e+00, 2.453640e+00, -2.015560e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.799195e-09, 1.000000e+00, 23, 2428, 1) + ((-7.360920e+00, 2.587732e+00, -3.061825e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 4.177692e-09, 1.000000e+00, 11, 1757, 1) + ((-8.996680e+00, 3.278803e+00, -8.453960e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.128354e-09, 1.000000e+00, 23, 2427, 1) + ((-9.220205e+00, 3.373238e+00, -9.190791e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.394910e-09, 1.000000e+00, 22, 2427, 3) + ((-9.320244e+00, 3.415502e+00, -9.520561e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.514208e-09, 1.000000e+00, 21, 2427, 2) + ((-1.005591e+01, 3.726304e+00, -1.194562e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.391498e-09, 1.000000e+00, 22, 2427, 3) + ((-1.015595e+01, 3.768569e+00, -1.227539e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.510796e-09, 1.000000e+00, 23, 2427, 1) + ((-1.062054e+01, 3.964848e+00, -1.380687e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.064826e-09, 1.000000e+00, 23, 2427, 1) + ((-1.063244e+01, 3.969501e+00, -1.382484e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.072756e-09, 1.000000e+00, 23, 2426, 1) + ((-1.093907e+01, 4.089400e+00, -1.428802e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.277097e-09, 1.000000e+00, 23, 2437, 1) + ((-1.108410e+01, 4.146112e+00, -1.450710e+01), (4.855193e-01, 3.316053e-01, -8.088937e-01), 8.856868e+05, 8.373750e-09, 1.000000e+00, 23, 2437, 1) + ((-1.080173e+01, 4.338973e+00, -1.497755e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 8.820862e-09, 1.000000e+00, 23, 2437, 1) + ((-1.063244e+01, 4.371524e+00, -1.555290e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 9.317522e-09, 1.000000e+00, 23, 2438, 1) + ((-1.041266e+01, 4.413783e+00, -1.629984e+01), (2.686183e-01, -3.269476e-01, -9.060626e-01), 6.562001e+05, 9.962308e-09, 1.000000e+00, 23, 2438, 1) + ((-1.016754e+01, 4.115428e+00, -1.712667e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.077718e-08, 1.000000e+00, 23, 2438, 1) + ((-1.019064e+01, 4.089400e+00, -1.713747e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.087569e-08, 1.000000e+00, 23, 2427, 1) + ((-1.024915e+01, 4.023496e+00, -1.716481e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.112511e-08, 1.000000e+00, 23, 2427, 1) + ((-1.018199e+01, 3.749638e+00, -1.740047e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.276389e-08, 1.000000e+00, 22, 2427, 3) + ((-1.015866e+01, 3.654498e+00, -1.748234e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.333321e-08, 1.000000e+00, 21, 2427, 2) + ((-1.009978e+01, 3.414404e+00, -1.768895e+01), (1.735861e-01, -9.678731e-01, 1.819053e-01), 2.620416e+04, 1.476994e-08, 1.000000e+00, 21, 2427, 2) + ((-9.994809e+00, 2.829099e+00, -1.757894e+01), (4.635724e-01, 5.558106e-01, 6.900545e-01), 2.214649e+04, 1.747088e-08, 1.000000e+00, 21, 2427, 2) + ((-9.553365e+00, 3.358379e+00, -1.692183e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.209726e-08, 1.000000e+00, 21, 2427, 2) + ((-1.011854e+01, 3.687059e+00, -1.760205e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.716243e-08, 1.000000e+00, 22, 2427, 3) + ((-1.020058e+01, 3.734765e+00, -1.770077e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.789760e-08, 1.000000e+00, 23, 2427, 1) + ((-1.063244e+01, 3.985917e+00, -1.822054e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.176800e-08, 1.000000e+00, 23, 2426, 1) + ((-1.081038e+01, 4.089400e+00, -1.843470e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.336273e-08, 1.000000e+00, 23, 2437, 1) + ((-1.081564e+01, 4.092455e+00, -1.844103e+01), (-6.690877e-01, 6.718700e-01, -3.176671e-01), 1.355236e+04, 3.340982e-08, 1.000000e+00, 23, 2437, 1) + ((-1.096190e+01, 4.239327e+00, -1.851047e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.476743e-08, 1.000000e+00, 23, 2437, 1) + ((-1.109457e+01, 4.420404e+00, -1.850054e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.628014e-08, 1.000000e+00, 22, 2437, 3) + ((-1.113484e+01, 4.475368e+00, -1.849752e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.673931e-08, 1.000000e+00, 22, 2437, 3) + ((-1.117187e+01, 4.372425e+00, -1.850142e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.748914e-08, 1.000000e+00, 23, 2437, 1) + ((-1.127367e+01, 4.089400e+00, -1.851213e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.955064e-08, 1.000000e+00, 23, 2426, 1) + ((-1.135375e+01, 3.866733e+00, -1.852056e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.117251e-08, 1.000000e+00, 22, 2426, 3) + ((-1.138419e+01, 3.782113e+00, -1.852377e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.178887e-08, 1.000000e+00, 21, 2426, 2) + ((-1.172456e+01, 2.835777e+00, -1.855959e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.868184e-08, 1.000000e+00, 22, 2426, 3) + ((-1.175499e+01, 2.751157e+00, -1.856280e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.929820e-08, 1.000000e+00, 23, 2426, 1) + ((-1.179525e+01, 2.639224e+00, -1.856703e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.011351e-08, 1.000000e+00, 23, 2426, 1) + ((-1.190609e+01, 2.453640e+00, -1.847770e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.190861e-08, 1.000000e+00, 23, 2411, 1) + ((-1.222017e+01, 1.927741e+00, -1.822457e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.699551e-08, 1.000000e+00, 23, 2411, 1) + ((-1.226820e+01, 1.951470e+00, -1.815983e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.888995e-08, 1.000000e+00, 23, 2100, 1) + ((-1.236181e+01, 1.997712e+00, -1.803368e+01), (1.748787e-01, 6.613493e-01, 7.294070e-01), 4.250133e+02, 6.258186e-08, 1.000000e+00, 23, 2100, 1) + ((-1.234968e+01, 2.043587e+00, -1.798308e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 6.501444e-08, 1.000000e+00, 23, 2100, 1) + ((-1.276513e+01, 2.146245e+00, -1.744506e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 8.979603e-08, 1.000000e+00, 22, 2100, 3) + ((-1.313233e+01, 2.236980e+00, -1.696953e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 1.116994e-07, 1.000000e+00, 23, 2100, 1) + ((-1.318468e+01, 2.249916e+00, -1.690173e+01), (-8.862976e-01, -6.402442e-02, 4.586692e-01), 3.113244e+02, 1.148223e-07, 1.000000e+00, 23, 2100, 1) + ((-1.363685e+01, 2.217253e+00, -1.666773e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.357269e-07, 1.000000e+00, 23, 2100, 1) + ((-1.334593e+01, 2.453640e+00, -1.709033e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.617034e-07, 1.000000e+00, 23, 2101, 1) + ((-1.308145e+01, 2.668542e+00, -1.747452e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.853189e-07, 1.000000e+00, 22, 2101, 3) + ((-1.304150e+01, 2.701005e+00, -1.753256e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.888862e-07, 1.000000e+00, 22, 2101, 3) + ((-1.304665e+01, 2.669815e+00, -1.753058e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.903682e-07, 1.000000e+00, 23, 2101, 1) + ((-1.308231e+01, 2.453640e+00, -1.751686e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.006392e-07, 1.000000e+00, 23, 2100, 1) + ((-1.311790e+01, 2.237916e+00, -1.750317e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.108888e-07, 1.000000e+00, 22, 2100, 3) + ((-1.313266e+01, 2.148507e+00, -1.749750e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.151369e-07, 1.000000e+00, 21, 2100, 2) + ((-1.320190e+01, 1.728791e+00, -1.747087e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.350787e-07, 1.000000e+00, 21, 2100, 2) + ((-1.309582e+01, 2.150526e+00, -1.834143e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.808996e-07, 1.000000e+00, 22, 2100, 3) + ((-1.307365e+01, 2.238628e+00, -1.852329e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.904717e-07, 1.000000e+00, 23, 2100, 1) + ((-1.301957e+01, 2.453640e+00, -1.896713e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 3.138324e-07, 1.000000e+00, 23, 2101, 1) + ((-1.297913e+01, 2.614390e+00, -1.929896e+01), (6.012134e-01, 7.985735e-01, -2.868317e-02), 4.041011e+01, 3.312976e-07, 1.000000e+00, 23, 2101, 1) + ((-1.295975e+01, 2.640133e+00, -1.929988e+01), (6.762805e-01, -5.875192e-01, 4.443713e-01), 3.527833e+01, 3.349640e-07, 1.000000e+00, 23, 2101, 1) + ((-1.282907e+01, 2.526604e+00, -1.921402e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.584852e-07, 1.000000e+00, 23, 2101, 1) + ((-1.284217e+01, 2.453640e+00, -1.921346e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.799102e-07, 1.000000e+00, 23, 2100, 1) + ((-1.288683e+01, 2.204886e+00, -1.921158e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.529534e-07, 1.000000e+00, 22, 2100, 3) + ((-1.290264e+01, 2.116831e+00, -1.921091e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.788097e-07, 1.000000e+00, 21, 2100, 2) + ((-1.308145e+01, 1.120923e+00, -1.920338e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.712448e-07, 1.000000e+00, 22, 2100, 3) + ((-1.309726e+01, 1.032868e+00, -1.920271e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.971010e-07, 1.000000e+00, 23, 2100, 1) + ((-1.312690e+01, 8.677798e-01, -1.920146e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.455768e-07, 1.000000e+00, 23, 2100, 1) + ((-1.316626e+01, 8.178800e-01, -1.918559e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.693415e-07, 1.000000e+00, 23, 2099, 1) + ((-1.324019e+01, 7.241633e-01, -1.915578e+01), (-9.367321e-01, -1.471894e-01, -3.175976e-01), 2.365289e+00, 9.139738e-07, 1.000000e+00, 23, 2099, 1) + ((-1.348497e+01, 6.857011e-01, -1.923877e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.036815e-06, 1.000000e+00, 23, 2099, 1) + ((-1.390396e+01, 7.859275e-01, -1.924890e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.269071e-06, 1.000000e+00, 23, 2114, 1) + ((-1.403754e+01, 8.178800e-01, -1.925212e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.343115e-06, 1.000000e+00, 23, 2115, 1) + ((-1.504223e+01, 1.058212e+00, -1.927640e+01), (-4.085804e-01, -2.719942e-01, -8.712526e-01), 1.628266e+00, 1.900041e-06, 1.000000e+00, 23, 2115, 1) + ((-1.523744e+01, 9.282558e-01, -1.969268e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.170751e-06, 1.000000e+00, 23, 2115, 1) + ((-1.553972e+01, 1.106680e+00, -1.997974e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.636878e-06, 1.000000e+00, 23, 2129, 1) + ((-1.585973e+01, 1.295571e+00, -2.028364e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.130348e-06, 1.000000e+00, 22, 2129, 3) + ((-1.593583e+01, 1.340489e+00, -2.035590e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.247693e-06, 1.000000e+00, 21, 2129, 2) + ((-1.647184e+01, 1.656882e+00, -2.086494e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 4.074258e-06, 1.000000e+00, 21, 2129, 2) + ((-1.585080e+01, 1.545037e+00, -2.159072e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.061748e-06, 1.000000e+00, 22, 2129, 3) + ((-1.576406e+01, 1.529415e+00, -2.169209e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.199673e-06, 1.000000e+00, 23, 2129, 1) + ((-1.553972e+01, 1.489015e+00, -2.195425e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.556377e-06, 1.000000e+00, 23, 2115, 1) + ((-1.546081e+01, 1.474803e+00, -2.204648e+01), (3.257038e-01, -9.420596e-01, -8.025439e-02), 3.076319e-01, 5.681852e-06, 1.000000e+00, 23, 2115, 1) + ((-1.543563e+01, 1.401988e+00, -2.205268e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 5.782605e-06, 1.000000e+00, 23, 2115, 1) + ((-1.553972e+01, 1.153338e+00, -2.213907e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 6.487752e-06, 1.000000e+00, 23, 2129, 1) + ((-1.565955e+01, 8.670807e-01, -2.223854e+01), (1.611814e-01, 2.692337e-01, -9.494913e-01), 8.559448e-02, 7.299552e-06, 1.000000e+00, 23, 2129, 1) + ((-1.563263e+01, 9.120446e-01, -2.239711e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 7.712256e-06, 1.000000e+00, 23, 2129, 1) + ((-1.592604e+01, 1.214620e+00, -2.249695e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.406031e-06, 1.000000e+00, 22, 2129, 3) + ((-1.598742e+01, 1.277922e+00, -2.251784e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.760391e-06, 1.000000e+00, 21, 2129, 2) + ((-1.670388e+01, 2.016770e+00, -2.276163e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.389636e-05, 1.000000e+00, 22, 2129, 3) + ((-1.676526e+01, 2.080073e+00, -2.278252e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.425072e-05, 1.000000e+00, 23, 2129, 1) + ((-1.681575e+01, 2.132139e+00, -2.279970e+01), (4.286076e-02, -9.409799e-01, -3.357375e-01), 1.813618e-02, 1.454218e-05, 1.000000e+00, 23, 2129, 1) + ((-1.681374e+01, 2.087933e+00, -2.281547e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.479439e-05, 1.000000e+00, 23, 2129, 1) + ((-1.682083e+01, 2.021795e+00, -2.287841e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.532970e-05, 1.000000e+00, 22, 2129, 3) + ((-1.684417e+01, 1.804084e+00, -2.308558e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.709182e-05, 1.000000e+00, 21, 2129, 2) + ((-1.686879e+01, 1.574384e+00, -2.330417e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.895097e-05, 1.000000e+00, 22, 2129, 3) + ((-1.689212e+01, 1.356673e+00, -2.351134e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 2.071309e-05, 1.000000e+00, 23, 2129, 1) + ((-1.689233e+01, 1.354754e+00, -2.351317e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.072862e-05, 1.000000e+00, 23, 2129, 1) + ((-1.689148e+01, 1.355453e+00, -2.351229e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.073958e-05, 1.000000e+00, 22, 2129, 3) + ((-1.682182e+01, 1.413107e+00, -2.343954e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.164421e-05, 1.000000e+00, 21, 2129, 2) + ((-1.636364e+01, 1.792326e+00, -2.296107e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 2.759442e-05, 1.000000e+00, 21, 2129, 2) + ((-1.598564e+01, 1.746738e+00, -2.286758e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 3.079609e-05, 0.000000e+00, 21, 2129, 2)] +ParticleType.NEUTRON [((-9.469716e-01, -2.580266e-01, 1.414357e-01), (1.438873e-01, 2.365819e-01, 9.608983e-01), 9.724461e+05, 0.000000e+00, 1.000000e+00, 23, 2403, 1) + ((-9.064818e-01, -1.914524e-01, 4.118326e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 2.064696e-10, 1.000000e+00, 23, 2403, 1) + ((-8.178800e-01, -1.616918e-01, 4.336377e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 3.725262e-10, 1.000000e+00, 11, 1756, 1) + ((-3.834875e-01, -1.578285e-02, 5.405432e-01), (-5.547498e-01, -6.358598e-02, 8.295839e-01), 1.474011e+05, 1.186660e-09, 1.000000e+00, 11, 1756, 1) + ((-7.999329e-01, -6.351625e-02, 1.163304e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.600465e-09, 1.000000e+00, 11, 1756, 1) + ((-8.178800e-01, -6.341842e-02, 1.190721e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.662321e-09, 1.000000e+00, 23, 2403, 1) + ((-1.035984e+00, -6.222961e-02, 1.523906e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.414026e-09, 1.000000e+00, 22, 2403, 3) + ((-1.124618e+00, -6.174649e-02, 1.659308e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.719509e-09, 1.000000e+00, 21, 2403, 2) + ((-1.705404e+00, -5.858082e-02, 2.546543e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 5.721217e-09, 1.000000e+00, 21, 2403, 2) + ((-1.851116e+00, -4.676544e-01, 2.685103e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.583734e-09, 1.000000e+00, 22, 2403, 3) + ((-1.880791e+00, -5.509662e-01, 2.713322e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.759394e-09, 1.000000e+00, 23, 2403, 1) + ((-1.948026e+00, -7.397227e-01, 2.777257e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.157380e-09, 1.000000e+00, 23, 2403, 1) + ((-2.068870e+00, -8.178800e-01, 2.735799e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.598974e-09, 1.000000e+00, 23, 2388, 1) + ((-2.111345e+00, -8.453511e-01, 2.721228e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 7.754188e-09, 1.000000e+00, 23, 2388, 1) + ((-2.453640e+00, -1.161216e+00, 3.335542e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.421339e-08, 1.000000e+00, 23, 2387, 1) + ((-2.715369e+00, -1.402736e+00, 3.805265e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.915229e-08, 1.000000e+00, 22, 2387, 3) + ((-2.785083e+00, -1.467067e+00, 3.930380e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 2.046780e-08, 1.000000e+00, 21, 2387, 2) + ((-2.940196e+00, -1.610203e+00, 4.208760e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 2.339483e-08, 1.000000e+00, 21, 2387, 2) + ((-3.600602e+00, -1.239800e+00, 3.812386e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.112139e-08, 1.000000e+00, 22, 2387, 3) + ((-3.682067e+00, -1.194109e+00, 3.763490e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.207450e-08, 1.000000e+00, 23, 2387, 1) + ((-4.089400e+00, -9.656478e-01, 3.519009e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.684019e-08, 1.000000e+00, 23, 2386, 1) + ((-4.185927e+00, -9.115084e-01, 3.461074e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 3.796953e-08, 1.000000e+00, 23, 2386, 1) + ((-4.089400e+00, -9.150200e-01, 3.260397e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 6.996444e-08, 1.000000e+00, 23, 2387, 1) + ((-3.920090e+00, -9.211794e-01, 2.908406e+00), (9.094673e-01, -3.659267e-01, -1.974002e-01), 9.547085e+00, 1.260840e-07, 1.000000e+00, 23, 2387, 1) + ((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 2387, 1) + ((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 2387, 1)] +ParticleType.NEUTRON [((6.474155e+00, -5.192870e+00, 5.413003e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2367, 2) + ((6.467293e+00, -5.416535e+00, 5.441544e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450870e-05, 1.000000e+00, 22, 2367, 3) + ((6.464574e+00, -5.505149e+00, 5.452851e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450874e-05, 1.000000e+00, 23, 2367, 1) + ((6.461877e+00, -5.593034e+00, 5.464065e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450879e-05, 1.000000e+00, 23, 2367, 1) + ((6.570892e+00, -5.725160e+00, 5.464970e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450891e-05, 1.000000e+00, 32, 7, 1) + ((6.821003e+00, -6.028296e+00, 5.467047e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450917e-05, 1.000000e+00, 31, 7, 4) + ((7.101210e+00, -6.367908e+00, 5.469374e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450947e-05, 1.000000e+00, 32, 7, 1) + ((7.360920e+00, -6.682677e+00, 5.471531e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450975e-05, 1.000000e+00, 23, 2353, 1) + ((7.833926e+00, -7.255962e+00, 5.475459e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451025e-05, 1.000000e+00, 23, 2353, 1) + ((8.142528e+00, -7.144944e+00, 5.464309e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451091e-05, 1.000000e+00, 22, 2353, 3) + ((8.590199e+00, -6.983897e+00, 5.448136e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451187e-05, 1.000000e+00, 23, 2353, 1) + ((8.682515e+00, -6.950687e+00, 5.444801e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451207e-05, 1.000000e+00, 23, 2353, 1) + ((8.996680e+00, -6.629985e+00, 5.450966e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451307e-05, 1.000000e+00, 23, 2354, 1) + ((9.231138e+00, -6.390649e+00, 5.455567e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451382e-05, 1.000000e+00, 22, 2354, 3) + ((9.650189e+00, -5.962879e+00, 5.463790e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451516e-05, 1.000000e+00, 23, 2354, 1) + ((9.721007e+00, -5.890588e+00, 5.465180e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451539e-05, 1.000000e+00, 23, 2354, 1) + ((9.939012e+00, -5.953026e+00, 5.222655e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451775e-05, 1.000000e+00, 22, 2354, 3) + ((1.002133e+01, -5.976602e+00, 5.131083e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451864e-05, 1.000000e+00, 23, 2354, 1) + ((1.020258e+01, -6.028514e+00, 4.929446e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452060e-05, 1.000000e+00, 23, 2354, 1) + ((1.063244e+01, -6.047973e+00, 4.703991e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452432e-05, 1.000000e+00, 23, 2355, 1) + ((1.084241e+01, -6.057477e+00, 4.593868e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452614e-05, 1.000000e+00, 23, 2355, 1) + ((1.107130e+01, -6.074053e+00, 4.699070e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452930e-05, 1.000000e+00, 22, 2355, 3) + ((1.121611e+01, -6.084540e+00, 4.765623e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453130e-05, 1.000000e+00, 21, 2355, 2) + ((1.174815e+01, -6.123069e+00, 5.010155e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453866e-05, 1.000000e+00, 22, 2355, 3) + ((1.189296e+01, -6.133556e+00, 5.076709e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.454067e-05, 1.000000e+00, 23, 2355, 1) + ((1.221698e+01, -6.157021e+00, 5.225634e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454515e-05, 1.000000e+00, 23, 2355, 1) + ((1.226820e+01, -6.225607e+00, 5.179351e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454893e-05, 1.000000e+00, 23, 2519, 1) + ((1.230378e+01, -6.273253e+00, 5.147199e+00), (9.203567e-01, -2.667811e-01, -2.859569e-01), 2.269067e+02, 4.455157e-05, 1.000000e+00, 23, 2519, 1) + ((1.237909e+01, -6.295083e+00, 5.123800e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.455549e-05, 1.000000e+00, 23, 2519, 1) + ((1.250758e+01, -6.372926e+00, 5.147974e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456396e-05, 1.000000e+00, 22, 2519, 3) + ((1.258603e+01, -6.420455e+00, 5.162734e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456914e-05, 1.000000e+00, 21, 2519, 2) + ((1.264082e+01, -6.453648e+00, 5.173042e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.457275e-05, 1.000000e+00, 21, 2519, 2) + ((1.288240e+01, -7.015898e+00, 5.025449e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.460837e-05, 1.000000e+00, 22, 2519, 3) + ((1.292943e+01, -7.125332e+00, 4.996722e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.461530e-05, 1.000000e+00, 23, 2519, 1) + ((1.303065e+01, -7.360920e+00, 4.934879e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.463022e-05, 1.000000e+00, 23, 2520, 1) + ((1.309295e+01, -7.505897e+00, 4.896822e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.463941e-05, 1.000000e+00, 23, 2520, 1) + ((1.311741e+01, -7.576618e+00, 4.913644e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.464426e-05, 1.000000e+00, 22, 2520, 3) + ((1.314895e+01, -7.667795e+00, 4.935331e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.465052e-05, 1.000000e+00, 21, 2520, 2) + ((1.345125e+01, -8.541749e+00, 5.143210e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471053e-05, 1.000000e+00, 22, 2520, 3) + ((1.348278e+01, -8.632925e+00, 5.164897e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471679e-05, 1.000000e+00, 23, 2520, 1) + ((1.356121e+01, -8.859646e+00, 5.218825e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.473236e-05, 1.000000e+00, 23, 2520, 1) + ((1.361604e+01, -8.996680e+00, 5.275368e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.474248e-05, 1.000000e+00, 23, 2521, 1) + ((1.390396e+01, -9.716172e+00, 5.572247e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.479558e-05, 1.000000e+00, 23, 2536, 1) + ((1.399742e+01, -9.949713e+00, 5.668611e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.481282e-05, 1.000000e+00, 23, 2536, 1) + ((1.390396e+01, -1.004824e+01, 5.750282e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.483180e-05, 1.000000e+00, 23, 2521, 1) + ((1.334984e+01, -1.063244e+01, 6.234531e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.494435e-05, 1.000000e+00, 23, 2522, 1) + ((1.317711e+01, -1.081455e+01, 6.385480e+00), (-4.211158e-01, -4.515418e-01, 7.866203e-01), 3.302717e+01, 4.497943e-05, 1.000000e+00, 23, 2522, 1) + ((1.316679e+01, -1.082561e+01, 6.404749e+00), (-5.182259e-01, 3.860612e-01, 7.631505e-01), 1.437084e+01, 4.498251e-05, 1.000000e+00, 23, 2522, 1) + ((1.292206e+01, -1.064329e+01, 6.765147e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.507257e-05, 1.000000e+00, 23, 2522, 1) + ((1.286229e+01, -1.063244e+01, 6.805923e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.508772e-05, 1.000000e+00, 23, 2521, 1) + ((1.284917e+01, -1.063006e+01, 6.814880e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509105e-05, 1.000000e+00, 23, 2521, 1) + ((1.284547e+01, -1.063244e+01, 6.820442e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509285e-05, 1.000000e+00, 23, 2522, 1) + ((1.249929e+01, -1.085555e+01, 7.341246e+00), (-1.520079e-01, -3.513652e-01, 9.238161e-01), 7.069024e+00, 4.526201e-05, 1.000000e+00, 23, 2522, 1) + ((1.240103e+01, -1.108268e+01, 7.938428e+00), (-7.405967e-01, -3.230926e-01, 5.891754e-01), 4.460475e+00, 4.543779e-05, 1.000000e+00, 23, 2522, 1) + ((1.229354e+01, -1.112958e+01, 8.023945e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.548748e-05, 1.000000e+00, 23, 2522, 1) + ((1.226820e+01, -1.110933e+01, 8.041241e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.550624e-05, 1.000000e+00, 23, 2314, 1) + ((1.198501e+01, -1.088299e+01, 8.234567e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.571593e-05, 1.000000e+00, 23, 2314, 1) + ((1.156403e+01, -1.063244e+01, 8.480859e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.600087e-05, 1.000000e+00, 23, 2329, 1) + ((1.150264e+01, -1.059590e+01, 8.516776e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.604243e-05, 1.000000e+00, 23, 2329, 1) + ((1.121659e+01, -1.063244e+01, 8.744860e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.623561e-05, 1.000000e+00, 23, 2314, 1) + ((1.063244e+01, -1.070706e+01, 9.210632e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.663011e-05, 1.000000e+00, 23, 2313, 1) + ((1.035391e+01, -1.074263e+01, 9.432717e+00), (-4.847677e-01, -8.685325e-01, -1.032060e-01), 5.647686e-01, 4.681821e-05, 1.000000e+00, 23, 2313, 1) + ((1.031409e+01, -1.081397e+01, 9.424239e+00), (-4.227592e-01, -9.022601e-01, -8.486053e-02), 5.651902e-01, 4.689723e-05, 1.000000e+00, 23, 2313, 1) + ((1.028497e+01, -1.087614e+01, 9.418392e+00), (1.549579e-01, -4.270887e-01, 8.908329e-01), 5.395517e-01, 4.696349e-05, 1.000000e+00, 23, 2313, 1) + ((1.034128e+01, -1.103135e+01, 9.742126e+00), (5.631544e-01, 4.925564e-01, 6.635098e-01), 2.637257e-01, 4.732118e-05, 1.000000e+00, 23, 2313, 1) + ((1.044415e+01, -1.094137e+01, 9.863334e+00), (-1.034377e-01, 7.912271e-01, 6.027108e-01), 1.474934e-01, 4.757836e-05, 1.000000e+00, 23, 2313, 1) + ((1.043959e+01, -1.090643e+01, 9.889950e+00), (1.163182e-01, 9.160889e-01, -3.837331e-01), 1.522434e-01, 4.766149e-05, 1.000000e+00, 23, 2313, 1) + ((1.045733e+01, -1.076664e+01, 9.831395e+00), (-8.136862e-01, 9.805444e-02, -5.729748e-01), 3.341488e-02, 4.794423e-05, 1.000000e+00, 23, 2313, 1) + ((1.044231e+01, -1.076483e+01, 9.820815e+00), (-8.437241e-01, 5.222731e-01, -1.239373e-01), 3.874838e-02, 4.801727e-05, 1.000000e+00, 23, 2313, 1) + ((1.028725e+01, -1.066884e+01, 9.798037e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.869227e-05, 1.000000e+00, 23, 2313, 1) + ((1.021310e+01, -1.063244e+01, 9.757708e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.902498e-05, 1.000000e+00, 23, 2328, 1) + ((1.012717e+01, -1.059025e+01, 9.710967e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 4.941058e-05, 1.000000e+00, 23, 2328, 1) + ((1.001043e+01, -1.038486e+01, 9.645483e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 5.039049e-05, 1.000000e+00, 22, 2328, 3) + ((9.971285e+00, -1.031600e+01, 9.623530e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.071901e-05, 1.000000e+00, 22, 2328, 3) + ((1.002723e+01, -1.037881e+01, 9.564267e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.116633e-05, 1.000000e+00, 23, 2328, 1) + ((1.025152e+01, -1.063060e+01, 9.326683e+00), (-8.159392e-01, -4.792697e-03, 5.781179e-01), 2.920905e-02, 5.295966e-05, 1.000000e+00, 23, 2328, 1) + ((1.000779e+01, -1.063203e+01, 9.499373e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422329e-05, 1.000000e+00, 23, 2328, 1) + ((1.000721e+01, -1.063244e+01, 9.498835e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422746e-05, 1.000000e+00, 23, 2313, 1) + ((9.852478e+00, -1.074269e+01, 9.354584e+00), (-6.686452e-01, -2.988396e-01, 6.808880e-01), 2.993224e-02, 5.534454e-05, 1.000000e+00, 23, 2313, 1) + ((9.765042e+00, -1.078177e+01, 9.443621e+00), (7.712484e-01, -5.215773e-01, 3.648739e-01), 3.590785e-02, 5.589099e-05, 1.000000e+00, 23, 2313, 1) + ((9.798992e+00, -1.080472e+01, 9.459682e+00), (-4.563170e-01, 8.081811e-01, -3.723144e-01), 2.674168e-02, 5.605894e-05, 1.000000e+00, 23, 2313, 1) + ((9.792857e+00, -1.079386e+01, 9.454677e+00), (-9.080336e-01, 4.172659e-01, 3.693418e-02), 9.753404e-03, 5.611838e-05, 1.000000e+00, 23, 2313, 1) + ((9.653805e+00, -1.072996e+01, 9.460332e+00), (-3.727950e-01, 2.889342e-01, -8.817828e-01), 1.781716e-02, 5.723944e-05, 1.000000e+00, 23, 2313, 1) + ((9.628677e+00, -1.071048e+01, 9.400895e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.760453e-05, 1.000000e+00, 23, 2313, 1) + ((9.563380e+00, -1.063244e+01, 9.395105e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.815928e-05, 1.000000e+00, 23, 2328, 1) + ((9.411305e+00, -1.045068e+01, 9.381621e+00), (3.205568e-01, -1.311309e-02, -9.471385e-01), 2.153422e-02, 5.945128e-05, 1.000000e+00, 23, 2328, 1) + ((9.860026e+00, -1.046903e+01, 8.055798e+00), (6.278124e-01, 1.023095e-01, -7.716115e-01), 2.013742e-02, 6.634788e-05, 1.000000e+00, 23, 2328, 1) + ((1.007604e+01, -1.043383e+01, 7.790303e+00), (6.790346e-01, 5.167838e-01, 5.213891e-01), 1.340865e-02, 6.810089e-05, 1.000000e+00, 23, 2328, 1) + ((1.008869e+01, -1.042421e+01, 7.800011e+00), (2.792456e-01, 1.367953e-01, 9.504257e-01), 8.576635e-03, 6.821715e-05, 1.000000e+00, 23, 2328, 1) + ((1.017046e+01, -1.038415e+01, 8.078330e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.050324e-05, 1.000000e+00, 23, 2328, 1) + ((1.008276e+01, -1.035463e+01, 8.083559e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.070353e-05, 1.000000e+00, 22, 2328, 3) + ((9.952201e+00, -1.031068e+01, 8.091343e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.100170e-05, 1.000000e+00, 21, 2328, 2) + ((9.404929e+00, -1.012646e+01, 8.123973e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.225157e-05, 1.000000e+00, 22, 2328, 3) + ((9.274369e+00, -1.008251e+01, 8.131758e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.254974e-05, 1.000000e+00, 23, 2328, 1) + ((9.126730e+00, -1.003281e+01, 8.140560e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.288692e-05, 1.000000e+00, 23, 2328, 1) + ((8.996680e+00, -1.006767e+01, 8.217365e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.321528e-05, 1.000000e+00, 23, 2327, 1) + ((8.694758e+00, -1.014859e+01, 8.395674e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.397758e-05, 1.000000e+00, 23, 2327, 1) + ((8.996680e+00, -9.720167e+00, 8.656770e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.511228e-05, 1.000000e+00, 23, 2328, 1) + ((9.263031e+00, -9.342216e+00, 8.887105e+00), (5.734531e-01, -5.017666e-01, 6.475970e-01), 9.798082e-02, 7.611330e-05, 1.000000e+00, 23, 2328, 1) + ((9.334809e+00, -9.405021e+00, 8.968164e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.640240e-05, 1.000000e+00, 23, 2328, 1) + ((9.335117e+00, -9.448857e+00, 8.932084e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.651925e-05, 1.000000e+00, 22, 2328, 3) + ((9.336345e+00, -9.623801e+00, 8.788098e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.698556e-05, 1.000000e+00, 21, 2328, 2) + ((9.339070e+00, -1.001201e+01, 8.468584e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.802034e-05, 1.000000e+00, 22, 2328, 3) + ((9.340298e+00, -1.018696e+01, 8.324598e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.848665e-05, 1.000000e+00, 23, 2328, 1) + ((9.343193e+00, -1.059945e+01, 7.985097e+00), (1.798796e-01, 3.522536e-02, -9.830577e-01), 1.283272e-01, 7.958616e-05, 1.000000e+00, 23, 2328, 1) + ((9.397753e+00, -1.058877e+01, 7.686922e+00), (6.459563e-01, 7.279465e-03, -7.633397e-01), 1.319449e-01, 8.019832e-05, 1.000000e+00, 23, 2328, 1) + ((9.462343e+00, -1.058804e+01, 7.610595e+00), (-5.748716e-01, 5.760301e-01, -5.811299e-01), 8.880732e-02, 8.039733e-05, 1.000000e+00, 23, 2328, 1) + ((9.287877e+00, -1.041322e+01, 7.434230e+00), (-4.932135e-03, 1.668926e-01, 9.859627e-01), 3.503028e-02, 8.113361e-05, 1.000000e+00, 23, 2328, 1) + ((9.286930e+00, -1.038117e+01, 7.623600e+00), (-9.325544e-02, -9.933000e-01, -6.825369e-02), 3.173764e-02, 8.187553e-05, 1.000000e+00, 23, 2328, 1) + ((9.283901e+00, -1.041342e+01, 7.621384e+00), (-4.235208e-01, -5.129112e-01, 7.466942e-01), 4.258127e-02, 8.200731e-05, 1.000000e+00, 23, 2328, 1) + ((9.264517e+00, -1.043690e+01, 7.655560e+00), (-7.165846e-01, 3.926265e-01, 5.764988e-01), 4.485063e-02, 8.216767e-05, 1.000000e+00, 23, 2328, 1) + ((9.256348e+00, -1.043242e+01, 7.662132e+00), (1.703748e-01, -9.175599e-01, -3.592441e-01), 3.521226e-02, 8.220659e-05, 1.000000e+00, 23, 2328, 1) + ((9.284015e+00, -1.058143e+01, 7.603793e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.283227e-05, 1.000000e+00, 23, 2328, 1) + ((9.309126e+00, -1.063244e+01, 7.631745e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.309804e-05, 1.000000e+00, 23, 2313, 1) + ((9.317824e+00, -1.065011e+01, 7.641427e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.319011e-05, 1.000000e+00, 23, 2313, 1) + ((9.459378e+00, -1.063244e+01, 7.505770e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.403060e-05, 1.000000e+00, 23, 2328, 1) + ((9.492454e+00, -1.062831e+01, 7.474071e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.422700e-05, 1.000000e+00, 23, 2328, 1) + ((9.492472e+00, -1.063244e+01, 7.472688e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.424159e-05, 1.000000e+00, 23, 2313, 1) + ((9.492761e+00, -1.069927e+01, 7.450302e+00), (9.457151e-01, -1.928731e-01, 2.615777e-01), 4.542312e-02, 8.447773e-05, 1.000000e+00, 23, 2313, 1) + ((9.890524e+00, -1.078039e+01, 7.560320e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.590450e-05, 1.000000e+00, 23, 2313, 1) + ((1.004645e+01, -1.080498e+01, 7.439717e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.651090e-05, 0.000000e+00, 23, 2313, 1)] From ce035884ac28e7c450d9ee2d1e182d2794d73508 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 2 Jun 2022 15:48:53 -0500 Subject: [PATCH 0362/2654] Add test for heating by nuclide --- tests/unit_tests/test_heating_by_nuclide.py | 57 +++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/unit_tests/test_heating_by_nuclide.py diff --git a/tests/unit_tests/test_heating_by_nuclide.py b/tests/unit_tests/test_heating_by_nuclide.py new file mode 100644 index 000000000..b34d7dd94 --- /dev/null +++ b/tests/unit_tests/test_heating_by_nuclide.py @@ -0,0 +1,57 @@ +import openmc +import pytest + +from tests.testing_harness import config + + +@pytest.fixture +def model(): + # Create simple sphere model + model = openmc.Model() + mat = openmc.Material() + mat.add_nuclide('U235', 1.0) + mat.add_nuclide('H1', 1.0) + mat.set_density('g/cm3', 5.0) + sph = openmc.Sphere(r=10.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sph) + model.geometry = openmc.Geometry([cell]) + model.settings.particles = 1000 + model.settings.inactive = 0 + model.settings.batches = 5 + model.settings.photon_transport = True + + # Add two tallies, one with heating by nuclide and one with total heating + particle_filter = openmc.ParticleFilter(['neutron', 'photon']) + heating_by_nuclide = openmc.Tally() + heating_by_nuclide.filters = [particle_filter] + heating_by_nuclide.nuclides = ['U235', 'H1'] + heating_by_nuclide.scores = ['heating'] + + heating_total = openmc.Tally() + heating_total.filters = [particle_filter] + heating_total.scores = ['heating'] + model.tallies.extend([heating_by_nuclide, heating_total]) + + return model + + +def test_heating_by_nuclide(model, run_in_tmpdir): + # If running in MPI mode, setup proper keyword arguments for run() + kwargs = {'openmc_exec': config['exe']} + if config['mpi']: + kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']] + sp_path = model.run(**kwargs) + + # Get tallies from resulting statepoint + with openmc.StatePoint(sp_path) as sp: + heating_by_nuclide = sp.tallies[model.tallies[0].id] + heating_total = sp.tallies[model.tallies[1].id] + + for particle in heating_by_nuclide.filters[0].bins: + # Get slice of each tally corresponding to a single particle + kwargs = {'filters': [openmc.ParticleFilter], 'filter_bins': [(particle,)]} + particle_slice_by_nuclide = heating_by_nuclide.get_values(**kwargs) + particle_slice_total = heating_total.get_values(**kwargs) + + # Summing over nuclides should equal total + assert particle_slice_by_nuclide.sum() == pytest.approx(particle_slice_total.sum()) From daf7bc4955d5d52dd426dd6caa88e324dc37eb82 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 2 Jun 2022 14:48:16 -0500 Subject: [PATCH 0363/2654] Break up photon heating by nuclide --- src/tallies/tally_scoring.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index c9930ee39..7decf58a4 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -963,18 +963,23 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, score = score_neutron_heating( p, tally, flux, HEATING, i_nuclide, atom_density); } else { - // The energy deposited is the difference between the pre-collision and - // post-collision energy... - score = E - p.E(); + if (i_nuclide < 0 || i_nuclide == p.event_nuclide()) { + // The energy deposited is the difference between the pre-collision + // and post-collision energy... + score = E - p.E(); - // ...less the energy of any secondary particles since they will be - // transported individually later - const auto& bank = p.secondary_bank(); - for (auto it = bank.end() - p.n_bank_second(); it < bank.end(); ++it) { - score -= it->E; + // ...less the energy of any secondary particles since they will be + // transported individually later + const auto& bank = p.secondary_bank(); + for (auto it = bank.end() - p.n_bank_second(); it < bank.end(); + ++it) { + score -= it->E; + } + + score *= p.wgt_last(); + } else { + score = 0.0; } - - score *= p.wgt_last(); } break; From 12d78288037cc6dd130d389d1e909cd97c97d3f7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 2 Jun 2022 17:18:15 -0500 Subject: [PATCH 0364/2654] Update photon_production regression test result --- src/tallies/tally_scoring.cpp | 2 +- tests/regression_tests/photon_production/results_true.dat | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index 7decf58a4..68eb344af 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -963,7 +963,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, score = score_neutron_heating( p, tally, flux, HEATING, i_nuclide, atom_density); } else { - if (i_nuclide < 0 || i_nuclide == p.event_nuclide()) { + if (i_nuclide == -1 || i_nuclide == p.event_nuclide()) { // The energy deposited is the difference between the pre-collision // and post-collision energy... score = E - p.E(); diff --git a/tests/regression_tests/photon_production/results_true.dat b/tests/regression_tests/photon_production/results_true.dat index 03fb80b81..398deeed8 100644 --- a/tests/regression_tests/photon_production/results_true.dat +++ b/tests/regression_tests/photon_production/results_true.dat @@ -67,8 +67,8 @@ tally 3: 0.000000E+00 0.000000E+00 0.000000E+00 -1.764573E+05 -3.113718E+10 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -79,8 +79,8 @@ tally 3: 0.000000E+00 0.000000E+00 0.000000E+00 -7.691658E+03 -5.916160E+07 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 From 0b77cc7edc6ec1d83a45e10a4beb2ebbf0aba34b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Apr 2022 17:11:21 -0500 Subject: [PATCH 0365/2654] Allow normal instantiation of ResultsList (instead of from_hdf5) --- docs/source/usersguide/depletion.rst | 2 +- .../pincell_depletion/restart_depletion.py | 4 +-- examples/pincell_depletion/run_depletion.py | 2 +- openmc/deplete/abc.py | 2 +- openmc/deplete/results.py | 7 +++- openmc/deplete/results_list.py | 36 ++++++++++++------- tests/regression_tests/deplete/test.py | 6 ++-- tests/unit_tests/test_deplete_activation.py | 4 +-- tests/unit_tests/test_deplete_integrator.py | 5 ++- tests/unit_tests/test_deplete_restart.py | 10 +++--- tests/unit_tests/test_deplete_resultslist.py | 2 +- tests/unit_tests/test_transfer_volumes.py | 2 +- 12 files changed, 48 insertions(+), 34 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 78a12c4ca..e3f4017f2 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -53,7 +53,7 @@ The coupled transport-depletion problem is executed, and once it is done a easy retrieval of k-effective, nuclide concentrations, and reaction rates over time:: - results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") + results = openmc.deplete.ResultsList("depletion_results.h5") time, keff = results.get_keff() Note that the coupling between the transport solver and the transmutation solver diff --git a/examples/pincell_depletion/restart_depletion.py b/examples/pincell_depletion/restart_depletion.py index 72209d2ab..45bb4343d 100644 --- a/examples/pincell_depletion/restart_depletion.py +++ b/examples/pincell_depletion/restart_depletion.py @@ -12,7 +12,7 @@ with openmc.StatePoint(statepoint) as sp: geometry = sp.summary.geometry # Load previous depletion results -previous_results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") +previous_results = openmc.deplete.ResultsList("depletion_results.h5") ############################################################################### # Transport calculation settings @@ -56,7 +56,7 @@ integrator.integrate() ############################################################################### # Open results file -results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") +results = openmc.deplete.ResultsList("depletion_results.h5") # Obtain K_eff as a function of time time, keff = results.get_keff(time_units='d') diff --git a/examples/pincell_depletion/run_depletion.py b/examples/pincell_depletion/run_depletion.py index 53b0614d1..727039a29 100644 --- a/examples/pincell_depletion/run_depletion.py +++ b/examples/pincell_depletion/run_depletion.py @@ -101,7 +101,7 @@ integrator.integrate() ############################################################################### # Open results file -results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") +results = openmc.deplete.ResultsList("depletion_results.h5") # Obtain K_eff as a function of time time, keff = results.get_keff(time_units='d') diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 0d1e8ad41..7c3fc42f7 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -842,7 +842,7 @@ class Integrator(ABC): k = ufloat(res.k[0, 0], res.k[0, 1]) # Scale reaction rates by ratio of source rates - rates *= source_rate / res.source_rate[0] + rates *= source_rate / res.source_rate return bos_conc, OperatorResult(k, rates) def _get_start_data(self): diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 3916fb4d7..9ff07b049 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -69,6 +69,11 @@ class Results: self.data = None + def __repr__(self): + t = self.time[0] + dt = self.time[1] - self.time[0] + return f"" + def __getitem__(self, pos): """Retrieves an item from results. @@ -406,7 +411,7 @@ class Results: results.data = number_dset[step, :, :, :] results.k = eigenvalues_dset[step, :] results.time = time_dset[step, :] - results.source_rate = source_rate_dset[step, :] + results.source_rate = source_rate_dset[step, 0] if "depletion time" in handle: proc_time_dset = handle["/depletion time"] diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index f2f2be0ab..843e3aec6 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -29,9 +29,24 @@ def _get_time_as(seconds, units): class ResultsList(list): """A list of openmc.deplete.Results objects - It is recommended to use :meth:`from_hdf5` over - direct creation. + Parameters + ---------- + filename : str + Path to depletion result file + """ + def __init__(self, filename): + with h5py.File(str(filename), "r") as fh: + cv.check_filetype_version(fh, 'depletion results', VERSION_RESULTS[0]) + data = [] + + # Get number of results stored + n = fh["number"][...].shape[0] + + for i in range(n): + data.append(Results.from_hdf5(fh, i)) + super().__init__(data) + @classmethod def from_hdf5(cls, filename): @@ -46,17 +61,14 @@ class ResultsList(list): ------- new : ResultsList New instance of depletion results + """ - with h5py.File(str(filename), "r") as fh: - cv.check_filetype_version(fh, 'depletion results', VERSION_RESULTS[0]) - new = cls() - - # Get number of results stored - n = fh["number"][...].shape[0] - - for i in range(n): - new.append(Results.from_hdf5(fh, i)) - return new + warn( + "The from_hdf5(...) method is no longer necessary and will be removed " + "in a future version of OpenMC. Use ResultsList(...) instead.", + FutureWarning + ) + return cls(filename) def get_atoms(self, mat, nuc, nuc_units="atoms", time_units="s"): """Get number of nuclides over time from a single material diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index 4f0e738a3..91f18667e 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -77,8 +77,8 @@ def test_full(run_in_tmpdir, problem, multiproc): return # Load the reference/test results - res_test = openmc.deplete.ResultsList.from_hdf5(path_test) - res_ref = openmc.deplete.ResultsList.from_hdf5(path_reference) + res_test = openmc.deplete.ResultsList(path_test) + res_ref = openmc.deplete.ResultsList(path_reference) # Assert same mats for mat in res_ref[0].mat_to_ind: @@ -139,7 +139,7 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): """Checks openmc.Materials objects can be created from depletion results""" # Load the reference/test results path_reference = Path(__file__).with_name('test_reference.h5') - res_ref = openmc.deplete.ResultsList.from_hdf5(path_reference) + res_ref = openmc.deplete.ResultsList(path_reference) # Firstly need to export materials.xml file for the initial simulation state geometry, lower_left, upper_right = problem diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 2f02ec4b8..2c3e0c053 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -107,7 +107,7 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts integrator.integrate() # Get resulting number of atoms - results = openmc.deplete.ResultsList.from_hdf5('depletion_results.h5') + results = openmc.deplete.ResultsList('depletion_results.h5') _, atoms = results.get_atoms(w, "W186") assert atoms[0] == pytest.approx(n0) @@ -155,7 +155,7 @@ def test_decay(run_in_tmpdir): integrator.integrate() # Get resulting number of atoms - results = openmc.deplete.ResultsList.from_hdf5('depletion_results.h5') + results = openmc.deplete.ResultsList('depletion_results.h5') _, atoms = results.get_atoms(mat, "Sr89") # Ensure density goes down by a factor of 2 after each half-life diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py index a08d8738c..9c53ad7e2 100644 --- a/tests/unit_tests/test_deplete_integrator.py +++ b/tests/unit_tests/test_deplete_integrator.py @@ -103,7 +103,7 @@ def test_results_save(run_in_tmpdir): Results.save(op, x2, op_result2, t2, 0, 1) # Load the files - res = ResultsList.from_hdf5("depletion_results.h5") + res = ResultsList("depletion_results.h5") for i in range(stages): for mat_i, mat in enumerate(burn_list): @@ -176,8 +176,7 @@ def test_integrator(run_in_tmpdir, scheme): # get expected results - res = ResultsList.from_hdf5( - operator.output_dir / "depletion_results.h5") + res = ResultsList(operator.output_dir / "depletion_results.h5") t1, y1 = res.get_atoms("1", "1") t2, y2 = res.get_atoms("1", "2") diff --git a/tests/unit_tests/test_deplete_restart.py b/tests/unit_tests/test_deplete_restart.py index 82ef05ac7..2bfcfea7d 100644 --- a/tests/unit_tests/test_deplete_restart.py +++ b/tests/unit_tests/test_deplete_restart.py @@ -24,8 +24,7 @@ def test_restart_predictor_cecm(run_in_tmpdir): openmc.deplete.PredictorIntegrator(op, dt, power).integrate() # Load the files - prev_res = openmc.deplete.ResultsList.from_hdf5( - op.output_dir / "depletion_results.h5") + prev_res = openmc.deplete.ResultsList(op.output_dir / "depletion_results.h5") # Re-create depletion operator and load previous results op = dummy_operator.DummyOperator(prev_res) @@ -51,8 +50,7 @@ def test_restart_cecm_predictor(run_in_tmpdir): cecm.integrate() # Load the files - prev_res = openmc.deplete.ResultsList.from_hdf5( - op.output_dir / "depletion_results.h5") + prev_res = openmc.deplete.ResultsList(op.output_dir / "depletion_results.h5") # Re-create depletion operator and load previous results op = dummy_operator.DummyOperator(prev_res) @@ -75,7 +73,7 @@ def test_restart(run_in_tmpdir, scheme): bundle.solver(operator, [0.75], 1.0).integrate() # restart - prev_res = openmc.deplete.ResultsList.from_hdf5( + prev_res = openmc.deplete.ResultsList( operator.output_dir / "depletion_results.h5") operator = dummy_operator.DummyOperator(prev_res) @@ -84,7 +82,7 @@ def test_restart(run_in_tmpdir, scheme): # compare results - results = openmc.deplete.ResultsList.from_hdf5( + results = openmc.deplete.ResultsList( operator.output_dir / "depletion_results.h5") _t, y1 = results.get_atoms("1", "1") diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 03e7c3eb0..2554d2188 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -13,7 +13,7 @@ def res(): """Load the reference results""" filename = (Path(__file__).parents[1] / 'regression_tests' / 'deplete' / 'test_reference.h5') - return openmc.deplete.ResultsList.from_hdf5(filename) + return openmc.deplete.ResultsList(filename) def test_get_atoms(res): diff --git a/tests/unit_tests/test_transfer_volumes.py b/tests/unit_tests/test_transfer_volumes.py index e1f3c1053..50e222b95 100644 --- a/tests/unit_tests/test_transfer_volumes.py +++ b/tests/unit_tests/test_transfer_volumes.py @@ -19,7 +19,7 @@ def test_transfer_volumes(run_in_tmpdir): PredictorIntegrator(op, dt, power).integrate() # Load the files - res = openmc.deplete.ResultsList.from_hdf5(op.output_dir / "depletion_results.h5") + res = openmc.deplete.ResultsList(op.output_dir / "depletion_results.h5") # Create a dictionary of volumes to transfer res[0].volume['1'] = 1.5 From aacf3c4938f2ce04ec9b75794f4a73f6bb162442 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Apr 2022 17:18:00 -0500 Subject: [PATCH 0366/2654] Rename deplete.Results -> deplete.StepResult --- docs/source/pythonapi/deplete.rst | 2 +- openmc/deplete/abc.py | 10 +++++----- openmc/deplete/results.py | 14 +++++++------- openmc/deplete/results_list.py | 12 ++++++++---- tests/unit_tests/test_deplete_integrator.py | 6 +++--- tests/unit_tests/test_deplete_resultslist.py | 2 +- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 383268f8b..41be2d88a 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -133,8 +133,8 @@ data, such as number densities and reaction rates for each material. AtomNumber OperatorResult ReactionRates - Results ResultsList + StepResult The following class and functions are used to solve the depletion equations, with :func:`cram.CRAM48` being the default. diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 7c3fc42f7..7d6e33924 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -22,7 +22,7 @@ from uncertainties import ufloat from openmc.lib import MaterialFilter, Tally from openmc.checkvalue import check_type, check_greater_than from openmc.mpi import comm -from .results import Results +from .results import StepResult from .chain import Chain from .results_list import ResultsList from .pool import deplete @@ -889,7 +889,7 @@ class Integrator(ABC): # Remove actual EOS concentration for next step conc = conc_list.pop() - Results.save(self.operator, conc_list, res_list, [t, t + dt], + StepResult.save(self.operator, conc_list, res_list, [t, t + dt], source_rate, self._i_res + i, proc_time) t += dt @@ -901,7 +901,7 @@ class Integrator(ABC): if output and final_step: print(f"[openmc.deplete] t={t} (final operator evaluation)") res_list = [self.operator(conc, source_rate if final_step else 0.0)] - Results.save(self.operator, [conc], res_list, [t, t], + StepResult.save(self.operator, [conc], res_list, [t, t], source_rate, self._i_res + len(self), proc_time) self.operator.write_bos_data(len(self) + self._i_res) @@ -1048,13 +1048,13 @@ class SIIntegrator(Integrator): # Remove actual EOS concentration for next step conc = conc_list.pop() - Results.save(self.operator, conc_list, res_list, [t, t + dt], + StepResult.save(self.operator, conc_list, res_list, [t, t + dt], p, self._i_res + i, proc_time) t += dt # No final simulation for SIE, use last iteration results - Results.save(self.operator, [conc], [res_list[-1]], [t, t], + StepResult.save(self.operator, [conc], [res_list[-1]], [t, t], p, self._i_res + len(self), proc_time) self.operator.write_bos_data(self._i_res + len(self)) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 9ff07b049..bfd165481 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -16,10 +16,10 @@ from .reaction_rates import ReactionRates VERSION_RESULTS = (1, 1) -__all__ = ["Results"] +__all__ = ["StepResult"] -class Results: +class StepResult: """Output of a depletion run Attributes @@ -72,7 +72,7 @@ class Results: def __repr__(self): t = self.time[0] dt = self.time[1] - self.time[0] - return f"" + return f"" def __getitem__(self, pos): """Retrieves an item from results. @@ -139,7 +139,7 @@ class Results: return self.data.shape[0] def allocate(self, volume, nuc_list, burn_list, full_burn_list, stages): - """Allocates memory of Results. + """Allocate memory for depletion step data Parameters ---------- @@ -177,10 +177,10 @@ class Results: Returns ------- - Results + StepResult New results object """ - new = Results() + new = StepResult() new.volume = {lm: self.volume[lm] for lm in local_materials} new.mat_to_ind = {mat: idx for (idx, mat) in enumerate(local_materials)} @@ -485,7 +485,7 @@ class Results: stages = len(x) # Create results - results = Results() + results = StepResult() results.allocate(vol_dict, nuc_list, burn_list, full_burn_list, stages) n_mat = len(burn_list) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 843e3aec6..97170f226 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -6,7 +6,7 @@ from warnings import warn import h5py import numpy as np -from .results import Results, VERSION_RESULTS +from .results import StepResult, VERSION_RESULTS import openmc.checkvalue as cv from openmc.data.library import DataLibrary from openmc.material import Material, Materials @@ -27,7 +27,11 @@ def _get_time_as(seconds, units): class ResultsList(list): - """A list of openmc.deplete.Results objects + """Results from a depletion simulation + + The :class:`ResultsList` class acts as a list that stores the results from + each depletion step and provides extra methods for interrogating these + results. Parameters ---------- @@ -44,7 +48,7 @@ class ResultsList(list): n = fh["number"][...].shape[0] for i in range(n): - data.append(Results.from_hdf5(fh, i)) + data.append(StepResult.from_hdf5(fh, i)) super().__init__(data) @@ -59,7 +63,7 @@ class ResultsList(list): Returns ------- - new : ResultsList + ResultsList New instance of depletion results """ diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py index 9c53ad7e2..4348b8c34 100644 --- a/tests/unit_tests/test_deplete_integrator.py +++ b/tests/unit_tests/test_deplete_integrator.py @@ -16,7 +16,7 @@ import pytest from openmc.mpi import comm from openmc.deplete import ( - ReactionRates, Results, ResultsList, OperatorResult, PredictorIntegrator, + ReactionRates, StepResult, ResultsList, OperatorResult, PredictorIntegrator, CECMIntegrator, CF4Integrator, CELIIntegrator, EPCRK4Integrator, LEQIIntegrator, SICELIIntegrator, SILEQIIntegrator, cram) @@ -99,8 +99,8 @@ def test_results_save(run_in_tmpdir): for k, rates in zip(eigvl1, rate1)] op_result2 = [OperatorResult(ufloat(*k), rates) for k, rates in zip(eigvl2, rate2)] - Results.save(op, x1, op_result1, t1, 0, 0) - Results.save(op, x2, op_result2, t2, 0, 1) + StepResult.save(op, x1, op_result1, t1, 0, 0) + StepResult.save(op, x2, op_result2, t2, 0, 1) # Load the files res = ResultsList("depletion_results.h5") diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 2554d2188..2a2669920 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -87,7 +87,7 @@ def test_get_steps(unit): conversion_to_seconds = 1 for ix in range(times.size): - res = openmc.deplete.Results() + res = openmc.deplete.StepResult() res.time = times[ix:ix + 1] * conversion_to_seconds results.append(res) From 8bfb1889b972ed31ab48da6b5c88810c8ddc38c2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Apr 2022 17:20:55 -0500 Subject: [PATCH 0367/2654] Rename deplete.ResultsList -> deplete.Results --- docs/source/pythonapi/deplete.rst | 2 +- docs/source/usersguide/depletion.rst | 4 ++-- examples/pincell_depletion/restart_depletion.py | 4 ++-- examples/pincell_depletion/run_depletion.py | 2 +- openmc/deplete/abc.py | 8 ++++---- openmc/deplete/operator.py | 12 ++++++------ openmc/deplete/results_list.py | 10 +++++----- tests/regression_tests/deplete/test.py | 6 +++--- tests/unit_tests/test_deplete_activation.py | 4 ++-- tests/unit_tests/test_deplete_integrator.py | 6 +++--- tests/unit_tests/test_deplete_restart.py | 8 ++++---- tests/unit_tests/test_deplete_resultslist.py | 8 ++++---- tests/unit_tests/test_transfer_volumes.py | 4 ++-- 13 files changed, 39 insertions(+), 39 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 41be2d88a..9f7d8c447 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -133,7 +133,7 @@ data, such as number densities and reaction rates for each material. AtomNumber OperatorResult ReactionRates - ResultsList + Results StepResult The following class and functions are used to solve the depletion equations, diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index e3f4017f2..57619611f 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -49,11 +49,11 @@ one of these functions along with the timesteps and power level:: The coupled transport-depletion problem is executed, and once it is done a ``depletion_results.h5`` file is written. The results can be analyzed using the -:class:`openmc.deplete.ResultsList` class. This class has methods that allow for +:class:`openmc.deplete.Results` class. This class has methods that allow for easy retrieval of k-effective, nuclide concentrations, and reaction rates over time:: - results = openmc.deplete.ResultsList("depletion_results.h5") + results = openmc.deplete.Results("depletion_results.h5") time, keff = results.get_keff() Note that the coupling between the transport solver and the transmutation solver diff --git a/examples/pincell_depletion/restart_depletion.py b/examples/pincell_depletion/restart_depletion.py index 45bb4343d..95bbb9954 100644 --- a/examples/pincell_depletion/restart_depletion.py +++ b/examples/pincell_depletion/restart_depletion.py @@ -12,7 +12,7 @@ with openmc.StatePoint(statepoint) as sp: geometry = sp.summary.geometry # Load previous depletion results -previous_results = openmc.deplete.ResultsList("depletion_results.h5") +previous_results = openmc.deplete.Results("depletion_results.h5") ############################################################################### # Transport calculation settings @@ -56,7 +56,7 @@ integrator.integrate() ############################################################################### # Open results file -results = openmc.deplete.ResultsList("depletion_results.h5") +results = openmc.deplete.Results("depletion_results.h5") # Obtain K_eff as a function of time time, keff = results.get_keff(time_units='d') diff --git a/examples/pincell_depletion/run_depletion.py b/examples/pincell_depletion/run_depletion.py index 727039a29..ae069334e 100644 --- a/examples/pincell_depletion/run_depletion.py +++ b/examples/pincell_depletion/run_depletion.py @@ -101,7 +101,7 @@ integrator.integrate() ############################################################################### # Open results file -results = openmc.deplete.ResultsList("depletion_results.h5") +results = openmc.deplete.Results("depletion_results.h5") # Obtain K_eff as a function of time time, keff = results.get_keff(time_units='d') diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 7d6e33924..9ba70af37 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -24,7 +24,7 @@ from openmc.checkvalue import check_type, check_greater_than from openmc.mpi import comm from .results import StepResult from .chain import Chain -from .results_list import ResultsList +from .results_list import Results from .pool import deplete @@ -79,7 +79,7 @@ class TransportOperator(ABC): in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. Defaults to 1.0e3. - prev_results : ResultsList, optional + prev_results : Results, optional Results from a previous depletion calculation. Attributes @@ -88,7 +88,7 @@ class TransportOperator(ABC): Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. - prev_res : ResultsList or None + prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. """ @@ -102,7 +102,7 @@ class TransportOperator(ABC): if prev_results is None: self.prev_res = None else: - check_type("previous results", prev_results, ResultsList) + check_type("previous results", prev_results, Results) self.prev_res = prev_results @property diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 1f31a22b6..da9588b87 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -25,7 +25,7 @@ from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .chain import _find_chain_file from .reaction_rates import ReactionRates -from .results_list import ResultsList +from .results_list import Results from .helpers import ( DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper, FissionYieldCutoffHelper, AveragedFissionYieldHelper, EnergyScoreHelper, @@ -94,7 +94,7 @@ class Operator(TransportOperator): Path to the depletion chain XML file. Defaults to the file listed under ``depletion_chain`` in :envvar:`OPENMC_CROSS_SECTIONS` environment variable. - prev_results : ResultsList, optional + prev_results : Results, optional Results from a previous depletion calculation. If this argument is specified, the depletion calculation will start from the latest state in the previous results. @@ -192,7 +192,7 @@ class Operator(TransportOperator): Initial heavy metal inventory [g] local_mats : list of str All burnable material IDs being managed by a single process - prev_res : ResultsList or None + prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. cleanup_when_done : bool @@ -284,7 +284,7 @@ class Operator(TransportOperator): if comm.size == 1: self.prev_res = prev_results else: - self.prev_res = ResultsList() + self.prev_res = Results() mat_indexes = _distribute(range(len(self.burnable_mats))) for res_obj in prev_results: new_res = res_obj.distribute(self.local_mats, mat_indexes) @@ -494,7 +494,7 @@ class Operator(TransportOperator): Volumes for the above materials in [cm^3] nuclides : list of str Nuclides to be used in the simulation. - prev_res : ResultsList, optional + prev_res : Results, optional Results from a previous depletion calculation """ @@ -543,7 +543,7 @@ class Operator(TransportOperator): ---------- mat : openmc.Material The material to read from - prev_res : ResultsList + prev_res : Results Results from a previous depletion calculation """ diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 97170f226..fb45792f6 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -12,7 +12,7 @@ from openmc.data.library import DataLibrary from openmc.material import Material, Materials from openmc.exceptions import DataError, InvalidArgumentError -__all__ = ["ResultsList"] +__all__ = ["Results"] def _get_time_as(seconds, units): @@ -26,10 +26,10 @@ def _get_time_as(seconds, units): return seconds -class ResultsList(list): +class Results(list): """Results from a depletion simulation - The :class:`ResultsList` class acts as a list that stores the results from + The :class:`Results` class acts as a list that stores the results from each depletion step and provides extra methods for interrogating these results. @@ -63,13 +63,13 @@ class ResultsList(list): Returns ------- - ResultsList + Results New instance of depletion results """ warn( "The from_hdf5(...) method is no longer necessary and will be removed " - "in a future version of OpenMC. Use ResultsList(...) instead.", + "in a future version of OpenMC. Use Results(...) instead.", FutureWarning ) return cls(filename) diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index 91f18667e..6c431fb33 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -77,8 +77,8 @@ def test_full(run_in_tmpdir, problem, multiproc): return # Load the reference/test results - res_test = openmc.deplete.ResultsList(path_test) - res_ref = openmc.deplete.ResultsList(path_reference) + res_test = openmc.deplete.Results(path_test) + res_ref = openmc.deplete.Results(path_reference) # Assert same mats for mat in res_ref[0].mat_to_ind: @@ -139,7 +139,7 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): """Checks openmc.Materials objects can be created from depletion results""" # Load the reference/test results path_reference = Path(__file__).with_name('test_reference.h5') - res_ref = openmc.deplete.ResultsList(path_reference) + res_ref = openmc.deplete.Results(path_reference) # Firstly need to export materials.xml file for the initial simulation state geometry, lower_left, upper_right = problem diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 2c3e0c053..0b82a5fbc 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -107,7 +107,7 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts integrator.integrate() # Get resulting number of atoms - results = openmc.deplete.ResultsList('depletion_results.h5') + results = openmc.deplete.Results('depletion_results.h5') _, atoms = results.get_atoms(w, "W186") assert atoms[0] == pytest.approx(n0) @@ -155,7 +155,7 @@ def test_decay(run_in_tmpdir): integrator.integrate() # Get resulting number of atoms - results = openmc.deplete.ResultsList('depletion_results.h5') + results = openmc.deplete.Results('depletion_results.h5') _, atoms = results.get_atoms(mat, "Sr89") # Ensure density goes down by a factor of 2 after each half-life diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py index 4348b8c34..cb6374152 100644 --- a/tests/unit_tests/test_deplete_integrator.py +++ b/tests/unit_tests/test_deplete_integrator.py @@ -16,7 +16,7 @@ import pytest from openmc.mpi import comm from openmc.deplete import ( - ReactionRates, StepResult, ResultsList, OperatorResult, PredictorIntegrator, + ReactionRates, StepResult, Results, OperatorResult, PredictorIntegrator, CECMIntegrator, CF4Integrator, CELIIntegrator, EPCRK4Integrator, LEQIIntegrator, SICELIIntegrator, SILEQIIntegrator, cram) @@ -103,7 +103,7 @@ def test_results_save(run_in_tmpdir): StepResult.save(op, x2, op_result2, t2, 0, 1) # Load the files - res = ResultsList("depletion_results.h5") + res = Results("depletion_results.h5") for i in range(stages): for mat_i, mat in enumerate(burn_list): @@ -176,7 +176,7 @@ def test_integrator(run_in_tmpdir, scheme): # get expected results - res = ResultsList(operator.output_dir / "depletion_results.h5") + res = Results(operator.output_dir / "depletion_results.h5") t1, y1 = res.get_atoms("1", "1") t2, y2 = res.get_atoms("1", "2") diff --git a/tests/unit_tests/test_deplete_restart.py b/tests/unit_tests/test_deplete_restart.py index 2bfcfea7d..e8bfc062a 100644 --- a/tests/unit_tests/test_deplete_restart.py +++ b/tests/unit_tests/test_deplete_restart.py @@ -24,7 +24,7 @@ def test_restart_predictor_cecm(run_in_tmpdir): openmc.deplete.PredictorIntegrator(op, dt, power).integrate() # Load the files - prev_res = openmc.deplete.ResultsList(op.output_dir / "depletion_results.h5") + prev_res = openmc.deplete.Results(op.output_dir / "depletion_results.h5") # Re-create depletion operator and load previous results op = dummy_operator.DummyOperator(prev_res) @@ -50,7 +50,7 @@ def test_restart_cecm_predictor(run_in_tmpdir): cecm.integrate() # Load the files - prev_res = openmc.deplete.ResultsList(op.output_dir / "depletion_results.h5") + prev_res = openmc.deplete.Results(op.output_dir / "depletion_results.h5") # Re-create depletion operator and load previous results op = dummy_operator.DummyOperator(prev_res) @@ -73,7 +73,7 @@ def test_restart(run_in_tmpdir, scheme): bundle.solver(operator, [0.75], 1.0).integrate() # restart - prev_res = openmc.deplete.ResultsList( + prev_res = openmc.deplete.Results( operator.output_dir / "depletion_results.h5") operator = dummy_operator.DummyOperator(prev_res) @@ -82,7 +82,7 @@ def test_restart(run_in_tmpdir, scheme): # compare results - results = openmc.deplete.ResultsList( + results = openmc.deplete.Results( operator.output_dir / "depletion_results.h5") _t, y1 = results.get_atoms("1", "1") diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 2a2669920..6ce15601f 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -1,4 +1,4 @@ -"""Tests the ResultsList class""" +"""Tests the Results class""" from pathlib import Path from math import inf @@ -13,7 +13,7 @@ def res(): """Load the reference results""" filename = (Path(__file__).parents[1] / 'regression_tests' / 'deplete' / 'test_reference.h5') - return openmc.deplete.ResultsList(filename) + return openmc.deplete.Results(filename) def test_get_atoms(res): @@ -72,9 +72,9 @@ def test_get_keff(res): @pytest.mark.parametrize("unit", ("s", "d", "min", "h")) def test_get_steps(unit): - # Make a ResultsList full of near-empty Result instances + # Make a Results full of near-empty Result instances # Just fill out a time schedule - results = openmc.deplete.ResultsList() + results = openmc.deplete.Results() # Time in units of unit times = np.linspace(0, 100, num=5) if unit == "d": diff --git a/tests/unit_tests/test_transfer_volumes.py b/tests/unit_tests/test_transfer_volumes.py index 50e222b95..b768bc88a 100644 --- a/tests/unit_tests/test_transfer_volumes.py +++ b/tests/unit_tests/test_transfer_volumes.py @@ -2,7 +2,7 @@ from pytest import approx import openmc -from openmc.deplete import PredictorIntegrator, ResultsList +from openmc.deplete import PredictorIntegrator, Results from tests import dummy_operator @@ -19,7 +19,7 @@ def test_transfer_volumes(run_in_tmpdir): PredictorIntegrator(op, dt, power).integrate() # Load the files - res = openmc.deplete.ResultsList(op.output_dir / "depletion_results.h5") + res = openmc.deplete.Results(op.output_dir / "depletion_results.h5") # Create a dictionary of volumes to transfer res[0].volume['1'] = 1.5 From bd7b33c636628cd4826dd4507fc01a9fc628896d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Apr 2022 17:23:37 -0500 Subject: [PATCH 0368/2654] Rename results.py stepresult.py --- openmc/deplete/__init__.py | 2 +- openmc/deplete/abc.py | 2 +- openmc/deplete/results_list.py | 2 +- openmc/deplete/{results.py => stepresult.py} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename openmc/deplete/{results.py => stepresult.py} (100%) diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py index b8c1cdfff..e15a368de 100644 --- a/openmc/deplete/__init__.py +++ b/openmc/deplete/__init__.py @@ -10,7 +10,7 @@ from .chain import * from .operator import * from .reaction_rates import * from .atom_number import * -from .results import * +from .stepresult import * from .results_list import * from .integrators import * from . import abc diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 9ba70af37..3d8d08c76 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -22,7 +22,7 @@ from uncertainties import ufloat from openmc.lib import MaterialFilter, Tally from openmc.checkvalue import check_type, check_greater_than from openmc.mpi import comm -from .results import StepResult +from .stepresult import StepResult from .chain import Chain from .results_list import Results from .pool import deplete diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index fb45792f6..952fb37f7 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -6,7 +6,7 @@ from warnings import warn import h5py import numpy as np -from .results import StepResult, VERSION_RESULTS +from .stepresult import StepResult, VERSION_RESULTS import openmc.checkvalue as cv from openmc.data.library import DataLibrary from openmc.material import Material, Materials diff --git a/openmc/deplete/results.py b/openmc/deplete/stepresult.py similarity index 100% rename from openmc/deplete/results.py rename to openmc/deplete/stepresult.py From 5421bf0b1f0a3186aa033be915d5d120c5b084cf Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Apr 2022 17:25:10 -0500 Subject: [PATCH 0369/2654] Rename results_list.py -> results.py --- openmc/deplete/__init__.py | 2 +- openmc/deplete/abc.py | 2 +- openmc/deplete/operator.py | 2 +- openmc/deplete/{results_list.py => results.py} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename openmc/deplete/{results_list.py => results.py} (100%) diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py index e15a368de..5891555a2 100644 --- a/openmc/deplete/__init__.py +++ b/openmc/deplete/__init__.py @@ -11,7 +11,7 @@ from .operator import * from .reaction_rates import * from .atom_number import * from .stepresult import * -from .results_list import * +from .results import * from .integrators import * from . import abc from . import cram diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 3d8d08c76..df30579e5 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -24,7 +24,7 @@ from openmc.checkvalue import check_type, check_greater_than from openmc.mpi import comm from .stepresult import StepResult from .chain import Chain -from .results_list import Results +from .results import Results from .pool import deplete diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index da9588b87..327c762e0 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -25,7 +25,7 @@ from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .chain import _find_chain_file from .reaction_rates import ReactionRates -from .results_list import Results +from .results import Results from .helpers import ( DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper, FissionYieldCutoffHelper, AveragedFissionYieldHelper, EnergyScoreHelper, diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results.py similarity index 100% rename from openmc/deplete/results_list.py rename to openmc/deplete/results.py From 8a4fd95b9bea56d83a9ded8467cb2da41be66605 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 2 May 2022 12:27:28 -0500 Subject: [PATCH 0370/2654] Retain ResultsList name for backwards compatibility --- openmc/deplete/results.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 952fb37f7..fd6d72fba 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -10,9 +10,9 @@ from .stepresult import StepResult, VERSION_RESULTS import openmc.checkvalue as cv from openmc.data.library import DataLibrary from openmc.material import Material, Materials -from openmc.exceptions import DataError, InvalidArgumentError +from openmc.exceptions import DataError -__all__ = ["Results"] +__all__ = ["Results", "ResultsList"] def _get_time_as(seconds, units): @@ -68,8 +68,8 @@ class Results(list): """ warn( - "The from_hdf5(...) method is no longer necessary and will be removed " - "in a future version of OpenMC. Use Results(...) instead.", + "The ResultsList.from_hdf5(...) method is no longer necessary and will " + "be removed in a future version of OpenMC. Use Results(...) instead.", FutureWarning ) return cls(filename) @@ -410,3 +410,7 @@ class Results(list): mat.add_nuclide(nuc, atoms_per_barn_cm) return mat_file + + +# Retain deprecated name for the time being +ResultsList = Results From 355ecd374751c5d773d5d97278c7d88e6cabf5f4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 5 May 2022 22:05:33 -0500 Subject: [PATCH 0371/2654] Allow deplete.Results() to be instantiated empty --- openmc/deplete/results.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index fd6d72fba..514c04820 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -39,16 +39,17 @@ class Results(list): Path to depletion result file """ - def __init__(self, filename): - with h5py.File(str(filename), "r") as fh: - cv.check_filetype_version(fh, 'depletion results', VERSION_RESULTS[0]) - data = [] + def __init__(self, filename=None): + data = [] + if filename is not None: + with h5py.File(str(filename), "r") as fh: + cv.check_filetype_version(fh, 'depletion results', VERSION_RESULTS[0]) - # Get number of results stored - n = fh["number"][...].shape[0] + # Get number of results stored + n = fh["number"][...].shape[0] - for i in range(n): - data.append(StepResult.from_hdf5(fh, i)) + for i in range(n): + data.append(StepResult.from_hdf5(fh, i)) super().__init__(data) From bc1ab31746518ab420f01695ab91da4390134cd4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 3 Jun 2022 09:09:52 -0500 Subject: [PATCH 0372/2654] Raise exception if timestep in [MWd/kg] is given with zero power --- openmc/deplete/abc.py | 3 +++ openmc/deplete/stepresult.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index df30579e5..457c51a8a 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -719,6 +719,9 @@ class Integrator(ABC): elif unit.lower() == 'mwd/kg': watt_days_per_kg = 1e6*timestep kilograms = 1e-3*operator.heavy_metal + if rate == 0.0: + raise ValueError("Cannot specify a timestep in [MWd/kg] when" + " the power is zero.") days = watt_days_per_kg * kilograms / rate seconds.append(days*_SECONDS_PER_DAY) else: diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index bfd165481..6f30e934d 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -20,7 +20,7 @@ __all__ = ["StepResult"] class StepResult: - """Output of a depletion run + """Result of a single depletion timestep Attributes ---------- From 7484618c7c93d3bb75fe6decc0104e3201129ad6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 5 Apr 2022 13:01:03 -0500 Subject: [PATCH 0373/2654] Adding sample methods to univariate distribution classes --- openmc/stats/univariate.py | 123 +++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index e4a9b8f92..ea8c9f943 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -60,6 +60,10 @@ class Univariate(EqualityMixin, ABC): elif distribution == 'mixture': return Mixture.from_xml_element(elem) + @abstractmethod + def sample(p, seed=None): + pass + class Discrete(Univariate): """Distribution characterized by a probability mass function. @@ -115,6 +119,26 @@ class Discrete(Univariate): cv.check_greater_than('discrete probability', pk, 0.0, True) self._p = p + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + + if len(self.x) == 1: + return np.full((n_samples), self.x[0]) + + out = np.zeros((n_samples,)) + for i, xi in enumerate(np.random.rand(n_samples)): + c = 0.0 + for j, prob in enumerate(self.p): + c += prob + if (xi < c): + out[i] = self.x[j] + break + return out + + def normalize(self): + norm = sum(self.p) + self.p = [val / norm for val in self.p] + def to_xml_element(self, element_name): """Return XML representation of the discrete distribution @@ -240,6 +264,10 @@ class Uniform(Univariate): t.c = [0., 1.] return t + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + return np.random.uniform(self.a, self.b, n_samples) + def to_xml_element(self, element_name): """Return XML representation of the uniform distribution @@ -341,6 +369,14 @@ class PowerLaw(Univariate): cv.check_type('power law exponent', n, Real) self._n = n + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + xi = np.random.rand(n_samples) + pwr = self.n + 1 + offset = self.a**pwr + span = self.b**pwr - offset + return np.power(offset + xi * span, (1/pwr)) + def to_xml_element(self, element_name): """Return XML representation of the power law distribution @@ -414,6 +450,16 @@ class Maxwell(Univariate): cv.check_greater_than('Maxwell temperature', theta, 0.0) self._theta = theta + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + self.sample_maxwell(self.theta, n_samples) + + @staticmethod + def sample_maxwell(t, n_samples): + r1, r2, r3 = np.random.rand(3, n_samples) + c = np.power(np.cos(0.5 * np.pi * r3), 2) + return t * (np.log(r1) + np.log(r2) * c) + def to_xml_element(self, element_name): """Return XML representation of the Maxwellian distribution @@ -502,6 +548,13 @@ class Watt(Univariate): cv.check_greater_than('Watt b', b, 0.0) self._b = b + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + w = Maxwell.sample_maxwell(self.a, n_samples) + u = np.random.uniform(-1., 1., n_samples) + aab = self.a * self.a * self.b + return w + 0.25*aab + u * np.sqrt(aab*w) + def to_xml_element(self, element_name): """Return XML representation of the Watt distribution @@ -588,6 +641,10 @@ class Normal(Univariate): cv.check_greater_than('Normal std_dev', std_dev, 0.0) self._std_dev = std_dev + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + return np.random.normal(self.mean_value, self.std_dev, n_samples) + def to_xml_element(self, element_name): """Return XML representation of the Normal distribution @@ -694,6 +751,12 @@ class Muir(Univariate): cv.check_greater_than('Muir kt', kt, 0.0) self._kt = kt + def sample(self, n_samples=1, seed=None): + # https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS + np.random.seed(seed) + sigma = np.sqrt(4.*self.e0*self.kt/self.m_rat) + return np.random.normal(self.e0, sigma, n_samples) + def to_xml_element(self, element_name): """Return XML representation of the Watt distribution @@ -803,6 +866,63 @@ class Tabular(Univariate): cv.check_value('interpolation', interpolation, _INTERPOLATION_SCHEMES) self._interpolation = interpolation + def cdf(self): + if self.interpolation not in ('histogram', 'linear-linear'): + raise NotImplementedError('Can only generate CDFs for tabular ' + 'distributions using histogram or ' + 'linear-linear interpolation') + c = np.zeros_like((len(self.x),)) + if self.interpolation == 'histogram': + c[1:] = self.p * np.diff(self.x) + elif self.interpolation == 'linear-linear': + c[1:] = 0.5 * np.diff(self.p) * np.diff(self.x) + return np.cumsum(c) + + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + xi = np.random.rand(n_samples) + cdf = self.cdf() + + # get CDF bins that are above the + # sampled values + c_i = np.full(n_samples, cdf[0]) + cdf_idx = np.zeros_like(n_samples) + for i, val in enumerate(cdf): + mask = xi > val + c_i[mask] = val + cdf_idx[mask] = i + + # get table values at each index where + # the random number is less than the next cdf + # entry + x_i = np.array([self.x[i] for i in cdf_idx]) + p_i = np.array([self.p[i] for i in cdf_idx]) + + if self.interpolation == 'histogram': + # mask where probability + pos_mask = p_i > 0.0 + p_i[pos_mask] = x_i[pos_mask] + (xi[pos_mask] - c_i[pos_mask]) \ + / p_i[pos_mask] + neg_mask = not pos_mask + p_i[neg_mask] = x_i[neg_mask] + return p_i + elif self.interpolation == 'linear-linear': + # get variable and probability values for the + # next entry + x_i1 = np.array([self.x[i+1] for i in cdf_idx]) + p_i1 = np.array([self.p[i+1] for i in cdf_idx]) + # compute slope between entries + m = (p_i1 - p_i) / (x_i1 - x_i) + # set values for zero slope + zero = m == 0.0 + m[zero] = x_i[zero] + (xi[zero] - c_i[zero]) / p_i[zero] + # set values for non-zero slope + non_zero = not zero + quad = np.pow(p_i[non_zero]**2) + 2. * m[non_zero] * (xi[non_zero] - c_i[non_zero]) + quad[quad < 0.0] = 0.0 + m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i) / m[non_zero] + return m + def to_xml_element(self, element_name): """Return XML representation of the tabular distribution @@ -890,6 +1010,9 @@ class Legendre(Univariate): def coefficients(self, coefficients): self._coefficients = np.asarray(coefficients) + def sample(self, n_samples=1, seed=None): + raise NotImplementedError + def to_xml_element(self, element_name): raise NotImplementedError From e856c6a27065eb9b2b64dd480f1200020937e276 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 5 Apr 2022 13:24:18 -0500 Subject: [PATCH 0374/2654] Correction to maxwell dist sampling --- openmc/stats/univariate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index ea8c9f943..72a5568aa 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -452,13 +452,13 @@ class Maxwell(Univariate): def sample(self, n_samples=1, seed=None): np.random.seed(seed) - self.sample_maxwell(self.theta, n_samples) + return self.sample_maxwell(self.theta, n_samples) @staticmethod def sample_maxwell(t, n_samples): r1, r2, r3 = np.random.rand(3, n_samples) c = np.power(np.cos(0.5 * np.pi * r3), 2) - return t * (np.log(r1) + np.log(r2) * c) + return -t * (np.log(r1) + np.log(r2) * c) def to_xml_element(self, element_name): """Return XML representation of the Maxwellian distribution From 136ff45cc56a4a552eea93b35aeaf792e9fad0e7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 5 Apr 2022 13:52:50 -0500 Subject: [PATCH 0375/2654] Adding docstrings. Corrections to Tabular sampling --- openmc/stats/univariate.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 72a5568aa..3d99f8b8c 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -61,7 +61,21 @@ class Univariate(EqualityMixin, ABC): return Mixture.from_xml_element(elem) @abstractmethod - def sample(p, seed=None): + def sample(n_samples=1, seed=None): + """Sample the univariate distribution + + Parameters + ---------- + n_samples : int + Number of sampled values to generate + seed : int or None + Initial random number seed. + + Returns + ------- + numpy.ndarray + A 1-D array of sampled values + """ pass @@ -867,15 +881,17 @@ class Tabular(Univariate): self._interpolation = interpolation def cdf(self): - if self.interpolation not in ('histogram', 'linear-linear'): + if not self.interpolation in ('histogram', 'linear-linear'): raise NotImplementedError('Can only generate CDFs for tabular ' 'distributions using histogram or ' 'linear-linear interpolation') - c = np.zeros_like((len(self.x),)) + c = np.zeros_like(self.x) + x = np.asarray(self.x) + p = np.asarray(self.p) if self.interpolation == 'histogram': - c[1:] = self.p * np.diff(self.x) + c[1:] = p * np.diff(x) elif self.interpolation == 'linear-linear': - c[1:] = 0.5 * np.diff(self.p) * np.diff(self.x) + c[1:] = 0.5 * (p[0:-1] + p[1:]) * np.diff(x) return np.cumsum(c) def sample(self, n_samples=1, seed=None): @@ -886,7 +902,7 @@ class Tabular(Univariate): # get CDF bins that are above the # sampled values c_i = np.full(n_samples, cdf[0]) - cdf_idx = np.zeros_like(n_samples) + cdf_idx = np.zeros((n_samples,), dtype=int) for i, val in enumerate(cdf): mask = xi > val c_i[mask] = val @@ -903,7 +919,7 @@ class Tabular(Univariate): pos_mask = p_i > 0.0 p_i[pos_mask] = x_i[pos_mask] + (xi[pos_mask] - c_i[pos_mask]) \ / p_i[pos_mask] - neg_mask = not pos_mask + neg_mask = np.invert(pos_mask) p_i[neg_mask] = x_i[neg_mask] return p_i elif self.interpolation == 'linear-linear': @@ -917,8 +933,8 @@ class Tabular(Univariate): zero = m == 0.0 m[zero] = x_i[zero] + (xi[zero] - c_i[zero]) / p_i[zero] # set values for non-zero slope - non_zero = not zero - quad = np.pow(p_i[non_zero]**2) + 2. * m[non_zero] * (xi[non_zero] - c_i[non_zero]) + non_zero = np.invert(zero) + quad = np.power(p_i[non_zero], 2) + 2. * m[non_zero] * (xi[non_zero] - c_i[non_zero]) quad[quad < 0.0] = 0.0 m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i) / m[non_zero] return m From 17be0257a0ec05994ff6d2a2fea8edcd15b5dfc7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 5 Apr 2022 14:05:35 -0500 Subject: [PATCH 0376/2654] Correction to histogram cdf method --- openmc/stats/univariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 3d99f8b8c..7fc479e63 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -889,7 +889,7 @@ class Tabular(Univariate): x = np.asarray(self.x) p = np.asarray(self.p) if self.interpolation == 'histogram': - c[1:] = p * np.diff(x) + c[1:] = p[:-1] * np.diff(x) elif self.interpolation == 'linear-linear': c[1:] = 0.5 * (p[0:-1] + p[1:]) * np.diff(x) return np.cumsum(c) From 8070ccaf52abb93eca2e3ee99784284d5b730a26 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 5 Apr 2022 15:32:38 -0500 Subject: [PATCH 0377/2654] Adding sampling for Mixture. Improving performance of Discrete sampling --- openmc/stats/univariate.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 7fc479e63..0e6b4ae61 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -133,20 +133,19 @@ class Discrete(Univariate): cv.check_greater_than('discrete probability', pk, 0.0, True) self._p = p + def cdf(self): + return np.insert(np.cumsum(self.p), 0, 0.0) + def sample(self, n_samples=1, seed=None): np.random.seed(seed) if len(self.x) == 1: return np.full((n_samples), self.x[0]) - out = np.zeros((n_samples,)) - for i, xi in enumerate(np.random.rand(n_samples)): - c = 0.0 - for j, prob in enumerate(self.p): - c += prob - if (xi < c): - out[i] = self.x[j] - break + xi = np.random.rand(n_samples) + out = np.zeros_like(xi) + for i, c in enumerate(self.cdf()[:-1]): + out[xi >= c] = self.x[i] return out def normalize(self): @@ -1086,6 +1085,27 @@ class Mixture(Univariate): Iterable, Univariate) self._distribution = distribution + def cdf(self): + return np.insert(np.cumsum(self.probability), 0, 0.0) + + def sample(self, n_samples=1, seed=None): + np.random.seed(seed) + xi = np.random.rand(n_samples) + idx = np.zeros_like(xi, dtype=int) + for i, c in enumerate(self.cdf()[:-1]): + idx[xi >= c] = i + + out = np.zeros_like(xi) + for i in np.unique(idx): + n_dist_samples = np.count_nonzero(idx == i) + samples = self.distribution[i].sample(n_dist_samples) + out[idx == i] = samples + return out + + def normalize(self): + norm = sum(self.probability) + self.probability = [val / norm for val in self.probability] + def to_xml_element(self, element_name): """Return XML representation of the mixture distribution From 2f22474aea252d2bdff2fecd5ef7e17aa31bba8f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 6 Apr 2022 10:32:39 -0500 Subject: [PATCH 0378/2654] Adding simple test for normal distribution --- tests/unit_tests/test_stats.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 51a561bd3..7bf67c1fa 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -65,6 +65,7 @@ def test_uniform(): assert t.p == [1/(b-a), 1/(b-a)] assert t.interpolation == 'histogram' + def test_powerlaw(): a, b, n = 10.0, 20.0, 2.0 d = openmc.stats.PowerLaw(a, b, n) @@ -76,6 +77,7 @@ def test_powerlaw(): assert d.n == n assert len(d) == 3 + def test_maxwell(): theta = 1.2895e6 d = openmc.stats.Maxwell(theta) @@ -264,6 +266,18 @@ def test_normal(): assert d.std_dev == pytest.approx(std_dev) assert len(d) == 2 + # sample normal distribution + n_samples = 10000 + samples = d.sample(n_samples, seed=100) + samples = np.abs(samples - mean) + within_1_sigma = np.count_nonzero(samples < std_dev) + assert within_1_sigma / n_samples >= 0.68 + within_2_sigma = np.count_nonzero(samples < 2*std_dev) + assert within_2_sigma / n_samples >= 0.95 + within_3_sigma = np.count_nonzero(samples < 3*std_dev) + assert within_3_sigma / n_samples >= 0.99 + + def test_muir(): mean = 10.0 mass = 5.0 From 2c74dcf336f135a11649391616bb9741aa139ee3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 6 Apr 2022 10:35:46 -0500 Subject: [PATCH 0379/2654] Adding similar test for Muir distribution --- openmc/stats/univariate.py | 7 +++++-- tests/unit_tests/test_stats.py | 11 +++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 0e6b4ae61..4f2fbf66c 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -764,11 +764,14 @@ class Muir(Univariate): cv.check_greater_than('Muir kt', kt, 0.0) self._kt = kt + @property + def std_dev(self): + return np.sqrt(4.*self.e0*self.kt/self.m_rat) + def sample(self, n_samples=1, seed=None): # https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS np.random.seed(seed) - sigma = np.sqrt(4.*self.e0*self.kt/self.m_rat) - return np.random.normal(self.e0, sigma, n_samples) + return np.random.normal(self.e0, self.std_dev, n_samples) def to_xml_element(self, element_name): """Return XML representation of the Watt distribution diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 7bf67c1fa..532936e42 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -292,3 +292,14 @@ def test_muir(): assert d.m_rat == pytest.approx(mass) assert d.kt == pytest.approx(temp) assert len(d) == 3 + + # sample normal distribution + n_samples = 10000 + samples = d.sample(n_samples, seed=100) + samples = np.abs(samples - mean) + within_1_sigma = np.count_nonzero(samples < d.std_dev) + assert within_1_sigma / n_samples >= 0.68 + within_2_sigma = np.count_nonzero(samples < 2*d.std_dev) + assert within_2_sigma / n_samples >= 0.95 + within_3_sigma = np.count_nonzero(samples < 3*d.std_dev) + assert within_3_sigma / n_samples >= 0.99 From 12b8a0802f7579ca1da24a7d2a0ba6bebdad6b3f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 2 Jun 2022 23:42:06 -0500 Subject: [PATCH 0380/2654] Updating masks and adding some comments for clarity --- openmc/stats/univariate.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 4f2fbf66c..120dc62b6 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -897,6 +897,10 @@ class Tabular(Univariate): return np.cumsum(c) def sample(self, n_samples=1, seed=None): + if not self.interpolation in ('histogram', 'linear-linear'): + raise NotImplementedError('Can only sample tabular distributions ' + 'using histogram or ' + 'linear-linear interpolation') np.random.seed(seed) xi = np.random.rand(n_samples) cdf = self.cdf() @@ -905,7 +909,7 @@ class Tabular(Univariate): # sampled values c_i = np.full(n_samples, cdf[0]) cdf_idx = np.zeros((n_samples,), dtype=int) - for i, val in enumerate(cdf): + for i, val in enumerate(cdf[:-1]): mask = xi > val c_i[mask] = val cdf_idx[mask] = i @@ -916,13 +920,17 @@ class Tabular(Univariate): x_i = np.array([self.x[i] for i in cdf_idx]) p_i = np.array([self.p[i] for i in cdf_idx]) + # TODO: check that probability doesn't exceed the last value + if self.interpolation == 'histogram': - # mask where probability + # mask where probability is greater than zero pos_mask = p_i > 0.0 + # probabilities greater than zero are set proportional to the + # position of the random numebers in relation to the cdf value p_i[pos_mask] = x_i[pos_mask] + (xi[pos_mask] - c_i[pos_mask]) \ / p_i[pos_mask] - neg_mask = np.invert(pos_mask) - p_i[neg_mask] = x_i[neg_mask] + # probabilities smaller than zero are set to the random number value + p_i[~pos_mask] = x_i[~pos_mask] return p_i elif self.interpolation == 'linear-linear': # get variable and probability values for the @@ -935,10 +943,10 @@ class Tabular(Univariate): zero = m == 0.0 m[zero] = x_i[zero] + (xi[zero] - c_i[zero]) / p_i[zero] # set values for non-zero slope - non_zero = np.invert(zero) + non_zero = ~zero quad = np.power(p_i[non_zero], 2) + 2. * m[non_zero] * (xi[non_zero] - c_i[non_zero]) quad[quad < 0.0] = 0.0 - m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i) / m[non_zero] + m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i[non_zero]) / m[non_zero] return m def to_xml_element(self, element_name): From 94c91cc6593fa6f61816e06b169dd6c82995bb19 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 2 Jun 2022 23:42:24 -0500 Subject: [PATCH 0381/2654] Adding more mean value tests for sampling distributions --- tests/unit_tests/test_stats.py | 84 +++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 532936e42..a3b5cfafb 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -253,6 +253,88 @@ def test_point(): d = openmc.stats.Point.from_xml_element(elem) assert d.xyz == pytest.approx(p) + +def test_discrete(): + + vals = np.array([1.0, 2.0, 3.0]) + probs = np.array([0.1, 0.7, 0.2]) + + exp_mean = (vals * probs).sum() + + d = openmc.stats.Discrete(vals, probs) + + # sample discrete distribution + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + # check that the mean of the samples is close to the true mean + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + + +def test_uniform(): + + lower = 1.1 + upper = 23.3 + + exp_mean = 0.5 * (lower + upper) + + d = openmc.stats.Uniform(lower, upper) + + # sample the uniform distribution + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + + +def test_power_law(): + + lower = 0.0 + upper = 1.0 + exponent = 2.0 + + d = openmc.stats.PowerLaw(lower, upper, exponent) + + exp_mean = (exponent + 1) / (exponent + 2) + + # sample power law distribution + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + + +def test_maxwell(): + theta = 1000 + + exp_mean = 0 + + d = openmc.stats.Maxwell(theta) + + exp_mean = 3/2 * theta + + # sample maxwell distribution + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + +def test_watt(): + + a = 10 + b = 20 + + d = openmc.stats.Watt(a, b) + + # mean value form adapted from + # "Prompt-fission-neutron average energy for 238U(n, f ) from + # threshold to 200 MeV" Ethvignot et. al. + # https://doi.org/10.1016/j.physletb.2003.09.048 + exp_mean = 3/2 * a + a**2 * b / 4 + + # sample Watt distribution + n_samples = 100_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + + + def test_normal(): mean = 10.0 std_dev = 2.0 @@ -293,7 +375,7 @@ def test_muir(): assert d.kt == pytest.approx(temp) assert len(d) == 3 - # sample normal distribution + # sample muir distribution n_samples = 10000 samples = d.sample(n_samples, seed=100) samples = np.abs(samples - mean) From e0d82e48782fc02cdf84481dbf91f775427607fe Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jun 2022 06:37:07 -0500 Subject: [PATCH 0382/2654] Use utf-8 encoding when reading dose coefficient files (thanks Fabricio Gatti) --- openmc/data/effective_dose/dose.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/data/effective_dose/dose.py b/openmc/data/effective_dose/dose.py index 6ceb2c09e..eb8fe9f35 100644 --- a/openmc/data/effective_dose/dose.py +++ b/openmc/data/effective_dose/dose.py @@ -23,7 +23,7 @@ def _load_dose_icrp116(): """Load effective dose tables from text files""" for particle, filename in _FILES: path = Path(__file__).parent / filename - data = np.loadtxt(path, skiprows=3) + data = np.loadtxt(path, skiprows=3, encoding='utf-8') data[:, 0] *= 1e6 # Change energies to eV _DOSE_ICRP116[particle] = data From e030b748360c833f63fe38a760f89b3ce03e396e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 8 Jun 2022 17:28:33 +0100 Subject: [PATCH 0383/2654] add get_activity --- openmc/data/data.py | 3565 +++++++++++++++++++++++++++++++++++++++++++ openmc/material.py | 16 + 2 files changed, 3581 insertions(+) diff --git a/openmc/data/data.py b/openmc/data/data.py index a1d0ee1dc..48a98dedd 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -177,6 +177,3571 @@ ATOMIC_SYMBOL = {0: 'n', 1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 118: 'Og'} ATOMIC_NUMBER = {value: key for key, value in ATOMIC_SYMBOL.items()} +# Half life values are from ENDF/B VII.1 and have units of seconds +HALF_LIFE = { + "H3": 388789600.0, + "H4": 9.90652e-23, + "H5": 7.99473e-23, + "H6": 2.84812e-22, + "H7": 2.3e-23, + "He5": 7.595e-22, + "He6": 0.8067, + "He7": 3.038e-21, + "He8": 0.1191, + "He9": 7e-21, + "He10": 1.519e-21, + "Li4": 7.55721e-23, + "Li5": 3.06868e-22, + "Li8": 0.838, + "Li9": 0.1783, + "Li10": 2e-21, + "Li11": 0.00859, + "Li12": 1e-08, + "Be5": 1e-09, + "Be6": 4.95326e-21, + "Be8": 8.18132e-17, + "Be10": 47652000000000.0, + "Be11": 13.81, + "Be12": 0.0213, + "Be13": 2.7e-21, + "Be14": 0.00435, + "Be15": 2e-07, + "Be16": 2e-07, + "B6": 1e-09, + "B7": 3.255e-22, + "B8": 0.77, + "B9": 8.43888e-19, + "B12": 0.0202, + "B13": 0.01736, + "B14": 0.0125, + "B15": 0.00993, + "B16": 1.9e-10, + "B17": 0.00508, + "B18": 2.6e-08, + "B19": 0.00292, + "C8": 1.9813e-21, + "C9": 0.1265, + "C10": 19.29, + "C11": 1223.1, + "C14": 179878000000.0, + "C15": 2.449, + "C16": 0.747, + "C17": 0.193, + "C18": 0.092, + "C19": 0.049, + "C20": 0.0145, + "C21": 3e-08, + "C22": 0.0062, + "N10": 2e-22, + "N11": 3.12742e-22, + "N12": 0.011, + "N13": 597.9, + "N16": 7.13, + "N17": 4.171, + "N18": 0.624, + "N19": 0.271, + "N20": 0.13, + "N21": 0.085, + "N22": 0.024, + "N23": 0.0145, + "N24": 5.2e-08, + "N25": 2.6e-07, + "O12": 1.13925e-21, + "O13": 0.00858, + "O14": 70.606, + "O15": 122.24, + "O19": 26.88, + "O20": 13.51, + "O21": 3.42, + "O22": 2.25, + "O23": 0.0905, + "O24": 0.065, + "O25": 5e-08, + "O26": 4e-08, + "O27": 2.6e-07, + "O28": 1e-07, + "F14": 5.0007e-22, + "F15": 4.557e-22, + "F16": 1.13925e-20, + "F17": 64.49, + "F18": 6586.2, + "F20": 11.163, + "F21": 4.158, + "F22": 4.23, + "F23": 2.23, + "F24": 0.39, + "F25": 0.05, + "F26": 0.0096, + "F27": 0.005, + "F28": 4e-08, + "F29": 0.0025, + "F30": 2.6e-07, + "F31": 2.5e-07, + "Ne16": 3.73524e-21, + "Ne17": 0.1092, + "Ne18": 1.672, + "Ne19": 17.22, + "Ne23": 37.24, + "Ne24": 202.8, + "Ne25": 0.602, + "Ne26": 0.197, + "Ne27": 0.032, + "Ne28": 0.0189, + "Ne29": 0.0148, + "Ne30": 0.0073, + "Ne31": 0.0034, + "Ne32": 0.0035, + "Ne33": 1.8e-07, + "Ne34": 6e-08, + "Na18": 1.3e-21, + "Na19": 4e-08, + "Na20": 0.4479, + "Na21": 22.49, + "Na22": 82134970.0, + "Na24": 53989.2, + "Na24_m1": 0.02018, + "Na25": 59.1, + "Na26": 1.077, + "Na27": 0.301, + "Na28": 0.0305, + "Na29": 0.0449, + "Na30": 0.048, + "Na31": 0.017, + "Na32": 0.0132, + "Na33": 0.008, + "Na34": 0.0055, + "Na35": 0.0015, + "Na36": 1.8e-07, + "Na37": 6e-08, + "Mg19": 4e-12, + "Mg20": 0.0908, + "Mg21": 0.122, + "Mg22": 3.8755, + "Mg23": 11.317, + "Mg27": 567.48, + "Mg28": 75294.0, + "Mg29": 1.3, + "Mg30": 0.335, + "Mg31": 0.232, + "Mg32": 0.086, + "Mg33": 0.0905, + "Mg34": 0.02, + "Mg35": 0.07, + "Mg36": 0.0039, + "Mg37": 2.6e-07, + "Mg38": 2.6e-07, + "Mg39": 1.8e-07, + "Mg40": 1.7e-07, + "Al21": 3.5e-08, + "Al22": 0.059, + "Al23": 0.47, + "Al24": 2.053, + "Al24_m1": 0.13, + "Al25": 7.183, + "Al26": 22626800000000.0, + "Al26_m1": 6.3452, + "Al28": 134.484, + "Al29": 393.6, + "Al30": 3.62, + "Al31": 0.644, + "Al32": 0.033, + "Al33": 0.0417, + "Al34": 0.042, + "Al35": 0.0386, + "Al36": 0.09, + "Al37": 0.0107, + "Al38": 0.0076, + "Al39": 7.6e-06, + "Al40": 2.6e-07, + "Al41": 2.6e-07, + "Al42": 1.7e-07, + "Si22": 0.029, + "Si23": 0.0423, + "Si24": 0.14, + "Si25": 0.22, + "Si26": 2.234, + "Si27": 4.16, + "Si31": 9438.0, + "Si32": 4828310000.0, + "Si33": 6.11, + "Si34": 2.77, + "Si35": 0.78, + "Si36": 0.45, + "Si37": 0.09, + "Si38": 1e-06, + "Si39": 0.0475, + "Si40": 0.033, + "Si41": 0.02, + "Si42": 0.0125, + "Si43": 6e-08, + "Si44": 3.6e-07, + "P24": 0.0074, + "P25": 3e-08, + "P26": 0.0437, + "P27": 0.26, + "P28": 0.2703, + "P29": 4.142, + "P30": 149.88, + "P32": 1232323.0, + "P33": 2189376.0, + "P34": 12.43, + "P35": 47.3, + "P36": 5.6, + "P37": 2.31, + "P38": 0.64, + "P39": 0.28, + "P40": 0.125, + "P41": 0.1, + "P42": 0.0485, + "P43": 0.0365, + "P44": 0.0185, + "P45": 2e-07, + "P46": 2e-07, + "S26": 0.01, + "S27": 0.0155, + "S28": 0.125, + "S29": 0.187, + "S30": 1.178, + "S31": 2.572, + "S35": 7560864.0, + "S37": 303.0, + "S38": 10218.0, + "S39": 11.5, + "S40": 8.8, + "S41": 1.99, + "S42": 1.013, + "S43": 0.28, + "S44": 0.1, + "S45": 0.068, + "S46": 0.05, + "S48": 2e-07, + "S49": 2e-07, + "Cl28": 0.0017, + "Cl29": 2e-08, + "Cl30": 3e-08, + "Cl31": 0.15, + "Cl32": 0.298, + "Cl33": 2.511, + "Cl34": 1.5264, + "Cl34_m1": 1920.0, + "Cl36": 9498840000000.0, + "Cl38": 2233.8, + "Cl38_m1": 0.715, + "Cl39": 3336.0, + "Cl40": 81.0, + "Cl41": 38.4, + "Cl42": 6.8, + "Cl43": 3.13, + "Cl44": 0.56, + "Cl45": 0.413, + "Cl46": 0.232, + "Cl47": 0.101, + "Cl48": 2e-07, + "Cl49": 1.7e-07, + "Cl50": 0.02, + "Cl51": 2e-07, + "Ar30": 2e-08, + "Ar31": 0.0151, + "Ar32": 0.098, + "Ar33": 0.173, + "Ar34": 0.8445, + "Ar35": 1.775, + "Ar37": 3027456.0, + "Ar39": 8488990000.0, + "Ar41": 6576.6, + "Ar42": 1038250000.0, + "Ar43": 322.2, + "Ar44": 712.2, + "Ar45": 21.48, + "Ar46": 8.4, + "Ar47": 1.23, + "Ar48": 0.475, + "Ar49": 0.17, + "Ar50": 0.085, + "Ar51": 2e-07, + "Ar52": 0.01, + "Ar53": 0.003, + "K32": 0.0033, + "K33": 2.5e-08, + "K34": 2.5e-08, + "K35": 0.178, + "K36": 0.342, + "K37": 1.226, + "K38": 458.16, + "K38_m1": 0.924, + "K40": 3.93839e16, + "K42": 44496.0, + "K43": 80280.0, + "K44": 1327.8, + "K45": 1068.6, + "K46": 105.0, + "K47": 17.5, + "K48": 6.8, + "K49": 1.26, + "K50": 0.472, + "K51": 0.365, + "K52": 0.105, + "K53": 0.03, + "K54": 0.01, + "K55": 0.003, + "Ca34": 3.5e-08, + "Ca35": 0.0257, + "Ca36": 0.102, + "Ca37": 0.1811, + "Ca38": 0.44, + "Ca39": 0.8596, + "Ca41": 3218880000000.0, + "Ca45": 14049500.0, + "Ca47": 391910.4, + "Ca48": 7.25824e26, + "Ca49": 523.08, + "Ca50": 13.9, + "Ca51": 10.0, + "Ca52": 4.6, + "Ca53": 0.09, + "Ca54": 0.086, + "Ca55": 0.022, + "Ca56": 0.01, + "Ca57": 0.005, + "Sc36": 0.0088, + "Sc37": 0.056, + "Sc38": 0.0423, + "Sc39": 3e-07, + "Sc40": 0.1823, + "Sc41": 0.5963, + "Sc42": 0.6808, + "Sc42_m1": 62.0, + "Sc43": 14007.6, + "Sc44": 14292.0, + "Sc44_m1": 210996.0, + "Sc45_m1": 0.318, + "Sc46": 7239456.0, + "Sc46_m1": 18.75, + "Sc47": 289370.9, + "Sc48": 157212.0, + "Sc49": 3430.8, + "Sc50": 102.5, + "Sc50_m1": 0.35, + "Sc51": 12.4, + "Sc52": 8.2, + "Sc53": 3.0, + "Sc54": 0.36, + "Sc55": 0.105, + "Sc56": 0.06, + "Sc57": 0.013, + "Sc58": 0.012, + "Sc59": 0.01, + "Sc60": 0.003, + "Ti38": 1.2e-07, + "Ti39": 0.032, + "Ti40": 0.0533, + "Ti41": 0.0804, + "Ti42": 0.199, + "Ti43": 0.509, + "Ti44": 1893460000.0, + "Ti45": 11088.0, + "Ti51": 345.6, + "Ti52": 102.0, + "Ti53": 32.7, + "Ti54": 1.5, + "Ti55": 1.3, + "Ti56": 0.2, + "Ti57": 0.06, + "Ti58": 0.059, + "Ti59": 0.03, + "Ti60": 0.022, + "Ti61": 3e-07, + "Ti62": 0.01, + "Ti63": 0.003, + "V40": 0.0077, + "V41": 0.0244, + "V42": 5.5e-08, + "V43": 0.8, + "V44": 0.111, + "V44_m1": 0.15, + "V45": 0.547, + "V46": 0.4225, + "V46_m1": 0.00102, + "V47": 1956.0, + "V48": 1380110.0, + "V49": 28512000.0, + "V50": 4.41806e24, + "V52": 224.58, + "V53": 92.58, + "V54": 49.8, + "V55": 6.54, + "V56": 0.216, + "V57": 0.35, + "V58": 0.185, + "V59": 0.075, + "V60": 0.068, + "V61": 0.047, + "V62": 1.5e-07, + "V63": 0.017, + "V64": 0.019, + "V65": 0.01, + "Cr42": 0.014, + "Cr43": 0.0216, + "Cr44": 0.0535, + "Cr45": 0.0609, + "Cr46": 0.26, + "Cr47": 0.5, + "Cr48": 77616.0, + "Cr49": 2538.0, + "Cr51": 2393366.0, + "Cr55": 209.82, + "Cr56": 356.4, + "Cr57": 21.1, + "Cr58": 7.0, + "Cr59": 0.46, + "Cr60": 0.49, + "Cr61": 0.27, + "Cr62": 0.19, + "Cr63": 0.129, + "Cr64": 0.043, + "Cr65": 0.027, + "Cr66": 0.01, + "Cr67": 0.05, + "Mn44": 1.05e-07, + "Mn45": 7e-08, + "Mn46": 0.0345, + "Mn47": 0.1, + "Mn48": 0.1581, + "Mn49": 0.382, + "Mn50": 0.28319, + "Mn50_m1": 105.0, + "Mn51": 2772.0, + "Mn52": 483062.4, + "Mn52_m1": 1266.0, + "Mn53": 116763000000000.0, + "Mn54": 26961120.0, + "Mn56": 9284.04, + "Mn57": 85.4, + "Mn58": 3.0, + "Mn58_m1": 65.4, + "Mn59": 4.59, + "Mn60": 51.0, + "Mn60_m1": 1.77, + "Mn61": 0.67, + "Mn62": 0.671, + "Mn62_m1": 0.092, + "Mn63": 0.29, + "Mn64": 0.09, + "Mn65": 0.092, + "Mn66": 0.064, + "Mn67": 0.047, + "Mn68": 0.028, + "Mn69": 0.014, + "Fe45": 0.00203, + "Fe46": 0.013, + "Fe47": 0.0219, + "Fe48": 0.044, + "Fe49": 0.0647, + "Fe50": 0.155, + "Fe51": 0.305, + "Fe52": 29790.0, + "Fe52_m1": 45.9, + "Fe53": 510.6, + "Fe53_m1": 152.4, + "Fe55": 86594050.0, + "Fe59": 3844368.0, + "Fe60": 47336400000000.0, + "Fe61": 358.8, + "Fe62": 68.0, + "Fe63": 6.1, + "Fe64": 2.0, + "Fe65": 0.81, + "Fe65_m1": 1.12, + "Fe66": 0.44, + "Fe67": 0.416, + "Fe68": 0.187, + "Fe69": 0.109, + "Fe70": 0.094, + "Fe71": 0.028, + "Fe72": 1.5e-07, + "Co49": 3.5e-08, + "Co50": 0.044, + "Co51": 2e-07, + "Co52": 0.115, + "Co53": 0.24, + "Co53_m1": 0.247, + "Co54": 0.19328, + "Co54_m1": 88.8, + "Co55": 63108.0, + "Co56": 6672931.0, + "Co57": 23478340.0, + "Co58": 6122304.0, + "Co58_m1": 32760.0, + "Co60": 166344200.0, + "Co60_m1": 628.02, + "Co61": 5940.0, + "Co62": 90.0, + "Co62_m1": 834.6, + "Co63": 27.4, + "Co64": 0.3, + "Co65": 1.16, + "Co66": 0.2, + "Co67": 0.425, + "Co68": 0.199, + "Co68_m1": 1.6, + "Co69": 0.22, + "Co70": 0.119, + "Co70_m1": 0.5, + "Co71": 0.079, + "Co72": 0.0599, + "Co73": 0.041, + "Co74": 0.03, + "Co75": 0.034, + "Ni48": 0.0021, + "Ni49": 0.0075, + "Ni50": 0.012, + "Ni51": 2e-07, + "Ni52": 0.038, + "Ni53": 0.045, + "Ni54": 0.104, + "Ni55": 0.2047, + "Ni56": 524880.0, + "Ni57": 128160.0, + "Ni59": 2398380000000.0, + "Ni63": 3193630000.0, + "Ni65": 9061.884, + "Ni66": 196560.0, + "Ni67": 21.0, + "Ni68": 29.0, + "Ni69": 11.4, + "Ni69_m1": 3.5, + "Ni70": 6.0, + "Ni71": 2.56, + "Ni72": 1.57, + "Ni73": 0.84, + "Ni74": 0.68, + "Ni75": 0.6, + "Ni76": 0.238, + "Ni77": 0.061, + "Ni78": 0.11, + "Cu52": 0.0069, + "Cu53": 3e-07, + "Cu54": 7.5e-08, + "Cu55": 0.04, + "Cu56": 0.094, + "Cu57": 0.1963, + "Cu58": 3.204, + "Cu59": 81.5, + "Cu60": 1422.0, + "Cu61": 11998.8, + "Cu62": 580.38, + "Cu64": 45723.6, + "Cu66": 307.2, + "Cu67": 222588.0, + "Cu68": 31.1, + "Cu68_m1": 225.0, + "Cu69": 171.0, + "Cu70": 44.5, + "Cu70_m1": 33.0, + "Cu70_m2": 6.6, + "Cu71": 19.5, + "Cu72": 6.63, + "Cu73": 4.2, + "Cu74": 1.75, + "Cu75": 1.224, + "Cu76": 0.653, + "Cu76_m1": 1.27, + "Cu77": 0.469, + "Cu78": 0.335, + "Cu79": 0.188, + "Cu80": 0.17, + "Cu81": 0.028, + "Zn54": 0.0037, + "Zn55": 0.02, + "Zn56": 5e-07, + "Zn57": 0.038, + "Zn58": 0.084, + "Zn59": 0.182, + "Zn60": 142.8, + "Zn61": 89.1, + "Zn61_m1": 0.43, + "Zn61_m2": 0.14, + "Zn62": 33336.0, + "Zn63": 2308.2, + "Zn65": 21075550.0, + "Zn69": 3384.0, + "Zn69_m1": 49536.0, + "Zn71": 147.0, + "Zn71_m1": 14256.0, + "Zn72": 167400.0, + "Zn73": 23.5, + "Zn73_m1": 5.8, + "Zn73_m2": 0.013, + "Zn74": 95.6, + "Zn75": 10.2, + "Zn76": 5.7, + "Zn77": 2.08, + "Zn77_m1": 1.05, + "Zn78": 1.47, + "Zn79": 0.995, + "Zn80": 0.54, + "Zn81": 0.32, + "Zn82": 0.052, + "Zn83": 0.043, + "Ga56": 0.0059, + "Ga57": 0.0123, + "Ga58": 0.0152, + "Ga59": 0.0418, + "Ga60": 0.07, + "Ga61": 0.168, + "Ga62": 0.11612, + "Ga63": 32.4, + "Ga64": 157.62, + "Ga65": 912.0, + "Ga66": 34164.0, + "Ga67": 281810.9, + "Ga68": 4062.6, + "Ga70": 1268.4, + "Ga72": 50760.0, + "Ga72_m1": 0.03968, + "Ga73": 17496.0, + "Ga74": 487.2, + "Ga74_m1": 9.5, + "Ga75": 126.0, + "Ga76": 32.6, + "Ga77": 13.2, + "Ga78": 5.09, + "Ga79": 2.847, + "Ga80": 1.676, + "Ga81": 1.217, + "Ga82": 0.599, + "Ga83": 0.3081, + "Ga84": 0.085, + "Ga85": 0.048, + "Ga86": 0.029, + "Ge58": 0.0152, + "Ge59": 0.0418, + "Ge60": 0.03, + "Ge61": 0.039, + "Ge62": 1.5e-07, + "Ge63": 0.142, + "Ge64": 63.7, + "Ge65": 30.9, + "Ge66": 8136.0, + "Ge67": 1134.0, + "Ge68": 23410080.0, + "Ge69": 140580.0, + "Ge71": 987552.0, + "Ge71_m1": 0.02041, + "Ge73_m1": 0.499, + "Ge75": 4966.8, + "Ge75_m1": 47.7, + "Ge77": 40680.0, + "Ge77_m1": 52.9, + "Ge78": 5280.0, + "Ge79": 18.98, + "Ge79_m1": 39.0, + "Ge80": 29.5, + "Ge81": 7.6, + "Ge81_m1": 7.6, + "Ge82": 4.56, + "Ge83": 1.85, + "Ge84": 0.954, + "Ge85": 0.535, + "Ge86": 0.095, + "Ge87": 0.14, + "Ge88": 0.066, + "Ge89": 0.039, + "As60": 0.0083, + "As61": 0.0166, + "As62": 0.0259, + "As63": 0.0921, + "As64": 0.036, + "As65": 0.128, + "As66": 0.09579, + "As67": 42.5, + "As68": 151.6, + "As69": 913.8, + "As70": 3156.0, + "As71": 235080.0, + "As72": 93600.0, + "As73": 6937920.0, + "As74": 1535328.0, + "As75_m1": 0.01762, + "As76": 94464.0, + "As77": 139788.0, + "As78": 5442.0, + "As79": 540.6, + "As80": 15.2, + "As81": 33.3, + "As82": 19.1, + "As82_m1": 13.6, + "As83": 13.4, + "As84": 4.2, + "As85": 2.021, + "As86": 0.945, + "As87": 0.56, + "As88": 0.112, + "As89": 0.059, + "As90": 0.043, + "As91": 0.044, + "As92": 0.027, + "Se65": 0.05, + "Se66": 0.033, + "Se67": 0.136, + "Se68": 35.5, + "Se69": 27.4, + "Se70": 2466.0, + "Se71": 284.4, + "Se72": 725760.0, + "Se73": 25740.0, + "Se73_m1": 2388.0, + "Se75": 10349860.0, + "Se77_m1": 17.36, + "Se79": 9309490000000.0, + "Se79_m1": 235.2, + "Se81": 1107.0, + "Se81_m1": 3436.8, + "Se83": 1338.0, + "Se83_m1": 70.1, + "Se84": 195.6, + "Se85": 31.7, + "Se86": 14.3, + "Se87": 5.5, + "Se88": 1.53, + "Se89": 0.41, + "Se90": 0.161, + "Se91": 0.27, + "Se92": 0.093, + "Se93": 0.062, + "Se94": 0.059, + "Br67": 0.0443, + "Br68": 1.2e-06, + "Br69": 2.4e-08, + "Br70": 0.0791, + "Br70_m1": 2.2, + "Br71": 21.4, + "Br72": 78.6, + "Br72_m1": 10.6, + "Br73": 204.0, + "Br74": 1524.0, + "Br74_m1": 2760.0, + "Br75": 5802.0, + "Br76": 58320.0, + "Br76_m1": 1.31, + "Br77": 205329.6, + "Br77_m1": 256.8, + "Br78": 387.0, + "Br79_m1": 4.86, + "Br80": 1060.8, + "Br80_m1": 15913.8, + "Br82": 127015.2, + "Br82_m1": 367.8, + "Br83": 8640.0, + "Br84": 1905.6, + "Br84_m1": 360.0, + "Br85": 174.0, + "Br86": 55.0, + "Br87": 55.65, + "Br88": 16.29, + "Br89": 4.4, + "Br90": 1.92, + "Br91": 0.541, + "Br92": 0.343, + "Br93": 0.102, + "Br94": 0.07, + "Br95": 0.066, + "Br96": 0.042, + "Br97": 0.04, + "Kr69": 0.032, + "Kr70": 0.052, + "Kr71": 0.1, + "Kr72": 17.1, + "Kr73": 27.3, + "Kr74": 690.0, + "Kr75": 257.4, + "Kr76": 53280.0, + "Kr77": 4464.0, + "Kr79": 126144.0, + "Kr79_m1": 50.0, + "Kr81": 7226690000000.0, + "Kr81_m1": 13.1, + "Kr83_m1": 6588.0, + "Kr85": 339433500.0, + "Kr85_m1": 16128.0, + "Kr87": 4578.0, + "Kr88": 10224.0, + "Kr89": 189.0, + "Kr90": 32.32, + "Kr91": 8.57, + "Kr92": 1.84, + "Kr93": 1.286, + "Kr94": 0.212, + "Kr95": 0.114, + "Kr96": 0.08, + "Kr97": 0.063, + "Kr98": 0.046, + "Kr99": 0.027, + "Kr100": 0.007, + "Rb71": 1e-09, + "Rb72": 1.2e-06, + "Rb73": 3e-08, + "Rb74": 0.064776, + "Rb75": 19.0, + "Rb76": 36.5, + "Rb77": 226.2, + "Rb78": 1059.6, + "Rb78_m1": 344.4, + "Rb79": 1374.0, + "Rb80": 34.0, + "Rb81": 16459.2, + "Rb81_m1": 1830.0, + "Rb82": 75.45, + "Rb82_m1": 23299.2, + "Rb83": 7447680.0, + "Rb84": 2835648.0, + "Rb84_m1": 1215.6, + "Rb86": 1609718.0, + "Rb86_m1": 61.02, + "Rb87": 1.51792e18, + "Rb88": 1066.38, + "Rb89": 909.0, + "Rb90": 158.0, + "Rb90_m1": 258.0, + "Rb91": 58.4, + "Rb92": 4.492, + "Rb93": 5.84, + "Rb94": 2.702, + "Rb95": 0.3777, + "Rb96": 0.203, + "Rb97": 0.1691, + "Rb98": 0.114, + "Rb98_m1": 0.096, + "Rb99": 0.054, + "Rb100": 0.051, + "Rb101": 0.032, + "Rb102": 0.037, + "Sr73": 0.025, + "Sr74": 1.2e-06, + "Sr75": 0.088, + "Sr76": 7.89, + "Sr77": 9.0, + "Sr78": 150.0, + "Sr79": 135.0, + "Sr80": 6378.0, + "Sr81": 1338.0, + "Sr82": 2190240.0, + "Sr83": 116676.0, + "Sr83_m1": 4.95, + "Sr85": 5602176.0, + "Sr85_m1": 4057.8, + "Sr87_m1": 10134.0, + "Sr89": 4365792.0, + "Sr90": 908543300.0, + "Sr91": 34668.0, + "Sr92": 9756.0, + "Sr93": 445.38, + "Sr94": 75.3, + "Sr95": 23.9, + "Sr96": 1.07, + "Sr97": 0.429, + "Sr98": 0.653, + "Sr99": 0.27, + "Sr100": 0.202, + "Sr101": 0.118, + "Sr102": 0.069, + "Sr103": 0.068, + "Sr104": 0.043, + "Sr105": 0.0556, + "Y76": 2e-07, + "Y77": 0.062, + "Y78": 0.05, + "Y78_m1": 5.7, + "Y79": 14.8, + "Y80": 30.1, + "Y80_m1": 4.8, + "Y81": 70.4, + "Y82": 8.3, + "Y83": 424.8, + "Y83_m1": 171.0, + "Y84": 2370.0, + "Y84_m1": 4.6, + "Y85": 9648.0, + "Y85_m1": 17496.0, + "Y86": 53064.0, + "Y86_m1": 2880.0, + "Y87": 287280.0, + "Y87_m1": 48132.0, + "Y88": 9212486.0, + "Y88_m1": 0.000301, + "Y88_m2": 0.01397, + "Y89_m1": 15.663, + "Y90": 230400.0, + "Y90_m1": 11484.0, + "Y91": 5055264.0, + "Y91_m1": 2982.6, + "Y92": 12744.0, + "Y93": 36648.0, + "Y93_m1": 0.82, + "Y94": 1122.0, + "Y95": 618.0, + "Y96": 5.34, + "Y96_m1": 9.6, + "Y97": 3.75, + "Y97_m1": 1.17, + "Y97_m2": 0.142, + "Y98": 0.548, + "Y98_m1": 2.0, + "Y99": 1.47, + "Y100": 0.735, + "Y100_m1": 0.94, + "Y101": 0.45, + "Y102": 0.36, + "Y102_m1": 0.298, + "Y103": 0.23, + "Y104": 0.18, + "Y105": 0.088, + "Y106": 0.066, + "Y107": 0.03, + "Y108": 0.048, + "Zr78": 2e-07, + "Zr79": 0.056, + "Zr80": 4.6, + "Zr81": 5.5, + "Zr82": 32.0, + "Zr83": 41.6, + "Zr84": 1554.0, + "Zr85": 471.6, + "Zr85_m1": 10.9, + "Zr86": 59400.0, + "Zr87": 6048.0, + "Zr87_m1": 14.0, + "Zr88": 7205760.0, + "Zr89": 282276.0, + "Zr89_m1": 249.66, + "Zr90_m1": 0.8092, + "Zr93": 48283100000000.0, + "Zr95": 5532365.0, + "Zr96": 6.31152e26, + "Zr97": 60296.4, + "Zr98": 30.7, + "Zr99": 2.1, + "Zr100": 7.1, + "Zr101": 2.3, + "Zr102": 2.9, + "Zr103": 1.3, + "Zr104": 1.2, + "Zr105": 0.6, + "Zr106": 0.27, + "Zr107": 0.15, + "Zr108": 0.08, + "Zr109": 0.117, + "Zr110": 0.098, + "Nb81": 0.8, + "Nb82": 0.05, + "Nb83": 4.1, + "Nb84": 9.8, + "Nb85": 20.9, + "Nb85_m1": 3.3, + "Nb86": 88.0, + "Nb87": 225.0, + "Nb87_m1": 156.0, + "Nb88": 873.0, + "Nb88_m1": 466.8, + "Nb89": 7308.0, + "Nb89_m1": 3960.0, + "Nb90": 52560.0, + "Nb90_m1": 18.81, + "Nb90_m2": 0.00619, + "Nb91": 21459200000.0, + "Nb91_m1": 5258304.0, + "Nb92": 1095050000000000.0, + "Nb92_m1": 876960.0, + "Nb93_m1": 509024100.0, + "Nb94": 640619000000.0, + "Nb94_m1": 375.78, + "Nb95": 3023222.0, + "Nb95_m1": 311904.0, + "Nb96": 84060.0, + "Nb97": 4326.0, + "Nb97_m1": 58.7, + "Nb98": 2.86, + "Nb98_m1": 3078.0, + "Nb99": 15.0, + "Nb99_m1": 150.0, + "Nb100": 1.5, + "Nb100_m1": 2.99, + "Nb101": 7.1, + "Nb102": 4.3, + "Nb102_m1": 1.3, + "Nb103": 1.5, + "Nb104": 4.9, + "Nb104_m1": 0.94, + "Nb105": 2.95, + "Nb106": 0.93, + "Nb107": 0.3, + "Nb108": 0.193, + "Nb109": 0.19, + "Nb110": 0.17, + "Nb111": 0.08, + "Nb112": 0.069, + "Nb113": 0.03, + "Mo83": 0.0195, + "Mo84": 3.8, + "Mo85": 3.2, + "Mo86": 19.6, + "Mo87": 14.02, + "Mo88": 480.0, + "Mo89": 126.6, + "Mo89_m1": 0.19, + "Mo90": 20412.0, + "Mo91": 929.4, + "Mo91_m1": 64.6, + "Mo93": 126230000000.0, + "Mo93_m1": 24660.0, + "Mo99": 237513.6, + "Mo100": 2.3037e26, + "Mo101": 876.6, + "Mo102": 678.0, + "Mo103": 67.5, + "Mo104": 60.0, + "Mo105": 35.6, + "Mo106": 8.73, + "Mo107": 3.5, + "Mo108": 1.09, + "Mo109": 0.53, + "Mo110": 0.3, + "Mo111": 0.2, + "Mo112": 0.287, + "Mo113": 0.1, + "Mo114": 0.08, + "Mo115": 0.092, + "Tc85": 0.5, + "Tc86": 0.054, + "Tc86_m1": 1.1e-06, + "Tc87": 2.2, + "Tc88": 5.8, + "Tc88_m1": 6.4, + "Tc89": 12.8, + "Tc89_m1": 12.9, + "Tc90": 8.7, + "Tc90_m1": 49.2, + "Tc91": 188.4, + "Tc91_m1": 198.0, + "Tc92": 255.0, + "Tc93": 9900.0, + "Tc93_m1": 2610.0, + "Tc94": 17580.0, + "Tc94_m1": 3120.0, + "Tc95": 72000.0, + "Tc95_m1": 5270400.0, + "Tc96": 369792.0, + "Tc96_m1": 3090.0, + "Tc97": 132857000000000.0, + "Tc97_m1": 7862400.0, + "Tc98": 132542000000000.0, + "Tc99": 6661810000000.0, + "Tc99_m1": 21624.12, + "Tc100": 15.46, + "Tc101": 852.0, + "Tc102": 5.28, + "Tc102_m1": 261.0, + "Tc103": 54.2, + "Tc104": 1098.0, + "Tc105": 456.0, + "Tc106": 35.6, + "Tc107": 21.2, + "Tc108": 5.17, + "Tc109": 0.86, + "Tc110": 0.92, + "Tc111": 0.29, + "Tc112": 0.28, + "Tc113": 0.16, + "Tc114": 0.15, + "Tc115": 0.073, + "Tc116": 0.09, + "Tc117": 0.04, + "Tc118": 0.066, + "Ru87": 1.5e-06, + "Ru88": 1.25, + "Ru89": 1.5, + "Ru90": 11.7, + "Ru91": 7.9, + "Ru91_m1": 7.6, + "Ru92": 219.0, + "Ru93": 59.7, + "Ru93_m1": 10.8, + "Ru94": 3108.0, + "Ru95": 5914.8, + "Ru97": 244512.0, + "Ru103": 3390941.0, + "Ru103_m1": 0.00169, + "Ru105": 15984.0, + "Ru106": 32123520.0, + "Ru107": 225.0, + "Ru108": 273.0, + "Ru109": 34.5, + "Ru110": 11.6, + "Ru111": 2.12, + "Ru112": 1.75, + "Ru113": 0.8, + "Ru113_m1": 0.51, + "Ru114": 0.52, + "Ru115": 0.74, + "Ru116": 0.204, + "Ru117": 0.142, + "Ru118": 0.123, + "Ru119": 0.162, + "Ru120": 0.149, + "Rh89": 1.5e-06, + "Rh90": 0.0145, + "Rh90_m1": 1.05, + "Rh91": 1.47, + "Rh92": 4.66, + "Rh93": 11.9, + "Rh94": 70.6, + "Rh94_m1": 25.8, + "Rh95": 301.2, + "Rh95_m1": 117.6, + "Rh96": 594.0, + "Rh96_m1": 90.6, + "Rh97": 1842.0, + "Rh97_m1": 2772.0, + "Rh98": 523.2, + "Rh98_m1": 216.0, + "Rh99": 1391040.0, + "Rh99_m1": 16920.0, + "Rh100": 74880.0, + "Rh100_m1": 276.0, + "Rh101": 104140100.0, + "Rh101_m1": 374976.0, + "Rh102": 17910720.0, + "Rh102_m1": 118088500.0, + "Rh103_m1": 3366.84, + "Rh104": 42.3, + "Rh104_m1": 260.4, + "Rh105": 127296.0, + "Rh105_m1": 40.0, + "Rh106": 30.07, + "Rh106_m1": 7860.0, + "Rh107": 1302.0, + "Rh108": 16.8, + "Rh108_m1": 360.0, + "Rh109": 80.0, + "Rh110": 3.2, + "Rh110_m1": 28.5, + "Rh111": 11.0, + "Rh112": 2.1, + "Rh112_m1": 6.73, + "Rh113": 2.8, + "Rh114": 1.85, + "Rh115": 0.99, + "Rh116": 0.68, + "Rh116_m1": 0.57, + "Rh117": 0.44, + "Rh118": 0.266, + "Rh119": 0.171, + "Rh120": 0.136, + "Rh121": 0.151, + "Rh122": 0.108, + "Rh123": 0.0489, + "Pd91": 1e-06, + "Pd92": 0.8, + "Pd93": 1.3, + "Pd94": 9.0, + "Pd95": 10.0, + "Pd95_m1": 13.3, + "Pd96": 122.0, + "Pd97": 186.0, + "Pd98": 1062.0, + "Pd99": 1284.0, + "Pd100": 313632.0, + "Pd101": 30492.0, + "Pd103": 1468022.0, + "Pd107": 205124000000000.0, + "Pd107_m1": 21.3, + "Pd109": 49324.32, + "Pd109_m1": 281.4, + "Pd111": 1404.0, + "Pd111_m1": 19800.0, + "Pd112": 75708.0, + "Pd113": 93.0, + "Pd113_m1": 0.3, + "Pd114": 145.2, + "Pd115": 25.0, + "Pd115_m1": 50.0, + "Pd116": 11.8, + "Pd117": 4.3, + "Pd117_m1": 0.0191, + "Pd118": 1.9, + "Pd119": 0.92, + "Pd120": 0.5, + "Pd121": 0.285, + "Pd122": 0.175, + "Pd123": 0.244, + "Pd124": 0.038, + "Pd125": 0.3987, + "Pd126": 0.2499, + "Ag93": 1.5e-06, + "Ag94": 0.035, + "Ag94_m1": 0.55, + "Ag94_m2": 0.4, + "Ag95": 2.0, + "Ag95_m1": 0.5, + "Ag95_m2": 0.016, + "Ag95_m3": 0.04, + "Ag96": 4.4, + "Ag96_m1": 6.9, + "Ag97": 25.5, + "Ag98": 47.5, + "Ag99": 124.0, + "Ag99_m1": 10.5, + "Ag100": 120.6, + "Ag100_m1": 134.4, + "Ag101": 666.0, + "Ag101_m1": 3.1, + "Ag102": 774.0, + "Ag102_m1": 462.0, + "Ag103": 3942.0, + "Ag103_m1": 5.7, + "Ag104": 4152.0, + "Ag104_m1": 2010.0, + "Ag105": 3567456.0, + "Ag105_m1": 433.8, + "Ag106": 1437.6, + "Ag106_m1": 715392.0, + "Ag107_m1": 44.3, + "Ag108": 142.92, + "Ag108_m1": 13822200000.0, + "Ag109_m1": 39.6, + "Ag110": 24.6, + "Ag110_m1": 21579260.0, + "Ag111": 643680.0, + "Ag111_m1": 64.8, + "Ag112": 11268.0, + "Ag113": 19332.0, + "Ag113_m1": 68.7, + "Ag114": 4.6, + "Ag114_m1": 0.0015, + "Ag115": 1200.0, + "Ag115_m1": 18.0, + "Ag116": 237.0, + "Ag116_m1": 20.0, + "Ag116_m2": 9.3, + "Ag117": 72.8, + "Ag117_m1": 5.34, + "Ag118": 3.76, + "Ag118_m1": 2.0, + "Ag119": 2.1, + "Ag119_m1": 6.0, + "Ag120": 1.23, + "Ag120_m1": 0.32, + "Ag121": 0.78, + "Ag122": 0.529, + "Ag122_m1": 0.2, + "Ag123": 0.3, + "Ag124": 0.172, + "Ag125": 0.166, + "Ag126": 0.107, + "Ag127": 0.109, + "Ag128": 0.058, + "Ag129": 0.046, + "Ag130": 0.05, + "Cd95": 0.005, + "Cd96": 1.0, + "Cd97": 2.8, + "Cd98": 9.2, + "Cd99": 16.0, + "Cd100": 49.1, + "Cd101": 81.6, + "Cd102": 330.0, + "Cd103": 438.0, + "Cd104": 3462.0, + "Cd105": 3330.0, + "Cd107": 23400.0, + "Cd109": 39864960.0, + "Cd111_m1": 2912.4, + "Cd113": 2.53723e23, + "Cd113_m1": 444962200.0, + "Cd115": 192456.0, + "Cd115_m1": 3849984.0, + "Cd116": 9.78286e26, + "Cd117": 8964.0, + "Cd117_m1": 12096.0, + "Cd118": 3018.0, + "Cd119": 161.4, + "Cd119_m1": 132.0, + "Cd120": 50.8, + "Cd121": 13.5, + "Cd121_m1": 8.3, + "Cd122": 5.24, + "Cd123": 2.1, + "Cd123_m1": 1.82, + "Cd124": 1.25, + "Cd125": 0.68, + "Cd125_m1": 0.48, + "Cd126": 0.515, + "Cd127": 0.37, + "Cd128": 0.28, + "Cd129": 0.27, + "Cd130": 0.162, + "Cd131": 0.068, + "Cd132": 0.097, + "In97": 0.005, + "In98": 0.0425, + "In98_m1": 1.6, + "In99": 3.05, + "In100": 5.9, + "In101": 15.1, + "In102": 23.3, + "In103": 65.0, + "In103_m1": 34.0, + "In104": 108.0, + "In104_m1": 15.7, + "In105": 304.2, + "In105_m1": 48.0, + "In106": 372.0, + "In106_m1": 312.0, + "In107": 1944.0, + "In107_m1": 50.4, + "In108": 3480.0, + "In108_m1": 2376.0, + "In109": 15001.2, + "In109_m1": 80.4, + "In109_m2": 0.209, + "In110": 17640.0, + "In110_m1": 4146.0, + "In111": 242326.1, + "In111_m1": 462.0, + "In112": 898.2, + "In112_m1": 1233.6, + "In113_m1": 5968.56, + "In114": 71.9, + "In114_m1": 4277664.0, + "In114_m2": 0.0431, + "In115": 1.39169e22, + "In115_m1": 16149.6, + "In116": 14.1, + "In116_m1": 3257.4, + "In116_m2": 2.18, + "In117": 2592.0, + "In117_m1": 6972.0, + "In118": 5.0, + "In118_m1": 267.0, + "In118_m2": 8.5, + "In119": 144.0, + "In119_m1": 1080.0, + "In120": 3.08, + "In120_m1": 46.2, + "In120_m2": 47.3, + "In121": 23.1, + "In121_m1": 232.8, + "In122": 1.5, + "In122_m1": 10.3, + "In122_m2": 10.8, + "In123": 6.17, + "In123_m1": 47.4, + "In124": 3.12, + "In124_m1": 3.7, + "In125": 2.36, + "In125_m1": 12.2, + "In126": 1.53, + "In126_m1": 1.64, + "In127": 1.09, + "In127_m1": 3.67, + "In128": 0.84, + "In128_m1": 0.72, + "In129": 0.61, + "In129_m1": 1.23, + "In130": 0.29, + "In130_m1": 0.54, + "In130_m2": 0.54, + "In131": 0.28, + "In131_m1": 0.35, + "In131_m2": 0.32, + "In132": 0.207, + "In133": 0.165, + "In133_m1": 0.18, + "In134": 0.14, + "In135": 0.092, + "Sn99": 0.005, + "Sn100": 0.86, + "Sn101": 1.7, + "Sn102": 4.5, + "Sn103": 7.0, + "Sn104": 20.8, + "Sn105": 34.0, + "Sn106": 115.0, + "Sn107": 174.0, + "Sn108": 618.0, + "Sn109": 1080.0, + "Sn110": 14796.0, + "Sn111": 2118.0, + "Sn113": 9943776.0, + "Sn113_m1": 1284.0, + "Sn117_m1": 1175040.0, + "Sn119_m1": 25315200.0, + "Sn121": 97308.0, + "Sn121_m1": 1385380000.0, + "Sn123": 11162880.0, + "Sn123_m1": 2403.6, + "Sn125": 832896.0, + "Sn125_m1": 571.2, + "Sn126": 7258250000000.0, + "Sn127": 7560.0, + "Sn127_m1": 247.8, + "Sn128": 3544.2, + "Sn128_m1": 6.5, + "Sn129": 133.8, + "Sn129_m1": 414.0, + "Sn130": 223.2, + "Sn130_m1": 102.0, + "Sn131": 56.0, + "Sn131_m1": 58.4, + "Sn132": 39.7, + "Sn133": 1.46, + "Sn134": 1.05, + "Sn135": 0.53, + "Sn136": 0.25, + "Sn137": 0.19, + "Sb103": 1.5e-06, + "Sb104": 0.46, + "Sb105": 1.22, + "Sb106": 0.6, + "Sb107": 4.0, + "Sb108": 7.4, + "Sb109": 17.0, + "Sb110": 23.0, + "Sb111": 75.0, + "Sb112": 51.4, + "Sb113": 400.2, + "Sb114": 209.4, + "Sb115": 1926.0, + "Sb116": 948.0, + "Sb116_m1": 3618.0, + "Sb117": 10080.0, + "Sb118": 216.0, + "Sb118_m1": 18000.0, + "Sb119": 137484.0, + "Sb119_m1": 0.85, + "Sb120": 953.4, + "Sb120_m1": 497664.0, + "Sb122": 235336.3, + "Sb122_m1": 251.46, + "Sb124": 5201280.0, + "Sb124_m1": 93.0, + "Sb124_m2": 1212.0, + "Sb125": 87053530.0, + "Sb126": 1067040.0, + "Sb126_m1": 1149.0, + "Sb126_m2": 11.0, + "Sb127": 332640.0, + "Sb128": 32436.0, + "Sb128_m1": 624.0, + "Sb129": 15840.0, + "Sb129_m1": 1062.0, + "Sb130": 2370.0, + "Sb130_m1": 378.0, + "Sb131": 1381.8, + "Sb132": 167.4, + "Sb132_m1": 246.0, + "Sb133": 150.0, + "Sb134": 0.78, + "Sb134_m1": 10.07, + "Sb135": 1.679, + "Sb136": 0.923, + "Sb137": 0.45, + "Sb138": 0.168, + "Sb139": 0.127, + "Te105": 6.2e-07, + "Te106": 6e-05, + "Te107": 0.0031, + "Te108": 2.1, + "Te109": 4.6, + "Te110": 18.6, + "Te111": 19.3, + "Te112": 120.0, + "Te113": 102.0, + "Te114": 912.0, + "Te115": 348.0, + "Te115_m1": 402.0, + "Te116": 8964.0, + "Te117": 3720.0, + "Te117_m1": 0.103, + "Te118": 518400.0, + "Te119": 57780.0, + "Te119_m1": 406080.0, + "Te121": 1656288.0, + "Te121_m1": 14186880.0, + "Te123_m1": 10298880.0, + "Te125_m1": 4959360.0, + "Te127": 33660.0, + "Te127_m1": 9417600.0, + "Te128": 2.77707e26, + "Te129": 4176.0, + "Te129_m1": 2903040.0, + "Te131": 1500.0, + "Te131_m1": 119700.0, + "Te132": 276825.6, + "Te133": 750.0, + "Te133_m1": 3324.0, + "Te134": 2508.0, + "Te135": 19.0, + "Te136": 17.5, + "Te137": 2.49, + "Te138": 1.4, + "Te139": 0.347, + "Te140": 0.304, + "Te141": 0.213, + "Te142": 0.2, + "I108": 0.036, + "I109": 0.000103, + "I110": 0.65, + "I111": 2.5, + "I112": 3.42, + "I113": 6.6, + "I114": 2.1, + "I114_m1": 6.2, + "I115": 78.0, + "I116": 2.91, + "I117": 133.2, + "I118": 822.0, + "I118_m1": 510.0, + "I119": 1146.0, + "I120": 4896.0, + "I120_m1": 3180.0, + "I121": 7632.0, + "I122": 217.8, + "I123": 47604.24, + "I124": 360806.4, + "I125": 5132160.0, + "I126": 1117152.0, + "I128": 1499.4, + "I129": 495454000000000.0, + "I130": 44496.0, + "I130_m1": 530.4, + "I131": 693377.3, + "I132": 8262.0, + "I132_m1": 4993.2, + "I133": 74880.0, + "I133_m1": 9.0, + "I134": 3150.0, + "I134_m1": 211.2, + "I135": 23652.0, + "I136": 83.4, + "I136_m1": 46.9, + "I137": 24.5, + "I138": 6.23, + "I139": 2.28, + "I140": 0.86, + "I141": 0.43, + "I142": 0.222, + "I143": 0.296, + "I144": 0.194, + "I145": 0.127, + "Xe110": 0.093, + "Xe111": 0.81, + "Xe112": 2.7, + "Xe113": 2.74, + "Xe114": 10.0, + "Xe115": 18.0, + "Xe116": 59.0, + "Xe117": 61.0, + "Xe118": 228.0, + "Xe119": 348.0, + "Xe120": 2400.0, + "Xe121": 2406.0, + "Xe122": 72360.0, + "Xe123": 7488.0, + "Xe125": 60840.0, + "Xe125_m1": 56.9, + "Xe127": 3144960.0, + "Xe127_m1": 69.2, + "Xe129_m1": 767232.0, + "Xe131_m1": 1022976.0, + "Xe132_m1": 0.00839, + "Xe133": 452995.2, + "Xe133_m1": 189216.0, + "Xe134_m1": 0.29, + "Xe135": 32904.0, + "Xe135_m1": 917.4, + "Xe137": 229.08, + "Xe138": 844.8, + "Xe139": 39.68, + "Xe140": 13.6, + "Xe141": 1.73, + "Xe142": 1.23, + "Xe143": 0.3, + "Xe144": 1.15, + "Xe145": 0.188, + "Xe146": 0.369, + "Xe147": 0.1, + "Cs112": 0.0005, + "Cs113": 1.67e-05, + "Cs114": 0.57, + "Cs115": 1.4, + "Cs116": 0.7, + "Cs116_m1": 3.85, + "Cs117": 8.4, + "Cs117_m1": 6.5, + "Cs118": 14.0, + "Cs118_m1": 17.0, + "Cs119": 43.0, + "Cs119_m1": 30.4, + "Cs120": 61.3, + "Cs120_m1": 57.0, + "Cs121": 155.0, + "Cs121_m1": 122.0, + "Cs122": 21.18, + "Cs122_m1": 0.36, + "Cs122_m2": 222.0, + "Cs123": 352.8, + "Cs123_m1": 1.64, + "Cs124": 30.8, + "Cs124_m1": 6.3, + "Cs125": 2802.0, + "Cs125_m1": 0.0009, + "Cs126": 98.4, + "Cs127": 22500.0, + "Cs128": 217.2, + "Cs129": 115416.0, + "Cs130": 1752.6, + "Cs130_m1": 207.6, + "Cs131": 837129.6, + "Cs132": 559872.0, + "Cs134": 65172760.0, + "Cs134_m1": 10483.2, + "Cs135": 72582500000000.0, + "Cs135_m1": 3180.0, + "Cs136": 1137024.0, + "Cs136_m1": 19.0, + "Cs137": 949252600.0, + "Cs138": 2004.6, + "Cs138_m1": 174.6, + "Cs139": 556.2, + "Cs140": 63.7, + "Cs141": 24.84, + "Cs142": 1.684, + "Cs143": 1.791, + "Cs144": 0.994, + "Cs144_m1": 1.0, + "Cs145": 0.587, + "Cs146": 0.321, + "Cs147": 0.23, + "Cs148": 0.146, + "Cs149": 0.05, + "Cs150": 0.05, + "Cs151": 0.05, + "Ba114": 0.43, + "Ba115": 0.45, + "Ba116": 1.3, + "Ba117": 1.75, + "Ba118": 5.5, + "Ba119": 5.4, + "Ba120": 24.0, + "Ba121": 29.7, + "Ba122": 117.0, + "Ba123": 162.0, + "Ba124": 660.0, + "Ba125": 210.0, + "Ba126": 6000.0, + "Ba127": 762.0, + "Ba127_m1": 1.9, + "Ba128": 209952.0, + "Ba129": 8028.0, + "Ba129_m1": 7776.0, + "Ba130_m1": 0.0094, + "Ba131": 993600.0, + "Ba131_m1": 876.0, + "Ba133": 331862400.0, + "Ba133_m1": 140040.0, + "Ba135_m1": 103320.0, + "Ba136_m1": 0.3084, + "Ba137_m1": 153.12, + "Ba139": 4983.6, + "Ba140": 1101833.0, + "Ba141": 1096.2, + "Ba142": 636.0, + "Ba143": 14.5, + "Ba144": 11.5, + "Ba145": 4.31, + "Ba146": 2.22, + "Ba147": 0.894, + "Ba148": 0.612, + "Ba149": 0.344, + "Ba150": 0.3, + "Ba151": 0.259, + "Ba152": 0.228, + "Ba153": 0.158, + "La117": 0.0235, + "La117_m1": 0.01, + "La118": 1.0, + "La119": 2.0, + "La120": 2.8, + "La121": 5.3, + "La122": 8.6, + "La123": 17.0, + "La124": 29.21, + "La124_m1": 21.0, + "La125": 64.8, + "La125_m1": 0.4, + "La126": 54.0, + "La126_m1": 50.0, + "La127": 306.0, + "La127_m1": 222.0, + "La128": 310.8, + "La128_m1": 60.0, + "La129": 696.0, + "La129_m1": 0.56, + "La130": 522.0, + "La131": 3540.0, + "La132": 17280.0, + "La132_m1": 1458.0, + "La133": 14083.2, + "La134": 387.0, + "La135": 70200.0, + "La136": 592.2, + "La136_m1": 0.114, + "La137": 1893460000000.0, + "La138": 3.21888e18, + "La140": 145026.7, + "La141": 14112.0, + "La142": 5466.0, + "La143": 852.0, + "La144": 40.8, + "La145": 24.8, + "La146": 6.27, + "La146_m1": 10.0, + "La147": 4.06, + "La148": 1.26, + "La149": 1.05, + "La150": 0.86, + "La151": 0.778, + "La152": 0.451, + "La153": 0.342, + "La154": 0.228, + "La155": 0.184, + "Ce119": 0.2, + "Ce120": 0.25, + "Ce121": 1.1, + "Ce122": 2.73, + "Ce123": 3.8, + "Ce124": 6.0, + "Ce125": 10.2, + "Ce126": 51.0, + "Ce127": 31.0, + "Ce127_m1": 28.6, + "Ce128": 235.8, + "Ce129": 210.0, + "Ce130": 1374.0, + "Ce131": 618.0, + "Ce131_m1": 324.0, + "Ce132": 12636.0, + "Ce132_m1": 0.0094, + "Ce133": 5820.0, + "Ce133_m1": 17640.0, + "Ce134": 273024.0, + "Ce135": 63720.0, + "Ce135_m1": 20.0, + "Ce137": 32400.0, + "Ce137_m1": 123840.0, + "Ce138_m1": 0.00865, + "Ce139": 11892180.0, + "Ce139_m1": 54.8, + "Ce141": 2808691.0, + "Ce143": 118940.4, + "Ce144": 24616220.0, + "Ce145": 180.6, + "Ce146": 811.2, + "Ce147": 56.4, + "Ce148": 56.0, + "Ce149": 5.3, + "Ce150": 4.0, + "Ce151": 1.76, + "Ce152": 1.4, + "Ce153": 0.979, + "Ce154": 0.775, + "Ce155": 0.471, + "Ce156": 0.369, + "Ce157": 0.2428, + "Pr121": 1.4, + "Pr122": 0.5, + "Pr123": 0.8, + "Pr124": 1.2, + "Pr125": 3.3, + "Pr126": 3.14, + "Pr127": 4.2, + "Pr128": 2.85, + "Pr129": 32.0, + "Pr130": 40.0, + "Pr131": 90.6, + "Pr131_m1": 5.73, + "Pr132": 96.0, + "Pr133": 390.0, + "Pr134": 1020.0, + "Pr134_m1": 660.0, + "Pr135": 1440.0, + "Pr136": 786.0, + "Pr137": 4608.0, + "Pr138": 87.0, + "Pr138_m1": 7632.0, + "Pr139": 15876.0, + "Pr140": 203.4, + "Pr142": 68832.0, + "Pr142_m1": 876.0, + "Pr143": 1172448.0, + "Pr144": 1036.8, + "Pr144_m1": 432.0, + "Pr145": 21542.4, + "Pr146": 1449.0, + "Pr147": 804.0, + "Pr148": 137.4, + "Pr148_m1": 120.6, + "Pr149": 135.6, + "Pr150": 6.19, + "Pr151": 18.9, + "Pr152": 3.63, + "Pr153": 4.28, + "Pr154": 2.3, + "Pr155": 0.852, + "Pr156": 0.733, + "Pr157": 0.598, + "Pr158": 0.1342, + "Pr159": 0.1055, + "Nd124": 0.5, + "Nd125": 0.6, + "Nd126": 2e-07, + "Nd127": 1.8, + "Nd128": 5.0, + "Nd129": 4.9, + "Nd130": 21.0, + "Nd131": 26.0, + "Nd132": 94.0, + "Nd133": 70.0, + "Nd133_m1": 70.0, + "Nd134": 510.0, + "Nd135": 744.0, + "Nd135_m1": 330.0, + "Nd136": 3039.0, + "Nd137": 2310.0, + "Nd137_m1": 1.6, + "Nd138": 18144.0, + "Nd139": 1782.0, + "Nd139_m1": 19800.0, + "Nd140": 291168.0, + "Nd141": 8964.0, + "Nd141_m1": 62.0, + "Nd144": 7.22669e22, + "Nd147": 948672.0, + "Nd149": 6220.8, + "Nd150": 2.49305e26, + "Nd151": 746.4, + "Nd152": 684.0, + "Nd153": 31.6, + "Nd154": 25.9, + "Nd155": 8.9, + "Nd156": 5.49, + "Nd157": 1.906, + "Nd158": 1.331, + "Nd159": 0.773, + "Nd160": 0.5883, + "Nd161": 0.4884, + "Pm126": 0.5, + "Pm127": 1.0, + "Pm128": 1.0, + "Pm129": 2.4, + "Pm130": 2.6, + "Pm131": 6.3, + "Pm132": 6.2, + "Pm133": 15.0, + "Pm133_m1": 8.8, + "Pm134": 5.0, + "Pm134_m1": 22.0, + "Pm135": 49.0, + "Pm135_m1": 45.0, + "Pm136": 47.0, + "Pm136_m1": 107.0, + "Pm137": 144.0, + "Pm138": 10.0, + "Pm138_m1": 194.4, + "Pm139": 249.0, + "Pm139_m1": 0.18, + "Pm140": 357.0, + "Pm140_m1": 357.0, + "Pm141": 1254.0, + "Pm142": 40.5, + "Pm142_m1": 0.002, + "Pm143": 22896000.0, + "Pm144": 31363200.0, + "Pm145": 558569500.0, + "Pm146": 174513500.0, + "Pm147": 82788210.0, + "Pm148": 463795.2, + "Pm148_m1": 3567456.0, + "Pm149": 191088.0, + "Pm150": 9648.0, + "Pm151": 102240.0, + "Pm152": 247.2, + "Pm152_m1": 451.2, + "Pm152_m2": 828.0, + "Pm153": 315.0, + "Pm154": 103.8, + "Pm154_m1": 160.8, + "Pm155": 41.5, + "Pm156": 26.7, + "Pm157": 10.56, + "Pm158": 4.8, + "Pm159": 1.47, + "Pm160": 1.561, + "Pm161": 1.065, + "Pm162": 0.2679, + "Pm163": 0.2, + "Sm128": 0.5, + "Sm129": 0.55, + "Sm130": 1.0, + "Sm131": 1.2, + "Sm132": 4.0, + "Sm133": 3.7, + "Sm134": 9.5, + "Sm135": 10.3, + "Sm136": 47.0, + "Sm137": 45.0, + "Sm138": 186.0, + "Sm139": 154.2, + "Sm139_m1": 10.7, + "Sm140": 889.2, + "Sm141": 612.0, + "Sm141_m1": 1356.0, + "Sm142": 4349.4, + "Sm143": 525.0, + "Sm143_m1": 66.0, + "Sm143_m2": 0.03, + "Sm145": 29376000.0, + "Sm146": 3250430000000000.0, + "Sm147": 3.34511e18, + "Sm148": 2.20903e23, + "Sm151": 2840184000.0, + "Sm153": 167400.0, + "Sm153_m1": 0.0106, + "Sm155": 1338.0, + "Sm156": 33840.0, + "Sm157": 482.0, + "Sm158": 318.0, + "Sm159": 11.37, + "Sm160": 9.6, + "Sm161": 4.8, + "Sm162": 2.4, + "Sm163": 1.748, + "Sm164": 1.226, + "Sm165": 0.764, + "Eu130": 0.001, + "Eu131": 0.0178, + "Eu132": 0.1, + "Eu133": 1.0, + "Eu134": 0.5, + "Eu135": 1.5, + "Eu136": 3.8, + "Eu136_m1": 3.3, + "Eu136_m2": 3.8, + "Eu137": 11.0, + "Eu138": 12.1, + "Eu139": 17.9, + "Eu140": 1.51, + "Eu140_m1": 0.125, + "Eu141": 40.7, + "Eu141_m1": 2.7, + "Eu142": 2.34, + "Eu142_m1": 73.38, + "Eu143": 155.4, + "Eu144": 10.2, + "Eu145": 512352.0, + "Eu146": 396576.0, + "Eu147": 2082240.0, + "Eu148": 4708800.0, + "Eu149": 8043840.0, + "Eu150": 1164480000.0, + "Eu150_m1": 46080.0, + "Eu152": 427195200.0, + "Eu152_m1": 33521.76, + "Eu152_m2": 5760.0, + "Eu154": 271426900.0, + "Eu154_m1": 2760.0, + "Eu155": 149993300.0, + "Eu156": 1312416.0, + "Eu157": 54648.0, + "Eu158": 2754.0, + "Eu159": 1086.0, + "Eu160": 38.0, + "Eu161": 26.0, + "Eu162": 10.6, + "Eu163": 7.7, + "Eu164": 2.844, + "Eu165": 2.3, + "Eu166": 0.4, + "Eu167": 0.2, + "Gd134": 0.4, + "Gd135": 1.1, + "Gd136": 2e-05, + "Gd137": 2.2, + "Gd138": 4.7, + "Gd139": 5.8, + "Gd139_m1": 4.8, + "Gd140": 15.8, + "Gd141": 14.0, + "Gd141_m1": 24.5, + "Gd142": 70.2, + "Gd143": 39.0, + "Gd143_m1": 110.0, + "Gd144": 268.2, + "Gd145": 1380.0, + "Gd145_m1": 85.0, + "Gd146": 4170528.0, + "Gd147": 137016.0, + "Gd148": 2354197000.0, + "Gd149": 801792.0, + "Gd150": 56488100000000.0, + "Gd151": 10713600.0, + "Gd152": 3.40822e21, + "Gd153": 20770560.0, + "Gd155_m1": 0.03197, + "Gd159": 66524.4, + "Gd161": 219.6, + "Gd162": 504.0, + "Gd163": 68.0, + "Gd164": 45.0, + "Gd165": 10.3, + "Gd166": 4.8, + "Gd167": 3.0, + "Gd168": 0.3, + "Gd169": 1.0, + "Tb135": 0.995, + "Tb136": 0.2, + "Tb137": 0.6, + "Tb138": 2e-07, + "Tb139": 1.6, + "Tb140": 2.4, + "Tb141": 3.5, + "Tb141_m1": 7.9, + "Tb142": 0.597, + "Tb142_m1": 0.303, + "Tb143": 12.0, + "Tb143_m1": 21.0, + "Tb144": 1.0, + "Tb144_m1": 4.25, + "Tb145": 30.9, + "Tb145_m1": 30.9, + "Tb146": 8.0, + "Tb146_m1": 23.0, + "Tb146_m2": 0.00118, + "Tb147": 5904.0, + "Tb147_m1": 109.8, + "Tb148": 3600.0, + "Tb148_m1": 132.0, + "Tb149": 14824.8, + "Tb149_m1": 249.6, + "Tb150": 12528.0, + "Tb150_m1": 348.0, + "Tb151": 63392.4, + "Tb151_m1": 25.0, + "Tb152": 63000.0, + "Tb152_m1": 252.0, + "Tb153": 202176.0, + "Tb154": 77400.0, + "Tb154_m1": 33840.0, + "Tb154_m2": 81720.0, + "Tb155": 459648.0, + "Tb156": 462240.0, + "Tb156_m1": 87840.0, + "Tb156_m2": 19080.0, + "Tb157": 2240590000.0, + "Tb158": 5680368000.0, + "Tb158_m1": 10.7, + "Tb160": 6246720.0, + "Tb161": 596678.4, + "Tb162": 456.0, + "Tb163": 1170.0, + "Tb164": 180.0, + "Tb165": 126.6, + "Tb166": 25.1, + "Tb167": 19.4, + "Tb168": 8.2, + "Tb169": 2.0, + "Tb170": 3.0, + "Tb171": 0.5, + "Dy138": 0.2, + "Dy139": 0.6, + "Dy140": 0.84, + "Dy141": 0.9, + "Dy142": 2.3, + "Dy143": 3.2, + "Dy143_m1": 3.0, + "Dy144": 9.1, + "Dy145": 6.0, + "Dy145_m1": 14.1, + "Dy146": 29.0, + "Dy146_m1": 0.15, + "Dy147": 40.0, + "Dy147_m1": 55.7, + "Dy148": 198.0, + "Dy149": 252.0, + "Dy149_m1": 0.49, + "Dy150": 430.2, + "Dy151": 1074.0, + "Dy152": 8568.0, + "Dy153": 23040.0, + "Dy154": 94672800000000.0, + "Dy155": 35640.0, + "Dy157": 29304.0, + "Dy157_m1": 0.0216, + "Dy159": 12476160.0, + "Dy165": 8402.4, + "Dy165_m1": 75.42, + "Dy166": 293760.0, + "Dy167": 372.0, + "Dy168": 522.0, + "Dy169": 39.0, + "Dy170": 30.0, + "Dy171": 6.0, + "Dy172": 3.0, + "Dy173": 2.0, + "Ho140": 0.006, + "Ho141": 0.0041, + "Ho142": 0.4, + "Ho143": 2e-07, + "Ho144": 0.7, + "Ho145": 2.4, + "Ho146": 3.6, + "Ho147": 5.8, + "Ho148": 2.2, + "Ho148_m1": 9.59, + "Ho148_m2": 0.00236, + "Ho149": 21.1, + "Ho149_m1": 56.0, + "Ho150": 72.0, + "Ho150_m1": 23.3, + "Ho151": 35.2, + "Ho151_m1": 47.2, + "Ho152": 161.8, + "Ho152_m1": 50.0, + "Ho153": 120.6, + "Ho153_m1": 558.0, + "Ho154": 705.6, + "Ho154_m1": 186.0, + "Ho155": 2880.0, + "Ho155_m1": 0.00088, + "Ho156": 3360.0, + "Ho156_m1": 9.5, + "Ho156_m2": 468.0, + "Ho157": 756.0, + "Ho158": 678.0, + "Ho158_m1": 1680.0, + "Ho158_m2": 1278.0, + "Ho159": 1983.0, + "Ho159_m1": 8.3, + "Ho160": 1536.0, + "Ho160_m1": 18072.0, + "Ho160_m2": 3.0, + "Ho161": 8928.0, + "Ho161_m1": 6.76, + "Ho162": 900.0, + "Ho162_m1": 4020.0, + "Ho163": 144218000000.0, + "Ho163_m1": 1.09, + "Ho164": 1740.0, + "Ho164_m1": 2250.0, + "Ho166": 96480.0, + "Ho166_m1": 37869100000.0, + "Ho167": 11160.0, + "Ho168": 179.4, + "Ho168_m1": 132.0, + "Ho169": 283.2, + "Ho170": 165.6, + "Ho170_m1": 43.0, + "Ho171": 53.0, + "Ho172": 25.0, + "Ho173": 10.0, + "Ho174": 8.0, + "Ho175": 5.0, + "Er143": 0.2, + "Er144": 2e-07, + "Er146": 1.7, + "Er147": 2.5, + "Er147_m1": 2.5, + "Er148": 4.6, + "Er149": 4.0, + "Er149_m1": 8.9, + "Er150": 18.5, + "Er151": 23.5, + "Er151_m1": 0.58, + "Er152": 10.3, + "Er153": 37.1, + "Er154": 223.8, + "Er155": 318.0, + "Er156": 1170.0, + "Er157": 1119.0, + "Er157_m1": 0.076, + "Er158": 8244.0, + "Er159": 2160.0, + "Er160": 102888.0, + "Er161": 11556.0, + "Er163": 4500.0, + "Er165": 37296.0, + "Er167_m1": 2.269, + "Er169": 811468.8, + "Er171": 27057.6, + "Er172": 177480.0, + "Er173": 84.0, + "Er174": 192.0, + "Er175": 72.0, + "Er176": 20.0, + "Er177": 3.0, + "Tm145": 3.1e-06, + "Tm146": 0.08, + "Tm146_m1": 0.2, + "Tm147": 0.58, + "Tm148": 0.7, + "Tm149": 0.9, + "Tm150": 2.2, + "Tm150_m1": 0.0052, + "Tm151": 4.17, + "Tm151_m1": 4.51e-07, + "Tm152": 8.0, + "Tm152_m1": 5.2, + "Tm153": 1.48, + "Tm153_m1": 2.5, + "Tm154": 8.1, + "Tm154_m1": 3.3, + "Tm155": 21.6, + "Tm155_m1": 45.0, + "Tm156": 83.8, + "Tm157": 217.8, + "Tm158": 238.8, + "Tm159": 547.8, + "Tm160": 564.0, + "Tm160_m1": 74.5, + "Tm161": 1812.0, + "Tm162": 1302.0, + "Tm162_m1": 24.3, + "Tm163": 6516.0, + "Tm164": 120.0, + "Tm164_m1": 306.0, + "Tm165": 108216.0, + "Tm166": 27720.0, + "Tm166_m1": 0.34, + "Tm167": 799200.0, + "Tm168": 8043840.0, + "Tm170": 11111040.0, + "Tm171": 60590590.0, + "Tm172": 228960.0, + "Tm173": 29664.0, + "Tm174": 324.0, + "Tm175": 912.0, + "Tm176": 114.0, + "Tm177": 90.0, + "Tm178": 30.0, + "Tm179": 20.0, + "Yb148": 0.25, + "Yb149": 0.7, + "Yb150": 2e-07, + "Yb151": 1.6, + "Yb151_m1": 1.6, + "Yb152": 3.04, + "Yb153": 4.2, + "Yb154": 0.409, + "Yb155": 1.793, + "Yb156": 26.1, + "Yb157": 38.6, + "Yb158": 89.4, + "Yb159": 100.2, + "Yb160": 288.0, + "Yb161": 252.0, + "Yb162": 1132.2, + "Yb163": 663.0, + "Yb164": 4548.0, + "Yb165": 594.0, + "Yb166": 204120.0, + "Yb167": 1050.0, + "Yb169": 2766355.0, + "Yb169_m1": 46.0, + "Yb171_m1": 0.00525, + "Yb175": 361584.0, + "Yb175_m1": 0.0682, + "Yb176_m1": 11.4, + "Yb177": 6879.6, + "Yb177_m1": 6.41, + "Yb178": 4440.0, + "Yb179": 480.0, + "Yb180": 144.0, + "Yb181": 60.0, + "Lu150": 0.043, + "Lu151": 0.0806, + "Lu152": 0.7, + "Lu153": 0.9, + "Lu153_m1": 1.0, + "Lu154": 2.0, + "Lu154_m1": 1.12, + "Lu155": 0.068, + "Lu155_m1": 0.138, + "Lu155_m2": 0.00269, + "Lu156": 0.494, + "Lu156_m1": 0.198, + "Lu157": 6.8, + "Lu157_m1": 4.79, + "Lu158": 10.6, + "Lu159": 12.1, + "Lu160": 36.1, + "Lu160_m1": 40.0, + "Lu161": 77.0, + "Lu161_m1": 0.0073, + "Lu162": 82.2, + "Lu162_m1": 90.0, + "Lu162_m2": 114.0, + "Lu163": 238.2, + "Lu164": 188.4, + "Lu165": 644.4, + "Lu166": 159.0, + "Lu166_m1": 84.6, + "Lu166_m2": 127.2, + "Lu167": 3090.0, + "Lu167_m1": 60.0, + "Lu168": 330.0, + "Lu168_m1": 402.0, + "Lu169": 122616.0, + "Lu169_m1": 160.0, + "Lu170": 173836.8, + "Lu170_m1": 0.67, + "Lu171": 711936.0, + "Lu171_m1": 79.0, + "Lu172": 578880.0, + "Lu172_m1": 222.0, + "Lu173": 43233910.0, + "Lu174": 104455700.0, + "Lu174_m1": 12268800.0, + "Lu176": 1.18657e18, + "Lu176_m1": 13086.0, + "Lu177": 574300.8, + "Lu177_m1": 13862020.0, + "Lu177_m2": 390.0, + "Lu178": 1704.0, + "Lu178_m1": 1386.0, + "Lu179": 16524.0, + "Lu179_m1": 0.0031, + "Lu180": 342.0, + "Lu180_m1": 0.001, + "Lu181": 210.0, + "Lu182": 120.0, + "Lu183": 58.0, + "Lu184": 20.0, + "Hf153": 6e-06, + "Hf154": 2.0, + "Hf155": 0.89, + "Hf156": 0.023, + "Hf157": 0.11, + "Hf158": 2.85, + "Hf159": 5.6, + "Hf160": 13.6, + "Hf161": 18.2, + "Hf162": 39.4, + "Hf163": 40.0, + "Hf164": 111.0, + "Hf165": 76.0, + "Hf166": 406.2, + "Hf167": 123.0, + "Hf168": 1557.0, + "Hf169": 194.4, + "Hf170": 57636.0, + "Hf171": 43560.0, + "Hf171_m1": 29.5, + "Hf172": 59012710.0, + "Hf173": 84960.0, + "Hf174": 6.31152e22, + "Hf175": 6048000.0, + "Hf177_m1": 1.09, + "Hf177_m2": 3084.0, + "Hf178_m1": 4.0, + "Hf178_m2": 978285600.0, + "Hf179_m1": 18.67, + "Hf179_m2": 2164320.0, + "Hf180_m1": 19800.0, + "Hf181": 3662496.0, + "Hf182": 280863000000000.0, + "Hf182_m1": 3690.0, + "Hf183": 3841.2, + "Hf184": 14832.0, + "Hf184_m1": 48.0, + "Hf185": 210.0, + "Hf186": 156.0, + "Hf187": 30.0, + "Hf188": 20.0, + "Ta155": 0.0031, + "Ta156": 0.144, + "Ta156_m1": 0.36, + "Ta157": 0.0101, + "Ta157_m1": 0.0043, + "Ta157_m2": 0.0017, + "Ta158": 0.055, + "Ta158_m1": 0.0367, + "Ta159": 0.83, + "Ta159_m1": 0.515, + "Ta160": 1.55, + "Ta160_m1": 1.7, + "Ta161": 2.89, + "Ta162": 3.57, + "Ta163": 10.6, + "Ta164": 14.2, + "Ta165": 31.0, + "Ta166": 34.4, + "Ta167": 80.0, + "Ta168": 120.0, + "Ta169": 294.0, + "Ta170": 405.6, + "Ta171": 1398.0, + "Ta172": 2208.0, + "Ta173": 11304.0, + "Ta174": 4104.0, + "Ta175": 37800.0, + "Ta176": 29124.0, + "Ta176_m1": 0.0011, + "Ta176_m2": 0.00097, + "Ta177": 203616.0, + "Ta178": 558.6, + "Ta178_m1": 8496.0, + "Ta178_m2": 0.058, + "Ta179": 57434830.0, + "Ta179_m1": 0.009, + "Ta179_m2": 0.0541, + "Ta180": 29354.4, + "Ta182": 9913536.0, + "Ta182_m1": 0.283, + "Ta182_m2": 950.4, + "Ta183": 440640.0, + "Ta184": 31320.0, + "Ta185": 2964.0, + "Ta185_m1": 0.002, + "Ta186": 630.0, + "Ta187": 120.0, + "Ta188": 20.0, + "Ta189": 3.0, + "Ta190": 0.3, + "W158": 0.00125, + "W159": 0.0073, + "W160": 0.091, + "W161": 0.409, + "W162": 1.36, + "W163": 2.8, + "W164": 6.3, + "W165": 5.1, + "W166": 19.2, + "W167": 19.9, + "W168": 53.0, + "W169": 74.0, + "W170": 145.2, + "W171": 142.8, + "W172": 396.0, + "W173": 456.0, + "W174": 1992.0, + "W175": 2112.0, + "W176": 9000.0, + "W177": 7920.0, + "W178": 1866240.0, + "W179": 2223.0, + "W179_m1": 384.0, + "W180": 5.68037e25, + "W180_m1": 0.00547, + "W181": 10471680.0, + "W183_m1": 5.2, + "W185": 6488640.0, + "W185_m1": 100.2, + "W186": 5.36e27, + "W186_m1": 0.003, + "W187": 86400.0, + "W188": 6028992.0, + "W189": 642.0, + "W190": 1800.0, + "W190_m1": 0.0031, + "W191": 20.0, + "W192": 10.0, + "Re160": 0.00085, + "Re161": 0.00037, + "Re161_m1": 0.0156, + "Re162": 0.107, + "Re162_m1": 0.077, + "Re163": 0.39, + "Re163_m1": 0.214, + "Re164": 0.53, + "Re164_m1": 0.87, + "Re165": 1.0, + "Re165_m1": 2.1, + "Re166": 2.25, + "Re167": 5.9, + "Re167_m1": 3.4, + "Re168": 4.4, + "Re169": 8.1, + "Re169_m1": 15.1, + "Re170": 9.2, + "Re171": 15.2, + "Re172": 55.0, + "Re172_m1": 15.0, + "Re173": 118.8, + "Re174": 144.0, + "Re175": 353.4, + "Re176": 318.0, + "Re177": 840.0, + "Re178": 792.0, + "Re179": 1170.0, + "Re180": 146.4, + "Re181": 71640.0, + "Re182": 230400.0, + "Re182_m1": 45720.0, + "Re183": 6048000.0, + "Re183_m1": 0.00104, + "Re184": 3058560.0, + "Re184_m1": 14601600.0, + "Re186": 321261.1, + "Re186_m1": 6311520000000.0, + "Re187": 1.36644e18, + "Re188": 61214.4, + "Re188_m1": 1115.4, + "Re189": 87480.0, + "Re190": 186.0, + "Re190_m1": 11520.0, + "Re191": 588.0, + "Re192": 16.0, + "Re193": 51.9, + "Re194": 1.0, + "Os162": 0.00205, + "Os163": 0.0055, + "Os164": 0.021, + "Os165": 0.071, + "Os166": 0.199, + "Os167": 0.81, + "Os168": 2.1, + "Os169": 3.43, + "Os170": 7.37, + "Os171": 8.3, + "Os172": 19.2, + "Os173": 22.4, + "Os174": 44.0, + "Os175": 84.0, + "Os176": 216.0, + "Os177": 180.0, + "Os178": 300.0, + "Os179": 390.0, + "Os180": 1290.0, + "Os181": 6300.0, + "Os181_m1": 162.0, + "Os182": 78624.0, + "Os183": 46800.0, + "Os183_m1": 35640.0, + "Os185": 8087040.0, + "Os186": 6.31152e22, + "Os189_m1": 20916.0, + "Os190_m1": 594.0, + "Os191": 1330560.0, + "Os191_m1": 47160.0, + "Os192_m1": 5.9, + "Os193": 108396.0, + "Os194": 189345600.0, + "Os195": 540.0, + "Os196": 2094.0, + "Ir164": 0.14, + "Ir164_m1": 9.5e-05, + "Ir165": 1e-06, + "Ir166": 0.0105, + "Ir166_m1": 0.0151, + "Ir167": 0.0352, + "Ir167_m1": 0.0257, + "Ir168": 0.232, + "Ir168_m1": 0.16, + "Ir169": 0.64, + "Ir169_m1": 0.281, + "Ir170": 0.9, + "Ir170_m1": 0.811, + "Ir171": 3.5, + "Ir171_m1": 1.4, + "Ir172": 4.4, + "Ir172_m1": 2.0, + "Ir173": 9.0, + "Ir173_m1": 2.2, + "Ir174": 7.9, + "Ir174_m1": 4.9, + "Ir175": 9.0, + "Ir176": 8.7, + "Ir177": 30.0, + "Ir178": 12.0, + "Ir179": 79.0, + "Ir180": 90.0, + "Ir181": 294.0, + "Ir182": 900.0, + "Ir183": 3480.0, + "Ir184": 11124.0, + "Ir185": 51840.0, + "Ir186": 59904.0, + "Ir186_m1": 6840.0, + "Ir187": 37800.0, + "Ir187_m1": 0.0303, + "Ir188": 149400.0, + "Ir188_m1": 0.0042, + "Ir189": 1140480.0, + "Ir189_m1": 0.0133, + "Ir189_m2": 0.0037, + "Ir190": 1017792.0, + "Ir190_m1": 4032.0, + "Ir190_m2": 11113.2, + "Ir191_m1": 4.899, + "Ir191_m2": 5.5, + "Ir192": 6378653.0, + "Ir192_m1": 87.0, + "Ir192_m2": 7605382000.0, + "Ir193_m1": 909792.0, + "Ir194": 69408.0, + "Ir194_m1": 0.03185, + "Ir194_m2": 14774400.0, + "Ir195": 9000.0, + "Ir195_m1": 13680.0, + "Ir196": 52.0, + "Ir196_m1": 5040.0, + "Ir197": 348.0, + "Ir197_m1": 534.0, + "Ir198": 8.0, + "Ir199": 6.5, + "Pt166": 0.0003, + "Pt167": 0.00078, + "Pt168": 0.002, + "Pt169": 0.007, + "Pt170": 0.014, + "Pt171": 0.051, + "Pt172": 0.096, + "Pt173": 0.382, + "Pt174": 0.889, + "Pt175": 2.53, + "Pt176": 6.33, + "Pt177": 10.6, + "Pt178": 21.1, + "Pt179": 21.2, + "Pt180": 56.0, + "Pt181": 52.0, + "Pt182": 180.0, + "Pt183": 390.0, + "Pt183_m1": 43.0, + "Pt184": 1038.0, + "Pt184_m1": 0.00101, + "Pt185": 4254.0, + "Pt185_m1": 1980.0, + "Pt186": 7488.0, + "Pt187": 8460.0, + "Pt188": 881280.0, + "Pt189": 39132.0, + "Pt190": 2.05124e19, + "Pt191": 242092.8, + "Pt193": 1577880000.0, + "Pt193_m1": 374112.0, + "Pt195_m1": 346464.0, + "Pt197": 71609.4, + "Pt197_m1": 5724.6, + "Pt199": 1848.0, + "Pt199_m1": 13.6, + "Pt200": 45360.0, + "Pt201": 150.0, + "Pt202": 158400.0, + "Au169": 0.00015, + "Au170": 0.000291, + "Au170_m1": 0.00062, + "Au171": 1.9e-05, + "Au171_m1": 0.00102, + "Au172": 0.0047, + "Au173": 0.025, + "Au173_m1": 0.014, + "Au174": 0.139, + "Au174_m1": 0.1629, + "Au175": 0.1, + "Au175_m1": 0.156, + "Au176": 1.05, + "Au176_m1": 1.36, + "Au177": 1.462, + "Au177_m1": 1.18, + "Au178": 2.6, + "Au179": 3.3, + "Au180": 8.1, + "Au181": 13.7, + "Au182": 15.6, + "Au183": 42.8, + "Au184": 20.6, + "Au184_m1": 47.6, + "Au185": 255.0, + "Au186": 642.0, + "Au187": 504.0, + "Au187_m1": 2.3, + "Au188": 530.4, + "Au189": 1722.0, + "Au189_m1": 275.4, + "Au190": 2568.0, + "Au190_m1": 0.125, + "Au191": 11448.0, + "Au191_m1": 0.92, + "Au192": 17784.0, + "Au192_m1": 0.029, + "Au192_m2": 0.16, + "Au193": 63540.0, + "Au193_m1": 3.9, + "Au194": 136872.0, + "Au194_m1": 0.6, + "Au194_m2": 0.42, + "Au195": 16078870.0, + "Au195_m1": 30.5, + "Au196": 532820.2, + "Au196_m1": 8.1, + "Au196_m2": 34560.0, + "Au197_m1": 7.73, + "Au198": 232822.1, + "Au198_m1": 196300.8, + "Au199": 271209.6, + "Au200": 2904.0, + "Au200_m1": 67320.0, + "Au201": 1560.0, + "Au202": 28.4, + "Au203": 60.0, + "Au204": 39.8, + "Au205": 31.0, + "Hg171": 6.9e-05, + "Hg172": 0.000365, + "Hg173": 0.0007, + "Hg174": 0.0019, + "Hg175": 0.0107, + "Hg176": 0.0203, + "Hg177": 0.1273, + "Hg178": 0.269, + "Hg179": 1.08, + "Hg180": 2.58, + "Hg181": 3.6, + "Hg182": 10.83, + "Hg183": 9.4, + "Hg184": 30.9, + "Hg185": 49.1, + "Hg185_m1": 21.6, + "Hg186": 82.8, + "Hg187": 144.0, + "Hg187_m1": 114.0, + "Hg188": 195.0, + "Hg189": 456.0, + "Hg189_m1": 516.0, + "Hg190": 1200.0, + "Hg191": 2940.0, + "Hg191_m1": 3048.0, + "Hg192": 17460.0, + "Hg193": 13680.0, + "Hg193_m1": 42480.0, + "Hg194": 14011600000.0, + "Hg195": 37908.0, + "Hg195_m1": 149760.0, + "Hg197": 230904.0, + "Hg197_m1": 85680.0, + "Hg199_m1": 2560.2, + "Hg203": 4025722.0, + "Hg205": 308.4, + "Hg205_m1": 0.00109, + "Hg206": 499.2, + "Hg207": 174.0, + "Hg208": 2490.0, + "Hg209": 36.5, + "Hg210": 146.0, + "Tl176": 0.006, + "Tl177": 0.018, + "Tl178": 0.06, + "Tl179": 0.23, + "Tl179_m1": 0.0017, + "Tl180": 1.09, + "Tl181": 3.2, + "Tl181_m1": 0.0014, + "Tl182": 3.1, + "Tl183": 6.9, + "Tl183_m1": 0.0533, + "Tl184": 11.0, + "Tl185": 19.5, + "Tl185_m1": 1.93, + "Tl186": 27.5, + "Tl186_m1": 2.9, + "Tl187": 51.0, + "Tl187_m1": 15.6, + "Tl188": 71.0, + "Tl188_m1": 71.0, + "Tl188_m2": 0.041, + "Tl189": 138.0, + "Tl189_m1": 84.0, + "Tl190": 222.0, + "Tl190_m1": 156.0, + "Tl191": 1200.0, + "Tl191_m1": 313.2, + "Tl192": 576.0, + "Tl192_m1": 648.0, + "Tl193": 1296.0, + "Tl193_m1": 126.6, + "Tl194": 1980.0, + "Tl194_m1": 1968.0, + "Tl195": 4176.0, + "Tl195_m1": 3.6, + "Tl196": 6624.0, + "Tl196_m1": 5076.0, + "Tl197": 10224.0, + "Tl197_m1": 0.54, + "Tl198": 19080.0, + "Tl198_m1": 6732.0, + "Tl198_m2": 0.0321, + "Tl199": 26712.0, + "Tl199_m1": 0.0284, + "Tl200": 93960.0, + "Tl200_m1": 0.034, + "Tl201": 262837.4, + "Tl201_m1": 0.00201, + "Tl202": 1063584.0, + "Tl204": 119382400.0, + "Tl206": 252.12, + "Tl206_m1": 224.4, + "Tl207": 286.2, + "Tl207_m1": 1.33, + "Tl208": 183.18, + "Tl209": 132.0, + "Tl210": 78.0, + "Tl211": 60.0, + "Tl212": 67.0, + "Pb178": 0.00023, + "Pb179": 0.003, + "Pb180": 0.0045, + "Pb181": 0.036, + "Pb181_m1": 0.045, + "Pb182": 0.0575, + "Pb183": 0.535, + "Pb183_m1": 0.415, + "Pb184": 0.49, + "Pb185": 6.3, + "Pb185_m1": 4.3, + "Pb186": 4.82, + "Pb187": 15.2, + "Pb187_m1": 18.3, + "Pb188": 25.1, + "Pb189": 39.0, + "Pb189_m1": 50.0, + "Pb190": 71.0, + "Pb191": 79.8, + "Pb191_m1": 130.8, + "Pb192": 210.0, + "Pb193": 120.0, + "Pb193_m1": 348.0, + "Pb194": 720.0, + "Pb195": 900.0, + "Pb195_m1": 900.0, + "Pb196": 2220.0, + "Pb197": 480.0, + "Pb197_m1": 2580.0, + "Pb198": 8640.0, + "Pb199": 5400.0, + "Pb199_m1": 732.0, + "Pb200": 77400.0, + "Pb201": 33588.0, + "Pb201_m1": 60.8, + "Pb202": 1656770000000.0, + "Pb202_m1": 12744.0, + "Pb203": 186912.0, + "Pb203_m1": 6.21, + "Pb203_m2": 0.48, + "Pb204": 4.4e24, + "Pb204_m1": 4015.8, + "Pb205": 545946000000000.0, + "Pb205_m1": 0.00555, + "Pb207_m1": 0.806, + "Pb209": 11710.8, + "Pb210": 700578700.0, + "Pb211": 2166.0, + "Pb212": 38304.0, + "Pb213": 612.0, + "Pb214": 1608.0, + "Pb215": 36.0, + "Bi184": 0.013, + "Bi184_m1": 0.0066, + "Bi185": 5.8e-05, + "Bi186": 0.015, + "Bi186_m1": 0.0098, + "Bi187": 0.032, + "Bi187_m1": 0.00031, + "Bi188": 0.06, + "Bi188_m1": 0.265, + "Bi189": 0.674, + "Bi189_m1": 0.005, + "Bi190": 6.3, + "Bi190_m1": 6.2, + "Bi191": 12.4, + "Bi191_m1": 0.125, + "Bi192": 34.6, + "Bi192_m1": 39.6, + "Bi193": 63.6, + "Bi193_m1": 3.2, + "Bi194": 95.0, + "Bi194_m1": 125.0, + "Bi194_m2": 115.0, + "Bi195": 183.0, + "Bi195_m1": 87.0, + "Bi196": 308.0, + "Bi196_m1": 0.6, + "Bi196_m2": 240.0, + "Bi197": 559.8, + "Bi197_m1": 302.4, + "Bi198": 618.0, + "Bi198_m1": 696.0, + "Bi198_m2": 7.7, + "Bi199": 1620.0, + "Bi199_m1": 1482.0, + "Bi200": 2184.0, + "Bi200_m1": 1860.0, + "Bi200_m2": 0.4, + "Bi201": 6180.0, + "Bi201_m1": 3450.0, + "Bi202": 6156.0, + "Bi203": 42336.0, + "Bi203_m1": 0.305, + "Bi204": 40392.0, + "Bi204_m1": 0.013, + "Bi204_m2": 0.00107, + "Bi205": 1322784.0, + "Bi206": 539395.2, + "Bi207": 995642300.0, + "Bi208": 11613200000000.0, + "Bi208_m1": 0.00258, + "Bi209": 5.99594e26, + "Bi210": 433036.8, + "Bi210_m1": 95935100000000.0, + "Bi211": 128.4, + "Bi212": 3633.0, + "Bi212_m1": 1500.0, + "Bi212_m2": 420.0, + "Bi213": 2735.4, + "Bi214": 1194.0, + "Bi215": 462.0, + "Bi215_m1": 36.4, + "Bi216": 135.0, + "Bi217": 98.5, + "Bi218": 33.0, + "Po188": 0.000425, + "Po189": 0.0035, + "Po190": 0.00245, + "Po191": 0.022, + "Po191_m1": 0.093, + "Po192": 0.0332, + "Po193": 0.37, + "Po193_m1": 0.373, + "Po194": 0.392, + "Po195": 4.64, + "Po195_m1": 1.92, + "Po196": 5.8, + "Po197": 84.0, + "Po197_m1": 32.0, + "Po198": 106.2, + "Po199": 328.2, + "Po199_m1": 250.2, + "Po200": 690.6, + "Po201": 936.0, + "Po201_m1": 537.6, + "Po202": 2676.0, + "Po203": 2202.0, + "Po203_m1": 45.0, + "Po204": 12708.0, + "Po205": 6264.0, + "Po205_m1": 0.000645, + "Po205_m2": 0.0574, + "Po206": 760320.0, + "Po207": 20880.0, + "Po207_m1": 2.79, + "Po208": 91453920.0, + "Po209": 3218880000.0, + "Po210": 11955690.0, + "Po211": 0.516, + "Po211_m1": 25.2, + "Po212": 2.99e-07, + "Po212_m1": 45.1, + "Po213": 4.2e-06, + "Po214": 0.0001643, + "Po215": 0.001781, + "Po216": 0.145, + "Po217": 1.53, + "Po218": 185.88, + "Po219": 3e-07, + "Po220": 3e-07, + "At193": 0.0285, + "At194": 0.04, + "At194_m1": 0.25, + "At195": 0.328, + "At195_m1": 0.147, + "At196": 0.388, + "At196_m1": 1.1e-05, + "At197": 0.388, + "At197_m1": 2.0, + "At198": 4.2, + "At198_m1": 1.0, + "At199": 7.03, + "At200": 43.0, + "At200_m1": 47.0, + "At200_m2": 7.9, + "At201": 85.2, + "At202": 184.0, + "At202_m1": 182.0, + "At202_m2": 0.46, + "At203": 444.0, + "At204": 553.2, + "At204_m1": 0.108, + "At205": 1614.0, + "At206": 1836.0, + "At207": 6480.0, + "At208": 5868.0, + "At209": 19476.0, + "At210": 29160.0, + "At211": 25970.4, + "At212": 0.314, + "At212_m1": 0.119, + "At213": 1.25e-07, + "At214": 5.58e-07, + "At215": 0.0001, + "At216": 0.0003, + "At217": 0.0323, + "At218": 1.5, + "At219": 56.0, + "At220": 222.6, + "At221": 138.0, + "At222": 54.0, + "At223": 50.0, + "Rn195": 0.0065, + "Rn195_m1": 0.005, + "Rn196": 0.0046, + "Rn197": 0.066, + "Rn197_m1": 0.021, + "Rn198": 0.065, + "Rn199": 0.59, + "Rn199_m1": 0.31, + "Rn200": 1.075, + "Rn201": 7.0, + "Rn201_m1": 3.8, + "Rn202": 9.7, + "Rn203": 44.0, + "Rn203_m1": 26.9, + "Rn204": 70.2, + "Rn205": 170.0, + "Rn206": 340.2, + "Rn207": 555.0, + "Rn208": 1461.0, + "Rn209": 1728.0, + "Rn210": 8640.0, + "Rn211": 52560.0, + "Rn212": 1434.0, + "Rn213": 0.025, + "Rn214": 2.7e-07, + "Rn215": 2.3e-06, + "Rn216": 4.5e-05, + "Rn217": 0.00054, + "Rn218": 0.035, + "Rn219": 3.96, + "Rn220": 55.6, + "Rn221": 1542.0, + "Rn222": 330350.4, + "Rn223": 1458.0, + "Rn224": 6420.0, + "Rn225": 279.6, + "Rn226": 444.0, + "Rn227": 20.8, + "Rn228": 65.0, + "Fr199": 0.015, + "Fr200": 0.049, + "Fr201": 0.069, + "Fr202": 0.3, + "Fr202_m1": 0.29, + "Fr203": 0.55, + "Fr204": 1.7, + "Fr204_m1": 2.6, + "Fr204_m2": 1.0, + "Fr205": 3.8, + "Fr206": 16.0, + "Fr206_m1": 16.0, + "Fr206_m2": 0.7, + "Fr207": 14.8, + "Fr208": 59.1, + "Fr209": 50.0, + "Fr210": 190.8, + "Fr211": 186.0, + "Fr212": 1200.0, + "Fr213": 34.82, + "Fr214": 0.005, + "Fr214_m1": 0.00335, + "Fr215": 8.6e-08, + "Fr216": 7e-07, + "Fr217": 1.9e-05, + "Fr218": 0.001, + "Fr218_m1": 0.022, + "Fr219": 0.02, + "Fr220": 27.4, + "Fr221": 294.0, + "Fr222": 852.0, + "Fr223": 1320.0, + "Fr224": 199.8, + "Fr225": 237.0, + "Fr226": 49.0, + "Fr227": 148.2, + "Fr228": 38.0, + "Fr229": 50.2, + "Fr230": 19.1, + "Fr231": 17.6, + "Fr232": 5.5, + "Ra202": 0.0275, + "Ra203": 0.031, + "Ra203_m1": 0.025, + "Ra204": 0.0605, + "Ra205": 0.22, + "Ra205_m1": 0.18, + "Ra206": 0.24, + "Ra207": 1.3, + "Ra207_m1": 0.055, + "Ra208": 1.3, + "Ra209": 4.6, + "Ra210": 3.7, + "Ra211": 13.0, + "Ra212": 13.0, + "Ra213": 163.8, + "Ra213_m1": 0.0021, + "Ra214": 2.46, + "Ra215": 0.00155, + "Ra216": 1.82e-07, + "Ra217": 1.6e-06, + "Ra218": 2.52e-05, + "Ra219": 0.01, + "Ra220": 0.018, + "Ra221": 28.0, + "Ra222": 36.17, + "Ra223": 987552.0, + "Ra224": 316224.0, + "Ra225": 1287360.0, + "Ra226": 50492200000.0, + "Ra227": 2532.0, + "Ra228": 181456200.0, + "Ra229": 240.0, + "Ra230": 5580.0, + "Ra231": 103.0, + "Ra232": 252.0, + "Ra233": 30.0, + "Ra234": 30.0, + "Ac206": 0.024, + "Ac206_m1": 0.0395, + "Ac207": 0.027, + "Ac208": 0.095, + "Ac208_m1": 0.025, + "Ac209": 0.098, + "Ac210": 0.35, + "Ac211": 0.21, + "Ac212": 0.93, + "Ac213": 0.8, + "Ac214": 8.2, + "Ac215": 0.17, + "Ac216": 0.00044, + "Ac216_m1": 0.000441, + "Ac217": 6.9e-08, + "Ac218": 1.08e-06, + "Ac219": 1.18e-05, + "Ac220": 0.0264, + "Ac221": 0.052, + "Ac222": 5.0, + "Ac222_m1": 63.0, + "Ac223": 126.0, + "Ac224": 10008.0, + "Ac225": 864000.0, + "Ac226": 105732.0, + "Ac227": 687072100.0, + "Ac228": 22140.0, + "Ac229": 3762.0, + "Ac230": 122.0, + "Ac231": 450.0, + "Ac232": 119.0, + "Ac233": 145.0, + "Ac234": 44.0, + "Ac235": 60.0, + "Ac236": 120.0, + "Th209": 0.0065, + "Th210": 0.016, + "Th211": 0.05, + "Th212": 0.035, + "Th213": 0.14, + "Th214": 0.1, + "Th215": 1.2, + "Th216": 0.026, + "Th217": 0.000251, + "Th218": 1.17e-07, + "Th219": 1.05e-06, + "Th220": 9.7e-06, + "Th221": 0.00173, + "Th222": 0.002237, + "Th223": 0.6, + "Th224": 1.05, + "Th225": 523.2, + "Th226": 1834.2, + "Th227": 1613952.0, + "Th228": 60338130.0, + "Th229": 231633000000.0, + "Th230": 2378810000000.0, + "Th231": 91872.0, + "Th232": 4.43384e17, + "Th233": 1338.0, + "Th234": 2082240.0, + "Th235": 426.0, + "Th236": 2238.0, + "Th237": 282.0, + "Th238": 564.0, + "Pa212": 0.0051, + "Pa213": 0.0053, + "Pa214": 0.017, + "Pa215": 0.014, + "Pa216": 0.16, + "Pa217": 0.0036, + "Pa217_m1": 0.0012, + "Pa218": 0.000113, + "Pa219": 5.3e-08, + "Pa220": 7.8e-07, + "Pa221": 5.9e-06, + "Pa222": 0.0033, + "Pa223": 0.0051, + "Pa224": 0.79, + "Pa225": 1.7, + "Pa226": 108.0, + "Pa227": 2298.0, + "Pa228": 79200.0, + "Pa229": 129600.0, + "Pa230": 1503360.0, + "Pa231": 1033830000000.0, + "Pa232": 114048.0, + "Pa233": 2330640.0, + "Pa234": 24120.0, + "Pa234_m1": 69.54, + "Pa235": 1466.4, + "Pa236": 546.0, + "Pa237": 522.0, + "Pa238": 136.2, + "Pa239": 6480.0, + "Pa240": 120.0, + "U217": 0.0235, + "U218": 0.000545, + "U219": 4.2e-05, + "U220": 6e-08, + "U222": 1.3e-06, + "U223": 1.8e-05, + "U224": 0.0009, + "U225": 0.084, + "U226": 0.35, + "U227": 66.0, + "U228": 546.0, + "U229": 3480.0, + "U230": 1797120.0, + "U231": 362880.0, + "U232": 2174319000.0, + "U233": 5023970000000.0, + "U234": 7747390000000.0, + "U235": 2.22102e16, + "U235_m1": 1560.0, + "U236": 739079000000000.0, + "U237": 583200.0, + "U238": 1.40999e17, + "U239": 1407.0, + "U240": 50760.0, + "U241": 300.0, + "U242": 1008.0, + "Np225": 2e-06, + "Np226": 0.035, + "Np227": 0.51, + "Np228": 61.4, + "Np229": 240.0, + "Np230": 276.0, + "Np231": 2928.0, + "Np232": 882.0, + "Np233": 2172.0, + "Np234": 380160.0, + "Np235": 34231680.0, + "Np236": 4828310000000.0, + "Np236_m1": 81000.0, + "Np237": 67659500000000.0, + "Np238": 182908.8, + "Np239": 203558.4, + "Np240": 3714.0, + "Np240_m1": 433.2, + "Np241": 834.0, + "Np242": 132.0, + "Np242_m1": 330.0, + "Np243": 111.0, + "Np244": 137.4, + "Pu228": 1.85, + "Pu229": 112.0, + "Pu230": 102.0, + "Pu231": 516.0, + "Pu232": 2028.0, + "Pu233": 1254.0, + "Pu234": 31680.0, + "Pu235": 1518.0, + "Pu236": 90191620.0, + "Pu237": 3943296.0, + "Pu237_m1": 0.18, + "Pu238": 2767602000.0, + "Pu239": 760854000000.0, + "Pu240": 207049000000.0, + "Pu241": 450958100.0, + "Pu242": 11786800000000.0, + "Pu243": 17841.6, + "Pu244": 2559320000000000.0, + "Pu245": 37800.0, + "Pu246": 936576.0, + "Pu247": 196128.0, + "Am231": 10.0, + "Am232": 79.0, + "Am233": 192.0, + "Am234": 139.2, + "Am235": 618.0, + "Am236": 216.0, + "Am237": 4416.0, + "Am238": 5880.0, + "Am239": 42840.0, + "Am240": 182880.0, + "Am241": 13651800000.0, + "Am242": 57672.0, + "Am242_m1": 4449622000.0, + "Am242_m2": 0.014, + "Am243": 232580000000.0, + "Am244": 36360.0, + "Am244_m1": 1560.0, + "Am245": 7380.0, + "Am246": 2340.0, + "Am246_m1": 1500.0, + "Am247": 1380.0, + "Am248": 600.0, + "Am249": 120.0, + "Cm233": 17.7, + "Cm234": 51.0, + "Cm235": 300.0, + "Cm236": 1900.0, + "Cm237": 1200.0, + "Cm238": 8640.0, + "Cm239": 10440.0, + "Cm240": 2332800.0, + "Cm241": 2833920.0, + "Cm242": 14078020.0, + "Cm243": 918326200.0, + "Cm244": 571508100.0, + "Cm244_m1": 5e-07, + "Cm245": 268240000000.0, + "Cm246": 150214000000.0, + "Cm247": 492299000000000.0, + "Cm248": 10982000000000.0, + "Cm249": 3849.0, + "Cm250": 261928000000.0, + "Cm251": 1008.0, + "Bk235": 20.0, + "Bk237": 60.0, + "Bk238": 144.0, + "Bk240": 288.0, + "Bk241": 276.0, + "Bk242": 420.0, + "Bk243": 16200.0, + "Bk244": 15660.0, + "Bk245": 426816.0, + "Bk246": 155520.0, + "Bk247": 43549500000.0, + "Bk248": 283824000.0, + "Bk248_m1": 85320.0, + "Bk249": 27648000.0, + "Bk250": 11563.2, + "Bk251": 3336.0, + "Bk253": 600.0, + "Bk254": 120.0, + "Cf237": 2.1, + "Cf238": 0.021, + "Cf239": 51.5, + "Cf240": 57.6, + "Cf241": 226.8, + "Cf242": 222.0, + "Cf243": 642.0, + "Cf244": 1164.0, + "Cf245": 2700.0, + "Cf246": 128520.0, + "Cf247": 11196.0, + "Cf248": 28814400.0, + "Cf249": 11076700000.0, + "Cf250": 412773400.0, + "Cf251": 28338700000.0, + "Cf252": 83468070.0, + "Cf253": 1538784.0, + "Cf254": 5227200.0, + "Cf255": 5100.0, + "Cf256": 738.0, + "Es240": 1.0, + "Es241": 8.5, + "Es242": 13.5, + "Es243": 21.0, + "Es244": 37.0, + "Es245": 66.0, + "Es246": 462.0, + "Es247": 273.0, + "Es247_m1": 54000000.0, + "Es248": 1620.0, + "Es249": 6132.0, + "Es250": 30960.0, + "Es250_m1": 7992.0, + "Es251": 118800.0, + "Es252": 40754880.0, + "Es253": 1768608.0, + "Es254": 23820480.0, + "Es254_m1": 141479.9, + "Es255": 3438720.0, + "Es256": 1524.0, + "Es256_m1": 27360.0, + "Es257": 665280.0, + "Es258": 180.0, + "Fm242": 0.0008, + "Fm243": 0.2, + "Fm244": 0.0033, + "Fm245": 4.2, + "Fm246": 1.1, + "Fm247": 29.0, + "Fm248": 36.0, + "Fm249": 156.0, + "Fm250": 1800.0, + "Fm250_m1": 1.8, + "Fm251": 19080.0, + "Fm252": 91404.0, + "Fm253": 259200.0, + "Fm254": 11664.0, + "Fm255": 72252.0, + "Fm256": 9456.0, + "Fm257": 8683200.0, + "Fm258": 0.00037, + "Fm259": 1.5, + "Fm260": 0.004, + "Md245": 0.0009, + "Md245_m1": 0.39, + "Md246": 0.9, + "Md247": 1.12, + "Md247_m1": 0.26, + "Md248": 7.0, + "Md249": 24.0, + "Md249_m1": 1.9, + "Md250": 27.5, + "Md251": 240.0, + "Md252": 138.0, + "Md253": 630.0, + "Md254": 1680.0, + "Md254_m1": 1680.0, + "Md255": 1620.0, + "Md256": 4620.0, + "Md257": 19872.0, + "Md258": 4449600.0, + "Md258_m1": 3420.0, + "Md259": 5760.0, + "Md260": 2747520.0, + "Md261": 2400.0, + "No250": 4.35e-06, + "No251": 0.8, + "No251_m1": 1.02, + "No252": 2.44, + "No253": 97.2, + "No254": 51.0, + "No254_m1": 0.28, + "No255": 186.0, + "No256": 2.91, + "No257": 25.0, + "No258": 0.0012, + "No259": 3480.0, + "No260": 0.106, + "No261": 160000.0, + "No262": 0.005, + "Lr251": 1.341, + "Lr252": 0.38, + "Lr253": 0.575, + "Lr253_m1": 1.535, + "Lr254": 13.0, + "Lr255": 22.0, + "Lr255_m1": 2.53, + "Lr256": 27.0, + "Lr257": 0.646, + "Lr258": 4.1, + "Lr259": 6.2, + "Lr260": 180.0, + "Lr261": 2340.0, + "Lr262": 14400.0, + "Lr263": 18000.0, + "Rf253": 5.15e-05, + "Rf254": 2.3e-05, + "Rf255": 1.68, + "Rf256": 0.0064, + "Rf257": 4.7, + "Rf257_m1": 3.9, + "Rf258": 0.012, + "Rf259": 3.2, + "Rf260": 0.021, + "Rf261": 65.0, + "Rf261_m1": 81.0, + "Rf262": 2.3, + "Rf263": 600.0, + "Rf264": 3600.0, + "Rf265": 1.0, + "Db255": 1.7, + "Db256": 1.7, + "Db257": 1.52, + "Db257_m1": 0.78, + "Db258": 4.0, + "Db258_m1": 20.0, + "Db259": 0.51, + "Db260": 1.52, + "Db261": 1.8, + "Db262": 35.0, + "Db263": 28.5, + "Db264": 180.0, + "Db265": 900.0, + "Sg258": 0.0032, + "Sg259": 0.555, + "Sg260": 0.0036, + "Sg261": 0.23, + "Sg262": 0.0079, + "Sg263": 1.0, + "Sg263_m1": 0.12, + "Sg264": 0.045, + "Sg265": 8.0, + "Sg266": 25.0, + "Sg269": 50.0, + "Bh260": 0.0003, + "Bh261": 0.013, + "Bh262": 0.102, + "Bh262_m1": 0.022, + "Bh263": 0.0002, + "Bh264": 0.66, + "Bh265": 1.1, + "Bh266": 5.4, + "Bh267": 21.0, + "Bh269": 50.0, + "Hs263": 0.00355, + "Hs264": 0.0008, + "Hs265": 0.00205, + "Hs265_m1": 0.0003, + "Hs266": 0.00265, + "Hs267": 0.0545, + "Hs268": 1.2, + "Hs269": 12.9, + "Hs273": 50.0, + "Mt265": 120.0, + "Mt266": 0.0018, + "Mt266_m1": 0.0017, + "Mt267": 0.01, + "Mt268": 0.0225, + "Mt269": 0.05, + "Mt270": 0.00605, + "Mt271": 5.0, + "Mt273": 20.0, + "Ds267": 2.8e-06, + "Ds268": 0.0001, + "Ds269": 0.000268, + "Ds270": 0.00015, + "Ds270_m1": 0.009, + "Ds271": 0.001705, + "Ds271_m1": 0.0865, + "Ds272": 1.0, + "Ds273": 0.000225, + "Ds279_m1": 0.19, + "Rg272": 0.0041, +} + + # Values here are from the Committee on Data for Science and Technology # (CODATA) 2018 recommendation (https://physics.nist.gov/cuu/Constants/). diff --git a/openmc/material.py b/openmc/material.py index e5c3f8e4b..5952162f6 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -3,6 +3,7 @@ from collections.abc import Iterable from copy import deepcopy from numbers import Real from pathlib import Path +import math import re import warnings from xml.etree import ElementTree as ET @@ -705,6 +706,21 @@ class Material(IDManagerMixin): def make_isotropic_in_lab(self): self.isotropic = [x.name for x in self._nuclides] + + def get_activity(self): + """Returns the total activity of the material in Becquerels.""" + + atoms_per_barn_cm2 = self.get_nuclide_atom_densities() + total_activity = 0 + for key, value in atoms_per_barn_cm2.items(): + if key in openmc.data.HALF_LIFE.keys(): + atoms = value[1] * self.volume * 1e24 + activity = 0.693 * atoms / openmc.data.HALF_LIFE[key] + print('activity', activity) + total_activity += activity + + return total_activity + def get_elements(self): """Returns all elements in the material From 5bf60560afa3f7036a928395fd26bded949bfffb Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 8 Jun 2022 17:31:30 +0100 Subject: [PATCH 0384/2654] removed import math --- openmc/material.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index 5952162f6..fc1fd1646 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -3,7 +3,6 @@ from collections.abc import Iterable from copy import deepcopy from numbers import Real from pathlib import Path -import math import re import warnings from xml.etree import ElementTree as ET From 47e242551d23a2285e3353b8a91b1efd91c66740 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 8 Jun 2022 17:34:10 +0100 Subject: [PATCH 0385/2654] using math to get ln(2) --- openmc/material.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index fc1fd1646..b62ba4142 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -3,6 +3,7 @@ from collections.abc import Iterable from copy import deepcopy from numbers import Real from pathlib import Path +import math import re import warnings from xml.etree import ElementTree as ET @@ -714,7 +715,7 @@ class Material(IDManagerMixin): for key, value in atoms_per_barn_cm2.items(): if key in openmc.data.HALF_LIFE.keys(): atoms = value[1] * self.volume * 1e24 - activity = 0.693 * atoms / openmc.data.HALF_LIFE[key] + activity = math.log(2) * atoms / openmc.data.HALF_LIFE[key] print('activity', activity) total_activity += activity From a4661fdca84807af15e19f125f4db30bcbeaca98 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 8 Jun 2022 17:39:40 +0100 Subject: [PATCH 0386/2654] [skip ci] removed print statement --- openmc/material.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index b62ba4142..a9f5afac8 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -716,7 +716,6 @@ class Material(IDManagerMixin): if key in openmc.data.HALF_LIFE.keys(): atoms = value[1] * self.volume * 1e24 activity = math.log(2) * atoms / openmc.data.HALF_LIFE[key] - print('activity', activity) total_activity += activity return total_activity From 9dc84fdb1859c73886b1f7596f30d3f6b9fa2cc9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 9 Jun 2022 01:17:46 -0500 Subject: [PATCH 0387/2654] Always normalize distributions when sampling. Adding normalization method for tabular. --- openmc/stats/univariate.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 120dc62b6..df1a72150 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -890,12 +890,17 @@ class Tabular(Univariate): c = np.zeros_like(self.x) x = np.asarray(self.x) p = np.asarray(self.p) + if self.interpolation == 'histogram': c[1:] = p[:-1] * np.diff(x) elif self.interpolation == 'linear-linear': c[1:] = 0.5 * (p[0:-1] + p[1:]) * np.diff(x) + return np.cumsum(c) + def normalize(self): + self.p = self.p / self.cdf().max() + def sample(self, n_samples=1, seed=None): if not self.interpolation in ('histogram', 'linear-linear'): raise NotImplementedError('Can only sample tabular distributions ' @@ -904,6 +909,9 @@ class Tabular(Univariate): np.random.seed(seed) xi = np.random.rand(n_samples) cdf = self.cdf() + cdf /= cdf.max() + # always use normalized probabilities when sampling + p = self.p / cdf.max() # get CDF bins that are above the # sampled values @@ -918,7 +926,7 @@ class Tabular(Univariate): # the random number is less than the next cdf # entry x_i = np.array([self.x[i] for i in cdf_idx]) - p_i = np.array([self.p[i] for i in cdf_idx]) + p_i = np.array([p[i] for i in cdf_idx]) # TODO: check that probability doesn't exceed the last value @@ -936,7 +944,7 @@ class Tabular(Univariate): # get variable and probability values for the # next entry x_i1 = np.array([self.x[i+1] for i in cdf_idx]) - p_i1 = np.array([self.p[i+1] for i in cdf_idx]) + p_i1 = np.array([p[i+1] for i in cdf_idx]) # compute slope between entries m = (p_i1 - p_i) / (x_i1 - x_i) # set values for zero slope @@ -944,9 +952,9 @@ class Tabular(Univariate): m[zero] = x_i[zero] + (xi[zero] - c_i[zero]) / p_i[zero] # set values for non-zero slope non_zero = ~zero - quad = np.power(p_i[non_zero], 2) + 2. * m[non_zero] * (xi[non_zero] - c_i[non_zero]) + quad = np.power(p_i[non_zero], 2) + 2.0 * m[non_zero] * (xi[non_zero] - c_i[non_zero]) quad[quad < 0.0] = 0.0 - m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i[non_zero]) / m[non_zero] + m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i[non_zero]) / m[non_zero] return m def to_xml_element(self, element_name): From 85b6566fd74c9c082ee943dd8d64a8138a119259 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 9 Jun 2022 01:18:17 -0500 Subject: [PATCH 0388/2654] Updating tabular means. Removing re-defined functions --- tests/unit_tests/test_stats.py | 174 +++++++++++++++++---------------- 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index a3b5cfafb..f847970c0 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -26,6 +26,20 @@ def test_discrete(): assert d2.p == [1.0] assert len(d2) == 1 + vals = np.array([1.0, 2.0, 3.0]) + probs = np.array([0.1, 0.7, 0.2]) + + exp_mean = (vals * probs).sum() + + d3 = openmc.stats.Discrete(vals, probs) + + # sample discrete distribution + n_samples = 1_000_000 + samples = d3.sample(n_samples, seed=100) + # check that the mean of the samples is close to the true mean + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + + def test_merge_discrete(): x1 = [0.0, 1.0, 10.0] @@ -65,9 +79,14 @@ def test_uniform(): assert t.p == [1/(b-a), 1/(b-a)] assert t.interpolation == 'histogram' + exp_mean = 0.5 * (a + b) + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + def test_powerlaw(): - a, b, n = 10.0, 20.0, 2.0 + a, b, n = 10.0, 100.0, 2.0 d = openmc.stats.PowerLaw(a, b, n) elem = d.to_xml_element('distribution') @@ -77,6 +96,13 @@ def test_powerlaw(): assert d.n == n assert len(d) == 3 + exp_mean = 100.0 * (n+1) / (n+2) + + # sample power law distribution + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + def test_maxwell(): theta = 1.2895e6 @@ -87,6 +113,14 @@ def test_maxwell(): assert d.theta == theta assert len(d) == 1 + exp_mean = 3/2 * theta + + # sample maxwell distribution + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + + def test_watt(): a, b = 0.965e6, 2.29e-6 @@ -98,19 +132,68 @@ def test_watt(): assert d.b == b assert len(d) == 2 + d = openmc.stats.Watt(a, b) + + # mean value form adapted from + # "Prompt-fission-neutron average energy for 238U(n, f ) from + # threshold to 200 MeV" Ethvignot et. al. + # https://doi.org/10.1016/j.physletb.2003.09.048 + exp_mean = 3/2 * a + a**2 * b / 4 + + # sample Watt distribution + n_samples = 1_000_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(exp_mean, rel=1e-03) + def test_tabular(): - x = [0.0, 5.0, 7.0] - p = [0.1, 0.2, 0.05] + x = np.array([0.0, 5.0, 7.0]) + p = np.array([0.1, 0.2, 0.05]) d = openmc.stats.Tabular(x, p, 'linear-linear') elem = d.to_xml_element('distribution') d = openmc.stats.Tabular.from_xml_element(elem) - assert d.x == x - assert d.p == p + assert all(d.x == x) + assert all(d.p == p) assert d.interpolation == 'linear-linear' assert len(d) == len(x) + # test linear-lienar sampling + d = openmc.stats.Tabular(x, p) + + # compute the expected value (mean) of the + # piecewise pdf + mean = 0.0 + d.normalize() + for i in range(1, len(x)): + y_min = d.p[i-1] + y_max = d.p[i] + x_min = d.x[i-1] + x_max = d.x[i] + + m = (y_max - y_min) / (x_max - x_min) + + exp_val = (1./3.) * m * (x_max**3 - x_min**3) + exp_val += 0.5 * m * x_min * (x_min**2 - x_max**2) + exp_val += 0.5 * y_min * (x_max**2 - x_min**2) + + mean += exp_val + + n_samples = 100_000 + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(mean, rel=1e-03) + + # test histogram sampling + d = openmc.stats.Tabular(x, p, interpolation='histogram') + d.normalize() + + mean = 0.5 * (x[:-1] + x[1:]) + mean *= np.diff(d.cdf()) + mean = sum(mean) + + samples = d.sample(n_samples, seed=100) + assert samples.mean() == pytest.approx(mean, rel=1e-03) + def test_legendre(): # Pu239 elastic scattering at 100 keV @@ -254,87 +337,6 @@ def test_point(): assert d.xyz == pytest.approx(p) -def test_discrete(): - - vals = np.array([1.0, 2.0, 3.0]) - probs = np.array([0.1, 0.7, 0.2]) - - exp_mean = (vals * probs).sum() - - d = openmc.stats.Discrete(vals, probs) - - # sample discrete distribution - n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) - # check that the mean of the samples is close to the true mean - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) - - -def test_uniform(): - - lower = 1.1 - upper = 23.3 - - exp_mean = 0.5 * (lower + upper) - - d = openmc.stats.Uniform(lower, upper) - - # sample the uniform distribution - n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) - - -def test_power_law(): - - lower = 0.0 - upper = 1.0 - exponent = 2.0 - - d = openmc.stats.PowerLaw(lower, upper, exponent) - - exp_mean = (exponent + 1) / (exponent + 2) - - # sample power law distribution - n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) - - -def test_maxwell(): - theta = 1000 - - exp_mean = 0 - - d = openmc.stats.Maxwell(theta) - - exp_mean = 3/2 * theta - - # sample maxwell distribution - n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) - -def test_watt(): - - a = 10 - b = 20 - - d = openmc.stats.Watt(a, b) - - # mean value form adapted from - # "Prompt-fission-neutron average energy for 238U(n, f ) from - # threshold to 200 MeV" Ethvignot et. al. - # https://doi.org/10.1016/j.physletb.2003.09.048 - exp_mean = 3/2 * a + a**2 * b / 4 - - # sample Watt distribution - n_samples = 100_000 - samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) - - - def test_normal(): mean = 10.0 std_dev = 2.0 From 1e83df9dc1d6709cfcb181fb818f6e7e28bb85d0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 9 Jun 2022 01:20:30 -0500 Subject: [PATCH 0389/2654] Removing re-defined distribution --- tests/unit_tests/test_stats.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index f847970c0..8e38a7b48 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -132,8 +132,6 @@ def test_watt(): assert d.b == b assert len(d) == 2 - d = openmc.stats.Watt(a, b) - # mean value form adapted from # "Prompt-fission-neutron average energy for 238U(n, f ) from # threshold to 200 MeV" Ethvignot et. al. From e1fd9959bc3aeb9d69005d5e5e971d11b441850f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 9 Jun 2022 08:00:17 -0500 Subject: [PATCH 0390/2654] A little cleanup --- openmc/stats/univariate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index df1a72150..d733b6193 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -566,7 +566,7 @@ class Watt(Univariate): w = Maxwell.sample_maxwell(self.a, n_samples) u = np.random.uniform(-1., 1., n_samples) aab = self.a * self.a * self.b - return w + 0.25*aab + u * np.sqrt(aab*w) + return w + 0.25*aab + u*np.sqrt(aab*w) def to_xml_element(self, element_name): """Return XML representation of the Watt distribution @@ -769,7 +769,7 @@ class Muir(Univariate): return np.sqrt(4.*self.e0*self.kt/self.m_rat) def sample(self, n_samples=1, seed=None): - # https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS + # Based on LANL report LA-05411-MS np.random.seed(seed) return np.random.normal(self.e0, self.std_dev, n_samples) @@ -899,7 +899,7 @@ class Tabular(Univariate): return np.cumsum(c) def normalize(self): - self.p = self.p / self.cdf().max() + self.p = np.asarray(self.p) / self.cdf().max() def sample(self, n_samples=1, seed=None): if not self.interpolation in ('histogram', 'linear-linear'): From 1234e0b17c4443b5602eda59125945fab610412b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Jun 2022 14:59:28 +0100 Subject: [PATCH 0391/2654] review suggestions from @PaulRomano --- openmc/data/data.py | 3602 +---------------------------- openmc/data/half_life.json | 3563 ++++++++++++++++++++++++++++ openmc/material.py | 36 +- tests/unit_tests/test_material.py | 18 + 4 files changed, 3636 insertions(+), 3583 deletions(-) create mode 100644 openmc/data/half_life.json diff --git a/openmc/data/data.py b/openmc/data/data.py index 48a98dedd..65702f7a5 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -1,10 +1,10 @@ import itertools -from math import sqrt +import json import os import re +from math import sqrt from warnings import warn - # Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions # of the elements 2013 (IUPAC Technical Report)", Pure. Appl. Chem. 88 (3), # pp. 293-306 (2013). The "representative isotopic abundance" values from @@ -177,3571 +177,6 @@ ATOMIC_SYMBOL = {0: 'n', 1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 118: 'Og'} ATOMIC_NUMBER = {value: key for key, value in ATOMIC_SYMBOL.items()} -# Half life values are from ENDF/B VII.1 and have units of seconds -HALF_LIFE = { - "H3": 388789600.0, - "H4": 9.90652e-23, - "H5": 7.99473e-23, - "H6": 2.84812e-22, - "H7": 2.3e-23, - "He5": 7.595e-22, - "He6": 0.8067, - "He7": 3.038e-21, - "He8": 0.1191, - "He9": 7e-21, - "He10": 1.519e-21, - "Li4": 7.55721e-23, - "Li5": 3.06868e-22, - "Li8": 0.838, - "Li9": 0.1783, - "Li10": 2e-21, - "Li11": 0.00859, - "Li12": 1e-08, - "Be5": 1e-09, - "Be6": 4.95326e-21, - "Be8": 8.18132e-17, - "Be10": 47652000000000.0, - "Be11": 13.81, - "Be12": 0.0213, - "Be13": 2.7e-21, - "Be14": 0.00435, - "Be15": 2e-07, - "Be16": 2e-07, - "B6": 1e-09, - "B7": 3.255e-22, - "B8": 0.77, - "B9": 8.43888e-19, - "B12": 0.0202, - "B13": 0.01736, - "B14": 0.0125, - "B15": 0.00993, - "B16": 1.9e-10, - "B17": 0.00508, - "B18": 2.6e-08, - "B19": 0.00292, - "C8": 1.9813e-21, - "C9": 0.1265, - "C10": 19.29, - "C11": 1223.1, - "C14": 179878000000.0, - "C15": 2.449, - "C16": 0.747, - "C17": 0.193, - "C18": 0.092, - "C19": 0.049, - "C20": 0.0145, - "C21": 3e-08, - "C22": 0.0062, - "N10": 2e-22, - "N11": 3.12742e-22, - "N12": 0.011, - "N13": 597.9, - "N16": 7.13, - "N17": 4.171, - "N18": 0.624, - "N19": 0.271, - "N20": 0.13, - "N21": 0.085, - "N22": 0.024, - "N23": 0.0145, - "N24": 5.2e-08, - "N25": 2.6e-07, - "O12": 1.13925e-21, - "O13": 0.00858, - "O14": 70.606, - "O15": 122.24, - "O19": 26.88, - "O20": 13.51, - "O21": 3.42, - "O22": 2.25, - "O23": 0.0905, - "O24": 0.065, - "O25": 5e-08, - "O26": 4e-08, - "O27": 2.6e-07, - "O28": 1e-07, - "F14": 5.0007e-22, - "F15": 4.557e-22, - "F16": 1.13925e-20, - "F17": 64.49, - "F18": 6586.2, - "F20": 11.163, - "F21": 4.158, - "F22": 4.23, - "F23": 2.23, - "F24": 0.39, - "F25": 0.05, - "F26": 0.0096, - "F27": 0.005, - "F28": 4e-08, - "F29": 0.0025, - "F30": 2.6e-07, - "F31": 2.5e-07, - "Ne16": 3.73524e-21, - "Ne17": 0.1092, - "Ne18": 1.672, - "Ne19": 17.22, - "Ne23": 37.24, - "Ne24": 202.8, - "Ne25": 0.602, - "Ne26": 0.197, - "Ne27": 0.032, - "Ne28": 0.0189, - "Ne29": 0.0148, - "Ne30": 0.0073, - "Ne31": 0.0034, - "Ne32": 0.0035, - "Ne33": 1.8e-07, - "Ne34": 6e-08, - "Na18": 1.3e-21, - "Na19": 4e-08, - "Na20": 0.4479, - "Na21": 22.49, - "Na22": 82134970.0, - "Na24": 53989.2, - "Na24_m1": 0.02018, - "Na25": 59.1, - "Na26": 1.077, - "Na27": 0.301, - "Na28": 0.0305, - "Na29": 0.0449, - "Na30": 0.048, - "Na31": 0.017, - "Na32": 0.0132, - "Na33": 0.008, - "Na34": 0.0055, - "Na35": 0.0015, - "Na36": 1.8e-07, - "Na37": 6e-08, - "Mg19": 4e-12, - "Mg20": 0.0908, - "Mg21": 0.122, - "Mg22": 3.8755, - "Mg23": 11.317, - "Mg27": 567.48, - "Mg28": 75294.0, - "Mg29": 1.3, - "Mg30": 0.335, - "Mg31": 0.232, - "Mg32": 0.086, - "Mg33": 0.0905, - "Mg34": 0.02, - "Mg35": 0.07, - "Mg36": 0.0039, - "Mg37": 2.6e-07, - "Mg38": 2.6e-07, - "Mg39": 1.8e-07, - "Mg40": 1.7e-07, - "Al21": 3.5e-08, - "Al22": 0.059, - "Al23": 0.47, - "Al24": 2.053, - "Al24_m1": 0.13, - "Al25": 7.183, - "Al26": 22626800000000.0, - "Al26_m1": 6.3452, - "Al28": 134.484, - "Al29": 393.6, - "Al30": 3.62, - "Al31": 0.644, - "Al32": 0.033, - "Al33": 0.0417, - "Al34": 0.042, - "Al35": 0.0386, - "Al36": 0.09, - "Al37": 0.0107, - "Al38": 0.0076, - "Al39": 7.6e-06, - "Al40": 2.6e-07, - "Al41": 2.6e-07, - "Al42": 1.7e-07, - "Si22": 0.029, - "Si23": 0.0423, - "Si24": 0.14, - "Si25": 0.22, - "Si26": 2.234, - "Si27": 4.16, - "Si31": 9438.0, - "Si32": 4828310000.0, - "Si33": 6.11, - "Si34": 2.77, - "Si35": 0.78, - "Si36": 0.45, - "Si37": 0.09, - "Si38": 1e-06, - "Si39": 0.0475, - "Si40": 0.033, - "Si41": 0.02, - "Si42": 0.0125, - "Si43": 6e-08, - "Si44": 3.6e-07, - "P24": 0.0074, - "P25": 3e-08, - "P26": 0.0437, - "P27": 0.26, - "P28": 0.2703, - "P29": 4.142, - "P30": 149.88, - "P32": 1232323.0, - "P33": 2189376.0, - "P34": 12.43, - "P35": 47.3, - "P36": 5.6, - "P37": 2.31, - "P38": 0.64, - "P39": 0.28, - "P40": 0.125, - "P41": 0.1, - "P42": 0.0485, - "P43": 0.0365, - "P44": 0.0185, - "P45": 2e-07, - "P46": 2e-07, - "S26": 0.01, - "S27": 0.0155, - "S28": 0.125, - "S29": 0.187, - "S30": 1.178, - "S31": 2.572, - "S35": 7560864.0, - "S37": 303.0, - "S38": 10218.0, - "S39": 11.5, - "S40": 8.8, - "S41": 1.99, - "S42": 1.013, - "S43": 0.28, - "S44": 0.1, - "S45": 0.068, - "S46": 0.05, - "S48": 2e-07, - "S49": 2e-07, - "Cl28": 0.0017, - "Cl29": 2e-08, - "Cl30": 3e-08, - "Cl31": 0.15, - "Cl32": 0.298, - "Cl33": 2.511, - "Cl34": 1.5264, - "Cl34_m1": 1920.0, - "Cl36": 9498840000000.0, - "Cl38": 2233.8, - "Cl38_m1": 0.715, - "Cl39": 3336.0, - "Cl40": 81.0, - "Cl41": 38.4, - "Cl42": 6.8, - "Cl43": 3.13, - "Cl44": 0.56, - "Cl45": 0.413, - "Cl46": 0.232, - "Cl47": 0.101, - "Cl48": 2e-07, - "Cl49": 1.7e-07, - "Cl50": 0.02, - "Cl51": 2e-07, - "Ar30": 2e-08, - "Ar31": 0.0151, - "Ar32": 0.098, - "Ar33": 0.173, - "Ar34": 0.8445, - "Ar35": 1.775, - "Ar37": 3027456.0, - "Ar39": 8488990000.0, - "Ar41": 6576.6, - "Ar42": 1038250000.0, - "Ar43": 322.2, - "Ar44": 712.2, - "Ar45": 21.48, - "Ar46": 8.4, - "Ar47": 1.23, - "Ar48": 0.475, - "Ar49": 0.17, - "Ar50": 0.085, - "Ar51": 2e-07, - "Ar52": 0.01, - "Ar53": 0.003, - "K32": 0.0033, - "K33": 2.5e-08, - "K34": 2.5e-08, - "K35": 0.178, - "K36": 0.342, - "K37": 1.226, - "K38": 458.16, - "K38_m1": 0.924, - "K40": 3.93839e16, - "K42": 44496.0, - "K43": 80280.0, - "K44": 1327.8, - "K45": 1068.6, - "K46": 105.0, - "K47": 17.5, - "K48": 6.8, - "K49": 1.26, - "K50": 0.472, - "K51": 0.365, - "K52": 0.105, - "K53": 0.03, - "K54": 0.01, - "K55": 0.003, - "Ca34": 3.5e-08, - "Ca35": 0.0257, - "Ca36": 0.102, - "Ca37": 0.1811, - "Ca38": 0.44, - "Ca39": 0.8596, - "Ca41": 3218880000000.0, - "Ca45": 14049500.0, - "Ca47": 391910.4, - "Ca48": 7.25824e26, - "Ca49": 523.08, - "Ca50": 13.9, - "Ca51": 10.0, - "Ca52": 4.6, - "Ca53": 0.09, - "Ca54": 0.086, - "Ca55": 0.022, - "Ca56": 0.01, - "Ca57": 0.005, - "Sc36": 0.0088, - "Sc37": 0.056, - "Sc38": 0.0423, - "Sc39": 3e-07, - "Sc40": 0.1823, - "Sc41": 0.5963, - "Sc42": 0.6808, - "Sc42_m1": 62.0, - "Sc43": 14007.6, - "Sc44": 14292.0, - "Sc44_m1": 210996.0, - "Sc45_m1": 0.318, - "Sc46": 7239456.0, - "Sc46_m1": 18.75, - "Sc47": 289370.9, - "Sc48": 157212.0, - "Sc49": 3430.8, - "Sc50": 102.5, - "Sc50_m1": 0.35, - "Sc51": 12.4, - "Sc52": 8.2, - "Sc53": 3.0, - "Sc54": 0.36, - "Sc55": 0.105, - "Sc56": 0.06, - "Sc57": 0.013, - "Sc58": 0.012, - "Sc59": 0.01, - "Sc60": 0.003, - "Ti38": 1.2e-07, - "Ti39": 0.032, - "Ti40": 0.0533, - "Ti41": 0.0804, - "Ti42": 0.199, - "Ti43": 0.509, - "Ti44": 1893460000.0, - "Ti45": 11088.0, - "Ti51": 345.6, - "Ti52": 102.0, - "Ti53": 32.7, - "Ti54": 1.5, - "Ti55": 1.3, - "Ti56": 0.2, - "Ti57": 0.06, - "Ti58": 0.059, - "Ti59": 0.03, - "Ti60": 0.022, - "Ti61": 3e-07, - "Ti62": 0.01, - "Ti63": 0.003, - "V40": 0.0077, - "V41": 0.0244, - "V42": 5.5e-08, - "V43": 0.8, - "V44": 0.111, - "V44_m1": 0.15, - "V45": 0.547, - "V46": 0.4225, - "V46_m1": 0.00102, - "V47": 1956.0, - "V48": 1380110.0, - "V49": 28512000.0, - "V50": 4.41806e24, - "V52": 224.58, - "V53": 92.58, - "V54": 49.8, - "V55": 6.54, - "V56": 0.216, - "V57": 0.35, - "V58": 0.185, - "V59": 0.075, - "V60": 0.068, - "V61": 0.047, - "V62": 1.5e-07, - "V63": 0.017, - "V64": 0.019, - "V65": 0.01, - "Cr42": 0.014, - "Cr43": 0.0216, - "Cr44": 0.0535, - "Cr45": 0.0609, - "Cr46": 0.26, - "Cr47": 0.5, - "Cr48": 77616.0, - "Cr49": 2538.0, - "Cr51": 2393366.0, - "Cr55": 209.82, - "Cr56": 356.4, - "Cr57": 21.1, - "Cr58": 7.0, - "Cr59": 0.46, - "Cr60": 0.49, - "Cr61": 0.27, - "Cr62": 0.19, - "Cr63": 0.129, - "Cr64": 0.043, - "Cr65": 0.027, - "Cr66": 0.01, - "Cr67": 0.05, - "Mn44": 1.05e-07, - "Mn45": 7e-08, - "Mn46": 0.0345, - "Mn47": 0.1, - "Mn48": 0.1581, - "Mn49": 0.382, - "Mn50": 0.28319, - "Mn50_m1": 105.0, - "Mn51": 2772.0, - "Mn52": 483062.4, - "Mn52_m1": 1266.0, - "Mn53": 116763000000000.0, - "Mn54": 26961120.0, - "Mn56": 9284.04, - "Mn57": 85.4, - "Mn58": 3.0, - "Mn58_m1": 65.4, - "Mn59": 4.59, - "Mn60": 51.0, - "Mn60_m1": 1.77, - "Mn61": 0.67, - "Mn62": 0.671, - "Mn62_m1": 0.092, - "Mn63": 0.29, - "Mn64": 0.09, - "Mn65": 0.092, - "Mn66": 0.064, - "Mn67": 0.047, - "Mn68": 0.028, - "Mn69": 0.014, - "Fe45": 0.00203, - "Fe46": 0.013, - "Fe47": 0.0219, - "Fe48": 0.044, - "Fe49": 0.0647, - "Fe50": 0.155, - "Fe51": 0.305, - "Fe52": 29790.0, - "Fe52_m1": 45.9, - "Fe53": 510.6, - "Fe53_m1": 152.4, - "Fe55": 86594050.0, - "Fe59": 3844368.0, - "Fe60": 47336400000000.0, - "Fe61": 358.8, - "Fe62": 68.0, - "Fe63": 6.1, - "Fe64": 2.0, - "Fe65": 0.81, - "Fe65_m1": 1.12, - "Fe66": 0.44, - "Fe67": 0.416, - "Fe68": 0.187, - "Fe69": 0.109, - "Fe70": 0.094, - "Fe71": 0.028, - "Fe72": 1.5e-07, - "Co49": 3.5e-08, - "Co50": 0.044, - "Co51": 2e-07, - "Co52": 0.115, - "Co53": 0.24, - "Co53_m1": 0.247, - "Co54": 0.19328, - "Co54_m1": 88.8, - "Co55": 63108.0, - "Co56": 6672931.0, - "Co57": 23478340.0, - "Co58": 6122304.0, - "Co58_m1": 32760.0, - "Co60": 166344200.0, - "Co60_m1": 628.02, - "Co61": 5940.0, - "Co62": 90.0, - "Co62_m1": 834.6, - "Co63": 27.4, - "Co64": 0.3, - "Co65": 1.16, - "Co66": 0.2, - "Co67": 0.425, - "Co68": 0.199, - "Co68_m1": 1.6, - "Co69": 0.22, - "Co70": 0.119, - "Co70_m1": 0.5, - "Co71": 0.079, - "Co72": 0.0599, - "Co73": 0.041, - "Co74": 0.03, - "Co75": 0.034, - "Ni48": 0.0021, - "Ni49": 0.0075, - "Ni50": 0.012, - "Ni51": 2e-07, - "Ni52": 0.038, - "Ni53": 0.045, - "Ni54": 0.104, - "Ni55": 0.2047, - "Ni56": 524880.0, - "Ni57": 128160.0, - "Ni59": 2398380000000.0, - "Ni63": 3193630000.0, - "Ni65": 9061.884, - "Ni66": 196560.0, - "Ni67": 21.0, - "Ni68": 29.0, - "Ni69": 11.4, - "Ni69_m1": 3.5, - "Ni70": 6.0, - "Ni71": 2.56, - "Ni72": 1.57, - "Ni73": 0.84, - "Ni74": 0.68, - "Ni75": 0.6, - "Ni76": 0.238, - "Ni77": 0.061, - "Ni78": 0.11, - "Cu52": 0.0069, - "Cu53": 3e-07, - "Cu54": 7.5e-08, - "Cu55": 0.04, - "Cu56": 0.094, - "Cu57": 0.1963, - "Cu58": 3.204, - "Cu59": 81.5, - "Cu60": 1422.0, - "Cu61": 11998.8, - "Cu62": 580.38, - "Cu64": 45723.6, - "Cu66": 307.2, - "Cu67": 222588.0, - "Cu68": 31.1, - "Cu68_m1": 225.0, - "Cu69": 171.0, - "Cu70": 44.5, - "Cu70_m1": 33.0, - "Cu70_m2": 6.6, - "Cu71": 19.5, - "Cu72": 6.63, - "Cu73": 4.2, - "Cu74": 1.75, - "Cu75": 1.224, - "Cu76": 0.653, - "Cu76_m1": 1.27, - "Cu77": 0.469, - "Cu78": 0.335, - "Cu79": 0.188, - "Cu80": 0.17, - "Cu81": 0.028, - "Zn54": 0.0037, - "Zn55": 0.02, - "Zn56": 5e-07, - "Zn57": 0.038, - "Zn58": 0.084, - "Zn59": 0.182, - "Zn60": 142.8, - "Zn61": 89.1, - "Zn61_m1": 0.43, - "Zn61_m2": 0.14, - "Zn62": 33336.0, - "Zn63": 2308.2, - "Zn65": 21075550.0, - "Zn69": 3384.0, - "Zn69_m1": 49536.0, - "Zn71": 147.0, - "Zn71_m1": 14256.0, - "Zn72": 167400.0, - "Zn73": 23.5, - "Zn73_m1": 5.8, - "Zn73_m2": 0.013, - "Zn74": 95.6, - "Zn75": 10.2, - "Zn76": 5.7, - "Zn77": 2.08, - "Zn77_m1": 1.05, - "Zn78": 1.47, - "Zn79": 0.995, - "Zn80": 0.54, - "Zn81": 0.32, - "Zn82": 0.052, - "Zn83": 0.043, - "Ga56": 0.0059, - "Ga57": 0.0123, - "Ga58": 0.0152, - "Ga59": 0.0418, - "Ga60": 0.07, - "Ga61": 0.168, - "Ga62": 0.11612, - "Ga63": 32.4, - "Ga64": 157.62, - "Ga65": 912.0, - "Ga66": 34164.0, - "Ga67": 281810.9, - "Ga68": 4062.6, - "Ga70": 1268.4, - "Ga72": 50760.0, - "Ga72_m1": 0.03968, - "Ga73": 17496.0, - "Ga74": 487.2, - "Ga74_m1": 9.5, - "Ga75": 126.0, - "Ga76": 32.6, - "Ga77": 13.2, - "Ga78": 5.09, - "Ga79": 2.847, - "Ga80": 1.676, - "Ga81": 1.217, - "Ga82": 0.599, - "Ga83": 0.3081, - "Ga84": 0.085, - "Ga85": 0.048, - "Ga86": 0.029, - "Ge58": 0.0152, - "Ge59": 0.0418, - "Ge60": 0.03, - "Ge61": 0.039, - "Ge62": 1.5e-07, - "Ge63": 0.142, - "Ge64": 63.7, - "Ge65": 30.9, - "Ge66": 8136.0, - "Ge67": 1134.0, - "Ge68": 23410080.0, - "Ge69": 140580.0, - "Ge71": 987552.0, - "Ge71_m1": 0.02041, - "Ge73_m1": 0.499, - "Ge75": 4966.8, - "Ge75_m1": 47.7, - "Ge77": 40680.0, - "Ge77_m1": 52.9, - "Ge78": 5280.0, - "Ge79": 18.98, - "Ge79_m1": 39.0, - "Ge80": 29.5, - "Ge81": 7.6, - "Ge81_m1": 7.6, - "Ge82": 4.56, - "Ge83": 1.85, - "Ge84": 0.954, - "Ge85": 0.535, - "Ge86": 0.095, - "Ge87": 0.14, - "Ge88": 0.066, - "Ge89": 0.039, - "As60": 0.0083, - "As61": 0.0166, - "As62": 0.0259, - "As63": 0.0921, - "As64": 0.036, - "As65": 0.128, - "As66": 0.09579, - "As67": 42.5, - "As68": 151.6, - "As69": 913.8, - "As70": 3156.0, - "As71": 235080.0, - "As72": 93600.0, - "As73": 6937920.0, - "As74": 1535328.0, - "As75_m1": 0.01762, - "As76": 94464.0, - "As77": 139788.0, - "As78": 5442.0, - "As79": 540.6, - "As80": 15.2, - "As81": 33.3, - "As82": 19.1, - "As82_m1": 13.6, - "As83": 13.4, - "As84": 4.2, - "As85": 2.021, - "As86": 0.945, - "As87": 0.56, - "As88": 0.112, - "As89": 0.059, - "As90": 0.043, - "As91": 0.044, - "As92": 0.027, - "Se65": 0.05, - "Se66": 0.033, - "Se67": 0.136, - "Se68": 35.5, - "Se69": 27.4, - "Se70": 2466.0, - "Se71": 284.4, - "Se72": 725760.0, - "Se73": 25740.0, - "Se73_m1": 2388.0, - "Se75": 10349860.0, - "Se77_m1": 17.36, - "Se79": 9309490000000.0, - "Se79_m1": 235.2, - "Se81": 1107.0, - "Se81_m1": 3436.8, - "Se83": 1338.0, - "Se83_m1": 70.1, - "Se84": 195.6, - "Se85": 31.7, - "Se86": 14.3, - "Se87": 5.5, - "Se88": 1.53, - "Se89": 0.41, - "Se90": 0.161, - "Se91": 0.27, - "Se92": 0.093, - "Se93": 0.062, - "Se94": 0.059, - "Br67": 0.0443, - "Br68": 1.2e-06, - "Br69": 2.4e-08, - "Br70": 0.0791, - "Br70_m1": 2.2, - "Br71": 21.4, - "Br72": 78.6, - "Br72_m1": 10.6, - "Br73": 204.0, - "Br74": 1524.0, - "Br74_m1": 2760.0, - "Br75": 5802.0, - "Br76": 58320.0, - "Br76_m1": 1.31, - "Br77": 205329.6, - "Br77_m1": 256.8, - "Br78": 387.0, - "Br79_m1": 4.86, - "Br80": 1060.8, - "Br80_m1": 15913.8, - "Br82": 127015.2, - "Br82_m1": 367.8, - "Br83": 8640.0, - "Br84": 1905.6, - "Br84_m1": 360.0, - "Br85": 174.0, - "Br86": 55.0, - "Br87": 55.65, - "Br88": 16.29, - "Br89": 4.4, - "Br90": 1.92, - "Br91": 0.541, - "Br92": 0.343, - "Br93": 0.102, - "Br94": 0.07, - "Br95": 0.066, - "Br96": 0.042, - "Br97": 0.04, - "Kr69": 0.032, - "Kr70": 0.052, - "Kr71": 0.1, - "Kr72": 17.1, - "Kr73": 27.3, - "Kr74": 690.0, - "Kr75": 257.4, - "Kr76": 53280.0, - "Kr77": 4464.0, - "Kr79": 126144.0, - "Kr79_m1": 50.0, - "Kr81": 7226690000000.0, - "Kr81_m1": 13.1, - "Kr83_m1": 6588.0, - "Kr85": 339433500.0, - "Kr85_m1": 16128.0, - "Kr87": 4578.0, - "Kr88": 10224.0, - "Kr89": 189.0, - "Kr90": 32.32, - "Kr91": 8.57, - "Kr92": 1.84, - "Kr93": 1.286, - "Kr94": 0.212, - "Kr95": 0.114, - "Kr96": 0.08, - "Kr97": 0.063, - "Kr98": 0.046, - "Kr99": 0.027, - "Kr100": 0.007, - "Rb71": 1e-09, - "Rb72": 1.2e-06, - "Rb73": 3e-08, - "Rb74": 0.064776, - "Rb75": 19.0, - "Rb76": 36.5, - "Rb77": 226.2, - "Rb78": 1059.6, - "Rb78_m1": 344.4, - "Rb79": 1374.0, - "Rb80": 34.0, - "Rb81": 16459.2, - "Rb81_m1": 1830.0, - "Rb82": 75.45, - "Rb82_m1": 23299.2, - "Rb83": 7447680.0, - "Rb84": 2835648.0, - "Rb84_m1": 1215.6, - "Rb86": 1609718.0, - "Rb86_m1": 61.02, - "Rb87": 1.51792e18, - "Rb88": 1066.38, - "Rb89": 909.0, - "Rb90": 158.0, - "Rb90_m1": 258.0, - "Rb91": 58.4, - "Rb92": 4.492, - "Rb93": 5.84, - "Rb94": 2.702, - "Rb95": 0.3777, - "Rb96": 0.203, - "Rb97": 0.1691, - "Rb98": 0.114, - "Rb98_m1": 0.096, - "Rb99": 0.054, - "Rb100": 0.051, - "Rb101": 0.032, - "Rb102": 0.037, - "Sr73": 0.025, - "Sr74": 1.2e-06, - "Sr75": 0.088, - "Sr76": 7.89, - "Sr77": 9.0, - "Sr78": 150.0, - "Sr79": 135.0, - "Sr80": 6378.0, - "Sr81": 1338.0, - "Sr82": 2190240.0, - "Sr83": 116676.0, - "Sr83_m1": 4.95, - "Sr85": 5602176.0, - "Sr85_m1": 4057.8, - "Sr87_m1": 10134.0, - "Sr89": 4365792.0, - "Sr90": 908543300.0, - "Sr91": 34668.0, - "Sr92": 9756.0, - "Sr93": 445.38, - "Sr94": 75.3, - "Sr95": 23.9, - "Sr96": 1.07, - "Sr97": 0.429, - "Sr98": 0.653, - "Sr99": 0.27, - "Sr100": 0.202, - "Sr101": 0.118, - "Sr102": 0.069, - "Sr103": 0.068, - "Sr104": 0.043, - "Sr105": 0.0556, - "Y76": 2e-07, - "Y77": 0.062, - "Y78": 0.05, - "Y78_m1": 5.7, - "Y79": 14.8, - "Y80": 30.1, - "Y80_m1": 4.8, - "Y81": 70.4, - "Y82": 8.3, - "Y83": 424.8, - "Y83_m1": 171.0, - "Y84": 2370.0, - "Y84_m1": 4.6, - "Y85": 9648.0, - "Y85_m1": 17496.0, - "Y86": 53064.0, - "Y86_m1": 2880.0, - "Y87": 287280.0, - "Y87_m1": 48132.0, - "Y88": 9212486.0, - "Y88_m1": 0.000301, - "Y88_m2": 0.01397, - "Y89_m1": 15.663, - "Y90": 230400.0, - "Y90_m1": 11484.0, - "Y91": 5055264.0, - "Y91_m1": 2982.6, - "Y92": 12744.0, - "Y93": 36648.0, - "Y93_m1": 0.82, - "Y94": 1122.0, - "Y95": 618.0, - "Y96": 5.34, - "Y96_m1": 9.6, - "Y97": 3.75, - "Y97_m1": 1.17, - "Y97_m2": 0.142, - "Y98": 0.548, - "Y98_m1": 2.0, - "Y99": 1.47, - "Y100": 0.735, - "Y100_m1": 0.94, - "Y101": 0.45, - "Y102": 0.36, - "Y102_m1": 0.298, - "Y103": 0.23, - "Y104": 0.18, - "Y105": 0.088, - "Y106": 0.066, - "Y107": 0.03, - "Y108": 0.048, - "Zr78": 2e-07, - "Zr79": 0.056, - "Zr80": 4.6, - "Zr81": 5.5, - "Zr82": 32.0, - "Zr83": 41.6, - "Zr84": 1554.0, - "Zr85": 471.6, - "Zr85_m1": 10.9, - "Zr86": 59400.0, - "Zr87": 6048.0, - "Zr87_m1": 14.0, - "Zr88": 7205760.0, - "Zr89": 282276.0, - "Zr89_m1": 249.66, - "Zr90_m1": 0.8092, - "Zr93": 48283100000000.0, - "Zr95": 5532365.0, - "Zr96": 6.31152e26, - "Zr97": 60296.4, - "Zr98": 30.7, - "Zr99": 2.1, - "Zr100": 7.1, - "Zr101": 2.3, - "Zr102": 2.9, - "Zr103": 1.3, - "Zr104": 1.2, - "Zr105": 0.6, - "Zr106": 0.27, - "Zr107": 0.15, - "Zr108": 0.08, - "Zr109": 0.117, - "Zr110": 0.098, - "Nb81": 0.8, - "Nb82": 0.05, - "Nb83": 4.1, - "Nb84": 9.8, - "Nb85": 20.9, - "Nb85_m1": 3.3, - "Nb86": 88.0, - "Nb87": 225.0, - "Nb87_m1": 156.0, - "Nb88": 873.0, - "Nb88_m1": 466.8, - "Nb89": 7308.0, - "Nb89_m1": 3960.0, - "Nb90": 52560.0, - "Nb90_m1": 18.81, - "Nb90_m2": 0.00619, - "Nb91": 21459200000.0, - "Nb91_m1": 5258304.0, - "Nb92": 1095050000000000.0, - "Nb92_m1": 876960.0, - "Nb93_m1": 509024100.0, - "Nb94": 640619000000.0, - "Nb94_m1": 375.78, - "Nb95": 3023222.0, - "Nb95_m1": 311904.0, - "Nb96": 84060.0, - "Nb97": 4326.0, - "Nb97_m1": 58.7, - "Nb98": 2.86, - "Nb98_m1": 3078.0, - "Nb99": 15.0, - "Nb99_m1": 150.0, - "Nb100": 1.5, - "Nb100_m1": 2.99, - "Nb101": 7.1, - "Nb102": 4.3, - "Nb102_m1": 1.3, - "Nb103": 1.5, - "Nb104": 4.9, - "Nb104_m1": 0.94, - "Nb105": 2.95, - "Nb106": 0.93, - "Nb107": 0.3, - "Nb108": 0.193, - "Nb109": 0.19, - "Nb110": 0.17, - "Nb111": 0.08, - "Nb112": 0.069, - "Nb113": 0.03, - "Mo83": 0.0195, - "Mo84": 3.8, - "Mo85": 3.2, - "Mo86": 19.6, - "Mo87": 14.02, - "Mo88": 480.0, - "Mo89": 126.6, - "Mo89_m1": 0.19, - "Mo90": 20412.0, - "Mo91": 929.4, - "Mo91_m1": 64.6, - "Mo93": 126230000000.0, - "Mo93_m1": 24660.0, - "Mo99": 237513.6, - "Mo100": 2.3037e26, - "Mo101": 876.6, - "Mo102": 678.0, - "Mo103": 67.5, - "Mo104": 60.0, - "Mo105": 35.6, - "Mo106": 8.73, - "Mo107": 3.5, - "Mo108": 1.09, - "Mo109": 0.53, - "Mo110": 0.3, - "Mo111": 0.2, - "Mo112": 0.287, - "Mo113": 0.1, - "Mo114": 0.08, - "Mo115": 0.092, - "Tc85": 0.5, - "Tc86": 0.054, - "Tc86_m1": 1.1e-06, - "Tc87": 2.2, - "Tc88": 5.8, - "Tc88_m1": 6.4, - "Tc89": 12.8, - "Tc89_m1": 12.9, - "Tc90": 8.7, - "Tc90_m1": 49.2, - "Tc91": 188.4, - "Tc91_m1": 198.0, - "Tc92": 255.0, - "Tc93": 9900.0, - "Tc93_m1": 2610.0, - "Tc94": 17580.0, - "Tc94_m1": 3120.0, - "Tc95": 72000.0, - "Tc95_m1": 5270400.0, - "Tc96": 369792.0, - "Tc96_m1": 3090.0, - "Tc97": 132857000000000.0, - "Tc97_m1": 7862400.0, - "Tc98": 132542000000000.0, - "Tc99": 6661810000000.0, - "Tc99_m1": 21624.12, - "Tc100": 15.46, - "Tc101": 852.0, - "Tc102": 5.28, - "Tc102_m1": 261.0, - "Tc103": 54.2, - "Tc104": 1098.0, - "Tc105": 456.0, - "Tc106": 35.6, - "Tc107": 21.2, - "Tc108": 5.17, - "Tc109": 0.86, - "Tc110": 0.92, - "Tc111": 0.29, - "Tc112": 0.28, - "Tc113": 0.16, - "Tc114": 0.15, - "Tc115": 0.073, - "Tc116": 0.09, - "Tc117": 0.04, - "Tc118": 0.066, - "Ru87": 1.5e-06, - "Ru88": 1.25, - "Ru89": 1.5, - "Ru90": 11.7, - "Ru91": 7.9, - "Ru91_m1": 7.6, - "Ru92": 219.0, - "Ru93": 59.7, - "Ru93_m1": 10.8, - "Ru94": 3108.0, - "Ru95": 5914.8, - "Ru97": 244512.0, - "Ru103": 3390941.0, - "Ru103_m1": 0.00169, - "Ru105": 15984.0, - "Ru106": 32123520.0, - "Ru107": 225.0, - "Ru108": 273.0, - "Ru109": 34.5, - "Ru110": 11.6, - "Ru111": 2.12, - "Ru112": 1.75, - "Ru113": 0.8, - "Ru113_m1": 0.51, - "Ru114": 0.52, - "Ru115": 0.74, - "Ru116": 0.204, - "Ru117": 0.142, - "Ru118": 0.123, - "Ru119": 0.162, - "Ru120": 0.149, - "Rh89": 1.5e-06, - "Rh90": 0.0145, - "Rh90_m1": 1.05, - "Rh91": 1.47, - "Rh92": 4.66, - "Rh93": 11.9, - "Rh94": 70.6, - "Rh94_m1": 25.8, - "Rh95": 301.2, - "Rh95_m1": 117.6, - "Rh96": 594.0, - "Rh96_m1": 90.6, - "Rh97": 1842.0, - "Rh97_m1": 2772.0, - "Rh98": 523.2, - "Rh98_m1": 216.0, - "Rh99": 1391040.0, - "Rh99_m1": 16920.0, - "Rh100": 74880.0, - "Rh100_m1": 276.0, - "Rh101": 104140100.0, - "Rh101_m1": 374976.0, - "Rh102": 17910720.0, - "Rh102_m1": 118088500.0, - "Rh103_m1": 3366.84, - "Rh104": 42.3, - "Rh104_m1": 260.4, - "Rh105": 127296.0, - "Rh105_m1": 40.0, - "Rh106": 30.07, - "Rh106_m1": 7860.0, - "Rh107": 1302.0, - "Rh108": 16.8, - "Rh108_m1": 360.0, - "Rh109": 80.0, - "Rh110": 3.2, - "Rh110_m1": 28.5, - "Rh111": 11.0, - "Rh112": 2.1, - "Rh112_m1": 6.73, - "Rh113": 2.8, - "Rh114": 1.85, - "Rh115": 0.99, - "Rh116": 0.68, - "Rh116_m1": 0.57, - "Rh117": 0.44, - "Rh118": 0.266, - "Rh119": 0.171, - "Rh120": 0.136, - "Rh121": 0.151, - "Rh122": 0.108, - "Rh123": 0.0489, - "Pd91": 1e-06, - "Pd92": 0.8, - "Pd93": 1.3, - "Pd94": 9.0, - "Pd95": 10.0, - "Pd95_m1": 13.3, - "Pd96": 122.0, - "Pd97": 186.0, - "Pd98": 1062.0, - "Pd99": 1284.0, - "Pd100": 313632.0, - "Pd101": 30492.0, - "Pd103": 1468022.0, - "Pd107": 205124000000000.0, - "Pd107_m1": 21.3, - "Pd109": 49324.32, - "Pd109_m1": 281.4, - "Pd111": 1404.0, - "Pd111_m1": 19800.0, - "Pd112": 75708.0, - "Pd113": 93.0, - "Pd113_m1": 0.3, - "Pd114": 145.2, - "Pd115": 25.0, - "Pd115_m1": 50.0, - "Pd116": 11.8, - "Pd117": 4.3, - "Pd117_m1": 0.0191, - "Pd118": 1.9, - "Pd119": 0.92, - "Pd120": 0.5, - "Pd121": 0.285, - "Pd122": 0.175, - "Pd123": 0.244, - "Pd124": 0.038, - "Pd125": 0.3987, - "Pd126": 0.2499, - "Ag93": 1.5e-06, - "Ag94": 0.035, - "Ag94_m1": 0.55, - "Ag94_m2": 0.4, - "Ag95": 2.0, - "Ag95_m1": 0.5, - "Ag95_m2": 0.016, - "Ag95_m3": 0.04, - "Ag96": 4.4, - "Ag96_m1": 6.9, - "Ag97": 25.5, - "Ag98": 47.5, - "Ag99": 124.0, - "Ag99_m1": 10.5, - "Ag100": 120.6, - "Ag100_m1": 134.4, - "Ag101": 666.0, - "Ag101_m1": 3.1, - "Ag102": 774.0, - "Ag102_m1": 462.0, - "Ag103": 3942.0, - "Ag103_m1": 5.7, - "Ag104": 4152.0, - "Ag104_m1": 2010.0, - "Ag105": 3567456.0, - "Ag105_m1": 433.8, - "Ag106": 1437.6, - "Ag106_m1": 715392.0, - "Ag107_m1": 44.3, - "Ag108": 142.92, - "Ag108_m1": 13822200000.0, - "Ag109_m1": 39.6, - "Ag110": 24.6, - "Ag110_m1": 21579260.0, - "Ag111": 643680.0, - "Ag111_m1": 64.8, - "Ag112": 11268.0, - "Ag113": 19332.0, - "Ag113_m1": 68.7, - "Ag114": 4.6, - "Ag114_m1": 0.0015, - "Ag115": 1200.0, - "Ag115_m1": 18.0, - "Ag116": 237.0, - "Ag116_m1": 20.0, - "Ag116_m2": 9.3, - "Ag117": 72.8, - "Ag117_m1": 5.34, - "Ag118": 3.76, - "Ag118_m1": 2.0, - "Ag119": 2.1, - "Ag119_m1": 6.0, - "Ag120": 1.23, - "Ag120_m1": 0.32, - "Ag121": 0.78, - "Ag122": 0.529, - "Ag122_m1": 0.2, - "Ag123": 0.3, - "Ag124": 0.172, - "Ag125": 0.166, - "Ag126": 0.107, - "Ag127": 0.109, - "Ag128": 0.058, - "Ag129": 0.046, - "Ag130": 0.05, - "Cd95": 0.005, - "Cd96": 1.0, - "Cd97": 2.8, - "Cd98": 9.2, - "Cd99": 16.0, - "Cd100": 49.1, - "Cd101": 81.6, - "Cd102": 330.0, - "Cd103": 438.0, - "Cd104": 3462.0, - "Cd105": 3330.0, - "Cd107": 23400.0, - "Cd109": 39864960.0, - "Cd111_m1": 2912.4, - "Cd113": 2.53723e23, - "Cd113_m1": 444962200.0, - "Cd115": 192456.0, - "Cd115_m1": 3849984.0, - "Cd116": 9.78286e26, - "Cd117": 8964.0, - "Cd117_m1": 12096.0, - "Cd118": 3018.0, - "Cd119": 161.4, - "Cd119_m1": 132.0, - "Cd120": 50.8, - "Cd121": 13.5, - "Cd121_m1": 8.3, - "Cd122": 5.24, - "Cd123": 2.1, - "Cd123_m1": 1.82, - "Cd124": 1.25, - "Cd125": 0.68, - "Cd125_m1": 0.48, - "Cd126": 0.515, - "Cd127": 0.37, - "Cd128": 0.28, - "Cd129": 0.27, - "Cd130": 0.162, - "Cd131": 0.068, - "Cd132": 0.097, - "In97": 0.005, - "In98": 0.0425, - "In98_m1": 1.6, - "In99": 3.05, - "In100": 5.9, - "In101": 15.1, - "In102": 23.3, - "In103": 65.0, - "In103_m1": 34.0, - "In104": 108.0, - "In104_m1": 15.7, - "In105": 304.2, - "In105_m1": 48.0, - "In106": 372.0, - "In106_m1": 312.0, - "In107": 1944.0, - "In107_m1": 50.4, - "In108": 3480.0, - "In108_m1": 2376.0, - "In109": 15001.2, - "In109_m1": 80.4, - "In109_m2": 0.209, - "In110": 17640.0, - "In110_m1": 4146.0, - "In111": 242326.1, - "In111_m1": 462.0, - "In112": 898.2, - "In112_m1": 1233.6, - "In113_m1": 5968.56, - "In114": 71.9, - "In114_m1": 4277664.0, - "In114_m2": 0.0431, - "In115": 1.39169e22, - "In115_m1": 16149.6, - "In116": 14.1, - "In116_m1": 3257.4, - "In116_m2": 2.18, - "In117": 2592.0, - "In117_m1": 6972.0, - "In118": 5.0, - "In118_m1": 267.0, - "In118_m2": 8.5, - "In119": 144.0, - "In119_m1": 1080.0, - "In120": 3.08, - "In120_m1": 46.2, - "In120_m2": 47.3, - "In121": 23.1, - "In121_m1": 232.8, - "In122": 1.5, - "In122_m1": 10.3, - "In122_m2": 10.8, - "In123": 6.17, - "In123_m1": 47.4, - "In124": 3.12, - "In124_m1": 3.7, - "In125": 2.36, - "In125_m1": 12.2, - "In126": 1.53, - "In126_m1": 1.64, - "In127": 1.09, - "In127_m1": 3.67, - "In128": 0.84, - "In128_m1": 0.72, - "In129": 0.61, - "In129_m1": 1.23, - "In130": 0.29, - "In130_m1": 0.54, - "In130_m2": 0.54, - "In131": 0.28, - "In131_m1": 0.35, - "In131_m2": 0.32, - "In132": 0.207, - "In133": 0.165, - "In133_m1": 0.18, - "In134": 0.14, - "In135": 0.092, - "Sn99": 0.005, - "Sn100": 0.86, - "Sn101": 1.7, - "Sn102": 4.5, - "Sn103": 7.0, - "Sn104": 20.8, - "Sn105": 34.0, - "Sn106": 115.0, - "Sn107": 174.0, - "Sn108": 618.0, - "Sn109": 1080.0, - "Sn110": 14796.0, - "Sn111": 2118.0, - "Sn113": 9943776.0, - "Sn113_m1": 1284.0, - "Sn117_m1": 1175040.0, - "Sn119_m1": 25315200.0, - "Sn121": 97308.0, - "Sn121_m1": 1385380000.0, - "Sn123": 11162880.0, - "Sn123_m1": 2403.6, - "Sn125": 832896.0, - "Sn125_m1": 571.2, - "Sn126": 7258250000000.0, - "Sn127": 7560.0, - "Sn127_m1": 247.8, - "Sn128": 3544.2, - "Sn128_m1": 6.5, - "Sn129": 133.8, - "Sn129_m1": 414.0, - "Sn130": 223.2, - "Sn130_m1": 102.0, - "Sn131": 56.0, - "Sn131_m1": 58.4, - "Sn132": 39.7, - "Sn133": 1.46, - "Sn134": 1.05, - "Sn135": 0.53, - "Sn136": 0.25, - "Sn137": 0.19, - "Sb103": 1.5e-06, - "Sb104": 0.46, - "Sb105": 1.22, - "Sb106": 0.6, - "Sb107": 4.0, - "Sb108": 7.4, - "Sb109": 17.0, - "Sb110": 23.0, - "Sb111": 75.0, - "Sb112": 51.4, - "Sb113": 400.2, - "Sb114": 209.4, - "Sb115": 1926.0, - "Sb116": 948.0, - "Sb116_m1": 3618.0, - "Sb117": 10080.0, - "Sb118": 216.0, - "Sb118_m1": 18000.0, - "Sb119": 137484.0, - "Sb119_m1": 0.85, - "Sb120": 953.4, - "Sb120_m1": 497664.0, - "Sb122": 235336.3, - "Sb122_m1": 251.46, - "Sb124": 5201280.0, - "Sb124_m1": 93.0, - "Sb124_m2": 1212.0, - "Sb125": 87053530.0, - "Sb126": 1067040.0, - "Sb126_m1": 1149.0, - "Sb126_m2": 11.0, - "Sb127": 332640.0, - "Sb128": 32436.0, - "Sb128_m1": 624.0, - "Sb129": 15840.0, - "Sb129_m1": 1062.0, - "Sb130": 2370.0, - "Sb130_m1": 378.0, - "Sb131": 1381.8, - "Sb132": 167.4, - "Sb132_m1": 246.0, - "Sb133": 150.0, - "Sb134": 0.78, - "Sb134_m1": 10.07, - "Sb135": 1.679, - "Sb136": 0.923, - "Sb137": 0.45, - "Sb138": 0.168, - "Sb139": 0.127, - "Te105": 6.2e-07, - "Te106": 6e-05, - "Te107": 0.0031, - "Te108": 2.1, - "Te109": 4.6, - "Te110": 18.6, - "Te111": 19.3, - "Te112": 120.0, - "Te113": 102.0, - "Te114": 912.0, - "Te115": 348.0, - "Te115_m1": 402.0, - "Te116": 8964.0, - "Te117": 3720.0, - "Te117_m1": 0.103, - "Te118": 518400.0, - "Te119": 57780.0, - "Te119_m1": 406080.0, - "Te121": 1656288.0, - "Te121_m1": 14186880.0, - "Te123_m1": 10298880.0, - "Te125_m1": 4959360.0, - "Te127": 33660.0, - "Te127_m1": 9417600.0, - "Te128": 2.77707e26, - "Te129": 4176.0, - "Te129_m1": 2903040.0, - "Te131": 1500.0, - "Te131_m1": 119700.0, - "Te132": 276825.6, - "Te133": 750.0, - "Te133_m1": 3324.0, - "Te134": 2508.0, - "Te135": 19.0, - "Te136": 17.5, - "Te137": 2.49, - "Te138": 1.4, - "Te139": 0.347, - "Te140": 0.304, - "Te141": 0.213, - "Te142": 0.2, - "I108": 0.036, - "I109": 0.000103, - "I110": 0.65, - "I111": 2.5, - "I112": 3.42, - "I113": 6.6, - "I114": 2.1, - "I114_m1": 6.2, - "I115": 78.0, - "I116": 2.91, - "I117": 133.2, - "I118": 822.0, - "I118_m1": 510.0, - "I119": 1146.0, - "I120": 4896.0, - "I120_m1": 3180.0, - "I121": 7632.0, - "I122": 217.8, - "I123": 47604.24, - "I124": 360806.4, - "I125": 5132160.0, - "I126": 1117152.0, - "I128": 1499.4, - "I129": 495454000000000.0, - "I130": 44496.0, - "I130_m1": 530.4, - "I131": 693377.3, - "I132": 8262.0, - "I132_m1": 4993.2, - "I133": 74880.0, - "I133_m1": 9.0, - "I134": 3150.0, - "I134_m1": 211.2, - "I135": 23652.0, - "I136": 83.4, - "I136_m1": 46.9, - "I137": 24.5, - "I138": 6.23, - "I139": 2.28, - "I140": 0.86, - "I141": 0.43, - "I142": 0.222, - "I143": 0.296, - "I144": 0.194, - "I145": 0.127, - "Xe110": 0.093, - "Xe111": 0.81, - "Xe112": 2.7, - "Xe113": 2.74, - "Xe114": 10.0, - "Xe115": 18.0, - "Xe116": 59.0, - "Xe117": 61.0, - "Xe118": 228.0, - "Xe119": 348.0, - "Xe120": 2400.0, - "Xe121": 2406.0, - "Xe122": 72360.0, - "Xe123": 7488.0, - "Xe125": 60840.0, - "Xe125_m1": 56.9, - "Xe127": 3144960.0, - "Xe127_m1": 69.2, - "Xe129_m1": 767232.0, - "Xe131_m1": 1022976.0, - "Xe132_m1": 0.00839, - "Xe133": 452995.2, - "Xe133_m1": 189216.0, - "Xe134_m1": 0.29, - "Xe135": 32904.0, - "Xe135_m1": 917.4, - "Xe137": 229.08, - "Xe138": 844.8, - "Xe139": 39.68, - "Xe140": 13.6, - "Xe141": 1.73, - "Xe142": 1.23, - "Xe143": 0.3, - "Xe144": 1.15, - "Xe145": 0.188, - "Xe146": 0.369, - "Xe147": 0.1, - "Cs112": 0.0005, - "Cs113": 1.67e-05, - "Cs114": 0.57, - "Cs115": 1.4, - "Cs116": 0.7, - "Cs116_m1": 3.85, - "Cs117": 8.4, - "Cs117_m1": 6.5, - "Cs118": 14.0, - "Cs118_m1": 17.0, - "Cs119": 43.0, - "Cs119_m1": 30.4, - "Cs120": 61.3, - "Cs120_m1": 57.0, - "Cs121": 155.0, - "Cs121_m1": 122.0, - "Cs122": 21.18, - "Cs122_m1": 0.36, - "Cs122_m2": 222.0, - "Cs123": 352.8, - "Cs123_m1": 1.64, - "Cs124": 30.8, - "Cs124_m1": 6.3, - "Cs125": 2802.0, - "Cs125_m1": 0.0009, - "Cs126": 98.4, - "Cs127": 22500.0, - "Cs128": 217.2, - "Cs129": 115416.0, - "Cs130": 1752.6, - "Cs130_m1": 207.6, - "Cs131": 837129.6, - "Cs132": 559872.0, - "Cs134": 65172760.0, - "Cs134_m1": 10483.2, - "Cs135": 72582500000000.0, - "Cs135_m1": 3180.0, - "Cs136": 1137024.0, - "Cs136_m1": 19.0, - "Cs137": 949252600.0, - "Cs138": 2004.6, - "Cs138_m1": 174.6, - "Cs139": 556.2, - "Cs140": 63.7, - "Cs141": 24.84, - "Cs142": 1.684, - "Cs143": 1.791, - "Cs144": 0.994, - "Cs144_m1": 1.0, - "Cs145": 0.587, - "Cs146": 0.321, - "Cs147": 0.23, - "Cs148": 0.146, - "Cs149": 0.05, - "Cs150": 0.05, - "Cs151": 0.05, - "Ba114": 0.43, - "Ba115": 0.45, - "Ba116": 1.3, - "Ba117": 1.75, - "Ba118": 5.5, - "Ba119": 5.4, - "Ba120": 24.0, - "Ba121": 29.7, - "Ba122": 117.0, - "Ba123": 162.0, - "Ba124": 660.0, - "Ba125": 210.0, - "Ba126": 6000.0, - "Ba127": 762.0, - "Ba127_m1": 1.9, - "Ba128": 209952.0, - "Ba129": 8028.0, - "Ba129_m1": 7776.0, - "Ba130_m1": 0.0094, - "Ba131": 993600.0, - "Ba131_m1": 876.0, - "Ba133": 331862400.0, - "Ba133_m1": 140040.0, - "Ba135_m1": 103320.0, - "Ba136_m1": 0.3084, - "Ba137_m1": 153.12, - "Ba139": 4983.6, - "Ba140": 1101833.0, - "Ba141": 1096.2, - "Ba142": 636.0, - "Ba143": 14.5, - "Ba144": 11.5, - "Ba145": 4.31, - "Ba146": 2.22, - "Ba147": 0.894, - "Ba148": 0.612, - "Ba149": 0.344, - "Ba150": 0.3, - "Ba151": 0.259, - "Ba152": 0.228, - "Ba153": 0.158, - "La117": 0.0235, - "La117_m1": 0.01, - "La118": 1.0, - "La119": 2.0, - "La120": 2.8, - "La121": 5.3, - "La122": 8.6, - "La123": 17.0, - "La124": 29.21, - "La124_m1": 21.0, - "La125": 64.8, - "La125_m1": 0.4, - "La126": 54.0, - "La126_m1": 50.0, - "La127": 306.0, - "La127_m1": 222.0, - "La128": 310.8, - "La128_m1": 60.0, - "La129": 696.0, - "La129_m1": 0.56, - "La130": 522.0, - "La131": 3540.0, - "La132": 17280.0, - "La132_m1": 1458.0, - "La133": 14083.2, - "La134": 387.0, - "La135": 70200.0, - "La136": 592.2, - "La136_m1": 0.114, - "La137": 1893460000000.0, - "La138": 3.21888e18, - "La140": 145026.7, - "La141": 14112.0, - "La142": 5466.0, - "La143": 852.0, - "La144": 40.8, - "La145": 24.8, - "La146": 6.27, - "La146_m1": 10.0, - "La147": 4.06, - "La148": 1.26, - "La149": 1.05, - "La150": 0.86, - "La151": 0.778, - "La152": 0.451, - "La153": 0.342, - "La154": 0.228, - "La155": 0.184, - "Ce119": 0.2, - "Ce120": 0.25, - "Ce121": 1.1, - "Ce122": 2.73, - "Ce123": 3.8, - "Ce124": 6.0, - "Ce125": 10.2, - "Ce126": 51.0, - "Ce127": 31.0, - "Ce127_m1": 28.6, - "Ce128": 235.8, - "Ce129": 210.0, - "Ce130": 1374.0, - "Ce131": 618.0, - "Ce131_m1": 324.0, - "Ce132": 12636.0, - "Ce132_m1": 0.0094, - "Ce133": 5820.0, - "Ce133_m1": 17640.0, - "Ce134": 273024.0, - "Ce135": 63720.0, - "Ce135_m1": 20.0, - "Ce137": 32400.0, - "Ce137_m1": 123840.0, - "Ce138_m1": 0.00865, - "Ce139": 11892180.0, - "Ce139_m1": 54.8, - "Ce141": 2808691.0, - "Ce143": 118940.4, - "Ce144": 24616220.0, - "Ce145": 180.6, - "Ce146": 811.2, - "Ce147": 56.4, - "Ce148": 56.0, - "Ce149": 5.3, - "Ce150": 4.0, - "Ce151": 1.76, - "Ce152": 1.4, - "Ce153": 0.979, - "Ce154": 0.775, - "Ce155": 0.471, - "Ce156": 0.369, - "Ce157": 0.2428, - "Pr121": 1.4, - "Pr122": 0.5, - "Pr123": 0.8, - "Pr124": 1.2, - "Pr125": 3.3, - "Pr126": 3.14, - "Pr127": 4.2, - "Pr128": 2.85, - "Pr129": 32.0, - "Pr130": 40.0, - "Pr131": 90.6, - "Pr131_m1": 5.73, - "Pr132": 96.0, - "Pr133": 390.0, - "Pr134": 1020.0, - "Pr134_m1": 660.0, - "Pr135": 1440.0, - "Pr136": 786.0, - "Pr137": 4608.0, - "Pr138": 87.0, - "Pr138_m1": 7632.0, - "Pr139": 15876.0, - "Pr140": 203.4, - "Pr142": 68832.0, - "Pr142_m1": 876.0, - "Pr143": 1172448.0, - "Pr144": 1036.8, - "Pr144_m1": 432.0, - "Pr145": 21542.4, - "Pr146": 1449.0, - "Pr147": 804.0, - "Pr148": 137.4, - "Pr148_m1": 120.6, - "Pr149": 135.6, - "Pr150": 6.19, - "Pr151": 18.9, - "Pr152": 3.63, - "Pr153": 4.28, - "Pr154": 2.3, - "Pr155": 0.852, - "Pr156": 0.733, - "Pr157": 0.598, - "Pr158": 0.1342, - "Pr159": 0.1055, - "Nd124": 0.5, - "Nd125": 0.6, - "Nd126": 2e-07, - "Nd127": 1.8, - "Nd128": 5.0, - "Nd129": 4.9, - "Nd130": 21.0, - "Nd131": 26.0, - "Nd132": 94.0, - "Nd133": 70.0, - "Nd133_m1": 70.0, - "Nd134": 510.0, - "Nd135": 744.0, - "Nd135_m1": 330.0, - "Nd136": 3039.0, - "Nd137": 2310.0, - "Nd137_m1": 1.6, - "Nd138": 18144.0, - "Nd139": 1782.0, - "Nd139_m1": 19800.0, - "Nd140": 291168.0, - "Nd141": 8964.0, - "Nd141_m1": 62.0, - "Nd144": 7.22669e22, - "Nd147": 948672.0, - "Nd149": 6220.8, - "Nd150": 2.49305e26, - "Nd151": 746.4, - "Nd152": 684.0, - "Nd153": 31.6, - "Nd154": 25.9, - "Nd155": 8.9, - "Nd156": 5.49, - "Nd157": 1.906, - "Nd158": 1.331, - "Nd159": 0.773, - "Nd160": 0.5883, - "Nd161": 0.4884, - "Pm126": 0.5, - "Pm127": 1.0, - "Pm128": 1.0, - "Pm129": 2.4, - "Pm130": 2.6, - "Pm131": 6.3, - "Pm132": 6.2, - "Pm133": 15.0, - "Pm133_m1": 8.8, - "Pm134": 5.0, - "Pm134_m1": 22.0, - "Pm135": 49.0, - "Pm135_m1": 45.0, - "Pm136": 47.0, - "Pm136_m1": 107.0, - "Pm137": 144.0, - "Pm138": 10.0, - "Pm138_m1": 194.4, - "Pm139": 249.0, - "Pm139_m1": 0.18, - "Pm140": 357.0, - "Pm140_m1": 357.0, - "Pm141": 1254.0, - "Pm142": 40.5, - "Pm142_m1": 0.002, - "Pm143": 22896000.0, - "Pm144": 31363200.0, - "Pm145": 558569500.0, - "Pm146": 174513500.0, - "Pm147": 82788210.0, - "Pm148": 463795.2, - "Pm148_m1": 3567456.0, - "Pm149": 191088.0, - "Pm150": 9648.0, - "Pm151": 102240.0, - "Pm152": 247.2, - "Pm152_m1": 451.2, - "Pm152_m2": 828.0, - "Pm153": 315.0, - "Pm154": 103.8, - "Pm154_m1": 160.8, - "Pm155": 41.5, - "Pm156": 26.7, - "Pm157": 10.56, - "Pm158": 4.8, - "Pm159": 1.47, - "Pm160": 1.561, - "Pm161": 1.065, - "Pm162": 0.2679, - "Pm163": 0.2, - "Sm128": 0.5, - "Sm129": 0.55, - "Sm130": 1.0, - "Sm131": 1.2, - "Sm132": 4.0, - "Sm133": 3.7, - "Sm134": 9.5, - "Sm135": 10.3, - "Sm136": 47.0, - "Sm137": 45.0, - "Sm138": 186.0, - "Sm139": 154.2, - "Sm139_m1": 10.7, - "Sm140": 889.2, - "Sm141": 612.0, - "Sm141_m1": 1356.0, - "Sm142": 4349.4, - "Sm143": 525.0, - "Sm143_m1": 66.0, - "Sm143_m2": 0.03, - "Sm145": 29376000.0, - "Sm146": 3250430000000000.0, - "Sm147": 3.34511e18, - "Sm148": 2.20903e23, - "Sm151": 2840184000.0, - "Sm153": 167400.0, - "Sm153_m1": 0.0106, - "Sm155": 1338.0, - "Sm156": 33840.0, - "Sm157": 482.0, - "Sm158": 318.0, - "Sm159": 11.37, - "Sm160": 9.6, - "Sm161": 4.8, - "Sm162": 2.4, - "Sm163": 1.748, - "Sm164": 1.226, - "Sm165": 0.764, - "Eu130": 0.001, - "Eu131": 0.0178, - "Eu132": 0.1, - "Eu133": 1.0, - "Eu134": 0.5, - "Eu135": 1.5, - "Eu136": 3.8, - "Eu136_m1": 3.3, - "Eu136_m2": 3.8, - "Eu137": 11.0, - "Eu138": 12.1, - "Eu139": 17.9, - "Eu140": 1.51, - "Eu140_m1": 0.125, - "Eu141": 40.7, - "Eu141_m1": 2.7, - "Eu142": 2.34, - "Eu142_m1": 73.38, - "Eu143": 155.4, - "Eu144": 10.2, - "Eu145": 512352.0, - "Eu146": 396576.0, - "Eu147": 2082240.0, - "Eu148": 4708800.0, - "Eu149": 8043840.0, - "Eu150": 1164480000.0, - "Eu150_m1": 46080.0, - "Eu152": 427195200.0, - "Eu152_m1": 33521.76, - "Eu152_m2": 5760.0, - "Eu154": 271426900.0, - "Eu154_m1": 2760.0, - "Eu155": 149993300.0, - "Eu156": 1312416.0, - "Eu157": 54648.0, - "Eu158": 2754.0, - "Eu159": 1086.0, - "Eu160": 38.0, - "Eu161": 26.0, - "Eu162": 10.6, - "Eu163": 7.7, - "Eu164": 2.844, - "Eu165": 2.3, - "Eu166": 0.4, - "Eu167": 0.2, - "Gd134": 0.4, - "Gd135": 1.1, - "Gd136": 2e-05, - "Gd137": 2.2, - "Gd138": 4.7, - "Gd139": 5.8, - "Gd139_m1": 4.8, - "Gd140": 15.8, - "Gd141": 14.0, - "Gd141_m1": 24.5, - "Gd142": 70.2, - "Gd143": 39.0, - "Gd143_m1": 110.0, - "Gd144": 268.2, - "Gd145": 1380.0, - "Gd145_m1": 85.0, - "Gd146": 4170528.0, - "Gd147": 137016.0, - "Gd148": 2354197000.0, - "Gd149": 801792.0, - "Gd150": 56488100000000.0, - "Gd151": 10713600.0, - "Gd152": 3.40822e21, - "Gd153": 20770560.0, - "Gd155_m1": 0.03197, - "Gd159": 66524.4, - "Gd161": 219.6, - "Gd162": 504.0, - "Gd163": 68.0, - "Gd164": 45.0, - "Gd165": 10.3, - "Gd166": 4.8, - "Gd167": 3.0, - "Gd168": 0.3, - "Gd169": 1.0, - "Tb135": 0.995, - "Tb136": 0.2, - "Tb137": 0.6, - "Tb138": 2e-07, - "Tb139": 1.6, - "Tb140": 2.4, - "Tb141": 3.5, - "Tb141_m1": 7.9, - "Tb142": 0.597, - "Tb142_m1": 0.303, - "Tb143": 12.0, - "Tb143_m1": 21.0, - "Tb144": 1.0, - "Tb144_m1": 4.25, - "Tb145": 30.9, - "Tb145_m1": 30.9, - "Tb146": 8.0, - "Tb146_m1": 23.0, - "Tb146_m2": 0.00118, - "Tb147": 5904.0, - "Tb147_m1": 109.8, - "Tb148": 3600.0, - "Tb148_m1": 132.0, - "Tb149": 14824.8, - "Tb149_m1": 249.6, - "Tb150": 12528.0, - "Tb150_m1": 348.0, - "Tb151": 63392.4, - "Tb151_m1": 25.0, - "Tb152": 63000.0, - "Tb152_m1": 252.0, - "Tb153": 202176.0, - "Tb154": 77400.0, - "Tb154_m1": 33840.0, - "Tb154_m2": 81720.0, - "Tb155": 459648.0, - "Tb156": 462240.0, - "Tb156_m1": 87840.0, - "Tb156_m2": 19080.0, - "Tb157": 2240590000.0, - "Tb158": 5680368000.0, - "Tb158_m1": 10.7, - "Tb160": 6246720.0, - "Tb161": 596678.4, - "Tb162": 456.0, - "Tb163": 1170.0, - "Tb164": 180.0, - "Tb165": 126.6, - "Tb166": 25.1, - "Tb167": 19.4, - "Tb168": 8.2, - "Tb169": 2.0, - "Tb170": 3.0, - "Tb171": 0.5, - "Dy138": 0.2, - "Dy139": 0.6, - "Dy140": 0.84, - "Dy141": 0.9, - "Dy142": 2.3, - "Dy143": 3.2, - "Dy143_m1": 3.0, - "Dy144": 9.1, - "Dy145": 6.0, - "Dy145_m1": 14.1, - "Dy146": 29.0, - "Dy146_m1": 0.15, - "Dy147": 40.0, - "Dy147_m1": 55.7, - "Dy148": 198.0, - "Dy149": 252.0, - "Dy149_m1": 0.49, - "Dy150": 430.2, - "Dy151": 1074.0, - "Dy152": 8568.0, - "Dy153": 23040.0, - "Dy154": 94672800000000.0, - "Dy155": 35640.0, - "Dy157": 29304.0, - "Dy157_m1": 0.0216, - "Dy159": 12476160.0, - "Dy165": 8402.4, - "Dy165_m1": 75.42, - "Dy166": 293760.0, - "Dy167": 372.0, - "Dy168": 522.0, - "Dy169": 39.0, - "Dy170": 30.0, - "Dy171": 6.0, - "Dy172": 3.0, - "Dy173": 2.0, - "Ho140": 0.006, - "Ho141": 0.0041, - "Ho142": 0.4, - "Ho143": 2e-07, - "Ho144": 0.7, - "Ho145": 2.4, - "Ho146": 3.6, - "Ho147": 5.8, - "Ho148": 2.2, - "Ho148_m1": 9.59, - "Ho148_m2": 0.00236, - "Ho149": 21.1, - "Ho149_m1": 56.0, - "Ho150": 72.0, - "Ho150_m1": 23.3, - "Ho151": 35.2, - "Ho151_m1": 47.2, - "Ho152": 161.8, - "Ho152_m1": 50.0, - "Ho153": 120.6, - "Ho153_m1": 558.0, - "Ho154": 705.6, - "Ho154_m1": 186.0, - "Ho155": 2880.0, - "Ho155_m1": 0.00088, - "Ho156": 3360.0, - "Ho156_m1": 9.5, - "Ho156_m2": 468.0, - "Ho157": 756.0, - "Ho158": 678.0, - "Ho158_m1": 1680.0, - "Ho158_m2": 1278.0, - "Ho159": 1983.0, - "Ho159_m1": 8.3, - "Ho160": 1536.0, - "Ho160_m1": 18072.0, - "Ho160_m2": 3.0, - "Ho161": 8928.0, - "Ho161_m1": 6.76, - "Ho162": 900.0, - "Ho162_m1": 4020.0, - "Ho163": 144218000000.0, - "Ho163_m1": 1.09, - "Ho164": 1740.0, - "Ho164_m1": 2250.0, - "Ho166": 96480.0, - "Ho166_m1": 37869100000.0, - "Ho167": 11160.0, - "Ho168": 179.4, - "Ho168_m1": 132.0, - "Ho169": 283.2, - "Ho170": 165.6, - "Ho170_m1": 43.0, - "Ho171": 53.0, - "Ho172": 25.0, - "Ho173": 10.0, - "Ho174": 8.0, - "Ho175": 5.0, - "Er143": 0.2, - "Er144": 2e-07, - "Er146": 1.7, - "Er147": 2.5, - "Er147_m1": 2.5, - "Er148": 4.6, - "Er149": 4.0, - "Er149_m1": 8.9, - "Er150": 18.5, - "Er151": 23.5, - "Er151_m1": 0.58, - "Er152": 10.3, - "Er153": 37.1, - "Er154": 223.8, - "Er155": 318.0, - "Er156": 1170.0, - "Er157": 1119.0, - "Er157_m1": 0.076, - "Er158": 8244.0, - "Er159": 2160.0, - "Er160": 102888.0, - "Er161": 11556.0, - "Er163": 4500.0, - "Er165": 37296.0, - "Er167_m1": 2.269, - "Er169": 811468.8, - "Er171": 27057.6, - "Er172": 177480.0, - "Er173": 84.0, - "Er174": 192.0, - "Er175": 72.0, - "Er176": 20.0, - "Er177": 3.0, - "Tm145": 3.1e-06, - "Tm146": 0.08, - "Tm146_m1": 0.2, - "Tm147": 0.58, - "Tm148": 0.7, - "Tm149": 0.9, - "Tm150": 2.2, - "Tm150_m1": 0.0052, - "Tm151": 4.17, - "Tm151_m1": 4.51e-07, - "Tm152": 8.0, - "Tm152_m1": 5.2, - "Tm153": 1.48, - "Tm153_m1": 2.5, - "Tm154": 8.1, - "Tm154_m1": 3.3, - "Tm155": 21.6, - "Tm155_m1": 45.0, - "Tm156": 83.8, - "Tm157": 217.8, - "Tm158": 238.8, - "Tm159": 547.8, - "Tm160": 564.0, - "Tm160_m1": 74.5, - "Tm161": 1812.0, - "Tm162": 1302.0, - "Tm162_m1": 24.3, - "Tm163": 6516.0, - "Tm164": 120.0, - "Tm164_m1": 306.0, - "Tm165": 108216.0, - "Tm166": 27720.0, - "Tm166_m1": 0.34, - "Tm167": 799200.0, - "Tm168": 8043840.0, - "Tm170": 11111040.0, - "Tm171": 60590590.0, - "Tm172": 228960.0, - "Tm173": 29664.0, - "Tm174": 324.0, - "Tm175": 912.0, - "Tm176": 114.0, - "Tm177": 90.0, - "Tm178": 30.0, - "Tm179": 20.0, - "Yb148": 0.25, - "Yb149": 0.7, - "Yb150": 2e-07, - "Yb151": 1.6, - "Yb151_m1": 1.6, - "Yb152": 3.04, - "Yb153": 4.2, - "Yb154": 0.409, - "Yb155": 1.793, - "Yb156": 26.1, - "Yb157": 38.6, - "Yb158": 89.4, - "Yb159": 100.2, - "Yb160": 288.0, - "Yb161": 252.0, - "Yb162": 1132.2, - "Yb163": 663.0, - "Yb164": 4548.0, - "Yb165": 594.0, - "Yb166": 204120.0, - "Yb167": 1050.0, - "Yb169": 2766355.0, - "Yb169_m1": 46.0, - "Yb171_m1": 0.00525, - "Yb175": 361584.0, - "Yb175_m1": 0.0682, - "Yb176_m1": 11.4, - "Yb177": 6879.6, - "Yb177_m1": 6.41, - "Yb178": 4440.0, - "Yb179": 480.0, - "Yb180": 144.0, - "Yb181": 60.0, - "Lu150": 0.043, - "Lu151": 0.0806, - "Lu152": 0.7, - "Lu153": 0.9, - "Lu153_m1": 1.0, - "Lu154": 2.0, - "Lu154_m1": 1.12, - "Lu155": 0.068, - "Lu155_m1": 0.138, - "Lu155_m2": 0.00269, - "Lu156": 0.494, - "Lu156_m1": 0.198, - "Lu157": 6.8, - "Lu157_m1": 4.79, - "Lu158": 10.6, - "Lu159": 12.1, - "Lu160": 36.1, - "Lu160_m1": 40.0, - "Lu161": 77.0, - "Lu161_m1": 0.0073, - "Lu162": 82.2, - "Lu162_m1": 90.0, - "Lu162_m2": 114.0, - "Lu163": 238.2, - "Lu164": 188.4, - "Lu165": 644.4, - "Lu166": 159.0, - "Lu166_m1": 84.6, - "Lu166_m2": 127.2, - "Lu167": 3090.0, - "Lu167_m1": 60.0, - "Lu168": 330.0, - "Lu168_m1": 402.0, - "Lu169": 122616.0, - "Lu169_m1": 160.0, - "Lu170": 173836.8, - "Lu170_m1": 0.67, - "Lu171": 711936.0, - "Lu171_m1": 79.0, - "Lu172": 578880.0, - "Lu172_m1": 222.0, - "Lu173": 43233910.0, - "Lu174": 104455700.0, - "Lu174_m1": 12268800.0, - "Lu176": 1.18657e18, - "Lu176_m1": 13086.0, - "Lu177": 574300.8, - "Lu177_m1": 13862020.0, - "Lu177_m2": 390.0, - "Lu178": 1704.0, - "Lu178_m1": 1386.0, - "Lu179": 16524.0, - "Lu179_m1": 0.0031, - "Lu180": 342.0, - "Lu180_m1": 0.001, - "Lu181": 210.0, - "Lu182": 120.0, - "Lu183": 58.0, - "Lu184": 20.0, - "Hf153": 6e-06, - "Hf154": 2.0, - "Hf155": 0.89, - "Hf156": 0.023, - "Hf157": 0.11, - "Hf158": 2.85, - "Hf159": 5.6, - "Hf160": 13.6, - "Hf161": 18.2, - "Hf162": 39.4, - "Hf163": 40.0, - "Hf164": 111.0, - "Hf165": 76.0, - "Hf166": 406.2, - "Hf167": 123.0, - "Hf168": 1557.0, - "Hf169": 194.4, - "Hf170": 57636.0, - "Hf171": 43560.0, - "Hf171_m1": 29.5, - "Hf172": 59012710.0, - "Hf173": 84960.0, - "Hf174": 6.31152e22, - "Hf175": 6048000.0, - "Hf177_m1": 1.09, - "Hf177_m2": 3084.0, - "Hf178_m1": 4.0, - "Hf178_m2": 978285600.0, - "Hf179_m1": 18.67, - "Hf179_m2": 2164320.0, - "Hf180_m1": 19800.0, - "Hf181": 3662496.0, - "Hf182": 280863000000000.0, - "Hf182_m1": 3690.0, - "Hf183": 3841.2, - "Hf184": 14832.0, - "Hf184_m1": 48.0, - "Hf185": 210.0, - "Hf186": 156.0, - "Hf187": 30.0, - "Hf188": 20.0, - "Ta155": 0.0031, - "Ta156": 0.144, - "Ta156_m1": 0.36, - "Ta157": 0.0101, - "Ta157_m1": 0.0043, - "Ta157_m2": 0.0017, - "Ta158": 0.055, - "Ta158_m1": 0.0367, - "Ta159": 0.83, - "Ta159_m1": 0.515, - "Ta160": 1.55, - "Ta160_m1": 1.7, - "Ta161": 2.89, - "Ta162": 3.57, - "Ta163": 10.6, - "Ta164": 14.2, - "Ta165": 31.0, - "Ta166": 34.4, - "Ta167": 80.0, - "Ta168": 120.0, - "Ta169": 294.0, - "Ta170": 405.6, - "Ta171": 1398.0, - "Ta172": 2208.0, - "Ta173": 11304.0, - "Ta174": 4104.0, - "Ta175": 37800.0, - "Ta176": 29124.0, - "Ta176_m1": 0.0011, - "Ta176_m2": 0.00097, - "Ta177": 203616.0, - "Ta178": 558.6, - "Ta178_m1": 8496.0, - "Ta178_m2": 0.058, - "Ta179": 57434830.0, - "Ta179_m1": 0.009, - "Ta179_m2": 0.0541, - "Ta180": 29354.4, - "Ta182": 9913536.0, - "Ta182_m1": 0.283, - "Ta182_m2": 950.4, - "Ta183": 440640.0, - "Ta184": 31320.0, - "Ta185": 2964.0, - "Ta185_m1": 0.002, - "Ta186": 630.0, - "Ta187": 120.0, - "Ta188": 20.0, - "Ta189": 3.0, - "Ta190": 0.3, - "W158": 0.00125, - "W159": 0.0073, - "W160": 0.091, - "W161": 0.409, - "W162": 1.36, - "W163": 2.8, - "W164": 6.3, - "W165": 5.1, - "W166": 19.2, - "W167": 19.9, - "W168": 53.0, - "W169": 74.0, - "W170": 145.2, - "W171": 142.8, - "W172": 396.0, - "W173": 456.0, - "W174": 1992.0, - "W175": 2112.0, - "W176": 9000.0, - "W177": 7920.0, - "W178": 1866240.0, - "W179": 2223.0, - "W179_m1": 384.0, - "W180": 5.68037e25, - "W180_m1": 0.00547, - "W181": 10471680.0, - "W183_m1": 5.2, - "W185": 6488640.0, - "W185_m1": 100.2, - "W186": 5.36e27, - "W186_m1": 0.003, - "W187": 86400.0, - "W188": 6028992.0, - "W189": 642.0, - "W190": 1800.0, - "W190_m1": 0.0031, - "W191": 20.0, - "W192": 10.0, - "Re160": 0.00085, - "Re161": 0.00037, - "Re161_m1": 0.0156, - "Re162": 0.107, - "Re162_m1": 0.077, - "Re163": 0.39, - "Re163_m1": 0.214, - "Re164": 0.53, - "Re164_m1": 0.87, - "Re165": 1.0, - "Re165_m1": 2.1, - "Re166": 2.25, - "Re167": 5.9, - "Re167_m1": 3.4, - "Re168": 4.4, - "Re169": 8.1, - "Re169_m1": 15.1, - "Re170": 9.2, - "Re171": 15.2, - "Re172": 55.0, - "Re172_m1": 15.0, - "Re173": 118.8, - "Re174": 144.0, - "Re175": 353.4, - "Re176": 318.0, - "Re177": 840.0, - "Re178": 792.0, - "Re179": 1170.0, - "Re180": 146.4, - "Re181": 71640.0, - "Re182": 230400.0, - "Re182_m1": 45720.0, - "Re183": 6048000.0, - "Re183_m1": 0.00104, - "Re184": 3058560.0, - "Re184_m1": 14601600.0, - "Re186": 321261.1, - "Re186_m1": 6311520000000.0, - "Re187": 1.36644e18, - "Re188": 61214.4, - "Re188_m1": 1115.4, - "Re189": 87480.0, - "Re190": 186.0, - "Re190_m1": 11520.0, - "Re191": 588.0, - "Re192": 16.0, - "Re193": 51.9, - "Re194": 1.0, - "Os162": 0.00205, - "Os163": 0.0055, - "Os164": 0.021, - "Os165": 0.071, - "Os166": 0.199, - "Os167": 0.81, - "Os168": 2.1, - "Os169": 3.43, - "Os170": 7.37, - "Os171": 8.3, - "Os172": 19.2, - "Os173": 22.4, - "Os174": 44.0, - "Os175": 84.0, - "Os176": 216.0, - "Os177": 180.0, - "Os178": 300.0, - "Os179": 390.0, - "Os180": 1290.0, - "Os181": 6300.0, - "Os181_m1": 162.0, - "Os182": 78624.0, - "Os183": 46800.0, - "Os183_m1": 35640.0, - "Os185": 8087040.0, - "Os186": 6.31152e22, - "Os189_m1": 20916.0, - "Os190_m1": 594.0, - "Os191": 1330560.0, - "Os191_m1": 47160.0, - "Os192_m1": 5.9, - "Os193": 108396.0, - "Os194": 189345600.0, - "Os195": 540.0, - "Os196": 2094.0, - "Ir164": 0.14, - "Ir164_m1": 9.5e-05, - "Ir165": 1e-06, - "Ir166": 0.0105, - "Ir166_m1": 0.0151, - "Ir167": 0.0352, - "Ir167_m1": 0.0257, - "Ir168": 0.232, - "Ir168_m1": 0.16, - "Ir169": 0.64, - "Ir169_m1": 0.281, - "Ir170": 0.9, - "Ir170_m1": 0.811, - "Ir171": 3.5, - "Ir171_m1": 1.4, - "Ir172": 4.4, - "Ir172_m1": 2.0, - "Ir173": 9.0, - "Ir173_m1": 2.2, - "Ir174": 7.9, - "Ir174_m1": 4.9, - "Ir175": 9.0, - "Ir176": 8.7, - "Ir177": 30.0, - "Ir178": 12.0, - "Ir179": 79.0, - "Ir180": 90.0, - "Ir181": 294.0, - "Ir182": 900.0, - "Ir183": 3480.0, - "Ir184": 11124.0, - "Ir185": 51840.0, - "Ir186": 59904.0, - "Ir186_m1": 6840.0, - "Ir187": 37800.0, - "Ir187_m1": 0.0303, - "Ir188": 149400.0, - "Ir188_m1": 0.0042, - "Ir189": 1140480.0, - "Ir189_m1": 0.0133, - "Ir189_m2": 0.0037, - "Ir190": 1017792.0, - "Ir190_m1": 4032.0, - "Ir190_m2": 11113.2, - "Ir191_m1": 4.899, - "Ir191_m2": 5.5, - "Ir192": 6378653.0, - "Ir192_m1": 87.0, - "Ir192_m2": 7605382000.0, - "Ir193_m1": 909792.0, - "Ir194": 69408.0, - "Ir194_m1": 0.03185, - "Ir194_m2": 14774400.0, - "Ir195": 9000.0, - "Ir195_m1": 13680.0, - "Ir196": 52.0, - "Ir196_m1": 5040.0, - "Ir197": 348.0, - "Ir197_m1": 534.0, - "Ir198": 8.0, - "Ir199": 6.5, - "Pt166": 0.0003, - "Pt167": 0.00078, - "Pt168": 0.002, - "Pt169": 0.007, - "Pt170": 0.014, - "Pt171": 0.051, - "Pt172": 0.096, - "Pt173": 0.382, - "Pt174": 0.889, - "Pt175": 2.53, - "Pt176": 6.33, - "Pt177": 10.6, - "Pt178": 21.1, - "Pt179": 21.2, - "Pt180": 56.0, - "Pt181": 52.0, - "Pt182": 180.0, - "Pt183": 390.0, - "Pt183_m1": 43.0, - "Pt184": 1038.0, - "Pt184_m1": 0.00101, - "Pt185": 4254.0, - "Pt185_m1": 1980.0, - "Pt186": 7488.0, - "Pt187": 8460.0, - "Pt188": 881280.0, - "Pt189": 39132.0, - "Pt190": 2.05124e19, - "Pt191": 242092.8, - "Pt193": 1577880000.0, - "Pt193_m1": 374112.0, - "Pt195_m1": 346464.0, - "Pt197": 71609.4, - "Pt197_m1": 5724.6, - "Pt199": 1848.0, - "Pt199_m1": 13.6, - "Pt200": 45360.0, - "Pt201": 150.0, - "Pt202": 158400.0, - "Au169": 0.00015, - "Au170": 0.000291, - "Au170_m1": 0.00062, - "Au171": 1.9e-05, - "Au171_m1": 0.00102, - "Au172": 0.0047, - "Au173": 0.025, - "Au173_m1": 0.014, - "Au174": 0.139, - "Au174_m1": 0.1629, - "Au175": 0.1, - "Au175_m1": 0.156, - "Au176": 1.05, - "Au176_m1": 1.36, - "Au177": 1.462, - "Au177_m1": 1.18, - "Au178": 2.6, - "Au179": 3.3, - "Au180": 8.1, - "Au181": 13.7, - "Au182": 15.6, - "Au183": 42.8, - "Au184": 20.6, - "Au184_m1": 47.6, - "Au185": 255.0, - "Au186": 642.0, - "Au187": 504.0, - "Au187_m1": 2.3, - "Au188": 530.4, - "Au189": 1722.0, - "Au189_m1": 275.4, - "Au190": 2568.0, - "Au190_m1": 0.125, - "Au191": 11448.0, - "Au191_m1": 0.92, - "Au192": 17784.0, - "Au192_m1": 0.029, - "Au192_m2": 0.16, - "Au193": 63540.0, - "Au193_m1": 3.9, - "Au194": 136872.0, - "Au194_m1": 0.6, - "Au194_m2": 0.42, - "Au195": 16078870.0, - "Au195_m1": 30.5, - "Au196": 532820.2, - "Au196_m1": 8.1, - "Au196_m2": 34560.0, - "Au197_m1": 7.73, - "Au198": 232822.1, - "Au198_m1": 196300.8, - "Au199": 271209.6, - "Au200": 2904.0, - "Au200_m1": 67320.0, - "Au201": 1560.0, - "Au202": 28.4, - "Au203": 60.0, - "Au204": 39.8, - "Au205": 31.0, - "Hg171": 6.9e-05, - "Hg172": 0.000365, - "Hg173": 0.0007, - "Hg174": 0.0019, - "Hg175": 0.0107, - "Hg176": 0.0203, - "Hg177": 0.1273, - "Hg178": 0.269, - "Hg179": 1.08, - "Hg180": 2.58, - "Hg181": 3.6, - "Hg182": 10.83, - "Hg183": 9.4, - "Hg184": 30.9, - "Hg185": 49.1, - "Hg185_m1": 21.6, - "Hg186": 82.8, - "Hg187": 144.0, - "Hg187_m1": 114.0, - "Hg188": 195.0, - "Hg189": 456.0, - "Hg189_m1": 516.0, - "Hg190": 1200.0, - "Hg191": 2940.0, - "Hg191_m1": 3048.0, - "Hg192": 17460.0, - "Hg193": 13680.0, - "Hg193_m1": 42480.0, - "Hg194": 14011600000.0, - "Hg195": 37908.0, - "Hg195_m1": 149760.0, - "Hg197": 230904.0, - "Hg197_m1": 85680.0, - "Hg199_m1": 2560.2, - "Hg203": 4025722.0, - "Hg205": 308.4, - "Hg205_m1": 0.00109, - "Hg206": 499.2, - "Hg207": 174.0, - "Hg208": 2490.0, - "Hg209": 36.5, - "Hg210": 146.0, - "Tl176": 0.006, - "Tl177": 0.018, - "Tl178": 0.06, - "Tl179": 0.23, - "Tl179_m1": 0.0017, - "Tl180": 1.09, - "Tl181": 3.2, - "Tl181_m1": 0.0014, - "Tl182": 3.1, - "Tl183": 6.9, - "Tl183_m1": 0.0533, - "Tl184": 11.0, - "Tl185": 19.5, - "Tl185_m1": 1.93, - "Tl186": 27.5, - "Tl186_m1": 2.9, - "Tl187": 51.0, - "Tl187_m1": 15.6, - "Tl188": 71.0, - "Tl188_m1": 71.0, - "Tl188_m2": 0.041, - "Tl189": 138.0, - "Tl189_m1": 84.0, - "Tl190": 222.0, - "Tl190_m1": 156.0, - "Tl191": 1200.0, - "Tl191_m1": 313.2, - "Tl192": 576.0, - "Tl192_m1": 648.0, - "Tl193": 1296.0, - "Tl193_m1": 126.6, - "Tl194": 1980.0, - "Tl194_m1": 1968.0, - "Tl195": 4176.0, - "Tl195_m1": 3.6, - "Tl196": 6624.0, - "Tl196_m1": 5076.0, - "Tl197": 10224.0, - "Tl197_m1": 0.54, - "Tl198": 19080.0, - "Tl198_m1": 6732.0, - "Tl198_m2": 0.0321, - "Tl199": 26712.0, - "Tl199_m1": 0.0284, - "Tl200": 93960.0, - "Tl200_m1": 0.034, - "Tl201": 262837.4, - "Tl201_m1": 0.00201, - "Tl202": 1063584.0, - "Tl204": 119382400.0, - "Tl206": 252.12, - "Tl206_m1": 224.4, - "Tl207": 286.2, - "Tl207_m1": 1.33, - "Tl208": 183.18, - "Tl209": 132.0, - "Tl210": 78.0, - "Tl211": 60.0, - "Tl212": 67.0, - "Pb178": 0.00023, - "Pb179": 0.003, - "Pb180": 0.0045, - "Pb181": 0.036, - "Pb181_m1": 0.045, - "Pb182": 0.0575, - "Pb183": 0.535, - "Pb183_m1": 0.415, - "Pb184": 0.49, - "Pb185": 6.3, - "Pb185_m1": 4.3, - "Pb186": 4.82, - "Pb187": 15.2, - "Pb187_m1": 18.3, - "Pb188": 25.1, - "Pb189": 39.0, - "Pb189_m1": 50.0, - "Pb190": 71.0, - "Pb191": 79.8, - "Pb191_m1": 130.8, - "Pb192": 210.0, - "Pb193": 120.0, - "Pb193_m1": 348.0, - "Pb194": 720.0, - "Pb195": 900.0, - "Pb195_m1": 900.0, - "Pb196": 2220.0, - "Pb197": 480.0, - "Pb197_m1": 2580.0, - "Pb198": 8640.0, - "Pb199": 5400.0, - "Pb199_m1": 732.0, - "Pb200": 77400.0, - "Pb201": 33588.0, - "Pb201_m1": 60.8, - "Pb202": 1656770000000.0, - "Pb202_m1": 12744.0, - "Pb203": 186912.0, - "Pb203_m1": 6.21, - "Pb203_m2": 0.48, - "Pb204": 4.4e24, - "Pb204_m1": 4015.8, - "Pb205": 545946000000000.0, - "Pb205_m1": 0.00555, - "Pb207_m1": 0.806, - "Pb209": 11710.8, - "Pb210": 700578700.0, - "Pb211": 2166.0, - "Pb212": 38304.0, - "Pb213": 612.0, - "Pb214": 1608.0, - "Pb215": 36.0, - "Bi184": 0.013, - "Bi184_m1": 0.0066, - "Bi185": 5.8e-05, - "Bi186": 0.015, - "Bi186_m1": 0.0098, - "Bi187": 0.032, - "Bi187_m1": 0.00031, - "Bi188": 0.06, - "Bi188_m1": 0.265, - "Bi189": 0.674, - "Bi189_m1": 0.005, - "Bi190": 6.3, - "Bi190_m1": 6.2, - "Bi191": 12.4, - "Bi191_m1": 0.125, - "Bi192": 34.6, - "Bi192_m1": 39.6, - "Bi193": 63.6, - "Bi193_m1": 3.2, - "Bi194": 95.0, - "Bi194_m1": 125.0, - "Bi194_m2": 115.0, - "Bi195": 183.0, - "Bi195_m1": 87.0, - "Bi196": 308.0, - "Bi196_m1": 0.6, - "Bi196_m2": 240.0, - "Bi197": 559.8, - "Bi197_m1": 302.4, - "Bi198": 618.0, - "Bi198_m1": 696.0, - "Bi198_m2": 7.7, - "Bi199": 1620.0, - "Bi199_m1": 1482.0, - "Bi200": 2184.0, - "Bi200_m1": 1860.0, - "Bi200_m2": 0.4, - "Bi201": 6180.0, - "Bi201_m1": 3450.0, - "Bi202": 6156.0, - "Bi203": 42336.0, - "Bi203_m1": 0.305, - "Bi204": 40392.0, - "Bi204_m1": 0.013, - "Bi204_m2": 0.00107, - "Bi205": 1322784.0, - "Bi206": 539395.2, - "Bi207": 995642300.0, - "Bi208": 11613200000000.0, - "Bi208_m1": 0.00258, - "Bi209": 5.99594e26, - "Bi210": 433036.8, - "Bi210_m1": 95935100000000.0, - "Bi211": 128.4, - "Bi212": 3633.0, - "Bi212_m1": 1500.0, - "Bi212_m2": 420.0, - "Bi213": 2735.4, - "Bi214": 1194.0, - "Bi215": 462.0, - "Bi215_m1": 36.4, - "Bi216": 135.0, - "Bi217": 98.5, - "Bi218": 33.0, - "Po188": 0.000425, - "Po189": 0.0035, - "Po190": 0.00245, - "Po191": 0.022, - "Po191_m1": 0.093, - "Po192": 0.0332, - "Po193": 0.37, - "Po193_m1": 0.373, - "Po194": 0.392, - "Po195": 4.64, - "Po195_m1": 1.92, - "Po196": 5.8, - "Po197": 84.0, - "Po197_m1": 32.0, - "Po198": 106.2, - "Po199": 328.2, - "Po199_m1": 250.2, - "Po200": 690.6, - "Po201": 936.0, - "Po201_m1": 537.6, - "Po202": 2676.0, - "Po203": 2202.0, - "Po203_m1": 45.0, - "Po204": 12708.0, - "Po205": 6264.0, - "Po205_m1": 0.000645, - "Po205_m2": 0.0574, - "Po206": 760320.0, - "Po207": 20880.0, - "Po207_m1": 2.79, - "Po208": 91453920.0, - "Po209": 3218880000.0, - "Po210": 11955690.0, - "Po211": 0.516, - "Po211_m1": 25.2, - "Po212": 2.99e-07, - "Po212_m1": 45.1, - "Po213": 4.2e-06, - "Po214": 0.0001643, - "Po215": 0.001781, - "Po216": 0.145, - "Po217": 1.53, - "Po218": 185.88, - "Po219": 3e-07, - "Po220": 3e-07, - "At193": 0.0285, - "At194": 0.04, - "At194_m1": 0.25, - "At195": 0.328, - "At195_m1": 0.147, - "At196": 0.388, - "At196_m1": 1.1e-05, - "At197": 0.388, - "At197_m1": 2.0, - "At198": 4.2, - "At198_m1": 1.0, - "At199": 7.03, - "At200": 43.0, - "At200_m1": 47.0, - "At200_m2": 7.9, - "At201": 85.2, - "At202": 184.0, - "At202_m1": 182.0, - "At202_m2": 0.46, - "At203": 444.0, - "At204": 553.2, - "At204_m1": 0.108, - "At205": 1614.0, - "At206": 1836.0, - "At207": 6480.0, - "At208": 5868.0, - "At209": 19476.0, - "At210": 29160.0, - "At211": 25970.4, - "At212": 0.314, - "At212_m1": 0.119, - "At213": 1.25e-07, - "At214": 5.58e-07, - "At215": 0.0001, - "At216": 0.0003, - "At217": 0.0323, - "At218": 1.5, - "At219": 56.0, - "At220": 222.6, - "At221": 138.0, - "At222": 54.0, - "At223": 50.0, - "Rn195": 0.0065, - "Rn195_m1": 0.005, - "Rn196": 0.0046, - "Rn197": 0.066, - "Rn197_m1": 0.021, - "Rn198": 0.065, - "Rn199": 0.59, - "Rn199_m1": 0.31, - "Rn200": 1.075, - "Rn201": 7.0, - "Rn201_m1": 3.8, - "Rn202": 9.7, - "Rn203": 44.0, - "Rn203_m1": 26.9, - "Rn204": 70.2, - "Rn205": 170.0, - "Rn206": 340.2, - "Rn207": 555.0, - "Rn208": 1461.0, - "Rn209": 1728.0, - "Rn210": 8640.0, - "Rn211": 52560.0, - "Rn212": 1434.0, - "Rn213": 0.025, - "Rn214": 2.7e-07, - "Rn215": 2.3e-06, - "Rn216": 4.5e-05, - "Rn217": 0.00054, - "Rn218": 0.035, - "Rn219": 3.96, - "Rn220": 55.6, - "Rn221": 1542.0, - "Rn222": 330350.4, - "Rn223": 1458.0, - "Rn224": 6420.0, - "Rn225": 279.6, - "Rn226": 444.0, - "Rn227": 20.8, - "Rn228": 65.0, - "Fr199": 0.015, - "Fr200": 0.049, - "Fr201": 0.069, - "Fr202": 0.3, - "Fr202_m1": 0.29, - "Fr203": 0.55, - "Fr204": 1.7, - "Fr204_m1": 2.6, - "Fr204_m2": 1.0, - "Fr205": 3.8, - "Fr206": 16.0, - "Fr206_m1": 16.0, - "Fr206_m2": 0.7, - "Fr207": 14.8, - "Fr208": 59.1, - "Fr209": 50.0, - "Fr210": 190.8, - "Fr211": 186.0, - "Fr212": 1200.0, - "Fr213": 34.82, - "Fr214": 0.005, - "Fr214_m1": 0.00335, - "Fr215": 8.6e-08, - "Fr216": 7e-07, - "Fr217": 1.9e-05, - "Fr218": 0.001, - "Fr218_m1": 0.022, - "Fr219": 0.02, - "Fr220": 27.4, - "Fr221": 294.0, - "Fr222": 852.0, - "Fr223": 1320.0, - "Fr224": 199.8, - "Fr225": 237.0, - "Fr226": 49.0, - "Fr227": 148.2, - "Fr228": 38.0, - "Fr229": 50.2, - "Fr230": 19.1, - "Fr231": 17.6, - "Fr232": 5.5, - "Ra202": 0.0275, - "Ra203": 0.031, - "Ra203_m1": 0.025, - "Ra204": 0.0605, - "Ra205": 0.22, - "Ra205_m1": 0.18, - "Ra206": 0.24, - "Ra207": 1.3, - "Ra207_m1": 0.055, - "Ra208": 1.3, - "Ra209": 4.6, - "Ra210": 3.7, - "Ra211": 13.0, - "Ra212": 13.0, - "Ra213": 163.8, - "Ra213_m1": 0.0021, - "Ra214": 2.46, - "Ra215": 0.00155, - "Ra216": 1.82e-07, - "Ra217": 1.6e-06, - "Ra218": 2.52e-05, - "Ra219": 0.01, - "Ra220": 0.018, - "Ra221": 28.0, - "Ra222": 36.17, - "Ra223": 987552.0, - "Ra224": 316224.0, - "Ra225": 1287360.0, - "Ra226": 50492200000.0, - "Ra227": 2532.0, - "Ra228": 181456200.0, - "Ra229": 240.0, - "Ra230": 5580.0, - "Ra231": 103.0, - "Ra232": 252.0, - "Ra233": 30.0, - "Ra234": 30.0, - "Ac206": 0.024, - "Ac206_m1": 0.0395, - "Ac207": 0.027, - "Ac208": 0.095, - "Ac208_m1": 0.025, - "Ac209": 0.098, - "Ac210": 0.35, - "Ac211": 0.21, - "Ac212": 0.93, - "Ac213": 0.8, - "Ac214": 8.2, - "Ac215": 0.17, - "Ac216": 0.00044, - "Ac216_m1": 0.000441, - "Ac217": 6.9e-08, - "Ac218": 1.08e-06, - "Ac219": 1.18e-05, - "Ac220": 0.0264, - "Ac221": 0.052, - "Ac222": 5.0, - "Ac222_m1": 63.0, - "Ac223": 126.0, - "Ac224": 10008.0, - "Ac225": 864000.0, - "Ac226": 105732.0, - "Ac227": 687072100.0, - "Ac228": 22140.0, - "Ac229": 3762.0, - "Ac230": 122.0, - "Ac231": 450.0, - "Ac232": 119.0, - "Ac233": 145.0, - "Ac234": 44.0, - "Ac235": 60.0, - "Ac236": 120.0, - "Th209": 0.0065, - "Th210": 0.016, - "Th211": 0.05, - "Th212": 0.035, - "Th213": 0.14, - "Th214": 0.1, - "Th215": 1.2, - "Th216": 0.026, - "Th217": 0.000251, - "Th218": 1.17e-07, - "Th219": 1.05e-06, - "Th220": 9.7e-06, - "Th221": 0.00173, - "Th222": 0.002237, - "Th223": 0.6, - "Th224": 1.05, - "Th225": 523.2, - "Th226": 1834.2, - "Th227": 1613952.0, - "Th228": 60338130.0, - "Th229": 231633000000.0, - "Th230": 2378810000000.0, - "Th231": 91872.0, - "Th232": 4.43384e17, - "Th233": 1338.0, - "Th234": 2082240.0, - "Th235": 426.0, - "Th236": 2238.0, - "Th237": 282.0, - "Th238": 564.0, - "Pa212": 0.0051, - "Pa213": 0.0053, - "Pa214": 0.017, - "Pa215": 0.014, - "Pa216": 0.16, - "Pa217": 0.0036, - "Pa217_m1": 0.0012, - "Pa218": 0.000113, - "Pa219": 5.3e-08, - "Pa220": 7.8e-07, - "Pa221": 5.9e-06, - "Pa222": 0.0033, - "Pa223": 0.0051, - "Pa224": 0.79, - "Pa225": 1.7, - "Pa226": 108.0, - "Pa227": 2298.0, - "Pa228": 79200.0, - "Pa229": 129600.0, - "Pa230": 1503360.0, - "Pa231": 1033830000000.0, - "Pa232": 114048.0, - "Pa233": 2330640.0, - "Pa234": 24120.0, - "Pa234_m1": 69.54, - "Pa235": 1466.4, - "Pa236": 546.0, - "Pa237": 522.0, - "Pa238": 136.2, - "Pa239": 6480.0, - "Pa240": 120.0, - "U217": 0.0235, - "U218": 0.000545, - "U219": 4.2e-05, - "U220": 6e-08, - "U222": 1.3e-06, - "U223": 1.8e-05, - "U224": 0.0009, - "U225": 0.084, - "U226": 0.35, - "U227": 66.0, - "U228": 546.0, - "U229": 3480.0, - "U230": 1797120.0, - "U231": 362880.0, - "U232": 2174319000.0, - "U233": 5023970000000.0, - "U234": 7747390000000.0, - "U235": 2.22102e16, - "U235_m1": 1560.0, - "U236": 739079000000000.0, - "U237": 583200.0, - "U238": 1.40999e17, - "U239": 1407.0, - "U240": 50760.0, - "U241": 300.0, - "U242": 1008.0, - "Np225": 2e-06, - "Np226": 0.035, - "Np227": 0.51, - "Np228": 61.4, - "Np229": 240.0, - "Np230": 276.0, - "Np231": 2928.0, - "Np232": 882.0, - "Np233": 2172.0, - "Np234": 380160.0, - "Np235": 34231680.0, - "Np236": 4828310000000.0, - "Np236_m1": 81000.0, - "Np237": 67659500000000.0, - "Np238": 182908.8, - "Np239": 203558.4, - "Np240": 3714.0, - "Np240_m1": 433.2, - "Np241": 834.0, - "Np242": 132.0, - "Np242_m1": 330.0, - "Np243": 111.0, - "Np244": 137.4, - "Pu228": 1.85, - "Pu229": 112.0, - "Pu230": 102.0, - "Pu231": 516.0, - "Pu232": 2028.0, - "Pu233": 1254.0, - "Pu234": 31680.0, - "Pu235": 1518.0, - "Pu236": 90191620.0, - "Pu237": 3943296.0, - "Pu237_m1": 0.18, - "Pu238": 2767602000.0, - "Pu239": 760854000000.0, - "Pu240": 207049000000.0, - "Pu241": 450958100.0, - "Pu242": 11786800000000.0, - "Pu243": 17841.6, - "Pu244": 2559320000000000.0, - "Pu245": 37800.0, - "Pu246": 936576.0, - "Pu247": 196128.0, - "Am231": 10.0, - "Am232": 79.0, - "Am233": 192.0, - "Am234": 139.2, - "Am235": 618.0, - "Am236": 216.0, - "Am237": 4416.0, - "Am238": 5880.0, - "Am239": 42840.0, - "Am240": 182880.0, - "Am241": 13651800000.0, - "Am242": 57672.0, - "Am242_m1": 4449622000.0, - "Am242_m2": 0.014, - "Am243": 232580000000.0, - "Am244": 36360.0, - "Am244_m1": 1560.0, - "Am245": 7380.0, - "Am246": 2340.0, - "Am246_m1": 1500.0, - "Am247": 1380.0, - "Am248": 600.0, - "Am249": 120.0, - "Cm233": 17.7, - "Cm234": 51.0, - "Cm235": 300.0, - "Cm236": 1900.0, - "Cm237": 1200.0, - "Cm238": 8640.0, - "Cm239": 10440.0, - "Cm240": 2332800.0, - "Cm241": 2833920.0, - "Cm242": 14078020.0, - "Cm243": 918326200.0, - "Cm244": 571508100.0, - "Cm244_m1": 5e-07, - "Cm245": 268240000000.0, - "Cm246": 150214000000.0, - "Cm247": 492299000000000.0, - "Cm248": 10982000000000.0, - "Cm249": 3849.0, - "Cm250": 261928000000.0, - "Cm251": 1008.0, - "Bk235": 20.0, - "Bk237": 60.0, - "Bk238": 144.0, - "Bk240": 288.0, - "Bk241": 276.0, - "Bk242": 420.0, - "Bk243": 16200.0, - "Bk244": 15660.0, - "Bk245": 426816.0, - "Bk246": 155520.0, - "Bk247": 43549500000.0, - "Bk248": 283824000.0, - "Bk248_m1": 85320.0, - "Bk249": 27648000.0, - "Bk250": 11563.2, - "Bk251": 3336.0, - "Bk253": 600.0, - "Bk254": 120.0, - "Cf237": 2.1, - "Cf238": 0.021, - "Cf239": 51.5, - "Cf240": 57.6, - "Cf241": 226.8, - "Cf242": 222.0, - "Cf243": 642.0, - "Cf244": 1164.0, - "Cf245": 2700.0, - "Cf246": 128520.0, - "Cf247": 11196.0, - "Cf248": 28814400.0, - "Cf249": 11076700000.0, - "Cf250": 412773400.0, - "Cf251": 28338700000.0, - "Cf252": 83468070.0, - "Cf253": 1538784.0, - "Cf254": 5227200.0, - "Cf255": 5100.0, - "Cf256": 738.0, - "Es240": 1.0, - "Es241": 8.5, - "Es242": 13.5, - "Es243": 21.0, - "Es244": 37.0, - "Es245": 66.0, - "Es246": 462.0, - "Es247": 273.0, - "Es247_m1": 54000000.0, - "Es248": 1620.0, - "Es249": 6132.0, - "Es250": 30960.0, - "Es250_m1": 7992.0, - "Es251": 118800.0, - "Es252": 40754880.0, - "Es253": 1768608.0, - "Es254": 23820480.0, - "Es254_m1": 141479.9, - "Es255": 3438720.0, - "Es256": 1524.0, - "Es256_m1": 27360.0, - "Es257": 665280.0, - "Es258": 180.0, - "Fm242": 0.0008, - "Fm243": 0.2, - "Fm244": 0.0033, - "Fm245": 4.2, - "Fm246": 1.1, - "Fm247": 29.0, - "Fm248": 36.0, - "Fm249": 156.0, - "Fm250": 1800.0, - "Fm250_m1": 1.8, - "Fm251": 19080.0, - "Fm252": 91404.0, - "Fm253": 259200.0, - "Fm254": 11664.0, - "Fm255": 72252.0, - "Fm256": 9456.0, - "Fm257": 8683200.0, - "Fm258": 0.00037, - "Fm259": 1.5, - "Fm260": 0.004, - "Md245": 0.0009, - "Md245_m1": 0.39, - "Md246": 0.9, - "Md247": 1.12, - "Md247_m1": 0.26, - "Md248": 7.0, - "Md249": 24.0, - "Md249_m1": 1.9, - "Md250": 27.5, - "Md251": 240.0, - "Md252": 138.0, - "Md253": 630.0, - "Md254": 1680.0, - "Md254_m1": 1680.0, - "Md255": 1620.0, - "Md256": 4620.0, - "Md257": 19872.0, - "Md258": 4449600.0, - "Md258_m1": 3420.0, - "Md259": 5760.0, - "Md260": 2747520.0, - "Md261": 2400.0, - "No250": 4.35e-06, - "No251": 0.8, - "No251_m1": 1.02, - "No252": 2.44, - "No253": 97.2, - "No254": 51.0, - "No254_m1": 0.28, - "No255": 186.0, - "No256": 2.91, - "No257": 25.0, - "No258": 0.0012, - "No259": 3480.0, - "No260": 0.106, - "No261": 160000.0, - "No262": 0.005, - "Lr251": 1.341, - "Lr252": 0.38, - "Lr253": 0.575, - "Lr253_m1": 1.535, - "Lr254": 13.0, - "Lr255": 22.0, - "Lr255_m1": 2.53, - "Lr256": 27.0, - "Lr257": 0.646, - "Lr258": 4.1, - "Lr259": 6.2, - "Lr260": 180.0, - "Lr261": 2340.0, - "Lr262": 14400.0, - "Lr263": 18000.0, - "Rf253": 5.15e-05, - "Rf254": 2.3e-05, - "Rf255": 1.68, - "Rf256": 0.0064, - "Rf257": 4.7, - "Rf257_m1": 3.9, - "Rf258": 0.012, - "Rf259": 3.2, - "Rf260": 0.021, - "Rf261": 65.0, - "Rf261_m1": 81.0, - "Rf262": 2.3, - "Rf263": 600.0, - "Rf264": 3600.0, - "Rf265": 1.0, - "Db255": 1.7, - "Db256": 1.7, - "Db257": 1.52, - "Db257_m1": 0.78, - "Db258": 4.0, - "Db258_m1": 20.0, - "Db259": 0.51, - "Db260": 1.52, - "Db261": 1.8, - "Db262": 35.0, - "Db263": 28.5, - "Db264": 180.0, - "Db265": 900.0, - "Sg258": 0.0032, - "Sg259": 0.555, - "Sg260": 0.0036, - "Sg261": 0.23, - "Sg262": 0.0079, - "Sg263": 1.0, - "Sg263_m1": 0.12, - "Sg264": 0.045, - "Sg265": 8.0, - "Sg266": 25.0, - "Sg269": 50.0, - "Bh260": 0.0003, - "Bh261": 0.013, - "Bh262": 0.102, - "Bh262_m1": 0.022, - "Bh263": 0.0002, - "Bh264": 0.66, - "Bh265": 1.1, - "Bh266": 5.4, - "Bh267": 21.0, - "Bh269": 50.0, - "Hs263": 0.00355, - "Hs264": 0.0008, - "Hs265": 0.00205, - "Hs265_m1": 0.0003, - "Hs266": 0.00265, - "Hs267": 0.0545, - "Hs268": 1.2, - "Hs269": 12.9, - "Hs273": 50.0, - "Mt265": 120.0, - "Mt266": 0.0018, - "Mt266_m1": 0.0017, - "Mt267": 0.01, - "Mt268": 0.0225, - "Mt269": 0.05, - "Mt270": 0.00605, - "Mt271": 5.0, - "Mt273": 20.0, - "Ds267": 2.8e-06, - "Ds268": 0.0001, - "Ds269": 0.000268, - "Ds270": 0.00015, - "Ds270_m1": 0.009, - "Ds271": 0.001705, - "Ds271_m1": 0.0865, - "Ds272": 1.0, - "Ds273": 0.000225, - "Ds279_m1": 0.19, - "Rg272": 0.0041, -} - - # Values here are from the Committee on Data for Science and Technology # (CODATA) 2018 recommendation (https://physics.nist.gov/cuu/Constants/). @@ -3764,6 +199,9 @@ _ATOMIC_MASS = {} # Regex for GND nuclide names (used in zam function) _GND_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)') +# Used in half_life function as a cache +_HALF_LIFE = {} + def atomic_mass(isotope): """Return atomic mass of isotope in atomic mass units. @@ -3838,6 +276,36 @@ def atomic_weight(element): .format(element)) +def half_life(isotope): + """Return half-life of isotope in seconds. Returns None if isotope is stable + + Half-life values are from `ENDF/B VIII.0 Decay Reaction Sublibrary + `_. + + Parameters + ---------- + isotope : str + Name of isotope, e.g., 'Pu239' + + Returns + ------- + float + Half-life of isotope in [seconds] + + """ + global _HALF_LIFE + if not _HALF_LIFE: + print('reading json file') + # Load data from AME2016 file + half_life_filename = os.path.join(os.path.dirname(__file__), 'half_life.json') + with open(half_life_filename, 'r') as f: + _HALF_LIFE = json.load(f) + + if isotope.title() not in _HALF_LIFE.keys(): + return None + + return _HALF_LIFE[isotope.title()] + def water_density(temperature, pressure=0.1013): """Return the density of liquid water at a given temperature and pressure. diff --git a/openmc/data/half_life.json b/openmc/data/half_life.json new file mode 100644 index 000000000..bb67da75d --- /dev/null +++ b/openmc/data/half_life.json @@ -0,0 +1,3563 @@ +{ + "H3": 388789600.0, + "H4": 9.90652e-23, + "H5": 7.99473e-23, + "H6": 2.84812e-22, + "H7": 2.3e-23, + "He5": 7.595e-22, + "He6": 0.8067, + "He7": 3.038e-21, + "He8": 0.1191, + "He9": 7e-21, + "He10": 1.519e-21, + "Li4": 7.55721e-23, + "Li5": 3.06868e-22, + "Li8": 0.838, + "Li9": 0.1783, + "Li10": 2e-21, + "Li11": 0.00859, + "Li12": 1e-08, + "Be5": 1e-09, + "Be6": 4.95326e-21, + "Be7": 4598208.0, + "Be8": 8.18132e-17, + "Be10": 47652000000000.0, + "Be11": 13.81, + "Be12": 0.0213, + "Be13": 2.7e-21, + "Be14": 0.00435, + "Be15": 2e-07, + "Be16": 2e-07, + "B6": 1e-09, + "B7": 3.255e-22, + "B8": 0.77, + "B9": 8.43888e-19, + "B12": 0.0202, + "B13": 0.01736, + "B14": 0.0125, + "B15": 0.00993, + "B16": 1.9e-10, + "B17": 0.00508, + "B18": 2.6e-08, + "B19": 0.00292, + "C8": 1.9813e-21, + "C9": 0.1265, + "C10": 19.29, + "C11": 1223.1, + "C14": 179878000000.0, + "C15": 2.449, + "C16": 0.747, + "C17": 0.193, + "C18": 0.092, + "C19": 0.049, + "C20": 0.0145, + "C21": 3e-08, + "C22": 0.0062, + "N10": 2e-22, + "N11": 3.12742e-22, + "N12": 0.011, + "N13": 597.9, + "N16": 7.13, + "N17": 4.171, + "N18": 0.624, + "N19": 0.271, + "N20": 0.13, + "N21": 0.085, + "N22": 0.024, + "N23": 0.0145, + "N24": 5.2e-08, + "N25": 2.6e-07, + "O12": 1.13925e-21, + "O13": 0.00858, + "O14": 70.606, + "O15": 122.24, + "O19": 26.88, + "O20": 13.51, + "O21": 3.42, + "O22": 2.25, + "O23": 0.0905, + "O24": 0.065, + "O25": 5e-08, + "O26": 4e-08, + "O27": 2.6e-07, + "O28": 1e-07, + "F14": 5.0007e-22, + "F15": 4.557e-22, + "F16": 1.13925e-20, + "F17": 64.49, + "F18": 6586.2, + "F20": 11.163, + "F21": 4.158, + "F22": 4.23, + "F23": 2.23, + "F24": 0.39, + "F25": 0.05, + "F26": 0.0096, + "F27": 0.005, + "F28": 4e-08, + "F29": 0.0025, + "F30": 2.6e-07, + "F31": 2.5e-07, + "Ne16": 3.73524e-21, + "Ne17": 0.1092, + "Ne18": 1.672, + "Ne19": 17.22, + "Ne23": 37.24, + "Ne24": 202.8, + "Ne25": 0.602, + "Ne26": 0.197, + "Ne27": 0.032, + "Ne28": 0.0189, + "Ne29": 0.0148, + "Ne30": 0.0073, + "Ne31": 0.0034, + "Ne32": 0.0035, + "Ne33": 1.8e-07, + "Ne34": 6e-08, + "Na18": 1.3e-21, + "Na19": 4e-08, + "Na20": 0.4479, + "Na21": 22.49, + "Na22": 82134970.0, + "Na24": 53989.2, + "Na24_m1": 0.02018, + "Na25": 59.1, + "Na26": 1.077, + "Na27": 0.301, + "Na28": 0.0305, + "Na29": 0.0449, + "Na30": 0.048, + "Na31": 0.017, + "Na32": 0.0132, + "Na33": 0.008, + "Na34": 0.0055, + "Na35": 0.0015, + "Na36": 1.8e-07, + "Na37": 6e-08, + "Mg19": 4e-12, + "Mg20": 0.0908, + "Mg21": 0.122, + "Mg22": 3.8755, + "Mg23": 11.317, + "Mg27": 567.48, + "Mg28": 75294.0, + "Mg29": 1.3, + "Mg30": 0.335, + "Mg31": 0.232, + "Mg32": 0.086, + "Mg33": 0.0905, + "Mg34": 0.02, + "Mg35": 0.07, + "Mg36": 0.0039, + "Mg37": 2.6e-07, + "Mg38": 2.6e-07, + "Mg39": 1.8e-07, + "Mg40": 1.7e-07, + "Al21": 3.5e-08, + "Al22": 0.059, + "Al23": 0.47, + "Al24": 2.053, + "Al24_m1": 0.13, + "Al25": 7.183, + "Al26": 22626800000000.0, + "Al26_m1": 6.3452, + "Al28": 134.484, + "Al29": 393.6, + "Al30": 3.62, + "Al31": 0.644, + "Al32": 0.033, + "Al33": 0.0417, + "Al34": 0.042, + "Al35": 0.0386, + "Al36": 0.09, + "Al37": 0.0107, + "Al38": 0.0076, + "Al39": 7.6e-06, + "Al40": 2.6e-07, + "Al41": 2.6e-07, + "Al42": 1.7e-07, + "Si22": 0.029, + "Si23": 0.0423, + "Si24": 0.14, + "Si25": 0.22, + "Si26": 2.234, + "Si27": 4.16, + "Si31": 9438.0, + "Si32": 4828310000.0, + "Si33": 6.11, + "Si34": 2.77, + "Si35": 0.78, + "Si36": 0.45, + "Si37": 0.09, + "Si38": 1e-06, + "Si39": 0.0475, + "Si40": 0.033, + "Si41": 0.02, + "Si42": 0.0125, + "Si43": 6e-08, + "Si44": 3.6e-07, + "P24": 0.0074, + "P25": 3e-08, + "P26": 0.0437, + "P27": 0.26, + "P28": 0.2703, + "P29": 4.142, + "P30": 149.88, + "P32": 1232323.0, + "P33": 2189376.0, + "P34": 12.43, + "P35": 47.3, + "P36": 5.6, + "P37": 2.31, + "P38": 0.64, + "P39": 0.28, + "P40": 0.125, + "P41": 0.1, + "P42": 0.0485, + "P43": 0.0365, + "P44": 0.0185, + "P45": 2e-07, + "P46": 2e-07, + "S26": 0.01, + "S27": 0.0155, + "S28": 0.125, + "S29": 0.187, + "S30": 1.178, + "S31": 2.572, + "S35": 7560864.0, + "S37": 303.0, + "S38": 10218.0, + "S39": 11.5, + "S40": 8.8, + "S41": 1.99, + "S42": 1.013, + "S43": 0.28, + "S44": 0.1, + "S45": 0.068, + "S46": 0.05, + "S48": 2e-07, + "S49": 2e-07, + "Cl28": 0.0017, + "Cl29": 2e-08, + "Cl30": 3e-08, + "Cl31": 0.15, + "Cl32": 0.298, + "Cl33": 2.511, + "Cl34": 1.5264, + "Cl34_m1": 1920.0, + "Cl36": 9498840000000.0, + "Cl38": 2233.8, + "Cl38_m1": 0.715, + "Cl39": 3336.0, + "Cl40": 81.0, + "Cl41": 38.4, + "Cl42": 6.8, + "Cl43": 3.13, + "Cl44": 0.56, + "Cl45": 0.413, + "Cl46": 0.232, + "Cl47": 0.101, + "Cl48": 2e-07, + "Cl49": 1.7e-07, + "Cl50": 0.02, + "Cl51": 2e-07, + "Ar30": 2e-08, + "Ar31": 0.0151, + "Ar32": 0.098, + "Ar33": 0.173, + "Ar34": 0.8445, + "Ar35": 1.775, + "Ar37": 3027456.0, + "Ar39": 8488990000.0, + "Ar41": 6576.6, + "Ar42": 1038250000.0, + "Ar43": 322.2, + "Ar44": 712.2, + "Ar45": 21.48, + "Ar46": 8.4, + "Ar47": 1.23, + "Ar48": 0.475, + "Ar49": 0.17, + "Ar50": 0.085, + "Ar51": 2e-07, + "Ar52": 0.01, + "Ar53": 0.003, + "K32": 0.0033, + "K33": 2.5e-08, + "K34": 2.5e-08, + "K35": 0.178, + "K36": 0.342, + "K37": 1.226, + "K38": 458.16, + "K38_m1": 0.924, + "K40": 3.93839e16, + "K42": 44496.0, + "K43": 80280.0, + "K44": 1327.8, + "K45": 1068.6, + "K46": 105.0, + "K47": 17.5, + "K48": 6.8, + "K49": 1.26, + "K50": 0.472, + "K51": 0.365, + "K52": 0.105, + "K53": 0.03, + "K54": 0.01, + "K55": 0.003, + "Ca34": 3.5e-08, + "Ca35": 0.0257, + "Ca36": 0.102, + "Ca37": 0.1811, + "Ca38": 0.44, + "Ca39": 0.8596, + "Ca41": 3218880000000.0, + "Ca45": 14049500.0, + "Ca47": 391910.4, + "Ca48": 7.25824e26, + "Ca49": 523.08, + "Ca50": 13.9, + "Ca51": 10.0, + "Ca52": 4.6, + "Ca53": 0.09, + "Ca54": 0.086, + "Ca55": 0.022, + "Ca56": 0.01, + "Ca57": 0.005, + "Sc36": 0.0088, + "Sc37": 0.056, + "Sc38": 0.0423, + "Sc39": 3e-07, + "Sc40": 0.1823, + "Sc41": 0.5963, + "Sc42": 0.6808, + "Sc42_m1": 62.0, + "Sc43": 14007.6, + "Sc44": 14292.0, + "Sc44_m1": 210996.0, + "Sc45_m1": 0.318, + "Sc46": 7239456.0, + "Sc46_m1": 18.75, + "Sc47": 289370.9, + "Sc48": 157212.0, + "Sc49": 3430.8, + "Sc50": 102.5, + "Sc50_m1": 0.35, + "Sc51": 12.4, + "Sc52": 8.2, + "Sc53": 3.0, + "Sc54": 0.36, + "Sc55": 0.105, + "Sc56": 0.06, + "Sc57": 0.013, + "Sc58": 0.012, + "Sc59": 0.01, + "Sc60": 0.003, + "Ti38": 1.2e-07, + "Ti39": 0.032, + "Ti40": 0.0533, + "Ti41": 0.0804, + "Ti42": 0.199, + "Ti43": 0.509, + "Ti44": 1893460000.0, + "Ti45": 11088.0, + "Ti51": 345.6, + "Ti52": 102.0, + "Ti53": 32.7, + "Ti54": 1.5, + "Ti55": 1.3, + "Ti56": 0.2, + "Ti57": 0.06, + "Ti58": 0.059, + "Ti59": 0.03, + "Ti60": 0.022, + "Ti61": 3e-07, + "Ti62": 0.01, + "Ti63": 0.003, + "V40": 0.0077, + "V41": 0.0244, + "V42": 5.5e-08, + "V43": 0.8, + "V44": 0.111, + "V44_m1": 0.15, + "V45": 0.547, + "V46": 0.4225, + "V46_m1": 0.00102, + "V47": 1956.0, + "V48": 1380110.0, + "V49": 28512000.0, + "V50": 4.41806e24, + "V52": 224.58, + "V53": 92.58, + "V54": 49.8, + "V55": 6.54, + "V56": 0.216, + "V57": 0.35, + "V58": 0.185, + "V59": 0.075, + "V60": 0.068, + "V61": 0.047, + "V62": 1.5e-07, + "V63": 0.017, + "V64": 0.019, + "V65": 0.01, + "Cr42": 0.014, + "Cr43": 0.0216, + "Cr44": 0.0535, + "Cr45": 0.0609, + "Cr46": 0.26, + "Cr47": 0.5, + "Cr48": 77616.0, + "Cr49": 2538.0, + "Cr51": 2393366.0, + "Cr55": 209.82, + "Cr56": 356.4, + "Cr57": 21.1, + "Cr58": 7.0, + "Cr59": 0.46, + "Cr60": 0.49, + "Cr61": 0.27, + "Cr62": 0.19, + "Cr63": 0.129, + "Cr64": 0.043, + "Cr65": 0.027, + "Cr66": 0.01, + "Cr67": 0.05, + "Mn44": 1.05e-07, + "Mn45": 7e-08, + "Mn46": 0.0345, + "Mn47": 0.1, + "Mn48": 0.1581, + "Mn49": 0.382, + "Mn50": 0.28319, + "Mn50_m1": 105.0, + "Mn51": 2772.0, + "Mn52": 483062.4, + "Mn52_m1": 1266.0, + "Mn53": 116763000000000.0, + "Mn54": 26961120.0, + "Mn56": 9284.04, + "Mn57": 85.4, + "Mn58": 3.0, + "Mn58_m1": 65.4, + "Mn59": 4.59, + "Mn60": 51.0, + "Mn60_m1": 1.77, + "Mn61": 0.67, + "Mn62": 0.671, + "Mn62_m1": 0.092, + "Mn63": 0.29, + "Mn64": 0.09, + "Mn65": 0.092, + "Mn66": 0.064, + "Mn67": 0.047, + "Mn68": 0.028, + "Mn69": 0.014, + "Fe45": 0.00203, + "Fe46": 0.013, + "Fe47": 0.0219, + "Fe48": 0.044, + "Fe49": 0.0647, + "Fe50": 0.155, + "Fe51": 0.305, + "Fe52": 29790.0, + "Fe52_m1": 45.9, + "Fe53": 510.6, + "Fe53_m1": 152.4, + "Fe55": 86594050.0, + "Fe59": 3844368.0, + "Fe60": 47336400000000.0, + "Fe61": 358.8, + "Fe62": 68.0, + "Fe63": 6.1, + "Fe64": 2.0, + "Fe65": 0.81, + "Fe65_m1": 1.12, + "Fe66": 0.44, + "Fe67": 0.416, + "Fe68": 0.187, + "Fe69": 0.109, + "Fe70": 0.094, + "Fe71": 0.028, + "Fe72": 1.5e-07, + "Co49": 3.5e-08, + "Co50": 0.044, + "Co51": 2e-07, + "Co52": 0.115, + "Co53": 0.24, + "Co53_m1": 0.247, + "Co54": 0.19328, + "Co54_m1": 88.8, + "Co55": 63108.0, + "Co56": 6672931.0, + "Co57": 23478340.0, + "Co58": 6122304.0, + "Co58_m1": 32760.0, + "Co60": 166344200.0, + "Co60_m1": 628.02, + "Co61": 5940.0, + "Co62": 90.0, + "Co62_m1": 834.6, + "Co63": 27.4, + "Co64": 0.3, + "Co65": 1.16, + "Co66": 0.2, + "Co67": 0.425, + "Co68": 0.199, + "Co68_m1": 1.6, + "Co69": 0.22, + "Co70": 0.119, + "Co70_m1": 0.5, + "Co71": 0.079, + "Co72": 0.0599, + "Co73": 0.041, + "Co74": 0.03, + "Co75": 0.034, + "Ni48": 0.0021, + "Ni49": 0.0075, + "Ni50": 0.012, + "Ni51": 2e-07, + "Ni52": 0.038, + "Ni53": 0.045, + "Ni54": 0.104, + "Ni55": 0.2047, + "Ni56": 524880.0, + "Ni57": 128160.0, + "Ni59": 2398380000000.0, + "Ni63": 3193630000.0, + "Ni65": 9061.884, + "Ni66": 196560.0, + "Ni67": 21.0, + "Ni68": 29.0, + "Ni69": 11.4, + "Ni69_m1": 3.5, + "Ni70": 6.0, + "Ni71": 2.56, + "Ni72": 1.57, + "Ni73": 0.84, + "Ni74": 0.68, + "Ni75": 0.6, + "Ni76": 0.238, + "Ni77": 0.061, + "Ni78": 0.11, + "Cu52": 0.0069, + "Cu53": 3e-07, + "Cu54": 7.5e-08, + "Cu55": 0.04, + "Cu56": 0.094, + "Cu57": 0.1963, + "Cu58": 3.204, + "Cu59": 81.5, + "Cu60": 1422.0, + "Cu61": 11998.8, + "Cu62": 580.38, + "Cu64": 45723.6, + "Cu66": 307.2, + "Cu67": 222588.0, + "Cu68": 31.1, + "Cu68_m1": 225.0, + "Cu69": 171.0, + "Cu70": 44.5, + "Cu70_m1": 33.0, + "Cu70_m2": 6.6, + "Cu71": 19.5, + "Cu72": 6.63, + "Cu73": 4.2, + "Cu74": 1.75, + "Cu75": 1.224, + "Cu76": 0.653, + "Cu76_m1": 1.27, + "Cu77": 0.469, + "Cu78": 0.335, + "Cu79": 0.188, + "Cu80": 0.17, + "Cu81": 0.028, + "Zn54": 0.0037, + "Zn55": 0.02, + "Zn56": 5e-07, + "Zn57": 0.038, + "Zn58": 0.084, + "Zn59": 0.182, + "Zn60": 142.8, + "Zn61": 89.1, + "Zn61_m1": 0.43, + "Zn61_m2": 0.14, + "Zn62": 33336.0, + "Zn63": 2308.2, + "Zn65": 21075550.0, + "Zn69": 3384.0, + "Zn69_m1": 49536.0, + "Zn71": 147.0, + "Zn71_m1": 14256.0, + "Zn72": 167400.0, + "Zn73": 23.5, + "Zn73_m1": 5.8, + "Zn73_m2": 0.013, + "Zn74": 95.6, + "Zn75": 10.2, + "Zn76": 5.7, + "Zn77": 2.08, + "Zn77_m1": 1.05, + "Zn78": 1.47, + "Zn79": 0.995, + "Zn80": 0.54, + "Zn81": 0.32, + "Zn82": 0.052, + "Zn83": 0.043, + "Ga56": 0.0059, + "Ga57": 0.0123, + "Ga58": 0.0152, + "Ga59": 0.0418, + "Ga60": 0.07, + "Ga61": 0.168, + "Ga62": 0.11612, + "Ga63": 32.4, + "Ga64": 157.62, + "Ga65": 912.0, + "Ga66": 34164.0, + "Ga67": 281810.9, + "Ga68": 4062.6, + "Ga70": 1268.4, + "Ga72": 50760.0, + "Ga72_m1": 0.03968, + "Ga73": 17496.0, + "Ga74": 487.2, + "Ga74_m1": 9.5, + "Ga75": 126.0, + "Ga76": 32.6, + "Ga77": 13.2, + "Ga78": 5.09, + "Ga79": 2.847, + "Ga80": 1.676, + "Ga81": 1.217, + "Ga82": 0.599, + "Ga83": 0.3081, + "Ga84": 0.085, + "Ga85": 0.048, + "Ga86": 0.029, + "Ge58": 0.0152, + "Ge59": 0.0418, + "Ge60": 0.03, + "Ge61": 0.039, + "Ge62": 1.5e-07, + "Ge63": 0.142, + "Ge64": 63.7, + "Ge65": 30.9, + "Ge66": 8136.0, + "Ge67": 1134.0, + "Ge68": 23410080.0, + "Ge69": 140580.0, + "Ge71": 987552.0, + "Ge71_m1": 0.02041, + "Ge73_m1": 0.499, + "Ge75": 4966.8, + "Ge75_m1": 47.7, + "Ge77": 40680.0, + "Ge77_m1": 52.9, + "Ge78": 5280.0, + "Ge79": 18.98, + "Ge79_m1": 39.0, + "Ge80": 29.5, + "Ge81": 7.6, + "Ge81_m1": 7.6, + "Ge82": 4.55, + "Ge83": 1.85, + "Ge84": 0.954, + "Ge85": 0.535, + "Ge86": 0.095, + "Ge87": 0.14, + "Ge88": 0.066, + "Ge89": 0.039, + "As60": 0.0083, + "As61": 0.0166, + "As62": 0.0259, + "As63": 0.0921, + "As64": 0.036, + "As65": 0.128, + "As66": 0.09579, + "As67": 42.5, + "As68": 151.6, + "As69": 913.8, + "As70": 3156.0, + "As71": 235080.0, + "As72": 93600.0, + "As73": 6937920.0, + "As74": 1535328.0, + "As75_m1": 0.01762, + "As76": 94464.0, + "As77": 139788.0, + "As78": 5442.0, + "As79": 540.6, + "As80": 15.2, + "As81": 33.3, + "As82": 19.1, + "As82_m1": 13.6, + "As83": 13.4, + "As84": 4.2, + "As85": 2.021, + "As86": 0.945, + "As87": 0.56, + "As88": 0.112, + "As89": 0.059, + "As90": 0.043, + "As91": 0.044, + "As92": 0.027, + "Se65": 0.05, + "Se66": 0.033, + "Se67": 0.136, + "Se68": 35.5, + "Se69": 27.4, + "Se70": 2466.0, + "Se71": 284.4, + "Se72": 725760.0, + "Se73": 25740.0, + "Se73_m1": 2388.0, + "Se75": 10349860.0, + "Se77_m1": 17.36, + "Se79": 9309490000000.0, + "Se79_m1": 235.2, + "Se81": 1107.0, + "Se81_m1": 3436.8, + "Se83": 1338.0, + "Se83_m1": 70.1, + "Se84": 195.6, + "Se85": 31.7, + "Se86": 14.3, + "Se87": 5.5, + "Se88": 1.53, + "Se89": 0.41, + "Se90": 0.161, + "Se91": 0.27, + "Se92": 0.093, + "Se93": 0.062, + "Se94": 0.059, + "Br67": 0.0443, + "Br68": 1.2e-06, + "Br69": 2.4e-08, + "Br70": 0.0791, + "Br70_m1": 2.2, + "Br71": 21.4, + "Br72": 78.6, + "Br72_m1": 10.6, + "Br73": 204.0, + "Br74": 1524.0, + "Br74_m1": 2760.0, + "Br75": 5802.0, + "Br76": 58320.0, + "Br76_m1": 1.31, + "Br77": 205329.6, + "Br77_m1": 256.8, + "Br78": 387.0, + "Br79_m1": 4.86, + "Br80": 1060.8, + "Br80_m1": 15913.8, + "Br82": 127015.2, + "Br82_m1": 367.8, + "Br83": 8640.0, + "Br84": 1905.6, + "Br84_m1": 360.0, + "Br85": 174.0, + "Br86": 55.0, + "Br87": 55.65, + "Br88": 16.29, + "Br89": 4.4, + "Br90": 1.92, + "Br91": 0.541, + "Br92": 0.343, + "Br93": 0.102, + "Br94": 0.07, + "Br95": 0.066, + "Br96": 0.042, + "Br97": 0.04, + "Kr69": 0.032, + "Kr70": 0.052, + "Kr71": 0.1, + "Kr72": 17.1, + "Kr73": 27.3, + "Kr74": 690.0, + "Kr75": 257.4, + "Kr76": 53280.0, + "Kr77": 4464.0, + "Kr79": 126144.0, + "Kr79_m1": 50.0, + "Kr81": 7226690000000.0, + "Kr81_m1": 13.1, + "Kr83_m1": 6588.0, + "Kr85": 339433500.0, + "Kr85_m1": 16128.0, + "Kr87": 4578.0, + "Kr88": 10224.0, + "Kr89": 189.0, + "Kr90": 32.32, + "Kr91": 8.57, + "Kr92": 1.84, + "Kr93": 1.286, + "Kr94": 0.212, + "Kr95": 0.114, + "Kr96": 0.08, + "Kr97": 0.063, + "Kr98": 0.046, + "Kr99": 0.027, + "Kr100": 0.007, + "Rb71": 1e-09, + "Rb72": 1.2e-06, + "Rb73": 3e-08, + "Rb74": 0.064776, + "Rb75": 19.0, + "Rb76": 36.5, + "Rb77": 226.2, + "Rb78": 1059.6, + "Rb78_m1": 344.4, + "Rb79": 1374.0, + "Rb80": 34.0, + "Rb81": 16459.2, + "Rb81_m1": 1830.0, + "Rb82": 75.45, + "Rb82_m1": 23299.2, + "Rb83": 7447680.0, + "Rb84": 2835648.0, + "Rb84_m1": 1215.6, + "Rb86": 1609718.0, + "Rb86_m1": 61.02, + "Rb87": 1.51792e18, + "Rb88": 1066.38, + "Rb89": 909.0, + "Rb90": 158.0, + "Rb90_m1": 258.0, + "Rb91": 58.4, + "Rb92": 4.492, + "Rb93": 5.84, + "Rb94": 2.702, + "Rb95": 0.3777, + "Rb96": 0.203, + "Rb97": 0.1691, + "Rb98": 0.114, + "Rb98_m1": 0.096, + "Rb99": 0.054, + "Rb100": 0.051, + "Rb101": 0.032, + "Rb102": 0.037, + "Sr73": 0.025, + "Sr74": 1.2e-06, + "Sr75": 0.088, + "Sr76": 7.89, + "Sr77": 9.0, + "Sr78": 150.0, + "Sr79": 135.0, + "Sr80": 6378.0, + "Sr81": 1338.0, + "Sr82": 2190240.0, + "Sr83": 116676.0, + "Sr83_m1": 4.95, + "Sr85": 5602176.0, + "Sr85_m1": 4057.8, + "Sr87_m1": 10134.0, + "Sr89": 4365792.0, + "Sr90": 908543300.0, + "Sr91": 34668.0, + "Sr92": 9756.0, + "Sr93": 445.38, + "Sr94": 75.3, + "Sr95": 23.9, + "Sr96": 1.07, + "Sr97": 0.429, + "Sr98": 0.653, + "Sr99": 0.27, + "Sr100": 0.202, + "Sr101": 0.118, + "Sr102": 0.069, + "Sr103": 0.068, + "Sr104": 0.043, + "Sr105": 0.0556, + "Y76": 2e-07, + "Y77": 0.062, + "Y78": 0.05, + "Y78_m1": 5.7, + "Y79": 14.8, + "Y80": 30.1, + "Y80_m1": 4.8, + "Y81": 70.4, + "Y82": 8.3, + "Y83": 424.8, + "Y83_m1": 171.0, + "Y84": 2370.0, + "Y84_m1": 4.6, + "Y85": 9648.0, + "Y85_m1": 17496.0, + "Y86": 53064.0, + "Y86_m1": 2880.0, + "Y87": 287280.0, + "Y87_m1": 48132.0, + "Y88": 9212486.0, + "Y88_m1": 0.000301, + "Y88_m2": 0.01397, + "Y89_m1": 15.663, + "Y90": 230400.0, + "Y90_m1": 11484.0, + "Y91": 5055264.0, + "Y91_m1": 2982.6, + "Y92": 12744.0, + "Y93": 36648.0, + "Y93_m1": 0.82, + "Y94": 1122.0, + "Y95": 618.0, + "Y96": 5.34, + "Y96_m1": 9.6, + "Y97": 3.75, + "Y97_m1": 1.17, + "Y97_m2": 0.142, + "Y98": 0.548, + "Y98_m1": 2.0, + "Y99": 1.47, + "Y100": 0.735, + "Y100_m1": 0.94, + "Y101": 0.45, + "Y102": 0.36, + "Y102_m1": 0.298, + "Y103": 0.23, + "Y104": 0.18, + "Y105": 0.088, + "Y106": 0.066, + "Y107": 0.03, + "Y108": 0.048, + "Zr78": 2e-07, + "Zr79": 0.056, + "Zr80": 4.6, + "Zr81": 5.5, + "Zr82": 32.0, + "Zr83": 41.6, + "Zr84": 1554.0, + "Zr85": 471.6, + "Zr85_m1": 10.9, + "Zr86": 59400.0, + "Zr87": 6048.0, + "Zr87_m1": 14.0, + "Zr88": 7205760.0, + "Zr89": 282276.0, + "Zr89_m1": 249.66, + "Zr90_m1": 0.8092, + "Zr93": 48283100000000.0, + "Zr95": 5532365.0, + "Zr96": 6.31152e26, + "Zr97": 60296.4, + "Zr98": 30.7, + "Zr99": 2.1, + "Zr100": 7.1, + "Zr101": 2.3, + "Zr102": 2.9, + "Zr103": 1.3, + "Zr104": 1.2, + "Zr105": 0.6, + "Zr106": 0.27, + "Zr107": 0.15, + "Zr108": 0.08, + "Zr109": 0.117, + "Zr110": 0.098, + "Nb81": 0.8, + "Nb82": 0.05, + "Nb83": 4.1, + "Nb84": 9.8, + "Nb85": 20.9, + "Nb85_m1": 3.3, + "Nb86": 88.0, + "Nb87": 225.0, + "Nb87_m1": 156.0, + "Nb88": 873.0, + "Nb88_m1": 466.8, + "Nb89": 7308.0, + "Nb89_m1": 3960.0, + "Nb90": 52560.0, + "Nb90_m1": 18.81, + "Nb90_m2": 0.00619, + "Nb91": 21459200000.0, + "Nb91_m1": 5258304.0, + "Nb92": 1095050000000000.0, + "Nb92_m1": 876960.0, + "Nb93_m1": 509024100.0, + "Nb94": 640619000000.0, + "Nb94_m1": 375.78, + "Nb95": 3023222.0, + "Nb95_m1": 311904.0, + "Nb96": 84060.0, + "Nb97": 4326.0, + "Nb97_m1": 58.7, + "Nb98": 2.86, + "Nb98_m1": 3078.0, + "Nb99": 15.0, + "Nb99_m1": 150.0, + "Nb100": 1.5, + "Nb100_m1": 2.99, + "Nb101": 7.1, + "Nb102": 4.3, + "Nb102_m1": 1.3, + "Nb103": 1.5, + "Nb104": 4.9, + "Nb104_m1": 0.94, + "Nb105": 2.95, + "Nb106": 0.93, + "Nb107": 0.3, + "Nb108": 0.193, + "Nb109": 0.19, + "Nb110": 0.17, + "Nb111": 0.08, + "Nb112": 0.069, + "Nb113": 0.03, + "Mo83": 0.0195, + "Mo84": 3.8, + "Mo85": 3.2, + "Mo86": 19.6, + "Mo87": 14.02, + "Mo88": 480.0, + "Mo89": 126.6, + "Mo89_m1": 0.19, + "Mo90": 20412.0, + "Mo91": 929.4, + "Mo91_m1": 64.6, + "Mo93": 126230000000.0, + "Mo93_m1": 24660.0, + "Mo99": 237513.6, + "Mo100": 2.3037e26, + "Mo101": 876.6, + "Mo102": 678.0, + "Mo103": 67.5, + "Mo104": 60.0, + "Mo105": 35.6, + "Mo106": 8.73, + "Mo107": 3.5, + "Mo108": 1.09, + "Mo109": 0.53, + "Mo110": 0.3, + "Mo111": 0.2, + "Mo112": 0.287, + "Mo113": 0.1, + "Mo114": 0.08, + "Mo115": 0.092, + "Tc85": 0.5, + "Tc86": 0.054, + "Tc86_m1": 1.1e-06, + "Tc87": 2.2, + "Tc88": 5.8, + "Tc88_m1": 6.4, + "Tc89": 12.8, + "Tc89_m1": 12.9, + "Tc90": 8.7, + "Tc90_m1": 49.2, + "Tc91": 188.4, + "Tc91_m1": 198.0, + "Tc92": 255.0, + "Tc93": 9900.0, + "Tc93_m1": 2610.0, + "Tc94": 17580.0, + "Tc94_m1": 3120.0, + "Tc95": 72000.0, + "Tc95_m1": 5270400.0, + "Tc96": 369792.0, + "Tc96_m1": 3090.0, + "Tc97": 132857000000000.0, + "Tc97_m1": 7862400.0, + "Tc98": 132542000000000.0, + "Tc99": 6661810000000.0, + "Tc99_m1": 21624.12, + "Tc100": 15.46, + "Tc101": 852.0, + "Tc102": 5.28, + "Tc102_m1": 261.0, + "Tc103": 54.2, + "Tc104": 1098.0, + "Tc105": 456.0, + "Tc106": 35.6, + "Tc107": 21.2, + "Tc108": 5.17, + "Tc109": 0.86, + "Tc110": 0.92, + "Tc111": 0.29, + "Tc112": 0.28, + "Tc113": 0.16, + "Tc114": 0.15, + "Tc115": 0.073, + "Tc116": 0.09, + "Tc117": 0.04, + "Tc118": 0.066, + "Ru87": 1.5e-06, + "Ru88": 1.25, + "Ru89": 1.5, + "Ru90": 11.7, + "Ru91": 7.9, + "Ru91_m1": 7.6, + "Ru92": 219.0, + "Ru93": 59.7, + "Ru93_m1": 10.8, + "Ru94": 3108.0, + "Ru95": 5914.8, + "Ru97": 244512.0, + "Ru103": 3390941.0, + "Ru103_m1": 0.00169, + "Ru105": 15984.0, + "Ru106": 32123520.0, + "Ru107": 225.0, + "Ru108": 273.0, + "Ru109": 34.5, + "Ru110": 11.6, + "Ru111": 2.12, + "Ru112": 1.75, + "Ru113": 0.8, + "Ru113_m1": 0.51, + "Ru114": 0.52, + "Ru115": 0.74, + "Ru116": 0.204, + "Ru117": 0.142, + "Ru118": 0.123, + "Ru119": 0.162, + "Ru120": 0.149, + "Rh89": 1.5e-06, + "Rh90": 0.0145, + "Rh90_m1": 1.05, + "Rh91": 1.47, + "Rh92": 4.66, + "Rh93": 11.9, + "Rh94": 70.6, + "Rh94_m1": 25.8, + "Rh95": 301.2, + "Rh95_m1": 117.6, + "Rh96": 594.0, + "Rh96_m1": 90.6, + "Rh97": 1842.0, + "Rh97_m1": 2772.0, + "Rh98": 523.2, + "Rh98_m1": 216.0, + "Rh99": 1391040.0, + "Rh99_m1": 16920.0, + "Rh100": 74880.0, + "Rh100_m1": 276.0, + "Rh101": 104140100.0, + "Rh101_m1": 374976.0, + "Rh102": 17910720.0, + "Rh102_m1": 118088500.0, + "Rh103_m1": 3366.84, + "Rh104": 42.3, + "Rh104_m1": 260.4, + "Rh105": 127296.0, + "Rh105_m1": 40.0, + "Rh106": 30.07, + "Rh106_m1": 7860.0, + "Rh107": 1302.0, + "Rh108": 16.8, + "Rh108_m1": 360.0, + "Rh109": 80.0, + "Rh110": 3.2, + "Rh110_m1": 28.5, + "Rh111": 11.0, + "Rh112": 2.1, + "Rh112_m1": 6.73, + "Rh113": 2.8, + "Rh114": 1.85, + "Rh115": 0.99, + "Rh116": 0.68, + "Rh116_m1": 0.57, + "Rh117": 0.44, + "Rh118": 0.266, + "Rh119": 0.171, + "Rh120": 0.136, + "Rh121": 0.151, + "Rh122": 0.108, + "Rh123": 0.0489, + "Pd91": 1e-06, + "Pd92": 0.8, + "Pd93": 1.3, + "Pd94": 9.0, + "Pd95": 10.0, + "Pd95_m1": 13.3, + "Pd96": 122.0, + "Pd97": 186.0, + "Pd98": 1062.0, + "Pd99": 1284.0, + "Pd100": 313632.0, + "Pd101": 30492.0, + "Pd103": 1468022.0, + "Pd107": 205124000000000.0, + "Pd107_m1": 21.3, + "Pd109": 49324.32, + "Pd109_m1": 281.4, + "Pd111": 1404.0, + "Pd111_m1": 19800.0, + "Pd112": 75708.0, + "Pd113": 93.0, + "Pd113_m1": 0.3, + "Pd114": 145.2, + "Pd115": 25.0, + "Pd115_m1": 50.0, + "Pd116": 11.8, + "Pd117": 4.3, + "Pd117_m1": 0.0191, + "Pd118": 1.9, + "Pd119": 0.92, + "Pd120": 0.5, + "Pd121": 0.285, + "Pd122": 0.175, + "Pd123": 0.244, + "Pd124": 0.038, + "Pd125": 0.3987, + "Pd126": 0.2499, + "Ag93": 1.5e-06, + "Ag94": 0.035, + "Ag94_m1": 0.55, + "Ag94_m2": 0.4, + "Ag95": 2.0, + "Ag95_m1": 0.5, + "Ag95_m2": 0.016, + "Ag95_m3": 0.04, + "Ag96": 4.4, + "Ag96_m1": 6.9, + "Ag97": 25.5, + "Ag98": 47.5, + "Ag99": 124.0, + "Ag99_m1": 10.5, + "Ag100": 120.6, + "Ag100_m1": 134.4, + "Ag101": 666.0, + "Ag101_m1": 3.1, + "Ag102": 774.0, + "Ag102_m1": 462.0, + "Ag103": 3942.0, + "Ag103_m1": 5.7, + "Ag104": 4152.0, + "Ag104_m1": 2010.0, + "Ag105": 3567456.0, + "Ag105_m1": 433.8, + "Ag106": 1437.6, + "Ag106_m1": 715392.0, + "Ag107_m1": 44.3, + "Ag108": 142.92, + "Ag108_m1": 13822200000.0, + "Ag109_m1": 39.6, + "Ag110": 24.6, + "Ag110_m1": 21579260.0, + "Ag111": 643680.0, + "Ag111_m1": 64.8, + "Ag112": 11268.0, + "Ag113": 19332.0, + "Ag113_m1": 68.7, + "Ag114": 4.6, + "Ag114_m1": 0.0015, + "Ag115": 1200.0, + "Ag115_m1": 18.0, + "Ag116": 237.0, + "Ag116_m1": 20.0, + "Ag116_m2": 9.3, + "Ag117": 72.8, + "Ag117_m1": 5.34, + "Ag118": 3.76, + "Ag118_m1": 2.0, + "Ag119": 2.1, + "Ag119_m1": 6.0, + "Ag120": 1.23, + "Ag120_m1": 0.32, + "Ag121": 0.78, + "Ag122": 0.529, + "Ag122_m1": 0.2, + "Ag123": 0.3, + "Ag124": 0.172, + "Ag125": 0.166, + "Ag126": 0.107, + "Ag127": 0.109, + "Ag128": 0.058, + "Ag129": 0.046, + "Ag130": 0.05, + "Cd95": 0.005, + "Cd96": 1.0, + "Cd97": 2.8, + "Cd98": 9.2, + "Cd99": 16.0, + "Cd100": 49.1, + "Cd101": 81.6, + "Cd102": 330.0, + "Cd103": 438.0, + "Cd104": 3462.0, + "Cd105": 3330.0, + "Cd107": 23400.0, + "Cd109": 39864960.0, + "Cd111_m1": 2912.4, + "Cd113": 2.53723e23, + "Cd113_m1": 444962200.0, + "Cd115": 192456.0, + "Cd115_m1": 3849984.0, + "Cd116": 9.78286e26, + "Cd117": 8964.0, + "Cd117_m1": 12096.0, + "Cd118": 3018.0, + "Cd119": 161.4, + "Cd119_m1": 132.0, + "Cd120": 50.8, + "Cd121": 13.5, + "Cd121_m1": 8.3, + "Cd122": 5.24, + "Cd123": 2.1, + "Cd123_m1": 1.82, + "Cd124": 1.25, + "Cd125": 0.68, + "Cd125_m1": 0.48, + "Cd126": 0.515, + "Cd127": 0.37, + "Cd128": 0.28, + "Cd129": 0.27, + "Cd130": 0.162, + "Cd131": 0.068, + "Cd132": 0.097, + "In97": 0.005, + "In98": 0.0425, + "In98_m1": 1.6, + "In99": 3.05, + "In100": 5.9, + "In101": 15.1, + "In102": 23.3, + "In103": 65.0, + "In103_m1": 34.0, + "In104": 108.0, + "In104_m1": 15.7, + "In105": 304.2, + "In105_m1": 48.0, + "In106": 372.0, + "In106_m1": 312.0, + "In107": 1944.0, + "In107_m1": 50.4, + "In108": 3480.0, + "In108_m1": 2376.0, + "In109": 15001.2, + "In109_m1": 80.4, + "In109_m2": 0.209, + "In110": 17640.0, + "In110_m1": 4146.0, + "In111": 242326.1, + "In111_m1": 462.0, + "In112": 898.2, + "In112_m1": 1233.6, + "In113_m1": 5968.56, + "In114": 71.9, + "In114_m1": 4277664.0, + "In114_m2": 0.0431, + "In115": 1.39169e22, + "In115_m1": 16149.6, + "In116": 14.1, + "In116_m1": 3257.4, + "In116_m2": 2.18, + "In117": 2592.0, + "In117_m1": 6972.0, + "In118": 5.0, + "In118_m1": 267.0, + "In118_m2": 8.5, + "In119": 144.0, + "In119_m1": 1080.0, + "In120": 3.08, + "In120_m1": 46.2, + "In120_m2": 47.3, + "In121": 23.1, + "In121_m1": 232.8, + "In122": 1.5, + "In122_m1": 10.3, + "In122_m2": 10.8, + "In123": 6.17, + "In123_m1": 47.4, + "In124": 3.12, + "In124_m1": 3.7, + "In125": 2.36, + "In125_m1": 12.2, + "In126": 1.53, + "In126_m1": 1.64, + "In127": 1.09, + "In127_m1": 3.67, + "In128": 0.84, + "In128_m1": 0.72, + "In129": 0.61, + "In129_m1": 1.23, + "In130": 0.29, + "In130_m1": 0.54, + "In130_m2": 0.54, + "In131": 0.28, + "In131_m1": 0.35, + "In131_m2": 0.32, + "In132": 0.207, + "In133": 0.165, + "In133_m1": 0.18, + "In134": 0.14, + "In135": 0.092, + "Sn99": 0.005, + "Sn100": 0.86, + "Sn101": 1.7, + "Sn102": 4.5, + "Sn103": 7.0, + "Sn104": 20.8, + "Sn105": 34.0, + "Sn106": 115.0, + "Sn107": 174.0, + "Sn108": 618.0, + "Sn109": 1080.0, + "Sn110": 14796.0, + "Sn111": 2118.0, + "Sn113": 9943776.0, + "Sn113_m1": 1284.0, + "Sn117_m1": 1175040.0, + "Sn119_m1": 25315200.0, + "Sn121": 97308.0, + "Sn121_m1": 1385380000.0, + "Sn123": 11162880.0, + "Sn123_m1": 2403.6, + "Sn125": 832896.0, + "Sn125_m1": 571.2, + "Sn126": 7258250000000.0, + "Sn127": 7560.0, + "Sn127_m1": 247.8, + "Sn128": 3544.2, + "Sn128_m1": 6.5, + "Sn129": 133.8, + "Sn129_m1": 414.0, + "Sn130": 223.2, + "Sn130_m1": 102.0, + "Sn131": 56.0, + "Sn131_m1": 58.4, + "Sn132": 39.7, + "Sn133": 1.46, + "Sn134": 1.05, + "Sn135": 0.53, + "Sn136": 0.25, + "Sn137": 0.19, + "Sb103": 1.5e-06, + "Sb104": 0.46, + "Sb105": 1.22, + "Sb106": 0.6, + "Sb107": 4.0, + "Sb108": 7.4, + "Sb109": 17.0, + "Sb110": 23.0, + "Sb111": 75.0, + "Sb112": 51.4, + "Sb113": 400.2, + "Sb114": 209.4, + "Sb115": 1926.0, + "Sb116": 948.0, + "Sb116_m1": 3618.0, + "Sb117": 10080.0, + "Sb118": 216.0, + "Sb118_m1": 18000.0, + "Sb119": 137484.0, + "Sb119_m1": 0.85, + "Sb120": 953.4, + "Sb120_m1": 497664.0, + "Sb122": 235336.3, + "Sb122_m1": 251.46, + "Sb124": 5201280.0, + "Sb124_m1": 93.0, + "Sb124_m2": 1212.0, + "Sb125": 87053530.0, + "Sb126": 1067040.0, + "Sb126_m1": 1149.0, + "Sb126_m2": 11.0, + "Sb127": 332640.0, + "Sb128": 32436.0, + "Sb128_m1": 624.0, + "Sb129": 15840.0, + "Sb129_m1": 1062.0, + "Sb130": 2370.0, + "Sb130_m1": 378.0, + "Sb131": 1381.8, + "Sb132": 167.4, + "Sb132_m1": 246.0, + "Sb133": 150.0, + "Sb134": 0.78, + "Sb134_m1": 10.07, + "Sb135": 1.679, + "Sb136": 0.923, + "Sb137": 0.45, + "Sb138": 0.168, + "Sb139": 0.127, + "Te105": 6.2e-07, + "Te106": 6e-05, + "Te107": 0.0031, + "Te108": 2.1, + "Te109": 4.6, + "Te110": 18.6, + "Te111": 19.3, + "Te112": 120.0, + "Te113": 102.0, + "Te114": 912.0, + "Te115": 348.0, + "Te115_m1": 402.0, + "Te116": 8964.0, + "Te117": 3720.0, + "Te117_m1": 0.103, + "Te118": 518400.0, + "Te119": 57780.0, + "Te119_m1": 406080.0, + "Te121": 1656288.0, + "Te121_m1": 14186880.0, + "Te123_m1": 10298880.0, + "Te125_m1": 4959360.0, + "Te127": 33660.0, + "Te127_m1": 9417600.0, + "Te128": 2.77707e26, + "Te129": 4176.0, + "Te129_m1": 2903040.0, + "Te131": 1500.0, + "Te131_m1": 119700.0, + "Te132": 276825.6, + "Te133": 750.0, + "Te133_m1": 3324.0, + "Te134": 2508.0, + "Te135": 19.0, + "Te136": 17.5, + "Te137": 2.49, + "Te138": 1.4, + "Te139": 0.347, + "Te140": 0.304, + "Te141": 0.213, + "Te142": 0.2, + "I108": 0.036, + "I109": 0.000103, + "I110": 0.65, + "I111": 2.5, + "I112": 3.42, + "I113": 6.6, + "I114": 2.1, + "I114_m1": 6.2, + "I115": 78.0, + "I116": 2.91, + "I117": 133.2, + "I118": 822.0, + "I118_m1": 510.0, + "I119": 1146.0, + "I120": 4896.0, + "I120_m1": 3180.0, + "I121": 7632.0, + "I122": 217.8, + "I123": 47604.24, + "I124": 360806.4, + "I125": 5132160.0, + "I126": 1117152.0, + "I128": 1499.4, + "I129": 495454000000000.0, + "I130": 44496.0, + "I130_m1": 530.4, + "I131": 693377.3, + "I132": 8262.0, + "I132_m1": 4993.2, + "I133": 74880.0, + "I133_m1": 9.0, + "I134": 3150.0, + "I134_m1": 211.2, + "I135": 23652.0, + "I136": 83.4, + "I136_m1": 46.9, + "I137": 24.5, + "I138": 6.23, + "I139": 2.28, + "I140": 0.86, + "I141": 0.43, + "I142": 0.222, + "I143": 0.296, + "I144": 0.194, + "I145": 0.127, + "Xe110": 0.093, + "Xe111": 0.81, + "Xe112": 2.7, + "Xe113": 2.74, + "Xe114": 10.0, + "Xe115": 18.0, + "Xe116": 59.0, + "Xe117": 61.0, + "Xe118": 228.0, + "Xe119": 348.0, + "Xe120": 2400.0, + "Xe121": 2406.0, + "Xe122": 72360.0, + "Xe123": 7488.0, + "Xe125": 60840.0, + "Xe125_m1": 56.9, + "Xe127": 3144960.0, + "Xe127_m1": 69.2, + "Xe129_m1": 767232.0, + "Xe131_m1": 1022976.0, + "Xe132_m1": 0.00839, + "Xe133": 452995.2, + "Xe133_m1": 189216.0, + "Xe134_m1": 0.29, + "Xe135": 32904.0, + "Xe135_m1": 917.4, + "Xe137": 229.08, + "Xe138": 844.8, + "Xe139": 39.68, + "Xe140": 13.6, + "Xe141": 1.73, + "Xe142": 1.23, + "Xe143": 0.3, + "Xe144": 1.15, + "Xe145": 0.188, + "Xe146": 0.369, + "Xe147": 0.1, + "Cs112": 0.0005, + "Cs113": 1.67e-05, + "Cs114": 0.57, + "Cs115": 1.4, + "Cs116": 0.7, + "Cs116_m1": 3.85, + "Cs117": 8.4, + "Cs117_m1": 6.5, + "Cs118": 14.0, + "Cs118_m1": 17.0, + "Cs119": 43.0, + "Cs119_m1": 30.4, + "Cs120": 61.3, + "Cs120_m1": 57.0, + "Cs121": 155.0, + "Cs121_m1": 122.0, + "Cs122": 21.18, + "Cs122_m1": 0.36, + "Cs122_m2": 222.0, + "Cs123": 352.8, + "Cs123_m1": 1.64, + "Cs124": 30.8, + "Cs124_m1": 6.3, + "Cs125": 2802.0, + "Cs125_m1": 0.0009, + "Cs126": 98.4, + "Cs127": 22500.0, + "Cs128": 217.2, + "Cs129": 115416.0, + "Cs130": 1752.6, + "Cs130_m1": 207.6, + "Cs131": 837129.6, + "Cs132": 559872.0, + "Cs134": 65172760.0, + "Cs134_m1": 10483.2, + "Cs135": 72582500000000.0, + "Cs135_m1": 3180.0, + "Cs136": 1137024.0, + "Cs136_m1": 19.0, + "Cs137": 949252600.0, + "Cs138": 2004.6, + "Cs138_m1": 174.6, + "Cs139": 556.2, + "Cs140": 63.7, + "Cs141": 24.84, + "Cs142": 1.684, + "Cs143": 1.791, + "Cs144": 0.994, + "Cs144_m1": 1.0, + "Cs145": 0.587, + "Cs146": 0.321, + "Cs147": 0.23, + "Cs148": 0.146, + "Cs149": 0.05, + "Cs150": 0.05, + "Cs151": 0.05, + "Ba114": 0.43, + "Ba115": 0.45, + "Ba116": 1.3, + "Ba117": 1.75, + "Ba118": 5.5, + "Ba119": 5.4, + "Ba120": 24.0, + "Ba121": 29.7, + "Ba122": 117.0, + "Ba123": 162.0, + "Ba124": 660.0, + "Ba125": 210.0, + "Ba126": 6000.0, + "Ba127": 762.0, + "Ba127_m1": 1.9, + "Ba128": 209952.0, + "Ba129": 8028.0, + "Ba129_m1": 7776.0, + "Ba130_m1": 0.0094, + "Ba131": 993600.0, + "Ba131_m1": 876.0, + "Ba133": 331862400.0, + "Ba133_m1": 140040.0, + "Ba135_m1": 103320.0, + "Ba136_m1": 0.3084, + "Ba137_m1": 153.12, + "Ba139": 4983.6, + "Ba140": 1101833.0, + "Ba141": 1096.2, + "Ba142": 636.0, + "Ba143": 14.5, + "Ba144": 11.5, + "Ba145": 4.31, + "Ba146": 2.22, + "Ba147": 0.894, + "Ba148": 0.612, + "Ba149": 0.344, + "Ba150": 0.3, + "Ba151": 0.259, + "Ba152": 0.228, + "Ba153": 0.158, + "La117": 0.0235, + "La117_m1": 0.01, + "La118": 1.0, + "La119": 2.0, + "La120": 2.8, + "La121": 5.3, + "La122": 8.6, + "La123": 17.0, + "La124": 29.21, + "La124_m1": 21.0, + "La125": 64.8, + "La125_m1": 0.4, + "La126": 54.0, + "La126_m1": 50.0, + "La127": 306.0, + "La127_m1": 222.0, + "La128": 310.8, + "La128_m1": 60.0, + "La129": 696.0, + "La129_m1": 0.56, + "La130": 522.0, + "La131": 3540.0, + "La132": 17280.0, + "La132_m1": 1458.0, + "La133": 14083.2, + "La134": 387.0, + "La135": 70200.0, + "La136": 592.2, + "La136_m1": 0.114, + "La137": 1893460000000.0, + "La138": 3.21888e18, + "La140": 145026.7, + "La141": 14112.0, + "La142": 5466.0, + "La143": 852.0, + "La144": 40.8, + "La145": 24.8, + "La146": 6.27, + "La146_m1": 10.0, + "La147": 4.06, + "La148": 1.26, + "La149": 1.05, + "La150": 0.86, + "La151": 0.778, + "La152": 0.451, + "La153": 0.342, + "La154": 0.228, + "La155": 0.184, + "Ce119": 0.2, + "Ce120": 0.25, + "Ce121": 1.1, + "Ce122": 2.73, + "Ce123": 3.8, + "Ce124": 6.0, + "Ce125": 10.2, + "Ce126": 51.0, + "Ce127": 31.0, + "Ce127_m1": 28.6, + "Ce128": 235.8, + "Ce129": 210.0, + "Ce130": 1374.0, + "Ce131": 618.0, + "Ce131_m1": 324.0, + "Ce132": 12636.0, + "Ce132_m1": 0.0094, + "Ce133": 5820.0, + "Ce133_m1": 17640.0, + "Ce134": 273024.0, + "Ce135": 63720.0, + "Ce135_m1": 20.0, + "Ce137": 32400.0, + "Ce137_m1": 123840.0, + "Ce138_m1": 0.00865, + "Ce139": 11892180.0, + "Ce139_m1": 54.8, + "Ce141": 2808691.0, + "Ce143": 118940.4, + "Ce144": 24616220.0, + "Ce145": 180.6, + "Ce146": 811.2, + "Ce147": 56.4, + "Ce148": 56.0, + "Ce149": 5.3, + "Ce150": 4.0, + "Ce151": 1.76, + "Ce152": 1.4, + "Ce153": 0.979, + "Ce154": 0.775, + "Ce155": 0.471, + "Ce156": 0.369, + "Ce157": 0.2428, + "Pr121": 1.4, + "Pr122": 0.5, + "Pr123": 0.8, + "Pr124": 1.2, + "Pr125": 3.3, + "Pr126": 3.14, + "Pr127": 4.2, + "Pr128": 2.85, + "Pr129": 32.0, + "Pr130": 40.0, + "Pr131": 90.6, + "Pr131_m1": 5.73, + "Pr132": 96.0, + "Pr133": 390.0, + "Pr134": 1020.0, + "Pr134_m1": 660.0, + "Pr135": 1440.0, + "Pr136": 786.0, + "Pr137": 4608.0, + "Pr138": 87.0, + "Pr138_m1": 7632.0, + "Pr139": 15876.0, + "Pr140": 203.4, + "Pr142": 68832.0, + "Pr142_m1": 876.0, + "Pr143": 1172448.0, + "Pr144": 1036.8, + "Pr144_m1": 432.0, + "Pr145": 21542.4, + "Pr146": 1449.0, + "Pr147": 804.0, + "Pr148": 137.4, + "Pr148_m1": 120.6, + "Pr149": 135.6, + "Pr150": 6.19, + "Pr151": 18.9, + "Pr152": 3.63, + "Pr153": 4.28, + "Pr154": 2.3, + "Pr155": 0.852, + "Pr156": 0.733, + "Pr157": 0.598, + "Pr158": 0.1342, + "Pr159": 0.1055, + "Nd124": 0.5, + "Nd125": 0.6, + "Nd126": 2e-07, + "Nd127": 1.8, + "Nd128": 5.0, + "Nd129": 4.9, + "Nd130": 21.0, + "Nd131": 26.0, + "Nd132": 94.0, + "Nd133": 70.0, + "Nd133_m1": 70.0, + "Nd134": 510.0, + "Nd135": 744.0, + "Nd135_m1": 330.0, + "Nd136": 3039.0, + "Nd137": 2310.0, + "Nd137_m1": 1.6, + "Nd138": 18144.0, + "Nd139": 1782.0, + "Nd139_m1": 19800.0, + "Nd140": 291168.0, + "Nd141": 8964.0, + "Nd141_m1": 62.0, + "Nd144": 7.22669e22, + "Nd147": 948672.0, + "Nd149": 6220.8, + "Nd150": 2.49305e26, + "Nd151": 746.4, + "Nd152": 684.0, + "Nd153": 31.6, + "Nd154": 25.9, + "Nd155": 8.9, + "Nd156": 5.49, + "Nd157": 1.906, + "Nd158": 1.331, + "Nd159": 0.773, + "Nd160": 0.5883, + "Nd161": 0.4884, + "Pm126": 0.5, + "Pm127": 1.0, + "Pm128": 1.0, + "Pm129": 2.4, + "Pm130": 2.6, + "Pm131": 6.3, + "Pm132": 6.2, + "Pm133": 15.0, + "Pm133_m1": 8.8, + "Pm134": 5.0, + "Pm134_m1": 22.0, + "Pm135": 49.0, + "Pm135_m1": 45.0, + "Pm136": 47.0, + "Pm136_m1": 107.0, + "Pm137": 144.0, + "Pm138": 10.0, + "Pm138_m1": 194.4, + "Pm139": 249.0, + "Pm139_m1": 0.18, + "Pm140": 357.0, + "Pm140_m1": 357.0, + "Pm141": 1254.0, + "Pm142": 40.5, + "Pm142_m1": 0.002, + "Pm143": 22896000.0, + "Pm144": 31363200.0, + "Pm145": 558569500.0, + "Pm146": 174513500.0, + "Pm147": 82788210.0, + "Pm148": 463795.2, + "Pm148_m1": 3567456.0, + "Pm149": 191088.0, + "Pm150": 9648.0, + "Pm151": 102240.0, + "Pm152": 247.2, + "Pm152_m1": 451.2, + "Pm152_m2": 828.0, + "Pm153": 315.0, + "Pm154": 103.8, + "Pm154_m1": 160.8, + "Pm155": 41.5, + "Pm156": 26.7, + "Pm157": 10.56, + "Pm158": 4.8, + "Pm159": 1.47, + "Pm160": 1.561, + "Pm161": 1.065, + "Pm162": 0.2679, + "Pm163": 0.2, + "Sm128": 0.5, + "Sm129": 0.55, + "Sm130": 1.0, + "Sm131": 1.2, + "Sm132": 4.0, + "Sm133": 3.7, + "Sm134": 9.5, + "Sm135": 10.3, + "Sm136": 47.0, + "Sm137": 45.0, + "Sm138": 186.0, + "Sm139": 154.2, + "Sm139_m1": 10.7, + "Sm140": 889.2, + "Sm141": 612.0, + "Sm141_m1": 1356.0, + "Sm142": 4349.4, + "Sm143": 525.0, + "Sm143_m1": 66.0, + "Sm143_m2": 0.03, + "Sm145": 29376000.0, + "Sm146": 3250430000000000.0, + "Sm147": 3.34511e18, + "Sm148": 2.20903e23, + "Sm151": 2840184000.0, + "Sm153": 167400.0, + "Sm153_m1": 0.0106, + "Sm155": 1338.0, + "Sm156": 33840.0, + "Sm157": 482.0, + "Sm158": 318.0, + "Sm159": 11.37, + "Sm160": 9.6, + "Sm161": 4.8, + "Sm162": 2.4, + "Sm163": 1.748, + "Sm164": 1.226, + "Sm165": 0.764, + "Eu130": 0.001, + "Eu131": 0.0178, + "Eu132": 0.1, + "Eu133": 1.0, + "Eu134": 0.5, + "Eu135": 1.5, + "Eu136": 3.8, + "Eu136_m1": 3.3, + "Eu136_m2": 3.8, + "Eu137": 11.0, + "Eu138": 12.1, + "Eu139": 17.9, + "Eu140": 1.51, + "Eu140_m1": 0.125, + "Eu141": 40.7, + "Eu141_m1": 2.7, + "Eu142": 2.34, + "Eu142_m1": 73.38, + "Eu143": 155.4, + "Eu144": 10.2, + "Eu145": 512352.0, + "Eu146": 396576.0, + "Eu147": 2082240.0, + "Eu148": 4708800.0, + "Eu149": 8043840.0, + "Eu150": 1164480000.0, + "Eu150_m1": 46080.0, + "Eu152": 427195200.0, + "Eu152_m1": 33521.76, + "Eu152_m2": 5760.0, + "Eu154": 271426900.0, + "Eu154_m1": 2760.0, + "Eu155": 149993300.0, + "Eu156": 1312416.0, + "Eu157": 54648.0, + "Eu158": 2754.0, + "Eu159": 1086.0, + "Eu160": 38.0, + "Eu161": 26.0, + "Eu162": 10.6, + "Eu163": 7.7, + "Eu164": 2.844, + "Eu165": 2.3, + "Eu166": 0.4, + "Eu167": 0.2, + "Gd134": 0.4, + "Gd135": 1.1, + "Gd136": 2e-05, + "Gd137": 2.2, + "Gd138": 4.7, + "Gd139": 5.8, + "Gd139_m1": 4.8, + "Gd140": 15.8, + "Gd141": 14.0, + "Gd141_m1": 24.5, + "Gd142": 70.2, + "Gd143": 39.0, + "Gd143_m1": 110.0, + "Gd144": 268.2, + "Gd145": 1380.0, + "Gd145_m1": 85.0, + "Gd146": 4170528.0, + "Gd147": 137016.0, + "Gd148": 2354197000.0, + "Gd149": 801792.0, + "Gd150": 56488100000000.0, + "Gd151": 10713600.0, + "Gd152": 3.40822e21, + "Gd153": 20770560.0, + "Gd155_m1": 0.03197, + "Gd159": 66524.4, + "Gd161": 219.6, + "Gd162": 504.0, + "Gd163": 68.0, + "Gd164": 45.0, + "Gd165": 10.3, + "Gd166": 4.8, + "Gd167": 3.0, + "Gd168": 0.3, + "Gd169": 1.0, + "Tb135": 0.995, + "Tb136": 0.2, + "Tb137": 0.6, + "Tb138": 2e-07, + "Tb139": 1.6, + "Tb140": 2.4, + "Tb141": 3.5, + "Tb141_m1": 7.9, + "Tb142": 0.597, + "Tb142_m1": 0.303, + "Tb143": 12.0, + "Tb143_m1": 21.0, + "Tb144": 1.0, + "Tb144_m1": 4.25, + "Tb145": 30.9, + "Tb145_m1": 30.9, + "Tb146": 8.0, + "Tb146_m1": 23.0, + "Tb146_m2": 0.00118, + "Tb147": 5904.0, + "Tb147_m1": 109.8, + "Tb148": 3600.0, + "Tb148_m1": 132.0, + "Tb149": 14824.8, + "Tb149_m1": 249.6, + "Tb150": 12528.0, + "Tb150_m1": 348.0, + "Tb151": 63392.4, + "Tb151_m1": 25.0, + "Tb152": 63000.0, + "Tb152_m1": 252.0, + "Tb153": 202176.0, + "Tb154": 77400.0, + "Tb154_m1": 33840.0, + "Tb154_m2": 81720.0, + "Tb155": 459648.0, + "Tb156": 462240.0, + "Tb156_m1": 87840.0, + "Tb156_m2": 19080.0, + "Tb157": 2240590000.0, + "Tb158": 5680368000.0, + "Tb158_m1": 10.7, + "Tb160": 6246720.0, + "Tb161": 596678.4, + "Tb162": 456.0, + "Tb163": 1170.0, + "Tb164": 180.0, + "Tb165": 126.6, + "Tb166": 25.1, + "Tb167": 19.4, + "Tb168": 8.2, + "Tb169": 2.0, + "Tb170": 3.0, + "Tb171": 0.5, + "Dy138": 0.2, + "Dy139": 0.6, + "Dy140": 0.84, + "Dy141": 0.9, + "Dy142": 2.3, + "Dy143": 3.2, + "Dy143_m1": 3.0, + "Dy144": 9.1, + "Dy145": 6.0, + "Dy145_m1": 14.1, + "Dy146": 29.0, + "Dy146_m1": 0.15, + "Dy147": 40.0, + "Dy147_m1": 55.7, + "Dy148": 198.0, + "Dy149": 252.0, + "Dy149_m1": 0.49, + "Dy150": 430.2, + "Dy151": 1074.0, + "Dy152": 8568.0, + "Dy153": 23040.0, + "Dy154": 94672800000000.0, + "Dy155": 35640.0, + "Dy157": 29304.0, + "Dy157_m1": 0.0216, + "Dy159": 12476160.0, + "Dy165": 8402.4, + "Dy165_m1": 75.42, + "Dy166": 293760.0, + "Dy167": 372.0, + "Dy168": 522.0, + "Dy169": 39.0, + "Dy170": 30.0, + "Dy171": 6.0, + "Dy172": 3.0, + "Dy173": 2.0, + "Ho140": 0.006, + "Ho141": 0.0041, + "Ho142": 0.4, + "Ho143": 2e-07, + "Ho144": 0.7, + "Ho145": 2.4, + "Ho146": 3.6, + "Ho147": 5.8, + "Ho148": 2.2, + "Ho148_m1": 9.59, + "Ho148_m2": 0.00236, + "Ho149": 21.1, + "Ho149_m1": 56.0, + "Ho150": 72.0, + "Ho150_m1": 23.3, + "Ho151": 35.2, + "Ho151_m1": 47.2, + "Ho152": 161.8, + "Ho152_m1": 50.0, + "Ho153": 120.6, + "Ho153_m1": 558.0, + "Ho154": 705.6, + "Ho154_m1": 186.0, + "Ho155": 2880.0, + "Ho155_m1": 0.00088, + "Ho156": 3360.0, + "Ho156_m1": 9.5, + "Ho156_m2": 468.0, + "Ho157": 756.0, + "Ho158": 678.0, + "Ho158_m1": 1680.0, + "Ho158_m2": 1278.0, + "Ho159": 1983.0, + "Ho159_m1": 8.3, + "Ho160": 1536.0, + "Ho160_m1": 18072.0, + "Ho160_m2": 3.0, + "Ho161": 8928.0, + "Ho161_m1": 6.76, + "Ho162": 900.0, + "Ho162_m1": 4020.0, + "Ho163": 144218000000.0, + "Ho163_m1": 1.09, + "Ho164": 1740.0, + "Ho164_m1": 2250.0, + "Ho166": 96480.0, + "Ho166_m1": 37869100000.0, + "Ho167": 11160.0, + "Ho168": 179.4, + "Ho168_m1": 132.0, + "Ho169": 283.2, + "Ho170": 165.6, + "Ho170_m1": 43.0, + "Ho171": 53.0, + "Ho172": 25.0, + "Ho173": 10.0, + "Ho174": 8.0, + "Ho175": 5.0, + "Er143": 0.2, + "Er144": 2e-07, + "Er146": 1.7, + "Er147": 2.5, + "Er147_m1": 2.5, + "Er148": 4.6, + "Er149": 4.0, + "Er149_m1": 8.9, + "Er150": 18.5, + "Er151": 23.5, + "Er151_m1": 0.58, + "Er152": 10.3, + "Er153": 37.1, + "Er154": 223.8, + "Er155": 318.0, + "Er156": 1170.0, + "Er157": 1119.0, + "Er157_m1": 0.076, + "Er158": 8244.0, + "Er159": 2160.0, + "Er160": 102888.0, + "Er161": 11556.0, + "Er163": 4500.0, + "Er165": 37296.0, + "Er167_m1": 2.269, + "Er169": 811468.8, + "Er171": 27057.6, + "Er172": 177480.0, + "Er173": 84.0, + "Er174": 192.0, + "Er175": 72.0, + "Er176": 20.0, + "Er177": 3.0, + "Tm145": 3.1e-06, + "Tm146": 0.08, + "Tm146_m1": 0.2, + "Tm147": 0.58, + "Tm148": 0.7, + "Tm149": 0.9, + "Tm150": 2.2, + "Tm150_m1": 0.0052, + "Tm151": 4.17, + "Tm151_m1": 4.51e-07, + "Tm152": 8.0, + "Tm152_m1": 5.2, + "Tm153": 1.48, + "Tm153_m1": 2.5, + "Tm154": 8.1, + "Tm154_m1": 3.3, + "Tm155": 21.6, + "Tm155_m1": 45.0, + "Tm156": 83.8, + "Tm157": 217.8, + "Tm158": 238.8, + "Tm159": 547.8, + "Tm160": 564.0, + "Tm160_m1": 74.5, + "Tm161": 1812.0, + "Tm162": 1302.0, + "Tm162_m1": 24.3, + "Tm163": 6516.0, + "Tm164": 120.0, + "Tm164_m1": 306.0, + "Tm165": 108216.0, + "Tm166": 27720.0, + "Tm166_m1": 0.34, + "Tm167": 799200.0, + "Tm168": 8043840.0, + "Tm170": 11111040.0, + "Tm171": 60590590.0, + "Tm172": 228960.0, + "Tm173": 29664.0, + "Tm174": 324.0, + "Tm175": 912.0, + "Tm176": 114.0, + "Tm177": 90.0, + "Tm178": 30.0, + "Tm179": 20.0, + "Yb148": 0.25, + "Yb149": 0.7, + "Yb150": 2e-07, + "Yb151": 1.6, + "Yb151_m1": 1.6, + "Yb152": 3.04, + "Yb153": 4.2, + "Yb154": 0.409, + "Yb155": 1.793, + "Yb156": 26.1, + "Yb157": 38.6, + "Yb158": 89.4, + "Yb159": 100.2, + "Yb160": 288.0, + "Yb161": 252.0, + "Yb162": 1132.2, + "Yb163": 663.0, + "Yb164": 4548.0, + "Yb165": 594.0, + "Yb166": 204120.0, + "Yb167": 1050.0, + "Yb169": 2766355.0, + "Yb169_m1": 46.0, + "Yb171_m1": 0.00525, + "Yb175": 361584.0, + "Yb175_m1": 0.0682, + "Yb176_m1": 11.4, + "Yb177": 6879.6, + "Yb177_m1": 6.41, + "Yb178": 4440.0, + "Yb179": 480.0, + "Yb180": 144.0, + "Yb181": 60.0, + "Lu150": 0.043, + "Lu151": 0.0806, + "Lu152": 0.7, + "Lu153": 0.9, + "Lu153_m1": 1.0, + "Lu154": 2.0, + "Lu154_m1": 1.12, + "Lu155": 0.068, + "Lu155_m1": 0.138, + "Lu155_m2": 0.00269, + "Lu156": 0.494, + "Lu156_m1": 0.198, + "Lu157": 6.8, + "Lu157_m1": 4.79, + "Lu158": 10.6, + "Lu159": 12.1, + "Lu160": 36.1, + "Lu160_m1": 40.0, + "Lu161": 77.0, + "Lu161_m1": 0.0073, + "Lu162": 82.2, + "Lu162_m1": 90.0, + "Lu162_m2": 114.0, + "Lu163": 238.2, + "Lu164": 188.4, + "Lu165": 644.4, + "Lu166": 159.0, + "Lu166_m1": 84.6, + "Lu166_m2": 127.2, + "Lu167": 3090.0, + "Lu167_m1": 60.0, + "Lu168": 330.0, + "Lu168_m1": 402.0, + "Lu169": 122616.0, + "Lu169_m1": 160.0, + "Lu170": 173836.8, + "Lu170_m1": 0.67, + "Lu171": 711936.0, + "Lu171_m1": 79.0, + "Lu172": 578880.0, + "Lu172_m1": 222.0, + "Lu173": 43233910.0, + "Lu174": 104455700.0, + "Lu174_m1": 12268800.0, + "Lu176": 1.18657e18, + "Lu176_m1": 13086.0, + "Lu177": 574300.8, + "Lu177_m1": 13862020.0, + "Lu177_m2": 390.0, + "Lu178": 1704.0, + "Lu178_m1": 1386.0, + "Lu179": 16524.0, + "Lu179_m1": 0.0031, + "Lu180": 342.0, + "Lu180_m1": 0.001, + "Lu181": 210.0, + "Lu182": 120.0, + "Lu183": 58.0, + "Lu184": 20.0, + "Hf153": 6e-06, + "Hf154": 2.0, + "Hf155": 0.89, + "Hf156": 0.023, + "Hf157": 0.11, + "Hf158": 2.85, + "Hf159": 5.6, + "Hf160": 13.6, + "Hf161": 18.2, + "Hf162": 39.4, + "Hf163": 40.0, + "Hf164": 111.0, + "Hf165": 76.0, + "Hf166": 406.2, + "Hf167": 123.0, + "Hf168": 1557.0, + "Hf169": 194.4, + "Hf170": 57636.0, + "Hf171": 43560.0, + "Hf171_m1": 29.5, + "Hf172": 59012710.0, + "Hf173": 84960.0, + "Hf174": 6.31152e22, + "Hf175": 6048000.0, + "Hf177_m1": 1.09, + "Hf177_m2": 3084.0, + "Hf178_m1": 4.0, + "Hf178_m2": 978285600.0, + "Hf179_m1": 18.67, + "Hf179_m2": 2164320.0, + "Hf180_m1": 19800.0, + "Hf181": 3662496.0, + "Hf182": 280863000000000.0, + "Hf182_m1": 3690.0, + "Hf183": 3841.2, + "Hf184": 14832.0, + "Hf184_m1": 48.0, + "Hf185": 210.0, + "Hf186": 156.0, + "Hf187": 30.0, + "Hf188": 20.0, + "Ta155": 0.0031, + "Ta156": 0.144, + "Ta156_m1": 0.36, + "Ta157": 0.0101, + "Ta157_m1": 0.0043, + "Ta157_m2": 0.0017, + "Ta158": 0.055, + "Ta158_m1": 0.0367, + "Ta159": 0.83, + "Ta159_m1": 0.515, + "Ta160": 1.55, + "Ta160_m1": 1.7, + "Ta161": 2.89, + "Ta162": 3.57, + "Ta163": 10.6, + "Ta164": 14.2, + "Ta165": 31.0, + "Ta166": 34.4, + "Ta167": 80.0, + "Ta168": 120.0, + "Ta169": 294.0, + "Ta170": 405.6, + "Ta171": 1398.0, + "Ta172": 2208.0, + "Ta173": 11304.0, + "Ta174": 4104.0, + "Ta175": 37800.0, + "Ta176": 29124.0, + "Ta176_m1": 0.0011, + "Ta176_m2": 0.00097, + "Ta177": 203616.0, + "Ta178": 558.6, + "Ta178_m1": 8496.0, + "Ta178_m2": 0.058, + "Ta179": 57434830.0, + "Ta179_m1": 0.009, + "Ta179_m2": 0.0541, + "Ta180": 29354.4, + "Ta182": 9913536.0, + "Ta182_m1": 0.283, + "Ta182_m2": 950.4, + "Ta183": 440640.0, + "Ta184": 31320.0, + "Ta185": 2964.0, + "Ta185_m1": 0.002, + "Ta186": 630.0, + "Ta187": 120.0, + "Ta188": 20.0, + "Ta189": 3.0, + "Ta190": 0.3, + "W158": 0.00125, + "W159": 0.0073, + "W160": 0.091, + "W161": 0.409, + "W162": 1.36, + "W163": 2.8, + "W164": 6.3, + "W165": 5.1, + "W166": 19.2, + "W167": 19.9, + "W168": 53.0, + "W169": 74.0, + "W170": 145.2, + "W171": 142.8, + "W172": 396.0, + "W173": 456.0, + "W174": 1992.0, + "W175": 2112.0, + "W176": 9000.0, + "W177": 7920.0, + "W178": 1866240.0, + "W179": 2223.0, + "W179_m1": 384.0, + "W180": 5.68037e25, + "W180_m1": 0.00547, + "W181": 10471680.0, + "W183_m1": 5.2, + "W185": 6488640.0, + "W185_m1": 100.2, + "W186": 5.36e27, + "W186_m1": 0.003, + "W187": 86400.0, + "W188": 6028992.0, + "W189": 642.0, + "W190": 1800.0, + "W190_m1": 0.0031, + "W191": 20.0, + "W192": 10.0, + "Re160": 0.00085, + "Re161": 0.00037, + "Re161_m1": 0.0156, + "Re162": 0.107, + "Re162_m1": 0.077, + "Re163": 0.39, + "Re163_m1": 0.214, + "Re164": 0.53, + "Re164_m1": 0.87, + "Re165": 1.0, + "Re165_m1": 2.1, + "Re166": 2.25, + "Re167": 5.9, + "Re167_m1": 3.4, + "Re168": 4.4, + "Re169": 8.1, + "Re169_m1": 15.1, + "Re170": 9.2, + "Re171": 15.2, + "Re172": 55.0, + "Re172_m1": 15.0, + "Re173": 118.8, + "Re174": 144.0, + "Re175": 353.4, + "Re176": 318.0, + "Re177": 840.0, + "Re178": 792.0, + "Re179": 1170.0, + "Re180": 146.4, + "Re181": 71640.0, + "Re182": 230400.0, + "Re182_m1": 45720.0, + "Re183": 6048000.0, + "Re183_m1": 0.00104, + "Re184": 3058560.0, + "Re184_m1": 14601600.0, + "Re186": 321261.1, + "Re186_m1": 6311520000000.0, + "Re187": 1.36644e18, + "Re188": 61214.4, + "Re188_m1": 1115.4, + "Re189": 87480.0, + "Re190": 186.0, + "Re190_m1": 11520.0, + "Re191": 588.0, + "Re192": 16.0, + "Re193": 51.9, + "Re194": 1.0, + "Os162": 0.00205, + "Os163": 0.0055, + "Os164": 0.021, + "Os165": 0.071, + "Os166": 0.199, + "Os167": 0.81, + "Os168": 2.1, + "Os169": 3.43, + "Os170": 7.37, + "Os171": 8.3, + "Os172": 19.2, + "Os173": 22.4, + "Os174": 44.0, + "Os175": 84.0, + "Os176": 216.0, + "Os177": 180.0, + "Os178": 300.0, + "Os179": 390.0, + "Os180": 1290.0, + "Os181": 6300.0, + "Os181_m1": 162.0, + "Os182": 78624.0, + "Os183": 46800.0, + "Os183_m1": 35640.0, + "Os185": 8087040.0, + "Os186": 6.31152e22, + "Os189_m1": 20916.0, + "Os190_m1": 594.0, + "Os191": 1330560.0, + "Os191_m1": 47160.0, + "Os192_m1": 5.9, + "Os193": 108396.0, + "Os194": 189345600.0, + "Os195": 540.0, + "Os196": 2094.0, + "Ir164": 0.14, + "Ir164_m1": 9.5e-05, + "Ir165": 1e-06, + "Ir166": 0.0105, + "Ir166_m1": 0.0151, + "Ir167": 0.0352, + "Ir167_m1": 0.0257, + "Ir168": 0.232, + "Ir168_m1": 0.16, + "Ir169": 0.64, + "Ir169_m1": 0.281, + "Ir170": 0.9, + "Ir170_m1": 0.811, + "Ir171": 3.5, + "Ir171_m1": 1.4, + "Ir172": 4.4, + "Ir172_m1": 2.0, + "Ir173": 9.0, + "Ir173_m1": 2.2, + "Ir174": 7.9, + "Ir174_m1": 4.9, + "Ir175": 9.0, + "Ir176": 8.7, + "Ir177": 30.0, + "Ir178": 12.0, + "Ir179": 79.0, + "Ir180": 90.0, + "Ir181": 294.0, + "Ir182": 900.0, + "Ir183": 3480.0, + "Ir184": 11124.0, + "Ir185": 51840.0, + "Ir186": 59904.0, + "Ir186_m1": 6840.0, + "Ir187": 37800.0, + "Ir187_m1": 0.0303, + "Ir188": 149400.0, + "Ir188_m1": 0.0042, + "Ir189": 1140480.0, + "Ir189_m1": 0.0133, + "Ir189_m2": 0.0037, + "Ir190": 1017792.0, + "Ir190_m1": 4032.0, + "Ir190_m2": 11113.2, + "Ir191_m1": 4.899, + "Ir191_m2": 5.5, + "Ir192": 6378653.0, + "Ir192_m1": 87.0, + "Ir192_m2": 7605382000.0, + "Ir193_m1": 909792.0, + "Ir194": 69408.0, + "Ir194_m1": 0.03185, + "Ir194_m2": 14774400.0, + "Ir195": 9000.0, + "Ir195_m1": 13680.0, + "Ir196": 52.0, + "Ir196_m1": 5040.0, + "Ir197": 348.0, + "Ir197_m1": 534.0, + "Ir198": 8.0, + "Ir199": 6.5, + "Pt166": 0.0003, + "Pt167": 0.00078, + "Pt168": 0.002, + "Pt169": 0.007, + "Pt170": 0.014, + "Pt171": 0.051, + "Pt172": 0.096, + "Pt173": 0.382, + "Pt174": 0.889, + "Pt175": 2.53, + "Pt176": 6.33, + "Pt177": 10.6, + "Pt178": 21.1, + "Pt179": 21.2, + "Pt180": 56.0, + "Pt181": 52.0, + "Pt182": 180.0, + "Pt183": 390.0, + "Pt183_m1": 43.0, + "Pt184": 1038.0, + "Pt184_m1": 0.00101, + "Pt185": 4254.0, + "Pt185_m1": 1980.0, + "Pt186": 7488.0, + "Pt187": 8460.0, + "Pt188": 881280.0, + "Pt189": 39132.0, + "Pt190": 2.05124e19, + "Pt191": 242092.8, + "Pt193": 1577880000.0, + "Pt193_m1": 374112.0, + "Pt195_m1": 346464.0, + "Pt197": 71609.4, + "Pt197_m1": 5724.6, + "Pt199": 1848.0, + "Pt199_m1": 13.6, + "Pt200": 45360.0, + "Pt201": 150.0, + "Pt202": 158400.0, + "Au169": 0.00015, + "Au170": 0.000291, + "Au170_m1": 0.00062, + "Au171": 1.9e-05, + "Au171_m1": 0.00102, + "Au172": 0.0047, + "Au173": 0.025, + "Au173_m1": 0.014, + "Au174": 0.139, + "Au174_m1": 0.1629, + "Au175": 0.1, + "Au175_m1": 0.156, + "Au176": 1.05, + "Au176_m1": 1.36, + "Au177": 1.462, + "Au177_m1": 1.18, + "Au178": 2.6, + "Au179": 3.3, + "Au180": 8.1, + "Au181": 13.7, + "Au182": 15.6, + "Au183": 42.8, + "Au184": 20.6, + "Au184_m1": 47.6, + "Au185": 255.0, + "Au186": 642.0, + "Au187": 504.0, + "Au187_m1": 2.3, + "Au188": 530.4, + "Au189": 1722.0, + "Au189_m1": 275.4, + "Au190": 2568.0, + "Au190_m1": 0.125, + "Au191": 11448.0, + "Au191_m1": 0.92, + "Au192": 17784.0, + "Au192_m1": 0.029, + "Au192_m2": 0.16, + "Au193": 63540.0, + "Au193_m1": 3.9, + "Au194": 136872.0, + "Au194_m1": 0.6, + "Au194_m2": 0.42, + "Au195": 16078870.0, + "Au195_m1": 30.5, + "Au196": 532820.2, + "Au196_m1": 8.1, + "Au196_m2": 34560.0, + "Au197_m1": 7.73, + "Au198": 232822.1, + "Au198_m1": 196300.8, + "Au199": 271209.6, + "Au200": 2904.0, + "Au200_m1": 67320.0, + "Au201": 1560.0, + "Au202": 28.4, + "Au203": 60.0, + "Au204": 39.8, + "Au205": 31.0, + "Hg171": 6.9e-05, + "Hg172": 0.000365, + "Hg173": 0.0007, + "Hg174": 0.0019, + "Hg175": 0.0107, + "Hg176": 0.0203, + "Hg177": 0.1273, + "Hg178": 0.269, + "Hg179": 1.08, + "Hg180": 2.58, + "Hg181": 3.6, + "Hg182": 10.83, + "Hg183": 9.4, + "Hg184": 30.9, + "Hg185": 49.1, + "Hg185_m1": 21.6, + "Hg186": 82.8, + "Hg187": 144.0, + "Hg187_m1": 114.0, + "Hg188": 195.0, + "Hg189": 456.0, + "Hg189_m1": 516.0, + "Hg190": 1200.0, + "Hg191": 2940.0, + "Hg191_m1": 3048.0, + "Hg192": 17460.0, + "Hg193": 13680.0, + "Hg193_m1": 42480.0, + "Hg194": 14011600000.0, + "Hg195": 37908.0, + "Hg195_m1": 149760.0, + "Hg197": 230904.0, + "Hg197_m1": 85680.0, + "Hg199_m1": 2560.2, + "Hg203": 4025722.0, + "Hg205": 308.4, + "Hg205_m1": 0.00109, + "Hg206": 499.2, + "Hg207": 174.0, + "Hg208": 2490.0, + "Hg209": 36.5, + "Hg210": 146.0, + "Tl176": 0.006, + "Tl177": 0.018, + "Tl178": 0.06, + "Tl179": 0.23, + "Tl179_m1": 0.0017, + "Tl180": 1.09, + "Tl181": 3.2, + "Tl181_m1": 0.0014, + "Tl182": 3.1, + "Tl183": 6.9, + "Tl183_m1": 0.0533, + "Tl184": 11.0, + "Tl185": 19.5, + "Tl185_m1": 1.93, + "Tl186": 27.5, + "Tl186_m1": 2.9, + "Tl187": 51.0, + "Tl187_m1": 15.6, + "Tl188": 71.0, + "Tl188_m1": 71.0, + "Tl188_m2": 0.041, + "Tl189": 138.0, + "Tl189_m1": 84.0, + "Tl190": 222.0, + "Tl190_m1": 156.0, + "Tl191": 1200.0, + "Tl191_m1": 313.2, + "Tl192": 576.0, + "Tl192_m1": 648.0, + "Tl193": 1296.0, + "Tl193_m1": 126.6, + "Tl194": 1980.0, + "Tl194_m1": 1968.0, + "Tl195": 4176.0, + "Tl195_m1": 3.6, + "Tl196": 6624.0, + "Tl196_m1": 5076.0, + "Tl197": 10224.0, + "Tl197_m1": 0.54, + "Tl198": 19080.0, + "Tl198_m1": 6732.0, + "Tl198_m2": 0.0321, + "Tl199": 26712.0, + "Tl199_m1": 0.0284, + "Tl200": 93960.0, + "Tl200_m1": 0.034, + "Tl201": 262837.4, + "Tl201_m1": 0.00201, + "Tl202": 1063584.0, + "Tl204": 119382400.0, + "Tl206": 252.12, + "Tl206_m1": 224.4, + "Tl207": 286.2, + "Tl207_m1": 1.33, + "Tl208": 183.18, + "Tl209": 132.0, + "Tl210": 78.0, + "Tl211": 60.0, + "Tl212": 67.0, + "Pb178": 0.00023, + "Pb179": 0.003, + "Pb180": 0.0045, + "Pb181": 0.036, + "Pb181_m1": 0.045, + "Pb182": 0.0575, + "Pb183": 0.535, + "Pb183_m1": 0.415, + "Pb184": 0.49, + "Pb185": 6.3, + "Pb185_m1": 4.3, + "Pb186": 4.82, + "Pb187": 15.2, + "Pb187_m1": 18.3, + "Pb188": 25.1, + "Pb189": 39.0, + "Pb189_m1": 50.0, + "Pb190": 71.0, + "Pb191": 79.8, + "Pb191_m1": 130.8, + "Pb192": 210.0, + "Pb193": 120.0, + "Pb193_m1": 348.0, + "Pb194": 720.0, + "Pb195": 900.0, + "Pb195_m1": 900.0, + "Pb196": 2220.0, + "Pb197": 480.0, + "Pb197_m1": 2580.0, + "Pb198": 8640.0, + "Pb199": 5400.0, + "Pb199_m1": 732.0, + "Pb200": 77400.0, + "Pb201": 33588.0, + "Pb201_m1": 60.8, + "Pb202": 1656770000000.0, + "Pb202_m1": 12744.0, + "Pb203": 186912.0, + "Pb203_m1": 6.21, + "Pb203_m2": 0.48, + "Pb204": 4.4e24, + "Pb204_m1": 4015.8, + "Pb205": 545946000000000.0, + "Pb205_m1": 0.00555, + "Pb207_m1": 0.806, + "Pb209": 11710.8, + "Pb210": 700578700.0, + "Pb211": 2166.0, + "Pb212": 38304.0, + "Pb213": 612.0, + "Pb214": 1608.0, + "Pb215": 36.0, + "Bi184": 0.013, + "Bi184_m1": 0.0066, + "Bi185": 5.8e-05, + "Bi186": 0.015, + "Bi186_m1": 0.0098, + "Bi187": 0.032, + "Bi187_m1": 0.00031, + "Bi188": 0.06, + "Bi188_m1": 0.265, + "Bi189": 0.674, + "Bi189_m1": 0.005, + "Bi190": 6.3, + "Bi190_m1": 6.2, + "Bi191": 12.4, + "Bi191_m1": 0.125, + "Bi192": 34.6, + "Bi192_m1": 39.6, + "Bi193": 63.6, + "Bi193_m1": 3.2, + "Bi194": 95.0, + "Bi194_m1": 125.0, + "Bi194_m2": 115.0, + "Bi195": 183.0, + "Bi195_m1": 87.0, + "Bi196": 308.0, + "Bi196_m1": 0.6, + "Bi196_m2": 240.0, + "Bi197": 559.8, + "Bi197_m1": 302.4, + "Bi198": 618.0, + "Bi198_m1": 696.0, + "Bi198_m2": 7.7, + "Bi199": 1620.0, + "Bi199_m1": 1482.0, + "Bi200": 2184.0, + "Bi200_m1": 1860.0, + "Bi200_m2": 0.4, + "Bi201": 6180.0, + "Bi201_m1": 3450.0, + "Bi202": 6156.0, + "Bi203": 42336.0, + "Bi203_m1": 0.305, + "Bi204": 40392.0, + "Bi204_m1": 0.013, + "Bi204_m2": 0.00107, + "Bi205": 1322784.0, + "Bi206": 539395.2, + "Bi207": 995642300.0, + "Bi208": 11613200000000.0, + "Bi208_m1": 0.00258, + "Bi209": 5.99594e26, + "Bi210": 433036.8, + "Bi210_m1": 95935100000000.0, + "Bi211": 128.4, + "Bi212": 3633.0, + "Bi212_m1": 1500.0, + "Bi212_m2": 420.0, + "Bi213": 2735.4, + "Bi214": 1194.0, + "Bi215": 462.0, + "Bi215_m1": 36.4, + "Bi216": 135.0, + "Bi217": 98.5, + "Bi218": 33.0, + "Po188": 0.000425, + "Po189": 0.0035, + "Po190": 0.00245, + "Po191": 0.022, + "Po191_m1": 0.093, + "Po192": 0.0332, + "Po193": 0.37, + "Po193_m1": 0.373, + "Po194": 0.392, + "Po195": 4.64, + "Po195_m1": 1.92, + "Po196": 5.8, + "Po197": 84.0, + "Po197_m1": 32.0, + "Po198": 106.2, + "Po199": 328.2, + "Po199_m1": 250.2, + "Po200": 690.6, + "Po201": 936.0, + "Po201_m1": 537.6, + "Po202": 2676.0, + "Po203": 2202.0, + "Po203_m1": 45.0, + "Po204": 12708.0, + "Po205": 6264.0, + "Po205_m1": 0.000645, + "Po205_m2": 0.0574, + "Po206": 760320.0, + "Po207": 20880.0, + "Po207_m1": 2.79, + "Po208": 91453920.0, + "Po209": 3218880000.0, + "Po210": 11955690.0, + "Po211": 0.516, + "Po211_m1": 25.2, + "Po212": 2.99e-07, + "Po212_m1": 45.1, + "Po213": 4.2e-06, + "Po214": 0.0001643, + "Po215": 0.001781, + "Po216": 0.145, + "Po217": 1.53, + "Po218": 185.88, + "Po219": 3e-07, + "Po220": 3e-07, + "At193": 0.0285, + "At194": 0.04, + "At194_m1": 0.25, + "At195": 0.328, + "At195_m1": 0.147, + "At196": 0.388, + "At196_m1": 1.1e-05, + "At197": 0.388, + "At197_m1": 2.0, + "At198": 4.2, + "At198_m1": 1.0, + "At199": 7.03, + "At200": 43.0, + "At200_m1": 47.0, + "At200_m2": 7.9, + "At201": 85.2, + "At202": 184.0, + "At202_m1": 182.0, + "At202_m2": 0.46, + "At203": 444.0, + "At204": 553.2, + "At204_m1": 0.108, + "At205": 1614.0, + "At206": 1836.0, + "At207": 6480.0, + "At208": 5868.0, + "At209": 19476.0, + "At210": 29160.0, + "At211": 25970.4, + "At212": 0.314, + "At212_m1": 0.119, + "At213": 1.25e-07, + "At214": 5.58e-07, + "At215": 0.0001, + "At216": 0.0003, + "At217": 0.0323, + "At218": 1.5, + "At219": 56.0, + "At220": 222.6, + "At221": 138.0, + "At222": 54.0, + "At223": 50.0, + "Rn195": 0.0065, + "Rn195_m1": 0.005, + "Rn196": 0.0046, + "Rn197": 0.066, + "Rn197_m1": 0.021, + "Rn198": 0.065, + "Rn199": 0.59, + "Rn199_m1": 0.31, + "Rn200": 1.075, + "Rn201": 7.0, + "Rn201_m1": 3.8, + "Rn202": 9.7, + "Rn203": 44.0, + "Rn203_m1": 26.9, + "Rn204": 70.2, + "Rn205": 170.0, + "Rn206": 340.2, + "Rn207": 555.0, + "Rn208": 1461.0, + "Rn209": 1728.0, + "Rn210": 8640.0, + "Rn211": 52560.0, + "Rn212": 1434.0, + "Rn213": 0.025, + "Rn214": 2.7e-07, + "Rn215": 2.3e-06, + "Rn216": 4.5e-05, + "Rn217": 0.00054, + "Rn218": 0.035, + "Rn219": 3.96, + "Rn220": 55.6, + "Rn221": 1542.0, + "Rn222": 330350.4, + "Rn223": 1458.0, + "Rn224": 6420.0, + "Rn225": 279.6, + "Rn226": 444.0, + "Rn227": 20.8, + "Rn228": 65.0, + "Fr199": 0.015, + "Fr200": 0.049, + "Fr201": 0.069, + "Fr202": 0.3, + "Fr202_m1": 0.29, + "Fr203": 0.55, + "Fr204": 1.7, + "Fr204_m1": 2.6, + "Fr204_m2": 1.0, + "Fr205": 3.8, + "Fr206": 16.0, + "Fr206_m1": 16.0, + "Fr206_m2": 0.7, + "Fr207": 14.8, + "Fr208": 59.1, + "Fr209": 50.0, + "Fr210": 190.8, + "Fr211": 186.0, + "Fr212": 1200.0, + "Fr213": 34.82, + "Fr214": 0.005, + "Fr214_m1": 0.00335, + "Fr215": 8.6e-08, + "Fr216": 7e-07, + "Fr217": 1.9e-05, + "Fr218": 0.001, + "Fr218_m1": 0.022, + "Fr219": 0.02, + "Fr220": 27.4, + "Fr221": 294.0, + "Fr222": 852.0, + "Fr223": 1320.0, + "Fr224": 199.8, + "Fr225": 237.0, + "Fr226": 49.0, + "Fr227": 148.2, + "Fr228": 38.0, + "Fr229": 50.2, + "Fr230": 19.1, + "Fr231": 17.6, + "Fr232": 5.5, + "Ra202": 0.0275, + "Ra203": 0.031, + "Ra203_m1": 0.025, + "Ra204": 0.0605, + "Ra205": 0.22, + "Ra205_m1": 0.18, + "Ra206": 0.24, + "Ra207": 1.3, + "Ra207_m1": 0.055, + "Ra208": 1.3, + "Ra209": 4.6, + "Ra210": 3.7, + "Ra211": 13.0, + "Ra212": 13.0, + "Ra213": 163.8, + "Ra213_m1": 0.0021, + "Ra214": 2.46, + "Ra215": 0.00155, + "Ra216": 1.82e-07, + "Ra217": 1.6e-06, + "Ra218": 2.52e-05, + "Ra219": 0.01, + "Ra220": 0.018, + "Ra221": 28.0, + "Ra222": 36.17, + "Ra223": 987552.0, + "Ra224": 316224.0, + "Ra225": 1287360.0, + "Ra226": 50492200000.0, + "Ra227": 2532.0, + "Ra228": 181456200.0, + "Ra229": 240.0, + "Ra230": 5580.0, + "Ra231": 103.0, + "Ra232": 252.0, + "Ra233": 30.0, + "Ra234": 30.0, + "Ac206": 0.024, + "Ac206_m1": 0.0395, + "Ac207": 0.027, + "Ac208": 0.095, + "Ac208_m1": 0.025, + "Ac209": 0.098, + "Ac210": 0.35, + "Ac211": 0.21, + "Ac212": 0.93, + "Ac213": 0.8, + "Ac214": 8.2, + "Ac215": 0.17, + "Ac216": 0.00044, + "Ac216_m1": 0.000441, + "Ac217": 6.9e-08, + "Ac218": 1.08e-06, + "Ac219": 1.18e-05, + "Ac220": 0.0264, + "Ac221": 0.052, + "Ac222": 5.0, + "Ac222_m1": 63.0, + "Ac223": 126.0, + "Ac224": 10008.0, + "Ac225": 864000.0, + "Ac226": 105732.0, + "Ac227": 687072100.0, + "Ac228": 22140.0, + "Ac229": 3762.0, + "Ac230": 122.0, + "Ac231": 450.0, + "Ac232": 119.0, + "Ac233": 145.0, + "Ac234": 44.0, + "Ac235": 60.0, + "Ac236": 120.0, + "Th209": 0.0065, + "Th210": 0.016, + "Th211": 0.05, + "Th212": 0.035, + "Th213": 0.14, + "Th214": 0.1, + "Th215": 1.2, + "Th216": 0.026, + "Th217": 0.000251, + "Th218": 1.17e-07, + "Th219": 1.05e-06, + "Th220": 9.7e-06, + "Th221": 0.00173, + "Th222": 0.002237, + "Th223": 0.6, + "Th224": 1.05, + "Th225": 523.2, + "Th226": 1834.2, + "Th227": 1613952.0, + "Th228": 60338130.0, + "Th229": 231633000000.0, + "Th230": 2378810000000.0, + "Th231": 91872.0, + "Th232": 4.43384e17, + "Th233": 1338.0, + "Th234": 2082240.0, + "Th235": 426.0, + "Th236": 2238.0, + "Th237": 282.0, + "Th238": 564.0, + "Pa212": 0.0051, + "Pa213": 0.0053, + "Pa214": 0.017, + "Pa215": 0.014, + "Pa216": 0.16, + "Pa217": 0.0036, + "Pa217_m1": 0.0012, + "Pa218": 0.000113, + "Pa219": 5.3e-08, + "Pa220": 7.8e-07, + "Pa221": 5.9e-06, + "Pa222": 0.0033, + "Pa223": 0.0051, + "Pa224": 0.79, + "Pa225": 1.7, + "Pa226": 108.0, + "Pa227": 2298.0, + "Pa228": 79200.0, + "Pa229": 129600.0, + "Pa230": 1503360.0, + "Pa231": 1033830000000.0, + "Pa232": 114048.0, + "Pa233": 2330640.0, + "Pa234": 24120.0, + "Pa234_m1": 69.54, + "Pa235": 1466.4, + "Pa236": 546.0, + "Pa237": 522.0, + "Pa238": 136.2, + "Pa239": 6480.0, + "Pa240": 120.0, + "U217": 0.0235, + "U218": 0.000545, + "U219": 4.2e-05, + "U220": 6e-08, + "U222": 1.3e-06, + "U223": 1.8e-05, + "U224": 0.0009, + "U225": 0.084, + "U226": 0.35, + "U227": 66.0, + "U228": 546.0, + "U229": 3480.0, + "U230": 1797120.0, + "U231": 362880.0, + "U232": 2174319000.0, + "U233": 5023970000000.0, + "U234": 7747390000000.0, + "U235": 2.22102e16, + "U235_m1": 1560.0, + "U236": 739079000000000.0, + "U237": 583200.0, + "U238": 1.40999e17, + "U239": 1407.0, + "U240": 50760.0, + "U241": 300.0, + "U242": 1008.0, + "Np225": 2e-06, + "Np226": 0.035, + "Np227": 0.51, + "Np228": 61.4, + "Np229": 240.0, + "Np230": 276.0, + "Np231": 2928.0, + "Np232": 882.0, + "Np233": 2172.0, + "Np234": 380160.0, + "Np235": 34231680.0, + "Np236": 4828310000000.0, + "Np236_m1": 81000.0, + "Np237": 67659500000000.0, + "Np238": 182908.8, + "Np239": 203558.4, + "Np240": 3714.0, + "Np240_m1": 433.2, + "Np241": 834.0, + "Np242": 132.0, + "Np242_m1": 330.0, + "Np243": 111.0, + "Np244": 137.4, + "Pu228": 1.85, + "Pu229": 112.0, + "Pu230": 102.0, + "Pu231": 516.0, + "Pu232": 2028.0, + "Pu233": 1254.0, + "Pu234": 31680.0, + "Pu235": 1518.0, + "Pu236": 90191620.0, + "Pu237": 3943296.0, + "Pu237_m1": 0.18, + "Pu238": 2767602000.0, + "Pu239": 760854000000.0, + "Pu240": 207049000000.0, + "Pu241": 450958100.0, + "Pu242": 11786800000000.0, + "Pu243": 17841.6, + "Pu244": 2559320000000000.0, + "Pu245": 37800.0, + "Pu246": 936576.0, + "Pu247": 196128.0, + "Am231": 10.0, + "Am232": 79.0, + "Am233": 192.0, + "Am234": 139.2, + "Am235": 618.0, + "Am236": 216.0, + "Am237": 4416.0, + "Am238": 5880.0, + "Am239": 42840.0, + "Am240": 182880.0, + "Am241": 13651800000.0, + "Am242": 57672.0, + "Am242_m1": 4449622000.0, + "Am242_m2": 0.014, + "Am243": 232580000000.0, + "Am244": 36360.0, + "Am244_m1": 1560.0, + "Am245": 7380.0, + "Am246": 2340.0, + "Am246_m1": 1500.0, + "Am247": 1380.0, + "Am248": 600.0, + "Am249": 120.0, + "Cm233": 17.7, + "Cm234": 51.0, + "Cm235": 300.0, + "Cm236": 1900.0, + "Cm237": 1200.0, + "Cm238": 8640.0, + "Cm239": 10440.0, + "Cm240": 2332800.0, + "Cm241": 2833920.0, + "Cm242": 14078020.0, + "Cm243": 918326200.0, + "Cm244": 571508100.0, + "Cm244_m1": 5e-07, + "Cm245": 268240000000.0, + "Cm246": 150214000000.0, + "Cm247": 492299000000000.0, + "Cm248": 10982000000000.0, + "Cm249": 3849.0, + "Cm250": 261928000000.0, + "Cm251": 1008.0, + "Bk235": 20.0, + "Bk237": 60.0, + "Bk238": 144.0, + "Bk240": 288.0, + "Bk241": 276.0, + "Bk242": 420.0, + "Bk243": 16200.0, + "Bk244": 15660.0, + "Bk245": 426816.0, + "Bk246": 155520.0, + "Bk247": 43549500000.0, + "Bk248": 283824000.0, + "Bk248_m1": 85320.0, + "Bk249": 27648000.0, + "Bk250": 11563.2, + "Bk251": 3336.0, + "Bk253": 600.0, + "Bk254": 120.0, + "Cf237": 2.1, + "Cf238": 0.021, + "Cf239": 51.5, + "Cf240": 57.6, + "Cf241": 226.8, + "Cf242": 222.0, + "Cf243": 642.0, + "Cf244": 1164.0, + "Cf245": 2700.0, + "Cf246": 128520.0, + "Cf247": 11196.0, + "Cf248": 28814400.0, + "Cf249": 11076700000.0, + "Cf250": 412773400.0, + "Cf251": 28338700000.0, + "Cf252": 83468070.0, + "Cf253": 1538784.0, + "Cf254": 5227200.0, + "Cf255": 5100.0, + "Cf256": 738.0, + "Es240": 1.0, + "Es241": 8.5, + "Es242": 13.5, + "Es243": 21.0, + "Es244": 37.0, + "Es245": 66.0, + "Es246": 462.0, + "Es247": 273.0, + "Es247_m1": 54000000.0, + "Es248": 1620.0, + "Es249": 6132.0, + "Es250": 30960.0, + "Es250_m1": 7992.0, + "Es251": 118800.0, + "Es252": 40754880.0, + "Es253": 1768608.0, + "Es254": 23820480.0, + "Es254_m1": 141479.9, + "Es255": 3438720.0, + "Es256": 1524.0, + "Es256_m1": 27360.0, + "Es257": 665280.0, + "Es258": 180.0, + "Fm242": 0.0008, + "Fm243": 0.2, + "Fm244": 0.0033, + "Fm245": 4.2, + "Fm246": 1.1, + "Fm247": 29.0, + "Fm248": 36.0, + "Fm249": 156.0, + "Fm250": 1800.0, + "Fm250_m1": 1.8, + "Fm251": 19080.0, + "Fm252": 91404.0, + "Fm253": 259200.0, + "Fm254": 11664.0, + "Fm255": 72252.0, + "Fm256": 9456.0, + "Fm257": 8683200.0, + "Fm258": 0.00037, + "Fm259": 1.5, + "Fm260": 0.004, + "Md245": 0.0009, + "Md245_m1": 0.39, + "Md246": 0.9, + "Md247": 1.12, + "Md247_m1": 0.26, + "Md248": 7.0, + "Md249": 24.0, + "Md249_m1": 1.9, + "Md250": 27.5, + "Md251": 240.0, + "Md252": 138.0, + "Md253": 630.0, + "Md254": 1680.0, + "Md254_m1": 1680.0, + "Md255": 1620.0, + "Md256": 4620.0, + "Md257": 19872.0, + "Md258": 4449600.0, + "Md258_m1": 3420.0, + "Md259": 5760.0, + "Md260": 2747520.0, + "Md261": 2400.0, + "No250": 4.35e-06, + "No251": 0.8, + "No251_m1": 1.02, + "No252": 2.44, + "No253": 97.2, + "No254": 51.0, + "No254_m1": 0.28, + "No255": 186.0, + "No256": 2.91, + "No257": 25.0, + "No258": 0.0012, + "No259": 3480.0, + "No260": 0.106, + "No261": 160000.0, + "No262": 0.005, + "Lr251": 1.341, + "Lr252": 0.38, + "Lr253": 0.575, + "Lr253_m1": 1.535, + "Lr254": 13.0, + "Lr255": 22.0, + "Lr255_m1": 2.53, + "Lr256": 27.0, + "Lr257": 0.646, + "Lr258": 4.1, + "Lr259": 6.2, + "Lr260": 180.0, + "Lr261": 2340.0, + "Lr262": 14400.0, + "Lr263": 18000.0, + "Rf253": 5.15e-05, + "Rf254": 2.3e-05, + "Rf255": 1.68, + "Rf256": 0.0064, + "Rf257": 4.7, + "Rf257_m1": 3.9, + "Rf258": 0.012, + "Rf259": 3.2, + "Rf260": 0.021, + "Rf261": 65.0, + "Rf261_m1": 81.0, + "Rf262": 2.3, + "Rf263": 600.0, + "Rf264": 3600.0, + "Rf265": 1.0, + "Db255": 1.7, + "Db256": 1.7, + "Db257": 1.52, + "Db257_m1": 0.78, + "Db258": 4.0, + "Db258_m1": 20.0, + "Db259": 0.51, + "Db260": 1.52, + "Db261": 1.8, + "Db262": 35.0, + "Db263": 28.5, + "Db264": 180.0, + "Db265": 900.0, + "Sg258": 0.0032, + "Sg259": 0.555, + "Sg260": 0.0036, + "Sg261": 0.23, + "Sg262": 0.0079, + "Sg263": 1.0, + "Sg263_m1": 0.12, + "Sg264": 0.045, + "Sg265": 8.0, + "Sg266": 25.0, + "Sg269": 50.0, + "Bh260": 0.0003, + "Bh261": 0.013, + "Bh262": 0.102, + "Bh262_m1": 0.022, + "Bh263": 0.0002, + "Bh264": 0.66, + "Bh265": 1.1, + "Bh266": 5.4, + "Bh267": 21.0, + "Bh269": 50.0, + "Hs263": 0.00355, + "Hs264": 0.0008, + "Hs265": 0.00205, + "Hs265_m1": 0.0003, + "Hs266": 0.00265, + "Hs267": 0.0545, + "Hs268": 1.2, + "Hs269": 12.9, + "Hs273": 50.0, + "Mt265": 120.0, + "Mt266": 0.0018, + "Mt266_m1": 0.0017, + "Mt267": 0.01, + "Mt268": 0.0225, + "Mt269": 0.05, + "Mt270": 0.00605, + "Mt271": 5.0, + "Mt273": 20.0, + "Ds267": 2.8e-06, + "Ds268": 0.0001, + "Ds269": 0.000268, + "Ds270": 0.00015, + "Ds270_m1": 0.009, + "Ds271": 0.001705, + "Ds271_m1": 0.0865, + "Ds272": 1.0, + "Ds273": 0.000225, + "Ds279_m1": 0.19, + "Rg272": 0.0041 +} diff --git a/openmc/material.py b/openmc/material.py index a9f5afac8..9706ffe78 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -30,9 +30,9 @@ class Material(IDManagerMixin): To create a material, one should create an instance of this class, add nuclides or elements with :meth:`Material.add_nuclide` or - `Material.add_element`, respectively, and set the total material density - with `Material.set_density()`. The material can then be assigned to a cell - using the :attr:`Cell.fill` attribute. + :meth:`Material.add_element`, respectively, and set the total material + density with :meth:`Material.set_density()`. The material can then be + assigned to a cell using the :attr:`Cell.fill` attribute. Parameters ---------- @@ -142,6 +142,23 @@ class Material(IDManagerMixin): return string + + @property + def activity(self): + """Returns the total activity of the material in Becquerels.""" + + atoms_per_barn_cm2 = self.get_nuclide_atom_densities() + total_activity = 0 + for key, value in atoms_per_barn_cm2.items(): + half_life = openmc.data.half_life(key) + print('half_life', half_life) + if half_life: + atoms = value[1] * self.volume * 1e24 + activity = math.log(2) * atoms / half_life + total_activity += activity + + return total_activity + @property def name(self): return self._name @@ -707,19 +724,6 @@ class Material(IDManagerMixin): self.isotropic = [x.name for x in self._nuclides] - def get_activity(self): - """Returns the total activity of the material in Becquerels.""" - - atoms_per_barn_cm2 = self.get_nuclide_atom_densities() - total_activity = 0 - for key, value in atoms_per_barn_cm2.items(): - if key in openmc.data.HALF_LIFE.keys(): - atoms = value[1] * self.volume * 1e24 - activity = math.log(2) * atoms / openmc.data.HALF_LIFE[key] - total_activity += activity - - return total_activity - def get_elements(self): """Returns all elements in the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 02e53a28d..baef3f9ef 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -404,3 +404,21 @@ def test_mix_materials(): assert m3.density == pytest.approx(dens3) assert m4.density == pytest.approx(dens4) assert m5.density == pytest.approx(dens5) + + +def test_activity_of_stable(): + """Creates a material with stable isotopes to checks the activity is 0""" + m1 = openmc.Material() + m1.add_element("Fe", 1) + m1.set_density('g/cm3', 1) + m1.volume = 1 + assert m1.activity == 0 + + +def test_activity_of_tritium(): + """Checks that 1g of tritium has the correct activity""" + m1 = openmc.Material() + m1.add_nuclide("H3", 1) + m1.set_density('g/cm3', 1) + m1.volume = 1 + assert pytest.approx(m1.activity) == 3.559778e14 From e5e1daf23fcf0f332ac2e79542dff36424d863e0 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Jun 2022 15:02:10 +0100 Subject: [PATCH 0392/2654] [skip ci] removed diagnostic prints --- openmc/data/data.py | 1 - openmc/material.py | 2 -- tests/unit_tests/test_material.py | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 65702f7a5..5aadfac87 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -295,7 +295,6 @@ def half_life(isotope): """ global _HALF_LIFE if not _HALF_LIFE: - print('reading json file') # Load data from AME2016 file half_life_filename = os.path.join(os.path.dirname(__file__), 'half_life.json') with open(half_life_filename, 'r') as f: diff --git a/openmc/material.py b/openmc/material.py index 9706ffe78..e49696706 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -151,7 +151,6 @@ class Material(IDManagerMixin): total_activity = 0 for key, value in atoms_per_barn_cm2.items(): half_life = openmc.data.half_life(key) - print('half_life', half_life) if half_life: atoms = value[1] * self.volume * 1e24 activity = math.log(2) * atoms / half_life @@ -723,7 +722,6 @@ class Material(IDManagerMixin): def make_isotropic_in_lab(self): self.isotropic = [x.name for x in self._nuclides] - def get_elements(self): """Returns all elements in the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index baef3f9ef..c5d3276a0 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -422,3 +422,4 @@ def test_activity_of_tritium(): m1.set_density('g/cm3', 1) m1.volume = 1 assert pytest.approx(m1.activity) == 3.559778e14 + From 61db44f40e33d132d895974852c448beeacc6770 Mon Sep 17 00:00:00 2001 From: myerspat Date: Thu, 9 Jun 2022 09:52:50 -0500 Subject: [PATCH 0393/2654] Xtensor for photoelectric cross sections matches the flux spectrum for uranium of the previous iteration of OpenMC --- src/photon.cpp | 15 +++++++++------ src/physics.cpp | 22 +++++++++++----------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/photon.cpp b/src/photon.cpp index 1be515a62..bb715cdea 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -128,7 +128,7 @@ PhotonInteraction::PhotonInteraction(hid_t group) } shells_.resize(n_shell); - cross_sections_.resize({energy_.size(), n_shell}); + cross_sections_ = xt::zeros({energy_.size(), n_shell}); // Create mapping from designator to index std::unordered_map shell_map; @@ -166,8 +166,8 @@ PhotonInteraction::PhotonInteraction(hid_t group) read_dataset(tgroup, "xs", xs); auto cross_section = xt::view(cross_sections_, - xt::range(shell.threshold, shell.threshold + xs.size()), i); - cross_section = xt::where(xs > 0.0, xt::log(xs), -500.0); + xt::range(shell.threshold, xt::placeholders::_), i); + cross_section = xt::where(xs > 0, xt::log(xs), 0); if (object_exists(tgroup, "transitions")) { // Determine dimensions of transitions @@ -571,10 +571,13 @@ void PhotonInteraction::calculate_xs(Particle& p) const incoherent_(i_grid) + f * (incoherent_(i_grid + 1) - incoherent_(i_grid))); // Calculate microscopic photoelectric cross section - const auto& xs_upper = xt::row(cross_sections_, i_grid); - const auto& xs_lower = xt::row(cross_sections_, i_grid + 1); + xs.photoelectric = 0.0; + const auto& xs_lower = xt::row(cross_sections_, i_grid); + const auto& xs_upper = xt::row(cross_sections_, i_grid + 1); - xs.photoelectric = xt::sum(xt::exp(xs_upper + f * (xs_upper - xs_lower)))[0]; + for (int i = 0; i < xs_upper.size(); ++i) + if (xs_lower(i) != 0) + xs.photoelectric += std::exp(xs_lower(i) + f * (xs_upper(i) - xs_lower(i))); // Calculate microscopic pair production cross section xs.pair_production = std::exp( diff --git a/src/physics.cpp b/src/physics.cpp index 38d74dbed..26b3a3520 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -29,6 +29,7 @@ #include // for max, min, max_element #include // for sqrt, exp, log, abs, copysign +#include namespace openmc { @@ -344,25 +345,24 @@ void sample_photon_reaction(Particle& p) // Photoelectric effect double prob_after = prob + micro.photoelectric; + int i_grid = micro.index_grid; + double f = micro.interp_factor; + const auto& xs_lower = xt::row(element.cross_sections_, i_grid); + const auto& xs_upper = xt::row(element.cross_sections_, i_grid + 1); + if (prob_after > cutoff) { for (int i_shell = 0; i_shell < element.shells_.size(); ++i_shell) { const auto& shell {element.shells_[i_shell]}; - // Get grid index and interpolation factor - int i_grid = micro.index_grid; - double f = micro.interp_factor; - // Check threshold of reaction - int i_start = shell.threshold; - if (i_grid < i_start) + if (xs_lower(i_shell) == 0) continue; - // Evaluation subshell photoionization cross section - double xs = std::exp(element.cross_sections_(i_grid - i_start) + - f * (element.cross_sections_(i_grid + 1 - i_start) - - element.cross_sections_(i_grid - i_start))); + // Evaluation subshell photoionization cross section + prob += std::exp(xs_lower(i_shell) + + f * (xs_upper(i_shell) - + xs_lower(i_shell))); - prob += xs; if (prob > cutoff) { double E_electron = p.E() - shell.binding_energy; From 70b1706460166ff6d0a05744ad804ef9fd0671ef Mon Sep 17 00:00:00 2001 From: myerspat Date: Thu, 9 Jun 2022 10:39:46 -0500 Subject: [PATCH 0394/2654] Moved initialized variables into if statement --- src/physics.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/physics.cpp b/src/physics.cpp index 26b3a3520..0df8e63c0 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -345,12 +345,14 @@ void sample_photon_reaction(Particle& p) // Photoelectric effect double prob_after = prob + micro.photoelectric; - int i_grid = micro.index_grid; - double f = micro.interp_factor; - const auto& xs_lower = xt::row(element.cross_sections_, i_grid); - const auto& xs_upper = xt::row(element.cross_sections_, i_grid + 1); if (prob_after > cutoff) { + + int i_grid = micro.index_grid; + double f = micro.interp_factor; + const auto& xs_lower = xt::row(element.cross_sections_, i_grid); + const auto& xs_upper = xt::row(element.cross_sections_, i_grid + 1); + for (int i_shell = 0; i_shell < element.shells_.size(); ++i_shell) { const auto& shell {element.shells_[i_shell]}; From 0e38755a0e7642d9dc4877ca1f5fa8082793c9be Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 9 Jun 2022 08:51:29 -0500 Subject: [PATCH 0395/2654] Region expression: ensure halfspace followed by ( results in implicit & operator --- openmc/region.py | 5 +++++ tests/unit_tests/test_region.py | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/openmc/region.py b/openmc/region.py index 8efee7c4e..56926187d 100644 --- a/openmc/region.py +++ b/openmc/region.py @@ -106,6 +106,11 @@ class Region(ABC): # If special character appears immediately after a non-operator, # create a token with the appropriate half-space if i_start >= 0: + # When an opening parenthesis appears after a non-operator, + # there's an implicit intersection operator between them + if expression[i] == '(': + tokens.append(' ') + j = int(expression[i_start:i]) if j < 0: tokens.append(-surfaces[abs(j)]) diff --git a/tests/unit_tests/test_region.py b/tests/unit_tests/test_region.py index e75982760..8537e3b80 100644 --- a/tests/unit_tests/test_region.py +++ b/tests/unit_tests/test_region.py @@ -204,3 +204,7 @@ def test_from_expression(reset): # Make sure ")(" is handled correctly r = openmc.Region.from_expression('(-1|2)(2|-3)', surfs) assert str(r) == '((-1 | 2) (2 | -3))' + + # Opening parenthesis immediately after halfspace + r = openmc.Region.from_expression('1(2|-3)', surfs) + assert str(r) == '(1 (2 | -3))' From aba235e0b46a33cd6dbbb388d52a27f56e149cba Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 10 Jun 2022 08:50:52 -0500 Subject: [PATCH 0396/2654] Update tests/unit_tests/test_stats.py Co-authored-by: Jonathan Shimwell --- tests/unit_tests/test_stats.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 8e38a7b48..c2578ea8b 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -120,6 +120,11 @@ def test_maxwell(): samples = d.sample(n_samples, seed=100) assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + # A second sample with a different seed + samples_2 = d.sample(n_samples, seed=200) + assert samples_2.mean() == pytest.approx(exp_mean, rel=1e-02) + assert samples_2.mean() != samples.mean() + def test_watt(): From 2f440125d9eab99cc2b5eebf6b3f456a01720d23 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 10 Jun 2022 09:02:26 -0500 Subject: [PATCH 0397/2654] Fix error in documentation (thanks @andrewmholcomb). Closes #2082 --- docs/source/methods/neutron_physics.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/methods/neutron_physics.rst b/docs/source/methods/neutron_physics.rst index bea92f992..f1b0a5bde 100644 --- a/docs/source/methods/neutron_physics.rst +++ b/docs/source/methods/neutron_physics.rst @@ -1403,7 +1403,7 @@ given analytically by .. math:: :label: coherent-elastic-angle - \mu = 1 - \frac{E_i}{E} + \mu = 1 - \frac{2E_i}{E} where :math:`E_i` is the energy of the Bragg edge that scattered the neutron. From 98a7d5eabc972a986a64307bc709dda7ecadaf3d Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 10 Jun 2022 11:57:35 -0500 Subject: [PATCH 0398/2654] added clang format --- src/photon.cpp | 7 ++++--- src/physics.cpp | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/photon.cpp b/src/photon.cpp index bb715cdea..85bd435c9 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -165,8 +165,8 @@ PhotonInteraction::PhotonInteraction(hid_t group) close_dataset(dset); read_dataset(tgroup, "xs", xs); - auto cross_section = xt::view(cross_sections_, - xt::range(shell.threshold, xt::placeholders::_), i); + auto cross_section = xt::view( + cross_sections_, xt::range(shell.threshold, xt::placeholders::_), i); cross_section = xt::where(xs > 0, xt::log(xs), 0); if (object_exists(tgroup, "transitions")) { @@ -577,7 +577,8 @@ void PhotonInteraction::calculate_xs(Particle& p) const for (int i = 0; i < xs_upper.size(); ++i) if (xs_lower(i) != 0) - xs.photoelectric += std::exp(xs_lower(i) + f * (xs_upper(i) - xs_lower(i))); + xs.photoelectric += + std::exp(xs_lower(i) + f * (xs_upper(i) - xs_lower(i))); // Calculate microscopic pair production cross section xs.pair_production = std::exp( diff --git a/src/physics.cpp b/src/physics.cpp index 0df8e63c0..cc712affd 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -361,9 +361,8 @@ void sample_photon_reaction(Particle& p) continue; // Evaluation subshell photoionization cross section - prob += std::exp(xs_lower(i_shell) + - f * (xs_upper(i_shell) - - xs_lower(i_shell))); + prob += std::exp( + xs_lower(i_shell) + f * (xs_upper(i_shell) - xs_lower(i_shell))); if (prob > cutoff) { double E_electron = p.E() - shell.binding_energy; From 382867db7feed2cd10223afe8397659edca1695b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 13 Jun 2022 12:32:09 -0500 Subject: [PATCH 0399/2654] Address @drewejohnson comments on #2077 --- openmc/deplete/results.py | 11 +++++------ openmc/deplete/stepresult.py | 5 +++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 514c04820..c238002fe 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -81,9 +81,9 @@ class Results(list): .. note:: Initial values for some isotopes that do not appear in initial concentrations may be non-zero, depending on the - value of :class:`openmc.deplete.Operator` ``dilute_initial``. - The :class:`openmc.deplete.Operator` adds isotopes according - to this setting, which can be set to zero. + value of the :attr:`openmc.deplete.Operator.dilute_initial` + attribute. The :class:`openmc.deplete.Operator` class adds isotopes + according to this setting, which can be set to zero. Parameters ---------- @@ -186,6 +186,8 @@ class Results(list): def get_keff(self, time_units='s'): """Evaluates the eigenvalue from a results list. + .. versionadded:: 0.13.1 + Parameters ---------- time_units : {"s", "d", "h", "min"}, optional @@ -220,7 +222,6 @@ class Results(list): "will be removed in a future version of OpenMC.", FutureWarning) return self.get_keff(time_units) - def get_depletion_time(self): """Return an array of the average time to deplete a material @@ -252,7 +253,6 @@ class Results(list): def get_times(self, time_units="d") -> np.ndarray: """Return the points in time that define the depletion schedule - .. versionadded:: 0.12.1 Parameters @@ -290,7 +290,6 @@ class Results(list): Passing ``atol=math.inf`` and ``rtol=math.inf`` will return the closest index to the requested point. - .. versionadded:: 0.12.1 Parameters diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index 6f30e934d..6e2373c45 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -1,6 +1,7 @@ -"""The results module. +"""The stepresult module. -Contains results generation and saving capabilities. +Contains capabilities for generating and saving results of a single depletion +timestep. """ from collections import OrderedDict From 9a86f7bb413995c66dc6824dd241c46b934477ba Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 14 Jun 2022 12:29:20 -0500 Subject: [PATCH 0400/2654] move TalliedFissionYieldHelper from abc.py to helpers.py --- openmc/deplete/abc.py | 96 +----------------------------------- openmc/deplete/helpers.py | 100 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 457c51a8a..a4f80e3d6 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -19,7 +19,6 @@ from warnings import warn from numpy import nonzero, empty, asarray from uncertainties import ufloat -from openmc.lib import MaterialFilter, Tally from openmc.checkvalue import check_type, check_greater_than from openmc.mpi import comm from .stepresult import StepResult @@ -30,7 +29,7 @@ from .pool import deplete __all__ = [ "OperatorResult", "TransportOperator", "ReactionRateHelper", - "NormalizationHelper", "FissionYieldHelper", "TalliedFissionYieldHelper", + "NormalizationHelper", "FissionYieldHelper", "Integrator", "SIIntegrator", "DepSystemSolver", "add_params"] @@ -480,99 +479,6 @@ class FissionYieldHelper(ABC): return cls(operator.chain.nuclides, **kwargs) -class TalliedFissionYieldHelper(FissionYieldHelper): - """Abstract class for computing fission yields with tallies - - Generates a basic fission rate tally in all burnable materials with - :meth:`generate_tallies`, and set nuclides to be tallied with - :meth:`update_tally_nuclides`. Subclasses will need to implement - :meth:`unpack` and :meth:`weighted_yields`. - - Parameters - ---------- - chain_nuclides : iterable of openmc.deplete.Nuclide - Nuclides tracked in the depletion chain. Not necessary - that all have yield data. - - Attributes - ---------- - constant_yields : dict of str to :class:`openmc.deplete.FissionYield` - Fission yields for all nuclides that only have one set of - fission yield data. Can be accessed as ``{parent: {product: yield}}`` - results : None or numpy.ndarray - Tally results shaped in a manner useful to this helper. - """ - - _upper_energy = 20.0e6 # upper energy for tallies - - def __init__(self, chain_nuclides): - super().__init__(chain_nuclides) - self._local_indexes = None - self._fission_rate_tally = None - self._tally_nucs = [] - self.results = None - - def generate_tallies(self, materials, mat_indexes): - """Construct the fission rate tally - - Parameters - ---------- - materials : iterable of :class:`openmc.lib.Material` - Materials to be used in :class:`openmc.lib.MaterialFilter` - mat_indexes : iterable of int - Indices of tallied materials that will have their fission - yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper - may only burn a subset of all materials when running - in parallel mode. - """ - self._local_indexes = asarray(mat_indexes) - - # Tally group-wise fission reaction rates - self._fission_rate_tally = Tally() - self._fission_rate_tally.writable = False - self._fission_rate_tally.scores = ['fission'] - self._fission_rate_tally.filters = [MaterialFilter(materials)] - - def update_tally_nuclides(self, nuclides): - """Tally nuclides with non-zero density and multiple yields - - Must be run after :meth:`generate_tallies`. - - Parameters - ---------- - nuclides : iterable of str - Potential nuclides to be tallied, such as those with - non-zero density at this stage. - - Returns - ------- - nuclides : list of str - Union of input nuclides and those that have multiple sets - of yield data. Sorted by nuclide name - - Raises - ------ - AttributeError - If tallies not generated - """ - assert self._fission_rate_tally is not None, ( - "Run generate_tallies first") - overlap = set(self._chain_nuclides).intersection(set(nuclides)) - nuclides = sorted(overlap) - self._tally_nucs = [self._chain_nuclides[n] for n in nuclides] - self._fission_rate_tally.nuclides = nuclides - return nuclides - - @abstractmethod - def unpack(self): - """Unpack tallies after a transport run. - - Abstract because each subclass will need to arrange its - tally data. - """ - - def add_params(cls): cls.__doc__ += cls._params return cls diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index f22382923..33bd182d7 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -2,6 +2,7 @@ Class for normalizing fission energy deposition """ import bisect +from abc import abstractmethod from collections import defaultdict from copy import deepcopy from itertools import product @@ -17,14 +18,107 @@ from openmc.lib import ( Tally, MaterialFilter, EnergyFilter, EnergyFunctionFilter) import openmc.lib from .abc import ( - ReactionRateHelper, NormalizationHelper, FissionYieldHelper, - TalliedFissionYieldHelper) + ReactionRateHelper, NormalizationHelper, FissionYieldHelper) __all__ = ( "DirectReactionRateHelper", "ChainFissionHelper", "EnergyScoreHelper" - "SourceRateHelper", "ConstantFissionYieldHelper", "FissionYieldCutoffHelper", + "SourceRateHelper", "TalliedFissionYieldHelper", + "ConstantFissionYieldHelper", "FissionYieldCutoffHelper", "AveragedFissionYieldHelper", "FluxCollapseHelper") +class TalliedFissionYieldHelper(FissionYieldHelper): + """Abstract class for computing fission yields with tallies + + Generates a basic fission rate tally in all burnable materials with + :meth:`generate_tallies`, and set nuclides to be tallied with + :meth:`update_tally_nuclides`. Subclasses will need to implement + :meth:`unpack` and :meth:`weighted_yields`. + + Parameters + ---------- + chain_nuclides : iterable of openmc.deplete.Nuclide + Nuclides tracked in the depletion chain. Not necessary + that all have yield data. + + Attributes + ---------- + constant_yields : dict of str to :class:`openmc.deplete.FissionYield` + Fission yields for all nuclides that only have one set of + fission yield data. Can be accessed as ``{parent: {product: yield}}`` + results : None or numpy.ndarray + Tally results shaped in a manner useful to this helper. + """ + + _upper_energy = 20.0e6 # upper energy for tallies + + def __init__(self, chain_nuclides): + super().__init__(chain_nuclides) + self._local_indexes = None + self._fission_rate_tally = None + self._tally_nucs = [] + self.results = None + + def generate_tallies(self, materials, mat_indexes): + """Construct the fission rate tally + + Parameters + ---------- + materials : iterable of :class:`openmc.lib.Material` + Materials to be used in :class:`openmc.lib.MaterialFilter` + mat_indexes : iterable of int + Indices of tallied materials that will have their fission + yields computed by this helper. Necessary as the + :class:`openmc.deplete.Operator` that uses this helper + may only burn a subset of all materials when running + in parallel mode. + """ + self._local_indexes = asarray(mat_indexes) + + # Tally group-wise fission reaction rates + self._fission_rate_tally = Tally() + self._fission_rate_tally.writable = False + self._fission_rate_tally.scores = ['fission'] + self._fission_rate_tally.filters = [MaterialFilter(materials)] + + def update_tally_nuclides(self, nuclides): + """Tally nuclides with non-zero density and multiple yields + + Must be run after :meth:`generate_tallies`. + + Parameters + ---------- + nuclides : iterable of str + Potential nuclides to be tallied, such as those with + non-zero density at this stage. + + Returns + ------- + nuclides : list of str + Union of input nuclides and those that have multiple sets + of yield data. Sorted by nuclide name + + Raises + ------ + AttributeError + If tallies not generated + """ + assert self._fission_rate_tally is not None, ( + "Run generate_tallies first") + overlap = set(self._chain_nuclides).intersection(set(nuclides)) + nuclides = sorted(overlap) + self._tally_nucs = [self._chain_nuclides[n] for n in nuclides] + self._fission_rate_tally.nuclides = nuclides + return nuclides + + @abstractmethod + def unpack(self): + """Unpack tallies after a transport run. + + Abstract because each subclass will need to arrange its + tally data. + """ + + # ------------------------------------- # Helpers for generating reaction rates # ------------------------------------- From 8b95bd4ee0fa0ca6e5f054ac5918c3c56da42f4f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 17 Jun 2022 13:24:36 -0500 Subject: [PATCH 0401/2654] Write material id in DAGMC lost particle message --- src/dagmc.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index e780d2e77..0368dbfa7 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -596,8 +596,12 @@ std::pair DAGCell::distance( dist = INFINITY; if (!dagmc_ptr_->is_implicit_complement(vol) || model::universe_map[dag_univ->id_] == model::root_universe) { + int32_t material_id = p->material() == MATERIAL_VOID + ? -1 + : model::materials[p->material()]->id(); p->mark_as_lost( - fmt::format("No intersection found with DAGMC cell {}", id_)); + fmt::format("No intersection found with DAGMC cell {}, material {}", + id_, material_id)); } } From 1f05c3b016119426b2fe98c8870fda1b2d4f6289 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 19 Jun 2022 00:59:05 -0500 Subject: [PATCH 0402/2654] Updating marked as lost message for clarity --- src/dagmc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 0368dbfa7..8ce5aabda 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -596,9 +596,9 @@ std::pair DAGCell::distance( dist = INFINITY; if (!dagmc_ptr_->is_implicit_complement(vol) || model::universe_map[dag_univ->id_] == model::root_universe) { - int32_t material_id = p->material() == MATERIAL_VOID - ? -1 - : model::materials[p->material()]->id(); + std::string material_id = p->material() == MATERIAL_VOID + ? "-1 (VOID)" + : std::to_string(model::materials[p->material()]->id()); p->mark_as_lost( fmt::format("No intersection found with DAGMC cell {}, material {}", id_, material_id)); From 0c3d30e6d1ebf373c7d79de1aeacfce88504609e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 19 Jun 2022 09:31:38 -0500 Subject: [PATCH 0403/2654] Update openmc/stats/univariate.py Co-authored-by: Paul Romano --- openmc/stats/univariate.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index d733b6193..e4c53c559 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -139,14 +139,7 @@ class Discrete(Univariate): def sample(self, n_samples=1, seed=None): np.random.seed(seed) - if len(self.x) == 1: - return np.full((n_samples), self.x[0]) - - xi = np.random.rand(n_samples) - out = np.zeros_like(xi) - for i, c in enumerate(self.cdf()[:-1]): - out[xi >= c] = self.x[i] - return out + return np.random.choice(self.x, n_samples, p=self.p) def normalize(self): norm = sum(self.p) From f52865854ba41746d58b6621215bb5c223c896f2 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 19 Jun 2022 09:39:53 -0500 Subject: [PATCH 0404/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/stats/univariate.py | 18 +++++++++--------- tests/unit_tests/test_stats.py | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index e4c53c559..6875f4e4f 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -381,7 +381,7 @@ class PowerLaw(Univariate): pwr = self.n + 1 offset = self.a**pwr span = self.b**pwr - offset - return np.power(offset + xi * span, (1/pwr)) + return np.power(offset + xi * span, 1/pwr) def to_xml_element(self, element_name): """Return XML representation of the power law distribution @@ -463,8 +463,8 @@ class Maxwell(Univariate): @staticmethod def sample_maxwell(t, n_samples): r1, r2, r3 = np.random.rand(3, n_samples) - c = np.power(np.cos(0.5 * np.pi * r3), 2) - return -t * (np.log(r1) + np.log(r2) * c) + c = np.cos(0.5 * np.pi * r3) + return -t * (np.log(r1) + np.log(r2) * c * c) def to_xml_element(self, element_name): """Return XML representation of the Maxwellian distribution @@ -887,7 +887,7 @@ class Tabular(Univariate): if self.interpolation == 'histogram': c[1:] = p[:-1] * np.diff(x) elif self.interpolation == 'linear-linear': - c[1:] = 0.5 * (p[0:-1] + p[1:]) * np.diff(x) + c[1:] = 0.5 * (p[:-1] + p[1:]) * np.diff(x) return np.cumsum(c) @@ -909,7 +909,7 @@ class Tabular(Univariate): # get CDF bins that are above the # sampled values c_i = np.full(n_samples, cdf[0]) - cdf_idx = np.zeros((n_samples,), dtype=int) + cdf_idx = np.zeros(n_samples, dtype=int) for i, val in enumerate(cdf[:-1]): mask = xi > val c_i[mask] = val @@ -918,8 +918,8 @@ class Tabular(Univariate): # get table values at each index where # the random number is less than the next cdf # entry - x_i = np.array([self.x[i] for i in cdf_idx]) - p_i = np.array([p[i] for i in cdf_idx]) + x_i = self.x[cdf_idx] + p_i = self.p[cdf_idx] # TODO: check that probability doesn't exceed the last value @@ -936,8 +936,8 @@ class Tabular(Univariate): elif self.interpolation == 'linear-linear': # get variable and probability values for the # next entry - x_i1 = np.array([self.x[i+1] for i in cdf_idx]) - p_i1 = np.array([p[i+1] for i in cdf_idx]) + x_i1 = self.x[cdf_idx + 1] + p_i1 = self.p[cdf_idx + 1] # compute slope between entries m = (p_i1 - p_i) / (x_i1 - x_i) # set values for zero slope diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index c2578ea8b..f62f2157b 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -161,7 +161,7 @@ def test_tabular(): assert d.interpolation == 'linear-linear' assert len(d) == len(x) - # test linear-lienar sampling + # test linear-linear sampling d = openmc.stats.Tabular(x, p) # compute the expected value (mean) of the From f46402fd87f33daf2da4050010973bd00b6c5bae Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 19 Jun 2022 09:36:31 -0500 Subject: [PATCH 0405/2654] Adding docstrings to normalize methods --- openmc/stats/univariate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 6875f4e4f..bbac4c030 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -142,6 +142,7 @@ class Discrete(Univariate): return np.random.choice(self.x, n_samples, p=self.p) def normalize(self): + """Normalize the probabilities stored on the distribution""" norm = sum(self.p) self.p = [val / norm for val in self.p] @@ -892,6 +893,7 @@ class Tabular(Univariate): return np.cumsum(c) def normalize(self): + """Normalize the probabilities stored on the distribution""" self.p = np.asarray(self.p) / self.cdf().max() def sample(self, n_samples=1, seed=None): @@ -1115,6 +1117,7 @@ class Mixture(Univariate): return out def normalize(self): + """Normalize the probabilities stored on the distribution""" norm = sum(self.probability) self.probability = [val / norm for val in self.probability] From 862189985b42253cebe12bcd6fc2888c954f6c09 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 19 Jun 2022 09:51:45 -0500 Subject: [PATCH 0406/2654] Check that output values do not exceed values in tabulated dist --- openmc/stats/univariate.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index bbac4c030..630bb665b 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -923,8 +923,6 @@ class Tabular(Univariate): x_i = self.x[cdf_idx] p_i = self.p[cdf_idx] - # TODO: check that probability doesn't exceed the last value - if self.interpolation == 'histogram': # mask where probability is greater than zero pos_mask = p_i > 0.0 @@ -934,7 +932,9 @@ class Tabular(Univariate): / p_i[pos_mask] # probabilities smaller than zero are set to the random number value p_i[~pos_mask] = x_i[~pos_mask] - return p_i + + samples_out = p_i + elif self.interpolation == 'linear-linear': # get variable and probability values for the # next entry @@ -950,7 +950,10 @@ class Tabular(Univariate): quad = np.power(p_i[non_zero], 2) + 2.0 * m[non_zero] * (xi[non_zero] - c_i[non_zero]) quad[quad < 0.0] = 0.0 m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i[non_zero]) / m[non_zero] - return m + samples_out = m + + assert all(samples_out < self.x[-1]) + return samples_out def to_xml_element(self, element_name): """Return XML representation of the tabular distribution From 967fc9f88bd7b22373505253eec7d5d6af3f7a4a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 19 Jun 2022 10:00:27 -0500 Subject: [PATCH 0407/2654] Adding a 'mean' method to tabular dist --- openmc/stats/univariate.py | 30 +++++++++++++++++++++++++++++- tests/unit_tests/test_stats.py | 27 ++------------------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 630bb665b..ae89cb79f 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -138,7 +138,6 @@ class Discrete(Univariate): def sample(self, n_samples=1, seed=None): np.random.seed(seed) - return np.random.choice(self.x, n_samples, p=self.p) def normalize(self): @@ -892,6 +891,35 @@ class Tabular(Univariate): return np.cumsum(c) + def mean(self): + """Compute the mean of the tabular distribution""" + if not self.interpolation in ('histogram', 'linear-linear'): + raise NotImplementedError('Can only compute mean for tabular ' + 'distributions using histogram ' + 'or linear-linear interpolation.') + if self.interpolation == 'linear-linear': + mean = 0.0 + self.normalize() + for i in range(1, len(self.x)): + y_min = self.p[i-1] + y_max = self.p[i] + x_min = self.x[i-1] + x_max = self.x[i] + + m = (y_max - y_min) / (x_max - x_min) + + exp_val = (1./3.) * m * (x_max**3 - x_min**3) + exp_val += 0.5 * m * x_min * (x_min**2 - x_max**2) + exp_val += 0.5 * y_min * (x_max**2 - x_min**2) + mean += exp_val + + elif self.interpolation == 'histogram': + mean = 0.5 * (self.x[:-1] + self.x[1:]) + mean *= np.diff(self.cdf()) + mean = sum(mean) + + return mean + def normalize(self): """Normalize the probabilities stored on the distribution""" self.p = np.asarray(self.p) / self.cdf().max() diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index f62f2157b..f789a0dca 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -40,7 +40,6 @@ def test_discrete(): assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) - def test_merge_discrete(): x1 = [0.0, 1.0, 10.0] p1 = [0.3, 0.2, 0.5] @@ -164,38 +163,16 @@ def test_tabular(): # test linear-linear sampling d = openmc.stats.Tabular(x, p) - # compute the expected value (mean) of the - # piecewise pdf - mean = 0.0 - d.normalize() - for i in range(1, len(x)): - y_min = d.p[i-1] - y_max = d.p[i] - x_min = d.x[i-1] - x_max = d.x[i] - - m = (y_max - y_min) / (x_max - x_min) - - exp_val = (1./3.) * m * (x_max**3 - x_min**3) - exp_val += 0.5 * m * x_min * (x_min**2 - x_max**2) - exp_val += 0.5 * y_min * (x_max**2 - x_min**2) - - mean += exp_val - n_samples = 100_000 samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(mean, rel=1e-03) + assert samples.mean() == pytest.approx(d.mean(), rel=1e-03) # test histogram sampling d = openmc.stats.Tabular(x, p, interpolation='histogram') d.normalize() - mean = 0.5 * (x[:-1] + x[1:]) - mean *= np.diff(d.cdf()) - mean = sum(mean) - samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(mean, rel=1e-03) + assert samples.mean() == pytest.approx(d.mean(), rel=1e-03) def test_legendre(): From f92ea393f23a602ef56227e057091fd4a6f811d3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 20 Jun 2022 06:39:55 -0500 Subject: [PATCH 0408/2654] Using np.random.choice in Mixture class --- openmc/stats/univariate.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index ae89cb79f..5528bdb30 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -1135,12 +1135,9 @@ class Mixture(Univariate): def sample(self, n_samples=1, seed=None): np.random.seed(seed) - xi = np.random.rand(n_samples) - idx = np.zeros_like(xi, dtype=int) - for i, c in enumerate(self.cdf()[:-1]): - idx[xi >= c] = i + idx = np.random.choice(self.distribution, n_samples, p=self.probability) - out = np.zeros_like(xi) + out = np.zeros_like(idx) for i in np.unique(idx): n_dist_samples = np.count_nonzero(idx == i) samples = self.distribution[i].sample(n_dist_samples) From acd6c567c3e44b3cdee15278728f0d1f8e8918ea Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 21 Jun 2022 14:19:45 +0000 Subject: [PATCH 0409/2654] added test for remove eleemnt --- tests/unit_tests/test_material.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 02e53a28d..3a976da99 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -38,6 +38,17 @@ def test_remove_nuclide(): assert m.nuclides[1].percent == 2.0 +def test_remove_elements(): + """Test removing elements.""" + m = openmc.Material() + for elem, percent in [('Li', 1.0), ('Be', 1.0)]: + m.add_element(elem, percent) + m.remove_nuclide('Li') + assert len(m.nuclides) == 1 + assert m.nuclides == ['Be9'] + assert m.nuclides[0].percent == 1.0 + + def test_elements(): """Test adding elements.""" m = openmc.Material() From 8fe6c8244cd4e3988d39558d3069b2770099d395 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 21 Jun 2022 14:58:39 -0500 Subject: [PATCH 0410/2654] Set CMP0128 to NEW for recent versions of CMake --- CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cf72db20..85dcd7084 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,10 +17,15 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) # Allow user to specify _ROOT variables -if (NOT (CMAKE_VERSION VERSION_LESS 3.12)) +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) cmake_policy(SET CMP0074 NEW) endif() +# Enable correct usage of CXX_EXTENSIONS +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.22) + cmake_policy(SET CMP0128 NEW) +endif() + #=============================================================================== # Command line options #=============================================================================== @@ -118,7 +123,7 @@ endif() # Version 1.12 of HDF5 deprecates the H5Oget_info_by_idx() interface. # Thus, we give these flags to allow usage of the old interface in newer # versions of HDF5. -if(NOT (${HDF5_VERSION} VERSION_LESS 1.12.0)) +if(${HDF5_VERSION} VERSION_GREATER_EQUAL 1.12.0) list(APPEND cxxflags -DH5Oget_info_by_idx_vers=1 -DH5O_info_t_vers=1) endif() @@ -205,7 +210,7 @@ endif() #=============================================================================== # CMake 3.13+ will complain about policy CMP0079 unless it is set explicitly -if (NOT (CMAKE_VERSION VERSION_LESS 3.13)) +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) cmake_policy(SET CMP0079 NEW) endif() From 7bbc778fd7bb56dcb98eb787c14f711cae78711f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 21 Jun 2022 23:27:44 +0100 Subject: [PATCH 0411/2654] [skip ci] review suggestions from @paulromano --- openmc/data/data.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openmc/data/data.py b/openmc/data/data.py index 5aadfac87..914c6c622 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -2,6 +2,7 @@ import itertools import json import os import re +from pathlib import Path from math import sqrt from warnings import warn From 87dafd1e3167a814f4e5b148e82242817cbf02e1 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 21 Jun 2022 23:14:49 +0000 Subject: [PATCH 0412/2654] review comments from @paulromano --- docs/source/pythonapi/data.rst | 1 + openmc/material.py | 5 +++-- setup.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 95fdfeca9..6f5c006c2 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -63,6 +63,7 @@ Core Functions atomic_weight dose_coefficients gnd_name + half_life isotopes linearize thin diff --git a/openmc/material.py b/openmc/material.py index e49696706..70cfa7ade 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -152,9 +152,10 @@ class Material(IDManagerMixin): for key, value in atoms_per_barn_cm2.items(): half_life = openmc.data.half_life(key) if half_life: - atoms = value[1] * self.volume * 1e24 - activity = math.log(2) * atoms / half_life + atoms = value[1] * self.volume + activity = atoms / half_life total_activity += activity + total_activity = math.log(2) * total_activity * 1e24 return total_activity diff --git a/setup.py b/setup.py index b2e3f160a..477f29dec 100755 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ kwargs = { # Data files and libraries 'package_data': { 'openmc.lib': ['libopenmc.{}'.format(suffix)], - 'openmc.data': ['mass16.txt', 'BREMX.DAT', '*.h5'], + 'openmc.data': ['mass16.txt', 'BREMX.DAT', 'half_life.json', '*.h5'], 'openmc.data.effective_dose': ['*.txt'] }, From e76bd84368d09c29252bedfbb22f631e60646b2b Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 21 Jun 2022 18:16:34 -0500 Subject: [PATCH 0413/2654] setup and initial structure for FluxSpectraOperator class --- openmc/deplete/flux_operator.py | 281 ++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 openmc/deplete/flux_operator.py diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py new file mode 100644 index 000000000..17b43dcfd --- /dev/null +++ b/openmc/deplete/flux_operator.py @@ -0,0 +1,281 @@ +"""Pure depletion operator + +This module implements a pure depletion operator that uses user provided fluxes +and one-group cross sections. + +""" + + +import copy +from collections import OrderedDict +import os +from warnings import warn + +import numpy as np +from uncertainties import ufloat + +import openmc +from openmc.checkvalue import check_value +from openmc.data import DataLibrary +from openmc.exceptions import DataError +from openmc.mpi import comm +from .operator import Operator, _distribute, _find_cross_sections +from .abc import TransportOperator, OperatorResult +from .atom_number import AtomNumber +from .chain import _find_chain_file +from .reaction_rates import ReactionRates +from .results import Results + + + +class FluxSpectraDepletionOperator(TransportOperator, Operator): + """Depletion operator that uses a user provided flux spectrum to + calculate reaction rates. The flux provided must match the type of cross + section library in use (contunuous flux for continuous energy library, + multi-group flux for multi-group library) + + Instances of this class can be used to perform depletion using one group + cross sections and constant flux. Normally, a user needn't call methods of + this class directly. Instead, an instance of this class is passed to an + integrator class, such as :class:`openmc.deplete.CECMIntegrator` + + Parameters + ---------- + model : openmc.model.Model + OpenMC Model object. Must contain geometry and materials information. + flux_spectra : ??? + Unnormalized flux spectrum. + chain_file : str + Path to the depletion chain XML file. + fission_q : dict, optional + Dictionary of nuclides and their fission Q values [eV]. If not given, + values will be pulled from the ``chain_file``. + dilute_initial : float, optional + Initial atom density [atoms/cm^3] to add for nuclides that are zero + in initial condition to ensure they exist in the decay chain. + Only done for nuclides with reaction rates. + Defaults to 1.0e3. + prev_results : Results, optional + Results from a previous depletion calculation. + reduce_chain : bool, optional + If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the + depletion chain up to ``reduce_chain_level``. Default is False. + reduce_chain_level : int, optional + Depth of the search when reducing the depletion chain. Only used + if ``reduce_chain`` evaluates to true. The default value of + ``None`` implies no limit on the depth. + + + Attributes + ---------- + dilute_initial : float + Initial atom density [atoms/cm^3] to add for nuclides that are zero + in initial condition to ensure they exist in the decay chain. + Only done for nuclides with reaction rates. + prev_res : Results or None + Results from a previous depletion calculation. ``None`` if no + results are to be used. + """ + + def __init__(self, model, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, + prev_results=None, reduce_chain=False, reduce_chain_level=None): + + # Determine cross sections / depletion chain + # TODO : add support for mg cross sections to _find_cross_sections + cross_sections = _find_cross_sections(model) + if chain_file is None: + chain_file = _find_chain_file(cross_sections) + + TransportOperator.__init__(chain_file, fission_q, dilute_initial, prev_results) + self.round_number = False + self.geometry = model.geometry + + # determine set of materials in the model + if not model.materials: + model.materials = openmc.Materials( + model.geometry.get_all_materials().values() + ) + self.materials = model.materials + self.flux_spectra = flux_spectra + + # Reduce the chain before we create more materials + if reduce_chain: + all_isotopes = set() + for material in self.materials: + if not material.depletable: + continue + for name, _dens_percent, _dens_type in material.nuclides: + all_isotopes.add(name) + self.chain = self.chain.reduce(all_isotopes, reduce_chain_level) + + # Clear out OpenMC, create task lists, distribute + self.burnable_mats, volume, nuclides = Operator._get_burnable_mats() + self.local_mats = _distribute(self.burnable_mats) + + # Generate map from local materials => material index + self._mat_index_map = { + lm: self.burnable_mats.index(lm) for lm in self.local_mats} + + # TODO: add support for loading previous results + + # Determine which nuclides have incident neutron data + # TODO : add support for mg cross sections to Operator._get_nuclides_with_data + self.nuclides_with_data = Operator._get_nuclides_with_data(mg_cross_sections) + + # Select nuclides with data that are also in the chain + self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides + if nuc.name in self.nuclides_with_data] + + # Extract number densities from the geometry / previous depletion run + Operator._extract_number(self.local_mats, volume, nuclides, self.prev_res) + + # Create reaction rates array + self.reaction_rates = ReactionRates( + self.local_mats, self._burnable_nucs, self.chain.reactions) + + # TODO : set up rate, yield, and normalization helper objects + + + def __call__(self, vec, source_rate): + """Runs a simulation. + + Parameters + ---------- + vec : list of numpy.ndarray + Total atoms to be used in function. + source_rate : float + Power in [W] or source rate in [neutron/sec] + + Returns + ------- + openmc.deplete.OperatorResult + Eigenvalue and reaction rates resulting from transport operator + + """ + + + + # Update the number densities regardless of the source rate + self.number.set_density(vec) + self._update_materials() + + # Update tally nuclides data in preparation for transport solve + nuclides = Operator._get_tally_nuclides() + self._rate_helper.nuclides = nuclides + self._normalization_helper.nuclides = nuclides + self._yield_helper.update_tally_nuclides(nuclides) + + + + rates = self.reaction_rates + rates.fill(0.0) + + # Get k and uncertainty + # TODO : add functionality to get this from the transport solver + + # Form fast map + nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides] + react_ind = [rates.index_rx[react] for react in self.chain.reactions] + + # Create arrays to store fission Q values, reaction rates, and nuclide + # numbers, zeroed out in material iteration + number = np.empty(rates.n_nuc) + + # Extract results + for i, mat in enumerate(self.local_mats): + # Get tally index + mat_index = self._mat_index_map[mat] + + # TODO : add machinery to multiply + # each cross section by the corresponding flux + + ... + + + # TODO: add flow control to determine if we need to scale + # the reaction rates + # Scale reaction rates to obtain units of reactions/sec + rates *= self._normalization_helper.factor(source_rate) + + # Store new fission yields on the chain + self.chain.fission_yields = fission_yields + + return OperatorResult(keff, rates) + + + def initial_condition(self): + """Performs final setup and returns initial condition. + + Returns + ------- + list of numpy.ndarray + Total density for initial conditions. + """ + + # TODO : implement these functions so they can store the + # cross section data + materials = [openmc.lib.materials[int(i)] + for i in self.burnable_mats] + self._rate_helper.generate_tallies(materials, self.chain.reactions) + self._normalization_helper.prepare( + self.chain.nuclides, self.reaction_rates.index_nuc) + # Tell fission yield helper what materials this process is + # responsible for + self._yield_helper.generate_tallies( + materials, tuple(sorted(self._mat_index_map.values()))) + + + # Return number density vector + return list(self.number.get_mat_slice(np.s_[:])) + + + + def write_bos_data(self, step): + """Document beginning of step data for a given step + + Called at the beginning of a depletion step and at + the final point in the simulation. + + Parameters + ---------- + step : int + Current depletion step including restarts + """ + ... + + + def _update_materials(self): + """Updates material compositions in OpenMC on all processes.""" + + for rank in range(comm.size): + number_i = comm.bcast(self.number, root=rank) + + for mat in number_i.materials: + nuclides = [] + densities = [] + for nuc in number_i.nuclides: + if nuc in self.nuclides_with_data: + val = 1.0e-24 * number_i.get_atom_density(mat, nuc) + + # If nuclide is zero, do not add to the problem. + if val > 0.0: + if self.round_number: + val_magnitude = np.floor(np.log10(val)) + val_scaled = val / 10**val_magnitude + val_round = round(val_scaled, 8) + + val = val_round * 10**val_magnitude + + nuclides.append(nuc) + densities.append(val) + else: + # Only output warnings if values are significantly + # negative. CRAM does not guarantee positive values. + if val < -1.0e-21: + print("WARNING: nuclide ", nuc, " in material ", mat, + " is negative (density = ", val, " at/barn-cm)") + number_i[mat, nuc] = 0.0 + + + #TODO Update densities on the Python side, otherwise the + # summary.h5 file contains densities at the first time step From 53b5cce209a9777368da90a53e29b7658b40295c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 08:01:07 +0100 Subject: [PATCH 0414/2654] Applying missed suggestions Co-authored-by: Paul Romano --- openmc/data/data.py | 13 ++++++------- openmc/material.py | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 914c6c622..d50afecc2 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -278,9 +278,9 @@ def atomic_weight(element): def half_life(isotope): - """Return half-life of isotope in seconds. Returns None if isotope is stable + """Return half-life of isotope in seconds or None if isotope is stable - Half-life values are from `ENDF/B VIII.0 Decay Reaction Sublibrary + Half-life values are from the `ENDF/B-VIII.0 decay sublibrary `_. Parameters @@ -291,15 +291,14 @@ def half_life(isotope): Returns ------- float - Half-life of isotope in [seconds] + Half-life of isotope in [s] """ global _HALF_LIFE if not _HALF_LIFE: - # Load data from AME2016 file - half_life_filename = os.path.join(os.path.dirname(__file__), 'half_life.json') - with open(half_life_filename, 'r') as f: - _HALF_LIFE = json.load(f) + # Load ENDF/B-VIII.0 data from JSON file + half_life_path = Path(__file__).with_name('half_life.json') + _HALF_LIFE = json.load(half_life_path.read_text()) if isotope.title() not in _HALF_LIFE.keys(): return None diff --git a/openmc/material.py b/openmc/material.py index 70cfa7ade..95fd7aaf7 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -147,9 +147,9 @@ class Material(IDManagerMixin): def activity(self): """Returns the total activity of the material in Becquerels.""" - atoms_per_barn_cm2 = self.get_nuclide_atom_densities() + atoms_per_barn_cm = self.get_nuclide_atom_densities() total_activity = 0 - for key, value in atoms_per_barn_cm2.items(): + for key, value in atoms_per_barn_cm.items(): half_life = openmc.data.half_life(key) if half_life: atoms = value[1] * self.volume From 9b36424e1632aa69716f8f07a51fc8c68d6ad3bf Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 08:19:00 +0100 Subject: [PATCH 0415/2654] added remove element to material --- openmc/material.py | 17 +++++++++++++++++ tests/unit_tests/test_material.py | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index de1b2187b..188ec2d47 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -407,6 +407,23 @@ class Material(IDManagerMixin): if nuclide == nuc.name: self.nuclides.remove(nuc) + def remove_element(self, element): + """Remove an element from the material + + Parameters + ---------- + element : str + Element to remove + + """ + cv.check_type('element', element, str) + + # If the Material contains the element, delete it + for nuc in reversed(self.nuclides): + element_name = re.split(r'(\d+)', nuc) + if nuc == element_name: + self.nuclides.remove(nuc) + def add_macroscopic(self, macroscopic): """Add a macroscopic to the material. This will also set the density of the material to 1.0, unless it has been otherwise set, diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 3a976da99..dda75c88b 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -43,7 +43,7 @@ def test_remove_elements(): m = openmc.Material() for elem, percent in [('Li', 1.0), ('Be', 1.0)]: m.add_element(elem, percent) - m.remove_nuclide('Li') + m.remove_element('Li') assert len(m.nuclides) == 1 assert m.nuclides == ['Be9'] assert m.nuclides[0].percent == 1.0 From 839c0fe81b1b65d205429f79dab317b3251b606a Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 08:32:37 +0100 Subject: [PATCH 0416/2654] refined remove element --- openmc/material.py | 5 +++-- tests/unit_tests/test_material.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 188ec2d47..d8fd1859f 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -420,8 +420,9 @@ class Material(IDManagerMixin): # If the Material contains the element, delete it for nuc in reversed(self.nuclides): - element_name = re.split(r'(\d+)', nuc) - if nuc == element_name: + element_name = re.split(r'(\d+)', nuc.name)[0] + print(element_name, element) + if element_name == element: self.nuclides.remove(nuc) def add_macroscopic(self, macroscopic): diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index dda75c88b..bfa40bb21 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -45,7 +45,7 @@ def test_remove_elements(): m.add_element(elem, percent) m.remove_element('Li') assert len(m.nuclides) == 1 - assert m.nuclides == ['Be9'] + assert m.nuclides[0].name == 'Be9' assert m.nuclides[0].percent == 1.0 From 649f4a28f260574725d9ae847a22d59ad42b69e3 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 14:21:02 +0200 Subject: [PATCH 0417/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- openmc/data/data.py | 7 ++----- openmc/material.py | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index d50afecc2..108b3c63a 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -298,12 +298,9 @@ def half_life(isotope): if not _HALF_LIFE: # Load ENDF/B-VIII.0 data from JSON file half_life_path = Path(__file__).with_name('half_life.json') - _HALF_LIFE = json.load(half_life_path.read_text()) + _HALF_LIFE = json.loads(half_life_path.read_text()) - if isotope.title() not in _HALF_LIFE.keys(): - return None - - return _HALF_LIFE[isotope.title()] + return _HALF_LIFE.get(isotope.title()) def water_density(temperature, pressure=0.1013): """Return the density of liquid water at a given temperature and pressure. diff --git a/openmc/material.py b/openmc/material.py index 95fd7aaf7..47f39b990 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -152,10 +152,8 @@ class Material(IDManagerMixin): for key, value in atoms_per_barn_cm.items(): half_life = openmc.data.half_life(key) if half_life: - atoms = value[1] * self.volume - activity = atoms / half_life - total_activity += activity - total_activity = math.log(2) * total_activity * 1e24 + total_activity += value[1] / half_life + total_activity *= math.log(2) * 1e24 * self.volume return total_activity From a003c5850a9dba44355c1af50ce5661ec74d742f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 14:59:21 +0100 Subject: [PATCH 0418/2654] added type hints to match doc strings --- openmc/material.py | 69 ++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index de1b2187b..31e674611 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -3,8 +3,11 @@ from collections.abc import Iterable from copy import deepcopy from numbers import Real from pathlib import Path +import os import re +import typing # imported separately as py3.8 requires typing.Iterable import warnings +from typing import Optional, Union from xml.etree import ElementTree as ET import numpy as np @@ -206,7 +209,7 @@ class Material(IDManagerMixin): return self._volume @name.setter - def name(self, name): + def name(self, name: Optional[str]): if name is not None: cv.check_type(f'name for Material ID="{self._id}"', name, str) @@ -215,25 +218,25 @@ class Material(IDManagerMixin): self._name = '' @temperature.setter - def temperature(self, temperature): + def temperature(self, temperature: Optional[Real]): cv.check_type(f'Temperature for Material ID="{self._id}"', temperature, (Real, type(None))) self._temperature = temperature @depletable.setter - def depletable(self, depletable): + def depletable(self, depletable: bool): cv.check_type(f'Depletable flag for Material ID="{self._id}"', depletable, bool) self._depletable = depletable @volume.setter - def volume(self, volume): + def volume(self, volume: Real): if volume is not None: cv.check_type('material volume', volume, Real) self._volume = volume @isotropic.setter - def isotropic(self, isotropic): + def isotropic(self, isotropic: typing.Iterable[str]): cv.check_iterable_type('Isotropic scattering nuclides', isotropic, str) self._isotropic = list(isotropic) @@ -251,7 +254,7 @@ class Material(IDManagerMixin): return density*self.volume @classmethod - def from_hdf5(cls, group): + def from_hdf5(cls, group: str): """Create material from HDF5 group Parameters @@ -305,7 +308,7 @@ class Material(IDManagerMixin): return material - def add_volume_information(self, volume_calc): + def add_volume_information(self, volume_calc: openmc.VolumeCalculation): """Add volume information to a material. Parameters @@ -325,7 +328,7 @@ class Material(IDManagerMixin): raise ValueError('No volume information found for material ID={}.' .format(self.id)) - def set_density(self, units, density=None): + def set_density(self, units: str, density:Optional[float]=None): """Set the density of the material Parameters @@ -357,7 +360,7 @@ class Material(IDManagerMixin): density, Real) self._density = density - def add_nuclide(self, nuclide, percent, percent_type='ao'): + def add_nuclide(self, nuclide: str, percent: float, percent_type: str='ao'): """Add a nuclide to the material Parameters @@ -391,7 +394,7 @@ class Material(IDManagerMixin): self._nuclides.append(NuclideTuple(nuclide, percent, percent_type)) - def remove_nuclide(self, nuclide): + def remove_nuclide(self, nuclide: str): """Remove a nuclide from the material Parameters @@ -407,7 +410,7 @@ class Material(IDManagerMixin): if nuclide == nuc.name: self.nuclides.remove(nuc) - def add_macroscopic(self, macroscopic): + def add_macroscopic(self, macroscopic: str): """Add a macroscopic to the material. This will also set the density of the material to 1.0, unless it has been otherwise set, as a default for Macroscopic cross sections. @@ -449,7 +452,7 @@ class Material(IDManagerMixin): if self._density is None: self.set_density('macro', 1.0) - def remove_macroscopic(self, macroscopic): + def remove_macroscopic(self, macroscopic: str): """Remove a macroscopic from the material Parameters @@ -468,8 +471,10 @@ class Material(IDManagerMixin): if macroscopic == self._macroscopic: self._macroscopic = None - def add_element(self, element, percent, percent_type='ao', enrichment=None, - enrichment_target=None, enrichment_type=None): + def add_element(self, element: str, percent: float, percent_type: str='ao', + enrichment: Optional[float]=None, + enrichment_target: Optional[str]=None, + enrichment_type: Optional[str]=None): """Add a natural element to the material Parameters @@ -574,8 +579,10 @@ class Material(IDManagerMixin): enrichment_type): self.add_nuclide(*nuclide) - def add_elements_from_formula(self, formula, percent_type='ao', enrichment=None, - enrichment_target=None, enrichment_type=None): + def add_elements_from_formula(self, formula: str, percent_type: str='ao', + enrichment: Optional[float]=None, + enrichment_target: Optional[float]=None, + enrichment_type: Optional[str]=None): """Add a elements from a chemical formula to the material. .. versionadded:: 0.12 @@ -672,7 +679,7 @@ class Material(IDManagerMixin): else: self.add_element(element, percent, percent_type) - def add_s_alpha_beta(self, name, fraction=1.0): + def add_s_alpha_beta(self, name: str, fraction: float=1.0): r"""Add an :math:`S(\alpha,\beta)` table to the material Parameters @@ -821,7 +828,7 @@ class Material(IDManagerMixin): return nuclides - def get_mass_density(self, nuclide=None): + def get_mass_density(self, nuclide: Optional[str]=None): """Return mass density of one or all nuclides Parameters @@ -844,7 +851,7 @@ class Material(IDManagerMixin): mass_density += density_i return mass_density - def get_mass(self, nuclide=None): + def get_mass(self, nuclide: Optional[str]=None): """Return mass of one or all nuclides. Note that this method requires that the :attr:`Material.volume` has @@ -866,7 +873,7 @@ class Material(IDManagerMixin): raise ValueError("Volume must be set in order to determine mass.") return self.volume*self.get_mass_density(nuclide) - def clone(self, memo=None): + def clone(self, memo: Optional[dict]=None): """Create a copy of this material with a new unique ID. Parameters @@ -905,7 +912,7 @@ class Material(IDManagerMixin): return memo[self] - def _get_nuclide_xml(self, nuclide): + def _get_nuclide_xml(self, nuclide: str): xml_element = ET.Element("nuclide") xml_element.set("name", nuclide.name) @@ -916,13 +923,13 @@ class Material(IDManagerMixin): return xml_element - def _get_macroscopic_xml(self, macroscopic): + def _get_macroscopic_xml(self, macroscopic: str): xml_element = ET.Element("macroscopic") xml_element.set("name", macroscopic) return xml_element - def _get_nuclides_xml(self, nuclides): + def _get_nuclides_xml(self, nuclides: typing.Iterable[str]): xml_elements = [] for nuclide in nuclides: xml_elements.append(self._get_nuclide_xml(nuclide)) @@ -989,7 +996,9 @@ class Material(IDManagerMixin): return element @classmethod - def mix_materials(cls, materials, fracs, percent_type='ao', name=None): + def mix_materials(cls, materials: typing.Iterable[openmc.Material], + fracs: typing.Iterable[float], percent_type: str='ao', + name: Optional[str]=None): """Mix materials together based on atom, weight, or volume fractions .. versionadded:: 0.12 @@ -1087,7 +1096,7 @@ class Material(IDManagerMixin): return new_mat @classmethod - def from_xml_element(cls, elem): + def from_xml_element(cls, elem: ET.Element): """Generate material from an XML element Parameters @@ -1190,7 +1199,7 @@ class Materials(cv.CheckedList): if cross_sections is not None: self._cross_sections = Path(cross_sections) - def append(self, material): + def append(self, material: openmc.Material): """Append material to collection Parameters @@ -1201,7 +1210,7 @@ class Materials(cv.CheckedList): """ super().append(material) - def insert(self, index, material): + def insert(self, index: int, material: openmc.Material): """Insert material before index Parameters @@ -1218,7 +1227,7 @@ class Materials(cv.CheckedList): for material in self: material.make_isotropic_in_lab() - def export_to_xml(self, path='materials.xml'): + def export_to_xml(self, path: Union[str, os.PathLike]='materials.xml'): """Export material collection to an XML file. Parameters @@ -1265,12 +1274,12 @@ class Materials(cv.CheckedList): fh.write('\n') @classmethod - def from_xml(cls, path='materials.xml'): + def from_xml(cls, path: Union[str, os.PathLike]='materials.xml'): """Generate materials collection from XML file Parameters ---------- - path : str, optional + path : str Path to materials XML file Returns From c2018c41fdc87d069e00cbe4e87cc07b87d8fc52 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 22:45:37 +0200 Subject: [PATCH 0419/2654] More efficient regex usage Co-authored-by: Paul Romano --- openmc/material.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index d8fd1859f..7e142f09a 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -420,8 +420,7 @@ class Material(IDManagerMixin): # If the Material contains the element, delete it for nuc in reversed(self.nuclides): - element_name = re.split(r'(\d+)', nuc.name)[0] - print(element_name, element) + element_name = re.split(r'\d+', nuc.name)[0] if element_name == element: self.nuclides.remove(nuc) From debc085cf692cb4f2a8a9585d0acfe4a7b06bfb9 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 22 Jun 2022 22:50:07 +0200 Subject: [PATCH 0420/2654] add placeholder skeleton for MCPL-input --- include/openmc/source.h | 19 +++++++++++++++++++ src/source.cpp | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/openmc/source.h b/include/openmc/source.h index 18fddc689..cadbfe93b 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -100,6 +100,25 @@ private: vector sites_; //!< Source sites from a file }; +//============================================================================== +// MCPL-file input source +//============================================================================== +class MCPLFileSource : public Source { +public: + // Constructors, destructors + MCPLFileSource(std::string path); + ~MCPLFileSource(); + + // Defer implementation to custom source library + SourceSite sample(uint64_t* seed) const override + +private: + vector sites_; //! Date: Wed, 22 Jun 2022 22:41:01 +0100 Subject: [PATCH 0421/2654] removed circular import types --- openmc/material.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 31e674611..78655007f 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -308,7 +308,7 @@ class Material(IDManagerMixin): return material - def add_volume_information(self, volume_calc: openmc.VolumeCalculation): + def add_volume_information(self, volume_calc): """Add volume information to a material. Parameters @@ -472,9 +472,9 @@ class Material(IDManagerMixin): self._macroscopic = None def add_element(self, element: str, percent: float, percent_type: str='ao', - enrichment: Optional[float]=None, - enrichment_target: Optional[str]=None, - enrichment_type: Optional[str]=None): + enrichment: Optional[float]=None, + enrichment_target: Optional[str]=None, + enrichment_type: Optional[str]=None): """Add a natural element to the material Parameters @@ -996,9 +996,8 @@ class Material(IDManagerMixin): return element @classmethod - def mix_materials(cls, materials: typing.Iterable[openmc.Material], - fracs: typing.Iterable[float], percent_type: str='ao', - name: Optional[str]=None): + def mix_materials(cls, materials, fracs: typing.Iterable[float], + percent_type: str='ao', name: Optional[str]=None): """Mix materials together based on atom, weight, or volume fractions .. versionadded:: 0.12 @@ -1199,7 +1198,7 @@ class Materials(cv.CheckedList): if cross_sections is not None: self._cross_sections = Path(cross_sections) - def append(self, material: openmc.Material): + def append(self, material): """Append material to collection Parameters @@ -1210,7 +1209,7 @@ class Materials(cv.CheckedList): """ super().append(material) - def insert(self, index: int, material: openmc.Material): + def insert(self, index: int, material): """Insert material before index Parameters From 270ef8346ceadf03c1724db355f4ec06768e1f07 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 23:18:14 +0100 Subject: [PATCH 0422/2654] added metastable activity test --- tests/unit_tests/test_material.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index c5d3276a0..c56c350b0 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -423,3 +423,11 @@ def test_activity_of_tritium(): m1.volume = 1 assert pytest.approx(m1.activity) == 3.559778e14 + +def test_activity_of_metastable(): + """Checks that 1 mol of a Tc99_m1 nuclides has the correct activity""" + m1 = openmc.Material() + m1.add_nuclide("Tc99_m1", 1) + m1.set_density('g/cm3', 1) + m1.volume = 98.9 + assert pytest.approx(m1.activity, rel=0.001) == 1.93e19 From 344c2a46404cdc74a114efd2f78fb8bc86dc46e2 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Jun 2022 23:27:41 +0100 Subject: [PATCH 0423/2654] lower case nucs in half-life --- openmc/data/data.py | 2 +- openmc/data/half_life.json | 7122 ++++++++++++++++++------------------ 2 files changed, 3562 insertions(+), 3562 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 108b3c63a..3a3cf5826 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -300,7 +300,7 @@ def half_life(isotope): half_life_path = Path(__file__).with_name('half_life.json') _HALF_LIFE = json.loads(half_life_path.read_text()) - return _HALF_LIFE.get(isotope.title()) + return _HALF_LIFE.get(isotope.lower()) def water_density(temperature, pressure=0.1013): """Return the density of liquid water at a given temperature and pressure. diff --git a/openmc/data/half_life.json b/openmc/data/half_life.json index bb67da75d..4f670918b 100644 --- a/openmc/data/half_life.json +++ b/openmc/data/half_life.json @@ -1,3563 +1,3563 @@ { - "H3": 388789600.0, - "H4": 9.90652e-23, - "H5": 7.99473e-23, - "H6": 2.84812e-22, - "H7": 2.3e-23, - "He5": 7.595e-22, - "He6": 0.8067, - "He7": 3.038e-21, - "He8": 0.1191, - "He9": 7e-21, - "He10": 1.519e-21, - "Li4": 7.55721e-23, - "Li5": 3.06868e-22, - "Li8": 0.838, - "Li9": 0.1783, - "Li10": 2e-21, - "Li11": 0.00859, - "Li12": 1e-08, - "Be5": 1e-09, - "Be6": 4.95326e-21, - "Be7": 4598208.0, - "Be8": 8.18132e-17, - "Be10": 47652000000000.0, - "Be11": 13.81, - "Be12": 0.0213, - "Be13": 2.7e-21, - "Be14": 0.00435, - "Be15": 2e-07, - "Be16": 2e-07, - "B6": 1e-09, - "B7": 3.255e-22, - "B8": 0.77, - "B9": 8.43888e-19, - "B12": 0.0202, - "B13": 0.01736, - "B14": 0.0125, - "B15": 0.00993, - "B16": 1.9e-10, - "B17": 0.00508, - "B18": 2.6e-08, - "B19": 0.00292, - "C8": 1.9813e-21, - "C9": 0.1265, - "C10": 19.29, - "C11": 1223.1, - "C14": 179878000000.0, - "C15": 2.449, - "C16": 0.747, - "C17": 0.193, - "C18": 0.092, - "C19": 0.049, - "C20": 0.0145, - "C21": 3e-08, - "C22": 0.0062, - "N10": 2e-22, - "N11": 3.12742e-22, - "N12": 0.011, - "N13": 597.9, - "N16": 7.13, - "N17": 4.171, - "N18": 0.624, - "N19": 0.271, - "N20": 0.13, - "N21": 0.085, - "N22": 0.024, - "N23": 0.0145, - "N24": 5.2e-08, - "N25": 2.6e-07, - "O12": 1.13925e-21, - "O13": 0.00858, - "O14": 70.606, - "O15": 122.24, - "O19": 26.88, - "O20": 13.51, - "O21": 3.42, - "O22": 2.25, - "O23": 0.0905, - "O24": 0.065, - "O25": 5e-08, - "O26": 4e-08, - "O27": 2.6e-07, - "O28": 1e-07, - "F14": 5.0007e-22, - "F15": 4.557e-22, - "F16": 1.13925e-20, - "F17": 64.49, - "F18": 6586.2, - "F20": 11.163, - "F21": 4.158, - "F22": 4.23, - "F23": 2.23, - "F24": 0.39, - "F25": 0.05, - "F26": 0.0096, - "F27": 0.005, - "F28": 4e-08, - "F29": 0.0025, - "F30": 2.6e-07, - "F31": 2.5e-07, - "Ne16": 3.73524e-21, - "Ne17": 0.1092, - "Ne18": 1.672, - "Ne19": 17.22, - "Ne23": 37.24, - "Ne24": 202.8, - "Ne25": 0.602, - "Ne26": 0.197, - "Ne27": 0.032, - "Ne28": 0.0189, - "Ne29": 0.0148, - "Ne30": 0.0073, - "Ne31": 0.0034, - "Ne32": 0.0035, - "Ne33": 1.8e-07, - "Ne34": 6e-08, - "Na18": 1.3e-21, - "Na19": 4e-08, - "Na20": 0.4479, - "Na21": 22.49, - "Na22": 82134970.0, - "Na24": 53989.2, - "Na24_m1": 0.02018, - "Na25": 59.1, - "Na26": 1.077, - "Na27": 0.301, - "Na28": 0.0305, - "Na29": 0.0449, - "Na30": 0.048, - "Na31": 0.017, - "Na32": 0.0132, - "Na33": 0.008, - "Na34": 0.0055, - "Na35": 0.0015, - "Na36": 1.8e-07, - "Na37": 6e-08, - "Mg19": 4e-12, - "Mg20": 0.0908, - "Mg21": 0.122, - "Mg22": 3.8755, - "Mg23": 11.317, - "Mg27": 567.48, - "Mg28": 75294.0, - "Mg29": 1.3, - "Mg30": 0.335, - "Mg31": 0.232, - "Mg32": 0.086, - "Mg33": 0.0905, - "Mg34": 0.02, - "Mg35": 0.07, - "Mg36": 0.0039, - "Mg37": 2.6e-07, - "Mg38": 2.6e-07, - "Mg39": 1.8e-07, - "Mg40": 1.7e-07, - "Al21": 3.5e-08, - "Al22": 0.059, - "Al23": 0.47, - "Al24": 2.053, - "Al24_m1": 0.13, - "Al25": 7.183, - "Al26": 22626800000000.0, - "Al26_m1": 6.3452, - "Al28": 134.484, - "Al29": 393.6, - "Al30": 3.62, - "Al31": 0.644, - "Al32": 0.033, - "Al33": 0.0417, - "Al34": 0.042, - "Al35": 0.0386, - "Al36": 0.09, - "Al37": 0.0107, - "Al38": 0.0076, - "Al39": 7.6e-06, - "Al40": 2.6e-07, - "Al41": 2.6e-07, - "Al42": 1.7e-07, - "Si22": 0.029, - "Si23": 0.0423, - "Si24": 0.14, - "Si25": 0.22, - "Si26": 2.234, - "Si27": 4.16, - "Si31": 9438.0, - "Si32": 4828310000.0, - "Si33": 6.11, - "Si34": 2.77, - "Si35": 0.78, - "Si36": 0.45, - "Si37": 0.09, - "Si38": 1e-06, - "Si39": 0.0475, - "Si40": 0.033, - "Si41": 0.02, - "Si42": 0.0125, - "Si43": 6e-08, - "Si44": 3.6e-07, - "P24": 0.0074, - "P25": 3e-08, - "P26": 0.0437, - "P27": 0.26, - "P28": 0.2703, - "P29": 4.142, - "P30": 149.88, - "P32": 1232323.0, - "P33": 2189376.0, - "P34": 12.43, - "P35": 47.3, - "P36": 5.6, - "P37": 2.31, - "P38": 0.64, - "P39": 0.28, - "P40": 0.125, - "P41": 0.1, - "P42": 0.0485, - "P43": 0.0365, - "P44": 0.0185, - "P45": 2e-07, - "P46": 2e-07, - "S26": 0.01, - "S27": 0.0155, - "S28": 0.125, - "S29": 0.187, - "S30": 1.178, - "S31": 2.572, - "S35": 7560864.0, - "S37": 303.0, - "S38": 10218.0, - "S39": 11.5, - "S40": 8.8, - "S41": 1.99, - "S42": 1.013, - "S43": 0.28, - "S44": 0.1, - "S45": 0.068, - "S46": 0.05, - "S48": 2e-07, - "S49": 2e-07, - "Cl28": 0.0017, - "Cl29": 2e-08, - "Cl30": 3e-08, - "Cl31": 0.15, - "Cl32": 0.298, - "Cl33": 2.511, - "Cl34": 1.5264, - "Cl34_m1": 1920.0, - "Cl36": 9498840000000.0, - "Cl38": 2233.8, - "Cl38_m1": 0.715, - "Cl39": 3336.0, - "Cl40": 81.0, - "Cl41": 38.4, - "Cl42": 6.8, - "Cl43": 3.13, - "Cl44": 0.56, - "Cl45": 0.413, - "Cl46": 0.232, - "Cl47": 0.101, - "Cl48": 2e-07, - "Cl49": 1.7e-07, - "Cl50": 0.02, - "Cl51": 2e-07, - "Ar30": 2e-08, - "Ar31": 0.0151, - "Ar32": 0.098, - "Ar33": 0.173, - "Ar34": 0.8445, - "Ar35": 1.775, - "Ar37": 3027456.0, - "Ar39": 8488990000.0, - "Ar41": 6576.6, - "Ar42": 1038250000.0, - "Ar43": 322.2, - "Ar44": 712.2, - "Ar45": 21.48, - "Ar46": 8.4, - "Ar47": 1.23, - "Ar48": 0.475, - "Ar49": 0.17, - "Ar50": 0.085, - "Ar51": 2e-07, - "Ar52": 0.01, - "Ar53": 0.003, - "K32": 0.0033, - "K33": 2.5e-08, - "K34": 2.5e-08, - "K35": 0.178, - "K36": 0.342, - "K37": 1.226, - "K38": 458.16, - "K38_m1": 0.924, - "K40": 3.93839e16, - "K42": 44496.0, - "K43": 80280.0, - "K44": 1327.8, - "K45": 1068.6, - "K46": 105.0, - "K47": 17.5, - "K48": 6.8, - "K49": 1.26, - "K50": 0.472, - "K51": 0.365, - "K52": 0.105, - "K53": 0.03, - "K54": 0.01, - "K55": 0.003, - "Ca34": 3.5e-08, - "Ca35": 0.0257, - "Ca36": 0.102, - "Ca37": 0.1811, - "Ca38": 0.44, - "Ca39": 0.8596, - "Ca41": 3218880000000.0, - "Ca45": 14049500.0, - "Ca47": 391910.4, - "Ca48": 7.25824e26, - "Ca49": 523.08, - "Ca50": 13.9, - "Ca51": 10.0, - "Ca52": 4.6, - "Ca53": 0.09, - "Ca54": 0.086, - "Ca55": 0.022, - "Ca56": 0.01, - "Ca57": 0.005, - "Sc36": 0.0088, - "Sc37": 0.056, - "Sc38": 0.0423, - "Sc39": 3e-07, - "Sc40": 0.1823, - "Sc41": 0.5963, - "Sc42": 0.6808, - "Sc42_m1": 62.0, - "Sc43": 14007.6, - "Sc44": 14292.0, - "Sc44_m1": 210996.0, - "Sc45_m1": 0.318, - "Sc46": 7239456.0, - "Sc46_m1": 18.75, - "Sc47": 289370.9, - "Sc48": 157212.0, - "Sc49": 3430.8, - "Sc50": 102.5, - "Sc50_m1": 0.35, - "Sc51": 12.4, - "Sc52": 8.2, - "Sc53": 3.0, - "Sc54": 0.36, - "Sc55": 0.105, - "Sc56": 0.06, - "Sc57": 0.013, - "Sc58": 0.012, - "Sc59": 0.01, - "Sc60": 0.003, - "Ti38": 1.2e-07, - "Ti39": 0.032, - "Ti40": 0.0533, - "Ti41": 0.0804, - "Ti42": 0.199, - "Ti43": 0.509, - "Ti44": 1893460000.0, - "Ti45": 11088.0, - "Ti51": 345.6, - "Ti52": 102.0, - "Ti53": 32.7, - "Ti54": 1.5, - "Ti55": 1.3, - "Ti56": 0.2, - "Ti57": 0.06, - "Ti58": 0.059, - "Ti59": 0.03, - "Ti60": 0.022, - "Ti61": 3e-07, - "Ti62": 0.01, - "Ti63": 0.003, - "V40": 0.0077, - "V41": 0.0244, - "V42": 5.5e-08, - "V43": 0.8, - "V44": 0.111, - "V44_m1": 0.15, - "V45": 0.547, - "V46": 0.4225, - "V46_m1": 0.00102, - "V47": 1956.0, - "V48": 1380110.0, - "V49": 28512000.0, - "V50": 4.41806e24, - "V52": 224.58, - "V53": 92.58, - "V54": 49.8, - "V55": 6.54, - "V56": 0.216, - "V57": 0.35, - "V58": 0.185, - "V59": 0.075, - "V60": 0.068, - "V61": 0.047, - "V62": 1.5e-07, - "V63": 0.017, - "V64": 0.019, - "V65": 0.01, - "Cr42": 0.014, - "Cr43": 0.0216, - "Cr44": 0.0535, - "Cr45": 0.0609, - "Cr46": 0.26, - "Cr47": 0.5, - "Cr48": 77616.0, - "Cr49": 2538.0, - "Cr51": 2393366.0, - "Cr55": 209.82, - "Cr56": 356.4, - "Cr57": 21.1, - "Cr58": 7.0, - "Cr59": 0.46, - "Cr60": 0.49, - "Cr61": 0.27, - "Cr62": 0.19, - "Cr63": 0.129, - "Cr64": 0.043, - "Cr65": 0.027, - "Cr66": 0.01, - "Cr67": 0.05, - "Mn44": 1.05e-07, - "Mn45": 7e-08, - "Mn46": 0.0345, - "Mn47": 0.1, - "Mn48": 0.1581, - "Mn49": 0.382, - "Mn50": 0.28319, - "Mn50_m1": 105.0, - "Mn51": 2772.0, - "Mn52": 483062.4, - "Mn52_m1": 1266.0, - "Mn53": 116763000000000.0, - "Mn54": 26961120.0, - "Mn56": 9284.04, - "Mn57": 85.4, - "Mn58": 3.0, - "Mn58_m1": 65.4, - "Mn59": 4.59, - "Mn60": 51.0, - "Mn60_m1": 1.77, - "Mn61": 0.67, - "Mn62": 0.671, - "Mn62_m1": 0.092, - "Mn63": 0.29, - "Mn64": 0.09, - "Mn65": 0.092, - "Mn66": 0.064, - "Mn67": 0.047, - "Mn68": 0.028, - "Mn69": 0.014, - "Fe45": 0.00203, - "Fe46": 0.013, - "Fe47": 0.0219, - "Fe48": 0.044, - "Fe49": 0.0647, - "Fe50": 0.155, - "Fe51": 0.305, - "Fe52": 29790.0, - "Fe52_m1": 45.9, - "Fe53": 510.6, - "Fe53_m1": 152.4, - "Fe55": 86594050.0, - "Fe59": 3844368.0, - "Fe60": 47336400000000.0, - "Fe61": 358.8, - "Fe62": 68.0, - "Fe63": 6.1, - "Fe64": 2.0, - "Fe65": 0.81, - "Fe65_m1": 1.12, - "Fe66": 0.44, - "Fe67": 0.416, - "Fe68": 0.187, - "Fe69": 0.109, - "Fe70": 0.094, - "Fe71": 0.028, - "Fe72": 1.5e-07, - "Co49": 3.5e-08, - "Co50": 0.044, - "Co51": 2e-07, - "Co52": 0.115, - "Co53": 0.24, - "Co53_m1": 0.247, - "Co54": 0.19328, - "Co54_m1": 88.8, - "Co55": 63108.0, - "Co56": 6672931.0, - "Co57": 23478340.0, - "Co58": 6122304.0, - "Co58_m1": 32760.0, - "Co60": 166344200.0, - "Co60_m1": 628.02, - "Co61": 5940.0, - "Co62": 90.0, - "Co62_m1": 834.6, - "Co63": 27.4, - "Co64": 0.3, - "Co65": 1.16, - "Co66": 0.2, - "Co67": 0.425, - "Co68": 0.199, - "Co68_m1": 1.6, - "Co69": 0.22, - "Co70": 0.119, - "Co70_m1": 0.5, - "Co71": 0.079, - "Co72": 0.0599, - "Co73": 0.041, - "Co74": 0.03, - "Co75": 0.034, - "Ni48": 0.0021, - "Ni49": 0.0075, - "Ni50": 0.012, - "Ni51": 2e-07, - "Ni52": 0.038, - "Ni53": 0.045, - "Ni54": 0.104, - "Ni55": 0.2047, - "Ni56": 524880.0, - "Ni57": 128160.0, - "Ni59": 2398380000000.0, - "Ni63": 3193630000.0, - "Ni65": 9061.884, - "Ni66": 196560.0, - "Ni67": 21.0, - "Ni68": 29.0, - "Ni69": 11.4, - "Ni69_m1": 3.5, - "Ni70": 6.0, - "Ni71": 2.56, - "Ni72": 1.57, - "Ni73": 0.84, - "Ni74": 0.68, - "Ni75": 0.6, - "Ni76": 0.238, - "Ni77": 0.061, - "Ni78": 0.11, - "Cu52": 0.0069, - "Cu53": 3e-07, - "Cu54": 7.5e-08, - "Cu55": 0.04, - "Cu56": 0.094, - "Cu57": 0.1963, - "Cu58": 3.204, - "Cu59": 81.5, - "Cu60": 1422.0, - "Cu61": 11998.8, - "Cu62": 580.38, - "Cu64": 45723.6, - "Cu66": 307.2, - "Cu67": 222588.0, - "Cu68": 31.1, - "Cu68_m1": 225.0, - "Cu69": 171.0, - "Cu70": 44.5, - "Cu70_m1": 33.0, - "Cu70_m2": 6.6, - "Cu71": 19.5, - "Cu72": 6.63, - "Cu73": 4.2, - "Cu74": 1.75, - "Cu75": 1.224, - "Cu76": 0.653, - "Cu76_m1": 1.27, - "Cu77": 0.469, - "Cu78": 0.335, - "Cu79": 0.188, - "Cu80": 0.17, - "Cu81": 0.028, - "Zn54": 0.0037, - "Zn55": 0.02, - "Zn56": 5e-07, - "Zn57": 0.038, - "Zn58": 0.084, - "Zn59": 0.182, - "Zn60": 142.8, - "Zn61": 89.1, - "Zn61_m1": 0.43, - "Zn61_m2": 0.14, - "Zn62": 33336.0, - "Zn63": 2308.2, - "Zn65": 21075550.0, - "Zn69": 3384.0, - "Zn69_m1": 49536.0, - "Zn71": 147.0, - "Zn71_m1": 14256.0, - "Zn72": 167400.0, - "Zn73": 23.5, - "Zn73_m1": 5.8, - "Zn73_m2": 0.013, - "Zn74": 95.6, - "Zn75": 10.2, - "Zn76": 5.7, - "Zn77": 2.08, - "Zn77_m1": 1.05, - "Zn78": 1.47, - "Zn79": 0.995, - "Zn80": 0.54, - "Zn81": 0.32, - "Zn82": 0.052, - "Zn83": 0.043, - "Ga56": 0.0059, - "Ga57": 0.0123, - "Ga58": 0.0152, - "Ga59": 0.0418, - "Ga60": 0.07, - "Ga61": 0.168, - "Ga62": 0.11612, - "Ga63": 32.4, - "Ga64": 157.62, - "Ga65": 912.0, - "Ga66": 34164.0, - "Ga67": 281810.9, - "Ga68": 4062.6, - "Ga70": 1268.4, - "Ga72": 50760.0, - "Ga72_m1": 0.03968, - "Ga73": 17496.0, - "Ga74": 487.2, - "Ga74_m1": 9.5, - "Ga75": 126.0, - "Ga76": 32.6, - "Ga77": 13.2, - "Ga78": 5.09, - "Ga79": 2.847, - "Ga80": 1.676, - "Ga81": 1.217, - "Ga82": 0.599, - "Ga83": 0.3081, - "Ga84": 0.085, - "Ga85": 0.048, - "Ga86": 0.029, - "Ge58": 0.0152, - "Ge59": 0.0418, - "Ge60": 0.03, - "Ge61": 0.039, - "Ge62": 1.5e-07, - "Ge63": 0.142, - "Ge64": 63.7, - "Ge65": 30.9, - "Ge66": 8136.0, - "Ge67": 1134.0, - "Ge68": 23410080.0, - "Ge69": 140580.0, - "Ge71": 987552.0, - "Ge71_m1": 0.02041, - "Ge73_m1": 0.499, - "Ge75": 4966.8, - "Ge75_m1": 47.7, - "Ge77": 40680.0, - "Ge77_m1": 52.9, - "Ge78": 5280.0, - "Ge79": 18.98, - "Ge79_m1": 39.0, - "Ge80": 29.5, - "Ge81": 7.6, - "Ge81_m1": 7.6, - "Ge82": 4.55, - "Ge83": 1.85, - "Ge84": 0.954, - "Ge85": 0.535, - "Ge86": 0.095, - "Ge87": 0.14, - "Ge88": 0.066, - "Ge89": 0.039, - "As60": 0.0083, - "As61": 0.0166, - "As62": 0.0259, - "As63": 0.0921, - "As64": 0.036, - "As65": 0.128, - "As66": 0.09579, - "As67": 42.5, - "As68": 151.6, - "As69": 913.8, - "As70": 3156.0, - "As71": 235080.0, - "As72": 93600.0, - "As73": 6937920.0, - "As74": 1535328.0, - "As75_m1": 0.01762, - "As76": 94464.0, - "As77": 139788.0, - "As78": 5442.0, - "As79": 540.6, - "As80": 15.2, - "As81": 33.3, - "As82": 19.1, - "As82_m1": 13.6, - "As83": 13.4, - "As84": 4.2, - "As85": 2.021, - "As86": 0.945, - "As87": 0.56, - "As88": 0.112, - "As89": 0.059, - "As90": 0.043, - "As91": 0.044, - "As92": 0.027, - "Se65": 0.05, - "Se66": 0.033, - "Se67": 0.136, - "Se68": 35.5, - "Se69": 27.4, - "Se70": 2466.0, - "Se71": 284.4, - "Se72": 725760.0, - "Se73": 25740.0, - "Se73_m1": 2388.0, - "Se75": 10349860.0, - "Se77_m1": 17.36, - "Se79": 9309490000000.0, - "Se79_m1": 235.2, - "Se81": 1107.0, - "Se81_m1": 3436.8, - "Se83": 1338.0, - "Se83_m1": 70.1, - "Se84": 195.6, - "Se85": 31.7, - "Se86": 14.3, - "Se87": 5.5, - "Se88": 1.53, - "Se89": 0.41, - "Se90": 0.161, - "Se91": 0.27, - "Se92": 0.093, - "Se93": 0.062, - "Se94": 0.059, - "Br67": 0.0443, - "Br68": 1.2e-06, - "Br69": 2.4e-08, - "Br70": 0.0791, - "Br70_m1": 2.2, - "Br71": 21.4, - "Br72": 78.6, - "Br72_m1": 10.6, - "Br73": 204.0, - "Br74": 1524.0, - "Br74_m1": 2760.0, - "Br75": 5802.0, - "Br76": 58320.0, - "Br76_m1": 1.31, - "Br77": 205329.6, - "Br77_m1": 256.8, - "Br78": 387.0, - "Br79_m1": 4.86, - "Br80": 1060.8, - "Br80_m1": 15913.8, - "Br82": 127015.2, - "Br82_m1": 367.8, - "Br83": 8640.0, - "Br84": 1905.6, - "Br84_m1": 360.0, - "Br85": 174.0, - "Br86": 55.0, - "Br87": 55.65, - "Br88": 16.29, - "Br89": 4.4, - "Br90": 1.92, - "Br91": 0.541, - "Br92": 0.343, - "Br93": 0.102, - "Br94": 0.07, - "Br95": 0.066, - "Br96": 0.042, - "Br97": 0.04, - "Kr69": 0.032, - "Kr70": 0.052, - "Kr71": 0.1, - "Kr72": 17.1, - "Kr73": 27.3, - "Kr74": 690.0, - "Kr75": 257.4, - "Kr76": 53280.0, - "Kr77": 4464.0, - "Kr79": 126144.0, - "Kr79_m1": 50.0, - "Kr81": 7226690000000.0, - "Kr81_m1": 13.1, - "Kr83_m1": 6588.0, - "Kr85": 339433500.0, - "Kr85_m1": 16128.0, - "Kr87": 4578.0, - "Kr88": 10224.0, - "Kr89": 189.0, - "Kr90": 32.32, - "Kr91": 8.57, - "Kr92": 1.84, - "Kr93": 1.286, - "Kr94": 0.212, - "Kr95": 0.114, - "Kr96": 0.08, - "Kr97": 0.063, - "Kr98": 0.046, - "Kr99": 0.027, - "Kr100": 0.007, - "Rb71": 1e-09, - "Rb72": 1.2e-06, - "Rb73": 3e-08, - "Rb74": 0.064776, - "Rb75": 19.0, - "Rb76": 36.5, - "Rb77": 226.2, - "Rb78": 1059.6, - "Rb78_m1": 344.4, - "Rb79": 1374.0, - "Rb80": 34.0, - "Rb81": 16459.2, - "Rb81_m1": 1830.0, - "Rb82": 75.45, - "Rb82_m1": 23299.2, - "Rb83": 7447680.0, - "Rb84": 2835648.0, - "Rb84_m1": 1215.6, - "Rb86": 1609718.0, - "Rb86_m1": 61.02, - "Rb87": 1.51792e18, - "Rb88": 1066.38, - "Rb89": 909.0, - "Rb90": 158.0, - "Rb90_m1": 258.0, - "Rb91": 58.4, - "Rb92": 4.492, - "Rb93": 5.84, - "Rb94": 2.702, - "Rb95": 0.3777, - "Rb96": 0.203, - "Rb97": 0.1691, - "Rb98": 0.114, - "Rb98_m1": 0.096, - "Rb99": 0.054, - "Rb100": 0.051, - "Rb101": 0.032, - "Rb102": 0.037, - "Sr73": 0.025, - "Sr74": 1.2e-06, - "Sr75": 0.088, - "Sr76": 7.89, - "Sr77": 9.0, - "Sr78": 150.0, - "Sr79": 135.0, - "Sr80": 6378.0, - "Sr81": 1338.0, - "Sr82": 2190240.0, - "Sr83": 116676.0, - "Sr83_m1": 4.95, - "Sr85": 5602176.0, - "Sr85_m1": 4057.8, - "Sr87_m1": 10134.0, - "Sr89": 4365792.0, - "Sr90": 908543300.0, - "Sr91": 34668.0, - "Sr92": 9756.0, - "Sr93": 445.38, - "Sr94": 75.3, - "Sr95": 23.9, - "Sr96": 1.07, - "Sr97": 0.429, - "Sr98": 0.653, - "Sr99": 0.27, - "Sr100": 0.202, - "Sr101": 0.118, - "Sr102": 0.069, - "Sr103": 0.068, - "Sr104": 0.043, - "Sr105": 0.0556, - "Y76": 2e-07, - "Y77": 0.062, - "Y78": 0.05, - "Y78_m1": 5.7, - "Y79": 14.8, - "Y80": 30.1, - "Y80_m1": 4.8, - "Y81": 70.4, - "Y82": 8.3, - "Y83": 424.8, - "Y83_m1": 171.0, - "Y84": 2370.0, - "Y84_m1": 4.6, - "Y85": 9648.0, - "Y85_m1": 17496.0, - "Y86": 53064.0, - "Y86_m1": 2880.0, - "Y87": 287280.0, - "Y87_m1": 48132.0, - "Y88": 9212486.0, - "Y88_m1": 0.000301, - "Y88_m2": 0.01397, - "Y89_m1": 15.663, - "Y90": 230400.0, - "Y90_m1": 11484.0, - "Y91": 5055264.0, - "Y91_m1": 2982.6, - "Y92": 12744.0, - "Y93": 36648.0, - "Y93_m1": 0.82, - "Y94": 1122.0, - "Y95": 618.0, - "Y96": 5.34, - "Y96_m1": 9.6, - "Y97": 3.75, - "Y97_m1": 1.17, - "Y97_m2": 0.142, - "Y98": 0.548, - "Y98_m1": 2.0, - "Y99": 1.47, - "Y100": 0.735, - "Y100_m1": 0.94, - "Y101": 0.45, - "Y102": 0.36, - "Y102_m1": 0.298, - "Y103": 0.23, - "Y104": 0.18, - "Y105": 0.088, - "Y106": 0.066, - "Y107": 0.03, - "Y108": 0.048, - "Zr78": 2e-07, - "Zr79": 0.056, - "Zr80": 4.6, - "Zr81": 5.5, - "Zr82": 32.0, - "Zr83": 41.6, - "Zr84": 1554.0, - "Zr85": 471.6, - "Zr85_m1": 10.9, - "Zr86": 59400.0, - "Zr87": 6048.0, - "Zr87_m1": 14.0, - "Zr88": 7205760.0, - "Zr89": 282276.0, - "Zr89_m1": 249.66, - "Zr90_m1": 0.8092, - "Zr93": 48283100000000.0, - "Zr95": 5532365.0, - "Zr96": 6.31152e26, - "Zr97": 60296.4, - "Zr98": 30.7, - "Zr99": 2.1, - "Zr100": 7.1, - "Zr101": 2.3, - "Zr102": 2.9, - "Zr103": 1.3, - "Zr104": 1.2, - "Zr105": 0.6, - "Zr106": 0.27, - "Zr107": 0.15, - "Zr108": 0.08, - "Zr109": 0.117, - "Zr110": 0.098, - "Nb81": 0.8, - "Nb82": 0.05, - "Nb83": 4.1, - "Nb84": 9.8, - "Nb85": 20.9, - "Nb85_m1": 3.3, - "Nb86": 88.0, - "Nb87": 225.0, - "Nb87_m1": 156.0, - "Nb88": 873.0, - "Nb88_m1": 466.8, - "Nb89": 7308.0, - "Nb89_m1": 3960.0, - "Nb90": 52560.0, - "Nb90_m1": 18.81, - "Nb90_m2": 0.00619, - "Nb91": 21459200000.0, - "Nb91_m1": 5258304.0, - "Nb92": 1095050000000000.0, - "Nb92_m1": 876960.0, - "Nb93_m1": 509024100.0, - "Nb94": 640619000000.0, - "Nb94_m1": 375.78, - "Nb95": 3023222.0, - "Nb95_m1": 311904.0, - "Nb96": 84060.0, - "Nb97": 4326.0, - "Nb97_m1": 58.7, - "Nb98": 2.86, - "Nb98_m1": 3078.0, - "Nb99": 15.0, - "Nb99_m1": 150.0, - "Nb100": 1.5, - "Nb100_m1": 2.99, - "Nb101": 7.1, - "Nb102": 4.3, - "Nb102_m1": 1.3, - "Nb103": 1.5, - "Nb104": 4.9, - "Nb104_m1": 0.94, - "Nb105": 2.95, - "Nb106": 0.93, - "Nb107": 0.3, - "Nb108": 0.193, - "Nb109": 0.19, - "Nb110": 0.17, - "Nb111": 0.08, - "Nb112": 0.069, - "Nb113": 0.03, - "Mo83": 0.0195, - "Mo84": 3.8, - "Mo85": 3.2, - "Mo86": 19.6, - "Mo87": 14.02, - "Mo88": 480.0, - "Mo89": 126.6, - "Mo89_m1": 0.19, - "Mo90": 20412.0, - "Mo91": 929.4, - "Mo91_m1": 64.6, - "Mo93": 126230000000.0, - "Mo93_m1": 24660.0, - "Mo99": 237513.6, - "Mo100": 2.3037e26, - "Mo101": 876.6, - "Mo102": 678.0, - "Mo103": 67.5, - "Mo104": 60.0, - "Mo105": 35.6, - "Mo106": 8.73, - "Mo107": 3.5, - "Mo108": 1.09, - "Mo109": 0.53, - "Mo110": 0.3, - "Mo111": 0.2, - "Mo112": 0.287, - "Mo113": 0.1, - "Mo114": 0.08, - "Mo115": 0.092, - "Tc85": 0.5, - "Tc86": 0.054, - "Tc86_m1": 1.1e-06, - "Tc87": 2.2, - "Tc88": 5.8, - "Tc88_m1": 6.4, - "Tc89": 12.8, - "Tc89_m1": 12.9, - "Tc90": 8.7, - "Tc90_m1": 49.2, - "Tc91": 188.4, - "Tc91_m1": 198.0, - "Tc92": 255.0, - "Tc93": 9900.0, - "Tc93_m1": 2610.0, - "Tc94": 17580.0, - "Tc94_m1": 3120.0, - "Tc95": 72000.0, - "Tc95_m1": 5270400.0, - "Tc96": 369792.0, - "Tc96_m1": 3090.0, - "Tc97": 132857000000000.0, - "Tc97_m1": 7862400.0, - "Tc98": 132542000000000.0, - "Tc99": 6661810000000.0, - "Tc99_m1": 21624.12, - "Tc100": 15.46, - "Tc101": 852.0, - "Tc102": 5.28, - "Tc102_m1": 261.0, - "Tc103": 54.2, - "Tc104": 1098.0, - "Tc105": 456.0, - "Tc106": 35.6, - "Tc107": 21.2, - "Tc108": 5.17, - "Tc109": 0.86, - "Tc110": 0.92, - "Tc111": 0.29, - "Tc112": 0.28, - "Tc113": 0.16, - "Tc114": 0.15, - "Tc115": 0.073, - "Tc116": 0.09, - "Tc117": 0.04, - "Tc118": 0.066, - "Ru87": 1.5e-06, - "Ru88": 1.25, - "Ru89": 1.5, - "Ru90": 11.7, - "Ru91": 7.9, - "Ru91_m1": 7.6, - "Ru92": 219.0, - "Ru93": 59.7, - "Ru93_m1": 10.8, - "Ru94": 3108.0, - "Ru95": 5914.8, - "Ru97": 244512.0, - "Ru103": 3390941.0, - "Ru103_m1": 0.00169, - "Ru105": 15984.0, - "Ru106": 32123520.0, - "Ru107": 225.0, - "Ru108": 273.0, - "Ru109": 34.5, - "Ru110": 11.6, - "Ru111": 2.12, - "Ru112": 1.75, - "Ru113": 0.8, - "Ru113_m1": 0.51, - "Ru114": 0.52, - "Ru115": 0.74, - "Ru116": 0.204, - "Ru117": 0.142, - "Ru118": 0.123, - "Ru119": 0.162, - "Ru120": 0.149, - "Rh89": 1.5e-06, - "Rh90": 0.0145, - "Rh90_m1": 1.05, - "Rh91": 1.47, - "Rh92": 4.66, - "Rh93": 11.9, - "Rh94": 70.6, - "Rh94_m1": 25.8, - "Rh95": 301.2, - "Rh95_m1": 117.6, - "Rh96": 594.0, - "Rh96_m1": 90.6, - "Rh97": 1842.0, - "Rh97_m1": 2772.0, - "Rh98": 523.2, - "Rh98_m1": 216.0, - "Rh99": 1391040.0, - "Rh99_m1": 16920.0, - "Rh100": 74880.0, - "Rh100_m1": 276.0, - "Rh101": 104140100.0, - "Rh101_m1": 374976.0, - "Rh102": 17910720.0, - "Rh102_m1": 118088500.0, - "Rh103_m1": 3366.84, - "Rh104": 42.3, - "Rh104_m1": 260.4, - "Rh105": 127296.0, - "Rh105_m1": 40.0, - "Rh106": 30.07, - "Rh106_m1": 7860.0, - "Rh107": 1302.0, - "Rh108": 16.8, - "Rh108_m1": 360.0, - "Rh109": 80.0, - "Rh110": 3.2, - "Rh110_m1": 28.5, - "Rh111": 11.0, - "Rh112": 2.1, - "Rh112_m1": 6.73, - "Rh113": 2.8, - "Rh114": 1.85, - "Rh115": 0.99, - "Rh116": 0.68, - "Rh116_m1": 0.57, - "Rh117": 0.44, - "Rh118": 0.266, - "Rh119": 0.171, - "Rh120": 0.136, - "Rh121": 0.151, - "Rh122": 0.108, - "Rh123": 0.0489, - "Pd91": 1e-06, - "Pd92": 0.8, - "Pd93": 1.3, - "Pd94": 9.0, - "Pd95": 10.0, - "Pd95_m1": 13.3, - "Pd96": 122.0, - "Pd97": 186.0, - "Pd98": 1062.0, - "Pd99": 1284.0, - "Pd100": 313632.0, - "Pd101": 30492.0, - "Pd103": 1468022.0, - "Pd107": 205124000000000.0, - "Pd107_m1": 21.3, - "Pd109": 49324.32, - "Pd109_m1": 281.4, - "Pd111": 1404.0, - "Pd111_m1": 19800.0, - "Pd112": 75708.0, - "Pd113": 93.0, - "Pd113_m1": 0.3, - "Pd114": 145.2, - "Pd115": 25.0, - "Pd115_m1": 50.0, - "Pd116": 11.8, - "Pd117": 4.3, - "Pd117_m1": 0.0191, - "Pd118": 1.9, - "Pd119": 0.92, - "Pd120": 0.5, - "Pd121": 0.285, - "Pd122": 0.175, - "Pd123": 0.244, - "Pd124": 0.038, - "Pd125": 0.3987, - "Pd126": 0.2499, - "Ag93": 1.5e-06, - "Ag94": 0.035, - "Ag94_m1": 0.55, - "Ag94_m2": 0.4, - "Ag95": 2.0, - "Ag95_m1": 0.5, - "Ag95_m2": 0.016, - "Ag95_m3": 0.04, - "Ag96": 4.4, - "Ag96_m1": 6.9, - "Ag97": 25.5, - "Ag98": 47.5, - "Ag99": 124.0, - "Ag99_m1": 10.5, - "Ag100": 120.6, - "Ag100_m1": 134.4, - "Ag101": 666.0, - "Ag101_m1": 3.1, - "Ag102": 774.0, - "Ag102_m1": 462.0, - "Ag103": 3942.0, - "Ag103_m1": 5.7, - "Ag104": 4152.0, - "Ag104_m1": 2010.0, - "Ag105": 3567456.0, - "Ag105_m1": 433.8, - "Ag106": 1437.6, - "Ag106_m1": 715392.0, - "Ag107_m1": 44.3, - "Ag108": 142.92, - "Ag108_m1": 13822200000.0, - "Ag109_m1": 39.6, - "Ag110": 24.6, - "Ag110_m1": 21579260.0, - "Ag111": 643680.0, - "Ag111_m1": 64.8, - "Ag112": 11268.0, - "Ag113": 19332.0, - "Ag113_m1": 68.7, - "Ag114": 4.6, - "Ag114_m1": 0.0015, - "Ag115": 1200.0, - "Ag115_m1": 18.0, - "Ag116": 237.0, - "Ag116_m1": 20.0, - "Ag116_m2": 9.3, - "Ag117": 72.8, - "Ag117_m1": 5.34, - "Ag118": 3.76, - "Ag118_m1": 2.0, - "Ag119": 2.1, - "Ag119_m1": 6.0, - "Ag120": 1.23, - "Ag120_m1": 0.32, - "Ag121": 0.78, - "Ag122": 0.529, - "Ag122_m1": 0.2, - "Ag123": 0.3, - "Ag124": 0.172, - "Ag125": 0.166, - "Ag126": 0.107, - "Ag127": 0.109, - "Ag128": 0.058, - "Ag129": 0.046, - "Ag130": 0.05, - "Cd95": 0.005, - "Cd96": 1.0, - "Cd97": 2.8, - "Cd98": 9.2, - "Cd99": 16.0, - "Cd100": 49.1, - "Cd101": 81.6, - "Cd102": 330.0, - "Cd103": 438.0, - "Cd104": 3462.0, - "Cd105": 3330.0, - "Cd107": 23400.0, - "Cd109": 39864960.0, - "Cd111_m1": 2912.4, - "Cd113": 2.53723e23, - "Cd113_m1": 444962200.0, - "Cd115": 192456.0, - "Cd115_m1": 3849984.0, - "Cd116": 9.78286e26, - "Cd117": 8964.0, - "Cd117_m1": 12096.0, - "Cd118": 3018.0, - "Cd119": 161.4, - "Cd119_m1": 132.0, - "Cd120": 50.8, - "Cd121": 13.5, - "Cd121_m1": 8.3, - "Cd122": 5.24, - "Cd123": 2.1, - "Cd123_m1": 1.82, - "Cd124": 1.25, - "Cd125": 0.68, - "Cd125_m1": 0.48, - "Cd126": 0.515, - "Cd127": 0.37, - "Cd128": 0.28, - "Cd129": 0.27, - "Cd130": 0.162, - "Cd131": 0.068, - "Cd132": 0.097, - "In97": 0.005, - "In98": 0.0425, - "In98_m1": 1.6, - "In99": 3.05, - "In100": 5.9, - "In101": 15.1, - "In102": 23.3, - "In103": 65.0, - "In103_m1": 34.0, - "In104": 108.0, - "In104_m1": 15.7, - "In105": 304.2, - "In105_m1": 48.0, - "In106": 372.0, - "In106_m1": 312.0, - "In107": 1944.0, - "In107_m1": 50.4, - "In108": 3480.0, - "In108_m1": 2376.0, - "In109": 15001.2, - "In109_m1": 80.4, - "In109_m2": 0.209, - "In110": 17640.0, - "In110_m1": 4146.0, - "In111": 242326.1, - "In111_m1": 462.0, - "In112": 898.2, - "In112_m1": 1233.6, - "In113_m1": 5968.56, - "In114": 71.9, - "In114_m1": 4277664.0, - "In114_m2": 0.0431, - "In115": 1.39169e22, - "In115_m1": 16149.6, - "In116": 14.1, - "In116_m1": 3257.4, - "In116_m2": 2.18, - "In117": 2592.0, - "In117_m1": 6972.0, - "In118": 5.0, - "In118_m1": 267.0, - "In118_m2": 8.5, - "In119": 144.0, - "In119_m1": 1080.0, - "In120": 3.08, - "In120_m1": 46.2, - "In120_m2": 47.3, - "In121": 23.1, - "In121_m1": 232.8, - "In122": 1.5, - "In122_m1": 10.3, - "In122_m2": 10.8, - "In123": 6.17, - "In123_m1": 47.4, - "In124": 3.12, - "In124_m1": 3.7, - "In125": 2.36, - "In125_m1": 12.2, - "In126": 1.53, - "In126_m1": 1.64, - "In127": 1.09, - "In127_m1": 3.67, - "In128": 0.84, - "In128_m1": 0.72, - "In129": 0.61, - "In129_m1": 1.23, - "In130": 0.29, - "In130_m1": 0.54, - "In130_m2": 0.54, - "In131": 0.28, - "In131_m1": 0.35, - "In131_m2": 0.32, - "In132": 0.207, - "In133": 0.165, - "In133_m1": 0.18, - "In134": 0.14, - "In135": 0.092, - "Sn99": 0.005, - "Sn100": 0.86, - "Sn101": 1.7, - "Sn102": 4.5, - "Sn103": 7.0, - "Sn104": 20.8, - "Sn105": 34.0, - "Sn106": 115.0, - "Sn107": 174.0, - "Sn108": 618.0, - "Sn109": 1080.0, - "Sn110": 14796.0, - "Sn111": 2118.0, - "Sn113": 9943776.0, - "Sn113_m1": 1284.0, - "Sn117_m1": 1175040.0, - "Sn119_m1": 25315200.0, - "Sn121": 97308.0, - "Sn121_m1": 1385380000.0, - "Sn123": 11162880.0, - "Sn123_m1": 2403.6, - "Sn125": 832896.0, - "Sn125_m1": 571.2, - "Sn126": 7258250000000.0, - "Sn127": 7560.0, - "Sn127_m1": 247.8, - "Sn128": 3544.2, - "Sn128_m1": 6.5, - "Sn129": 133.8, - "Sn129_m1": 414.0, - "Sn130": 223.2, - "Sn130_m1": 102.0, - "Sn131": 56.0, - "Sn131_m1": 58.4, - "Sn132": 39.7, - "Sn133": 1.46, - "Sn134": 1.05, - "Sn135": 0.53, - "Sn136": 0.25, - "Sn137": 0.19, - "Sb103": 1.5e-06, - "Sb104": 0.46, - "Sb105": 1.22, - "Sb106": 0.6, - "Sb107": 4.0, - "Sb108": 7.4, - "Sb109": 17.0, - "Sb110": 23.0, - "Sb111": 75.0, - "Sb112": 51.4, - "Sb113": 400.2, - "Sb114": 209.4, - "Sb115": 1926.0, - "Sb116": 948.0, - "Sb116_m1": 3618.0, - "Sb117": 10080.0, - "Sb118": 216.0, - "Sb118_m1": 18000.0, - "Sb119": 137484.0, - "Sb119_m1": 0.85, - "Sb120": 953.4, - "Sb120_m1": 497664.0, - "Sb122": 235336.3, - "Sb122_m1": 251.46, - "Sb124": 5201280.0, - "Sb124_m1": 93.0, - "Sb124_m2": 1212.0, - "Sb125": 87053530.0, - "Sb126": 1067040.0, - "Sb126_m1": 1149.0, - "Sb126_m2": 11.0, - "Sb127": 332640.0, - "Sb128": 32436.0, - "Sb128_m1": 624.0, - "Sb129": 15840.0, - "Sb129_m1": 1062.0, - "Sb130": 2370.0, - "Sb130_m1": 378.0, - "Sb131": 1381.8, - "Sb132": 167.4, - "Sb132_m1": 246.0, - "Sb133": 150.0, - "Sb134": 0.78, - "Sb134_m1": 10.07, - "Sb135": 1.679, - "Sb136": 0.923, - "Sb137": 0.45, - "Sb138": 0.168, - "Sb139": 0.127, - "Te105": 6.2e-07, - "Te106": 6e-05, - "Te107": 0.0031, - "Te108": 2.1, - "Te109": 4.6, - "Te110": 18.6, - "Te111": 19.3, - "Te112": 120.0, - "Te113": 102.0, - "Te114": 912.0, - "Te115": 348.0, - "Te115_m1": 402.0, - "Te116": 8964.0, - "Te117": 3720.0, - "Te117_m1": 0.103, - "Te118": 518400.0, - "Te119": 57780.0, - "Te119_m1": 406080.0, - "Te121": 1656288.0, - "Te121_m1": 14186880.0, - "Te123_m1": 10298880.0, - "Te125_m1": 4959360.0, - "Te127": 33660.0, - "Te127_m1": 9417600.0, - "Te128": 2.77707e26, - "Te129": 4176.0, - "Te129_m1": 2903040.0, - "Te131": 1500.0, - "Te131_m1": 119700.0, - "Te132": 276825.6, - "Te133": 750.0, - "Te133_m1": 3324.0, - "Te134": 2508.0, - "Te135": 19.0, - "Te136": 17.5, - "Te137": 2.49, - "Te138": 1.4, - "Te139": 0.347, - "Te140": 0.304, - "Te141": 0.213, - "Te142": 0.2, - "I108": 0.036, - "I109": 0.000103, - "I110": 0.65, - "I111": 2.5, - "I112": 3.42, - "I113": 6.6, - "I114": 2.1, - "I114_m1": 6.2, - "I115": 78.0, - "I116": 2.91, - "I117": 133.2, - "I118": 822.0, - "I118_m1": 510.0, - "I119": 1146.0, - "I120": 4896.0, - "I120_m1": 3180.0, - "I121": 7632.0, - "I122": 217.8, - "I123": 47604.24, - "I124": 360806.4, - "I125": 5132160.0, - "I126": 1117152.0, - "I128": 1499.4, - "I129": 495454000000000.0, - "I130": 44496.0, - "I130_m1": 530.4, - "I131": 693377.3, - "I132": 8262.0, - "I132_m1": 4993.2, - "I133": 74880.0, - "I133_m1": 9.0, - "I134": 3150.0, - "I134_m1": 211.2, - "I135": 23652.0, - "I136": 83.4, - "I136_m1": 46.9, - "I137": 24.5, - "I138": 6.23, - "I139": 2.28, - "I140": 0.86, - "I141": 0.43, - "I142": 0.222, - "I143": 0.296, - "I144": 0.194, - "I145": 0.127, - "Xe110": 0.093, - "Xe111": 0.81, - "Xe112": 2.7, - "Xe113": 2.74, - "Xe114": 10.0, - "Xe115": 18.0, - "Xe116": 59.0, - "Xe117": 61.0, - "Xe118": 228.0, - "Xe119": 348.0, - "Xe120": 2400.0, - "Xe121": 2406.0, - "Xe122": 72360.0, - "Xe123": 7488.0, - "Xe125": 60840.0, - "Xe125_m1": 56.9, - "Xe127": 3144960.0, - "Xe127_m1": 69.2, - "Xe129_m1": 767232.0, - "Xe131_m1": 1022976.0, - "Xe132_m1": 0.00839, - "Xe133": 452995.2, - "Xe133_m1": 189216.0, - "Xe134_m1": 0.29, - "Xe135": 32904.0, - "Xe135_m1": 917.4, - "Xe137": 229.08, - "Xe138": 844.8, - "Xe139": 39.68, - "Xe140": 13.6, - "Xe141": 1.73, - "Xe142": 1.23, - "Xe143": 0.3, - "Xe144": 1.15, - "Xe145": 0.188, - "Xe146": 0.369, - "Xe147": 0.1, - "Cs112": 0.0005, - "Cs113": 1.67e-05, - "Cs114": 0.57, - "Cs115": 1.4, - "Cs116": 0.7, - "Cs116_m1": 3.85, - "Cs117": 8.4, - "Cs117_m1": 6.5, - "Cs118": 14.0, - "Cs118_m1": 17.0, - "Cs119": 43.0, - "Cs119_m1": 30.4, - "Cs120": 61.3, - "Cs120_m1": 57.0, - "Cs121": 155.0, - "Cs121_m1": 122.0, - "Cs122": 21.18, - "Cs122_m1": 0.36, - "Cs122_m2": 222.0, - "Cs123": 352.8, - "Cs123_m1": 1.64, - "Cs124": 30.8, - "Cs124_m1": 6.3, - "Cs125": 2802.0, - "Cs125_m1": 0.0009, - "Cs126": 98.4, - "Cs127": 22500.0, - "Cs128": 217.2, - "Cs129": 115416.0, - "Cs130": 1752.6, - "Cs130_m1": 207.6, - "Cs131": 837129.6, - "Cs132": 559872.0, - "Cs134": 65172760.0, - "Cs134_m1": 10483.2, - "Cs135": 72582500000000.0, - "Cs135_m1": 3180.0, - "Cs136": 1137024.0, - "Cs136_m1": 19.0, - "Cs137": 949252600.0, - "Cs138": 2004.6, - "Cs138_m1": 174.6, - "Cs139": 556.2, - "Cs140": 63.7, - "Cs141": 24.84, - "Cs142": 1.684, - "Cs143": 1.791, - "Cs144": 0.994, - "Cs144_m1": 1.0, - "Cs145": 0.587, - "Cs146": 0.321, - "Cs147": 0.23, - "Cs148": 0.146, - "Cs149": 0.05, - "Cs150": 0.05, - "Cs151": 0.05, - "Ba114": 0.43, - "Ba115": 0.45, - "Ba116": 1.3, - "Ba117": 1.75, - "Ba118": 5.5, - "Ba119": 5.4, - "Ba120": 24.0, - "Ba121": 29.7, - "Ba122": 117.0, - "Ba123": 162.0, - "Ba124": 660.0, - "Ba125": 210.0, - "Ba126": 6000.0, - "Ba127": 762.0, - "Ba127_m1": 1.9, - "Ba128": 209952.0, - "Ba129": 8028.0, - "Ba129_m1": 7776.0, - "Ba130_m1": 0.0094, - "Ba131": 993600.0, - "Ba131_m1": 876.0, - "Ba133": 331862400.0, - "Ba133_m1": 140040.0, - "Ba135_m1": 103320.0, - "Ba136_m1": 0.3084, - "Ba137_m1": 153.12, - "Ba139": 4983.6, - "Ba140": 1101833.0, - "Ba141": 1096.2, - "Ba142": 636.0, - "Ba143": 14.5, - "Ba144": 11.5, - "Ba145": 4.31, - "Ba146": 2.22, - "Ba147": 0.894, - "Ba148": 0.612, - "Ba149": 0.344, - "Ba150": 0.3, - "Ba151": 0.259, - "Ba152": 0.228, - "Ba153": 0.158, - "La117": 0.0235, - "La117_m1": 0.01, - "La118": 1.0, - "La119": 2.0, - "La120": 2.8, - "La121": 5.3, - "La122": 8.6, - "La123": 17.0, - "La124": 29.21, - "La124_m1": 21.0, - "La125": 64.8, - "La125_m1": 0.4, - "La126": 54.0, - "La126_m1": 50.0, - "La127": 306.0, - "La127_m1": 222.0, - "La128": 310.8, - "La128_m1": 60.0, - "La129": 696.0, - "La129_m1": 0.56, - "La130": 522.0, - "La131": 3540.0, - "La132": 17280.0, - "La132_m1": 1458.0, - "La133": 14083.2, - "La134": 387.0, - "La135": 70200.0, - "La136": 592.2, - "La136_m1": 0.114, - "La137": 1893460000000.0, - "La138": 3.21888e18, - "La140": 145026.7, - "La141": 14112.0, - "La142": 5466.0, - "La143": 852.0, - "La144": 40.8, - "La145": 24.8, - "La146": 6.27, - "La146_m1": 10.0, - "La147": 4.06, - "La148": 1.26, - "La149": 1.05, - "La150": 0.86, - "La151": 0.778, - "La152": 0.451, - "La153": 0.342, - "La154": 0.228, - "La155": 0.184, - "Ce119": 0.2, - "Ce120": 0.25, - "Ce121": 1.1, - "Ce122": 2.73, - "Ce123": 3.8, - "Ce124": 6.0, - "Ce125": 10.2, - "Ce126": 51.0, - "Ce127": 31.0, - "Ce127_m1": 28.6, - "Ce128": 235.8, - "Ce129": 210.0, - "Ce130": 1374.0, - "Ce131": 618.0, - "Ce131_m1": 324.0, - "Ce132": 12636.0, - "Ce132_m1": 0.0094, - "Ce133": 5820.0, - "Ce133_m1": 17640.0, - "Ce134": 273024.0, - "Ce135": 63720.0, - "Ce135_m1": 20.0, - "Ce137": 32400.0, - "Ce137_m1": 123840.0, - "Ce138_m1": 0.00865, - "Ce139": 11892180.0, - "Ce139_m1": 54.8, - "Ce141": 2808691.0, - "Ce143": 118940.4, - "Ce144": 24616220.0, - "Ce145": 180.6, - "Ce146": 811.2, - "Ce147": 56.4, - "Ce148": 56.0, - "Ce149": 5.3, - "Ce150": 4.0, - "Ce151": 1.76, - "Ce152": 1.4, - "Ce153": 0.979, - "Ce154": 0.775, - "Ce155": 0.471, - "Ce156": 0.369, - "Ce157": 0.2428, - "Pr121": 1.4, - "Pr122": 0.5, - "Pr123": 0.8, - "Pr124": 1.2, - "Pr125": 3.3, - "Pr126": 3.14, - "Pr127": 4.2, - "Pr128": 2.85, - "Pr129": 32.0, - "Pr130": 40.0, - "Pr131": 90.6, - "Pr131_m1": 5.73, - "Pr132": 96.0, - "Pr133": 390.0, - "Pr134": 1020.0, - "Pr134_m1": 660.0, - "Pr135": 1440.0, - "Pr136": 786.0, - "Pr137": 4608.0, - "Pr138": 87.0, - "Pr138_m1": 7632.0, - "Pr139": 15876.0, - "Pr140": 203.4, - "Pr142": 68832.0, - "Pr142_m1": 876.0, - "Pr143": 1172448.0, - "Pr144": 1036.8, - "Pr144_m1": 432.0, - "Pr145": 21542.4, - "Pr146": 1449.0, - "Pr147": 804.0, - "Pr148": 137.4, - "Pr148_m1": 120.6, - "Pr149": 135.6, - "Pr150": 6.19, - "Pr151": 18.9, - "Pr152": 3.63, - "Pr153": 4.28, - "Pr154": 2.3, - "Pr155": 0.852, - "Pr156": 0.733, - "Pr157": 0.598, - "Pr158": 0.1342, - "Pr159": 0.1055, - "Nd124": 0.5, - "Nd125": 0.6, - "Nd126": 2e-07, - "Nd127": 1.8, - "Nd128": 5.0, - "Nd129": 4.9, - "Nd130": 21.0, - "Nd131": 26.0, - "Nd132": 94.0, - "Nd133": 70.0, - "Nd133_m1": 70.0, - "Nd134": 510.0, - "Nd135": 744.0, - "Nd135_m1": 330.0, - "Nd136": 3039.0, - "Nd137": 2310.0, - "Nd137_m1": 1.6, - "Nd138": 18144.0, - "Nd139": 1782.0, - "Nd139_m1": 19800.0, - "Nd140": 291168.0, - "Nd141": 8964.0, - "Nd141_m1": 62.0, - "Nd144": 7.22669e22, - "Nd147": 948672.0, - "Nd149": 6220.8, - "Nd150": 2.49305e26, - "Nd151": 746.4, - "Nd152": 684.0, - "Nd153": 31.6, - "Nd154": 25.9, - "Nd155": 8.9, - "Nd156": 5.49, - "Nd157": 1.906, - "Nd158": 1.331, - "Nd159": 0.773, - "Nd160": 0.5883, - "Nd161": 0.4884, - "Pm126": 0.5, - "Pm127": 1.0, - "Pm128": 1.0, - "Pm129": 2.4, - "Pm130": 2.6, - "Pm131": 6.3, - "Pm132": 6.2, - "Pm133": 15.0, - "Pm133_m1": 8.8, - "Pm134": 5.0, - "Pm134_m1": 22.0, - "Pm135": 49.0, - "Pm135_m1": 45.0, - "Pm136": 47.0, - "Pm136_m1": 107.0, - "Pm137": 144.0, - "Pm138": 10.0, - "Pm138_m1": 194.4, - "Pm139": 249.0, - "Pm139_m1": 0.18, - "Pm140": 357.0, - "Pm140_m1": 357.0, - "Pm141": 1254.0, - "Pm142": 40.5, - "Pm142_m1": 0.002, - "Pm143": 22896000.0, - "Pm144": 31363200.0, - "Pm145": 558569500.0, - "Pm146": 174513500.0, - "Pm147": 82788210.0, - "Pm148": 463795.2, - "Pm148_m1": 3567456.0, - "Pm149": 191088.0, - "Pm150": 9648.0, - "Pm151": 102240.0, - "Pm152": 247.2, - "Pm152_m1": 451.2, - "Pm152_m2": 828.0, - "Pm153": 315.0, - "Pm154": 103.8, - "Pm154_m1": 160.8, - "Pm155": 41.5, - "Pm156": 26.7, - "Pm157": 10.56, - "Pm158": 4.8, - "Pm159": 1.47, - "Pm160": 1.561, - "Pm161": 1.065, - "Pm162": 0.2679, - "Pm163": 0.2, - "Sm128": 0.5, - "Sm129": 0.55, - "Sm130": 1.0, - "Sm131": 1.2, - "Sm132": 4.0, - "Sm133": 3.7, - "Sm134": 9.5, - "Sm135": 10.3, - "Sm136": 47.0, - "Sm137": 45.0, - "Sm138": 186.0, - "Sm139": 154.2, - "Sm139_m1": 10.7, - "Sm140": 889.2, - "Sm141": 612.0, - "Sm141_m1": 1356.0, - "Sm142": 4349.4, - "Sm143": 525.0, - "Sm143_m1": 66.0, - "Sm143_m2": 0.03, - "Sm145": 29376000.0, - "Sm146": 3250430000000000.0, - "Sm147": 3.34511e18, - "Sm148": 2.20903e23, - "Sm151": 2840184000.0, - "Sm153": 167400.0, - "Sm153_m1": 0.0106, - "Sm155": 1338.0, - "Sm156": 33840.0, - "Sm157": 482.0, - "Sm158": 318.0, - "Sm159": 11.37, - "Sm160": 9.6, - "Sm161": 4.8, - "Sm162": 2.4, - "Sm163": 1.748, - "Sm164": 1.226, - "Sm165": 0.764, - "Eu130": 0.001, - "Eu131": 0.0178, - "Eu132": 0.1, - "Eu133": 1.0, - "Eu134": 0.5, - "Eu135": 1.5, - "Eu136": 3.8, - "Eu136_m1": 3.3, - "Eu136_m2": 3.8, - "Eu137": 11.0, - "Eu138": 12.1, - "Eu139": 17.9, - "Eu140": 1.51, - "Eu140_m1": 0.125, - "Eu141": 40.7, - "Eu141_m1": 2.7, - "Eu142": 2.34, - "Eu142_m1": 73.38, - "Eu143": 155.4, - "Eu144": 10.2, - "Eu145": 512352.0, - "Eu146": 396576.0, - "Eu147": 2082240.0, - "Eu148": 4708800.0, - "Eu149": 8043840.0, - "Eu150": 1164480000.0, - "Eu150_m1": 46080.0, - "Eu152": 427195200.0, - "Eu152_m1": 33521.76, - "Eu152_m2": 5760.0, - "Eu154": 271426900.0, - "Eu154_m1": 2760.0, - "Eu155": 149993300.0, - "Eu156": 1312416.0, - "Eu157": 54648.0, - "Eu158": 2754.0, - "Eu159": 1086.0, - "Eu160": 38.0, - "Eu161": 26.0, - "Eu162": 10.6, - "Eu163": 7.7, - "Eu164": 2.844, - "Eu165": 2.3, - "Eu166": 0.4, - "Eu167": 0.2, - "Gd134": 0.4, - "Gd135": 1.1, - "Gd136": 2e-05, - "Gd137": 2.2, - "Gd138": 4.7, - "Gd139": 5.8, - "Gd139_m1": 4.8, - "Gd140": 15.8, - "Gd141": 14.0, - "Gd141_m1": 24.5, - "Gd142": 70.2, - "Gd143": 39.0, - "Gd143_m1": 110.0, - "Gd144": 268.2, - "Gd145": 1380.0, - "Gd145_m1": 85.0, - "Gd146": 4170528.0, - "Gd147": 137016.0, - "Gd148": 2354197000.0, - "Gd149": 801792.0, - "Gd150": 56488100000000.0, - "Gd151": 10713600.0, - "Gd152": 3.40822e21, - "Gd153": 20770560.0, - "Gd155_m1": 0.03197, - "Gd159": 66524.4, - "Gd161": 219.6, - "Gd162": 504.0, - "Gd163": 68.0, - "Gd164": 45.0, - "Gd165": 10.3, - "Gd166": 4.8, - "Gd167": 3.0, - "Gd168": 0.3, - "Gd169": 1.0, - "Tb135": 0.995, - "Tb136": 0.2, - "Tb137": 0.6, - "Tb138": 2e-07, - "Tb139": 1.6, - "Tb140": 2.4, - "Tb141": 3.5, - "Tb141_m1": 7.9, - "Tb142": 0.597, - "Tb142_m1": 0.303, - "Tb143": 12.0, - "Tb143_m1": 21.0, - "Tb144": 1.0, - "Tb144_m1": 4.25, - "Tb145": 30.9, - "Tb145_m1": 30.9, - "Tb146": 8.0, - "Tb146_m1": 23.0, - "Tb146_m2": 0.00118, - "Tb147": 5904.0, - "Tb147_m1": 109.8, - "Tb148": 3600.0, - "Tb148_m1": 132.0, - "Tb149": 14824.8, - "Tb149_m1": 249.6, - "Tb150": 12528.0, - "Tb150_m1": 348.0, - "Tb151": 63392.4, - "Tb151_m1": 25.0, - "Tb152": 63000.0, - "Tb152_m1": 252.0, - "Tb153": 202176.0, - "Tb154": 77400.0, - "Tb154_m1": 33840.0, - "Tb154_m2": 81720.0, - "Tb155": 459648.0, - "Tb156": 462240.0, - "Tb156_m1": 87840.0, - "Tb156_m2": 19080.0, - "Tb157": 2240590000.0, - "Tb158": 5680368000.0, - "Tb158_m1": 10.7, - "Tb160": 6246720.0, - "Tb161": 596678.4, - "Tb162": 456.0, - "Tb163": 1170.0, - "Tb164": 180.0, - "Tb165": 126.6, - "Tb166": 25.1, - "Tb167": 19.4, - "Tb168": 8.2, - "Tb169": 2.0, - "Tb170": 3.0, - "Tb171": 0.5, - "Dy138": 0.2, - "Dy139": 0.6, - "Dy140": 0.84, - "Dy141": 0.9, - "Dy142": 2.3, - "Dy143": 3.2, - "Dy143_m1": 3.0, - "Dy144": 9.1, - "Dy145": 6.0, - "Dy145_m1": 14.1, - "Dy146": 29.0, - "Dy146_m1": 0.15, - "Dy147": 40.0, - "Dy147_m1": 55.7, - "Dy148": 198.0, - "Dy149": 252.0, - "Dy149_m1": 0.49, - "Dy150": 430.2, - "Dy151": 1074.0, - "Dy152": 8568.0, - "Dy153": 23040.0, - "Dy154": 94672800000000.0, - "Dy155": 35640.0, - "Dy157": 29304.0, - "Dy157_m1": 0.0216, - "Dy159": 12476160.0, - "Dy165": 8402.4, - "Dy165_m1": 75.42, - "Dy166": 293760.0, - "Dy167": 372.0, - "Dy168": 522.0, - "Dy169": 39.0, - "Dy170": 30.0, - "Dy171": 6.0, - "Dy172": 3.0, - "Dy173": 2.0, - "Ho140": 0.006, - "Ho141": 0.0041, - "Ho142": 0.4, - "Ho143": 2e-07, - "Ho144": 0.7, - "Ho145": 2.4, - "Ho146": 3.6, - "Ho147": 5.8, - "Ho148": 2.2, - "Ho148_m1": 9.59, - "Ho148_m2": 0.00236, - "Ho149": 21.1, - "Ho149_m1": 56.0, - "Ho150": 72.0, - "Ho150_m1": 23.3, - "Ho151": 35.2, - "Ho151_m1": 47.2, - "Ho152": 161.8, - "Ho152_m1": 50.0, - "Ho153": 120.6, - "Ho153_m1": 558.0, - "Ho154": 705.6, - "Ho154_m1": 186.0, - "Ho155": 2880.0, - "Ho155_m1": 0.00088, - "Ho156": 3360.0, - "Ho156_m1": 9.5, - "Ho156_m2": 468.0, - "Ho157": 756.0, - "Ho158": 678.0, - "Ho158_m1": 1680.0, - "Ho158_m2": 1278.0, - "Ho159": 1983.0, - "Ho159_m1": 8.3, - "Ho160": 1536.0, - "Ho160_m1": 18072.0, - "Ho160_m2": 3.0, - "Ho161": 8928.0, - "Ho161_m1": 6.76, - "Ho162": 900.0, - "Ho162_m1": 4020.0, - "Ho163": 144218000000.0, - "Ho163_m1": 1.09, - "Ho164": 1740.0, - "Ho164_m1": 2250.0, - "Ho166": 96480.0, - "Ho166_m1": 37869100000.0, - "Ho167": 11160.0, - "Ho168": 179.4, - "Ho168_m1": 132.0, - "Ho169": 283.2, - "Ho170": 165.6, - "Ho170_m1": 43.0, - "Ho171": 53.0, - "Ho172": 25.0, - "Ho173": 10.0, - "Ho174": 8.0, - "Ho175": 5.0, - "Er143": 0.2, - "Er144": 2e-07, - "Er146": 1.7, - "Er147": 2.5, - "Er147_m1": 2.5, - "Er148": 4.6, - "Er149": 4.0, - "Er149_m1": 8.9, - "Er150": 18.5, - "Er151": 23.5, - "Er151_m1": 0.58, - "Er152": 10.3, - "Er153": 37.1, - "Er154": 223.8, - "Er155": 318.0, - "Er156": 1170.0, - "Er157": 1119.0, - "Er157_m1": 0.076, - "Er158": 8244.0, - "Er159": 2160.0, - "Er160": 102888.0, - "Er161": 11556.0, - "Er163": 4500.0, - "Er165": 37296.0, - "Er167_m1": 2.269, - "Er169": 811468.8, - "Er171": 27057.6, - "Er172": 177480.0, - "Er173": 84.0, - "Er174": 192.0, - "Er175": 72.0, - "Er176": 20.0, - "Er177": 3.0, - "Tm145": 3.1e-06, - "Tm146": 0.08, - "Tm146_m1": 0.2, - "Tm147": 0.58, - "Tm148": 0.7, - "Tm149": 0.9, - "Tm150": 2.2, - "Tm150_m1": 0.0052, - "Tm151": 4.17, - "Tm151_m1": 4.51e-07, - "Tm152": 8.0, - "Tm152_m1": 5.2, - "Tm153": 1.48, - "Tm153_m1": 2.5, - "Tm154": 8.1, - "Tm154_m1": 3.3, - "Tm155": 21.6, - "Tm155_m1": 45.0, - "Tm156": 83.8, - "Tm157": 217.8, - "Tm158": 238.8, - "Tm159": 547.8, - "Tm160": 564.0, - "Tm160_m1": 74.5, - "Tm161": 1812.0, - "Tm162": 1302.0, - "Tm162_m1": 24.3, - "Tm163": 6516.0, - "Tm164": 120.0, - "Tm164_m1": 306.0, - "Tm165": 108216.0, - "Tm166": 27720.0, - "Tm166_m1": 0.34, - "Tm167": 799200.0, - "Tm168": 8043840.0, - "Tm170": 11111040.0, - "Tm171": 60590590.0, - "Tm172": 228960.0, - "Tm173": 29664.0, - "Tm174": 324.0, - "Tm175": 912.0, - "Tm176": 114.0, - "Tm177": 90.0, - "Tm178": 30.0, - "Tm179": 20.0, - "Yb148": 0.25, - "Yb149": 0.7, - "Yb150": 2e-07, - "Yb151": 1.6, - "Yb151_m1": 1.6, - "Yb152": 3.04, - "Yb153": 4.2, - "Yb154": 0.409, - "Yb155": 1.793, - "Yb156": 26.1, - "Yb157": 38.6, - "Yb158": 89.4, - "Yb159": 100.2, - "Yb160": 288.0, - "Yb161": 252.0, - "Yb162": 1132.2, - "Yb163": 663.0, - "Yb164": 4548.0, - "Yb165": 594.0, - "Yb166": 204120.0, - "Yb167": 1050.0, - "Yb169": 2766355.0, - "Yb169_m1": 46.0, - "Yb171_m1": 0.00525, - "Yb175": 361584.0, - "Yb175_m1": 0.0682, - "Yb176_m1": 11.4, - "Yb177": 6879.6, - "Yb177_m1": 6.41, - "Yb178": 4440.0, - "Yb179": 480.0, - "Yb180": 144.0, - "Yb181": 60.0, - "Lu150": 0.043, - "Lu151": 0.0806, - "Lu152": 0.7, - "Lu153": 0.9, - "Lu153_m1": 1.0, - "Lu154": 2.0, - "Lu154_m1": 1.12, - "Lu155": 0.068, - "Lu155_m1": 0.138, - "Lu155_m2": 0.00269, - "Lu156": 0.494, - "Lu156_m1": 0.198, - "Lu157": 6.8, - "Lu157_m1": 4.79, - "Lu158": 10.6, - "Lu159": 12.1, - "Lu160": 36.1, - "Lu160_m1": 40.0, - "Lu161": 77.0, - "Lu161_m1": 0.0073, - "Lu162": 82.2, - "Lu162_m1": 90.0, - "Lu162_m2": 114.0, - "Lu163": 238.2, - "Lu164": 188.4, - "Lu165": 644.4, - "Lu166": 159.0, - "Lu166_m1": 84.6, - "Lu166_m2": 127.2, - "Lu167": 3090.0, - "Lu167_m1": 60.0, - "Lu168": 330.0, - "Lu168_m1": 402.0, - "Lu169": 122616.0, - "Lu169_m1": 160.0, - "Lu170": 173836.8, - "Lu170_m1": 0.67, - "Lu171": 711936.0, - "Lu171_m1": 79.0, - "Lu172": 578880.0, - "Lu172_m1": 222.0, - "Lu173": 43233910.0, - "Lu174": 104455700.0, - "Lu174_m1": 12268800.0, - "Lu176": 1.18657e18, - "Lu176_m1": 13086.0, - "Lu177": 574300.8, - "Lu177_m1": 13862020.0, - "Lu177_m2": 390.0, - "Lu178": 1704.0, - "Lu178_m1": 1386.0, - "Lu179": 16524.0, - "Lu179_m1": 0.0031, - "Lu180": 342.0, - "Lu180_m1": 0.001, - "Lu181": 210.0, - "Lu182": 120.0, - "Lu183": 58.0, - "Lu184": 20.0, - "Hf153": 6e-06, - "Hf154": 2.0, - "Hf155": 0.89, - "Hf156": 0.023, - "Hf157": 0.11, - "Hf158": 2.85, - "Hf159": 5.6, - "Hf160": 13.6, - "Hf161": 18.2, - "Hf162": 39.4, - "Hf163": 40.0, - "Hf164": 111.0, - "Hf165": 76.0, - "Hf166": 406.2, - "Hf167": 123.0, - "Hf168": 1557.0, - "Hf169": 194.4, - "Hf170": 57636.0, - "Hf171": 43560.0, - "Hf171_m1": 29.5, - "Hf172": 59012710.0, - "Hf173": 84960.0, - "Hf174": 6.31152e22, - "Hf175": 6048000.0, - "Hf177_m1": 1.09, - "Hf177_m2": 3084.0, - "Hf178_m1": 4.0, - "Hf178_m2": 978285600.0, - "Hf179_m1": 18.67, - "Hf179_m2": 2164320.0, - "Hf180_m1": 19800.0, - "Hf181": 3662496.0, - "Hf182": 280863000000000.0, - "Hf182_m1": 3690.0, - "Hf183": 3841.2, - "Hf184": 14832.0, - "Hf184_m1": 48.0, - "Hf185": 210.0, - "Hf186": 156.0, - "Hf187": 30.0, - "Hf188": 20.0, - "Ta155": 0.0031, - "Ta156": 0.144, - "Ta156_m1": 0.36, - "Ta157": 0.0101, - "Ta157_m1": 0.0043, - "Ta157_m2": 0.0017, - "Ta158": 0.055, - "Ta158_m1": 0.0367, - "Ta159": 0.83, - "Ta159_m1": 0.515, - "Ta160": 1.55, - "Ta160_m1": 1.7, - "Ta161": 2.89, - "Ta162": 3.57, - "Ta163": 10.6, - "Ta164": 14.2, - "Ta165": 31.0, - "Ta166": 34.4, - "Ta167": 80.0, - "Ta168": 120.0, - "Ta169": 294.0, - "Ta170": 405.6, - "Ta171": 1398.0, - "Ta172": 2208.0, - "Ta173": 11304.0, - "Ta174": 4104.0, - "Ta175": 37800.0, - "Ta176": 29124.0, - "Ta176_m1": 0.0011, - "Ta176_m2": 0.00097, - "Ta177": 203616.0, - "Ta178": 558.6, - "Ta178_m1": 8496.0, - "Ta178_m2": 0.058, - "Ta179": 57434830.0, - "Ta179_m1": 0.009, - "Ta179_m2": 0.0541, - "Ta180": 29354.4, - "Ta182": 9913536.0, - "Ta182_m1": 0.283, - "Ta182_m2": 950.4, - "Ta183": 440640.0, - "Ta184": 31320.0, - "Ta185": 2964.0, - "Ta185_m1": 0.002, - "Ta186": 630.0, - "Ta187": 120.0, - "Ta188": 20.0, - "Ta189": 3.0, - "Ta190": 0.3, - "W158": 0.00125, - "W159": 0.0073, - "W160": 0.091, - "W161": 0.409, - "W162": 1.36, - "W163": 2.8, - "W164": 6.3, - "W165": 5.1, - "W166": 19.2, - "W167": 19.9, - "W168": 53.0, - "W169": 74.0, - "W170": 145.2, - "W171": 142.8, - "W172": 396.0, - "W173": 456.0, - "W174": 1992.0, - "W175": 2112.0, - "W176": 9000.0, - "W177": 7920.0, - "W178": 1866240.0, - "W179": 2223.0, - "W179_m1": 384.0, - "W180": 5.68037e25, - "W180_m1": 0.00547, - "W181": 10471680.0, - "W183_m1": 5.2, - "W185": 6488640.0, - "W185_m1": 100.2, - "W186": 5.36e27, - "W186_m1": 0.003, - "W187": 86400.0, - "W188": 6028992.0, - "W189": 642.0, - "W190": 1800.0, - "W190_m1": 0.0031, - "W191": 20.0, - "W192": 10.0, - "Re160": 0.00085, - "Re161": 0.00037, - "Re161_m1": 0.0156, - "Re162": 0.107, - "Re162_m1": 0.077, - "Re163": 0.39, - "Re163_m1": 0.214, - "Re164": 0.53, - "Re164_m1": 0.87, - "Re165": 1.0, - "Re165_m1": 2.1, - "Re166": 2.25, - "Re167": 5.9, - "Re167_m1": 3.4, - "Re168": 4.4, - "Re169": 8.1, - "Re169_m1": 15.1, - "Re170": 9.2, - "Re171": 15.2, - "Re172": 55.0, - "Re172_m1": 15.0, - "Re173": 118.8, - "Re174": 144.0, - "Re175": 353.4, - "Re176": 318.0, - "Re177": 840.0, - "Re178": 792.0, - "Re179": 1170.0, - "Re180": 146.4, - "Re181": 71640.0, - "Re182": 230400.0, - "Re182_m1": 45720.0, - "Re183": 6048000.0, - "Re183_m1": 0.00104, - "Re184": 3058560.0, - "Re184_m1": 14601600.0, - "Re186": 321261.1, - "Re186_m1": 6311520000000.0, - "Re187": 1.36644e18, - "Re188": 61214.4, - "Re188_m1": 1115.4, - "Re189": 87480.0, - "Re190": 186.0, - "Re190_m1": 11520.0, - "Re191": 588.0, - "Re192": 16.0, - "Re193": 51.9, - "Re194": 1.0, - "Os162": 0.00205, - "Os163": 0.0055, - "Os164": 0.021, - "Os165": 0.071, - "Os166": 0.199, - "Os167": 0.81, - "Os168": 2.1, - "Os169": 3.43, - "Os170": 7.37, - "Os171": 8.3, - "Os172": 19.2, - "Os173": 22.4, - "Os174": 44.0, - "Os175": 84.0, - "Os176": 216.0, - "Os177": 180.0, - "Os178": 300.0, - "Os179": 390.0, - "Os180": 1290.0, - "Os181": 6300.0, - "Os181_m1": 162.0, - "Os182": 78624.0, - "Os183": 46800.0, - "Os183_m1": 35640.0, - "Os185": 8087040.0, - "Os186": 6.31152e22, - "Os189_m1": 20916.0, - "Os190_m1": 594.0, - "Os191": 1330560.0, - "Os191_m1": 47160.0, - "Os192_m1": 5.9, - "Os193": 108396.0, - "Os194": 189345600.0, - "Os195": 540.0, - "Os196": 2094.0, - "Ir164": 0.14, - "Ir164_m1": 9.5e-05, - "Ir165": 1e-06, - "Ir166": 0.0105, - "Ir166_m1": 0.0151, - "Ir167": 0.0352, - "Ir167_m1": 0.0257, - "Ir168": 0.232, - "Ir168_m1": 0.16, - "Ir169": 0.64, - "Ir169_m1": 0.281, - "Ir170": 0.9, - "Ir170_m1": 0.811, - "Ir171": 3.5, - "Ir171_m1": 1.4, - "Ir172": 4.4, - "Ir172_m1": 2.0, - "Ir173": 9.0, - "Ir173_m1": 2.2, - "Ir174": 7.9, - "Ir174_m1": 4.9, - "Ir175": 9.0, - "Ir176": 8.7, - "Ir177": 30.0, - "Ir178": 12.0, - "Ir179": 79.0, - "Ir180": 90.0, - "Ir181": 294.0, - "Ir182": 900.0, - "Ir183": 3480.0, - "Ir184": 11124.0, - "Ir185": 51840.0, - "Ir186": 59904.0, - "Ir186_m1": 6840.0, - "Ir187": 37800.0, - "Ir187_m1": 0.0303, - "Ir188": 149400.0, - "Ir188_m1": 0.0042, - "Ir189": 1140480.0, - "Ir189_m1": 0.0133, - "Ir189_m2": 0.0037, - "Ir190": 1017792.0, - "Ir190_m1": 4032.0, - "Ir190_m2": 11113.2, - "Ir191_m1": 4.899, - "Ir191_m2": 5.5, - "Ir192": 6378653.0, - "Ir192_m1": 87.0, - "Ir192_m2": 7605382000.0, - "Ir193_m1": 909792.0, - "Ir194": 69408.0, - "Ir194_m1": 0.03185, - "Ir194_m2": 14774400.0, - "Ir195": 9000.0, - "Ir195_m1": 13680.0, - "Ir196": 52.0, - "Ir196_m1": 5040.0, - "Ir197": 348.0, - "Ir197_m1": 534.0, - "Ir198": 8.0, - "Ir199": 6.5, - "Pt166": 0.0003, - "Pt167": 0.00078, - "Pt168": 0.002, - "Pt169": 0.007, - "Pt170": 0.014, - "Pt171": 0.051, - "Pt172": 0.096, - "Pt173": 0.382, - "Pt174": 0.889, - "Pt175": 2.53, - "Pt176": 6.33, - "Pt177": 10.6, - "Pt178": 21.1, - "Pt179": 21.2, - "Pt180": 56.0, - "Pt181": 52.0, - "Pt182": 180.0, - "Pt183": 390.0, - "Pt183_m1": 43.0, - "Pt184": 1038.0, - "Pt184_m1": 0.00101, - "Pt185": 4254.0, - "Pt185_m1": 1980.0, - "Pt186": 7488.0, - "Pt187": 8460.0, - "Pt188": 881280.0, - "Pt189": 39132.0, - "Pt190": 2.05124e19, - "Pt191": 242092.8, - "Pt193": 1577880000.0, - "Pt193_m1": 374112.0, - "Pt195_m1": 346464.0, - "Pt197": 71609.4, - "Pt197_m1": 5724.6, - "Pt199": 1848.0, - "Pt199_m1": 13.6, - "Pt200": 45360.0, - "Pt201": 150.0, - "Pt202": 158400.0, - "Au169": 0.00015, - "Au170": 0.000291, - "Au170_m1": 0.00062, - "Au171": 1.9e-05, - "Au171_m1": 0.00102, - "Au172": 0.0047, - "Au173": 0.025, - "Au173_m1": 0.014, - "Au174": 0.139, - "Au174_m1": 0.1629, - "Au175": 0.1, - "Au175_m1": 0.156, - "Au176": 1.05, - "Au176_m1": 1.36, - "Au177": 1.462, - "Au177_m1": 1.18, - "Au178": 2.6, - "Au179": 3.3, - "Au180": 8.1, - "Au181": 13.7, - "Au182": 15.6, - "Au183": 42.8, - "Au184": 20.6, - "Au184_m1": 47.6, - "Au185": 255.0, - "Au186": 642.0, - "Au187": 504.0, - "Au187_m1": 2.3, - "Au188": 530.4, - "Au189": 1722.0, - "Au189_m1": 275.4, - "Au190": 2568.0, - "Au190_m1": 0.125, - "Au191": 11448.0, - "Au191_m1": 0.92, - "Au192": 17784.0, - "Au192_m1": 0.029, - "Au192_m2": 0.16, - "Au193": 63540.0, - "Au193_m1": 3.9, - "Au194": 136872.0, - "Au194_m1": 0.6, - "Au194_m2": 0.42, - "Au195": 16078870.0, - "Au195_m1": 30.5, - "Au196": 532820.2, - "Au196_m1": 8.1, - "Au196_m2": 34560.0, - "Au197_m1": 7.73, - "Au198": 232822.1, - "Au198_m1": 196300.8, - "Au199": 271209.6, - "Au200": 2904.0, - "Au200_m1": 67320.0, - "Au201": 1560.0, - "Au202": 28.4, - "Au203": 60.0, - "Au204": 39.8, - "Au205": 31.0, - "Hg171": 6.9e-05, - "Hg172": 0.000365, - "Hg173": 0.0007, - "Hg174": 0.0019, - "Hg175": 0.0107, - "Hg176": 0.0203, - "Hg177": 0.1273, - "Hg178": 0.269, - "Hg179": 1.08, - "Hg180": 2.58, - "Hg181": 3.6, - "Hg182": 10.83, - "Hg183": 9.4, - "Hg184": 30.9, - "Hg185": 49.1, - "Hg185_m1": 21.6, - "Hg186": 82.8, - "Hg187": 144.0, - "Hg187_m1": 114.0, - "Hg188": 195.0, - "Hg189": 456.0, - "Hg189_m1": 516.0, - "Hg190": 1200.0, - "Hg191": 2940.0, - "Hg191_m1": 3048.0, - "Hg192": 17460.0, - "Hg193": 13680.0, - "Hg193_m1": 42480.0, - "Hg194": 14011600000.0, - "Hg195": 37908.0, - "Hg195_m1": 149760.0, - "Hg197": 230904.0, - "Hg197_m1": 85680.0, - "Hg199_m1": 2560.2, - "Hg203": 4025722.0, - "Hg205": 308.4, - "Hg205_m1": 0.00109, - "Hg206": 499.2, - "Hg207": 174.0, - "Hg208": 2490.0, - "Hg209": 36.5, - "Hg210": 146.0, - "Tl176": 0.006, - "Tl177": 0.018, - "Tl178": 0.06, - "Tl179": 0.23, - "Tl179_m1": 0.0017, - "Tl180": 1.09, - "Tl181": 3.2, - "Tl181_m1": 0.0014, - "Tl182": 3.1, - "Tl183": 6.9, - "Tl183_m1": 0.0533, - "Tl184": 11.0, - "Tl185": 19.5, - "Tl185_m1": 1.93, - "Tl186": 27.5, - "Tl186_m1": 2.9, - "Tl187": 51.0, - "Tl187_m1": 15.6, - "Tl188": 71.0, - "Tl188_m1": 71.0, - "Tl188_m2": 0.041, - "Tl189": 138.0, - "Tl189_m1": 84.0, - "Tl190": 222.0, - "Tl190_m1": 156.0, - "Tl191": 1200.0, - "Tl191_m1": 313.2, - "Tl192": 576.0, - "Tl192_m1": 648.0, - "Tl193": 1296.0, - "Tl193_m1": 126.6, - "Tl194": 1980.0, - "Tl194_m1": 1968.0, - "Tl195": 4176.0, - "Tl195_m1": 3.6, - "Tl196": 6624.0, - "Tl196_m1": 5076.0, - "Tl197": 10224.0, - "Tl197_m1": 0.54, - "Tl198": 19080.0, - "Tl198_m1": 6732.0, - "Tl198_m2": 0.0321, - "Tl199": 26712.0, - "Tl199_m1": 0.0284, - "Tl200": 93960.0, - "Tl200_m1": 0.034, - "Tl201": 262837.4, - "Tl201_m1": 0.00201, - "Tl202": 1063584.0, - "Tl204": 119382400.0, - "Tl206": 252.12, - "Tl206_m1": 224.4, - "Tl207": 286.2, - "Tl207_m1": 1.33, - "Tl208": 183.18, - "Tl209": 132.0, - "Tl210": 78.0, - "Tl211": 60.0, - "Tl212": 67.0, - "Pb178": 0.00023, - "Pb179": 0.003, - "Pb180": 0.0045, - "Pb181": 0.036, - "Pb181_m1": 0.045, - "Pb182": 0.0575, - "Pb183": 0.535, - "Pb183_m1": 0.415, - "Pb184": 0.49, - "Pb185": 6.3, - "Pb185_m1": 4.3, - "Pb186": 4.82, - "Pb187": 15.2, - "Pb187_m1": 18.3, - "Pb188": 25.1, - "Pb189": 39.0, - "Pb189_m1": 50.0, - "Pb190": 71.0, - "Pb191": 79.8, - "Pb191_m1": 130.8, - "Pb192": 210.0, - "Pb193": 120.0, - "Pb193_m1": 348.0, - "Pb194": 720.0, - "Pb195": 900.0, - "Pb195_m1": 900.0, - "Pb196": 2220.0, - "Pb197": 480.0, - "Pb197_m1": 2580.0, - "Pb198": 8640.0, - "Pb199": 5400.0, - "Pb199_m1": 732.0, - "Pb200": 77400.0, - "Pb201": 33588.0, - "Pb201_m1": 60.8, - "Pb202": 1656770000000.0, - "Pb202_m1": 12744.0, - "Pb203": 186912.0, - "Pb203_m1": 6.21, - "Pb203_m2": 0.48, - "Pb204": 4.4e24, - "Pb204_m1": 4015.8, - "Pb205": 545946000000000.0, - "Pb205_m1": 0.00555, - "Pb207_m1": 0.806, - "Pb209": 11710.8, - "Pb210": 700578700.0, - "Pb211": 2166.0, - "Pb212": 38304.0, - "Pb213": 612.0, - "Pb214": 1608.0, - "Pb215": 36.0, - "Bi184": 0.013, - "Bi184_m1": 0.0066, - "Bi185": 5.8e-05, - "Bi186": 0.015, - "Bi186_m1": 0.0098, - "Bi187": 0.032, - "Bi187_m1": 0.00031, - "Bi188": 0.06, - "Bi188_m1": 0.265, - "Bi189": 0.674, - "Bi189_m1": 0.005, - "Bi190": 6.3, - "Bi190_m1": 6.2, - "Bi191": 12.4, - "Bi191_m1": 0.125, - "Bi192": 34.6, - "Bi192_m1": 39.6, - "Bi193": 63.6, - "Bi193_m1": 3.2, - "Bi194": 95.0, - "Bi194_m1": 125.0, - "Bi194_m2": 115.0, - "Bi195": 183.0, - "Bi195_m1": 87.0, - "Bi196": 308.0, - "Bi196_m1": 0.6, - "Bi196_m2": 240.0, - "Bi197": 559.8, - "Bi197_m1": 302.4, - "Bi198": 618.0, - "Bi198_m1": 696.0, - "Bi198_m2": 7.7, - "Bi199": 1620.0, - "Bi199_m1": 1482.0, - "Bi200": 2184.0, - "Bi200_m1": 1860.0, - "Bi200_m2": 0.4, - "Bi201": 6180.0, - "Bi201_m1": 3450.0, - "Bi202": 6156.0, - "Bi203": 42336.0, - "Bi203_m1": 0.305, - "Bi204": 40392.0, - "Bi204_m1": 0.013, - "Bi204_m2": 0.00107, - "Bi205": 1322784.0, - "Bi206": 539395.2, - "Bi207": 995642300.0, - "Bi208": 11613200000000.0, - "Bi208_m1": 0.00258, - "Bi209": 5.99594e26, - "Bi210": 433036.8, - "Bi210_m1": 95935100000000.0, - "Bi211": 128.4, - "Bi212": 3633.0, - "Bi212_m1": 1500.0, - "Bi212_m2": 420.0, - "Bi213": 2735.4, - "Bi214": 1194.0, - "Bi215": 462.0, - "Bi215_m1": 36.4, - "Bi216": 135.0, - "Bi217": 98.5, - "Bi218": 33.0, - "Po188": 0.000425, - "Po189": 0.0035, - "Po190": 0.00245, - "Po191": 0.022, - "Po191_m1": 0.093, - "Po192": 0.0332, - "Po193": 0.37, - "Po193_m1": 0.373, - "Po194": 0.392, - "Po195": 4.64, - "Po195_m1": 1.92, - "Po196": 5.8, - "Po197": 84.0, - "Po197_m1": 32.0, - "Po198": 106.2, - "Po199": 328.2, - "Po199_m1": 250.2, - "Po200": 690.6, - "Po201": 936.0, - "Po201_m1": 537.6, - "Po202": 2676.0, - "Po203": 2202.0, - "Po203_m1": 45.0, - "Po204": 12708.0, - "Po205": 6264.0, - "Po205_m1": 0.000645, - "Po205_m2": 0.0574, - "Po206": 760320.0, - "Po207": 20880.0, - "Po207_m1": 2.79, - "Po208": 91453920.0, - "Po209": 3218880000.0, - "Po210": 11955690.0, - "Po211": 0.516, - "Po211_m1": 25.2, - "Po212": 2.99e-07, - "Po212_m1": 45.1, - "Po213": 4.2e-06, - "Po214": 0.0001643, - "Po215": 0.001781, - "Po216": 0.145, - "Po217": 1.53, - "Po218": 185.88, - "Po219": 3e-07, - "Po220": 3e-07, - "At193": 0.0285, - "At194": 0.04, - "At194_m1": 0.25, - "At195": 0.328, - "At195_m1": 0.147, - "At196": 0.388, - "At196_m1": 1.1e-05, - "At197": 0.388, - "At197_m1": 2.0, - "At198": 4.2, - "At198_m1": 1.0, - "At199": 7.03, - "At200": 43.0, - "At200_m1": 47.0, - "At200_m2": 7.9, - "At201": 85.2, - "At202": 184.0, - "At202_m1": 182.0, - "At202_m2": 0.46, - "At203": 444.0, - "At204": 553.2, - "At204_m1": 0.108, - "At205": 1614.0, - "At206": 1836.0, - "At207": 6480.0, - "At208": 5868.0, - "At209": 19476.0, - "At210": 29160.0, - "At211": 25970.4, - "At212": 0.314, - "At212_m1": 0.119, - "At213": 1.25e-07, - "At214": 5.58e-07, - "At215": 0.0001, - "At216": 0.0003, - "At217": 0.0323, - "At218": 1.5, - "At219": 56.0, - "At220": 222.6, - "At221": 138.0, - "At222": 54.0, - "At223": 50.0, - "Rn195": 0.0065, - "Rn195_m1": 0.005, - "Rn196": 0.0046, - "Rn197": 0.066, - "Rn197_m1": 0.021, - "Rn198": 0.065, - "Rn199": 0.59, - "Rn199_m1": 0.31, - "Rn200": 1.075, - "Rn201": 7.0, - "Rn201_m1": 3.8, - "Rn202": 9.7, - "Rn203": 44.0, - "Rn203_m1": 26.9, - "Rn204": 70.2, - "Rn205": 170.0, - "Rn206": 340.2, - "Rn207": 555.0, - "Rn208": 1461.0, - "Rn209": 1728.0, - "Rn210": 8640.0, - "Rn211": 52560.0, - "Rn212": 1434.0, - "Rn213": 0.025, - "Rn214": 2.7e-07, - "Rn215": 2.3e-06, - "Rn216": 4.5e-05, - "Rn217": 0.00054, - "Rn218": 0.035, - "Rn219": 3.96, - "Rn220": 55.6, - "Rn221": 1542.0, - "Rn222": 330350.4, - "Rn223": 1458.0, - "Rn224": 6420.0, - "Rn225": 279.6, - "Rn226": 444.0, - "Rn227": 20.8, - "Rn228": 65.0, - "Fr199": 0.015, - "Fr200": 0.049, - "Fr201": 0.069, - "Fr202": 0.3, - "Fr202_m1": 0.29, - "Fr203": 0.55, - "Fr204": 1.7, - "Fr204_m1": 2.6, - "Fr204_m2": 1.0, - "Fr205": 3.8, - "Fr206": 16.0, - "Fr206_m1": 16.0, - "Fr206_m2": 0.7, - "Fr207": 14.8, - "Fr208": 59.1, - "Fr209": 50.0, - "Fr210": 190.8, - "Fr211": 186.0, - "Fr212": 1200.0, - "Fr213": 34.82, - "Fr214": 0.005, - "Fr214_m1": 0.00335, - "Fr215": 8.6e-08, - "Fr216": 7e-07, - "Fr217": 1.9e-05, - "Fr218": 0.001, - "Fr218_m1": 0.022, - "Fr219": 0.02, - "Fr220": 27.4, - "Fr221": 294.0, - "Fr222": 852.0, - "Fr223": 1320.0, - "Fr224": 199.8, - "Fr225": 237.0, - "Fr226": 49.0, - "Fr227": 148.2, - "Fr228": 38.0, - "Fr229": 50.2, - "Fr230": 19.1, - "Fr231": 17.6, - "Fr232": 5.5, - "Ra202": 0.0275, - "Ra203": 0.031, - "Ra203_m1": 0.025, - "Ra204": 0.0605, - "Ra205": 0.22, - "Ra205_m1": 0.18, - "Ra206": 0.24, - "Ra207": 1.3, - "Ra207_m1": 0.055, - "Ra208": 1.3, - "Ra209": 4.6, - "Ra210": 3.7, - "Ra211": 13.0, - "Ra212": 13.0, - "Ra213": 163.8, - "Ra213_m1": 0.0021, - "Ra214": 2.46, - "Ra215": 0.00155, - "Ra216": 1.82e-07, - "Ra217": 1.6e-06, - "Ra218": 2.52e-05, - "Ra219": 0.01, - "Ra220": 0.018, - "Ra221": 28.0, - "Ra222": 36.17, - "Ra223": 987552.0, - "Ra224": 316224.0, - "Ra225": 1287360.0, - "Ra226": 50492200000.0, - "Ra227": 2532.0, - "Ra228": 181456200.0, - "Ra229": 240.0, - "Ra230": 5580.0, - "Ra231": 103.0, - "Ra232": 252.0, - "Ra233": 30.0, - "Ra234": 30.0, - "Ac206": 0.024, - "Ac206_m1": 0.0395, - "Ac207": 0.027, - "Ac208": 0.095, - "Ac208_m1": 0.025, - "Ac209": 0.098, - "Ac210": 0.35, - "Ac211": 0.21, - "Ac212": 0.93, - "Ac213": 0.8, - "Ac214": 8.2, - "Ac215": 0.17, - "Ac216": 0.00044, - "Ac216_m1": 0.000441, - "Ac217": 6.9e-08, - "Ac218": 1.08e-06, - "Ac219": 1.18e-05, - "Ac220": 0.0264, - "Ac221": 0.052, - "Ac222": 5.0, - "Ac222_m1": 63.0, - "Ac223": 126.0, - "Ac224": 10008.0, - "Ac225": 864000.0, - "Ac226": 105732.0, - "Ac227": 687072100.0, - "Ac228": 22140.0, - "Ac229": 3762.0, - "Ac230": 122.0, - "Ac231": 450.0, - "Ac232": 119.0, - "Ac233": 145.0, - "Ac234": 44.0, - "Ac235": 60.0, - "Ac236": 120.0, - "Th209": 0.0065, - "Th210": 0.016, - "Th211": 0.05, - "Th212": 0.035, - "Th213": 0.14, - "Th214": 0.1, - "Th215": 1.2, - "Th216": 0.026, - "Th217": 0.000251, - "Th218": 1.17e-07, - "Th219": 1.05e-06, - "Th220": 9.7e-06, - "Th221": 0.00173, - "Th222": 0.002237, - "Th223": 0.6, - "Th224": 1.05, - "Th225": 523.2, - "Th226": 1834.2, - "Th227": 1613952.0, - "Th228": 60338130.0, - "Th229": 231633000000.0, - "Th230": 2378810000000.0, - "Th231": 91872.0, - "Th232": 4.43384e17, - "Th233": 1338.0, - "Th234": 2082240.0, - "Th235": 426.0, - "Th236": 2238.0, - "Th237": 282.0, - "Th238": 564.0, - "Pa212": 0.0051, - "Pa213": 0.0053, - "Pa214": 0.017, - "Pa215": 0.014, - "Pa216": 0.16, - "Pa217": 0.0036, - "Pa217_m1": 0.0012, - "Pa218": 0.000113, - "Pa219": 5.3e-08, - "Pa220": 7.8e-07, - "Pa221": 5.9e-06, - "Pa222": 0.0033, - "Pa223": 0.0051, - "Pa224": 0.79, - "Pa225": 1.7, - "Pa226": 108.0, - "Pa227": 2298.0, - "Pa228": 79200.0, - "Pa229": 129600.0, - "Pa230": 1503360.0, - "Pa231": 1033830000000.0, - "Pa232": 114048.0, - "Pa233": 2330640.0, - "Pa234": 24120.0, - "Pa234_m1": 69.54, - "Pa235": 1466.4, - "Pa236": 546.0, - "Pa237": 522.0, - "Pa238": 136.2, - "Pa239": 6480.0, - "Pa240": 120.0, - "U217": 0.0235, - "U218": 0.000545, - "U219": 4.2e-05, - "U220": 6e-08, - "U222": 1.3e-06, - "U223": 1.8e-05, - "U224": 0.0009, - "U225": 0.084, - "U226": 0.35, - "U227": 66.0, - "U228": 546.0, - "U229": 3480.0, - "U230": 1797120.0, - "U231": 362880.0, - "U232": 2174319000.0, - "U233": 5023970000000.0, - "U234": 7747390000000.0, - "U235": 2.22102e16, - "U235_m1": 1560.0, - "U236": 739079000000000.0, - "U237": 583200.0, - "U238": 1.40999e17, - "U239": 1407.0, - "U240": 50760.0, - "U241": 300.0, - "U242": 1008.0, - "Np225": 2e-06, - "Np226": 0.035, - "Np227": 0.51, - "Np228": 61.4, - "Np229": 240.0, - "Np230": 276.0, - "Np231": 2928.0, - "Np232": 882.0, - "Np233": 2172.0, - "Np234": 380160.0, - "Np235": 34231680.0, - "Np236": 4828310000000.0, - "Np236_m1": 81000.0, - "Np237": 67659500000000.0, - "Np238": 182908.8, - "Np239": 203558.4, - "Np240": 3714.0, - "Np240_m1": 433.2, - "Np241": 834.0, - "Np242": 132.0, - "Np242_m1": 330.0, - "Np243": 111.0, - "Np244": 137.4, - "Pu228": 1.85, - "Pu229": 112.0, - "Pu230": 102.0, - "Pu231": 516.0, - "Pu232": 2028.0, - "Pu233": 1254.0, - "Pu234": 31680.0, - "Pu235": 1518.0, - "Pu236": 90191620.0, - "Pu237": 3943296.0, - "Pu237_m1": 0.18, - "Pu238": 2767602000.0, - "Pu239": 760854000000.0, - "Pu240": 207049000000.0, - "Pu241": 450958100.0, - "Pu242": 11786800000000.0, - "Pu243": 17841.6, - "Pu244": 2559320000000000.0, - "Pu245": 37800.0, - "Pu246": 936576.0, - "Pu247": 196128.0, - "Am231": 10.0, - "Am232": 79.0, - "Am233": 192.0, - "Am234": 139.2, - "Am235": 618.0, - "Am236": 216.0, - "Am237": 4416.0, - "Am238": 5880.0, - "Am239": 42840.0, - "Am240": 182880.0, - "Am241": 13651800000.0, - "Am242": 57672.0, - "Am242_m1": 4449622000.0, - "Am242_m2": 0.014, - "Am243": 232580000000.0, - "Am244": 36360.0, - "Am244_m1": 1560.0, - "Am245": 7380.0, - "Am246": 2340.0, - "Am246_m1": 1500.0, - "Am247": 1380.0, - "Am248": 600.0, - "Am249": 120.0, - "Cm233": 17.7, - "Cm234": 51.0, - "Cm235": 300.0, - "Cm236": 1900.0, - "Cm237": 1200.0, - "Cm238": 8640.0, - "Cm239": 10440.0, - "Cm240": 2332800.0, - "Cm241": 2833920.0, - "Cm242": 14078020.0, - "Cm243": 918326200.0, - "Cm244": 571508100.0, - "Cm244_m1": 5e-07, - "Cm245": 268240000000.0, - "Cm246": 150214000000.0, - "Cm247": 492299000000000.0, - "Cm248": 10982000000000.0, - "Cm249": 3849.0, - "Cm250": 261928000000.0, - "Cm251": 1008.0, - "Bk235": 20.0, - "Bk237": 60.0, - "Bk238": 144.0, - "Bk240": 288.0, - "Bk241": 276.0, - "Bk242": 420.0, - "Bk243": 16200.0, - "Bk244": 15660.0, - "Bk245": 426816.0, - "Bk246": 155520.0, - "Bk247": 43549500000.0, - "Bk248": 283824000.0, - "Bk248_m1": 85320.0, - "Bk249": 27648000.0, - "Bk250": 11563.2, - "Bk251": 3336.0, - "Bk253": 600.0, - "Bk254": 120.0, - "Cf237": 2.1, - "Cf238": 0.021, - "Cf239": 51.5, - "Cf240": 57.6, - "Cf241": 226.8, - "Cf242": 222.0, - "Cf243": 642.0, - "Cf244": 1164.0, - "Cf245": 2700.0, - "Cf246": 128520.0, - "Cf247": 11196.0, - "Cf248": 28814400.0, - "Cf249": 11076700000.0, - "Cf250": 412773400.0, - "Cf251": 28338700000.0, - "Cf252": 83468070.0, - "Cf253": 1538784.0, - "Cf254": 5227200.0, - "Cf255": 5100.0, - "Cf256": 738.0, - "Es240": 1.0, - "Es241": 8.5, - "Es242": 13.5, - "Es243": 21.0, - "Es244": 37.0, - "Es245": 66.0, - "Es246": 462.0, - "Es247": 273.0, - "Es247_m1": 54000000.0, - "Es248": 1620.0, - "Es249": 6132.0, - "Es250": 30960.0, - "Es250_m1": 7992.0, - "Es251": 118800.0, - "Es252": 40754880.0, - "Es253": 1768608.0, - "Es254": 23820480.0, - "Es254_m1": 141479.9, - "Es255": 3438720.0, - "Es256": 1524.0, - "Es256_m1": 27360.0, - "Es257": 665280.0, - "Es258": 180.0, - "Fm242": 0.0008, - "Fm243": 0.2, - "Fm244": 0.0033, - "Fm245": 4.2, - "Fm246": 1.1, - "Fm247": 29.0, - "Fm248": 36.0, - "Fm249": 156.0, - "Fm250": 1800.0, - "Fm250_m1": 1.8, - "Fm251": 19080.0, - "Fm252": 91404.0, - "Fm253": 259200.0, - "Fm254": 11664.0, - "Fm255": 72252.0, - "Fm256": 9456.0, - "Fm257": 8683200.0, - "Fm258": 0.00037, - "Fm259": 1.5, - "Fm260": 0.004, - "Md245": 0.0009, - "Md245_m1": 0.39, - "Md246": 0.9, - "Md247": 1.12, - "Md247_m1": 0.26, - "Md248": 7.0, - "Md249": 24.0, - "Md249_m1": 1.9, - "Md250": 27.5, - "Md251": 240.0, - "Md252": 138.0, - "Md253": 630.0, - "Md254": 1680.0, - "Md254_m1": 1680.0, - "Md255": 1620.0, - "Md256": 4620.0, - "Md257": 19872.0, - "Md258": 4449600.0, - "Md258_m1": 3420.0, - "Md259": 5760.0, - "Md260": 2747520.0, - "Md261": 2400.0, - "No250": 4.35e-06, - "No251": 0.8, - "No251_m1": 1.02, - "No252": 2.44, - "No253": 97.2, - "No254": 51.0, - "No254_m1": 0.28, - "No255": 186.0, - "No256": 2.91, - "No257": 25.0, - "No258": 0.0012, - "No259": 3480.0, - "No260": 0.106, - "No261": 160000.0, - "No262": 0.005, - "Lr251": 1.341, - "Lr252": 0.38, - "Lr253": 0.575, - "Lr253_m1": 1.535, - "Lr254": 13.0, - "Lr255": 22.0, - "Lr255_m1": 2.53, - "Lr256": 27.0, - "Lr257": 0.646, - "Lr258": 4.1, - "Lr259": 6.2, - "Lr260": 180.0, - "Lr261": 2340.0, - "Lr262": 14400.0, - "Lr263": 18000.0, - "Rf253": 5.15e-05, - "Rf254": 2.3e-05, - "Rf255": 1.68, - "Rf256": 0.0064, - "Rf257": 4.7, - "Rf257_m1": 3.9, - "Rf258": 0.012, - "Rf259": 3.2, - "Rf260": 0.021, - "Rf261": 65.0, - "Rf261_m1": 81.0, - "Rf262": 2.3, - "Rf263": 600.0, - "Rf264": 3600.0, - "Rf265": 1.0, - "Db255": 1.7, - "Db256": 1.7, - "Db257": 1.52, - "Db257_m1": 0.78, - "Db258": 4.0, - "Db258_m1": 20.0, - "Db259": 0.51, - "Db260": 1.52, - "Db261": 1.8, - "Db262": 35.0, - "Db263": 28.5, - "Db264": 180.0, - "Db265": 900.0, - "Sg258": 0.0032, - "Sg259": 0.555, - "Sg260": 0.0036, - "Sg261": 0.23, - "Sg262": 0.0079, - "Sg263": 1.0, - "Sg263_m1": 0.12, - "Sg264": 0.045, - "Sg265": 8.0, - "Sg266": 25.0, - "Sg269": 50.0, - "Bh260": 0.0003, - "Bh261": 0.013, - "Bh262": 0.102, - "Bh262_m1": 0.022, - "Bh263": 0.0002, - "Bh264": 0.66, - "Bh265": 1.1, - "Bh266": 5.4, - "Bh267": 21.0, - "Bh269": 50.0, - "Hs263": 0.00355, - "Hs264": 0.0008, - "Hs265": 0.00205, - "Hs265_m1": 0.0003, - "Hs266": 0.00265, - "Hs267": 0.0545, - "Hs268": 1.2, - "Hs269": 12.9, - "Hs273": 50.0, - "Mt265": 120.0, - "Mt266": 0.0018, - "Mt266_m1": 0.0017, - "Mt267": 0.01, - "Mt268": 0.0225, - "Mt269": 0.05, - "Mt270": 0.00605, - "Mt271": 5.0, - "Mt273": 20.0, - "Ds267": 2.8e-06, - "Ds268": 0.0001, - "Ds269": 0.000268, - "Ds270": 0.00015, - "Ds270_m1": 0.009, - "Ds271": 0.001705, - "Ds271_m1": 0.0865, - "Ds272": 1.0, - "Ds273": 0.000225, - "Ds279_m1": 0.19, - "Rg272": 0.0041 + "h3": 388789600.0, + "h4": 9.90652e-23, + "h5": 7.99473e-23, + "h6": 2.84812e-22, + "h7": 2.3e-23, + "he5": 7.595e-22, + "he6": 0.8067, + "he7": 3.038e-21, + "he8": 0.1191, + "he9": 7e-21, + "he10": 1.519e-21, + "li4": 7.55721e-23, + "li5": 3.06868e-22, + "li8": 0.838, + "li9": 0.1783, + "li10": 2e-21, + "li11": 0.00859, + "li12": 1e-08, + "be5": 1e-09, + "be6": 4.95326e-21, + "be7": 4598208.0, + "be8": 8.18132e-17, + "be10": 47652000000000.0, + "be11": 13.81, + "be12": 0.0213, + "be13": 2.7e-21, + "be14": 0.00435, + "be15": 2e-07, + "be16": 2e-07, + "b6": 1e-09, + "b7": 3.255e-22, + "b8": 0.77, + "b9": 8.43888e-19, + "b12": 0.0202, + "b13": 0.01736, + "b14": 0.0125, + "b15": 0.00993, + "b16": 1.9e-10, + "b17": 0.00508, + "b18": 2.6e-08, + "b19": 0.00292, + "c8": 1.9813e-21, + "c9": 0.1265, + "c10": 19.29, + "c11": 1223.1, + "c14": 179878000000.0, + "c15": 2.449, + "c16": 0.747, + "c17": 0.193, + "c18": 0.092, + "c19": 0.049, + "c20": 0.0145, + "c21": 3e-08, + "c22": 0.0062, + "n10": 2e-22, + "n11": 3.12742e-22, + "n12": 0.011, + "n13": 597.9, + "n16": 7.13, + "n17": 4.171, + "n18": 0.624, + "n19": 0.271, + "n20": 0.13, + "n21": 0.085, + "n22": 0.024, + "n23": 0.0145, + "n24": 5.2e-08, + "n25": 2.6e-07, + "o12": 1.13925e-21, + "o13": 0.00858, + "o14": 70.606, + "o15": 122.24, + "o19": 26.88, + "o20": 13.51, + "o21": 3.42, + "o22": 2.25, + "o23": 0.0905, + "o24": 0.065, + "o25": 5e-08, + "o26": 4e-08, + "o27": 2.6e-07, + "o28": 1e-07, + "f14": 5.0007e-22, + "f15": 4.557e-22, + "f16": 1.13925e-20, + "f17": 64.49, + "f18": 6586.2, + "f20": 11.163, + "f21": 4.158, + "f22": 4.23, + "f23": 2.23, + "f24": 0.39, + "f25": 0.05, + "f26": 0.0096, + "f27": 0.005, + "f28": 4e-08, + "f29": 0.0025, + "f30": 2.6e-07, + "f31": 2.5e-07, + "ne16": 3.73524e-21, + "ne17": 0.1092, + "ne18": 1.672, + "ne19": 17.22, + "ne23": 37.24, + "ne24": 202.8, + "ne25": 0.602, + "ne26": 0.197, + "ne27": 0.032, + "ne28": 0.0189, + "ne29": 0.0148, + "ne30": 0.0073, + "ne31": 0.0034, + "ne32": 0.0035, + "ne33": 1.8e-07, + "ne34": 6e-08, + "na18": 1.3e-21, + "na19": 4e-08, + "na20": 0.4479, + "na21": 22.49, + "na22": 82134970.0, + "na24": 53989.2, + "na24_m1": 0.02018, + "na25": 59.1, + "na26": 1.077, + "na27": 0.301, + "na28": 0.0305, + "na29": 0.0449, + "na30": 0.048, + "na31": 0.017, + "na32": 0.0132, + "na33": 0.008, + "na34": 0.0055, + "na35": 0.0015, + "na36": 1.8e-07, + "na37": 6e-08, + "mg19": 4e-12, + "mg20": 0.0908, + "mg21": 0.122, + "mg22": 3.8755, + "mg23": 11.317, + "mg27": 567.48, + "mg28": 75294.0, + "mg29": 1.3, + "mg30": 0.335, + "mg31": 0.232, + "mg32": 0.086, + "mg33": 0.0905, + "mg34": 0.02, + "mg35": 0.07, + "mg36": 0.0039, + "mg37": 2.6e-07, + "mg38": 2.6e-07, + "mg39": 1.8e-07, + "mg40": 1.7e-07, + "al21": 3.5e-08, + "al22": 0.059, + "al23": 0.47, + "al24": 2.053, + "al24_m1": 0.13, + "al25": 7.183, + "al26": 22626800000000.0, + "al26_m1": 6.3452, + "al28": 134.484, + "al29": 393.6, + "al30": 3.62, + "al31": 0.644, + "al32": 0.033, + "al33": 0.0417, + "al34": 0.042, + "al35": 0.0386, + "al36": 0.09, + "al37": 0.0107, + "al38": 0.0076, + "al39": 7.6e-06, + "al40": 2.6e-07, + "al41": 2.6e-07, + "al42": 1.7e-07, + "si22": 0.029, + "si23": 0.0423, + "si24": 0.14, + "si25": 0.22, + "si26": 2.234, + "si27": 4.16, + "si31": 9438.0, + "si32": 4828310000.0, + "si33": 6.11, + "si34": 2.77, + "si35": 0.78, + "si36": 0.45, + "si37": 0.09, + "si38": 1e-06, + "si39": 0.0475, + "si40": 0.033, + "si41": 0.02, + "si42": 0.0125, + "si43": 6e-08, + "si44": 3.6e-07, + "p24": 0.0074, + "p25": 3e-08, + "p26": 0.0437, + "p27": 0.26, + "p28": 0.2703, + "p29": 4.142, + "p30": 149.88, + "p32": 1232323.0, + "p33": 2189376.0, + "p34": 12.43, + "p35": 47.3, + "p36": 5.6, + "p37": 2.31, + "p38": 0.64, + "p39": 0.28, + "p40": 0.125, + "p41": 0.1, + "p42": 0.0485, + "p43": 0.0365, + "p44": 0.0185, + "p45": 2e-07, + "p46": 2e-07, + "s26": 0.01, + "s27": 0.0155, + "s28": 0.125, + "s29": 0.187, + "s30": 1.178, + "s31": 2.572, + "s35": 7560864.0, + "s37": 303.0, + "s38": 10218.0, + "s39": 11.5, + "s40": 8.8, + "s41": 1.99, + "s42": 1.013, + "s43": 0.28, + "s44": 0.1, + "s45": 0.068, + "s46": 0.05, + "s48": 2e-07, + "s49": 2e-07, + "cl28": 0.0017, + "cl29": 2e-08, + "cl30": 3e-08, + "cl31": 0.15, + "cl32": 0.298, + "cl33": 2.511, + "cl34": 1.5264, + "cl34_m1": 1920.0, + "cl36": 9498840000000.0, + "cl38": 2233.8, + "cl38_m1": 0.715, + "cl39": 3336.0, + "cl40": 81.0, + "cl41": 38.4, + "cl42": 6.8, + "cl43": 3.13, + "cl44": 0.56, + "cl45": 0.413, + "cl46": 0.232, + "cl47": 0.101, + "cl48": 2e-07, + "cl49": 1.7e-07, + "cl50": 0.02, + "cl51": 2e-07, + "ar30": 2e-08, + "ar31": 0.0151, + "ar32": 0.098, + "ar33": 0.173, + "ar34": 0.8445, + "ar35": 1.775, + "ar37": 3027456.0, + "ar39": 8488990000.0, + "ar41": 6576.6, + "ar42": 1038250000.0, + "ar43": 322.2, + "ar44": 712.2, + "ar45": 21.48, + "ar46": 8.4, + "ar47": 1.23, + "ar48": 0.475, + "ar49": 0.17, + "ar50": 0.085, + "ar51": 2e-07, + "ar52": 0.01, + "ar53": 0.003, + "k32": 0.0033, + "k33": 2.5e-08, + "k34": 2.5e-08, + "k35": 0.178, + "k36": 0.342, + "k37": 1.226, + "k38": 458.16, + "k38_m1": 0.924, + "k40": 3.93839e16, + "k42": 44496.0, + "k43": 80280.0, + "k44": 1327.8, + "k45": 1068.6, + "k46": 105.0, + "k47": 17.5, + "k48": 6.8, + "k49": 1.26, + "k50": 0.472, + "k51": 0.365, + "k52": 0.105, + "k53": 0.03, + "k54": 0.01, + "k55": 0.003, + "ca34": 3.5e-08, + "ca35": 0.0257, + "ca36": 0.102, + "ca37": 0.1811, + "ca38": 0.44, + "ca39": 0.8596, + "ca41": 3218880000000.0, + "ca45": 14049500.0, + "ca47": 391910.4, + "ca48": 7.25824e26, + "ca49": 523.08, + "ca50": 13.9, + "ca51": 10.0, + "ca52": 4.6, + "ca53": 0.09, + "ca54": 0.086, + "ca55": 0.022, + "ca56": 0.01, + "ca57": 0.005, + "sc36": 0.0088, + "sc37": 0.056, + "sc38": 0.0423, + "sc39": 3e-07, + "sc40": 0.1823, + "sc41": 0.5963, + "sc42": 0.6808, + "sc42_m1": 62.0, + "sc43": 14007.6, + "sc44": 14292.0, + "sc44_m1": 210996.0, + "sc45_m1": 0.318, + "sc46": 7239456.0, + "sc46_m1": 18.75, + "sc47": 289370.9, + "sc48": 157212.0, + "sc49": 3430.8, + "sc50": 102.5, + "sc50_m1": 0.35, + "sc51": 12.4, + "sc52": 8.2, + "sc53": 3.0, + "sc54": 0.36, + "sc55": 0.105, + "sc56": 0.06, + "sc57": 0.013, + "sc58": 0.012, + "sc59": 0.01, + "sc60": 0.003, + "ti38": 1.2e-07, + "ti39": 0.032, + "ti40": 0.0533, + "ti41": 0.0804, + "ti42": 0.199, + "ti43": 0.509, + "ti44": 1893460000.0, + "ti45": 11088.0, + "ti51": 345.6, + "ti52": 102.0, + "ti53": 32.7, + "ti54": 1.5, + "ti55": 1.3, + "ti56": 0.2, + "ti57": 0.06, + "ti58": 0.059, + "ti59": 0.03, + "ti60": 0.022, + "ti61": 3e-07, + "ti62": 0.01, + "ti63": 0.003, + "v40": 0.0077, + "v41": 0.0244, + "v42": 5.5e-08, + "v43": 0.8, + "v44": 0.111, + "v44_m1": 0.15, + "v45": 0.547, + "v46": 0.4225, + "v46_m1": 0.00102, + "v47": 1956.0, + "v48": 1380110.0, + "v49": 28512000.0, + "v50": 4.41806e24, + "v52": 224.58, + "v53": 92.58, + "v54": 49.8, + "v55": 6.54, + "v56": 0.216, + "v57": 0.35, + "v58": 0.185, + "v59": 0.075, + "v60": 0.068, + "v61": 0.047, + "v62": 1.5e-07, + "v63": 0.017, + "v64": 0.019, + "v65": 0.01, + "cr42": 0.014, + "cr43": 0.0216, + "cr44": 0.0535, + "cr45": 0.0609, + "cr46": 0.26, + "cr47": 0.5, + "cr48": 77616.0, + "cr49": 2538.0, + "cr51": 2393366.0, + "cr55": 209.82, + "cr56": 356.4, + "cr57": 21.1, + "cr58": 7.0, + "cr59": 0.46, + "cr60": 0.49, + "cr61": 0.27, + "cr62": 0.19, + "cr63": 0.129, + "cr64": 0.043, + "cr65": 0.027, + "cr66": 0.01, + "cr67": 0.05, + "mn44": 1.05e-07, + "mn45": 7e-08, + "mn46": 0.0345, + "mn47": 0.1, + "mn48": 0.1581, + "mn49": 0.382, + "mn50": 0.28319, + "mn50_m1": 105.0, + "mn51": 2772.0, + "mn52": 483062.4, + "mn52_m1": 1266.0, + "mn53": 116763000000000.0, + "mn54": 26961120.0, + "mn56": 9284.04, + "mn57": 85.4, + "mn58": 3.0, + "mn58_m1": 65.4, + "mn59": 4.59, + "mn60": 51.0, + "mn60_m1": 1.77, + "mn61": 0.67, + "mn62": 0.671, + "mn62_m1": 0.092, + "mn63": 0.29, + "mn64": 0.09, + "mn65": 0.092, + "mn66": 0.064, + "mn67": 0.047, + "mn68": 0.028, + "mn69": 0.014, + "fe45": 0.00203, + "fe46": 0.013, + "fe47": 0.0219, + "fe48": 0.044, + "fe49": 0.0647, + "fe50": 0.155, + "fe51": 0.305, + "fe52": 29790.0, + "fe52_m1": 45.9, + "fe53": 510.6, + "fe53_m1": 152.4, + "fe55": 86594050.0, + "fe59": 3844368.0, + "fe60": 47336400000000.0, + "fe61": 358.8, + "fe62": 68.0, + "fe63": 6.1, + "fe64": 2.0, + "fe65": 0.81, + "fe65_m1": 1.12, + "fe66": 0.44, + "fe67": 0.416, + "fe68": 0.187, + "fe69": 0.109, + "fe70": 0.094, + "fe71": 0.028, + "fe72": 1.5e-07, + "co49": 3.5e-08, + "co50": 0.044, + "co51": 2e-07, + "co52": 0.115, + "co53": 0.24, + "co53_m1": 0.247, + "co54": 0.19328, + "co54_m1": 88.8, + "co55": 63108.0, + "co56": 6672931.0, + "co57": 23478340.0, + "co58": 6122304.0, + "co58_m1": 32760.0, + "co60": 166344200.0, + "co60_m1": 628.02, + "co61": 5940.0, + "co62": 90.0, + "co62_m1": 834.6, + "co63": 27.4, + "co64": 0.3, + "co65": 1.16, + "co66": 0.2, + "co67": 0.425, + "co68": 0.199, + "co68_m1": 1.6, + "co69": 0.22, + "co70": 0.119, + "co70_m1": 0.5, + "co71": 0.079, + "co72": 0.0599, + "co73": 0.041, + "co74": 0.03, + "co75": 0.034, + "ni48": 0.0021, + "ni49": 0.0075, + "ni50": 0.012, + "ni51": 2e-07, + "ni52": 0.038, + "ni53": 0.045, + "ni54": 0.104, + "ni55": 0.2047, + "ni56": 524880.0, + "ni57": 128160.0, + "ni59": 2398380000000.0, + "ni63": 3193630000.0, + "ni65": 9061.884, + "ni66": 196560.0, + "ni67": 21.0, + "ni68": 29.0, + "ni69": 11.4, + "ni69_m1": 3.5, + "ni70": 6.0, + "ni71": 2.56, + "ni72": 1.57, + "ni73": 0.84, + "ni74": 0.68, + "ni75": 0.6, + "ni76": 0.238, + "ni77": 0.061, + "ni78": 0.11, + "cu52": 0.0069, + "cu53": 3e-07, + "cu54": 7.5e-08, + "cu55": 0.04, + "cu56": 0.094, + "cu57": 0.1963, + "cu58": 3.204, + "cu59": 81.5, + "cu60": 1422.0, + "cu61": 11998.8, + "cu62": 580.38, + "cu64": 45723.6, + "cu66": 307.2, + "cu67": 222588.0, + "cu68": 31.1, + "cu68_m1": 225.0, + "cu69": 171.0, + "cu70": 44.5, + "cu70_m1": 33.0, + "cu70_m2": 6.6, + "cu71": 19.5, + "cu72": 6.63, + "cu73": 4.2, + "cu74": 1.75, + "cu75": 1.224, + "cu76": 0.653, + "cu76_m1": 1.27, + "cu77": 0.469, + "cu78": 0.335, + "cu79": 0.188, + "cu80": 0.17, + "cu81": 0.028, + "zn54": 0.0037, + "zn55": 0.02, + "zn56": 5e-07, + "zn57": 0.038, + "zn58": 0.084, + "zn59": 0.182, + "zn60": 142.8, + "zn61": 89.1, + "zn61_m1": 0.43, + "zn61_m2": 0.14, + "zn62": 33336.0, + "zn63": 2308.2, + "zn65": 21075550.0, + "zn69": 3384.0, + "zn69_m1": 49536.0, + "zn71": 147.0, + "zn71_m1": 14256.0, + "zn72": 167400.0, + "zn73": 23.5, + "zn73_m1": 5.8, + "zn73_m2": 0.013, + "zn74": 95.6, + "zn75": 10.2, + "zn76": 5.7, + "zn77": 2.08, + "zn77_m1": 1.05, + "zn78": 1.47, + "zn79": 0.995, + "zn80": 0.54, + "zn81": 0.32, + "zn82": 0.052, + "zn83": 0.043, + "ga56": 0.0059, + "ga57": 0.0123, + "ga58": 0.0152, + "ga59": 0.0418, + "ga60": 0.07, + "ga61": 0.168, + "ga62": 0.11612, + "ga63": 32.4, + "ga64": 157.62, + "ga65": 912.0, + "ga66": 34164.0, + "ga67": 281810.9, + "ga68": 4062.6, + "ga70": 1268.4, + "ga72": 50760.0, + "ga72_m1": 0.03968, + "ga73": 17496.0, + "ga74": 487.2, + "ga74_m1": 9.5, + "ga75": 126.0, + "ga76": 32.6, + "ga77": 13.2, + "ga78": 5.09, + "ga79": 2.847, + "ga80": 1.676, + "ga81": 1.217, + "ga82": 0.599, + "ga83": 0.3081, + "ga84": 0.085, + "ga85": 0.048, + "ga86": 0.029, + "ge58": 0.0152, + "ge59": 0.0418, + "ge60": 0.03, + "ge61": 0.039, + "ge62": 1.5e-07, + "ge63": 0.142, + "ge64": 63.7, + "ge65": 30.9, + "ge66": 8136.0, + "ge67": 1134.0, + "ge68": 23410080.0, + "ge69": 140580.0, + "ge71": 987552.0, + "ge71_m1": 0.02041, + "ge73_m1": 0.499, + "ge75": 4966.8, + "ge75_m1": 47.7, + "ge77": 40680.0, + "ge77_m1": 52.9, + "ge78": 5280.0, + "ge79": 18.98, + "ge79_m1": 39.0, + "ge80": 29.5, + "ge81": 7.6, + "ge81_m1": 7.6, + "ge82": 4.55, + "ge83": 1.85, + "ge84": 0.954, + "ge85": 0.535, + "ge86": 0.095, + "ge87": 0.14, + "ge88": 0.066, + "ge89": 0.039, + "as60": 0.0083, + "as61": 0.0166, + "as62": 0.0259, + "as63": 0.0921, + "as64": 0.036, + "as65": 0.128, + "as66": 0.09579, + "as67": 42.5, + "as68": 151.6, + "as69": 913.8, + "as70": 3156.0, + "as71": 235080.0, + "as72": 93600.0, + "as73": 6937920.0, + "as74": 1535328.0, + "as75_m1": 0.01762, + "as76": 94464.0, + "as77": 139788.0, + "as78": 5442.0, + "as79": 540.6, + "as80": 15.2, + "as81": 33.3, + "as82": 19.1, + "as82_m1": 13.6, + "as83": 13.4, + "as84": 4.2, + "as85": 2.021, + "as86": 0.945, + "as87": 0.56, + "as88": 0.112, + "as89": 0.059, + "as90": 0.043, + "as91": 0.044, + "as92": 0.027, + "se65": 0.05, + "se66": 0.033, + "se67": 0.136, + "se68": 35.5, + "se69": 27.4, + "se70": 2466.0, + "se71": 284.4, + "se72": 725760.0, + "se73": 25740.0, + "se73_m1": 2388.0, + "se75": 10349860.0, + "se77_m1": 17.36, + "se79": 9309490000000.0, + "se79_m1": 235.2, + "se81": 1107.0, + "se81_m1": 3436.8, + "se83": 1338.0, + "se83_m1": 70.1, + "se84": 195.6, + "se85": 31.7, + "se86": 14.3, + "se87": 5.5, + "se88": 1.53, + "se89": 0.41, + "se90": 0.161, + "se91": 0.27, + "se92": 0.093, + "se93": 0.062, + "se94": 0.059, + "br67": 0.0443, + "br68": 1.2e-06, + "br69": 2.4e-08, + "br70": 0.0791, + "br70_m1": 2.2, + "br71": 21.4, + "br72": 78.6, + "br72_m1": 10.6, + "br73": 204.0, + "br74": 1524.0, + "br74_m1": 2760.0, + "br75": 5802.0, + "br76": 58320.0, + "br76_m1": 1.31, + "br77": 205329.6, + "br77_m1": 256.8, + "br78": 387.0, + "br79_m1": 4.86, + "br80": 1060.8, + "br80_m1": 15913.8, + "br82": 127015.2, + "br82_m1": 367.8, + "br83": 8640.0, + "br84": 1905.6, + "br84_m1": 360.0, + "br85": 174.0, + "br86": 55.0, + "br87": 55.65, + "br88": 16.29, + "br89": 4.4, + "br90": 1.92, + "br91": 0.541, + "br92": 0.343, + "br93": 0.102, + "br94": 0.07, + "br95": 0.066, + "br96": 0.042, + "br97": 0.04, + "kr69": 0.032, + "kr70": 0.052, + "kr71": 0.1, + "kr72": 17.1, + "kr73": 27.3, + "kr74": 690.0, + "kr75": 257.4, + "kr76": 53280.0, + "kr77": 4464.0, + "kr79": 126144.0, + "kr79_m1": 50.0, + "kr81": 7226690000000.0, + "kr81_m1": 13.1, + "kr83_m1": 6588.0, + "kr85": 339433500.0, + "kr85_m1": 16128.0, + "kr87": 4578.0, + "kr88": 10224.0, + "kr89": 189.0, + "kr90": 32.32, + "kr91": 8.57, + "kr92": 1.84, + "kr93": 1.286, + "kr94": 0.212, + "kr95": 0.114, + "kr96": 0.08, + "kr97": 0.063, + "kr98": 0.046, + "kr99": 0.027, + "kr100": 0.007, + "rb71": 1e-09, + "rb72": 1.2e-06, + "rb73": 3e-08, + "rb74": 0.064776, + "rb75": 19.0, + "rb76": 36.5, + "rb77": 226.2, + "rb78": 1059.6, + "rb78_m1": 344.4, + "rb79": 1374.0, + "rb80": 34.0, + "rb81": 16459.2, + "rb81_m1": 1830.0, + "rb82": 75.45, + "rb82_m1": 23299.2, + "rb83": 7447680.0, + "rb84": 2835648.0, + "rb84_m1": 1215.6, + "rb86": 1609718.0, + "rb86_m1": 61.02, + "rb87": 1.51792e18, + "rb88": 1066.38, + "rb89": 909.0, + "rb90": 158.0, + "rb90_m1": 258.0, + "rb91": 58.4, + "rb92": 4.492, + "rb93": 5.84, + "rb94": 2.702, + "rb95": 0.3777, + "rb96": 0.203, + "rb97": 0.1691, + "rb98": 0.114, + "rb98_m1": 0.096, + "rb99": 0.054, + "rb100": 0.051, + "rb101": 0.032, + "rb102": 0.037, + "sr73": 0.025, + "sr74": 1.2e-06, + "sr75": 0.088, + "sr76": 7.89, + "sr77": 9.0, + "sr78": 150.0, + "sr79": 135.0, + "sr80": 6378.0, + "sr81": 1338.0, + "sr82": 2190240.0, + "sr83": 116676.0, + "sr83_m1": 4.95, + "sr85": 5602176.0, + "sr85_m1": 4057.8, + "sr87_m1": 10134.0, + "sr89": 4365792.0, + "sr90": 908543300.0, + "sr91": 34668.0, + "sr92": 9756.0, + "sr93": 445.38, + "sr94": 75.3, + "sr95": 23.9, + "sr96": 1.07, + "sr97": 0.429, + "sr98": 0.653, + "sr99": 0.27, + "sr100": 0.202, + "sr101": 0.118, + "sr102": 0.069, + "sr103": 0.068, + "sr104": 0.043, + "sr105": 0.0556, + "y76": 2e-07, + "y77": 0.062, + "y78": 0.05, + "y78_m1": 5.7, + "y79": 14.8, + "y80": 30.1, + "y80_m1": 4.8, + "y81": 70.4, + "y82": 8.3, + "y83": 424.8, + "y83_m1": 171.0, + "y84": 2370.0, + "y84_m1": 4.6, + "y85": 9648.0, + "y85_m1": 17496.0, + "y86": 53064.0, + "y86_m1": 2880.0, + "y87": 287280.0, + "y87_m1": 48132.0, + "y88": 9212486.0, + "y88_m1": 0.000301, + "y88_m2": 0.01397, + "y89_m1": 15.663, + "y90": 230400.0, + "y90_m1": 11484.0, + "y91": 5055264.0, + "y91_m1": 2982.6, + "y92": 12744.0, + "y93": 36648.0, + "y93_m1": 0.82, + "y94": 1122.0, + "y95": 618.0, + "y96": 5.34, + "y96_m1": 9.6, + "y97": 3.75, + "y97_m1": 1.17, + "y97_m2": 0.142, + "y98": 0.548, + "y98_m1": 2.0, + "y99": 1.47, + "y100": 0.735, + "y100_m1": 0.94, + "y101": 0.45, + "y102": 0.36, + "y102_m1": 0.298, + "y103": 0.23, + "y104": 0.18, + "y105": 0.088, + "y106": 0.066, + "y107": 0.03, + "y108": 0.048, + "zr78": 2e-07, + "zr79": 0.056, + "zr80": 4.6, + "zr81": 5.5, + "zr82": 32.0, + "zr83": 41.6, + "zr84": 1554.0, + "zr85": 471.6, + "zr85_m1": 10.9, + "zr86": 59400.0, + "zr87": 6048.0, + "zr87_m1": 14.0, + "zr88": 7205760.0, + "zr89": 282276.0, + "zr89_m1": 249.66, + "zr90_m1": 0.8092, + "zr93": 48283100000000.0, + "zr95": 5532365.0, + "zr96": 6.31152e26, + "zr97": 60296.4, + "zr98": 30.7, + "zr99": 2.1, + "zr100": 7.1, + "zr101": 2.3, + "zr102": 2.9, + "zr103": 1.3, + "zr104": 1.2, + "zr105": 0.6, + "zr106": 0.27, + "zr107": 0.15, + "zr108": 0.08, + "zr109": 0.117, + "zr110": 0.098, + "nb81": 0.8, + "nb82": 0.05, + "nb83": 4.1, + "nb84": 9.8, + "nb85": 20.9, + "nb85_m1": 3.3, + "nb86": 88.0, + "nb87": 225.0, + "nb87_m1": 156.0, + "nb88": 873.0, + "nb88_m1": 466.8, + "nb89": 7308.0, + "nb89_m1": 3960.0, + "nb90": 52560.0, + "nb90_m1": 18.81, + "nb90_m2": 0.00619, + "nb91": 21459200000.0, + "nb91_m1": 5258304.0, + "nb92": 1095050000000000.0, + "nb92_m1": 876960.0, + "nb93_m1": 509024100.0, + "nb94": 640619000000.0, + "nb94_m1": 375.78, + "nb95": 3023222.0, + "nb95_m1": 311904.0, + "nb96": 84060.0, + "nb97": 4326.0, + "nb97_m1": 58.7, + "nb98": 2.86, + "nb98_m1": 3078.0, + "nb99": 15.0, + "nb99_m1": 150.0, + "nb100": 1.5, + "nb100_m1": 2.99, + "nb101": 7.1, + "nb102": 4.3, + "nb102_m1": 1.3, + "nb103": 1.5, + "nb104": 4.9, + "nb104_m1": 0.94, + "nb105": 2.95, + "nb106": 0.93, + "nb107": 0.3, + "nb108": 0.193, + "nb109": 0.19, + "nb110": 0.17, + "nb111": 0.08, + "nb112": 0.069, + "nb113": 0.03, + "mo83": 0.0195, + "mo84": 3.8, + "mo85": 3.2, + "mo86": 19.6, + "mo87": 14.02, + "mo88": 480.0, + "mo89": 126.6, + "mo89_m1": 0.19, + "mo90": 20412.0, + "mo91": 929.4, + "mo91_m1": 64.6, + "mo93": 126230000000.0, + "mo93_m1": 24660.0, + "mo99": 237513.6, + "mo100": 2.3037e26, + "mo101": 876.6, + "mo102": 678.0, + "mo103": 67.5, + "mo104": 60.0, + "mo105": 35.6, + "mo106": 8.73, + "mo107": 3.5, + "mo108": 1.09, + "mo109": 0.53, + "mo110": 0.3, + "mo111": 0.2, + "mo112": 0.287, + "mo113": 0.1, + "mo114": 0.08, + "mo115": 0.092, + "tc85": 0.5, + "tc86": 0.054, + "tc86_m1": 1.1e-06, + "tc87": 2.2, + "tc88": 5.8, + "tc88_m1": 6.4, + "tc89": 12.8, + "tc89_m1": 12.9, + "tc90": 8.7, + "tc90_m1": 49.2, + "tc91": 188.4, + "tc91_m1": 198.0, + "tc92": 255.0, + "tc93": 9900.0, + "tc93_m1": 2610.0, + "tc94": 17580.0, + "tc94_m1": 3120.0, + "tc95": 72000.0, + "tc95_m1": 5270400.0, + "tc96": 369792.0, + "tc96_m1": 3090.0, + "tc97": 132857000000000.0, + "tc97_m1": 7862400.0, + "tc98": 132542000000000.0, + "tc99": 6661810000000.0, + "tc99_m1": 21624.12, + "tc100": 15.46, + "tc101": 852.0, + "tc102": 5.28, + "tc102_m1": 261.0, + "tc103": 54.2, + "tc104": 1098.0, + "tc105": 456.0, + "tc106": 35.6, + "tc107": 21.2, + "tc108": 5.17, + "tc109": 0.86, + "tc110": 0.92, + "tc111": 0.29, + "tc112": 0.28, + "tc113": 0.16, + "tc114": 0.15, + "tc115": 0.073, + "tc116": 0.09, + "tc117": 0.04, + "tc118": 0.066, + "ru87": 1.5e-06, + "ru88": 1.25, + "ru89": 1.5, + "ru90": 11.7, + "ru91": 7.9, + "ru91_m1": 7.6, + "ru92": 219.0, + "ru93": 59.7, + "ru93_m1": 10.8, + "ru94": 3108.0, + "ru95": 5914.8, + "ru97": 244512.0, + "ru103": 3390941.0, + "ru103_m1": 0.00169, + "ru105": 15984.0, + "ru106": 32123520.0, + "ru107": 225.0, + "ru108": 273.0, + "ru109": 34.5, + "ru110": 11.6, + "ru111": 2.12, + "ru112": 1.75, + "ru113": 0.8, + "ru113_m1": 0.51, + "ru114": 0.52, + "ru115": 0.74, + "ru116": 0.204, + "ru117": 0.142, + "ru118": 0.123, + "ru119": 0.162, + "ru120": 0.149, + "rh89": 1.5e-06, + "rh90": 0.0145, + "rh90_m1": 1.05, + "rh91": 1.47, + "rh92": 4.66, + "rh93": 11.9, + "rh94": 70.6, + "rh94_m1": 25.8, + "rh95": 301.2, + "rh95_m1": 117.6, + "rh96": 594.0, + "rh96_m1": 90.6, + "rh97": 1842.0, + "rh97_m1": 2772.0, + "rh98": 523.2, + "rh98_m1": 216.0, + "rh99": 1391040.0, + "rh99_m1": 16920.0, + "rh100": 74880.0, + "rh100_m1": 276.0, + "rh101": 104140100.0, + "rh101_m1": 374976.0, + "rh102": 17910720.0, + "rh102_m1": 118088500.0, + "rh103_m1": 3366.84, + "rh104": 42.3, + "rh104_m1": 260.4, + "rh105": 127296.0, + "rh105_m1": 40.0, + "rh106": 30.07, + "rh106_m1": 7860.0, + "rh107": 1302.0, + "rh108": 16.8, + "rh108_m1": 360.0, + "rh109": 80.0, + "rh110": 3.2, + "rh110_m1": 28.5, + "rh111": 11.0, + "rh112": 2.1, + "rh112_m1": 6.73, + "rh113": 2.8, + "rh114": 1.85, + "rh115": 0.99, + "rh116": 0.68, + "rh116_m1": 0.57, + "rh117": 0.44, + "rh118": 0.266, + "rh119": 0.171, + "rh120": 0.136, + "rh121": 0.151, + "rh122": 0.108, + "rh123": 0.0489, + "pd91": 1e-06, + "pd92": 0.8, + "pd93": 1.3, + "pd94": 9.0, + "pd95": 10.0, + "pd95_m1": 13.3, + "pd96": 122.0, + "pd97": 186.0, + "pd98": 1062.0, + "pd99": 1284.0, + "pd100": 313632.0, + "pd101": 30492.0, + "pd103": 1468022.0, + "pd107": 205124000000000.0, + "pd107_m1": 21.3, + "pd109": 49324.32, + "pd109_m1": 281.4, + "pd111": 1404.0, + "pd111_m1": 19800.0, + "pd112": 75708.0, + "pd113": 93.0, + "pd113_m1": 0.3, + "pd114": 145.2, + "pd115": 25.0, + "pd115_m1": 50.0, + "pd116": 11.8, + "pd117": 4.3, + "pd117_m1": 0.0191, + "pd118": 1.9, + "pd119": 0.92, + "pd120": 0.5, + "pd121": 0.285, + "pd122": 0.175, + "pd123": 0.244, + "pd124": 0.038, + "pd125": 0.3987, + "pd126": 0.2499, + "ag93": 1.5e-06, + "ag94": 0.035, + "ag94_m1": 0.55, + "ag94_m2": 0.4, + "ag95": 2.0, + "ag95_m1": 0.5, + "ag95_m2": 0.016, + "ag95_m3": 0.04, + "ag96": 4.4, + "ag96_m1": 6.9, + "ag97": 25.5, + "ag98": 47.5, + "ag99": 124.0, + "ag99_m1": 10.5, + "ag100": 120.6, + "ag100_m1": 134.4, + "ag101": 666.0, + "ag101_m1": 3.1, + "ag102": 774.0, + "ag102_m1": 462.0, + "ag103": 3942.0, + "ag103_m1": 5.7, + "ag104": 4152.0, + "ag104_m1": 2010.0, + "ag105": 3567456.0, + "ag105_m1": 433.8, + "ag106": 1437.6, + "ag106_m1": 715392.0, + "ag107_m1": 44.3, + "ag108": 142.92, + "ag108_m1": 13822200000.0, + "ag109_m1": 39.6, + "ag110": 24.6, + "ag110_m1": 21579260.0, + "ag111": 643680.0, + "ag111_m1": 64.8, + "ag112": 11268.0, + "ag113": 19332.0, + "ag113_m1": 68.7, + "ag114": 4.6, + "ag114_m1": 0.0015, + "ag115": 1200.0, + "ag115_m1": 18.0, + "ag116": 237.0, + "ag116_m1": 20.0, + "ag116_m2": 9.3, + "ag117": 72.8, + "ag117_m1": 5.34, + "ag118": 3.76, + "ag118_m1": 2.0, + "ag119": 2.1, + "ag119_m1": 6.0, + "ag120": 1.23, + "ag120_m1": 0.32, + "ag121": 0.78, + "ag122": 0.529, + "ag122_m1": 0.2, + "ag123": 0.3, + "ag124": 0.172, + "ag125": 0.166, + "ag126": 0.107, + "ag127": 0.109, + "ag128": 0.058, + "ag129": 0.046, + "ag130": 0.05, + "cd95": 0.005, + "cd96": 1.0, + "cd97": 2.8, + "cd98": 9.2, + "cd99": 16.0, + "cd100": 49.1, + "cd101": 81.6, + "cd102": 330.0, + "cd103": 438.0, + "cd104": 3462.0, + "cd105": 3330.0, + "cd107": 23400.0, + "cd109": 39864960.0, + "cd111_m1": 2912.4, + "cd113": 2.53723e23, + "cd113_m1": 444962200.0, + "cd115": 192456.0, + "cd115_m1": 3849984.0, + "cd116": 9.78286e26, + "cd117": 8964.0, + "cd117_m1": 12096.0, + "cd118": 3018.0, + "cd119": 161.4, + "cd119_m1": 132.0, + "cd120": 50.8, + "cd121": 13.5, + "cd121_m1": 8.3, + "cd122": 5.24, + "cd123": 2.1, + "cd123_m1": 1.82, + "cd124": 1.25, + "cd125": 0.68, + "cd125_m1": 0.48, + "cd126": 0.515, + "cd127": 0.37, + "cd128": 0.28, + "cd129": 0.27, + "cd130": 0.162, + "cd131": 0.068, + "cd132": 0.097, + "in97": 0.005, + "in98": 0.0425, + "in98_m1": 1.6, + "in99": 3.05, + "in100": 5.9, + "in101": 15.1, + "in102": 23.3, + "in103": 65.0, + "in103_m1": 34.0, + "in104": 108.0, + "in104_m1": 15.7, + "in105": 304.2, + "in105_m1": 48.0, + "in106": 372.0, + "in106_m1": 312.0, + "in107": 1944.0, + "in107_m1": 50.4, + "in108": 3480.0, + "in108_m1": 2376.0, + "in109": 15001.2, + "in109_m1": 80.4, + "in109_m2": 0.209, + "in110": 17640.0, + "in110_m1": 4146.0, + "in111": 242326.1, + "in111_m1": 462.0, + "in112": 898.2, + "in112_m1": 1233.6, + "in113_m1": 5968.56, + "in114": 71.9, + "in114_m1": 4277664.0, + "in114_m2": 0.0431, + "in115": 1.39169e22, + "in115_m1": 16149.6, + "in116": 14.1, + "in116_m1": 3257.4, + "in116_m2": 2.18, + "in117": 2592.0, + "in117_m1": 6972.0, + "in118": 5.0, + "in118_m1": 267.0, + "in118_m2": 8.5, + "in119": 144.0, + "in119_m1": 1080.0, + "in120": 3.08, + "in120_m1": 46.2, + "in120_m2": 47.3, + "in121": 23.1, + "in121_m1": 232.8, + "in122": 1.5, + "in122_m1": 10.3, + "in122_m2": 10.8, + "in123": 6.17, + "in123_m1": 47.4, + "in124": 3.12, + "in124_m1": 3.7, + "in125": 2.36, + "in125_m1": 12.2, + "in126": 1.53, + "in126_m1": 1.64, + "in127": 1.09, + "in127_m1": 3.67, + "in128": 0.84, + "in128_m1": 0.72, + "in129": 0.61, + "in129_m1": 1.23, + "in130": 0.29, + "in130_m1": 0.54, + "in130_m2": 0.54, + "in131": 0.28, + "in131_m1": 0.35, + "in131_m2": 0.32, + "in132": 0.207, + "in133": 0.165, + "in133_m1": 0.18, + "in134": 0.14, + "in135": 0.092, + "sn99": 0.005, + "sn100": 0.86, + "sn101": 1.7, + "sn102": 4.5, + "sn103": 7.0, + "sn104": 20.8, + "sn105": 34.0, + "sn106": 115.0, + "sn107": 174.0, + "sn108": 618.0, + "sn109": 1080.0, + "sn110": 14796.0, + "sn111": 2118.0, + "sn113": 9943776.0, + "sn113_m1": 1284.0, + "sn117_m1": 1175040.0, + "sn119_m1": 25315200.0, + "sn121": 97308.0, + "sn121_m1": 1385380000.0, + "sn123": 11162880.0, + "sn123_m1": 2403.6, + "sn125": 832896.0, + "sn125_m1": 571.2, + "sn126": 7258250000000.0, + "sn127": 7560.0, + "sn127_m1": 247.8, + "sn128": 3544.2, + "sn128_m1": 6.5, + "sn129": 133.8, + "sn129_m1": 414.0, + "sn130": 223.2, + "sn130_m1": 102.0, + "sn131": 56.0, + "sn131_m1": 58.4, + "sn132": 39.7, + "sn133": 1.46, + "sn134": 1.05, + "sn135": 0.53, + "sn136": 0.25, + "sn137": 0.19, + "sb103": 1.5e-06, + "sb104": 0.46, + "sb105": 1.22, + "sb106": 0.6, + "sb107": 4.0, + "sb108": 7.4, + "sb109": 17.0, + "sb110": 23.0, + "sb111": 75.0, + "sb112": 51.4, + "sb113": 400.2, + "sb114": 209.4, + "sb115": 1926.0, + "sb116": 948.0, + "sb116_m1": 3618.0, + "sb117": 10080.0, + "sb118": 216.0, + "sb118_m1": 18000.0, + "sb119": 137484.0, + "sb119_m1": 0.85, + "sb120": 953.4, + "sb120_m1": 497664.0, + "sb122": 235336.3, + "sb122_m1": 251.46, + "sb124": 5201280.0, + "sb124_m1": 93.0, + "sb124_m2": 1212.0, + "sb125": 87053530.0, + "sb126": 1067040.0, + "sb126_m1": 1149.0, + "sb126_m2": 11.0, + "sb127": 332640.0, + "sb128": 32436.0, + "sb128_m1": 624.0, + "sb129": 15840.0, + "sb129_m1": 1062.0, + "sb130": 2370.0, + "sb130_m1": 378.0, + "sb131": 1381.8, + "sb132": 167.4, + "sb132_m1": 246.0, + "sb133": 150.0, + "sb134": 0.78, + "sb134_m1": 10.07, + "sb135": 1.679, + "sb136": 0.923, + "sb137": 0.45, + "sb138": 0.168, + "sb139": 0.127, + "te105": 6.2e-07, + "te106": 6e-05, + "te107": 0.0031, + "te108": 2.1, + "te109": 4.6, + "te110": 18.6, + "te111": 19.3, + "te112": 120.0, + "te113": 102.0, + "te114": 912.0, + "te115": 348.0, + "te115_m1": 402.0, + "te116": 8964.0, + "te117": 3720.0, + "te117_m1": 0.103, + "te118": 518400.0, + "te119": 57780.0, + "te119_m1": 406080.0, + "te121": 1656288.0, + "te121_m1": 14186880.0, + "te123_m1": 10298880.0, + "te125_m1": 4959360.0, + "te127": 33660.0, + "te127_m1": 9417600.0, + "te128": 2.77707e26, + "te129": 4176.0, + "te129_m1": 2903040.0, + "te131": 1500.0, + "te131_m1": 119700.0, + "te132": 276825.6, + "te133": 750.0, + "te133_m1": 3324.0, + "te134": 2508.0, + "te135": 19.0, + "te136": 17.5, + "te137": 2.49, + "te138": 1.4, + "te139": 0.347, + "te140": 0.304, + "te141": 0.213, + "te142": 0.2, + "i108": 0.036, + "i109": 0.000103, + "i110": 0.65, + "i111": 2.5, + "i112": 3.42, + "i113": 6.6, + "i114": 2.1, + "i114_m1": 6.2, + "i115": 78.0, + "i116": 2.91, + "i117": 133.2, + "i118": 822.0, + "i118_m1": 510.0, + "i119": 1146.0, + "i120": 4896.0, + "i120_m1": 3180.0, + "i121": 7632.0, + "i122": 217.8, + "i123": 47604.24, + "i124": 360806.4, + "i125": 5132160.0, + "i126": 1117152.0, + "i128": 1499.4, + "i129": 495454000000000.0, + "i130": 44496.0, + "i130_m1": 530.4, + "i131": 693377.3, + "i132": 8262.0, + "i132_m1": 4993.2, + "i133": 74880.0, + "i133_m1": 9.0, + "i134": 3150.0, + "i134_m1": 211.2, + "i135": 23652.0, + "i136": 83.4, + "i136_m1": 46.9, + "i137": 24.5, + "i138": 6.23, + "i139": 2.28, + "i140": 0.86, + "i141": 0.43, + "i142": 0.222, + "i143": 0.296, + "i144": 0.194, + "i145": 0.127, + "xe110": 0.093, + "xe111": 0.81, + "xe112": 2.7, + "xe113": 2.74, + "xe114": 10.0, + "xe115": 18.0, + "xe116": 59.0, + "xe117": 61.0, + "xe118": 228.0, + "xe119": 348.0, + "xe120": 2400.0, + "xe121": 2406.0, + "xe122": 72360.0, + "xe123": 7488.0, + "xe125": 60840.0, + "xe125_m1": 56.9, + "xe127": 3144960.0, + "xe127_m1": 69.2, + "xe129_m1": 767232.0, + "xe131_m1": 1022976.0, + "xe132_m1": 0.00839, + "xe133": 452995.2, + "xe133_m1": 189216.0, + "xe134_m1": 0.29, + "xe135": 32904.0, + "xe135_m1": 917.4, + "xe137": 229.08, + "xe138": 844.8, + "xe139": 39.68, + "xe140": 13.6, + "xe141": 1.73, + "xe142": 1.23, + "xe143": 0.3, + "xe144": 1.15, + "xe145": 0.188, + "xe146": 0.369, + "xe147": 0.1, + "cs112": 0.0005, + "cs113": 1.67e-05, + "cs114": 0.57, + "cs115": 1.4, + "cs116": 0.7, + "cs116_m1": 3.85, + "cs117": 8.4, + "cs117_m1": 6.5, + "cs118": 14.0, + "cs118_m1": 17.0, + "cs119": 43.0, + "cs119_m1": 30.4, + "cs120": 61.3, + "cs120_m1": 57.0, + "cs121": 155.0, + "cs121_m1": 122.0, + "cs122": 21.18, + "cs122_m1": 0.36, + "cs122_m2": 222.0, + "cs123": 352.8, + "cs123_m1": 1.64, + "cs124": 30.8, + "cs124_m1": 6.3, + "cs125": 2802.0, + "cs125_m1": 0.0009, + "cs126": 98.4, + "cs127": 22500.0, + "cs128": 217.2, + "cs129": 115416.0, + "cs130": 1752.6, + "cs130_m1": 207.6, + "cs131": 837129.6, + "cs132": 559872.0, + "cs134": 65172760.0, + "cs134_m1": 10483.2, + "cs135": 72582500000000.0, + "cs135_m1": 3180.0, + "cs136": 1137024.0, + "cs136_m1": 19.0, + "cs137": 949252600.0, + "cs138": 2004.6, + "cs138_m1": 174.6, + "cs139": 556.2, + "cs140": 63.7, + "cs141": 24.84, + "cs142": 1.684, + "cs143": 1.791, + "cs144": 0.994, + "cs144_m1": 1.0, + "cs145": 0.587, + "cs146": 0.321, + "cs147": 0.23, + "cs148": 0.146, + "cs149": 0.05, + "cs150": 0.05, + "cs151": 0.05, + "ba114": 0.43, + "ba115": 0.45, + "ba116": 1.3, + "ba117": 1.75, + "ba118": 5.5, + "ba119": 5.4, + "ba120": 24.0, + "ba121": 29.7, + "ba122": 117.0, + "ba123": 162.0, + "ba124": 660.0, + "ba125": 210.0, + "ba126": 6000.0, + "ba127": 762.0, + "ba127_m1": 1.9, + "ba128": 209952.0, + "ba129": 8028.0, + "ba129_m1": 7776.0, + "ba130_m1": 0.0094, + "ba131": 993600.0, + "ba131_m1": 876.0, + "ba133": 331862400.0, + "ba133_m1": 140040.0, + "ba135_m1": 103320.0, + "ba136_m1": 0.3084, + "ba137_m1": 153.12, + "ba139": 4983.6, + "ba140": 1101833.0, + "ba141": 1096.2, + "ba142": 636.0, + "ba143": 14.5, + "ba144": 11.5, + "ba145": 4.31, + "ba146": 2.22, + "ba147": 0.894, + "ba148": 0.612, + "ba149": 0.344, + "ba150": 0.3, + "ba151": 0.259, + "ba152": 0.228, + "ba153": 0.158, + "la117": 0.0235, + "la117_m1": 0.01, + "la118": 1.0, + "la119": 2.0, + "la120": 2.8, + "la121": 5.3, + "la122": 8.6, + "la123": 17.0, + "la124": 29.21, + "la124_m1": 21.0, + "la125": 64.8, + "la125_m1": 0.4, + "la126": 54.0, + "la126_m1": 50.0, + "la127": 306.0, + "la127_m1": 222.0, + "la128": 310.8, + "la128_m1": 60.0, + "la129": 696.0, + "la129_m1": 0.56, + "la130": 522.0, + "la131": 3540.0, + "la132": 17280.0, + "la132_m1": 1458.0, + "la133": 14083.2, + "la134": 387.0, + "la135": 70200.0, + "la136": 592.2, + "la136_m1": 0.114, + "la137": 1893460000000.0, + "la138": 3.21888e18, + "la140": 145026.7, + "la141": 14112.0, + "la142": 5466.0, + "la143": 852.0, + "la144": 40.8, + "la145": 24.8, + "la146": 6.27, + "la146_m1": 10.0, + "la147": 4.06, + "la148": 1.26, + "la149": 1.05, + "la150": 0.86, + "la151": 0.778, + "la152": 0.451, + "la153": 0.342, + "la154": 0.228, + "la155": 0.184, + "ce119": 0.2, + "ce120": 0.25, + "ce121": 1.1, + "ce122": 2.73, + "ce123": 3.8, + "ce124": 6.0, + "ce125": 10.2, + "ce126": 51.0, + "ce127": 31.0, + "ce127_m1": 28.6, + "ce128": 235.8, + "ce129": 210.0, + "ce130": 1374.0, + "ce131": 618.0, + "ce131_m1": 324.0, + "ce132": 12636.0, + "ce132_m1": 0.0094, + "ce133": 5820.0, + "ce133_m1": 17640.0, + "ce134": 273024.0, + "ce135": 63720.0, + "ce135_m1": 20.0, + "ce137": 32400.0, + "ce137_m1": 123840.0, + "ce138_m1": 0.00865, + "ce139": 11892180.0, + "ce139_m1": 54.8, + "ce141": 2808691.0, + "ce143": 118940.4, + "ce144": 24616220.0, + "ce145": 180.6, + "ce146": 811.2, + "ce147": 56.4, + "ce148": 56.0, + "ce149": 5.3, + "ce150": 4.0, + "ce151": 1.76, + "ce152": 1.4, + "ce153": 0.979, + "ce154": 0.775, + "ce155": 0.471, + "ce156": 0.369, + "ce157": 0.2428, + "pr121": 1.4, + "pr122": 0.5, + "pr123": 0.8, + "pr124": 1.2, + "pr125": 3.3, + "pr126": 3.14, + "pr127": 4.2, + "pr128": 2.85, + "pr129": 32.0, + "pr130": 40.0, + "pr131": 90.6, + "pr131_m1": 5.73, + "pr132": 96.0, + "pr133": 390.0, + "pr134": 1020.0, + "pr134_m1": 660.0, + "pr135": 1440.0, + "pr136": 786.0, + "pr137": 4608.0, + "pr138": 87.0, + "pr138_m1": 7632.0, + "pr139": 15876.0, + "pr140": 203.4, + "pr142": 68832.0, + "pr142_m1": 876.0, + "pr143": 1172448.0, + "pr144": 1036.8, + "pr144_m1": 432.0, + "pr145": 21542.4, + "pr146": 1449.0, + "pr147": 804.0, + "pr148": 137.4, + "pr148_m1": 120.6, + "pr149": 135.6, + "pr150": 6.19, + "pr151": 18.9, + "pr152": 3.63, + "pr153": 4.28, + "pr154": 2.3, + "pr155": 0.852, + "pr156": 0.733, + "pr157": 0.598, + "pr158": 0.1342, + "pr159": 0.1055, + "nd124": 0.5, + "nd125": 0.6, + "nd126": 2e-07, + "nd127": 1.8, + "nd128": 5.0, + "nd129": 4.9, + "nd130": 21.0, + "nd131": 26.0, + "nd132": 94.0, + "nd133": 70.0, + "nd133_m1": 70.0, + "nd134": 510.0, + "nd135": 744.0, + "nd135_m1": 330.0, + "nd136": 3039.0, + "nd137": 2310.0, + "nd137_m1": 1.6, + "nd138": 18144.0, + "nd139": 1782.0, + "nd139_m1": 19800.0, + "nd140": 291168.0, + "nd141": 8964.0, + "nd141_m1": 62.0, + "nd144": 7.22669e22, + "nd147": 948672.0, + "nd149": 6220.8, + "nd150": 2.49305e26, + "nd151": 746.4, + "nd152": 684.0, + "nd153": 31.6, + "nd154": 25.9, + "nd155": 8.9, + "nd156": 5.49, + "nd157": 1.906, + "nd158": 1.331, + "nd159": 0.773, + "nd160": 0.5883, + "nd161": 0.4884, + "pm126": 0.5, + "pm127": 1.0, + "pm128": 1.0, + "pm129": 2.4, + "pm130": 2.6, + "pm131": 6.3, + "pm132": 6.2, + "pm133": 15.0, + "pm133_m1": 8.8, + "pm134": 5.0, + "pm134_m1": 22.0, + "pm135": 49.0, + "pm135_m1": 45.0, + "pm136": 47.0, + "pm136_m1": 107.0, + "pm137": 144.0, + "pm138": 10.0, + "pm138_m1": 194.4, + "pm139": 249.0, + "pm139_m1": 0.18, + "pm140": 357.0, + "pm140_m1": 357.0, + "pm141": 1254.0, + "pm142": 40.5, + "pm142_m1": 0.002, + "pm143": 22896000.0, + "pm144": 31363200.0, + "pm145": 558569500.0, + "pm146": 174513500.0, + "pm147": 82788210.0, + "pm148": 463795.2, + "pm148_m1": 3567456.0, + "pm149": 191088.0, + "pm150": 9648.0, + "pm151": 102240.0, + "pm152": 247.2, + "pm152_m1": 451.2, + "pm152_m2": 828.0, + "pm153": 315.0, + "pm154": 103.8, + "pm154_m1": 160.8, + "pm155": 41.5, + "pm156": 26.7, + "pm157": 10.56, + "pm158": 4.8, + "pm159": 1.47, + "pm160": 1.561, + "pm161": 1.065, + "pm162": 0.2679, + "pm163": 0.2, + "sm128": 0.5, + "sm129": 0.55, + "sm130": 1.0, + "sm131": 1.2, + "sm132": 4.0, + "sm133": 3.7, + "sm134": 9.5, + "sm135": 10.3, + "sm136": 47.0, + "sm137": 45.0, + "sm138": 186.0, + "sm139": 154.2, + "sm139_m1": 10.7, + "sm140": 889.2, + "sm141": 612.0, + "sm141_m1": 1356.0, + "sm142": 4349.4, + "sm143": 525.0, + "sm143_m1": 66.0, + "sm143_m2": 0.03, + "sm145": 29376000.0, + "sm146": 3250430000000000.0, + "sm147": 3.34511e18, + "sm148": 2.20903e23, + "sm151": 2840184000.0, + "sm153": 167400.0, + "sm153_m1": 0.0106, + "sm155": 1338.0, + "sm156": 33840.0, + "sm157": 482.0, + "sm158": 318.0, + "sm159": 11.37, + "sm160": 9.6, + "sm161": 4.8, + "sm162": 2.4, + "sm163": 1.748, + "sm164": 1.226, + "sm165": 0.764, + "eu130": 0.001, + "eu131": 0.0178, + "eu132": 0.1, + "eu133": 1.0, + "eu134": 0.5, + "eu135": 1.5, + "eu136": 3.8, + "eu136_m1": 3.3, + "eu136_m2": 3.8, + "eu137": 11.0, + "eu138": 12.1, + "eu139": 17.9, + "eu140": 1.51, + "eu140_m1": 0.125, + "eu141": 40.7, + "eu141_m1": 2.7, + "eu142": 2.34, + "eu142_m1": 73.38, + "eu143": 155.4, + "eu144": 10.2, + "eu145": 512352.0, + "eu146": 396576.0, + "eu147": 2082240.0, + "eu148": 4708800.0, + "eu149": 8043840.0, + "eu150": 1164480000.0, + "eu150_m1": 46080.0, + "eu152": 427195200.0, + "eu152_m1": 33521.76, + "eu152_m2": 5760.0, + "eu154": 271426900.0, + "eu154_m1": 2760.0, + "eu155": 149993300.0, + "eu156": 1312416.0, + "eu157": 54648.0, + "eu158": 2754.0, + "eu159": 1086.0, + "eu160": 38.0, + "eu161": 26.0, + "eu162": 10.6, + "eu163": 7.7, + "eu164": 2.844, + "eu165": 2.3, + "eu166": 0.4, + "eu167": 0.2, + "gd134": 0.4, + "gd135": 1.1, + "gd136": 2e-05, + "gd137": 2.2, + "gd138": 4.7, + "gd139": 5.8, + "gd139_m1": 4.8, + "gd140": 15.8, + "gd141": 14.0, + "gd141_m1": 24.5, + "gd142": 70.2, + "gd143": 39.0, + "gd143_m1": 110.0, + "gd144": 268.2, + "gd145": 1380.0, + "gd145_m1": 85.0, + "gd146": 4170528.0, + "gd147": 137016.0, + "gd148": 2354197000.0, + "gd149": 801792.0, + "gd150": 56488100000000.0, + "gd151": 10713600.0, + "gd152": 3.40822e21, + "gd153": 20770560.0, + "gd155_m1": 0.03197, + "gd159": 66524.4, + "gd161": 219.6, + "gd162": 504.0, + "gd163": 68.0, + "gd164": 45.0, + "gd165": 10.3, + "gd166": 4.8, + "gd167": 3.0, + "gd168": 0.3, + "gd169": 1.0, + "tb135": 0.995, + "tb136": 0.2, + "tb137": 0.6, + "tb138": 2e-07, + "tb139": 1.6, + "tb140": 2.4, + "tb141": 3.5, + "tb141_m1": 7.9, + "tb142": 0.597, + "tb142_m1": 0.303, + "tb143": 12.0, + "tb143_m1": 21.0, + "tb144": 1.0, + "tb144_m1": 4.25, + "tb145": 30.9, + "tb145_m1": 30.9, + "tb146": 8.0, + "tb146_m1": 23.0, + "tb146_m2": 0.00118, + "tb147": 5904.0, + "tb147_m1": 109.8, + "tb148": 3600.0, + "tb148_m1": 132.0, + "tb149": 14824.8, + "tb149_m1": 249.6, + "tb150": 12528.0, + "tb150_m1": 348.0, + "tb151": 63392.4, + "tb151_m1": 25.0, + "tb152": 63000.0, + "tb152_m1": 252.0, + "tb153": 202176.0, + "tb154": 77400.0, + "tb154_m1": 33840.0, + "tb154_m2": 81720.0, + "tb155": 459648.0, + "tb156": 462240.0, + "tb156_m1": 87840.0, + "tb156_m2": 19080.0, + "tb157": 2240590000.0, + "tb158": 5680368000.0, + "tb158_m1": 10.7, + "tb160": 6246720.0, + "tb161": 596678.4, + "tb162": 456.0, + "tb163": 1170.0, + "tb164": 180.0, + "tb165": 126.6, + "tb166": 25.1, + "tb167": 19.4, + "tb168": 8.2, + "tb169": 2.0, + "tb170": 3.0, + "tb171": 0.5, + "dy138": 0.2, + "dy139": 0.6, + "dy140": 0.84, + "dy141": 0.9, + "dy142": 2.3, + "dy143": 3.2, + "dy143_m1": 3.0, + "dy144": 9.1, + "dy145": 6.0, + "dy145_m1": 14.1, + "dy146": 29.0, + "dy146_m1": 0.15, + "dy147": 40.0, + "dy147_m1": 55.7, + "dy148": 198.0, + "dy149": 252.0, + "dy149_m1": 0.49, + "dy150": 430.2, + "dy151": 1074.0, + "dy152": 8568.0, + "dy153": 23040.0, + "dy154": 94672800000000.0, + "dy155": 35640.0, + "dy157": 29304.0, + "dy157_m1": 0.0216, + "dy159": 12476160.0, + "dy165": 8402.4, + "dy165_m1": 75.42, + "dy166": 293760.0, + "dy167": 372.0, + "dy168": 522.0, + "dy169": 39.0, + "dy170": 30.0, + "dy171": 6.0, + "dy172": 3.0, + "dy173": 2.0, + "ho140": 0.006, + "ho141": 0.0041, + "ho142": 0.4, + "ho143": 2e-07, + "ho144": 0.7, + "ho145": 2.4, + "ho146": 3.6, + "ho147": 5.8, + "ho148": 2.2, + "ho148_m1": 9.59, + "ho148_m2": 0.00236, + "ho149": 21.1, + "ho149_m1": 56.0, + "ho150": 72.0, + "ho150_m1": 23.3, + "ho151": 35.2, + "ho151_m1": 47.2, + "ho152": 161.8, + "ho152_m1": 50.0, + "ho153": 120.6, + "ho153_m1": 558.0, + "ho154": 705.6, + "ho154_m1": 186.0, + "ho155": 2880.0, + "ho155_m1": 0.00088, + "ho156": 3360.0, + "ho156_m1": 9.5, + "ho156_m2": 468.0, + "ho157": 756.0, + "ho158": 678.0, + "ho158_m1": 1680.0, + "ho158_m2": 1278.0, + "ho159": 1983.0, + "ho159_m1": 8.3, + "ho160": 1536.0, + "ho160_m1": 18072.0, + "ho160_m2": 3.0, + "ho161": 8928.0, + "ho161_m1": 6.76, + "ho162": 900.0, + "ho162_m1": 4020.0, + "ho163": 144218000000.0, + "ho163_m1": 1.09, + "ho164": 1740.0, + "ho164_m1": 2250.0, + "ho166": 96480.0, + "ho166_m1": 37869100000.0, + "ho167": 11160.0, + "ho168": 179.4, + "ho168_m1": 132.0, + "ho169": 283.2, + "ho170": 165.6, + "ho170_m1": 43.0, + "ho171": 53.0, + "ho172": 25.0, + "ho173": 10.0, + "ho174": 8.0, + "ho175": 5.0, + "er143": 0.2, + "er144": 2e-07, + "er146": 1.7, + "er147": 2.5, + "er147_m1": 2.5, + "er148": 4.6, + "er149": 4.0, + "er149_m1": 8.9, + "er150": 18.5, + "er151": 23.5, + "er151_m1": 0.58, + "er152": 10.3, + "er153": 37.1, + "er154": 223.8, + "er155": 318.0, + "er156": 1170.0, + "er157": 1119.0, + "er157_m1": 0.076, + "er158": 8244.0, + "er159": 2160.0, + "er160": 102888.0, + "er161": 11556.0, + "er163": 4500.0, + "er165": 37296.0, + "er167_m1": 2.269, + "er169": 811468.8, + "er171": 27057.6, + "er172": 177480.0, + "er173": 84.0, + "er174": 192.0, + "er175": 72.0, + "er176": 20.0, + "er177": 3.0, + "tm145": 3.1e-06, + "tm146": 0.08, + "tm146_m1": 0.2, + "tm147": 0.58, + "tm148": 0.7, + "tm149": 0.9, + "tm150": 2.2, + "tm150_m1": 0.0052, + "tm151": 4.17, + "tm151_m1": 4.51e-07, + "tm152": 8.0, + "tm152_m1": 5.2, + "tm153": 1.48, + "tm153_m1": 2.5, + "tm154": 8.1, + "tm154_m1": 3.3, + "tm155": 21.6, + "tm155_m1": 45.0, + "tm156": 83.8, + "tm157": 217.8, + "tm158": 238.8, + "tm159": 547.8, + "tm160": 564.0, + "tm160_m1": 74.5, + "tm161": 1812.0, + "tm162": 1302.0, + "tm162_m1": 24.3, + "tm163": 6516.0, + "tm164": 120.0, + "tm164_m1": 306.0, + "tm165": 108216.0, + "tm166": 27720.0, + "tm166_m1": 0.34, + "tm167": 799200.0, + "tm168": 8043840.0, + "tm170": 11111040.0, + "tm171": 60590590.0, + "tm172": 228960.0, + "tm173": 29664.0, + "tm174": 324.0, + "tm175": 912.0, + "tm176": 114.0, + "tm177": 90.0, + "tm178": 30.0, + "tm179": 20.0, + "yb148": 0.25, + "yb149": 0.7, + "yb150": 2e-07, + "yb151": 1.6, + "yb151_m1": 1.6, + "yb152": 3.04, + "yb153": 4.2, + "yb154": 0.409, + "yb155": 1.793, + "yb156": 26.1, + "yb157": 38.6, + "yb158": 89.4, + "yb159": 100.2, + "yb160": 288.0, + "yb161": 252.0, + "yb162": 1132.2, + "yb163": 663.0, + "yb164": 4548.0, + "yb165": 594.0, + "yb166": 204120.0, + "yb167": 1050.0, + "yb169": 2766355.0, + "yb169_m1": 46.0, + "yb171_m1": 0.00525, + "yb175": 361584.0, + "yb175_m1": 0.0682, + "yb176_m1": 11.4, + "yb177": 6879.6, + "yb177_m1": 6.41, + "yb178": 4440.0, + "yb179": 480.0, + "yb180": 144.0, + "yb181": 60.0, + "lu150": 0.043, + "lu151": 0.0806, + "lu152": 0.7, + "lu153": 0.9, + "lu153_m1": 1.0, + "lu154": 2.0, + "lu154_m1": 1.12, + "lu155": 0.068, + "lu155_m1": 0.138, + "lu155_m2": 0.00269, + "lu156": 0.494, + "lu156_m1": 0.198, + "lu157": 6.8, + "lu157_m1": 4.79, + "lu158": 10.6, + "lu159": 12.1, + "lu160": 36.1, + "lu160_m1": 40.0, + "lu161": 77.0, + "lu161_m1": 0.0073, + "lu162": 82.2, + "lu162_m1": 90.0, + "lu162_m2": 114.0, + "lu163": 238.2, + "lu164": 188.4, + "lu165": 644.4, + "lu166": 159.0, + "lu166_m1": 84.6, + "lu166_m2": 127.2, + "lu167": 3090.0, + "lu167_m1": 60.0, + "lu168": 330.0, + "lu168_m1": 402.0, + "lu169": 122616.0, + "lu169_m1": 160.0, + "lu170": 173836.8, + "lu170_m1": 0.67, + "lu171": 711936.0, + "lu171_m1": 79.0, + "lu172": 578880.0, + "lu172_m1": 222.0, + "lu173": 43233910.0, + "lu174": 104455700.0, + "lu174_m1": 12268800.0, + "lu176": 1.18657e18, + "lu176_m1": 13086.0, + "lu177": 574300.8, + "lu177_m1": 13862020.0, + "lu177_m2": 390.0, + "lu178": 1704.0, + "lu178_m1": 1386.0, + "lu179": 16524.0, + "lu179_m1": 0.0031, + "lu180": 342.0, + "lu180_m1": 0.001, + "lu181": 210.0, + "lu182": 120.0, + "lu183": 58.0, + "lu184": 20.0, + "hf153": 6e-06, + "hf154": 2.0, + "hf155": 0.89, + "hf156": 0.023, + "hf157": 0.11, + "hf158": 2.85, + "hf159": 5.6, + "hf160": 13.6, + "hf161": 18.2, + "hf162": 39.4, + "hf163": 40.0, + "hf164": 111.0, + "hf165": 76.0, + "hf166": 406.2, + "hf167": 123.0, + "hf168": 1557.0, + "hf169": 194.4, + "hf170": 57636.0, + "hf171": 43560.0, + "hf171_m1": 29.5, + "hf172": 59012710.0, + "hf173": 84960.0, + "hf174": 6.31152e22, + "hf175": 6048000.0, + "hf177_m1": 1.09, + "hf177_m2": 3084.0, + "hf178_m1": 4.0, + "hf178_m2": 978285600.0, + "hf179_m1": 18.67, + "hf179_m2": 2164320.0, + "hf180_m1": 19800.0, + "hf181": 3662496.0, + "hf182": 280863000000000.0, + "hf182_m1": 3690.0, + "hf183": 3841.2, + "hf184": 14832.0, + "hf184_m1": 48.0, + "hf185": 210.0, + "hf186": 156.0, + "hf187": 30.0, + "hf188": 20.0, + "ta155": 0.0031, + "ta156": 0.144, + "ta156_m1": 0.36, + "ta157": 0.0101, + "ta157_m1": 0.0043, + "ta157_m2": 0.0017, + "ta158": 0.055, + "ta158_m1": 0.0367, + "ta159": 0.83, + "ta159_m1": 0.515, + "ta160": 1.55, + "ta160_m1": 1.7, + "ta161": 2.89, + "ta162": 3.57, + "ta163": 10.6, + "ta164": 14.2, + "ta165": 31.0, + "ta166": 34.4, + "ta167": 80.0, + "ta168": 120.0, + "ta169": 294.0, + "ta170": 405.6, + "ta171": 1398.0, + "ta172": 2208.0, + "ta173": 11304.0, + "ta174": 4104.0, + "ta175": 37800.0, + "ta176": 29124.0, + "ta176_m1": 0.0011, + "ta176_m2": 0.00097, + "ta177": 203616.0, + "ta178": 558.6, + "ta178_m1": 8496.0, + "ta178_m2": 0.058, + "ta179": 57434830.0, + "ta179_m1": 0.009, + "ta179_m2": 0.0541, + "ta180": 29354.4, + "ta182": 9913536.0, + "ta182_m1": 0.283, + "ta182_m2": 950.4, + "ta183": 440640.0, + "ta184": 31320.0, + "ta185": 2964.0, + "ta185_m1": 0.002, + "ta186": 630.0, + "ta187": 120.0, + "ta188": 20.0, + "ta189": 3.0, + "ta190": 0.3, + "w158": 0.00125, + "w159": 0.0073, + "w160": 0.091, + "w161": 0.409, + "w162": 1.36, + "w163": 2.8, + "w164": 6.3, + "w165": 5.1, + "w166": 19.2, + "w167": 19.9, + "w168": 53.0, + "w169": 74.0, + "w170": 145.2, + "w171": 142.8, + "w172": 396.0, + "w173": 456.0, + "w174": 1992.0, + "w175": 2112.0, + "w176": 9000.0, + "w177": 7920.0, + "w178": 1866240.0, + "w179": 2223.0, + "w179_m1": 384.0, + "w180": 5.68037e25, + "w180_m1": 0.00547, + "w181": 10471680.0, + "w183_m1": 5.2, + "w185": 6488640.0, + "w185_m1": 100.2, + "w186": 5.36e27, + "w186_m1": 0.003, + "w187": 86400.0, + "w188": 6028992.0, + "w189": 642.0, + "w190": 1800.0, + "w190_m1": 0.0031, + "w191": 20.0, + "w192": 10.0, + "re160": 0.00085, + "re161": 0.00037, + "re161_m1": 0.0156, + "re162": 0.107, + "re162_m1": 0.077, + "re163": 0.39, + "re163_m1": 0.214, + "re164": 0.53, + "re164_m1": 0.87, + "re165": 1.0, + "re165_m1": 2.1, + "re166": 2.25, + "re167": 5.9, + "re167_m1": 3.4, + "re168": 4.4, + "re169": 8.1, + "re169_m1": 15.1, + "re170": 9.2, + "re171": 15.2, + "re172": 55.0, + "re172_m1": 15.0, + "re173": 118.8, + "re174": 144.0, + "re175": 353.4, + "re176": 318.0, + "re177": 840.0, + "re178": 792.0, + "re179": 1170.0, + "re180": 146.4, + "re181": 71640.0, + "re182": 230400.0, + "re182_m1": 45720.0, + "re183": 6048000.0, + "re183_m1": 0.00104, + "re184": 3058560.0, + "re184_m1": 14601600.0, + "re186": 321261.1, + "re186_m1": 6311520000000.0, + "re187": 1.36644e18, + "re188": 61214.4, + "re188_m1": 1115.4, + "re189": 87480.0, + "re190": 186.0, + "re190_m1": 11520.0, + "re191": 588.0, + "re192": 16.0, + "re193": 51.9, + "re194": 1.0, + "os162": 0.00205, + "os163": 0.0055, + "os164": 0.021, + "os165": 0.071, + "os166": 0.199, + "os167": 0.81, + "os168": 2.1, + "os169": 3.43, + "os170": 7.37, + "os171": 8.3, + "os172": 19.2, + "os173": 22.4, + "os174": 44.0, + "os175": 84.0, + "os176": 216.0, + "os177": 180.0, + "os178": 300.0, + "os179": 390.0, + "os180": 1290.0, + "os181": 6300.0, + "os181_m1": 162.0, + "os182": 78624.0, + "os183": 46800.0, + "os183_m1": 35640.0, + "os185": 8087040.0, + "os186": 6.31152e22, + "os189_m1": 20916.0, + "os190_m1": 594.0, + "os191": 1330560.0, + "os191_m1": 47160.0, + "os192_m1": 5.9, + "os193": 108396.0, + "os194": 189345600.0, + "os195": 540.0, + "os196": 2094.0, + "ir164": 0.14, + "ir164_m1": 9.5e-05, + "ir165": 1e-06, + "ir166": 0.0105, + "ir166_m1": 0.0151, + "ir167": 0.0352, + "ir167_m1": 0.0257, + "ir168": 0.232, + "ir168_m1": 0.16, + "ir169": 0.64, + "ir169_m1": 0.281, + "ir170": 0.9, + "ir170_m1": 0.811, + "ir171": 3.5, + "ir171_m1": 1.4, + "ir172": 4.4, + "ir172_m1": 2.0, + "ir173": 9.0, + "ir173_m1": 2.2, + "ir174": 7.9, + "ir174_m1": 4.9, + "ir175": 9.0, + "ir176": 8.7, + "ir177": 30.0, + "ir178": 12.0, + "ir179": 79.0, + "ir180": 90.0, + "ir181": 294.0, + "ir182": 900.0, + "ir183": 3480.0, + "ir184": 11124.0, + "ir185": 51840.0, + "ir186": 59904.0, + "ir186_m1": 6840.0, + "ir187": 37800.0, + "ir187_m1": 0.0303, + "ir188": 149400.0, + "ir188_m1": 0.0042, + "ir189": 1140480.0, + "ir189_m1": 0.0133, + "ir189_m2": 0.0037, + "ir190": 1017792.0, + "ir190_m1": 4032.0, + "ir190_m2": 11113.2, + "ir191_m1": 4.899, + "ir191_m2": 5.5, + "ir192": 6378653.0, + "ir192_m1": 87.0, + "ir192_m2": 7605382000.0, + "ir193_m1": 909792.0, + "ir194": 69408.0, + "ir194_m1": 0.03185, + "ir194_m2": 14774400.0, + "ir195": 9000.0, + "ir195_m1": 13680.0, + "ir196": 52.0, + "ir196_m1": 5040.0, + "ir197": 348.0, + "ir197_m1": 534.0, + "ir198": 8.0, + "ir199": 6.5, + "pt166": 0.0003, + "pt167": 0.00078, + "pt168": 0.002, + "pt169": 0.007, + "pt170": 0.014, + "pt171": 0.051, + "pt172": 0.096, + "pt173": 0.382, + "pt174": 0.889, + "pt175": 2.53, + "pt176": 6.33, + "pt177": 10.6, + "pt178": 21.1, + "pt179": 21.2, + "pt180": 56.0, + "pt181": 52.0, + "pt182": 180.0, + "pt183": 390.0, + "pt183_m1": 43.0, + "pt184": 1038.0, + "pt184_m1": 0.00101, + "pt185": 4254.0, + "pt185_m1": 1980.0, + "pt186": 7488.0, + "pt187": 8460.0, + "pt188": 881280.0, + "pt189": 39132.0, + "pt190": 2.05124e19, + "pt191": 242092.8, + "pt193": 1577880000.0, + "pt193_m1": 374112.0, + "pt195_m1": 346464.0, + "pt197": 71609.4, + "pt197_m1": 5724.6, + "pt199": 1848.0, + "pt199_m1": 13.6, + "pt200": 45360.0, + "pt201": 150.0, + "pt202": 158400.0, + "au169": 0.00015, + "au170": 0.000291, + "au170_m1": 0.00062, + "au171": 1.9e-05, + "au171_m1": 0.00102, + "au172": 0.0047, + "au173": 0.025, + "au173_m1": 0.014, + "au174": 0.139, + "au174_m1": 0.1629, + "au175": 0.1, + "au175_m1": 0.156, + "au176": 1.05, + "au176_m1": 1.36, + "au177": 1.462, + "au177_m1": 1.18, + "au178": 2.6, + "au179": 3.3, + "au180": 8.1, + "au181": 13.7, + "au182": 15.6, + "au183": 42.8, + "au184": 20.6, + "au184_m1": 47.6, + "au185": 255.0, + "au186": 642.0, + "au187": 504.0, + "au187_m1": 2.3, + "au188": 530.4, + "au189": 1722.0, + "au189_m1": 275.4, + "au190": 2568.0, + "au190_m1": 0.125, + "au191": 11448.0, + "au191_m1": 0.92, + "au192": 17784.0, + "au192_m1": 0.029, + "au192_m2": 0.16, + "au193": 63540.0, + "au193_m1": 3.9, + "au194": 136872.0, + "au194_m1": 0.6, + "au194_m2": 0.42, + "au195": 16078870.0, + "au195_m1": 30.5, + "au196": 532820.2, + "au196_m1": 8.1, + "au196_m2": 34560.0, + "au197_m1": 7.73, + "au198": 232822.1, + "au198_m1": 196300.8, + "au199": 271209.6, + "au200": 2904.0, + "au200_m1": 67320.0, + "au201": 1560.0, + "au202": 28.4, + "au203": 60.0, + "au204": 39.8, + "au205": 31.0, + "hg171": 6.9e-05, + "hg172": 0.000365, + "hg173": 0.0007, + "hg174": 0.0019, + "hg175": 0.0107, + "hg176": 0.0203, + "hg177": 0.1273, + "hg178": 0.269, + "hg179": 1.08, + "hg180": 2.58, + "hg181": 3.6, + "hg182": 10.83, + "hg183": 9.4, + "hg184": 30.9, + "hg185": 49.1, + "hg185_m1": 21.6, + "hg186": 82.8, + "hg187": 144.0, + "hg187_m1": 114.0, + "hg188": 195.0, + "hg189": 456.0, + "hg189_m1": 516.0, + "hg190": 1200.0, + "hg191": 2940.0, + "hg191_m1": 3048.0, + "hg192": 17460.0, + "hg193": 13680.0, + "hg193_m1": 42480.0, + "hg194": 14011600000.0, + "hg195": 37908.0, + "hg195_m1": 149760.0, + "hg197": 230904.0, + "hg197_m1": 85680.0, + "hg199_m1": 2560.2, + "hg203": 4025722.0, + "hg205": 308.4, + "hg205_m1": 0.00109, + "hg206": 499.2, + "hg207": 174.0, + "hg208": 2490.0, + "hg209": 36.5, + "hg210": 146.0, + "tl176": 0.006, + "tl177": 0.018, + "tl178": 0.06, + "tl179": 0.23, + "tl179_m1": 0.0017, + "tl180": 1.09, + "tl181": 3.2, + "tl181_m1": 0.0014, + "tl182": 3.1, + "tl183": 6.9, + "tl183_m1": 0.0533, + "tl184": 11.0, + "tl185": 19.5, + "tl185_m1": 1.93, + "tl186": 27.5, + "tl186_m1": 2.9, + "tl187": 51.0, + "tl187_m1": 15.6, + "tl188": 71.0, + "tl188_m1": 71.0, + "tl188_m2": 0.041, + "tl189": 138.0, + "tl189_m1": 84.0, + "tl190": 222.0, + "tl190_m1": 156.0, + "tl191": 1200.0, + "tl191_m1": 313.2, + "tl192": 576.0, + "tl192_m1": 648.0, + "tl193": 1296.0, + "tl193_m1": 126.6, + "tl194": 1980.0, + "tl194_m1": 1968.0, + "tl195": 4176.0, + "tl195_m1": 3.6, + "tl196": 6624.0, + "tl196_m1": 5076.0, + "tl197": 10224.0, + "tl197_m1": 0.54, + "tl198": 19080.0, + "tl198_m1": 6732.0, + "tl198_m2": 0.0321, + "tl199": 26712.0, + "tl199_m1": 0.0284, + "tl200": 93960.0, + "tl200_m1": 0.034, + "tl201": 262837.4, + "tl201_m1": 0.00201, + "tl202": 1063584.0, + "tl204": 119382400.0, + "tl206": 252.12, + "tl206_m1": 224.4, + "tl207": 286.2, + "tl207_m1": 1.33, + "tl208": 183.18, + "tl209": 132.0, + "tl210": 78.0, + "tl211": 60.0, + "tl212": 67.0, + "pb178": 0.00023, + "pb179": 0.003, + "pb180": 0.0045, + "pb181": 0.036, + "pb181_m1": 0.045, + "pb182": 0.0575, + "pb183": 0.535, + "pb183_m1": 0.415, + "pb184": 0.49, + "pb185": 6.3, + "pb185_m1": 4.3, + "pb186": 4.82, + "pb187": 15.2, + "pb187_m1": 18.3, + "pb188": 25.1, + "pb189": 39.0, + "pb189_m1": 50.0, + "pb190": 71.0, + "pb191": 79.8, + "pb191_m1": 130.8, + "pb192": 210.0, + "pb193": 120.0, + "pb193_m1": 348.0, + "pb194": 720.0, + "pb195": 900.0, + "pb195_m1": 900.0, + "pb196": 2220.0, + "pb197": 480.0, + "pb197_m1": 2580.0, + "pb198": 8640.0, + "pb199": 5400.0, + "pb199_m1": 732.0, + "pb200": 77400.0, + "pb201": 33588.0, + "pb201_m1": 60.8, + "pb202": 1656770000000.0, + "pb202_m1": 12744.0, + "pb203": 186912.0, + "pb203_m1": 6.21, + "pb203_m2": 0.48, + "pb204": 4.4e24, + "pb204_m1": 4015.8, + "pb205": 545946000000000.0, + "pb205_m1": 0.00555, + "pb207_m1": 0.806, + "pb209": 11710.8, + "pb210": 700578700.0, + "pb211": 2166.0, + "pb212": 38304.0, + "pb213": 612.0, + "pb214": 1608.0, + "pb215": 36.0, + "bi184": 0.013, + "bi184_m1": 0.0066, + "bi185": 5.8e-05, + "bi186": 0.015, + "bi186_m1": 0.0098, + "bi187": 0.032, + "bi187_m1": 0.00031, + "bi188": 0.06, + "bi188_m1": 0.265, + "bi189": 0.674, + "bi189_m1": 0.005, + "bi190": 6.3, + "bi190_m1": 6.2, + "bi191": 12.4, + "bi191_m1": 0.125, + "bi192": 34.6, + "bi192_m1": 39.6, + "bi193": 63.6, + "bi193_m1": 3.2, + "bi194": 95.0, + "bi194_m1": 125.0, + "bi194_m2": 115.0, + "bi195": 183.0, + "bi195_m1": 87.0, + "bi196": 308.0, + "bi196_m1": 0.6, + "bi196_m2": 240.0, + "bi197": 559.8, + "bi197_m1": 302.4, + "bi198": 618.0, + "bi198_m1": 696.0, + "bi198_m2": 7.7, + "bi199": 1620.0, + "bi199_m1": 1482.0, + "bi200": 2184.0, + "bi200_m1": 1860.0, + "bi200_m2": 0.4, + "bi201": 6180.0, + "bi201_m1": 3450.0, + "bi202": 6156.0, + "bi203": 42336.0, + "bi203_m1": 0.305, + "bi204": 40392.0, + "bi204_m1": 0.013, + "bi204_m2": 0.00107, + "bi205": 1322784.0, + "bi206": 539395.2, + "bi207": 995642300.0, + "bi208": 11613200000000.0, + "bi208_m1": 0.00258, + "bi209": 5.99594e26, + "bi210": 433036.8, + "bi210_m1": 95935100000000.0, + "bi211": 128.4, + "bi212": 3633.0, + "bi212_m1": 1500.0, + "bi212_m2": 420.0, + "bi213": 2735.4, + "bi214": 1194.0, + "bi215": 462.0, + "bi215_m1": 36.4, + "bi216": 135.0, + "bi217": 98.5, + "bi218": 33.0, + "po188": 0.000425, + "po189": 0.0035, + "po190": 0.00245, + "po191": 0.022, + "po191_m1": 0.093, + "po192": 0.0332, + "po193": 0.37, + "po193_m1": 0.373, + "po194": 0.392, + "po195": 4.64, + "po195_m1": 1.92, + "po196": 5.8, + "po197": 84.0, + "po197_m1": 32.0, + "po198": 106.2, + "po199": 328.2, + "po199_m1": 250.2, + "po200": 690.6, + "po201": 936.0, + "po201_m1": 537.6, + "po202": 2676.0, + "po203": 2202.0, + "po203_m1": 45.0, + "po204": 12708.0, + "po205": 6264.0, + "po205_m1": 0.000645, + "po205_m2": 0.0574, + "po206": 760320.0, + "po207": 20880.0, + "po207_m1": 2.79, + "po208": 91453920.0, + "po209": 3218880000.0, + "po210": 11955690.0, + "po211": 0.516, + "po211_m1": 25.2, + "po212": 2.99e-07, + "po212_m1": 45.1, + "po213": 4.2e-06, + "po214": 0.0001643, + "po215": 0.001781, + "po216": 0.145, + "po217": 1.53, + "po218": 185.88, + "po219": 3e-07, + "po220": 3e-07, + "at193": 0.0285, + "at194": 0.04, + "at194_m1": 0.25, + "at195": 0.328, + "at195_m1": 0.147, + "at196": 0.388, + "at196_m1": 1.1e-05, + "at197": 0.388, + "at197_m1": 2.0, + "at198": 4.2, + "at198_m1": 1.0, + "at199": 7.03, + "at200": 43.0, + "at200_m1": 47.0, + "at200_m2": 7.9, + "at201": 85.2, + "at202": 184.0, + "at202_m1": 182.0, + "at202_m2": 0.46, + "at203": 444.0, + "at204": 553.2, + "at204_m1": 0.108, + "at205": 1614.0, + "at206": 1836.0, + "at207": 6480.0, + "at208": 5868.0, + "at209": 19476.0, + "at210": 29160.0, + "at211": 25970.4, + "at212": 0.314, + "at212_m1": 0.119, + "at213": 1.25e-07, + "at214": 5.58e-07, + "at215": 0.0001, + "at216": 0.0003, + "at217": 0.0323, + "at218": 1.5, + "at219": 56.0, + "at220": 222.6, + "at221": 138.0, + "at222": 54.0, + "at223": 50.0, + "rn195": 0.0065, + "rn195_m1": 0.005, + "rn196": 0.0046, + "rn197": 0.066, + "rn197_m1": 0.021, + "rn198": 0.065, + "rn199": 0.59, + "rn199_m1": 0.31, + "rn200": 1.075, + "rn201": 7.0, + "rn201_m1": 3.8, + "rn202": 9.7, + "rn203": 44.0, + "rn203_m1": 26.9, + "rn204": 70.2, + "rn205": 170.0, + "rn206": 340.2, + "rn207": 555.0, + "rn208": 1461.0, + "rn209": 1728.0, + "rn210": 8640.0, + "rn211": 52560.0, + "rn212": 1434.0, + "rn213": 0.025, + "rn214": 2.7e-07, + "rn215": 2.3e-06, + "rn216": 4.5e-05, + "rn217": 0.00054, + "rn218": 0.035, + "rn219": 3.96, + "rn220": 55.6, + "rn221": 1542.0, + "rn222": 330350.4, + "rn223": 1458.0, + "rn224": 6420.0, + "rn225": 279.6, + "rn226": 444.0, + "rn227": 20.8, + "rn228": 65.0, + "fr199": 0.015, + "fr200": 0.049, + "fr201": 0.069, + "fr202": 0.3, + "fr202_m1": 0.29, + "fr203": 0.55, + "fr204": 1.7, + "fr204_m1": 2.6, + "fr204_m2": 1.0, + "fr205": 3.8, + "fr206": 16.0, + "fr206_m1": 16.0, + "fr206_m2": 0.7, + "fr207": 14.8, + "fr208": 59.1, + "fr209": 50.0, + "fr210": 190.8, + "fr211": 186.0, + "fr212": 1200.0, + "fr213": 34.82, + "fr214": 0.005, + "fr214_m1": 0.00335, + "fr215": 8.6e-08, + "fr216": 7e-07, + "fr217": 1.9e-05, + "fr218": 0.001, + "fr218_m1": 0.022, + "fr219": 0.02, + "fr220": 27.4, + "fr221": 294.0, + "fr222": 852.0, + "fr223": 1320.0, + "fr224": 199.8, + "fr225": 237.0, + "fr226": 49.0, + "fr227": 148.2, + "fr228": 38.0, + "fr229": 50.2, + "fr230": 19.1, + "fr231": 17.6, + "fr232": 5.5, + "ra202": 0.0275, + "ra203": 0.031, + "ra203_m1": 0.025, + "ra204": 0.0605, + "ra205": 0.22, + "ra205_m1": 0.18, + "ra206": 0.24, + "ra207": 1.3, + "ra207_m1": 0.055, + "ra208": 1.3, + "ra209": 4.6, + "ra210": 3.7, + "ra211": 13.0, + "ra212": 13.0, + "ra213": 163.8, + "ra213_m1": 0.0021, + "ra214": 2.46, + "ra215": 0.00155, + "ra216": 1.82e-07, + "ra217": 1.6e-06, + "ra218": 2.52e-05, + "ra219": 0.01, + "ra220": 0.018, + "ra221": 28.0, + "ra222": 36.17, + "ra223": 987552.0, + "ra224": 316224.0, + "ra225": 1287360.0, + "ra226": 50492200000.0, + "ra227": 2532.0, + "ra228": 181456200.0, + "ra229": 240.0, + "ra230": 5580.0, + "ra231": 103.0, + "ra232": 252.0, + "ra233": 30.0, + "ra234": 30.0, + "ac206": 0.024, + "ac206_m1": 0.0395, + "ac207": 0.027, + "ac208": 0.095, + "ac208_m1": 0.025, + "ac209": 0.098, + "ac210": 0.35, + "ac211": 0.21, + "ac212": 0.93, + "ac213": 0.8, + "ac214": 8.2, + "ac215": 0.17, + "ac216": 0.00044, + "ac216_m1": 0.000441, + "ac217": 6.9e-08, + "ac218": 1.08e-06, + "ac219": 1.18e-05, + "ac220": 0.0264, + "ac221": 0.052, + "ac222": 5.0, + "ac222_m1": 63.0, + "ac223": 126.0, + "ac224": 10008.0, + "ac225": 864000.0, + "ac226": 105732.0, + "ac227": 687072100.0, + "ac228": 22140.0, + "ac229": 3762.0, + "ac230": 122.0, + "ac231": 450.0, + "ac232": 119.0, + "ac233": 145.0, + "ac234": 44.0, + "ac235": 60.0, + "ac236": 120.0, + "th209": 0.0065, + "th210": 0.016, + "th211": 0.05, + "th212": 0.035, + "th213": 0.14, + "th214": 0.1, + "th215": 1.2, + "th216": 0.026, + "th217": 0.000251, + "th218": 1.17e-07, + "th219": 1.05e-06, + "th220": 9.7e-06, + "th221": 0.00173, + "th222": 0.002237, + "th223": 0.6, + "th224": 1.05, + "th225": 523.2, + "th226": 1834.2, + "th227": 1613952.0, + "th228": 60338130.0, + "th229": 231633000000.0, + "th230": 2378810000000.0, + "th231": 91872.0, + "th232": 4.43384e17, + "th233": 1338.0, + "th234": 2082240.0, + "th235": 426.0, + "th236": 2238.0, + "th237": 282.0, + "th238": 564.0, + "pa212": 0.0051, + "pa213": 0.0053, + "pa214": 0.017, + "pa215": 0.014, + "pa216": 0.16, + "pa217": 0.0036, + "pa217_m1": 0.0012, + "pa218": 0.000113, + "pa219": 5.3e-08, + "pa220": 7.8e-07, + "pa221": 5.9e-06, + "pa222": 0.0033, + "pa223": 0.0051, + "pa224": 0.79, + "pa225": 1.7, + "pa226": 108.0, + "pa227": 2298.0, + "pa228": 79200.0, + "pa229": 129600.0, + "pa230": 1503360.0, + "pa231": 1033830000000.0, + "pa232": 114048.0, + "pa233": 2330640.0, + "pa234": 24120.0, + "pa234_m1": 69.54, + "pa235": 1466.4, + "pa236": 546.0, + "pa237": 522.0, + "pa238": 136.2, + "pa239": 6480.0, + "pa240": 120.0, + "u217": 0.0235, + "u218": 0.000545, + "u219": 4.2e-05, + "u220": 6e-08, + "u222": 1.3e-06, + "u223": 1.8e-05, + "u224": 0.0009, + "u225": 0.084, + "u226": 0.35, + "u227": 66.0, + "u228": 546.0, + "u229": 3480.0, + "u230": 1797120.0, + "u231": 362880.0, + "u232": 2174319000.0, + "u233": 5023970000000.0, + "u234": 7747390000000.0, + "u235": 2.22102e16, + "u235_m1": 1560.0, + "u236": 739079000000000.0, + "u237": 583200.0, + "u238": 1.40999e17, + "u239": 1407.0, + "u240": 50760.0, + "u241": 300.0, + "u242": 1008.0, + "np225": 2e-06, + "np226": 0.035, + "np227": 0.51, + "np228": 61.4, + "np229": 240.0, + "np230": 276.0, + "np231": 2928.0, + "np232": 882.0, + "np233": 2172.0, + "np234": 380160.0, + "np235": 34231680.0, + "np236": 4828310000000.0, + "np236_m1": 81000.0, + "np237": 67659500000000.0, + "np238": 182908.8, + "np239": 203558.4, + "np240": 3714.0, + "np240_m1": 433.2, + "np241": 834.0, + "np242": 132.0, + "np242_m1": 330.0, + "np243": 111.0, + "np244": 137.4, + "pu228": 1.85, + "pu229": 112.0, + "pu230": 102.0, + "pu231": 516.0, + "pu232": 2028.0, + "pu233": 1254.0, + "pu234": 31680.0, + "pu235": 1518.0, + "pu236": 90191620.0, + "pu237": 3943296.0, + "pu237_m1": 0.18, + "pu238": 2767602000.0, + "pu239": 760854000000.0, + "pu240": 207049000000.0, + "pu241": 450958100.0, + "pu242": 11786800000000.0, + "pu243": 17841.6, + "pu244": 2559320000000000.0, + "pu245": 37800.0, + "pu246": 936576.0, + "pu247": 196128.0, + "am231": 10.0, + "am232": 79.0, + "am233": 192.0, + "am234": 139.2, + "am235": 618.0, + "am236": 216.0, + "am237": 4416.0, + "am238": 5880.0, + "am239": 42840.0, + "am240": 182880.0, + "am241": 13651800000.0, + "am242": 57672.0, + "am242_m1": 4449622000.0, + "am242_m2": 0.014, + "am243": 232580000000.0, + "am244": 36360.0, + "am244_m1": 1560.0, + "am245": 7380.0, + "am246": 2340.0, + "am246_m1": 1500.0, + "am247": 1380.0, + "am248": 600.0, + "am249": 120.0, + "cm233": 17.7, + "cm234": 51.0, + "cm235": 300.0, + "cm236": 1900.0, + "cm237": 1200.0, + "cm238": 8640.0, + "cm239": 10440.0, + "cm240": 2332800.0, + "cm241": 2833920.0, + "cm242": 14078020.0, + "cm243": 918326200.0, + "cm244": 571508100.0, + "cm244_m1": 5e-07, + "cm245": 268240000000.0, + "cm246": 150214000000.0, + "cm247": 492299000000000.0, + "cm248": 10982000000000.0, + "cm249": 3849.0, + "cm250": 261928000000.0, + "cm251": 1008.0, + "bk235": 20.0, + "bk237": 60.0, + "bk238": 144.0, + "bk240": 288.0, + "bk241": 276.0, + "bk242": 420.0, + "bk243": 16200.0, + "bk244": 15660.0, + "bk245": 426816.0, + "bk246": 155520.0, + "bk247": 43549500000.0, + "bk248": 283824000.0, + "bk248_m1": 85320.0, + "bk249": 27648000.0, + "bk250": 11563.2, + "bk251": 3336.0, + "bk253": 600.0, + "bk254": 120.0, + "cf237": 2.1, + "cf238": 0.021, + "cf239": 51.5, + "cf240": 57.6, + "cf241": 226.8, + "cf242": 222.0, + "cf243": 642.0, + "cf244": 1164.0, + "cf245": 2700.0, + "cf246": 128520.0, + "cf247": 11196.0, + "cf248": 28814400.0, + "cf249": 11076700000.0, + "cf250": 412773400.0, + "cf251": 28338700000.0, + "cf252": 83468070.0, + "cf253": 1538784.0, + "cf254": 5227200.0, + "cf255": 5100.0, + "cf256": 738.0, + "es240": 1.0, + "es241": 8.5, + "es242": 13.5, + "es243": 21.0, + "es244": 37.0, + "es245": 66.0, + "es246": 462.0, + "es247": 273.0, + "es247_m1": 54000000.0, + "es248": 1620.0, + "es249": 6132.0, + "es250": 30960.0, + "es250_m1": 7992.0, + "es251": 118800.0, + "es252": 40754880.0, + "es253": 1768608.0, + "es254": 23820480.0, + "es254_m1": 141479.9, + "es255": 3438720.0, + "es256": 1524.0, + "es256_m1": 27360.0, + "es257": 665280.0, + "es258": 180.0, + "fm242": 0.0008, + "fm243": 0.2, + "fm244": 0.0033, + "fm245": 4.2, + "fm246": 1.1, + "fm247": 29.0, + "fm248": 36.0, + "fm249": 156.0, + "fm250": 1800.0, + "fm250_m1": 1.8, + "fm251": 19080.0, + "fm252": 91404.0, + "fm253": 259200.0, + "fm254": 11664.0, + "fm255": 72252.0, + "fm256": 9456.0, + "fm257": 8683200.0, + "fm258": 0.00037, + "fm259": 1.5, + "fm260": 0.004, + "md245": 0.0009, + "md245_m1": 0.39, + "md246": 0.9, + "md247": 1.12, + "md247_m1": 0.26, + "md248": 7.0, + "md249": 24.0, + "md249_m1": 1.9, + "md250": 27.5, + "md251": 240.0, + "md252": 138.0, + "md253": 630.0, + "md254": 1680.0, + "md254_m1": 1680.0, + "md255": 1620.0, + "md256": 4620.0, + "md257": 19872.0, + "md258": 4449600.0, + "md258_m1": 3420.0, + "md259": 5760.0, + "md260": 2747520.0, + "md261": 2400.0, + "no250": 4.35e-06, + "no251": 0.8, + "no251_m1": 1.02, + "no252": 2.44, + "no253": 97.2, + "no254": 51.0, + "no254_m1": 0.28, + "no255": 186.0, + "no256": 2.91, + "no257": 25.0, + "no258": 0.0012, + "no259": 3480.0, + "no260": 0.106, + "no261": 160000.0, + "no262": 0.005, + "lr251": 1.341, + "lr252": 0.38, + "lr253": 0.575, + "lr253_m1": 1.535, + "lr254": 13.0, + "lr255": 22.0, + "lr255_m1": 2.53, + "lr256": 27.0, + "lr257": 0.646, + "lr258": 4.1, + "lr259": 6.2, + "lr260": 180.0, + "lr261": 2340.0, + "lr262": 14400.0, + "lr263": 18000.0, + "rf253": 5.15e-05, + "rf254": 2.3e-05, + "rf255": 1.68, + "rf256": 0.0064, + "rf257": 4.7, + "rf257_m1": 3.9, + "rf258": 0.012, + "rf259": 3.2, + "rf260": 0.021, + "rf261": 65.0, + "rf261_m1": 81.0, + "rf262": 2.3, + "rf263": 600.0, + "rf264": 3600.0, + "rf265": 1.0, + "db255": 1.7, + "db256": 1.7, + "db257": 1.52, + "db257_m1": 0.78, + "db258": 4.0, + "db258_m1": 20.0, + "db259": 0.51, + "db260": 1.52, + "db261": 1.8, + "db262": 35.0, + "db263": 28.5, + "db264": 180.0, + "db265": 900.0, + "sg258": 0.0032, + "sg259": 0.555, + "sg260": 0.0036, + "sg261": 0.23, + "sg262": 0.0079, + "sg263": 1.0, + "sg263_m1": 0.12, + "sg264": 0.045, + "sg265": 8.0, + "sg266": 25.0, + "sg269": 50.0, + "bh260": 0.0003, + "bh261": 0.013, + "bh262": 0.102, + "bh262_m1": 0.022, + "bh263": 0.0002, + "bh264": 0.66, + "bh265": 1.1, + "bh266": 5.4, + "bh267": 21.0, + "bh269": 50.0, + "hs263": 0.00355, + "hs264": 0.0008, + "hs265": 0.00205, + "hs265_m1": 0.0003, + "hs266": 0.00265, + "hs267": 0.0545, + "hs268": 1.2, + "hs269": 12.9, + "hs273": 50.0, + "mt265": 120.0, + "mt266": 0.0018, + "mt266_m1": 0.0017, + "mt267": 0.01, + "mt268": 0.0225, + "mt269": 0.05, + "mt270": 0.00605, + "mt271": 5.0, + "mt273": 20.0, + "ds267": 2.8e-06, + "ds268": 0.0001, + "ds269": 0.000268, + "ds270": 0.00015, + "ds270_m1": 0.009, + "ds271": 0.001705, + "ds271_m1": 0.0865, + "ds272": 1.0, + "ds273": 0.000225, + "ds279_m1": 0.19, + "rg272": 0.0041 } From 9c132bfbf02a80ecafd7dbd9d5f2b5701690d7e2 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 23 Jun 2022 11:34:53 +0200 Subject: [PATCH 0424/2654] include mcpl header --- src/source.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/source.cpp b/src/source.cpp index cd8b5e574..5e26fa0a8 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -31,6 +31,10 @@ #include "openmc/state_point.h" #include "openmc/xml_interface.h" +#ifdef HAS_MCPL +#include +#endif + namespace openmc { //============================================================================== From 5d74af4bf766ab732d320081be47b9c4f78303fe Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 23 Jun 2022 11:35:46 +0200 Subject: [PATCH 0425/2654] declarations of MCPL-internals --- include/openmc/source.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index cadbfe93b..69dd47eae 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -109,11 +109,20 @@ public: MCPLFileSource(std::string path); ~MCPLFileSource(); - // Defer implementation to custom source library - SourceSite sample(uint64_t* seed) const override + // Properties + ParticleType particle_type() const { return particle_; } + + //! Sample from the external source distribution + //! \param[inout] seed Pseudorandom seed pointer + //! \return Site read from MCPL-file + SourceSite sample(uint64_t* seed) const override; private: + ParticleType particle_ {ParticleType::neutron}; //!< Type of particle emitted vector sites_; //! Date: Thu, 23 Jun 2022 11:37:05 +0200 Subject: [PATCH 0426/2654] internals of sample and constructor --- src/source.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 5e26fa0a8..231f355fc 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -337,7 +337,7 @@ CustomSourceWrapper::~CustomSourceWrapper() } //=========================================================================== -// Read an MCPL-file +// Read particles from an MCPL-file //=========================================================================== MCPLFileSource::MCPLFileSource(std::string path) { @@ -348,12 +348,55 @@ MCPLFileSource::MCPLFileSource(std::string path) // Read the source from a binary file instead of sampling from some // assumed source distribution - write_message(6, "Reading source file from {}...", path); + write_message(6, "Reading mcpl source file from {}",path); // Open the mcpl file - id_t file_id = mcpl_open(path.c_str) - + mcpl_file = mcpl_open(path.c_str); + //do checks on the mcpl_file to see if particles are many enough. + // should model this on the example source shown in the docs. + uint64_t nparticles=mcpl_hdr_nparticles(mcpl_file); + +} + +MCPLFileSource::~MCPLFilsSource(){ + mcpl_close_file(mcpl_file); +} + +SourceSite MCPLFileSource::sample(uint64_t *seed){ + SourceSite omc_particle; + mcpl_particle *mcpl_particle; + //extract particle from mcpl-file + mcpl_particle=mcpl_reazd(mcplfile); + // check if it is a neutron or a photon. otherwise skip + while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) + { + mcpl_particle(mcpl_read(mcplfile); + //check for file exhaustion + } + + if(mcpl_particle->pdgcode=2112) { + omc_particle_=ParticleType::neutron; + } else { + omc_particle_=Particletype::photon; + } + + //particle is good, convert to openmc-formalism + omc_particle.r.x=mcpl_particle.x; + omc_particle.r.y=mcpl_particle.y; + omc_particle.r.z=mcpl_particle.z; + + omc_particle.u.x=mcpl_particle->direction[0]; + omc_particle.u.y=mcpl_particle->direction[1]; + omc_particle.u.z=mcpl_particle->direction[2]; + + //mcpl stores particles in MeV + omc_particle.E=mcpl_particle->ekin*1e6; + + omc_particle.t=mcpl_particle->time*1e-3; + omc_particle.wgt=mcpl_particle->weight; + omc_particle.delayed_group=0; + return omc_particle; } From 3e61076715b9a15285b2d731127b968c600d7812 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 25 Jun 2022 14:38:19 +0200 Subject: [PATCH 0427/2654] Changing check for Tabular to use std. dev. --- tests/unit_tests/test_stats.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index f789a0dca..87d811881 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -165,14 +165,26 @@ def test_tabular(): n_samples = 100_000 samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(d.mean(), rel=1e-03) + diff = np.abs(samples - d.mean()) + # within_1_sigma = np.count_nonzero(diff < samples.std()) + # assert within_1_sigma / n_samples >= 0.68 + within_2_sigma = np.count_nonzero(diff < 2*samples.std()) + assert within_2_sigma / n_samples >= 0.95 + within_3_sigma = np.count_nonzero(diff < 3*samples.std()) + assert within_3_sigma / n_samples >= 0.99 # test histogram sampling d = openmc.stats.Tabular(x, p, interpolation='histogram') d.normalize() samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(d.mean(), rel=1e-03) + diff = np.abs(samples - d.mean()) + # within_1_sigma = np.count_nonzero(diff < samples.std()) + # assert within_1_sigma / n_samples >= 0.68 + within_2_sigma = np.count_nonzero(diff < 2*samples.std()) + assert within_2_sigma / n_samples >= 0.95 + within_3_sigma = np.count_nonzero(diff < 3*samples.std()) + assert within_3_sigma / n_samples >= 0.99 def test_legendre(): From e9eaf2edef09fe4cec82810d8669e6437d512a4d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 26 Jun 2022 01:10:53 -0400 Subject: [PATCH 0428/2654] Using std. dev. of sampled mean for comparison --- tests/unit_tests/test_stats.py | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 87d811881..b57f9578a 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -36,8 +36,10 @@ def test_discrete(): # sample discrete distribution n_samples = 1_000_000 samples = d3.sample(n_samples, seed=100) - # check that the mean of the samples is close to the true mean - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + # check that the mean of the samples is within 3 std. dev. + # of the expected mean + std_dev = samples.std() / np.sqrt(n_samples) + assert np.abs(exp_mean - samples.mean()) < 3*std_dev def test_merge_discrete(): @@ -81,7 +83,10 @@ def test_uniform(): exp_mean = 0.5 * (a + b) n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + # check that the mean of the samples is within 3 std. dev. + # of the expected mean + std_dev = samples.std() / np.sqrt(n_samples) + assert np.abs(exp_mean - samples.mean()) < 3*std_dev def test_powerlaw(): @@ -100,7 +105,10 @@ def test_powerlaw(): # sample power law distribution n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + # check that the mean of the samples is within 3 std. dev. + # of the expected mean + std_dev = samples.std() / np.sqrt(n_samples) + assert np.abs(exp_mean - samples.mean()) < 3*std_dev def test_maxwell(): @@ -117,13 +125,19 @@ def test_maxwell(): # sample maxwell distribution n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-02) + # check that the mean of the samples is within 3 std. dev. + # of the expected mean + std_dev = samples.std() / np.sqrt(n_samples) + assert np.abs(exp_mean - samples.mean()) < 3*std_dev # A second sample with a different seed samples_2 = d.sample(n_samples, seed=200) - assert samples_2.mean() == pytest.approx(exp_mean, rel=1e-02) - assert samples_2.mean() != samples.mean() + # check that the mean of the samples is within 3 std. dev. + # of the expected mean + std_dev = samples_2.std() / np.sqrt(n_samples) + assert np.abs(exp_mean - samples_2.mean()) < 3*std_dev + assert samples_2.mean() != samples.mean() def test_watt(): @@ -145,7 +159,10 @@ def test_watt(): # sample Watt distribution n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - assert samples.mean() == pytest.approx(exp_mean, rel=1e-03) + # check that the mean of the samples is within 3 std. dev. + # of the expected mean + std_dev = samples.std() / np.sqrt(n_samples) + assert np.abs(exp_mean - samples.mean()) < 3*std_dev def test_tabular(): From 491798b24dc13dc839ef7e421c453aeff450929b Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 09:59:11 -0500 Subject: [PATCH 0429/2654] remove model parameter, replace with nuclides parameter We will be passing a data structure that already contains nuclide and cross section information to this class, so we will not need all the capabilities of an openmc Model. --- openmc/deplete/flux_operator.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 17b43dcfd..dbc7eaa2a 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -41,10 +41,10 @@ class FluxSpectraDepletionOperator(TransportOperator, Operator): Parameters ---------- - model : openmc.model.Model - OpenMC Model object. Must contain geometry and materials information. + nuclides : pandas.DataFrame + DataFrame contaning nuclide concentration as well as cross section data. flux_spectra : ??? - Unnormalized flux spectrum. + Flux spectrum chain_file : str Path to the depletion chain XML file. fission_q : dict, optional @@ -77,25 +77,17 @@ class FluxSpectraDepletionOperator(TransportOperator, Operator): results are to be used. """ - def __init__(self, model, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, + def __init__(self, nuclides, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None): # Determine cross sections / depletion chain # TODO : add support for mg cross sections to _find_cross_sections - cross_sections = _find_cross_sections(model) if chain_file is None: chain_file = _find_chain_file(cross_sections) TransportOperator.__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False - self.geometry = model.geometry - # determine set of materials in the model - if not model.materials: - model.materials = openmc.Materials( - model.geometry.get_all_materials().values() - ) - self.materials = model.materials self.flux_spectra = flux_spectra # Reduce the chain before we create more materials From 498deeea28d1d927599cb860f8717c7aba5cf76c Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 10:11:50 -0500 Subject: [PATCH 0430/2654] modify block reducing depletion chain This change modifies the block to handle information stored in the nuclides parameter --- openmc/deplete/flux_operator.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index dbc7eaa2a..d8688aa60 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -80,6 +80,9 @@ class FluxSpectraDepletionOperator(TransportOperator, Operator): def __init__(self, nuclides, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None): + + # TODO : validate nuclides parameter + # Determine cross sections / depletion chain # TODO : add support for mg cross sections to _find_cross_sections if chain_file is None: @@ -90,15 +93,12 @@ class FluxSpectraDepletionOperator(TransportOperator, Operator): self.flux_spectra = flux_spectra - # Reduce the chain before we create more materials + # Reduce the chain if reduce_chain: - all_isotopes = set() - for material in self.materials: - if not material.depletable: - continue - for name, _dens_percent, _dens_type in material.nuclides: - all_isotopes.add(name) - self.chain = self.chain.reduce(all_isotopes, reduce_chain_level) + all_nuclides = set() + for nuclide_name in nuclides.index: + all_isotopes.add(nuclide_name) + self.chain = self.chain.reduce(all_nuclides, reduce_chain_level) # Clear out OpenMC, create task lists, distribute self.burnable_mats, volume, nuclides = Operator._get_burnable_mats() From 200ea764aced25a48f6e47b241236eb9744a2231 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 10:40:43 -0500 Subject: [PATCH 0431/2654] make FluxSpectraDepletionOperator not a subclass of Operator --- openmc/deplete/flux_operator.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index d8688aa60..8981a5d01 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -19,7 +19,6 @@ from openmc.checkvalue import check_value from openmc.data import DataLibrary from openmc.exceptions import DataError from openmc.mpi import comm -from .operator import Operator, _distribute, _find_cross_sections from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .chain import _find_chain_file @@ -28,7 +27,7 @@ from .results import Results -class FluxSpectraDepletionOperator(TransportOperator, Operator): +class FluxSpectraDepletionOperator(TransportOperator): """Depletion operator that uses a user provided flux spectrum to calculate reaction rates. The flux provided must match the type of cross section library in use (contunuous flux for continuous energy library, @@ -101,7 +100,7 @@ class FluxSpectraDepletionOperator(TransportOperator, Operator): self.chain = self.chain.reduce(all_nuclides, reduce_chain_level) # Clear out OpenMC, create task lists, distribute - self.burnable_mats, volume, nuclides = Operator._get_burnable_mats() + self.burnable_mats, volume, nuclides = self.get_burnable_mats() self.local_mats = _distribute(self.burnable_mats) # Generate map from local materials => material index @@ -110,16 +109,15 @@ class FluxSpectraDepletionOperator(TransportOperator, Operator): # TODO: add support for loading previous results - # Determine which nuclides have incident neutron data - # TODO : add support for mg cross sections to Operator._get_nuclides_with_data - self.nuclides_with_data = Operator._get_nuclides_with_data(mg_cross_sections) + # TODO : Determine which nuclides have incident neutron data + self.nuclides_with_data = self._get_nuclides_with_data() # Select nuclides with data that are also in the chain self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides if nuc.name in self.nuclides_with_data] # Extract number densities from the geometry / previous depletion run - Operator._extract_number(self.local_mats, volume, nuclides, self.prev_res) + self._extract_number(self.local_mats, volume, nuclides, self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( @@ -152,7 +150,7 @@ class FluxSpectraDepletionOperator(TransportOperator, Operator): self._update_materials() # Update tally nuclides data in preparation for transport solve - nuclides = Operator._get_tally_nuclides() + nuclides = self.._get_tally_nuclides() self._rate_helper.nuclides = nuclides self._normalization_helper.nuclides = nuclides self._yield_helper.update_tally_nuclides(nuclides) From fa6fd9384e07385bced4ca1b8bfa498600ebb496 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 10:45:50 -0500 Subject: [PATCH 0432/2654] make nuclude concentrations and nuclide cross section data parameters separate --- openmc/deplete/flux_operator.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 8981a5d01..78ef8b8c4 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -40,8 +40,11 @@ class FluxSpectraDepletionOperator(TransportOperator): Parameters ---------- - nuclides : pandas.DataFrame - DataFrame contaning nuclide concentration as well as cross section data. + nuclides : dict of str to float + Dictionary with nuclides names as keys and concentration as values. + micro_xs : pandas.DataFrame + DataFrame with nuclides names as index and microscopic cross section + data in the columns. flux_spectra : ??? Flux spectrum chain_file : str @@ -76,16 +79,11 @@ class FluxSpectraDepletionOperator(TransportOperator): results are to be used. """ - def __init__(self, nuclides, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, + def __init__(self, nuclides, micro_xs, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None): - # TODO : validate nuclides parameter - - # Determine cross sections / depletion chain - # TODO : add support for mg cross sections to _find_cross_sections - if chain_file is None: - chain_file = _find_chain_file(cross_sections) + # TODO : validate nuclides and micro-xs parameters TransportOperator.__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False @@ -95,7 +93,7 @@ class FluxSpectraDepletionOperator(TransportOperator): # Reduce the chain if reduce_chain: all_nuclides = set() - for nuclide_name in nuclides.index: + for nuclide_name in nuclides.keys(): all_isotopes.add(nuclide_name) self.chain = self.chain.reduce(all_nuclides, reduce_chain_level) From 194c846bd72c6a722635104d9401ef1277161168 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 11:10:06 -0500 Subject: [PATCH 0433/2654] remove local_mats attribute --- openmc/deplete/flux_operator.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 78ef8b8c4..0e74eb824 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -98,12 +98,7 @@ class FluxSpectraDepletionOperator(TransportOperator): self.chain = self.chain.reduce(all_nuclides, reduce_chain_level) # Clear out OpenMC, create task lists, distribute - self.burnable_mats, volume, nuclides = self.get_burnable_mats() - self.local_mats = _distribute(self.burnable_mats) - - # Generate map from local materials => material index - self._mat_index_map = { - lm: self.burnable_mats.index(lm) for lm in self.local_mats} + #self.burnable_mats, volume, nuclides = self.get_burnable_mats() # TODO: add support for loading previous results @@ -115,11 +110,11 @@ class FluxSpectraDepletionOperator(TransportOperator): if nuc.name in self.nuclides_with_data] # Extract number densities from the geometry / previous depletion run - self._extract_number(self.local_mats, volume, nuclides, self.prev_res) + self._extract_number('0', volume, nuclides, self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( - self.local_mats, self._burnable_nucs, self.chain.reactions) + '0', self._burnable_nucs, self.chain.reactions) # TODO : set up rate, yield, and normalization helper objects @@ -170,7 +165,7 @@ class FluxSpectraDepletionOperator(TransportOperator): number = np.empty(rates.n_nuc) # Extract results - for i, mat in enumerate(self.local_mats): + for i, mat in enumerate(...): # Get tally index mat_index = self._mat_index_map[mat] From 9096b1e0f020c6cda8b20a9ae972f159f6e77105 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 11:22:36 -0500 Subject: [PATCH 0434/2654] remove looping over materials in the _call_ method --- openmc/deplete/flux_operator.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 0e74eb824..0dd87a32a 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -110,7 +110,7 @@ class FluxSpectraDepletionOperator(TransportOperator): if nuc.name in self.nuclides_with_data] # Extract number densities from the geometry / previous depletion run - self._extract_number('0', volume, nuclides, self.prev_res) + self._extract_number('0', volume, list(nuclides.keys()), self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( @@ -164,10 +164,15 @@ class FluxSpectraDepletionOperator(TransportOperator): # numbers, zeroed out in material iteration number = np.empty(rates.n_nuc) - # Extract results - for i, mat in enumerate(...): - # Get tally index - mat_index = self._mat_index_map[mat] + # Zero out reaction rates and nuclide numbers + number.fill(0.0) + + # Get new number densities + for nuc, i_nuc_results in zip(nuclides, nuc_ind): + number[i_nuc_results] = self.number['0', nuc] + + + # TODO : add machinery to multiply # each cross section by the corresponding flux From 1e631991303c74202b945f328f2a93339ab30eef Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 11:31:18 -0500 Subject: [PATCH 0435/2654] add ConstantFissionYieldHelper --- openmc/deplete/flux_operator.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 0dd87a32a..593a1ccff 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -24,6 +24,9 @@ from .atom_number import AtomNumber from .chain import _find_chain_file from .reaction_rates import ReactionRates from .results import Results +from .helpers import ( + DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper) + @@ -116,7 +119,12 @@ class FluxSpectraDepletionOperator(TransportOperator): self.reaction_rates = ReactionRates( '0', self._burnable_nucs, self.chain.reactions) - # TODO : set up rate, yield, and normalization helper objects + # Select and create fission yield helper + fission_helper = ConstantFissionYieldHelper + fission_yield_opts = ( + {} if fission_yield_opts is None else fission_yield_opts) + self._yield_helper = fission_helper.from_operator( + self, **fission_yield_opts) def __call__(self, vec, source_rate): @@ -143,13 +151,12 @@ class FluxSpectraDepletionOperator(TransportOperator): self._update_materials() # Update tally nuclides data in preparation for transport solve - nuclides = self.._get_tally_nuclides() + nuclides = self._get_tally_nuclides() self._rate_helper.nuclides = nuclides self._normalization_helper.nuclides = nuclides self._yield_helper.update_tally_nuclides(nuclides) - rates = self.reaction_rates rates.fill(0.0) @@ -165,13 +172,14 @@ class FluxSpectraDepletionOperator(TransportOperator): number = np.empty(rates.n_nuc) # Zero out reaction rates and nuclide numbers - number.fill(0.0) + number.fill(0.0) # Get new number densities for nuc, i_nuc_results in zip(nuclides, nuc_ind): number[i_nuc_results] = self.number['0', nuc] - + # Compute fission yields for this material + fission_yields.append(self._yield_helper.weighted_yields(i)) # TODO : add machinery to multiply From b9f75d961b534eb463a0f99655a1e6ad2889287f Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 11:48:50 -0500 Subject: [PATCH 0436/2654] clean up __call__ method --- openmc/deplete/flux_operator.py | 91 +++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 593a1ccff..f7a29b5b8 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -25,7 +25,8 @@ from .chain import _find_chain_file from .reaction_rates import ReactionRates from .results import Results from .helpers import ( - DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper) + FluxReactionRateHelper, ChainFissionHelper, SourceRateHelper, + ConstantFissionYieldHelper) @@ -150,27 +151,35 @@ class FluxSpectraDepletionOperator(TransportOperator): self.number.set_density(vec) self._update_materials() - # Update tally nuclides data in preparation for transport solve - nuclides = self._get_tally_nuclides() + # Update nuclides data in preparation for transport solve + nuclides = self._get_reaction_nuclides() self._rate_helper.nuclides = nuclides - self._normalization_helper.nuclides = nuclides self._yield_helper.update_tally_nuclides(nuclides) - rates = self.reaction_rates rates.fill(0.0) # Get k and uncertainty # TODO : add functionality to get this from the transport solver + keff = ... # Form fast map nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides] react_ind = [rates.index_rx[react] for react in self.chain.reactions] + # Keep track of energy produced from all reactions in eV per source + # particle + self._normalization_helper.reset() + + # Store fission yield dictionaries + fission_yields = [] + # Create arrays to store fission Q values, reaction rates, and nuclide # numbers, zeroed out in material iteration number = np.empty(rates.n_nuc) + fission_ind = rates.index_rx.get("fission") + # Zero out reaction rates and nuclide numbers number.fill(0.0) @@ -178,18 +187,20 @@ class FluxSpectraDepletionOperator(TransportOperator): for nuc, i_nuc_results in zip(nuclides, nuc_ind): number[i_nuc_results] = self.number['0', nuc] + # TODO : implement rate helper for flux and xs inputs + reaction_rates = self._rate_helper.get_material_rates( + 0, nuc_ind, react_ind) + # Compute fission yields for this material - fission_yields.append(self._yield_helper.weighted_yields(i)) + fission_yields.append(self._yield_helper.weighted_yields(0)) + # Accumulate energy from fission + if fission_ind is not None: + self._normalization_helper.update(reaction_rates[:, fission_ind]) - # TODO : add machinery to multiply - # each cross section by the corresponding flux + # Divide by total number and store + rates[0] = self._rate_helper.divide_by_adens(number) - ... - - - # TODO: add flow control to determine if we need to scale - # the reaction rates # Scale reaction rates to obtain units of reactions/sec rates *= self._normalization_helper.factor(source_rate) @@ -210,16 +221,7 @@ class FluxSpectraDepletionOperator(TransportOperator): # TODO : implement these functions so they can store the # cross section data - materials = [openmc.lib.materials[int(i)] - for i in self.burnable_mats] self._rate_helper.generate_tallies(materials, self.chain.reactions) - self._normalization_helper.prepare( - self.chain.nuclides, self.reaction_rates.index_nuc) - # Tell fission yield helper what materials this process is - # responsible for - self._yield_helper.generate_tallies( - materials, tuple(sorted(self._mat_index_map.values()))) - # Return number density vector return list(self.number.get_mat_slice(np.s_[:])) @@ -275,3 +277,48 @@ class FluxSpectraDepletionOperator(TransportOperator): #TODO Update densities on the Python side, otherwise the # summary.h5 file contains densities at the first time step + + def _get_reaction_nuclides(self): + """Determine nuclides that should be tallied for reaction rates. + + This method returns a list of all nuclides that have neutron data and + are listed in the depletion chain. Technically, we should tally nuclides + that may not appear in the depletion chain because we still need to get + the fission reaction rate for these nuclides in order to normalize + power, but that is left as a future exercise. + + Returns + ------- + list of str + Tally nuclides + + """ + nuc_set = set() + + # Create the set of all nuclides in the decay chain in materials marked + # for burning in which the number density is greater than zero. + for nuc in self.number.nuclides: + if nuc in self.nuclides_with_data: + if np.sum(self.number[:, nuc]) > 0.0: + nuc_set.add(nuc) + + # Communicate which nuclides have nonzeros to rank 0 + if comm.rank == 0: + for i in range(1, comm.size): + nuc_newset = comm.recv(source=i, tag=i) + nuc_set |= nuc_newset + else: + comm.send(nuc_set, dest=0, tag=comm.rank) + + if comm.rank == 0: + # Sort nuclides in the same order as self.number + nuc_list = [nuc for nuc in self.number.nuclides + if nuc in nuc_set] + else: + nuc_list = None + + # Store list of tally nuclides on each process + nuc_list = comm.bcast(nuc_list) + return [nuc for nuc in nuc_list if nuc in self.chain] + + From 28a7b587aa9bb03b38ca22c40c5d8f965c9a3d4d Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 15:15:29 -0500 Subject: [PATCH 0437/2654] refine __call__; remove/disable _rate_helper attribute; add _normalization_helper, _yield_helper attributes --- openmc/deplete/flux_operator.py | 37 ++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index f7a29b5b8..02ef64cf0 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -89,7 +89,7 @@ class FluxSpectraDepletionOperator(TransportOperator): # TODO : validate nuclides and micro-xs parameters - TransportOperator.__init__(chain_file, fission_q, dilute_initial, prev_results) + super.__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False self.flux_spectra = flux_spectra @@ -120,6 +120,12 @@ class FluxSpectraDepletionOperator(TransportOperator): self.reaction_rates = ReactionRates( '0', self._burnable_nucs, self.chain.reactions) + # Initialize normalization helper + if normalization_mode == "fission-q": + self._normalization_helper = ChainFissionHelper() + else: + self._normalization_helper = SourceRateHelper() + # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper fission_yield_opts = ( @@ -145,15 +151,12 @@ class FluxSpectraDepletionOperator(TransportOperator): """ - - # Update the number densities regardless of the source rate self.number.set_density(vec) self._update_materials() # Update nuclides data in preparation for transport solve nuclides = self._get_reaction_nuclides() - self._rate_helper.nuclides = nuclides self._yield_helper.update_tally_nuclides(nuclides) rates = self.reaction_rates @@ -185,24 +188,31 @@ class FluxSpectraDepletionOperator(TransportOperator): # Get new number densities for nuc, i_nuc_results in zip(nuclides, nuc_ind): - number[i_nuc_results] = self.number['0', nuc] + number[i_nuc_results] = self.number[0, nuc] - # TODO : implement rate helper for flux and xs inputs - reaction_rates = self._rate_helper.get_material_rates( - 0, nuc_ind, react_ind) + # Store microscopic cross sections in rates array + for nuc in nuclides: + for rxn in self.chain.reactions: + rates.set('0', nuc, rxn, self.micro_xs[rxn].loc[nuc]) + + # Get reaction rate in reactions/sec + rates *= self.flux_spectra # Compute fission yields for this material fission_yields.append(self._yield_helper.weighted_yields(0)) # Accumulate energy from fission if fission_ind is not None: - self._normalization_helper.update(reaction_rates[:, fission_ind]) + self._normalization_helper.update(rxn_rates[:, fission_ind]) + ## These don't seem relevant so I'm commenting them out for now + ## will delete if they are indeed not useful # Divide by total number and store - rates[0] = self._rate_helper.divide_by_adens(number) + #rates[0] = self._rate_helper.divide_by_adens(number) # Scale reaction rates to obtain units of reactions/sec - rates *= self._normalization_helper.factor(source_rate) + #rates *= self._normalization_helper.factor(source_rate) + ## # Store new fission yields on the chain self.chain.fission_yields = fission_yields @@ -219,9 +229,8 @@ class FluxSpectraDepletionOperator(TransportOperator): Total density for initial conditions. """ - # TODO : implement these functions so they can store the - # cross section data - self._rate_helper.generate_tallies(materials, self.chain.reactions) + self._normalization_helper.prepare( + self.chain.nuclides, self.reaction_rates.index_nuc) # Return number density vector return list(self.number.get_mat_slice(np.s_[:])) From b85da509885338b7976859d2e8ada7ed2ea15263 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 15:53:48 -0500 Subject: [PATCH 0438/2654] add basic type verification for nuclides, micro_xs parameters; comment out _normalization_helper attribute --- openmc/deplete/flux_operator.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 02ef64cf0..e3bc6a5f3 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -12,6 +12,7 @@ import os from warnings import warn import numpy as np +import pandas as pd from uncertainties import ufloat import openmc @@ -49,8 +50,8 @@ class FluxSpectraDepletionOperator(TransportOperator): micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. - flux_spectra : ??? - Flux spectrum + flux_spectra : float + Flux spectrum [n cm^-2 s^-1] chain_file : str Path to the depletion chain XML file. fission_q : dict, optional @@ -85,13 +86,8 @@ class FluxSpectraDepletionOperator(TransportOperator): def __init__(self, nuclides, micro_xs, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None): - - - # TODO : validate nuclides and micro-xs parameters - super.__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False - self.flux_spectra = flux_spectra # Reduce the chain @@ -101,6 +97,10 @@ class FluxSpectraDepletionOperator(TransportOperator): all_isotopes.add(nuclide_name) self.chain = self.chain.reduce(all_nuclides, reduce_chain_level) + # Validate nuclides and micro-xs parameters + check_value('nuclides', nuclides, dict, str) + check_type('micro_xs', micro_xs, pd.DataFrame) + # Clear out OpenMC, create task lists, distribute #self.burnable_mats, volume, nuclides = self.get_burnable_mats() @@ -113,6 +113,7 @@ class FluxSpectraDepletionOperator(TransportOperator): self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides if nuc.name in self.nuclides_with_data] + # TODO : implement _extract_number # Extract number densities from the geometry / previous depletion run self._extract_number('0', volume, list(nuclides.keys()), self.prev_res) @@ -121,10 +122,10 @@ class FluxSpectraDepletionOperator(TransportOperator): '0', self._burnable_nucs, self.chain.reactions) # Initialize normalization helper - if normalization_mode == "fission-q": - self._normalization_helper = ChainFissionHelper() - else: - self._normalization_helper = SourceRateHelper() + #if normalization_mode == "fission-q": + # self._normalization_helper = ChainFissionHelper() + #else: + # self._normalization_helper = SourceRateHelper() # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper @@ -202,8 +203,8 @@ class FluxSpectraDepletionOperator(TransportOperator): fission_yields.append(self._yield_helper.weighted_yields(0)) # Accumulate energy from fission - if fission_ind is not None: - self._normalization_helper.update(rxn_rates[:, fission_ind]) + #if fission_ind is not None: + # self._normalization_helper.update(rxn_rates[:, fission_ind]) ## These don't seem relevant so I'm commenting them out for now ## will delete if they are indeed not useful @@ -229,8 +230,8 @@ class FluxSpectraDepletionOperator(TransportOperator): Total density for initial conditions. """ - self._normalization_helper.prepare( - self.chain.nuclides, self.reaction_rates.index_nuc) + #self._normalization_helper.prepare( + # self.chain.nuclides, self.reaction_rates.index_nuc) # Return number density vector return list(self.number.get_mat_slice(np.s_[:])) From 909b96f31e90a8a8ce40e890b3f4e73ee516466b Mon Sep 17 00:00:00 2001 From: erkn Date: Mon, 27 Jun 2022 23:25:35 +0200 Subject: [PATCH 0439/2654] (wip): skeleton for input only test --- .../regression_tests/source_mcpl_file/test.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/test.py diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py new file mode 100644 index 000000000..5a6a87d87 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -0,0 +1,52 @@ +import pathlib as pl +import os +import shutil +import subprocess +import textwrap + +import openmc +import pytest + +from tests.testing_harness import TestHarness + +def model(): + subprocess.run(['gcc','-o gen_dummt_mcpl.out','-lm','-lmcpl','gen_dummy_mcpl.c'] ) + subprocess.run(['./gen_dummy_mcpl.out']) + +class SourceMCPLFileTestHarness(TestHarness): + def execute_test(self): + """Run OpenMC with the appropriate arguments and check the outputs.""" + try: + self._create_input() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._compare_results() + finally: + self._cleanup() + + def update_results(self): + """Update the results_true using the current version of OpenMC.""" + try: + self._create_input() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._overwrite_results() + finally: + self._cleanup() + + def _test_output_created(self): + """Check that the output files were created""" + stat epoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) + assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ + 'exist.' + assert statepoint[0].endswith('h5'), \ + 'statepoint file does not end with h5.' + +def test_mcpl_source_file(): + harness = SourceMCPLFileTestHarness('statepoint.10.h5') + harness.main() + From 3c30dbba5b643e8464eb9b45a8667e08bf6ad44b Mon Sep 17 00:00:00 2001 From: erkn Date: Mon, 27 Jun 2022 23:26:01 +0200 Subject: [PATCH 0440/2654] c-prog to generate a dummy mcpl --- .../source_mcpl_file/gen_dummy_mcpl.c | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c new file mode 100644 index 000000000..7b5a933f1 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include + +const int batches=10; +const int particles=10000; + +double rand01(){ + double r=rand()/((double) RAND_MAX); + return r; +} + + +int main(int argc, char **argv){ + char outfilename[128]; + snprintf(outfilename,127,"source.%d.mcpl",batches); + + /*generate an mcpl_header_of sorts*/ + mcpl_outfile_t outfile=mcpl_create_outfile(outfilename); + mcpl_particle_t *particle, Particle; + + char line[256]; + snprintf(line,255,"gen_dummy_mcpl.c"); + mcpl_hdr_set_srcname(outfile,line); + mcpl_enable_universal_pdgcode(outfile,2112);/*all particles are neutrons*/ + snprintf(line,255,"Dummy MCPL-file for testing OpenMC mcpl input"); + mcpl_hdr_add_comment(outfile,line); + + /*also add the instrument file and the command line as blobs*/ + FILE *fp; + if( (fp=fopen("gen_dummy_mcpl.c","rb"))!=NULL){ + unsigned char *buffer; + int size,status; + /*find the file size by seeking to end, "tell" the position, and then go back again*/ + fseek(fp, 0L, SEEK_END); + size = ftell(fp); // get current file pointer + fseek(fp, 0L, SEEK_SET); // seek back to beginning of file + if ( size && (buffer=malloc(size))!=NULL){ + if (size!=(fread(buffer,1,size,fp))){ + fprintf(stderr,"Warning: c source generator file not read cleanly\n"); + } + mcpl_hdr_add_data(outfile, "mcpl_point_source_file_generator", size, buffer); + free(buffer); + } + fclose(fp); + } else { + fprintf(stderr,"Warning: could not open c source generator file, hence not embedded.\n"); + } + + + /*the main particle loop*/ + particle=&Particle; + int i; + for (i=0;iposition[0]=0; + particle->position[1]=0; + particle->position[2]=0; + + /*generate a random direction on unit sphere*/ + double nrm=2.0; + double vx,vy,vz; + int iter=0; + do { + if(iter>100){ + printf("warning: exceeed max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); + } + vx=rand01()*2.0-1.0; + vy=rand01()*2.0-1.0; + vz=rand01()*2.0-1.0; + nrm=(vx*vx + vy*vy + vz*vz); + iter++; + } while (nrm>1.0); + vx/=sqrt(nrm); + vy/=sqrt(nrm); + vz/=sqrt(nrm); + particle->direction[0]=vx; + particle->direction[1]=vy; + particle->direction[2]=vz; + + /*generate the kinetic energy (in MeV) of the particle*/ + particle->ekin=1e-3; + + /*set time=0*/ + particle->time=0; + /*set weight*/ + particle->weight=1; + + particle->userflags=0; + mcpl_add_particle(outfile,particle); + } + mcpl_closeandgzip_outfile(outfile); +} From d8902a603e7d66550c7ee4b3d0f782edf7594a12 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 16:26:01 -0500 Subject: [PATCH 0441/2654] add volume parameter; add attributes to docstring; implement _get_all_depletion_nuclides, _get_nuclides_with_data --- openmc/deplete/flux_operator.py | 75 ++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index e3bc6a5f3..c12cfe084 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -45,6 +45,8 @@ class FluxSpectraDepletionOperator(TransportOperator): Parameters ---------- + volume : float + Volume of the material being depleted in cm^3 nuclides : dict of str to float Dictionary with nuclides names as keys and concentration as values. micro_xs : pandas.DataFrame @@ -82,9 +84,22 @@ class FluxSpectraDepletionOperator(TransportOperator): prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. + number : openmc.deplete.AtomNumber + Total number of atoms in simulation. + nuclides_with_data : set of str + A set listing all unique nuclides available from cross_sections.xml. + chain : openmc.deplete.Chain + The depletion chain information necessary to form matrices and tallies. + reaction_rates : openmc.deplete.ReactionRates + Reaction rates from the last operator step. + heavy_metal : float + Initial heavy metal inventory [g] + prev_res : Results or None + Results from a previous depletion calculation. ``None`` if no + results are to be used. """ - def __init__(self, nuclides, micro_xs, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, + def __init__(self, volume, nuclides, micro_xs, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None): super.__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False @@ -101,12 +116,13 @@ class FluxSpectraDepletionOperator(TransportOperator): check_value('nuclides', nuclides, dict, str) check_type('micro_xs', micro_xs, pd.DataFrame) - # Clear out OpenMC, create task lists, distribute - #self.burnable_mats, volume, nuclides = self.get_burnable_mats() + self._micro_xs = micro_xs + + nuclides = self._get_all_depletion_nuclides(volume, nuclides) # TODO: add support for loading previous results - # TODO : Determine which nuclides have incident neutron data + # Determine which nuclides have cross section data self.nuclides_with_data = self._get_nuclides_with_data() # Select nuclides with data that are also in the chain @@ -115,7 +131,7 @@ class FluxSpectraDepletionOperator(TransportOperator): # TODO : implement _extract_number # Extract number densities from the geometry / previous depletion run - self._extract_number('0', volume, list(nuclides.keys()), self.prev_res) + self._extract_number('0', volume, nuclides, self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( @@ -194,7 +210,7 @@ class FluxSpectraDepletionOperator(TransportOperator): # Store microscopic cross sections in rates array for nuc in nuclides: for rxn in self.chain.reactions: - rates.set('0', nuc, rxn, self.micro_xs[rxn].loc[nuc]) + rates.set('0', nuc, rxn, self._micro_xs[rxn].loc[nuc]) # Get reaction rate in reactions/sec rates *= self.flux_spectra @@ -331,4 +347,51 @@ class FluxSpectraDepletionOperator(TransportOperator): nuc_list = comm.bcast(nuc_list) return [nuc for nuc in nuc_list if nuc in self.chain] + def _get_all_depletion_nuclides(self, volume, nuclides): + """Determine nuclides that will show up in simulation + + Parameters + ---------- + volume : float + Volume of material in cm^3 + + Returns + ------- + nuclides : list of str + Nuclides in order of how they'll appear in the simulation. + + """ + + model_nuclides = set() + + self.heavy_metal = 0.0 + + bu_mat = openmc.Material() + bu_mat.volume = volume + for n, conc in nuclides: + bu_mat.add_nuclides(n,conc) + model_nuclides.add(n) + + self.heavy_metal = bu_mat.fissionable_mass + + # Sort the sets + model_nuclides = sorted(model_nuclides) + + # Construct a global nuclide dictionary, burned first + nuclides = list(self.chain.nuclide_dict) + for nuc in model_nuclides: + if nuc not in nuclides: + nuclides.append(nuc) + + return nuclides + + def _get_nuclides_with_data(self): + """Finds nuclides with cross section data""" + nuclides = set() + for name in self._micro_xs.index: + if name not in nuclides: + nuclides.add(name) + + return nuclides + From 13c9fdccf031c11abe809e6a67f993c120e762e1 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 27 Jun 2022 16:59:04 -0500 Subject: [PATCH 0442/2654] Add comments --- openmc/deplete/flux_operator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index c12cfe084..d1be3f608 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -170,9 +170,12 @@ class FluxSpectraDepletionOperator(TransportOperator): # Update the number densities regardless of the source rate self.number.set_density(vec) + ## TODO : make sure this function works w the current structure. self._update_materials() # Update nuclides data in preparation for transport solve + + ## TODO : make sure this function works w the current structure. nuclides = self._get_reaction_nuclides() self._yield_helper.update_tally_nuclides(nuclides) From a4f98b489c161ed4b7ac26cca4e945d535ccaba3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 23 May 2022 14:20:01 -0500 Subject: [PATCH 0443/2654] Change values in dict returned by Material.get_nuclide_atom_densities --- openmc/cell.py | 8 ++++---- openmc/deplete/operator.py | 15 +++++++-------- openmc/material.py | 20 ++++++++++++-------- openmc/plotter.py | 12 ++++-------- tests/unit_tests/test_deplete_activation.py | 2 +- tests/unit_tests/test_material.py | 15 +++++++-------- tests/unit_tests/test_model.py | 18 ++++++++---------- 7 files changed, 43 insertions(+), 47 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 103a34fe6..4b419e1c6 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -214,8 +214,8 @@ class Cell(IDManagerMixin): self._atoms = self._fill.get_nuclide_atom_densities() # Convert to total number of atoms - for key, nuclide in self._atoms.items(): - atom = nuclide[1] * self._volume * 1.0e+24 + for key, atom_per_bcm in self._atoms.items(): + atom = atom_per_bcm * self._volume * 1.0e+24 self._atoms[key] = atom elif self.fill_type == 'distribmat': @@ -224,12 +224,12 @@ class Cell(IDManagerMixin): partial_volume = self.volume / len(self.fill) self._atoms = OrderedDict() for mat in self.fill: - for key, nuclide in mat.get_nuclide_atom_densities().items(): + for key, atom_per_bcm in mat.get_nuclide_atom_densities().items(): # To account for overlap of nuclides between distribmat # we need to append new atoms to any existing value # hence it is necessary to ask for default. atom = self._atoms.setdefault(key, 0) - atom += nuclide[1] * partial_volume * 1.0e+24 + atom += atom_per_bcm * partial_volume * 1.0e+24 self._atoms[key] = atom else: diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 327c762e0..7ef874e87 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -528,9 +528,9 @@ class Operator(TransportOperator): """ mat_id = str(mat.id) - for nuclide, density in mat.get_nuclide_atom_densities().values(): - number = density * 1.0e24 - self.number.set_atom_density(mat_id, nuclide, number) + for nuclide, atom_per_bcm in mat.get_nuclide_atom_densities().items(): + atom_per_cc = atom_per_bcm * 1.0e24 + self.number.set_atom_density(mat_id, nuclide, atom_per_cc) def _set_number_from_results(self, mat, prev_res): """Extracts material nuclides and number densities. @@ -556,16 +556,15 @@ class Operator(TransportOperator): # Merge lists of nuclides, with the same order for every calculation geom_nuc_densities.update(depl_nuc) - for nuclide in geom_nuc_densities.keys(): + for nuclide, atom_per_bcm in geom_nuc_densities.items(): if nuclide in depl_nuc: concentration = prev_res.get_atoms(mat_id, nuclide)[1][-1] volume = prev_res[-1].volume[mat_id] - number = concentration / volume + atom_per_cc = concentration / volume else: - density = geom_nuc_densities[nuclide][1] - number = density * 1.0e24 + atom_per_cc = atom_per_bcm * 1.0e24 - self.number.set_atom_density(mat_id, nuclide, number) + self.number.set_atom_density(mat_id, nuclide, atom_per_cc) def initial_condition(self): """Performs final setup and returns initial condition. diff --git a/openmc/material.py b/openmc/material.py index 3c2a98ffd..073dab712 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -259,10 +259,10 @@ class Material(IDManagerMixin): if self.volume is None: raise ValueError("Volume must be set in order to determine mass.") density = 0.0 - for nuc, atoms_per_cc in self.get_nuclide_atom_densities().values(): + for nuc, atoms_per_bcm in self.get_nuclide_atom_densities().items(): Z = openmc.data.zam(nuc)[0] if Z >= 90: - density += 1e24 * atoms_per_cc * openmc.data.atomic_mass(nuc) \ + density += 1e24 * atoms_per_bcm * openmc.data.atomic_mass(nuc) \ / openmc.data.AVOGADRO return density*self.volume @@ -786,11 +786,15 @@ class Material(IDManagerMixin): """Returns all nuclides in the material and their atomic densities in units of atom/b-cm + .. versionchanged:: 0.13.1 + The values in the dictionary were changed from a tuple containing + the nuclide name and the density to just the density. + Returns ------- nuclides : dict - Dictionary whose keys are nuclide names and values are tuples of - (nuclide, density in atom/b-cm) + Dictionary whose keys are nuclide names and values are densities in + [atom/b-cm] """ @@ -850,7 +854,7 @@ class Material(IDManagerMixin): nuclides = OrderedDict() for n, nuc in enumerate(nucs): - nuclides[nuc] = (nuc, nuc_densities[n]) + nuclides[nuc] = nuc_densities[n] return nuclides @@ -870,9 +874,9 @@ class Material(IDManagerMixin): """ mass_density = 0.0 - for nuc, atoms_per_cc in self.get_nuclide_atom_densities().values(): + for nuc, atoms_per_bcm in self.get_nuclide_atom_densities().items(): if nuclide is None or nuclide == nuc: - density_i = 1e24 * atoms_per_cc * openmc.data.atomic_mass(nuc) \ + density_i = 1e24 * atoms_per_bcm * openmc.data.atomic_mass(nuc) \ / openmc.data.AVOGADRO mass_density += density_i return mass_density @@ -1092,7 +1096,7 @@ class Material(IDManagerMixin): nuclides_per_cc = defaultdict(float) mass_per_cc = defaultdict(float) for mat, wgt in zip(materials, wgts): - for nuc, atoms_per_bcm in mat.get_nuclide_atom_densities().values(): + for nuc, atoms_per_bcm in mat.get_nuclide_atom_densities().items(): nuc_per_cc = wgt*1.e24*atoms_per_bcm nuclides_per_cc[nuc] += nuc_per_cc mass_per_cc[nuc] += nuc_per_cc*openmc.data.atomic_mass(nuc) / \ diff --git a/openmc/plotter.py b/openmc/plotter.py index 92acaf5bb..16760868e 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -542,15 +542,11 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., if isinstance(this, openmc.Material): # Expand elements in to nuclides with atomic densities - nuclides = this.get_nuclide_atom_densities() - # For ease of processing split out the nuclide and its fraction - nuc_fractions = {nuclide[1][0]: nuclide[1][1] - for nuclide in nuclides.items()} + nuc_fractions = this.get_nuclide_atom_densities() # Create a dict of [nuclide name] = nuclide object to carry forward # with a common nuclides format between openmc.Material and # openmc.Element objects - nuclides = {nuclide[1][0]: nuclide[1][0] - for nuclide in nuclides.items()} + nuclides = {nuclide: nuclide for nuclide in nuc_fractions} else: # Expand elements in to nuclides with atomic densities nuclides = this.expand(1., 'ao', enrichment=enrichment, @@ -885,13 +881,13 @@ def _calculate_mgxs_elem_mat(this, types, library, orders=None, # Check to see if we have nuclides/elements or a macroscopic object if this._macroscopic is not None: # We have macroscopics - nuclides = {this._macroscopic: (this._macroscopic, this.density)} + nuclides = {this._macroscopic: this.density} else: # Expand elements in to nuclides with atomic densities nuclides = this.get_nuclide_atom_densities() # For ease of processing split out nuc and nuc_density - nuc_fraction = [nuclide[1][1] for nuclide in nuclides.items()] + nuc_fraction = list(nuclides.values()) else: T = temperature # Expand elements in to nuclides with atomic densities diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 0b82a5fbc..cb3b86b9c 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -92,7 +92,7 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts w = model.geometry.get_materials_by_name('tungsten')[0] atom_densities = w.get_nuclide_atom_densities() - atom_per_cc = 1e24 * atom_densities['W186'][1] # Density in atom/cm^3 + atom_per_cc = 1e24 * atom_densities['W186'] # Density in atom/cm^3 n0 = atom_per_cc * w.volume # Absolute number of atoms # Pick a random irradiation time and then determine necessary source rate to diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index c15a4b9e5..374b5a3d8 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -100,7 +100,7 @@ def test_add_elements_by_formula(): m.add_elements_from_formula('Li4SiO4') # checking the ratio of elements is 4:1:4 for Li:Si:O elem = defaultdict(float) - for nuclide, adens in m.get_nuclide_atom_densities().values(): + for nuclide, adens in m.get_nuclide_atom_densities().items(): if nuclide.startswith("Li"): elem["Li"] += adens if nuclide.startswith("Si"): @@ -117,7 +117,7 @@ def test_add_elements_by_formula(): 'O16': 0.443386, 'O17': 0.000168} nuc_dens = m.get_nuclide_atom_densities() for nuclide in ref_dens: - assert nuc_dens[nuclide][1] == pytest.approx(ref_dens[nuclide], 1e-2) + assert nuc_dens[nuclide] == pytest.approx(ref_dens[nuclide], 1e-2) # testing the correct nuclides are added to the Material when enriched m = openmc.Material() @@ -129,7 +129,7 @@ def test_add_elements_by_formula(): 'O16': 0.443386, 'O17': 0.000168} nuc_dens = m.get_nuclide_atom_densities() for nuclide in ref_dens: - assert nuc_dens[nuclide][1] == pytest.approx(ref_dens[nuclide], 1e-2) + assert nuc_dens[nuclide] == pytest.approx(ref_dens[nuclide], 1e-2) # testing the use of brackets m = openmc.Material() @@ -137,7 +137,7 @@ def test_add_elements_by_formula(): # checking the ratio of elements is 2:2:6 for Mg:N:O elem = defaultdict(float) - for nuclide, adens in m.get_nuclide_atom_densities().values(): + for nuclide, adens in m.get_nuclide_atom_densities().items(): if nuclide.startswith("Mg"): elem["Mg"] += adens if nuclide.startswith("N"): @@ -155,7 +155,7 @@ def test_add_elements_by_formula(): 'O16': 0.599772, 'O17': 0.000227} nuc_dens = m.get_nuclide_atom_densities() for nuclide in ref_dens: - assert nuc_dens[nuclide][1] == pytest.approx(ref_dens[nuclide], 1e-2) + assert nuc_dens[nuclide] == pytest.approx(ref_dens[nuclide], 1e-2) # testing non integer multiplier results in a value error m = openmc.Material() @@ -289,8 +289,7 @@ def test_get_nuclide_densities(uo2): def test_get_nuclide_atom_densities(uo2): - nucs = uo2.get_nuclide_atom_densities() - for nuc, density in nucs.values(): + for nuc, density in uo2.get_nuclide_atom_densities().items(): assert nuc in ('U235', 'O16') assert density > 0 @@ -341,7 +340,7 @@ def test_borated_water(): 'O16':2.4672e-02} nuc_dens = m.get_nuclide_atom_densities() for nuclide in ref_dens: - assert nuc_dens[nuclide][1] == pytest.approx(ref_dens[nuclide], 1e-2) + assert nuc_dens[nuclide] == pytest.approx(ref_dens[nuclide], 1e-2) assert m.id == 50 # Test the Celsius conversion. diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 10417b20e..9b05ed2a5 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -391,16 +391,14 @@ def test_py_lib_attributes(run_in_tmpdir, pin_model_attributes, mpi_intracomm): assert openmc.lib.materials[1].get_density('atom/b-cm') == \ pytest.approx(0.06891296988603757, abs=1e-13) mat_a_dens = np.sum( - [v[1] for v in test_model.materials[0]. - get_nuclide_atom_densities().values()]) + list(test_model.materials[0].get_nuclide_atom_densities().values())) assert mat_a_dens == pytest.approx(0.06891296988603757, abs=1e-8) # Change the density test_model.update_densities(['UO2'], 2.) assert openmc.lib.materials[1].get_density('atom/b-cm') == \ pytest.approx(2., abs=1e-13) mat_a_dens = np.sum( - [v[1] for v in test_model.materials[0]. - get_nuclide_atom_densities().values()]) + list(test_model.materials[0].get_nuclide_atom_densities().values())) assert mat_a_dens == pytest.approx(2., abs=1e-8) # Now lets do the cell temperature updates. @@ -441,7 +439,7 @@ def test_deplete(run_in_tmpdir, pin_model_attributes, mpi_intracomm): test_model = openmc.Model(geom, mats, settings, tals, plots) initial_mat = mats[0].clone() - initial_u = initial_mat.get_nuclide_atom_densities()['U235'][1] + initial_u = initial_mat.get_nuclide_atom_densities()['U235'] # Note that the chain file includes only U-235 fission to a stable Xe136 w/ # a yield of 100%. Thus all the U235 we lose becomes Xe136 @@ -453,8 +451,8 @@ def test_deplete(run_in_tmpdir, pin_model_attributes, mpi_intracomm): operator_kwargs=op_kwargs, power=1., output=False) # Get the new Xe136 and U235 atom densities - after_xe = mats[0].get_nuclide_atom_densities()['Xe136'][1] - after_u = mats[0].get_nuclide_atom_densities()['U235'][1] + after_xe = mats[0].get_nuclide_atom_densities()['Xe136'] + after_u = mats[0].get_nuclide_atom_densities()['U235'] assert after_xe + after_u == pytest.approx(initial_u, abs=1e-15) assert test_model.is_initialized is False @@ -462,7 +460,7 @@ def test_deplete(run_in_tmpdir, pin_model_attributes, mpi_intracomm): mats[0].nuclides.clear() densities = initial_mat.get_nuclide_atom_densities() tot_density = 0. - for nuc, density in densities.values(): + for nuc, density in densities.items(): mats[0].add_nuclide(nuc, density) tot_density += density mats[0].set_density('atom/b-cm', tot_density) @@ -473,8 +471,8 @@ def test_deplete(run_in_tmpdir, pin_model_attributes, mpi_intracomm): operator_kwargs=op_kwargs, power=1., output=False) # Get the new Xe136 and U235 atom densities - after_lib_xe = mats[0].get_nuclide_atom_densities()['Xe136'][1] - after_lib_u = mats[0].get_nuclide_atom_densities()['U235'][1] + after_lib_xe = mats[0].get_nuclide_atom_densities()['Xe136'] + after_lib_u = mats[0].get_nuclide_atom_densities()['U235'] assert after_lib_xe + after_lib_u == pytest.approx(initial_u, abs=1e-15) assert test_model.is_initialized is True From 7fcc20472690c49cf2b0508b099dc440b6249dc4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 23 May 2022 14:43:34 -0500 Subject: [PATCH 0444/2654] Implement Material.get_nuclide_atoms method --- openmc/material.py | 19 +++++++++++++++++++ tests/unit_tests/test_material.py | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/openmc/material.py b/openmc/material.py index 073dab712..ea42d64b1 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -858,6 +858,25 @@ class Material(IDManagerMixin): return nuclides + def get_nuclide_atoms(self): + """Return number of atoms of each nuclide in the material + + .. versionadded:: 0.13.1 + + Returns + ------- + dict + Dictionary whose keys are nuclide names and values are number of + atoms present in the material. + + """ + if self.volume is None: + raise ValueError("Volume must be set in order to determine atoms.") + atoms = {} + for nuclide, atom_per_bcm in self.get_nuclide_atom_densities().items(): + atoms[nuclide] = 1.0e24 * atom_per_bcm * self.volume + return atoms + def get_mass_density(self, nuclide=None): """Return mass density of one or all nuclides diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 374b5a3d8..fd0e4f624 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -294,6 +294,16 @@ def test_get_nuclide_atom_densities(uo2): assert density > 0 +def test_get_nuclide_atoms(): + mat = openmc.Material() + mat.add_nuclide('Li6', 1.0) + mat.set_density('atom/cm3', 3.26e20) + mat.volume = 100.0 + + atoms = mat.get_nuclide_atoms() + assert atoms['Li6'] == pytest.approx(mat.density * mat.volume) + + def test_mass(): m = openmc.Material() m.add_nuclide('Zr90', 1.0, 'wo') From 19494cccd022cdf9ee9c0c8e6461bea494d95e69 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 12:47:36 -0500 Subject: [PATCH 0445/2654] Add check in Decay.decay_constant for erroneous half-life --- openmc/data/decay.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 5ca2b235a..51a594bc8 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -465,11 +465,10 @@ class Decay(EqualityMixin): @property def decay_constant(self): - if hasattr(self.half_life, 'n'): - return log(2.)/self.half_life - else: - mu, sigma = self.half_life - return ufloat(log(2.)/mu, log(2.)/mu**2*sigma) + if self.half_life.n == 0.0: + name = self.nuclide['name'] + raise ValueError(f"{name} is listed as unstable but has a zero half-life.") + return log(2.)/self.half_life @property def decay_energy(self): From 3c20b1e415e89b1b2b2b8e4953710f0b6851fb62 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 28 Jun 2022 08:00:16 -0500 Subject: [PATCH 0446/2654] Fix use of get_nuclide_atom_densities in Material.activity property --- openmc/material.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index ea42d64b1..1341746dc 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -86,6 +86,9 @@ class Material(IDManagerMixin): fissionable_mass : float Mass of fissionable nuclides in the material in [g]. Requires that the :attr:`volume` attribute is set. + activity : float + Activity of the material in [Bq]. Requires that the :attr:`volume` + attribute is set. """ @@ -152,7 +155,7 @@ class Material(IDManagerMixin): for key, value in atoms_per_barn_cm.items(): half_life = openmc.data.half_life(key) if half_life: - total_activity += value[1] / half_life + total_activity += value / half_life total_activity *= math.log(2) * 1e24 * self.volume return total_activity From fc615451d04c358d0f32bb72837fc52992fb39b0 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 28 Jun 2022 15:54:49 +0200 Subject: [PATCH 0447/2654] added method to Tally --- openmc/tallies.py | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/openmc/tallies.py b/openmc/tallies.py index d0355f14e..f559c392c 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -8,6 +8,8 @@ from pathlib import Path from xml.etree import ElementTree as ET import h5py +import vtk +import vtk.util.numpy_support as nps import numpy as np import pandas as pd import scipy.sparse as sps @@ -457,6 +459,54 @@ class Tally(IDManagerMixin): self._std_dev = np.reshape(self._std_dev.toarray(), self.shape) self._sparse = False + def write_to_vtk(self, filename): + mesh = None + for f in self.filters: + if isinstance(f, openmc.MeshFilter): + if isinstance(f.mesh, (openmc.RegularMesh, openmc.CylindricalMesh)): + mesh = f.mesh + break + + if not mesh: + raise ValueError( + "write_to_vtk only works with openmc.RegularMesh, openmc.CylindricalMesh" + ) + + if isinstance(mesh, openmc.RegularMesh): + vtk_grid = voxels_to_vtk( + x_vals=np.linspace( + mesh.lower_left[0], + mesh.upper_right[0], + num=mesh.dimension[0] + 1, + ), + y_vals=np.linspace( + mesh.lower_left[1], + mesh.upper_right[1], + num=mesh.dimension[1] + 1, + ), + z_vals=np.linspace( + mesh.lower_left[2], + mesh.upper_right[2], + num=mesh.dimension[2] + 1, + ), + mean=self.mean, + std_dev=self.std_dev, + cylindrical=False, + ) + elif isinstance(mesh, openmc.CylindricalMesh): + vtk_grid = voxels_to_vtk( + x_vals=mesh.r_grid, + y_vals=mesh.phi_grid, + z_vals=mesh.z_grid, + mean=self.mean, + std_dev=self.std_dev, + cylindrical=True, + ) + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() + def remove_score(self, score): """Remove a score from the tally @@ -3229,3 +3279,39 @@ class Tallies(cv.CheckedList): tallies.append(tally) return cls(tallies) + + +def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): + vtk_box = vtk.vtkStructuredGrid() + + vtk_box.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) + + # points + points = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) + if cylindrical: + points_cartesian = np.copy(points) + r = points[:, 0] + phi = points[:, 1] + z = points[:, 2] + points_cartesian[:, 0] = r * np.cos(phi) + points_cartesian[:, 1] = r * np.sin(phi) + points_cartesian[:, 2] = z + + vtkPts = vtk.vtkPoints() + vtkPts.SetData(nps.numpy_to_vtk(points, deep=True)) + + vtk_box.SetPoints(vtkPts) + + # # data + mean_array = vtk.vtkDoubleArray() + mean_array.SetName("mean") + mean_array.SetArray(mean, mean.size, True) + + std_dev_array = vtk.vtkDoubleArray() + std_dev_array.SetName("std_dev") + std_dev_array.SetArray(std_dev, std_dev.size, True) + + vtk_box.GetCellData().AddArray(mean_array) + vtk_box.GetCellData().AddArray(std_dev_array) + + return vtk_box From e870ab2040e6d2a9894eb99e413a5174f83ae546 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 28 Jun 2022 16:00:54 +0200 Subject: [PATCH 0448/2654] added RectilinearMesh --- openmc/tallies.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index f559c392c..20e6e3996 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -463,13 +463,13 @@ class Tally(IDManagerMixin): mesh = None for f in self.filters: if isinstance(f, openmc.MeshFilter): - if isinstance(f.mesh, (openmc.RegularMesh, openmc.CylindricalMesh)): + if isinstance(f.mesh, (openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh)): mesh = f.mesh break if not mesh: raise ValueError( - "write_to_vtk only works with openmc.RegularMesh, openmc.CylindricalMesh" + "write_to_vtk only works with openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh" ) if isinstance(mesh, openmc.RegularMesh): @@ -493,6 +493,15 @@ class Tally(IDManagerMixin): std_dev=self.std_dev, cylindrical=False, ) + if isinstance(mesh, openmc.RectilinearMesh): + vtk_grid = voxels_to_vtk( + x_vals=mesh.x_grid, + y_vals=mesh.y_grid, + z_vals=mesh.z_grid, + mean=self.mean, + std_dev=self.std_dev, + cylindrical=False, + ) elif isinstance(mesh, openmc.CylindricalMesh): vtk_grid = voxels_to_vtk( x_vals=mesh.r_grid, From 06c5d3ec584c9ef9a62b08c561945b34e2e6b4e9 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 28 Jun 2022 16:04:33 +0200 Subject: [PATCH 0449/2654] added comments --- openmc/tallies.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 20e6e3996..6797253e1 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -460,6 +460,7 @@ class Tally(IDManagerMixin): self._sparse = False def write_to_vtk(self, filename): + # check that tally has a MeshFilter mesh = None for f in self.filters: if isinstance(f, openmc.MeshFilter): @@ -511,6 +512,8 @@ class Tally(IDManagerMixin): std_dev=self.std_dev, cylindrical=True, ) + + # write the .vtk file writer = vtk.vtkStructuredGridWriter() writer.SetFileName(filename) writer.SetInputData(vtk_grid) @@ -3291,36 +3294,32 @@ class Tallies(cv.CheckedList): def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): - vtk_box = vtk.vtkStructuredGrid() + vtk_grid = vtk.vtkStructuredGrid() - vtk_box.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) + vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) - # points + # create points points = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) - if cylindrical: + if cylindrical: # transform points to cartesian coordinates points_cartesian = np.copy(points) - r = points[:, 0] - phi = points[:, 1] - z = points[:, 2] + r, phi, z = points[:, 0], points[:, 1], points[:, 2] points_cartesian[:, 0] = r * np.cos(phi) points_cartesian[:, 1] = r * np.sin(phi) points_cartesian[:, 2] = z vtkPts = vtk.vtkPoints() vtkPts.SetData(nps.numpy_to_vtk(points, deep=True)) + vtk_grid.SetPoints(vtkPts) - vtk_box.SetPoints(vtkPts) - - # # data + # add mean and std dev data mean_array = vtk.vtkDoubleArray() mean_array.SetName("mean") mean_array.SetArray(mean, mean.size, True) + vtk_grid.GetCellData().AddArray(mean_array) std_dev_array = vtk.vtkDoubleArray() std_dev_array.SetName("std_dev") std_dev_array.SetArray(std_dev, std_dev.size, True) + vtk_grid.GetCellData().AddArray(std_dev_array) - vtk_box.GetCellData().AddArray(mean_array) - vtk_box.GetCellData().AddArray(std_dev_array) - - return vtk_box + return vtk_grid From 30b06fa2910a51ac04a249170bff27d54cb3f26a Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 28 Jun 2022 16:08:36 +0200 Subject: [PATCH 0450/2654] docstrings --- openmc/tallies.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 6797253e1..77f0b8cd3 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -460,6 +460,15 @@ class Tally(IDManagerMixin): self._sparse = False def write_to_vtk(self, filename): + """Writes the tally to a vtk file + + Args: + filename (str): the filename (must end with .vtk) + + Raises: + ValueError: if no MeshFilter with appropriate mesh was found + (SphericalMesh not supported) + """ # check that tally has a MeshFilter mesh = None for f in self.filters: @@ -512,7 +521,7 @@ class Tally(IDManagerMixin): std_dev=self.std_dev, cylindrical=True, ) - + # write the .vtk file writer = vtk.vtkStructuredGridWriter() writer.SetFileName(filename) @@ -3294,6 +3303,20 @@ class Tallies(cv.CheckedList): def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): + """Creates a vtk object from a list of X, Y, Z values and mean/std_dev data. + + Args: + x_vals (list): X values. + y_vals (list): Y values. + z_vals (list): Z values. + mean (np.array): the tally mean. + std_dev (np.array): the tally standard deviation. + cylindrical (bool, optional): If set to True, cylindrical coordinates + (r, phi, z) are assumed. Defaults to True. + + Returns: + vtkStructuredGrid: a vtk object containing tally data on the appropriate grid + """ vtk_grid = vtk.vtkStructuredGrid() vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) From 06c6bcd7d269aa3b3317c8d64f9cf4318170468c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 28 Jun 2022 16:09:32 +0200 Subject: [PATCH 0451/2654] added TODO --- openmc/tallies.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmc/tallies.py b/openmc/tallies.py index 77f0b8cd3..c0f410524 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3317,6 +3317,9 @@ def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): Returns: vtkStructuredGrid: a vtk object containing tally data on the appropriate grid """ + + # TODO: should this be a method of Tally? + vtk_grid = vtk.vtkStructuredGrid() vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) From 877a62c0af072e14c3b62991f21a6648352dc8bb Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 28 Jun 2022 16:43:42 +0200 Subject: [PATCH 0452/2654] fixed cylindrical --- openmc/tallies.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openmc/tallies.py b/openmc/tallies.py index c0f410524..2e31e8ee2 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3332,6 +3332,7 @@ def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): points_cartesian[:, 0] = r * np.cos(phi) points_cartesian[:, 1] = r * np.sin(phi) points_cartesian[:, 2] = z + points = points_cartesian vtkPts = vtk.vtkPoints() vtkPts.SetData(nps.numpy_to_vtk(points, deep=True)) From 1eb8670f2b93cbbb42912dd7903c1d1ae18b1d33 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 28 Jun 2022 16:46:10 +0200 Subject: [PATCH 0453/2654] mean and std_dev are np.zeros if None (for testing without running a sim) --- openmc/tallies.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openmc/tallies.py b/openmc/tallies.py index 2e31e8ee2..75c7ea8f3 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3341,11 +3341,23 @@ def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): # add mean and std dev data mean_array = vtk.vtkDoubleArray() mean_array.SetName("mean") + if mean is None: + mean = np.zeros( + (len(x_vals) - 1) + * (len(y_vals) - 1) + * (len(z_vals) - 1) + ) mean_array.SetArray(mean, mean.size, True) vtk_grid.GetCellData().AddArray(mean_array) std_dev_array = vtk.vtkDoubleArray() std_dev_array.SetName("std_dev") + if std_dev is None: + std_dev = np.zeros( + (len(x_vals) - 1) + * (len(y_vals) - 1) + * (len(z_vals) - 1) + ) std_dev_array.SetArray(std_dev, std_dev.size, True) vtk_grid.GetCellData().AddArray(std_dev_array) From 3d0b404b7a99388296dda50d087d267bf3c6f917 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 28 Jun 2022 16:06:17 +0100 Subject: [PATCH 0454/2654] added multi stages option --- Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 755d9f2a0..152590161 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ # sudo docker run image_name:tag_name or ID with no tag sudo docker run ID number -FROM debian:bullseye-slim +FROM debian:bullseye-slim AS dependencies # By default this Dockerfile builds OpenMC without DAGMC and LIBMESH support ARG build_dagmc=off @@ -172,6 +172,8 @@ RUN if [ "$build_libmesh" = "on" ]; then \ && rm -rf ${LIBMESH_INSTALL_DIR}/build ${LIBMESH_INSTALL_DIR}/libmesh ; \ fi +FROM dependencies as build + # clone and install openmc RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ && git clone --shallow-submodules --recurse-submodules --single-branch -b ${openmc_branch} --depth=1 ${OPENMC_REPO} \ @@ -207,5 +209,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ && cd ../openmc && pip install .[test,depletion-mpi] \ && python -c "import openmc" +FROM build as release + # Download cross sections (NNDC and WMP) and ENDF data needed by test suite RUN ${HOME}/OpenMC/openmc/tools/ci/download-xs.sh From 419351bb260f837386bcd5c6e798405638820e17 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 28 Jun 2022 16:14:52 +0100 Subject: [PATCH 0455/2654] uppercase AS --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 152590161..341390c9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -172,7 +172,7 @@ RUN if [ "$build_libmesh" = "on" ]; then \ && rm -rf ${LIBMESH_INSTALL_DIR}/build ${LIBMESH_INSTALL_DIR}/libmesh ; \ fi -FROM dependencies as build +FROM dependencies AS build # clone and install openmc RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ @@ -209,7 +209,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ && cd ../openmc && pip install .[test,depletion-mpi] \ && python -c "import openmc" -FROM build as release +FROM build AS release # Download cross sections (NNDC and WMP) and ENDF data needed by test suite RUN ${HOME}/OpenMC/openmc/tools/ci/download-xs.sh From 782d987fc836494166ffb66ab9e9f81888666582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Tue, 28 Jun 2022 20:18:52 +0200 Subject: [PATCH 0456/2654] Optional vtk import Co-authored-by: Jonathan Shimwell --- openmc/tallies.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 75c7ea8f3..b795fc83a 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -8,8 +8,6 @@ from pathlib import Path from xml.etree import ElementTree as ET import h5py -import vtk -import vtk.util.numpy_support as nps import numpy as np import pandas as pd import scipy.sparse as sps @@ -470,6 +468,12 @@ class Tally(IDManagerMixin): (SphericalMesh not supported) """ # check that tally has a MeshFilter + try: + import vtk + import vtk.util.numpy_support as nps + except ImportError: + msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' + raise ImportError(msg) mesh = None for f in self.filters: if isinstance(f, openmc.MeshFilter): From a0f8b9937d85bae835f8a1e2d3a379d650e4585c Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 28 Jun 2022 14:37:42 -0500 Subject: [PATCH 0457/2654] add keff handling; add comments from review with paul; add density to rxn rate calculation to get right units --- openmc/deplete/flux_operator.py | 98 ++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 25 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index d1be3f608..cd06894f6 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -33,10 +33,8 @@ from .helpers import ( class FluxSpectraDepletionOperator(TransportOperator): - """Depletion operator that uses a user provided flux spectrum to - calculate reaction rates. The flux provided must match the type of cross - section library in use (contunuous flux for continuous energy library, - multi-group flux for multi-group library) + """Depletion operator that uses a user provided flux spectrum and one-group + cross sections calculate reaction rates. Instances of this class can be used to perform depletion using one group cross sections and constant flux. Normally, a user needn't call methods of @@ -49,6 +47,7 @@ class FluxSpectraDepletionOperator(TransportOperator): Volume of the material being depleted in cm^3 nuclides : dict of str to float Dictionary with nuclides names as keys and concentration as values. + Nuclide concentration is assumed to be in [units?] micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. @@ -56,6 +55,9 @@ class FluxSpectraDepletionOperator(TransportOperator): Flux spectrum [n cm^-2 s^-1] chain_file : str Path to the depletion chain XML file. + keff : 2-tuple of float, optional + keff eigenvalue and uncertainty from transport calculation. + Defualt is None. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. @@ -99,7 +101,7 @@ class FluxSpectraDepletionOperator(TransportOperator): results are to be used. """ - def __init__(self, volume, nuclides, micro_xs, flux_spectra, chain_file, fission_q=None, dilute_initial=1.0e3, + def __init__(self, volume, nuclides, micro_xs, flux_spectra, chain_file, keff=None, fission_q=None, dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None): super.__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False @@ -117,6 +119,7 @@ class FluxSpectraDepletionOperator(TransportOperator): check_type('micro_xs', micro_xs, pd.DataFrame) self._micro_xs = micro_xs + self._keff = keff nuclides = self._get_all_depletion_nuclides(volume, nuclides) @@ -131,18 +134,13 @@ class FluxSpectraDepletionOperator(TransportOperator): # TODO : implement _extract_number # Extract number densities from the geometry / previous depletion run + #!!! consider removing this and just using the nuclides dict... self._extract_number('0', volume, nuclides, self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( '0', self._burnable_nucs, self.chain.reactions) - # Initialize normalization helper - #if normalization_mode == "fission-q": - # self._normalization_helper = ChainFissionHelper() - #else: - # self._normalization_helper = SourceRateHelper() - # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper fission_yield_opts = ( @@ -169,6 +167,7 @@ class FluxSpectraDepletionOperator(TransportOperator): """ # Update the number densities regardless of the source rate + #!!! See previous excamation point comment self.number.set_density(vec) ## TODO : make sure this function works w the current structure. self._update_materials() @@ -176,24 +175,18 @@ class FluxSpectraDepletionOperator(TransportOperator): # Update nuclides data in preparation for transport solve ## TODO : make sure this function works w the current structure. + # this nuclides varibale is all the nuclides that will show up via depletion + # that have xs data nuclides = self._get_reaction_nuclides() self._yield_helper.update_tally_nuclides(nuclides) rates = self.reaction_rates rates.fill(0.0) - # Get k and uncertainty - # TODO : add functionality to get this from the transport solver - keff = ... - # Form fast map nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides] react_ind = [rates.index_rx[react] for react in self.chain.reactions] - # Keep track of energy produced from all reactions in eV per source - # particle - self._normalization_helper.reset() - # Store fission yield dictionaries fission_yields = [] @@ -210,10 +203,11 @@ class FluxSpectraDepletionOperator(TransportOperator): for nuc, i_nuc_results in zip(nuclides, nuc_ind): number[i_nuc_results] = self.number[0, nuc] - # Store microscopic cross sections in rates array + # Calculate macroscopic cross sections and store them in rates array for nuc in nuclides: + density = number.get_atom_density('0', nuc) for rxn in self.chain.reactions: - rates.set('0', nuc, rxn, self._micro_xs[rxn].loc[nuc]) + rates.set('0', nuc, rxn, self._micro_xs[rxn].loc[nuc] * density) # Get reaction rate in reactions/sec rates *= self.flux_spectra @@ -225,10 +219,15 @@ class FluxSpectraDepletionOperator(TransportOperator): #if fission_ind is not None: # self._normalization_helper.update(rxn_rates[:, fission_ind]) - ## These don't seem relevant so I'm commenting them out for now - ## will delete if they are indeed not useful # Divide by total number and store - #rates[0] = self._rate_helper.divide_by_adens(number) + # the reason we do this is bc in the equation, we multiply the depletion matrix + # by the nuclide vector. Since what we want is the depletion matrix, we need to + # divide the reaction rates by the number of atoms to get the right units. + mask = nonzero(number) + results = rates[0] + for col in range(results.shape[1]): + results[mask, col] /= number[mask] + rates[0] = results # Scale reaction rates to obtain units of reactions/sec #rates *= self._normalization_helper.factor(source_rate) @@ -237,7 +236,7 @@ class FluxSpectraDepletionOperator(TransportOperator): # Store new fission yields on the chain self.chain.fission_yields = fission_yields - return OperatorResult(keff, rates) + return OperatorResult(self._keff, rates) def initial_condition(self): @@ -397,4 +396,53 @@ class FluxSpectraDepletionOperator(TransportOperator): return nuclides + def _extract_number(self, local_mats, volume, nuclides, prev_res=None): + """Construct AtomNumber using geometry + + Parameters + ---------- + local_mats : list of str + Material IDs to be managed by this process + volume : OrderedDict of str to float + Volumes for the above materials in [cm^3] + nuclides : list of str + Nuclides to be used in the simulation. + prev_res : Results, optional + Results from a previous depletion calculation + + """ + self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) + + if self.dilute_initial != 0.0: + for nuc in self._burnable_nucs: + self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) + + # Now extract and store the number densities + # From the geometry if no previous depletion results + if prev_res is None: + for mat in self.materials: + if str(mat.id) in local_mats: + self._set_number_from_mat(mat) + + # Else from previous depletion results + else: + for mat in self.materials: + if str(mat.id) in local_mats: + self._set_number_from_results(mat, prev_res) + + def _set_number_from_mat(self, mat): + """Extracts material and number densities from openmc.Material + + Parameters + ---------- + mat : openmc.Material + The material to read from + + """ + mat_id = str(mat.id) + + for nuclide, density in mat.get_nuclide_atom_densities().values(): + number = density * 1.0e24 + self.number.set_atom_density(mat_id, nuclide, number) + From 760ef42ce174ff421fafc85d2bdfa000d69bd2f1 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 28 Jun 2022 16:02:06 -0500 Subject: [PATCH 0458/2654] consistency and bug fixes - import check_type instead of check_value - remove unused classed from .helpers import statement - add unit spec to nuclides parameter - remove volume parameter from _get_all_depletion_nuclides - fix input sytax for ReactionRate object - add get_results_info function (to be implemented) - impement _extract_number function --- openmc/deplete/flux_operator.py | 88 ++++++++++++++++----------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index cd06894f6..84248c6fb 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -16,7 +16,7 @@ import pandas as pd from uncertainties import ufloat import openmc -from openmc.checkvalue import check_value +from openmc.checkvalue import check_type from openmc.data import DataLibrary from openmc.exceptions import DataError from openmc.mpi import comm @@ -25,9 +25,7 @@ from .atom_number import AtomNumber from .chain import _find_chain_file from .reaction_rates import ReactionRates from .results import Results -from .helpers import ( - FluxReactionRateHelper, ChainFissionHelper, SourceRateHelper, - ConstantFissionYieldHelper) +from .helpers import ConstantFissionYieldHelper @@ -47,7 +45,7 @@ class FluxSpectraDepletionOperator(TransportOperator): Volume of the material being depleted in cm^3 nuclides : dict of str to float Dictionary with nuclides names as keys and concentration as values. - Nuclide concentration is assumed to be in [units?] + Nuclide concentration is assumed to be in [at/cm^3] micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. @@ -102,10 +100,11 @@ class FluxSpectraDepletionOperator(TransportOperator): """ def __init__(self, volume, nuclides, micro_xs, flux_spectra, chain_file, keff=None, fission_q=None, dilute_initial=1.0e3, - prev_results=None, reduce_chain=False, reduce_chain_level=None): - super.__init__(chain_file, fission_q, dilute_initial, prev_results) + prev_results=None, reduce_chain=False, reduce_chain_level=None, fission_yield_opts=None): + super().__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False self.flux_spectra = flux_spectra + self._init_nuclides = nuclides # Reduce the chain if reduce_chain: @@ -115,13 +114,13 @@ class FluxSpectraDepletionOperator(TransportOperator): self.chain = self.chain.reduce(all_nuclides, reduce_chain_level) # Validate nuclides and micro-xs parameters - check_value('nuclides', nuclides, dict, str) + check_type('nuclides', nuclides, dict, str) check_type('micro_xs', micro_xs, pd.DataFrame) self._micro_xs = micro_xs self._keff = keff - nuclides = self._get_all_depletion_nuclides(volume, nuclides) + nuclides = self._get_all_depletion_nuclides(nuclides) # TODO: add support for loading previous results @@ -135,11 +134,11 @@ class FluxSpectraDepletionOperator(TransportOperator): # TODO : implement _extract_number # Extract number densities from the geometry / previous depletion run #!!! consider removing this and just using the nuclides dict... - self._extract_number('0', volume, nuclides, self.prev_res) + self._extract_number(['0'], {'0': volume}, nuclides, self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( - '0', self._burnable_nucs, self.chain.reactions) + ['0'], self._burnable_nucs, self.chain.reactions) # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper @@ -269,6 +268,23 @@ class FluxSpectraDepletionOperator(TransportOperator): """ ... + def get_results_info(self): + """Returns volume list, cell lists, and nuc lists. + + Returns + ------- + volume : dict of str to float + Volumes corresponding to materials in burn_list + nuc_list : list of str + A list of all nuclide names. Used for sorting the simulation. + burn_list : list of int + A list of all cell IDs to be burned. Used for sorting the + simulation. + full_burn_list : list of int + All burnable materials in the geometry. + """ + + def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" @@ -349,13 +365,14 @@ class FluxSpectraDepletionOperator(TransportOperator): nuc_list = comm.bcast(nuc_list) return [nuc for nuc in nuc_list if nuc in self.chain] - def _get_all_depletion_nuclides(self, volume, nuclides): + def _get_all_depletion_nuclides(self, nuclides): """Determine nuclides that will show up in simulation Parameters ---------- - volume : float - Volume of material in cm^3 + nuclides : dict + dict whose keys are nuclide symbols as strings, + and whose values are nuclide concentrations in at/cm^3 Returns ------- @@ -366,15 +383,14 @@ class FluxSpectraDepletionOperator(TransportOperator): model_nuclides = set() - self.heavy_metal = 0.0 + #self.heavy_metal = 0.0 - bu_mat = openmc.Material() - bu_mat.volume = volume - for n, conc in nuclides: - bu_mat.add_nuclides(n,conc) + #bu_mat = openmc.Material() + #bu_mat.volume = volume + for n in nuclides: model_nuclides.add(n) - self.heavy_metal = bu_mat.fissionable_mass + #self.heavy_metal = bu_mat.fissionable_mass # Sort the sets model_nuclides = sorted(model_nuclides) @@ -391,8 +407,7 @@ class FluxSpectraDepletionOperator(TransportOperator): """Finds nuclides with cross section data""" nuclides = set() for name in self._micro_xs.index: - if name not in nuclides: - nuclides.add(name) + nuclides.add(name) return nuclides @@ -420,29 +435,12 @@ class FluxSpectraDepletionOperator(TransportOperator): # Now extract and store the number densities # From the geometry if no previous depletion results if prev_res is None: - for mat in self.materials: - if str(mat.id) in local_mats: - self._set_number_from_mat(mat) + for nuclide in nuclides: + if nuclide in self._init_nuclides: + self.number.set_atom_density('0', nuclide, self._init_nuclides[nuclide]) + elif nuclide not in self._burnable_nucs: + self.number.set_atom_density('0', nuclide, 0) # Else from previous depletion results else: - for mat in self.materials: - if str(mat.id) in local_mats: - self._set_number_from_results(mat, prev_res) - - def _set_number_from_mat(self, mat): - """Extracts material and number densities from openmc.Material - - Parameters - ---------- - mat : openmc.Material - The material to read from - - """ - mat_id = str(mat.id) - - for nuclide, density in mat.get_nuclide_atom_densities().values(): - number = density * 1.0e24 - self.number.set_atom_density(mat_id, nuclide, number) - - + raise RuntimeError("Loading from previous results not yet supported") From 22a29af6dc4283b5781a3802f6eff46f2d8357a8 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 28 Jun 2022 16:11:20 -0500 Subject: [PATCH 0459/2654] implement get_results_info function --- openmc/deplete/flux_operator.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 84248c6fb..c4ceacc5a 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -105,6 +105,7 @@ class FluxSpectraDepletionOperator(TransportOperator): self.round_number = False self.flux_spectra = flux_spectra self._init_nuclides = nuclides + self._volume = volume # Reduce the chain if reduce_chain: @@ -268,6 +269,7 @@ class FluxSpectraDepletionOperator(TransportOperator): """ ... + def get_results_info(self): """Returns volume list, cell lists, and nuc lists. @@ -283,7 +285,16 @@ class FluxSpectraDepletionOperator(TransportOperator): full_burn_list : list of int All burnable materials in the geometry. """ + nuc_list = self.number.burnable_nuclides + burn_list = ['0'] + volume = {'0': self._volume} + + # Combine volume dictionaries across processes + volume_list = comm.allgather(volume) + volume = {k: v for d in volume_list for k, v in d.items()} + + return volume, nuc_list, burn_list, burn_list def _update_materials(self): From 992d4c16611044f9554ddcd4ff86ad2a0d1a8a91 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 28 Jun 2022 16:11:43 -0500 Subject: [PATCH 0460/2654] add flux_operator to the __init__ module --- openmc/deplete/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py index 5891555a2..753167741 100644 --- a/openmc/deplete/__init__.py +++ b/openmc/deplete/__init__.py @@ -8,6 +8,7 @@ A depletion front-end tool. from .nuclide import * from .chain import * from .operator import * +from .flux_operator import * from .reaction_rates import * from .atom_number import * from .stepresult import * From e170914e39dffe51da10693f8436f237f3a1ad01 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 28 Jun 2022 21:03:41 -0500 Subject: [PATCH 0461/2654] variable name and algorithm improvements - grammatical fixes in docstring for nuclide parameter - remove unnecessary for loop in the reduce_chain block - rename _get_all_depletion_nuclides to _get_all_nuclides_in_simulation - change output of the above to an attribute, _all_nuclides - change output of _get_reaction_nuclides to rxn_nuclides in __call__ - pass on creating statepoints - make loop in _get_reaction_nuclides more efficient - remove unnecessary loop in _get_nuclides_with_data --- openmc/deplete/flux_operator.py | 113 ++++++++++++++------------------ 1 file changed, 50 insertions(+), 63 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index c4ceacc5a..48e9fda33 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -28,8 +28,6 @@ from .results import Results from .helpers import ConstantFissionYieldHelper - - class FluxSpectraDepletionOperator(TransportOperator): """Depletion operator that uses a user provided flux spectrum and one-group cross sections calculate reaction rates. @@ -44,11 +42,11 @@ class FluxSpectraDepletionOperator(TransportOperator): volume : float Volume of the material being depleted in cm^3 nuclides : dict of str to float - Dictionary with nuclides names as keys and concentration as values. - Nuclide concentration is assumed to be in [at/cm^3] + Dictionary with nuclide names as keys and nuclide concentrations as + values. Nuclide concentration units are [at/cm^3]. micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section - data in the columns. + data in the columns. Cross section units are [cm^-2]. flux_spectra : float Flux spectrum [n cm^-2 s^-1] chain_file : str @@ -99,20 +97,28 @@ class FluxSpectraDepletionOperator(TransportOperator): results are to be used. """ - def __init__(self, volume, nuclides, micro_xs, flux_spectra, chain_file, keff=None, fission_q=None, dilute_initial=1.0e3, - prev_results=None, reduce_chain=False, reduce_chain_level=None, fission_yield_opts=None): + def __init__(self, + volume, + nuclides, + micro_xs, + flux_spectra, + chain_file, + keff=None, + fission_q=None, + dilute_initial=1.0e3, + prev_results=None, + reduce_chain=False, + reduce_chain_level=None, + fission_yield_opts=None): super().__init__(chain_file, fission_q, dilute_initial, prev_results) - self.round_number = False self.flux_spectra = flux_spectra self._init_nuclides = nuclides self._volume = volume - # Reduce the chain + # Reduce the chain to only those nuclides present if reduce_chain: - all_nuclides = set() - for nuclide_name in nuclides.keys(): - all_isotopes.add(nuclide_name) - self.chain = self.chain.reduce(all_nuclides, reduce_chain_level) + init_nuc_names = set(nuclides.keys()) + self.chain = self.chain.reduce(init_nuc_names, reduce_chain_level) # Validate nuclides and micro-xs parameters check_type('nuclides', nuclides, dict, str) @@ -121,21 +127,24 @@ class FluxSpectraDepletionOperator(TransportOperator): self._micro_xs = micro_xs self._keff = keff - nuclides = self._get_all_depletion_nuclides(nuclides) + self._all_nuclides = self._get_all_nuclides_in_simulation() # TODO: add support for loading previous results # Determine which nuclides have cross section data + # This nuclides variables contains every nuclides + # for which there is an entry in the micro_xs parameter self.nuclides_with_data = self._get_nuclides_with_data() # Select nuclides with data that are also in the chain self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides if nuc.name in self.nuclides_with_data] - # TODO : implement _extract_number # Extract number densities from the geometry / previous depletion run - #!!! consider removing this and just using the nuclides dict... - self._extract_number(['0'], {'0': volume}, nuclides, self.prev_res) + self._extract_number(['0'], + {'0': volume}, + self._all_nuclides, + self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( @@ -167,7 +176,6 @@ class FluxSpectraDepletionOperator(TransportOperator): """ # Update the number densities regardless of the source rate - #!!! See previous excamation point comment self.number.set_density(vec) ## TODO : make sure this function works w the current structure. self._update_materials() @@ -175,16 +183,15 @@ class FluxSpectraDepletionOperator(TransportOperator): # Update nuclides data in preparation for transport solve ## TODO : make sure this function works w the current structure. - # this nuclides varibale is all the nuclides that will show up via depletion + # this nuclides varibale contains all the nuclides that will show up via depletion # that have xs data - nuclides = self._get_reaction_nuclides() - self._yield_helper.update_tally_nuclides(nuclides) + rxn_nuclides = self._get_reaction_nuclides() rates = self.reaction_rates rates.fill(0.0) # Form fast map - nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides] + nuc_ind = [rates.index_nuc[nuc] for nuc in rxn_nuclides] react_ind = [rates.index_rx[react] for react in self.chain.reactions] # Store fission yield dictionaries @@ -267,7 +274,7 @@ class FluxSpectraDepletionOperator(TransportOperator): step : int Current depletion step including restarts """ - ... + pass def get_results_info(self): @@ -334,10 +341,10 @@ class FluxSpectraDepletionOperator(TransportOperator): # summary.h5 file contains densities at the first time step def _get_reaction_nuclides(self): - """Determine nuclides that should be tallied for reaction rates. + """Determine nuclides that should have reation rates This method returns a list of all nuclides that have neutron data and - are listed in the depletion chain. Technically, we should tally nuclides + are listed in the depletion chain. Technically, we should list nuclides that may not appear in the depletion chain because we still need to get the fission reaction rate for these nuclides in order to normalize power, but that is left as a future exercise. @@ -345,17 +352,15 @@ class FluxSpectraDepletionOperator(TransportOperator): Returns ------- list of str - Tally nuclides + nuclides with reaction rates """ - nuc_set = set() - # Create the set of all nuclides in the decay chain in materials marked # for burning in which the number density is greater than zero. - for nuc in self.number.nuclides: - if nuc in self.nuclides_with_data: - if np.sum(self.number[:, nuc]) > 0.0: - nuc_set.add(nuc) + nuc_set = set(self._all_nuclides).intersection(self.nuclides_with_data) + for nuc in nuc_set: + if not np.sum(self.number[:, nuc]) > 0.0: + nuc_set.remove(nuc) # Communicate which nuclides have nonzeros to rank 0 if comm.rank == 0: @@ -376,51 +381,33 @@ class FluxSpectraDepletionOperator(TransportOperator): nuc_list = comm.bcast(nuc_list) return [nuc for nuc in nuc_list if nuc in self.chain] - def _get_all_depletion_nuclides(self, nuclides): - """Determine nuclides that will show up in simulation - - Parameters - ---------- - nuclides : dict - dict whose keys are nuclide symbols as strings, - and whose values are nuclide concentrations in at/cm^3 + def _get_all_nuclides_in_simulation(self): + """Determine nuclides that will show up in simulation. + This is the union of the nuclides provided by the user and + the nuclides present in the depletion chain. Returns ------- - nuclides : list of str + all_nuclides : list of str Nuclides in order of how they'll appear in the simulation. """ - model_nuclides = set() - - #self.heavy_metal = 0.0 - - #bu_mat = openmc.Material() - #bu_mat.volume = volume - for n in nuclides: - model_nuclides.add(n) - - #self.heavy_metal = bu_mat.fissionable_mass - - # Sort the sets - model_nuclides = sorted(model_nuclides) + init_nuclides = sorted(self._init_nuclides.keys()) # Construct a global nuclide dictionary, burned first - nuclides = list(self.chain.nuclide_dict) - for nuc in model_nuclides: - if nuc not in nuclides: - nuclides.append(nuc) + all_nuclides = list(self.chain.nuclide_dict) + for nuc in init_nuclides: + if nuc not in all_nuclides: + all_nuclides.append(nuc) - return nuclides + return all_nuclides def _get_nuclides_with_data(self): """Finds nuclides with cross section data""" - nuclides = set() - for name in self._micro_xs.index: - nuclides.add(name) + nuclides_with_data = set(self._micro_xs.index) - return nuclides + return nuclides_with_data def _extract_number(self, local_mats, volume, nuclides, prev_res=None): """Construct AtomNumber using geometry From 7723ea492c12e17c2a8e2bef8f301386410b15a3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 28 Jun 2022 09:45:38 -0500 Subject: [PATCH 0462/2654] Add Material.get_nuclide_activity method and decay_constant function --- docs/source/pythonapi/data.rst | 1 + openmc/data/data.py | 35 ++++++++++++++++++++++++++++-- openmc/material.py | 30 +++++++++++++++---------- tests/unit_tests/test_data_misc.py | 13 ++++++++++- 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 6f5c006c2..287738774 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -61,6 +61,7 @@ Core Functions atomic_mass atomic_weight + decay_constant dose_coefficients gnd_name half_life diff --git a/openmc/data/data.py b/openmc/data/data.py index 3a3cf5826..71b93293e 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -3,7 +3,7 @@ import json import os import re from pathlib import Path -from math import sqrt +from math import sqrt, log from warnings import warn # Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions @@ -202,7 +202,7 @@ _GND_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)') # Used in half_life function as a cache _HALF_LIFE = {} - +_LOG_TWO = log(2.0) def atomic_mass(isotope): """Return atomic mass of isotope in atomic mass units. @@ -283,6 +283,8 @@ def half_life(isotope): Half-life values are from the `ENDF/B-VIII.0 decay sublibrary `_. + .. versionadded:: 0.13.1 + Parameters ---------- isotope : str @@ -302,6 +304,35 @@ def half_life(isotope): return _HALF_LIFE.get(isotope.lower()) + +def decay_constant(isotope): + """Return decay constant of isotope in [s^-1] + + Decay constants are based on half-life values from the + :func:`~openmc.data.half_life` function. When the isotope is stable, a decay + constant of zero is returned. + + .. versionadded:: 0.13.1 + + Parameters + ---------- + isotope : str + Name of isotope, e.g., 'Pu239' + + Returns + ------- + float + Decay constant of isotope in [s^-1] + + See also + -------- + openmc.data.half_life + + """ + t = half_life(isotope) + return _LOG_TWO / t if t else 0.0 + + def water_density(temperature, pressure=0.1013): """Return the density of liquid water at a given temperature and pressure. diff --git a/openmc/material.py b/openmc/material.py index 1341746dc..e8285de7c 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -3,7 +3,6 @@ from collections.abc import Iterable from copy import deepcopy from numbers import Real from pathlib import Path -import math import re import warnings from xml.etree import ElementTree as ET @@ -145,20 +144,10 @@ class Material(IDManagerMixin): return string - @property def activity(self): """Returns the total activity of the material in Becquerels.""" - - atoms_per_barn_cm = self.get_nuclide_atom_densities() - total_activity = 0 - for key, value in atoms_per_barn_cm.items(): - half_life = openmc.data.half_life(key) - if half_life: - total_activity += value / half_life - total_activity *= math.log(2) * 1e24 * self.volume - - return total_activity + return sum(self.get_nuclide_activity().values()) @property def name(self): @@ -861,6 +850,23 @@ class Material(IDManagerMixin): return nuclides + def get_nuclide_activity(self): + """Return activity in [Bq] for each nuclide in the material + + .. versionadded:: 0.13.1 + + Returns + ------- + dict + Dictionary whose keys are nuclide names and values are activity in + [Bq]. + """ + activity = {} + for nuclide, atoms in self.get_nuclide_atoms().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = inv_seconds * atoms + return activity + def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material diff --git a/tests/unit_tests/test_data_misc.py b/tests/unit_tests/test_data_misc.py index 6a81fb1e0..c3f7e3cff 100644 --- a/tests/unit_tests/test_data_misc.py +++ b/tests/unit_tests/test_data_misc.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from collections.abc import Mapping +from math import log import os from pathlib import Path @@ -126,3 +126,14 @@ def test_zam(): assert openmc.data.zam('Am242_m10') == (95, 242, 10) with pytest.raises(ValueError): openmc.data.zam('garbage') + + +def test_half_life(): + assert openmc.data.half_life('H2') is None + assert openmc.data.half_life('U235') == pytest.approx(2.22102e16) + assert openmc.data.half_life('Am242') == pytest.approx(57672.0) + assert openmc.data.half_life('Am242_m1') == pytest.approx(4449622000.0) + assert openmc.data.decay_constant('H2') == 0.0 + assert openmc.data.decay_constant('U235') == pytest.approx(log(2.0)/2.22102e16) + assert openmc.data.decay_constant('Am242') == pytest.approx(log(2.0)/57672.0) + assert openmc.data.decay_constant('Am242_m1') == pytest.approx(log(2.0)/4449622000.0) From 6eaab920eeaddac452ad07e25015357c3658f139 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 08:18:10 +0200 Subject: [PATCH 0463/2654] better error catching --- openmc/tallies.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index b795fc83a..faa7c3efe 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -471,9 +471,12 @@ class Tally(IDManagerMixin): try: import vtk import vtk.util.numpy_support as nps - except ImportError: + except ModuleNotFoundError: msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' - raise ImportError(msg) + raise ModuleNotFoundError(msg) + except ImportError as err: + raise err + mesh = None for f in self.filters: if isinstance(f, openmc.MeshFilter): From fb40ba894addb3ab87226e80e631aaa6288dafa6 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 08:18:22 +0200 Subject: [PATCH 0464/2654] moved comment statement --- openmc/tallies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index faa7c3efe..bec0ddc6f 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -467,7 +467,6 @@ class Tally(IDManagerMixin): ValueError: if no MeshFilter with appropriate mesh was found (SphericalMesh not supported) """ - # check that tally has a MeshFilter try: import vtk import vtk.util.numpy_support as nps @@ -477,6 +476,7 @@ class Tally(IDManagerMixin): except ImportError as err: raise err + # check that tally has a MeshFilter mesh = None for f in self.filters: if isinstance(f, openmc.MeshFilter): From dacd3b75b855d8f28da8f7eedea4e6508c20fd80 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 08:20:25 +0200 Subject: [PATCH 0465/2654] moved import to voxels_to_vtk --- openmc/tallies.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index bec0ddc6f..fbf2962b9 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -467,15 +467,6 @@ class Tally(IDManagerMixin): ValueError: if no MeshFilter with appropriate mesh was found (SphericalMesh not supported) """ - try: - import vtk - import vtk.util.numpy_support as nps - except ModuleNotFoundError: - msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' - raise ModuleNotFoundError(msg) - except ImportError as err: - raise err - # check that tally has a MeshFilter mesh = None for f in self.filters: @@ -3324,7 +3315,14 @@ def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): Returns: vtkStructuredGrid: a vtk object containing tally data on the appropriate grid """ - + try: + import vtk + import vtk.util.numpy_support as nps + except ModuleNotFoundError: + msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' + raise ModuleNotFoundError(msg) + except ImportError as err: + raise err # TODO: should this be a method of Tally? vtk_grid = vtk.vtkStructuredGrid() From 9ec0a0a3df1a90783e1b0e60701f972275ffd17e Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 08:42:32 +0200 Subject: [PATCH 0466/2654] refactoring --- openmc/tallies.py | 105 +++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index fbf2962b9..a25d535e5 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -464,61 +464,29 @@ class Tally(IDManagerMixin): filename (str): the filename (must end with .vtk) Raises: - ValueError: if no MeshFilter with appropriate mesh was found - (SphericalMesh not supported) + ValueError: if no MeshFilter was found """ + try: + import vtk + except ModuleNotFoundError: + msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' + raise ModuleNotFoundError(msg) + except ImportError as err: + raise err + # check that tally has a MeshFilter mesh = None for f in self.filters: if isinstance(f, openmc.MeshFilter): - if isinstance(f.mesh, (openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh)): - mesh = f.mesh - break + mesh = f.mesh + break if not mesh: raise ValueError( - "write_to_vtk only works with openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh" + "write_to_vtk requires a MeshFilter in the tally filters" ) - if isinstance(mesh, openmc.RegularMesh): - vtk_grid = voxels_to_vtk( - x_vals=np.linspace( - mesh.lower_left[0], - mesh.upper_right[0], - num=mesh.dimension[0] + 1, - ), - y_vals=np.linspace( - mesh.lower_left[1], - mesh.upper_right[1], - num=mesh.dimension[1] + 1, - ), - z_vals=np.linspace( - mesh.lower_left[2], - mesh.upper_right[2], - num=mesh.dimension[2] + 1, - ), - mean=self.mean, - std_dev=self.std_dev, - cylindrical=False, - ) - if isinstance(mesh, openmc.RectilinearMesh): - vtk_grid = voxels_to_vtk( - x_vals=mesh.x_grid, - y_vals=mesh.y_grid, - z_vals=mesh.z_grid, - mean=self.mean, - std_dev=self.std_dev, - cylindrical=False, - ) - elif isinstance(mesh, openmc.CylindricalMesh): - vtk_grid = voxels_to_vtk( - x_vals=mesh.r_grid, - y_vals=mesh.phi_grid, - z_vals=mesh.z_grid, - mean=self.mean, - std_dev=self.std_dev, - cylindrical=True, - ) + vtk_grid = voxels_to_vtk(mesh, self.mean, self.std_dev) # write the .vtk file writer = vtk.vtkStructuredGridWriter() @@ -3300,20 +3268,20 @@ class Tallies(cv.CheckedList): return cls(tallies) -def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): +def voxels_to_vtk(mesh, mean, std_dev): """Creates a vtk object from a list of X, Y, Z values and mean/std_dev data. Args: - x_vals (list): X values. - y_vals (list): Y values. - z_vals (list): Z values. + mesh (openmc.StructuredMesh): The tallied mesh (SphericalMesh is not yet supported). mean (np.array): the tally mean. std_dev (np.array): the tally standard deviation. - cylindrical (bool, optional): If set to True, cylindrical coordinates - (r, phi, z) are assumed. Defaults to True. Returns: vtkStructuredGrid: a vtk object containing tally data on the appropriate grid + + Raises: + ValueError: if mesh is not openmc.RegularMesh, openmc.RectilinearMesh or + openmc.CylindricalMesh """ try: import vtk @@ -3325,13 +3293,46 @@ def voxels_to_vtk(x_vals, y_vals, z_vals, mean, std_dev, cylindrical=True): raise err # TODO: should this be a method of Tally? + system_of_coordinates = "cartesian" + + if isinstance(mesh, openmc.RegularMesh): + print('coucou') + x_vals = np.linspace( + mesh.lower_left[0], + mesh.upper_right[0], + num=mesh.dimension[0] + 1, + ) + y_vals = np.linspace( + mesh.lower_left[1], + mesh.upper_right[1], + num=mesh.dimension[1] + 1, + ) + z_vals = np.linspace( + mesh.lower_left[2], + mesh.upper_right[2], + num=mesh.dimension[2] + 1, + ) + elif isinstance(mesh, openmc.RectilinearMesh): + x_vals = mesh.x_grid + y_vals = mesh.y_grid + z_vals = mesh.z_grid + elif isinstance(mesh, openmc.CylindricalMesh): + x_vals = mesh.r_grid + y_vals = mesh.phi_grid + z_vals = mesh.z_grid + system_of_coordinates = "cylindrical" + else: + print(type(mesh)) + raise ValueError( + "voxels_to_vtk only works with openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh" + ) vtk_grid = vtk.vtkStructuredGrid() vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) # create points points = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) - if cylindrical: # transform points to cartesian coordinates + if system_of_coordinates == "cylindrical": # transform points to cartesian coordinates points_cartesian = np.copy(points) r, phi, z = points[:, 0], points[:, 1], points[:, 2] points_cartesian[:, 0] = r * np.cos(phi) From 11cee75e46ebc7e9756d81dbfae3452ff824cc10 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 09:12:28 +0200 Subject: [PATCH 0467/2654] put write_to_vtk method at the end --- openmc/tallies.py | 74 +++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index a25d535e5..198f5581b 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -457,43 +457,6 @@ class Tally(IDManagerMixin): self._std_dev = np.reshape(self._std_dev.toarray(), self.shape) self._sparse = False - def write_to_vtk(self, filename): - """Writes the tally to a vtk file - - Args: - filename (str): the filename (must end with .vtk) - - Raises: - ValueError: if no MeshFilter was found - """ - try: - import vtk - except ModuleNotFoundError: - msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' - raise ModuleNotFoundError(msg) - except ImportError as err: - raise err - - # check that tally has a MeshFilter - mesh = None - for f in self.filters: - if isinstance(f, openmc.MeshFilter): - mesh = f.mesh - break - - if not mesh: - raise ValueError( - "write_to_vtk requires a MeshFilter in the tally filters" - ) - - vtk_grid = voxels_to_vtk(mesh, self.mean, self.std_dev) - - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() - def remove_score(self, score): """Remove a score from the tally @@ -3050,6 +3013,43 @@ class Tally(IDManagerMixin): new_tally.sparse = self.sparse return new_tally + def write_to_vtk(self, filename): + """Writes the tally to a vtk file + + Args: + filename (str): the filename (must end with .vtk) + + Raises: + ValueError: if no MeshFilter was found + """ + try: + import vtk + except ModuleNotFoundError: + msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' + raise ModuleNotFoundError(msg) + except ImportError as err: + raise err + + # check that tally has a MeshFilter + mesh = None + for f in self.filters: + if isinstance(f, openmc.MeshFilter): + mesh = f.mesh + break + + if not mesh: + raise ValueError( + "write_to_vtk requires a MeshFilter in the tally filters" + ) + + vtk_grid = voxels_to_vtk(mesh, self.mean, self.std_dev) + + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() + class Tallies(cv.CheckedList): """Collection of Tallies used for an OpenMC simulation. From bff8bc4b459030448749e587fb0fde2cf53d48f9 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 09:16:40 +0200 Subject: [PATCH 0468/2654] added tests --- tests/unit_tests/test_tallies.py | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/unit_tests/test_tallies.py b/tests/unit_tests/test_tallies.py index aeeb0612d..b6fc6cc47 100644 --- a/tests/unit_tests/test_tallies.py +++ b/tests/unit_tests/test_tallies.py @@ -1,4 +1,8 @@ import numpy as np +import pytest +import vtk +from os.path import exists + import openmc @@ -38,3 +42,61 @@ def test_xml_roundtrip(run_in_tmpdir): assert new_tally.triggers[0].trigger_type == tally.triggers[0].trigger_type assert new_tally.triggers[0].threshold == tally.triggers[0].threshold assert new_tally.triggers[0].scores == tally.triggers[0].scores + + +cylinder_mesh = openmc.CylindricalMesh() +cylinder_mesh.r_grid = np.linspace(1, 2, num=30) +cylinder_mesh.phi_grid = np.linspace(0, np.pi / 2, num=50) +cylinder_mesh.z_grid = np.linspace(0, 1, num=30) + +regular_mesh = openmc.RegularMesh() +regular_mesh.lower_left = [0, 0, 0] +regular_mesh.upper_right = [1, 1, 1] +regular_mesh.dimension = [10, 5, 6] + +rectilinear_mesh = openmc.RectilinearMesh() +rectilinear_mesh.x_grid = np.linspace(0, 1) +rectilinear_mesh.y_grid = np.linspace(0, 1) +rectilinear_mesh.z_grid = np.linspace(0, 1) + + +@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh]) +def test_voxels_to_vtk(mesh): + vtk_grid = openmc.voxels_to_vtk(mesh, mean=None, std_dev=None) + assert isinstance(vtk_grid, vtk.vtkStructuredGrid) + + +@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh]) +def test_write_to_vtk(mesh, tmpdir): + # build + tally = openmc.Tally() + tally.filters = [openmc.MeshFilter(mesh)] + filename = tmpdir / "out.vtk" + # run + tally.write_to_vtk(filename) + # test + assert exists(filename) + + +def test_write_to_vtk_raises_error_when_no_meshfilter(): + # build + tally = openmc.Tally() + + # test + expected_err_msg = "write_to_vtk requires a MeshFilter in the tally filters" + with pytest.raises(ValueError, match=expected_err_msg): + tally.write_to_vtk("out.vtk") + + +def test_voxel_to_vtk_raises_error_with_wrong_mesh(): + # build + tally = openmc.Tally() + spherical_mesh = openmc.SphericalMesh() + spherical_mesh.r_grid = np.linspace(1, 2) + spherical_mesh.phi_grid = np.linspace(1, 2) + spherical_mesh.theta_grid = np.linspace(1, 2) + tally.filters = [openmc.MeshFilter(spherical_mesh)] + # test + expected_err_msg = "voxels_to_vtk only works with openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh" + with pytest.raises(ValueError, match=expected_err_msg): + tally.write_to_vtk("out.vtk") \ No newline at end of file From b61ec91d781caf8e7ca593a98c76d916a8efa94e Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 09:50:28 +0200 Subject: [PATCH 0469/2654] removed print statement --- openmc/tallies.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 198f5581b..88f747249 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3296,7 +3296,6 @@ def voxels_to_vtk(mesh, mean, std_dev): system_of_coordinates = "cartesian" if isinstance(mesh, openmc.RegularMesh): - print('coucou') x_vals = np.linspace( mesh.lower_left[0], mesh.upper_right[0], From cac84d6e1f76b69d28da8674fcf81011170cf446 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 09:50:42 +0200 Subject: [PATCH 0470/2654] removd print statement --- openmc/tallies.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 88f747249..020d4a3d9 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3321,7 +3321,6 @@ def voxels_to_vtk(mesh, mean, std_dev): z_vals = mesh.z_grid system_of_coordinates = "cylindrical" else: - print(type(mesh)) raise ValueError( "voxels_to_vtk only works with openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh" ) From 7be28ef156a96fb4c525130d9c52e6966cf43539 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 11:08:58 +0200 Subject: [PATCH 0471/2654] added vtk_grid to meshes --- openmc/mesh.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 7f7b07879..dbdfb10b0 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -621,7 +621,45 @@ class RegularMesh(StructuredMesh): root_cell.fill = lattice return root_cell, cells + + def vtk_grid(self, filename=None): + import vtk + from vtk.util import numpy_support as nps + x_vals = np.linspace( + self.lower_left[0], + self.upper_right[0], + num=self.dimension[0] + 1, + ) + y_vals = np.linspace( + self.lower_left[1], + self.upper_right[1], + num=self.dimension[1] + 1, + ) + z_vals = np.linspace( + self.lower_left[2], + self.upper_right[2], + num=self.dimension[2] + 1, + ) + vtk_grid = vtk.vtkStructuredGrid() + + vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) + + # create points + pts_cartesian = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) + + vtkPts = vtk.vtkPoints() + vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) + vtk_grid.SetPoints(vtkPts) + + if filename: + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() + + return vtk_grid def Mesh(*args, **kwargs): warnings.warn("Mesh has been renamed RegularMesh. Future versions of " @@ -821,6 +859,33 @@ class RectilinearMesh(StructuredMesh): return element + def vtk_grid(self, filename=None): + import vtk + from vtk.util import numpy_support as nps + + x_vals = self.x_grid + y_vals = self.y_grid + z_vals = self.z_grid + vtk_grid = vtk.vtkStructuredGrid() + + vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) + + # create points + pts_cartesian = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) + + vtkPts = vtk.vtkPoints() + vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) + vtk_grid.SetPoints(vtkPts) + + if filename: + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() + + return vtk_grid + class CylindricalMesh(StructuredMesh): """A 3D cylindrical mesh @@ -1012,6 +1077,37 @@ class CylindricalMesh(StructuredMesh): return np.multiply.outer(np.outer(V_r, V_p), V_z) + def vtk_grid(self, filename=None): + import vtk + from vtk.util import numpy_support as nps + + r_vals = self.r_grid + phi_vals = self.phi_grid + z_vals = self.z_grid + vtk_grid = vtk.vtkStructuredGrid() + + vtk_grid.SetDimensions(len(r_vals), len(phi_vals), len(z_vals)) + + # create points + pts_cylindrical = np.array([[r, phi, z] for z in z_vals for phi in phi_vals for r in r_vals]) + pts_cartesian = np.copy(pts_cylindrical) + r, phi, z = pts_cylindrical[:, 0], pts_cylindrical[:, 1], pts_cylindrical[:, 2] + pts_cartesian[:, 0] = r * np.cos(phi) + pts_cartesian[:, 1] = r * np.sin(phi) + pts_cartesian[:, 2] = z + + vtkPts = vtk.vtkPoints() + vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) + vtk_grid.SetPoints(vtkPts) + + if filename: + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() + + return vtk_grid class SphericalMesh(StructuredMesh): """A 3D spherical mesh @@ -1204,6 +1300,9 @@ class SphericalMesh(StructuredMesh): return np.multiply.outer(np.outer(V_r, V_t), V_p) + def vtk_grid(self, filename=None): + raise NotImplementedError("vtk_grid not implemented for SphericalMesh") + class UnstructuredMesh(MeshBase): """A 3D unstructured mesh From 4ab6617bc4fe681bff68bce6dd4b22bf57a821d9 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 11:09:18 +0200 Subject: [PATCH 0472/2654] write_to_vtk makes use of mesh.vtk_grid() --- openmc/tallies.py | 113 +++++----------------------------------------- 1 file changed, 12 insertions(+), 101 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 020d4a3d9..e67365df6 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3042,7 +3042,18 @@ class Tally(IDManagerMixin): "write_to_vtk requires a MeshFilter in the tally filters" ) - vtk_grid = voxels_to_vtk(mesh, self.mean, self.std_dev) + vtk_grid = mesh.vtk_grid() + + # add mean and std dev data + mean_array = vtk.vtkDoubleArray() + mean_array.SetName("mean") + mean_array.SetArray(self.mean, self.mean.size, True) + vtk_grid.GetCellData().AddArray(mean_array) + + std_dev_array = vtk.vtkDoubleArray() + std_dev_array.SetName("std_dev") + std_dev_array.SetArray(self.std_dev, self.std_dev.size, True) + vtk_grid.GetCellData().AddArray(std_dev_array) # write the .vtk file writer = vtk.vtkStructuredGridWriter() @@ -3266,103 +3277,3 @@ class Tallies(cv.CheckedList): tallies.append(tally) return cls(tallies) - - -def voxels_to_vtk(mesh, mean, std_dev): - """Creates a vtk object from a list of X, Y, Z values and mean/std_dev data. - - Args: - mesh (openmc.StructuredMesh): The tallied mesh (SphericalMesh is not yet supported). - mean (np.array): the tally mean. - std_dev (np.array): the tally standard deviation. - - Returns: - vtkStructuredGrid: a vtk object containing tally data on the appropriate grid - - Raises: - ValueError: if mesh is not openmc.RegularMesh, openmc.RectilinearMesh or - openmc.CylindricalMesh - """ - try: - import vtk - import vtk.util.numpy_support as nps - except ModuleNotFoundError: - msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' - raise ModuleNotFoundError(msg) - except ImportError as err: - raise err - # TODO: should this be a method of Tally? - - system_of_coordinates = "cartesian" - - if isinstance(mesh, openmc.RegularMesh): - x_vals = np.linspace( - mesh.lower_left[0], - mesh.upper_right[0], - num=mesh.dimension[0] + 1, - ) - y_vals = np.linspace( - mesh.lower_left[1], - mesh.upper_right[1], - num=mesh.dimension[1] + 1, - ) - z_vals = np.linspace( - mesh.lower_left[2], - mesh.upper_right[2], - num=mesh.dimension[2] + 1, - ) - elif isinstance(mesh, openmc.RectilinearMesh): - x_vals = mesh.x_grid - y_vals = mesh.y_grid - z_vals = mesh.z_grid - elif isinstance(mesh, openmc.CylindricalMesh): - x_vals = mesh.r_grid - y_vals = mesh.phi_grid - z_vals = mesh.z_grid - system_of_coordinates = "cylindrical" - else: - raise ValueError( - "voxels_to_vtk only works with openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh" - ) - vtk_grid = vtk.vtkStructuredGrid() - - vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) - - # create points - points = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) - if system_of_coordinates == "cylindrical": # transform points to cartesian coordinates - points_cartesian = np.copy(points) - r, phi, z = points[:, 0], points[:, 1], points[:, 2] - points_cartesian[:, 0] = r * np.cos(phi) - points_cartesian[:, 1] = r * np.sin(phi) - points_cartesian[:, 2] = z - points = points_cartesian - - vtkPts = vtk.vtkPoints() - vtkPts.SetData(nps.numpy_to_vtk(points, deep=True)) - vtk_grid.SetPoints(vtkPts) - - # add mean and std dev data - mean_array = vtk.vtkDoubleArray() - mean_array.SetName("mean") - if mean is None: - mean = np.zeros( - (len(x_vals) - 1) - * (len(y_vals) - 1) - * (len(z_vals) - 1) - ) - mean_array.SetArray(mean, mean.size, True) - vtk_grid.GetCellData().AddArray(mean_array) - - std_dev_array = vtk.vtkDoubleArray() - std_dev_array.SetName("std_dev") - if std_dev is None: - std_dev = np.zeros( - (len(x_vals) - 1) - * (len(y_vals) - 1) - * (len(z_vals) - 1) - ) - std_dev_array.SetArray(std_dev, std_dev.size, True) - vtk_grid.GetCellData().AddArray(std_dev_array) - - return vtk_grid From 8958b74da73e47757147ab80b22b325926291142 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 11:09:32 +0200 Subject: [PATCH 0473/2654] adapted tests --- tests/unit_tests/test_tallies.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/unit_tests/test_tallies.py b/tests/unit_tests/test_tallies.py index b6fc6cc47..e49596f6d 100644 --- a/tests/unit_tests/test_tallies.py +++ b/tests/unit_tests/test_tallies.py @@ -43,6 +43,23 @@ def test_xml_roundtrip(run_in_tmpdir): assert new_tally.triggers[0].threshold == tally.triggers[0].threshold assert new_tally.triggers[0].scores == tally.triggers[0].scores +def run_dummy_sim(tally): + mat = openmc.Material() + mat.add_nuclide('Zr90', 1.0) + mat.set_density('g/cm3', 1.0) + + model = openmc.Model() + sph = openmc.Sphere(r=25.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sph) + model.geometry = openmc.Geometry([cell]) + + model.settings.run_mode = 'fixed source' + model.settings.batches = 2 + model.settings.particles = 50 + + model.tallies = openmc.Tallies([tally]) + + model.run() cylinder_mesh = openmc.CylindricalMesh() cylinder_mesh.r_grid = np.linspace(1, 2, num=30) @@ -59,19 +76,13 @@ rectilinear_mesh.x_grid = np.linspace(0, 1) rectilinear_mesh.y_grid = np.linspace(0, 1) rectilinear_mesh.z_grid = np.linspace(0, 1) - -@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh]) -def test_voxels_to_vtk(mesh): - vtk_grid = openmc.voxels_to_vtk(mesh, mean=None, std_dev=None) - assert isinstance(vtk_grid, vtk.vtkStructuredGrid) - - @pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh]) def test_write_to_vtk(mesh, tmpdir): # build tally = openmc.Tally() tally.filters = [openmc.MeshFilter(mesh)] filename = tmpdir / "out.vtk" + run_dummy_sim(tally) # run tally.write_to_vtk(filename) # test @@ -97,6 +108,6 @@ def test_voxel_to_vtk_raises_error_with_wrong_mesh(): spherical_mesh.theta_grid = np.linspace(1, 2) tally.filters = [openmc.MeshFilter(spherical_mesh)] # test - expected_err_msg = "voxels_to_vtk only works with openmc.RegularMesh, openmc.RectilinearMesh, openmc.CylindricalMesh" - with pytest.raises(ValueError, match=expected_err_msg): + expected_err_msg = "vtk_grid not implemented for SphericalMesh" + with pytest.raises(NotImplementedError, match=expected_err_msg): tally.write_to_vtk("out.vtk") \ No newline at end of file From 2a78c06cf512e579eaeef007a63a2c90da9cb4ed Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 11:21:45 +0200 Subject: [PATCH 0474/2654] added docstrings --- openmc/mesh.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index dbdfb10b0..f6e395328 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -623,6 +623,15 @@ class RegularMesh(StructuredMesh): return root_cell, cells def vtk_grid(self, filename=None): + """Creates a VTK object of the mesh + + Args: + filename (str, optional): Name of the vtk file to write = + (must end with .vtk). Defaults to None. + + Returns: + vtk.vtkStructuredGrid: the VTK object + """ import vtk from vtk.util import numpy_support as nps @@ -860,6 +869,15 @@ class RectilinearMesh(StructuredMesh): return element def vtk_grid(self, filename=None): + """Creates a VTK object of the mesh + + Args: + filename (str, optional): Name of the vtk file to write = + (must end with .vtk). Defaults to None. + + Returns: + vtk.vtkStructuredGrid: the VTK object + """ import vtk from vtk.util import numpy_support as nps @@ -1078,6 +1096,15 @@ class CylindricalMesh(StructuredMesh): return np.multiply.outer(np.outer(V_r, V_p), V_z) def vtk_grid(self, filename=None): + """Creates a VTK object of the mesh + + Args: + filename (str, optional): Name of the vtk file to write = + (must end with .vtk). Defaults to None. + + Returns: + vtk.vtkStructuredGrid: the VTK object + """ import vtk from vtk.util import numpy_support as nps @@ -1301,6 +1328,16 @@ class SphericalMesh(StructuredMesh): return np.multiply.outer(np.outer(V_r, V_t), V_p) def vtk_grid(self, filename=None): + """Creates a VTK object of the mesh + + Args: + filename (str, optional): Name of the vtk file to write = + (must end with .vtk). Defaults to None. + + Returns: + vtk.vtkStructuredGrid: the VTK object + """ + # FIXME raise NotImplementedError("vtk_grid not implemented for SphericalMesh") From 913bc99564b97490d90152aa68ed9a65838bdc3e Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 11:33:17 +0200 Subject: [PATCH 0475/2654] minor refactore --- openmc/mesh.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index f6e395328..d89a980ac 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1108,15 +1108,12 @@ class CylindricalMesh(StructuredMesh): import vtk from vtk.util import numpy_support as nps - r_vals = self.r_grid - phi_vals = self.phi_grid - z_vals = self.z_grid vtk_grid = vtk.vtkStructuredGrid() - vtk_grid.SetDimensions(len(r_vals), len(phi_vals), len(z_vals)) + vtk_grid.SetDimensions(len(self.r_grid), len(self.phi_grid), len(self.z_grid)) # create points - pts_cylindrical = np.array([[r, phi, z] for z in z_vals for phi in phi_vals for r in r_vals]) + pts_cylindrical = np.array([[r, phi, z] for z in self.z_grid for phi in self.phi_grid for r in self.r_grid]) pts_cartesian = np.copy(pts_cylindrical) r, phi, z = pts_cylindrical[:, 0], pts_cylindrical[:, 1], pts_cylindrical[:, 2] pts_cartesian[:, 0] = r * np.cos(phi) From aeb66509098b597a5cd53fca88d5e21096c691a0 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 11:54:52 +0200 Subject: [PATCH 0476/2654] implemented spherical grid --- openmc/mesh.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d89a980ac..260ed5f43 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1334,8 +1334,33 @@ class SphericalMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object """ - # FIXME - raise NotImplementedError("vtk_grid not implemented for SphericalMesh") + import vtk + from vtk.util import numpy_support as nps + + vtk_grid = vtk.vtkStructuredGrid() + + vtk_grid.SetDimensions(len(self.r_grid), len(self.theta_grid), len(self.phi_grid)) + + # create points + pts_cylindrical = np.array([[r, theta, phi] for phi in self.phi_grid for theta in self.theta_grid for r in self.r_grid]) + pts_cartesian = np.copy(pts_cylindrical) + r, theta, phi = pts_cylindrical[:, 0], pts_cylindrical[:, 1], pts_cylindrical[:, 2] + pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) + pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) + pts_cartesian[:, 2] = r * np.cos(phi) + + vtkPts = vtk.vtkPoints() + vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) + vtk_grid.SetPoints(vtkPts) + + if filename: + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() + + return vtk_grid class UnstructuredMesh(MeshBase): From 7de718a85c1ceaa0a6c485184829357d0f5c6372 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 11:56:32 +0200 Subject: [PATCH 0477/2654] adapted tests --- tests/unit_tests/test_tallies.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/unit_tests/test_tallies.py b/tests/unit_tests/test_tallies.py index e49596f6d..e3f9a486d 100644 --- a/tests/unit_tests/test_tallies.py +++ b/tests/unit_tests/test_tallies.py @@ -76,7 +76,12 @@ rectilinear_mesh.x_grid = np.linspace(0, 1) rectilinear_mesh.y_grid = np.linspace(0, 1) rectilinear_mesh.z_grid = np.linspace(0, 1) -@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh]) +spherical_mesh = openmc.SphericalMesh() +spherical_mesh.r_grid = np.linspace(1, 2) +spherical_mesh.phi_grid = np.linspace(1, 2) +spherical_mesh.theta_grid = np.linspace(1, 2) + +@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) def test_write_to_vtk(mesh, tmpdir): # build tally = openmc.Tally() @@ -97,17 +102,3 @@ def test_write_to_vtk_raises_error_when_no_meshfilter(): expected_err_msg = "write_to_vtk requires a MeshFilter in the tally filters" with pytest.raises(ValueError, match=expected_err_msg): tally.write_to_vtk("out.vtk") - - -def test_voxel_to_vtk_raises_error_with_wrong_mesh(): - # build - tally = openmc.Tally() - spherical_mesh = openmc.SphericalMesh() - spherical_mesh.r_grid = np.linspace(1, 2) - spherical_mesh.phi_grid = np.linspace(1, 2) - spherical_mesh.theta_grid = np.linspace(1, 2) - tally.filters = [openmc.MeshFilter(spherical_mesh)] - # test - expected_err_msg = "vtk_grid not implemented for SphericalMesh" - with pytest.raises(NotImplementedError, match=expected_err_msg): - tally.write_to_vtk("out.vtk") \ No newline at end of file From 0f23bf2109505f1ebb2de692552f096b25a5e93b Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 12:21:59 +0200 Subject: [PATCH 0478/2654] write_data_to_vtk SphericalMesh --- openmc/mesh.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 260ed5f43..c780827ea 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1324,7 +1324,7 @@ class SphericalMesh(StructuredMesh): return np.multiply.outer(np.outer(V_r, V_t), V_p) - def vtk_grid(self, filename=None): + def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh Args: @@ -1337,6 +1337,19 @@ class SphericalMesh(StructuredMesh): import vtk from vtk.util import numpy_support as nps + if self.volumes is None and volume_normalization: + raise RuntimeError("No volume data is present on this " + "unstructured mesh. Please load the " + " mesh information from a statepoint file.") + + # check that the data sets are appropriately sized + for label, dataset in datasets.items(): + if isinstance(dataset, np.ndarray): + assert dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2] + else: + assert len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2] + cv.check_type('label', label, str) + vtk_grid = vtk.vtkStructuredGrid() vtk_grid.SetDimensions(len(self.r_grid), len(self.theta_grid), len(self.phi_grid)) @@ -1353,12 +1366,26 @@ class SphericalMesh(StructuredMesh): vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) vtk_grid.SetPoints(vtkPts) - if filename: - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() + # create VTK arrays for each of + # the data sets + for label, dataset in datasets.items(): + dataset = np.asarray(dataset).flatten() + + if volume_normalization: + dataset /= self.volumes.flatten() + + dataset_array = vtk.vtkDoubleArray() + dataset_array.SetName(label) + dataset_array.SetArray(nps.numpy_to_vtk(dataset), + dataset.size, + True) + vtk_grid.GetCellData().AddArray(dataset_array) + + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() return vtk_grid From 15cc2a0804d3fa146bf6e337f4987ae634490513 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 12:23:55 +0200 Subject: [PATCH 0479/2654] fixed variable name --- openmc/mesh.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index c780827ea..3dbc170d6 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1355,9 +1355,9 @@ class SphericalMesh(StructuredMesh): vtk_grid.SetDimensions(len(self.r_grid), len(self.theta_grid), len(self.phi_grid)) # create points - pts_cylindrical = np.array([[r, theta, phi] for phi in self.phi_grid for theta in self.theta_grid for r in self.r_grid]) - pts_cartesian = np.copy(pts_cylindrical) - r, theta, phi = pts_cylindrical[:, 0], pts_cylindrical[:, 1], pts_cylindrical[:, 2] + pts_spherical = np.array([[r, theta, phi] for phi in self.phi_grid for theta in self.theta_grid for r in self.r_grid]) + pts_cartesian = np.copy(pts_spherical) + r, theta, phi = pts_spherical[:, 0], pts_spherical[:, 1], pts_spherical[:, 2] pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) pts_cartesian[:, 2] = r * np.cos(phi) From 3b1d1756e4716e5e70f58a3142dc7efaed2d7913 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 12:26:29 +0200 Subject: [PATCH 0480/2654] write_data_to_vtk CylindricalMesh --- openmc/mesh.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 3dbc170d6..029d714f0 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1095,7 +1095,7 @@ class CylindricalMesh(StructuredMesh): return np.multiply.outer(np.outer(V_r, V_p), V_z) - def vtk_grid(self, filename=None): + def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh Args: @@ -1108,6 +1108,19 @@ class CylindricalMesh(StructuredMesh): import vtk from vtk.util import numpy_support as nps + if self.volumes is None and volume_normalization: + raise RuntimeError("No volume data is present on this " + "unstructured mesh. Please load the " + " mesh information from a statepoint file.") + + # check that the data sets are appropriately sized + for label, dataset in datasets.items(): + if isinstance(dataset, np.ndarray): + assert dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2] + else: + assert len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2] + cv.check_type('label', label, str) + vtk_grid = vtk.vtkStructuredGrid() vtk_grid.SetDimensions(len(self.r_grid), len(self.phi_grid), len(self.z_grid)) @@ -1124,12 +1137,26 @@ class CylindricalMesh(StructuredMesh): vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) vtk_grid.SetPoints(vtkPts) - if filename: - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() + # create VTK arrays for each of + # the data sets + for label, dataset in datasets.items(): + dataset = np.asarray(dataset).flatten() + + if volume_normalization: + dataset /= self.volumes.flatten() + + dataset_array = vtk.vtkDoubleArray() + dataset_array.SetName(label) + dataset_array.SetArray(nps.numpy_to_vtk(dataset), + dataset.size, + True) + vtk_grid.GetCellData().AddArray(dataset_array) + + + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() return vtk_grid From 722b572dc314ba3dc5802da57a43e0d124323556 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 12:31:35 +0200 Subject: [PATCH 0481/2654] write_data_to_vtk RegularMesh --- openmc/mesh.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 029d714f0..179e9a171 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -622,7 +622,7 @@ class RegularMesh(StructuredMesh): return root_cell, cells - def vtk_grid(self, filename=None): + def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh Args: @@ -635,6 +635,19 @@ class RegularMesh(StructuredMesh): import vtk from vtk.util import numpy_support as nps + if self.volumes is None and volume_normalization: + raise RuntimeError("No volume data is present on this " + "unstructured mesh. Please load the " + " mesh information from a statepoint file.") + + # check that the data sets are appropriately sized + for label, dataset in datasets.items(): + if isinstance(dataset, np.ndarray): + assert dataset.size == self.dimension[0] * self.dimension[1] * self.dimension[2] + else: + assert len(dataset) == self.dimension[0] * self.dimension[1] * self.dimension[2] + cv.check_type('label', label, str) + x_vals = np.linspace( self.lower_left[0], self.upper_right[0], @@ -661,12 +674,26 @@ class RegularMesh(StructuredMesh): vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) vtk_grid.SetPoints(vtkPts) - if filename: - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() + # create VTK arrays for each of + # the data sets + for label, dataset in datasets.items(): + dataset = np.asarray(dataset).flatten() + + if volume_normalization: + dataset /= self.volumes.flatten() + + dataset_array = vtk.vtkDoubleArray() + dataset_array.SetName(label) + dataset_array.SetArray(nps.numpy_to_vtk(dataset), + dataset.size, + True) + vtk_grid.GetCellData().AddArray(dataset_array) + + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() return vtk_grid From 5ecac76b6960f635f375fd48f3cb567733073d3f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 12:34:05 +0200 Subject: [PATCH 0482/2654] write_data_to_vtk rectilinear mesh --- openmc/mesh.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 179e9a171..db2e1593c 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -895,7 +895,7 @@ class RectilinearMesh(StructuredMesh): return element - def vtk_grid(self, filename=None): + def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh Args: @@ -908,6 +908,19 @@ class RectilinearMesh(StructuredMesh): import vtk from vtk.util import numpy_support as nps + if self.volumes is None and volume_normalization: + raise RuntimeError("No volume data is present on this " + "unstructured mesh. Please load the " + " mesh information from a statepoint file.") + + # check that the data sets are appropriately sized + for label, dataset in datasets.items(): + if isinstance(dataset, np.ndarray): + assert dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2] + else: + assert len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2] + cv.check_type('label', label, str) + x_vals = self.x_grid y_vals = self.y_grid z_vals = self.z_grid @@ -922,12 +935,26 @@ class RectilinearMesh(StructuredMesh): vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) vtk_grid.SetPoints(vtkPts) - if filename: - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() + # create VTK arrays for each of + # the data sets + for label, dataset in datasets.items(): + dataset = np.asarray(dataset).flatten() + + if volume_normalization: + dataset /= self.volumes.flatten() + + dataset_array = vtk.vtkDoubleArray() + dataset_array.SetName(label) + dataset_array.SetArray(nps.numpy_to_vtk(dataset), + dataset.size, + True) + vtk_grid.GetCellData().AddArray(dataset_array) + + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() return vtk_grid From 3233ffc759708b6df7a12c8234404897fa329e51 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 12:34:58 +0200 Subject: [PATCH 0483/2654] removed Tally.write_to_vtk --- openmc/tallies.py | 48 ----------------------------------------------- 1 file changed, 48 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index e67365df6..d0355f14e 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3013,54 +3013,6 @@ class Tally(IDManagerMixin): new_tally.sparse = self.sparse return new_tally - def write_to_vtk(self, filename): - """Writes the tally to a vtk file - - Args: - filename (str): the filename (must end with .vtk) - - Raises: - ValueError: if no MeshFilter was found - """ - try: - import vtk - except ModuleNotFoundError: - msg = 'Python package vtk was not found, please install vtk to use Tally.write_to_vtk.' - raise ModuleNotFoundError(msg) - except ImportError as err: - raise err - - # check that tally has a MeshFilter - mesh = None - for f in self.filters: - if isinstance(f, openmc.MeshFilter): - mesh = f.mesh - break - - if not mesh: - raise ValueError( - "write_to_vtk requires a MeshFilter in the tally filters" - ) - - vtk_grid = mesh.vtk_grid() - - # add mean and std dev data - mean_array = vtk.vtkDoubleArray() - mean_array.SetName("mean") - mean_array.SetArray(self.mean, self.mean.size, True) - vtk_grid.GetCellData().AddArray(mean_array) - - std_dev_array = vtk.vtkDoubleArray() - std_dev_array.SetName("std_dev") - std_dev_array.SetArray(self.std_dev, self.std_dev.size, True) - vtk_grid.GetCellData().AddArray(std_dev_array) - - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() - class Tallies(cv.CheckedList): """Collection of Tallies used for an OpenMC simulation. From c58465214b96f7245979f792f4bf98201551e560 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 13:01:47 +0200 Subject: [PATCH 0484/2654] removed tally tests --- tests/unit_tests/test_tallies.py | 63 -------------------------------- 1 file changed, 63 deletions(-) diff --git a/tests/unit_tests/test_tallies.py b/tests/unit_tests/test_tallies.py index e3f9a486d..bfff741a9 100644 --- a/tests/unit_tests/test_tallies.py +++ b/tests/unit_tests/test_tallies.py @@ -1,7 +1,4 @@ import numpy as np -import pytest -import vtk -from os.path import exists import openmc @@ -42,63 +39,3 @@ def test_xml_roundtrip(run_in_tmpdir): assert new_tally.triggers[0].trigger_type == tally.triggers[0].trigger_type assert new_tally.triggers[0].threshold == tally.triggers[0].threshold assert new_tally.triggers[0].scores == tally.triggers[0].scores - -def run_dummy_sim(tally): - mat = openmc.Material() - mat.add_nuclide('Zr90', 1.0) - mat.set_density('g/cm3', 1.0) - - model = openmc.Model() - sph = openmc.Sphere(r=25.0, boundary_type='vacuum') - cell = openmc.Cell(fill=mat, region=-sph) - model.geometry = openmc.Geometry([cell]) - - model.settings.run_mode = 'fixed source' - model.settings.batches = 2 - model.settings.particles = 50 - - model.tallies = openmc.Tallies([tally]) - - model.run() - -cylinder_mesh = openmc.CylindricalMesh() -cylinder_mesh.r_grid = np.linspace(1, 2, num=30) -cylinder_mesh.phi_grid = np.linspace(0, np.pi / 2, num=50) -cylinder_mesh.z_grid = np.linspace(0, 1, num=30) - -regular_mesh = openmc.RegularMesh() -regular_mesh.lower_left = [0, 0, 0] -regular_mesh.upper_right = [1, 1, 1] -regular_mesh.dimension = [10, 5, 6] - -rectilinear_mesh = openmc.RectilinearMesh() -rectilinear_mesh.x_grid = np.linspace(0, 1) -rectilinear_mesh.y_grid = np.linspace(0, 1) -rectilinear_mesh.z_grid = np.linspace(0, 1) - -spherical_mesh = openmc.SphericalMesh() -spherical_mesh.r_grid = np.linspace(1, 2) -spherical_mesh.phi_grid = np.linspace(1, 2) -spherical_mesh.theta_grid = np.linspace(1, 2) - -@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) -def test_write_to_vtk(mesh, tmpdir): - # build - tally = openmc.Tally() - tally.filters = [openmc.MeshFilter(mesh)] - filename = tmpdir / "out.vtk" - run_dummy_sim(tally) - # run - tally.write_to_vtk(filename) - # test - assert exists(filename) - - -def test_write_to_vtk_raises_error_when_no_meshfilter(): - # build - tally = openmc.Tally() - - # test - expected_err_msg = "write_to_vtk requires a MeshFilter in the tally filters" - with pytest.raises(ValueError, match=expected_err_msg): - tally.write_to_vtk("out.vtk") From 15b98ea541fd27f6e02b5939bd482155cf44b56b Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 13:02:12 +0200 Subject: [PATCH 0485/2654] added a test to meshes --- tests/unit_tests/test_mesh_to_vtk.py | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/unit_tests/test_mesh_to_vtk.py diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py new file mode 100644 index 000000000..b5c8ca60a --- /dev/null +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -0,0 +1,35 @@ +import numpy as np +from os.path import exists +import pytest + +import openmc + + +regular_mesh = openmc.RegularMesh() +regular_mesh.lower_left = (0, 0, 0) +regular_mesh.upper_right = (1, 1, 1) +regular_mesh.dimension = [30, 20, 10] + +rectilinear_mesh = openmc.RectilinearMesh() +rectilinear_mesh.x_grid = np.linspace(1, 2, num=30) +rectilinear_mesh.y_grid = np.linspace(1, 2, num=30) +rectilinear_mesh.z_grid = np.linspace(1, 2, num=30) + +cylinder_mesh = openmc.CylindricalMesh() +cylinder_mesh.r_grid = np.linspace(1, 2, num=30) +cylinder_mesh.phi_grid = np.linspace(0, np.pi, num=50) +cylinder_mesh.z_grid = np.linspace(0, 1, num=30) + +spherical_mesh = openmc.SphericalMesh() +spherical_mesh.r_grid = np.linspace(1, 2, num=30) +spherical_mesh.phi_grid = np.linspace(0, np.pi, num=50) +spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, num=30) + +@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) +def test_write_data_to_vtk(mesh, tmpdir): + filename = tmpdir / "out.vtk" + + data = np.random.random(mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2]) + + mesh.write_data_to_vtk(filename=filename, datasets={"label": data}) + assert exists(filename) \ No newline at end of file From 5174145c1ec9daacac8cfcd33e4b9212d9889fa1 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 13:21:36 +0200 Subject: [PATCH 0486/2654] added checks to test --- tests/unit_tests/test_mesh_to_vtk.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index b5c8ca60a..e487b3668 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -1,6 +1,8 @@ import numpy as np from os.path import exists import pytest +import vtk +from vtk.util import numpy_support as nps import openmc @@ -27,9 +29,30 @@ spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, num=30) @pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) def test_write_data_to_vtk(mesh, tmpdir): + # BUILD filename = tmpdir / "out.vtk" data = np.random.random(mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2]) - mesh.write_data_to_vtk(filename=filename, datasets={"label": data}) - assert exists(filename) \ No newline at end of file + # RUN + mesh.write_data_to_vtk(filename=filename, datasets={"label1": data, "label2": data}) + + # TEST + assert exists(filename) + + # read file + reader = vtk.vtkStructuredGridReader() + reader.SetFileName(filename) + reader.Update() + + # check name of datasets + vtk_grid = reader.GetOutput() + array1 = vtk_grid.GetCellData().GetArray(0) + array2 = vtk_grid.GetCellData().GetArray(1) + + assert array1.GetName() == "label1" + assert array2.GetName() == "label2" + + # check size of datasets + assert nps.vtk_to_numpy(array1).size == data.size + assert nps.vtk_to_numpy(array2).size == data.size \ No newline at end of file From 5603e328b8650e874b2cf0235bba6fe792850129 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 13:24:44 +0200 Subject: [PATCH 0487/2654] docstrings --- openmc/mesh.py | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index db2e1593c..1372c5196 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -626,8 +626,16 @@ class RegularMesh(StructuredMesh): """Creates a VTK object of the mesh Args: - filename (str, optional): Name of the vtk file to write = - (must end with .vtk). Defaults to None. + filename (str): Name of the VTK file to write. + datasets (dict): Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization (bool, optional): Whether or not to + normalize the data by the volume of the mesh elements. + Defaults to True. + + Raises: + RuntimeError: when no volume data is found and volume_normalisation + is required Returns: vtk.vtkStructuredGrid: the VTK object @@ -899,8 +907,16 @@ class RectilinearMesh(StructuredMesh): """Creates a VTK object of the mesh Args: - filename (str, optional): Name of the vtk file to write = - (must end with .vtk). Defaults to None. + filename (str): Name of the VTK file to write. + datasets (dict): Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization (bool, optional): Whether or not to + normalize the data by the volume of the mesh elements. + Defaults to True. + + Raises: + RuntimeError: when no volume data is found and volume_normalisation + is required Returns: vtk.vtkStructuredGrid: the VTK object @@ -1153,8 +1169,16 @@ class CylindricalMesh(StructuredMesh): """Creates a VTK object of the mesh Args: - filename (str, optional): Name of the vtk file to write = - (must end with .vtk). Defaults to None. + filename (str): Name of the VTK file to write. + datasets (dict): Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization (bool, optional): Whether or not to + normalize the data by the volume of the mesh elements. + Defaults to True. + + Raises: + RuntimeError: when no volume data is found and volume_normalisation + is required Returns: vtk.vtkStructuredGrid: the VTK object @@ -1409,8 +1433,16 @@ class SphericalMesh(StructuredMesh): """Creates a VTK object of the mesh Args: - filename (str, optional): Name of the vtk file to write = - (must end with .vtk). Defaults to None. + filename (str): Name of the VTK file to write. + datasets (dict): Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization (bool, optional): Whether or not to + normalize the data by the volume of the mesh elements. + Defaults to True. + + Raises: + RuntimeError: when no volume data is found and volume_normalisation + is required Returns: vtk.vtkStructuredGrid: the VTK object From c77eb6097d6584820256ad497520273669299f9a Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:18:31 +0200 Subject: [PATCH 0488/2654] removed check volume for structured meshes --- openmc/mesh.py | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 1372c5196..a63834941 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -633,21 +633,12 @@ class RegularMesh(StructuredMesh): normalize the data by the volume of the mesh elements. Defaults to True. - Raises: - RuntimeError: when no volume data is found and volume_normalisation - is required - Returns: vtk.vtkStructuredGrid: the VTK object """ import vtk from vtk.util import numpy_support as nps - if self.volumes is None and volume_normalization: - raise RuntimeError("No volume data is present on this " - "unstructured mesh. Please load the " - " mesh information from a statepoint file.") - # check that the data sets are appropriately sized for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): @@ -914,21 +905,12 @@ class RectilinearMesh(StructuredMesh): normalize the data by the volume of the mesh elements. Defaults to True. - Raises: - RuntimeError: when no volume data is found and volume_normalisation - is required - Returns: vtk.vtkStructuredGrid: the VTK object """ import vtk from vtk.util import numpy_support as nps - if self.volumes is None and volume_normalization: - raise RuntimeError("No volume data is present on this " - "unstructured mesh. Please load the " - " mesh information from a statepoint file.") - # check that the data sets are appropriately sized for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): @@ -1176,21 +1158,12 @@ class CylindricalMesh(StructuredMesh): normalize the data by the volume of the mesh elements. Defaults to True. - Raises: - RuntimeError: when no volume data is found and volume_normalisation - is required - Returns: vtk.vtkStructuredGrid: the VTK object """ import vtk from vtk.util import numpy_support as nps - if self.volumes is None and volume_normalization: - raise RuntimeError("No volume data is present on this " - "unstructured mesh. Please load the " - " mesh information from a statepoint file.") - # check that the data sets are appropriately sized for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): @@ -1440,21 +1413,12 @@ class SphericalMesh(StructuredMesh): normalize the data by the volume of the mesh elements. Defaults to True. - Raises: - RuntimeError: when no volume data is found and volume_normalisation - is required - Returns: vtk.vtkStructuredGrid: the VTK object """ import vtk from vtk.util import numpy_support as nps - if self.volumes is None and volume_normalization: - raise RuntimeError("No volume data is present on this " - "unstructured mesh. Please load the " - " mesh information from a statepoint file.") - # check that the data sets are appropriately sized for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): From 1a7c0791bf92e46475343323d7ac0b939bcb9a5a Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:19:12 +0200 Subject: [PATCH 0489/2654] z is unchanged --- openmc/mesh.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index a63834941..1ccb6e86e 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1179,10 +1179,9 @@ class CylindricalMesh(StructuredMesh): # create points pts_cylindrical = np.array([[r, phi, z] for z in self.z_grid for phi in self.phi_grid for r in self.r_grid]) pts_cartesian = np.copy(pts_cylindrical) - r, phi, z = pts_cylindrical[:, 0], pts_cylindrical[:, 1], pts_cylindrical[:, 2] + r, phi = pts_cylindrical[:, 0], pts_cylindrical[:, 1] pts_cartesian[:, 0] = r * np.cos(phi) pts_cartesian[:, 1] = r * np.sin(phi) - pts_cartesian[:, 2] = z vtkPts = vtk.vtkPoints() vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) From 9867a4340abbbd2fa093acb1fd04ed1745ab6513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:19:56 +0200 Subject: [PATCH 0490/2654] [skip ci] use .num_mesh_cells Co-authored-by: Paul Romano --- tests/unit_tests/test_mesh_to_vtk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index e487b3668..b57235edd 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -32,7 +32,7 @@ def test_write_data_to_vtk(mesh, tmpdir): # BUILD filename = tmpdir / "out.vtk" - data = np.random.random(mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2]) + data = np.random.random(mesh.num_mesh_cells) # RUN mesh.write_data_to_vtk(filename=filename, datasets={"label1": data, "label2": data}) From 7e074fe354fc60887c8c4d6540c28e1a6a338ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:20:17 +0200 Subject: [PATCH 0491/2654] [skip ci] str(filename) Co-authored-by: Paul Romano --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 1372c5196..e024710b4 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -699,7 +699,7 @@ class RegularMesh(StructuredMesh): # write the .vtk file writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) + writer.SetFileName(str(filename)) writer.SetInputData(vtk_grid) writer.Write() From 1155ffb739d8a80e5520c1013596864874a57cf5 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:21:15 +0200 Subject: [PATCH 0492/2654] added pathlib import --- tests/unit_tests/test_mesh_to_vtk.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index e487b3668..cfb0407ca 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -1,5 +1,6 @@ import numpy as np from os.path import exists +from pathlib import Path import pytest import vtk from vtk.util import numpy_support as nps From aeeb078344023ebb47ec7238b763c89a541a05fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:22:01 +0200 Subject: [PATCH 0493/2654] [skip ci] pathlib instead of os Co-authored-by: Paul Romano --- tests/unit_tests/test_mesh_to_vtk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index b57235edd..3b7ccf9fa 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -30,7 +30,7 @@ spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, num=30) @pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) def test_write_data_to_vtk(mesh, tmpdir): # BUILD - filename = tmpdir / "out.vtk" + filename = Path(tmpdir) / "out.vtk" data = np.random.random(mesh.num_mesh_cells) From f99e93b5839f4166972fa8e83d93de6eccb5b619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:22:26 +0200 Subject: [PATCH 0494/2654] [skip ci] is_file() instead of exists() Co-authored-by: Paul Romano --- tests/unit_tests/test_mesh_to_vtk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 3b7ccf9fa..31fbd4c88 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -38,7 +38,7 @@ def test_write_data_to_vtk(mesh, tmpdir): mesh.write_data_to_vtk(filename=filename, datasets={"label1": data, "label2": data}) # TEST - assert exists(filename) + assert filename.is_file() # read file reader = vtk.vtkStructuredGridReader() From 1266e433c8bd3f525e6b1ea9bafef174238be09c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:23:06 +0200 Subject: [PATCH 0495/2654] removed unused import --- tests/unit_tests/test_mesh_to_vtk.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 572834f84..5da62cdef 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -1,5 +1,4 @@ import numpy as np -from os.path import exists from pathlib import Path import pytest import vtk From 58ccb82cf50a5ba76e622f96969ba4db6752a885 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:26:27 +0200 Subject: [PATCH 0496/2654] back to .dimension --- tests/unit_tests/test_mesh_to_vtk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 5da62cdef..451c869c2 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -32,7 +32,7 @@ def test_write_data_to_vtk(mesh, tmpdir): # BUILD filename = Path(tmpdir) / "out.vtk" - data = np.random.random(mesh.num_mesh_cells) + data = np.random.random(mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2]) # RUN mesh.write_data_to_vtk(filename=filename, datasets={"label1": data, "label2": data}) From 890c3ad0d58fa59532dc143e56c0100e4540fd0d Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:26:46 +0200 Subject: [PATCH 0497/2654] pytest.importorskip --- tests/unit_tests/test_mesh_to_vtk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 451c869c2..f651f5acb 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -1,7 +1,8 @@ import numpy as np from pathlib import Path import pytest -import vtk + +vtk = pytest.importorskip("vtk") from vtk.util import numpy_support as nps import openmc From 48a0d15b1aa6bbbfa2f3b3c85252a9d05c923028 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:36:54 +0200 Subject: [PATCH 0498/2654] added error raise + new test --- openmc/mesh.py | 53 ++++++++++++++++++++++------ tests/unit_tests/test_mesh_to_vtk.py | 17 ++++++++- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index b883a4a09..ada69887a 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -635,16 +635,22 @@ class RegularMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object + + Raises: + RuntimeError: when the size of a dataset doesn't match the number of cells """ import vtk from vtk.util import numpy_support as nps # check that the data sets are appropriately sized + errmsg = "The size of the dataset {} should be equal to the number of cells" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): - assert dataset.size == self.dimension[0] * self.dimension[1] * self.dimension[2] + if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) else: - assert len(dataset) == self.dimension[0] * self.dimension[1] * self.dimension[2] + if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) cv.check_type('label', label, str) x_vals = np.linspace( @@ -907,16 +913,22 @@ class RectilinearMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object + + Raises: + RuntimeError: when the size of a dataset doesn't match the number of cells """ import vtk from vtk.util import numpy_support as nps # check that the data sets are appropriately sized + errmsg = "The size of the dataset {} should be equal to the number of cells" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): - assert dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2] + if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) else: - assert len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2] + if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) cv.check_type('label', label, str) x_vals = self.x_grid @@ -1160,16 +1172,22 @@ class CylindricalMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object + + Raises: + RuntimeError: when the size of a dataset doesn't match the number of cells """ import vtk from vtk.util import numpy_support as nps # check that the data sets are appropriately sized + errmsg = "The size of the dataset {} should be equal to the number of cells" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): - assert dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2] + if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) else: - assert len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2] + if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) cv.check_type('label', label, str) vtk_grid = vtk.vtkStructuredGrid() @@ -1414,16 +1432,23 @@ class SphericalMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object + + Raises: + RuntimeError: when the size of a dataset doesn't match the number of cells """ import vtk from vtk.util import numpy_support as nps # check that the data sets are appropriately sized + errmsg = "The size of the dataset {} should be equal to the number of cells" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): - assert dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2] + if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) else: - assert len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2] + if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) + cv.check_type('label', label, str) vtk_grid = vtk.vtkStructuredGrid() @@ -1642,6 +1667,11 @@ class UnstructuredMesh(MeshBase): volume_normalization : bool Whether or not to normalize the data by the volume of the mesh elements + + Raises + ------ + RuntimeError + when the size of a dataset doesn't match the number of cells """ import vtk @@ -1658,11 +1688,14 @@ class UnstructuredMesh(MeshBase): " mesh information from a statepoint file.") # check that the data sets are appropriately sized + errmsg = "The size of the dataset {} should be equal to the number of cells" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): - assert dataset.size == self.n_elements + if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) else: - assert len(dataset) == self.n_elements + if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) cv.check_type('label', label, str) # create data arrays for the cells/points diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index f651f5acb..9022feecd 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -56,4 +56,19 @@ def test_write_data_to_vtk(mesh, tmpdir): # check size of datasets assert nps.vtk_to_numpy(array1).size == data.size - assert nps.vtk_to_numpy(array2).size == data.size \ No newline at end of file + assert nps.vtk_to_numpy(array2).size == data.size + +@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) +def test_write_data_to_vtk_size_mismatch(mesh): + """Checks that an error is raised when the size of the dataset + doesn't match the mesh number of cells + + Args: + mesh (openmc.StructuredMesh): the mesh to test + """ + right_size = mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2] + data = np.random.random(right_size + 1) + + expected_error_msg = "The size of the dataset label should be equal to the number of cells" + with pytest.raises(RuntimeError, match=expected_error_msg): + mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) \ No newline at end of file From 8857b769324f299ad410926b2542c7b7a24a895f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:50:28 +0200 Subject: [PATCH 0499/2654] refactored by adding StructuredMesh.write_data_to_vtk() --- openmc/mesh.py | 260 +++++++++++++------------------------------------ 1 file changed, 70 insertions(+), 190 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index ada69887a..5083b215c 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -193,6 +193,51 @@ class StructuredMesh(MeshBase): s1 = (slice(1, None),)*ndim + (slice(None),) return (vertices[s0] + vertices[s1]) / 2 + def write_data_to_vtk(self, points, filename, datasets, volume_normalization=True): + import vtk + from vtk.util import numpy_support as nps + + # check that the data sets are appropriately sized + errmsg = "The size of the dataset {} should be equal to the number of cells" + for label, dataset in datasets.items(): + if isinstance(dataset, np.ndarray): + if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) + else: + if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: + raise RuntimeError(errmsg.format(label)) + cv.check_type('label', label, str) + + vtk_grid = vtk.vtkStructuredGrid() + + vtk_grid.SetDimensions(*self.dimension) + + vtkPts = vtk.vtkPoints() + vtkPts.SetData(nps.numpy_to_vtk(points, deep=True)) + vtk_grid.SetPoints(vtkPts) + + # create VTK arrays for each of + # the data sets + for label, dataset in datasets.items(): + dataset = np.asarray(dataset).flatten() + + if volume_normalization: + dataset /= self.volumes.flatten() + + dataset_array = vtk.vtkDoubleArray() + dataset_array.SetName(label) + dataset_array.SetArray(nps.numpy_to_vtk(dataset), + dataset.size, + True) + vtk_grid.GetCellData().AddArray(dataset_array) + + # write the .vtk file + writer = vtk.vtkStructuredGridWriter() + writer.SetFileName(str(filename)) + writer.SetInputData(vtk_grid) + writer.Write() + + return vtk_grid class RegularMesh(StructuredMesh): """A regular Cartesian mesh in one, two, or three dimensions @@ -635,23 +680,7 @@ class RegularMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object - - Raises: - RuntimeError: when the size of a dataset doesn't match the number of cells """ - import vtk - from vtk.util import numpy_support as nps - - # check that the data sets are appropriately sized - errmsg = "The size of the dataset {} should be equal to the number of cells" - for label, dataset in datasets.items(): - if isinstance(dataset, np.ndarray): - if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - else: - if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - cv.check_type('label', label, str) x_vals = np.linspace( self.lower_left[0], @@ -668,39 +697,16 @@ class RegularMesh(StructuredMesh): self.upper_right[2], num=self.dimension[2] + 1, ) - vtk_grid = vtk.vtkStructuredGrid() - - vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) # create points pts_cartesian = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) - vtkPts = vtk.vtkPoints() - vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) - vtk_grid.SetPoints(vtkPts) - - # create VTK arrays for each of - # the data sets - for label, dataset in datasets.items(): - dataset = np.asarray(dataset).flatten() - - if volume_normalization: - dataset /= self.volumes.flatten() - - dataset_array = vtk.vtkDoubleArray() - dataset_array.SetName(label) - dataset_array.SetArray(nps.numpy_to_vtk(dataset), - dataset.size, - True) - vtk_grid.GetCellData().AddArray(dataset_array) - - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(str(filename)) - writer.SetInputData(vtk_grid) - writer.Write() - - return vtk_grid + return super().write_data_to_vtk( + points=pts_cartesian, + filename=filename, + datasets=datasets, + volume_normalization=volume_normalization + ) def Mesh(*args, **kwargs): warnings.warn("Mesh has been renamed RegularMesh. Future versions of " @@ -913,60 +919,16 @@ class RectilinearMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object - - Raises: - RuntimeError: when the size of a dataset doesn't match the number of cells """ - import vtk - from vtk.util import numpy_support as nps - - # check that the data sets are appropriately sized - errmsg = "The size of the dataset {} should be equal to the number of cells" - for label, dataset in datasets.items(): - if isinstance(dataset, np.ndarray): - if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - else: - if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - cv.check_type('label', label, str) - - x_vals = self.x_grid - y_vals = self.y_grid - z_vals = self.z_grid - vtk_grid = vtk.vtkStructuredGrid() - - vtk_grid.SetDimensions(len(x_vals), len(y_vals), len(z_vals)) - # create points - pts_cartesian = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) + pts_cartesian = np.array([[x, y, z] for z in self.z_grid for y in self.y_grid for x in self.x_grid]) - vtkPts = vtk.vtkPoints() - vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) - vtk_grid.SetPoints(vtkPts) - - # create VTK arrays for each of - # the data sets - for label, dataset in datasets.items(): - dataset = np.asarray(dataset).flatten() - - if volume_normalization: - dataset /= self.volumes.flatten() - - dataset_array = vtk.vtkDoubleArray() - dataset_array.SetName(label) - dataset_array.SetArray(nps.numpy_to_vtk(dataset), - dataset.size, - True) - vtk_grid.GetCellData().AddArray(dataset_array) - - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() - - return vtk_grid + return super().write_data_to_vtk( + points=pts_cartesian, + filename=filename, + datasets=datasets, + volume_normalization=volume_normalization + ) class CylindricalMesh(StructuredMesh): @@ -1172,28 +1134,7 @@ class CylindricalMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object - - Raises: - RuntimeError: when the size of a dataset doesn't match the number of cells """ - import vtk - from vtk.util import numpy_support as nps - - # check that the data sets are appropriately sized - errmsg = "The size of the dataset {} should be equal to the number of cells" - for label, dataset in datasets.items(): - if isinstance(dataset, np.ndarray): - if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - else: - if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - cv.check_type('label', label, str) - - vtk_grid = vtk.vtkStructuredGrid() - - vtk_grid.SetDimensions(len(self.r_grid), len(self.phi_grid), len(self.z_grid)) - # create points pts_cylindrical = np.array([[r, phi, z] for z in self.z_grid for phi in self.phi_grid for r in self.r_grid]) pts_cartesian = np.copy(pts_cylindrical) @@ -1201,32 +1142,12 @@ class CylindricalMesh(StructuredMesh): pts_cartesian[:, 0] = r * np.cos(phi) pts_cartesian[:, 1] = r * np.sin(phi) - vtkPts = vtk.vtkPoints() - vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) - vtk_grid.SetPoints(vtkPts) - - # create VTK arrays for each of - # the data sets - for label, dataset in datasets.items(): - dataset = np.asarray(dataset).flatten() - - if volume_normalization: - dataset /= self.volumes.flatten() - - dataset_array = vtk.vtkDoubleArray() - dataset_array.SetName(label) - dataset_array.SetArray(nps.numpy_to_vtk(dataset), - dataset.size, - True) - vtk_grid.GetCellData().AddArray(dataset_array) - - - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() - - return vtk_grid + return super().write_data_to_vtk( + points=pts_cartesian, + filename=filename, + datasets=datasets, + volume_normalization=volume_normalization + ) class SphericalMesh(StructuredMesh): """A 3D spherical mesh @@ -1432,28 +1353,7 @@ class SphericalMesh(StructuredMesh): Returns: vtk.vtkStructuredGrid: the VTK object - - Raises: - RuntimeError: when the size of a dataset doesn't match the number of cells """ - import vtk - from vtk.util import numpy_support as nps - - # check that the data sets are appropriately sized - errmsg = "The size of the dataset {} should be equal to the number of cells" - for label, dataset in datasets.items(): - if isinstance(dataset, np.ndarray): - if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - else: - if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - - cv.check_type('label', label, str) - - vtk_grid = vtk.vtkStructuredGrid() - - vtk_grid.SetDimensions(len(self.r_grid), len(self.theta_grid), len(self.phi_grid)) # create points pts_spherical = np.array([[r, theta, phi] for phi in self.phi_grid for theta in self.theta_grid for r in self.r_grid]) @@ -1463,32 +1363,12 @@ class SphericalMesh(StructuredMesh): pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) pts_cartesian[:, 2] = r * np.cos(phi) - vtkPts = vtk.vtkPoints() - vtkPts.SetData(nps.numpy_to_vtk(pts_cartesian, deep=True)) - vtk_grid.SetPoints(vtkPts) - - # create VTK arrays for each of - # the data sets - for label, dataset in datasets.items(): - dataset = np.asarray(dataset).flatten() - - if volume_normalization: - dataset /= self.volumes.flatten() - - dataset_array = vtk.vtkDoubleArray() - dataset_array.SetName(label) - dataset_array.SetArray(nps.numpy_to_vtk(dataset), - dataset.size, - True) - vtk_grid.GetCellData().AddArray(dataset_array) - - # write the .vtk file - writer = vtk.vtkStructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(vtk_grid) - writer.Write() - - return vtk_grid + return super().write_data_to_vtk( + points=pts_cartesian, + filename=filename, + datasets=datasets, + volume_normalization=volume_normalization + ) class UnstructuredMesh(MeshBase): From 0c4de41f5076acbd93efaad6cdb970e26c890964 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 14:56:27 +0200 Subject: [PATCH 0500/2654] docstrings --- openmc/mesh.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 5083b215c..449edb8d6 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -194,6 +194,24 @@ class StructuredMesh(MeshBase): return (vertices[s0] + vertices[s1]) / 2 def write_data_to_vtk(self, points, filename, datasets, volume_normalization=True): + """Creates a VTK object of the mesh + + Args: + points (list or np.array): List of (X,Y,Y) tuples. + filename (str): Name of the VTK file to write. + datasets (dict): Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization (bool, optional): Whether or not to + normalize the data by the volume of the mesh elements. + Defaults to True. + + Raises: + RuntimeError: when the size of a dataset doesn't match the number of cells + + Returns: + vtk.vtkStructuredGrid: the VTK object + """ + import vtk from vtk.util import numpy_support as nps From ad73f03a0d712311b0d5ef80f0456d2c35b61dbe Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 15:02:20 +0200 Subject: [PATCH 0501/2654] converted docstrings to numpy style --- openmc/mesh.py | 129 +++++++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 48 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 449edb8d6..aa338f97e 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -196,20 +196,29 @@ class StructuredMesh(MeshBase): def write_data_to_vtk(self, points, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh - Args: - points (list or np.array): List of (X,Y,Y) tuples. - filename (str): Name of the VTK file to write. - datasets (dict): Dictionary whose keys are the data labels - and values are the data sets. - volume_normalization (bool, optional): Whether or not to - normalize the data by the volume of the mesh elements. - Defaults to True. + Parameters + ---------- + points : list or np.array + List of (X,Y,Y) tuples. + filename : str + Name of the VTK file to write. + datasets : dict + Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization : bool, optional + Whether or not to normalize the data by + the volume of the mesh elements. + Defaults to True. - Raises: - RuntimeError: when the size of a dataset doesn't match the number of cells + Raises + ------ + RuntimeError + When the size of a dataset doesn't match the number of cells - Returns: - vtk.vtkStructuredGrid: the VTK object + Returns + ------- + vtk.vtkStructuredGrid + the VTK object """ import vtk @@ -688,16 +697,22 @@ class RegularMesh(StructuredMesh): def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh - Args: - filename (str): Name of the VTK file to write. - datasets (dict): Dictionary whose keys are the data labels - and values are the data sets. - volume_normalization (bool, optional): Whether or not to - normalize the data by the volume of the mesh elements. - Defaults to True. + Parameters + ---------- + filename : str + Name of the VTK file to write. + datasets : dict + Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization : bool, optional + Whether or not to normalize the data by + the volume of the mesh elements. + Defaults to True. - Returns: - vtk.vtkStructuredGrid: the VTK object + Returns + ------- + vtk.vtkStructuredGrid + the VTK object """ x_vals = np.linspace( @@ -927,16 +942,22 @@ class RectilinearMesh(StructuredMesh): def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh - Args: - filename (str): Name of the VTK file to write. - datasets (dict): Dictionary whose keys are the data labels - and values are the data sets. - volume_normalization (bool, optional): Whether or not to - normalize the data by the volume of the mesh elements. - Defaults to True. + Parameters + ---------- + filename : str + Name of the VTK file to write. + datasets : dict + Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization : bool, optional + Whether or not to normalize the data by + the volume of the mesh elements. + Defaults to True. - Returns: - vtk.vtkStructuredGrid: the VTK object + Returns + ------- + vtk.vtkStructuredGrid + the VTK object """ # create points pts_cartesian = np.array([[x, y, z] for z in self.z_grid for y in self.y_grid for x in self.x_grid]) @@ -1142,16 +1163,22 @@ class CylindricalMesh(StructuredMesh): def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh - Args: - filename (str): Name of the VTK file to write. - datasets (dict): Dictionary whose keys are the data labels - and values are the data sets. - volume_normalization (bool, optional): Whether or not to - normalize the data by the volume of the mesh elements. - Defaults to True. + Parameters + ---------- + filename : str + Name of the VTK file to write. + datasets : dict + Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization : bool, optional + Whether or not to normalize the data by + the volume of the mesh elements. + Defaults to True. - Returns: - vtk.vtkStructuredGrid: the VTK object + Returns + ------- + vtk.vtkStructuredGrid + the VTK object """ # create points pts_cylindrical = np.array([[r, phi, z] for z in self.z_grid for phi in self.phi_grid for r in self.r_grid]) @@ -1361,16 +1388,22 @@ class SphericalMesh(StructuredMesh): def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh - Args: - filename (str): Name of the VTK file to write. - datasets (dict): Dictionary whose keys are the data labels - and values are the data sets. - volume_normalization (bool, optional): Whether or not to - normalize the data by the volume of the mesh elements. - Defaults to True. + Parameters + ---------- + filename : str + Name of the VTK file to write. + datasets : dict + Dictionary whose keys are the data labels + and values are the data sets. + volume_normalization : bool, optional + Whether or not to normalize the data by + the volume of the mesh elements. + Defaults to True. - Returns: - vtk.vtkStructuredGrid: the VTK object + Returns + ------- + vtk.vtkStructuredGrid + the VTK object """ # create points From a2299063f5b4061a2eb2cd762004439fadbab57c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 15:02:52 +0200 Subject: [PATCH 0502/2654] converted docstrings to numpy style --- tests/unit_tests/test_mesh_to_vtk.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 9022feecd..9247540a0 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -63,8 +63,10 @@ def test_write_data_to_vtk_size_mismatch(mesh): """Checks that an error is raised when the size of the dataset doesn't match the mesh number of cells - Args: - mesh (openmc.StructuredMesh): the mesh to test + Parameters + ---------- + mesh : openmc.StructuredMesh + The mesh to test """ right_size = mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2] data = np.random.random(right_size + 1) From d80bf7bdb596a7169f0e28d42b363d1886c43448 Mon Sep 17 00:00:00 2001 From: Patrick Myers <90068356+myerspat@users.noreply.github.com> Date: Wed, 29 Jun 2022 09:25:59 -0500 Subject: [PATCH 0503/2654] Added comments explaining reasoning for 2D xtensor xs in photon.h Co-authored-by: Paul Romano --- include/openmc/photon.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/openmc/photon.h b/include/openmc/photon.h index 50ee228c4..09fb3ba01 100644 --- a/include/openmc/photon.h +++ b/include/openmc/photon.h @@ -79,7 +79,9 @@ public: Tabulated1D coherent_anomalous_real_; Tabulated1D coherent_anomalous_imag_; - // Photoionization and atomic relaxation data + // Photoionization and atomic relaxation data. Subshell cross sections are + // stored separately to improve memory access pattern when calculating the + // total cross section vector shells_; xt::xtensor cross_sections_; From 2c5a845897aeb973448f31cea2d9256754262e3e Mon Sep 17 00:00:00 2001 From: Patrick Myers <90068356+myerspat@users.noreply.github.com> Date: Wed, 29 Jun 2022 09:26:36 -0500 Subject: [PATCH 0504/2654] Removed an include from photon.cpp Co-authored-by: Paul Romano --- src/photon.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/photon.cpp b/src/photon.cpp index 85bd435c9..a127ac2fe 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -17,7 +17,6 @@ #include "xtensor/xmath.hpp" #include "xtensor/xoperation.hpp" #include "xtensor/xslice.hpp" -#include "xtensor/xtensor_forward.hpp" #include "xtensor/xview.hpp" #include From c38ed4d8759704e829454abfc12dfa2189dd4bf1 Mon Sep 17 00:00:00 2001 From: myerspat Date: Wed, 29 Jun 2022 09:37:18 -0500 Subject: [PATCH 0505/2654] used placeholders namespace and added comment about variables initialized --- src/photon.cpp | 6 ++++-- src/physics.cpp | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/photon.cpp b/src/photon.cpp index a127ac2fe..2f9bc5e3d 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -46,6 +46,8 @@ vector> elements; PhotonInteraction::PhotonInteraction(hid_t group) { + using namespace xt::placeholders; + // Set index of element in global vector index_ = data::elements.size(); @@ -164,8 +166,8 @@ PhotonInteraction::PhotonInteraction(hid_t group) close_dataset(dset); read_dataset(tgroup, "xs", xs); - auto cross_section = xt::view( - cross_sections_, xt::range(shell.threshold, xt::placeholders::_), i); + auto cross_section = + xt::view(cross_sections_, xt::range(shell.threshold, _), i); cross_section = xt::where(xs > 0, xt::log(xs), 0); if (object_exists(tgroup, "transitions")) { diff --git a/src/physics.cpp b/src/physics.cpp index cc712affd..bcdcf7ecf 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -347,7 +347,8 @@ void sample_photon_reaction(Particle& p) double prob_after = prob + micro.photoelectric; if (prob_after > cutoff) { - + // Get grid index, interpolation factor, and bounding subshell + // cross sections int i_grid = micro.index_grid; double f = micro.interp_factor; const auto& xs_lower = xt::row(element.cross_sections_, i_grid); From 7cba2ad03012658481c6edbc04f070892e90dd3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:46:10 +0200 Subject: [PATCH 0506/2654] [skip ci] X Y Y typo Co-authored-by: Paul Romano --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index aa338f97e..90f4c55a9 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -199,7 +199,7 @@ class StructuredMesh(MeshBase): Parameters ---------- points : list or np.array - List of (X,Y,Y) tuples. + List of (X,Y,Z) tuples. filename : str Name of the VTK file to write. datasets : dict From 5180ab3f8a6031cfbcd708c04e7fd23f8936085a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:46:43 +0200 Subject: [PATCH 0507/2654] [skip ci] removed default value Co-authored-by: Paul Romano --- openmc/mesh.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 90f4c55a9..73a49bfc1 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -208,7 +208,6 @@ class StructuredMesh(MeshBase): volume_normalization : bool, optional Whether or not to normalize the data by the volume of the mesh elements. - Defaults to True. Raises ------ From 94ef0c40abe6f4a208aaaccad36c17ff486dd9b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:47:24 +0200 Subject: [PATCH 0508/2654] [skip ci] refactore upperright and lowerleft Co-authored-by: Paul Romano --- openmc/mesh.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 73a49bfc1..7155b0ba0 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -714,21 +714,10 @@ class RegularMesh(StructuredMesh): the VTK object """ - x_vals = np.linspace( - self.lower_left[0], - self.upper_right[0], - num=self.dimension[0] + 1, - ) - y_vals = np.linspace( - self.lower_left[1], - self.upper_right[1], - num=self.dimension[1] + 1, - ) - z_vals = np.linspace( - self.lower_left[2], - self.upper_right[2], - num=self.dimension[2] + 1, - ) + ll, ur = self.lower_left, self.upper_right + x_vals = np.linspace(ll[0], ur[0], num=self.dimension[0] + 1) + y_vals = np.linspace(ll[1], ur[1], num=self.dimension[1] + 1) + z_vals = np.linspace(ll[2], ur[2], num=self.dimension[2] + 1) # create points pts_cartesian = np.array([[x, y, z] for z in z_vals for y in y_vals for x in x_vals]) From 96c89f138daa97f78cb996449a32a88ca58754ff Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 19:01:39 +0200 Subject: [PATCH 0509/2654] multiple lines --- openmc/mesh.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 7155b0ba0..209002e42 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1169,7 +1169,14 @@ class CylindricalMesh(StructuredMesh): the VTK object """ # create points - pts_cylindrical = np.array([[r, phi, z] for z in self.z_grid for phi in self.phi_grid for r in self.r_grid]) + pts_cylindrical = np.array( + [ + [r, phi, z] + for z in self.z_grid + for phi in self.phi_grid + for r in self.r_grid + ] + ) pts_cartesian = np.copy(pts_cylindrical) r, phi = pts_cylindrical[:, 0], pts_cylindrical[:, 1] pts_cartesian[:, 0] = r * np.cos(phi) @@ -1395,7 +1402,14 @@ class SphericalMesh(StructuredMesh): """ # create points - pts_spherical = np.array([[r, theta, phi] for phi in self.phi_grid for theta in self.theta_grid for r in self.r_grid]) + pts_spherical = np.array( + [ + [r, theta, phi] + for phi in self.phi_grid + for theta in self.theta_grid + for r in self.r_grid + ] + ) pts_cartesian = np.copy(pts_spherical) r, theta, phi = pts_spherical[:, 0], pts_spherical[:, 1], pts_spherical[:, 2] pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) From fabe3e607c92891ec740aefa632eba010428eef2 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 29 Jun 2022 19:02:25 +0200 Subject: [PATCH 0510/2654] pathlib --- openmc/mesh.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 209002e42..2a53c8a91 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -698,7 +698,7 @@ class RegularMesh(StructuredMesh): Parameters ---------- - filename : str + filename : str or pathlib.Path Name of the VTK file to write. datasets : dict Dictionary whose keys are the data labels @@ -932,7 +932,7 @@ class RectilinearMesh(StructuredMesh): Parameters ---------- - filename : str + filename : str or pathlib.Path Name of the VTK file to write. datasets : dict Dictionary whose keys are the data labels @@ -1153,7 +1153,7 @@ class CylindricalMesh(StructuredMesh): Parameters ---------- - filename : str + filename : str or pathlib.Path Name of the VTK file to write. datasets : dict Dictionary whose keys are the data labels @@ -1385,7 +1385,7 @@ class SphericalMesh(StructuredMesh): Parameters ---------- - filename : str + filename : str or pathlib.Path Name of the VTK file to write. datasets : dict Dictionary whose keys are the data labels @@ -1592,7 +1592,7 @@ class UnstructuredMesh(MeshBase): Parameters ---------- - filename : str + filename : str or pathlib.Path Name of the VTK file to write. datasets : dict Dictionary whose keys are the data labels From 1ea6734a7fab225103ae857329ab587b5093c886 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 29 Jun 2022 13:16:22 -0500 Subject: [PATCH 0511/2654] remove cruft comments, clean up docstrings --- openmc/deplete/flux_operator.py | 38 ++++++++++----------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 48e9fda33..be23a2dba 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -29,8 +29,8 @@ from .helpers import ConstantFissionYieldHelper class FluxSpectraDepletionOperator(TransportOperator): - """Depletion operator that uses a user provided flux spectrum and one-group - cross sections calculate reaction rates. + """Depletion operator that uses a user-provided flux spectrum and one-group + cross sections to calculate reaction rates. Instances of this class can be used to perform depletion using one group cross sections and constant flux. Normally, a user needn't call methods of @@ -90,8 +90,6 @@ class FluxSpectraDepletionOperator(TransportOperator): The depletion chain information necessary to form matrices and tallies. reaction_rates : openmc.deplete.ReactionRates Reaction rates from the last operator step. - heavy_metal : float - Initial heavy metal inventory [g] prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. @@ -159,7 +157,7 @@ class FluxSpectraDepletionOperator(TransportOperator): def __call__(self, vec, source_rate): - """Runs a simulation. + """Obtain the reaction rates Parameters ---------- @@ -177,14 +175,9 @@ class FluxSpectraDepletionOperator(TransportOperator): # Update the number densities regardless of the source rate self.number.set_density(vec) - ## TODO : make sure this function works w the current structure. self._update_materials() - # Update nuclides data in preparation for transport solve - - ## TODO : make sure this function works w the current structure. - # this nuclides varibale contains all the nuclides that will show up via depletion - # that have xs data + # Get all nuclides for which we will calculate reaction rates rxn_nuclides = self._get_reaction_nuclides() rates = self.reaction_rates @@ -222,13 +215,10 @@ class FluxSpectraDepletionOperator(TransportOperator): # Compute fission yields for this material fission_yields.append(self._yield_helper.weighted_yields(0)) - # Accumulate energy from fission - #if fission_ind is not None: - # self._normalization_helper.update(rxn_rates[:, fission_ind]) - - # Divide by total number and store - # the reason we do this is bc in the equation, we multiply the depletion matrix - # by the nuclide vector. Since what we want is the depletion matrix, we need to + # Divide by total number of atoms and store + # the reason we do this is based on the mathematical equation; + # in the equation, we multiply the depletion matrix by the nuclide + # vector. Since what we want is the depletion matrix, we need to # divide the reaction rates by the number of atoms to get the right units. mask = nonzero(number) results = rates[0] @@ -236,10 +226,6 @@ class FluxSpectraDepletionOperator(TransportOperator): results[mask, col] /= number[mask] rates[0] = results - # Scale reaction rates to obtain units of reactions/sec - #rates *= self._normalization_helper.factor(source_rate) - ## - # Store new fission yields on the chain self.chain.fission_yields = fission_yields @@ -255,9 +241,6 @@ class FluxSpectraDepletionOperator(TransportOperator): Total density for initial conditions. """ - #self._normalization_helper.prepare( - # self.chain.nuclides, self.reaction_rates.index_nuc) - # Return number density vector return list(self.number.get_mat_slice(np.s_[:])) @@ -274,6 +257,7 @@ class FluxSpectraDepletionOperator(TransportOperator): step : int Current depletion step including restarts """ + # Since we aren't running a transport simulation, we simply pass pass @@ -341,7 +325,7 @@ class FluxSpectraDepletionOperator(TransportOperator): # summary.h5 file contains densities at the first time step def _get_reaction_nuclides(self): - """Determine nuclides that should have reation rates + """Determine nuclides that should have reaction rates This method returns a list of all nuclides that have neutron data and are listed in the depletion chain. Technically, we should list nuclides @@ -382,7 +366,7 @@ class FluxSpectraDepletionOperator(TransportOperator): return [nuc for nuc in nuc_list if nuc in self.chain] def _get_all_nuclides_in_simulation(self): - """Determine nuclides that will show up in simulation. + """Determine nuclides that will show up in the simulation. This is the union of the nuclides provided by the user and the nuclides present in the depletion chain. From 50acd579cbfec9817c731665d8b427638f8921a9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 29 Jun 2022 14:18:07 -0500 Subject: [PATCH 0512/2654] added convenience functions for creating the mirco_xs parameter --- openmc/deplete/flux_operator.py | 71 ++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index be23a2dba..b74403b69 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -22,7 +22,7 @@ from openmc.exceptions import DataError from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber -from .chain import _find_chain_file +from .chain import _find_chain_file, REACTIONS from .reaction_rates import ReactionRates from .results import Results from .helpers import ConstantFissionYieldHelper @@ -288,6 +288,75 @@ class FluxSpectraDepletionOperator(TransportOperator): return volume, nuc_list, burn_list, burn_list + @staticmethod + def create_micro_xs_from_data_array(nuclides, reactions, data, units='barn'): + """ + Creates a ``micro_xs`` parameter from a dictionary. + + Parameters + ---------- + nuclides : list of str + List of nuclide symbols for that have data for at least one + reaction. + reactions : list of str + List of reactions. All reactions must match those in ``chain.REACTONS`` + data : ndarray of floats + Array containing one-group microscopic cross section information for each + nuclide and reaction. + units : {'barn', 'cm^2'}, optional + Units for microscopic cross section data. Defaults to ``barn``. + + Returns + ------- + micro_xs : pandas.DataFrame + A DataFrame object correctly formatted for use in ``FluxOperator`` + """ + + # Validate inputs + try: + assert data.shape == (len(nuclides), len(reactions)) + except AssertionError: + raise SyntaxError('Nuclides list of length {len(nuclides)} and + reactions array of length {len(reactions)} do not + match dimensions of data array of shape {data.shape}') + + check_iterable_type('nuclides', nuclides, str) + check_iterable_type('reactions', reactions, str) + check_type('data', data, float, expected_iter_type=np.array) + check_value('reactions', reactions, chain.REACTIONS) + + if units == 'barn': + data /= 1e24 + + return pd.DataFrame(index=nuclides, columns=reactions, data=data) + + + @staticmethod + def create_micro_xs_from_csv(csv_file, units='barn'): + """ + Create the ``micro_xs`` parameter from a ``.csv`` file. + + Parameters + ---------- + csv_file : str + Relative path to csv-file containing microscopic cross section + data. + units : {'barn', 'cm^2'}, optional + Units for microscopic cross section data. Defaults to ``barn``. + + Returns + ------- + micro_xs : pandas.DataFrame + A DataFrame object correctly formatted for use in ``FluxOperator`` + + """ + micro_xs = pd.DataFrame.read_csv(csv_file) + if units == 'barn': + micro_xs /= 1e24 + + return micro_xs + + def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" From ecc38a1ae4ba2adc194bd0a0c61a3d088b56b242 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 29 Jun 2022 14:47:30 -0500 Subject: [PATCH 0513/2654] fix multi-line error message --- openmc/deplete/flux_operator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index b74403b69..ab6fbe565 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -316,9 +316,9 @@ class FluxSpectraDepletionOperator(TransportOperator): try: assert data.shape == (len(nuclides), len(reactions)) except AssertionError: - raise SyntaxError('Nuclides list of length {len(nuclides)} and - reactions array of length {len(reactions)} do not - match dimensions of data array of shape {data.shape}') + raise SyntaxError('Nuclides list of length {len(nuclides)} and' + 'reactions array of length {len(reactions)} do not' + 'match dimensions of data array of shape {data.shape}') check_iterable_type('nuclides', nuclides, str) check_iterable_type('reactions', reactions, str) From 5fec7a2355819039007e509d4cc365dfcf6ac928 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 29 Jun 2022 15:05:22 -0500 Subject: [PATCH 0514/2654] pep8 fixes --- openmc/deplete/flux_operator.py | 53 +++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index ab6fbe565..3ca046cf2 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -155,7 +155,6 @@ class FluxSpectraDepletionOperator(TransportOperator): self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) - def __call__(self, vec, source_rate): """Obtain the reaction rates @@ -207,7 +206,12 @@ class FluxSpectraDepletionOperator(TransportOperator): for nuc in nuclides: density = number.get_atom_density('0', nuc) for rxn in self.chain.reactions: - rates.set('0', nuc, rxn, self._micro_xs[rxn].loc[nuc] * density) + rates.set( + '0', + nuc, + rxn, + self._micro_xs[rxn].loc[nuc] * + density) # Get reaction rate in reactions/sec rates *= self.flux_spectra @@ -219,7 +223,8 @@ class FluxSpectraDepletionOperator(TransportOperator): # the reason we do this is based on the mathematical equation; # in the equation, we multiply the depletion matrix by the nuclide # vector. Since what we want is the depletion matrix, we need to - # divide the reaction rates by the number of atoms to get the right units. + # divide the reaction rates by the number of atoms to get the right + # units. mask = nonzero(number) results = rates[0] for col in range(results.shape[1]): @@ -231,7 +236,6 @@ class FluxSpectraDepletionOperator(TransportOperator): return OperatorResult(self._keff, rates) - def initial_condition(self): """Performs final setup and returns initial condition. @@ -244,8 +248,6 @@ class FluxSpectraDepletionOperator(TransportOperator): # Return number density vector return list(self.number.get_mat_slice(np.s_[:])) - - def write_bos_data(self, step): """Document beginning of step data for a given step @@ -260,7 +262,6 @@ class FluxSpectraDepletionOperator(TransportOperator): # Since we aren't running a transport simulation, we simply pass pass - def get_results_info(self): """Returns volume list, cell lists, and nuc lists. @@ -287,9 +288,9 @@ class FluxSpectraDepletionOperator(TransportOperator): return volume, nuc_list, burn_list, burn_list - @staticmethod - def create_micro_xs_from_data_array(nuclides, reactions, data, units='barn'): + def create_micro_xs_from_data_array( + nuclides, reactions, data, units='barn'): """ Creates a ``micro_xs`` parameter from a dictionary. @@ -316,9 +317,10 @@ class FluxSpectraDepletionOperator(TransportOperator): try: assert data.shape == (len(nuclides), len(reactions)) except AssertionError: - raise SyntaxError('Nuclides list of length {len(nuclides)} and' - 'reactions array of length {len(reactions)} do not' - 'match dimensions of data array of shape {data.shape}') + raise SyntaxError( + 'Nuclides list of length {len(nuclides)} and' + 'reactions array of length {len(reactions)} do not' + 'match dimensions of data array of shape {data.shape}') check_iterable_type('nuclides', nuclides, str) check_iterable_type('reactions', reactions, str) @@ -330,7 +332,6 @@ class FluxSpectraDepletionOperator(TransportOperator): return pd.DataFrame(index=nuclides, columns=reactions, data=data) - @staticmethod def create_micro_xs_from_csv(csv_file, units='barn'): """ @@ -356,7 +357,6 @@ class FluxSpectraDepletionOperator(TransportOperator): return micro_xs - def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" @@ -383,14 +383,20 @@ class FluxSpectraDepletionOperator(TransportOperator): densities.append(val) else: # Only output warnings if values are significantly - # negative. CRAM does not guarantee positive values. + # negative. CRAM does not guarantee positive + # values. if val < -1.0e-21: - print("WARNING: nuclide ", nuc, " in material ", mat, - " is negative (density = ", val, " at/barn-cm)") + print( + "WARNING: nuclide ", + nuc, + " in material ", + mat, + " is negative (density = ", + val, + " at/barn-cm)") number_i[mat, nuc] = 0.0 - - #TODO Update densities on the Python side, otherwise the + # TODO Update densities on the Python side, otherwise the # summary.h5 file contains densities at the first time step def _get_reaction_nuclides(self): @@ -481,17 +487,20 @@ class FluxSpectraDepletionOperator(TransportOperator): if self.dilute_initial != 0.0: for nuc in self._burnable_nucs: - self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) + self.number.set_atom_density( + np.s_[:], nuc, self.dilute_initial) # Now extract and store the number densities # From the geometry if no previous depletion results if prev_res is None: for nuclide in nuclides: if nuclide in self._init_nuclides: - self.number.set_atom_density('0', nuclide, self._init_nuclides[nuclide]) + self.number.set_atom_density( + '0', nuclide, self._init_nuclides[nuclide]) elif nuclide not in self._burnable_nucs: self.number.set_atom_density('0', nuclide, 0) # Else from previous depletion results else: - raise RuntimeError("Loading from previous results not yet supported") + raise RuntimeError( + "Loading from previous results not yet supported") From 0b0265cb592685d8e6daec688229996d7b7e9f5a Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 1 Jul 2022 11:37:16 +0200 Subject: [PATCH 0515/2654] adapted tests --- tests/unit_tests/test_mesh_to_vtk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 9247540a0..26a393b41 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -33,7 +33,7 @@ def test_write_data_to_vtk(mesh, tmpdir): # BUILD filename = Path(tmpdir) / "out.vtk" - data = np.random.random(mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2]) + data = np.random.random(mesh.num_mesh_cells) # RUN mesh.write_data_to_vtk(filename=filename, datasets={"label1": data, "label2": data}) @@ -68,7 +68,7 @@ def test_write_data_to_vtk_size_mismatch(mesh): mesh : openmc.StructuredMesh The mesh to test """ - right_size = mesh.dimension[0]*mesh.dimension[1]*mesh.dimension[2] + right_size = mesh.num_mesh_cells data = np.random.random(right_size + 1) expected_error_msg = "The size of the dataset label should be equal to the number of cells" From 9c892f04dbd36bc423a0560b72bb2da3a1b2a21a Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 1 Jul 2022 09:42:35 +0000 Subject: [PATCH 0516/2654] added num_mesh_cells property to StructuredMesh --- openmc/mesh.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 2a53c8a91..925a63aee 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -193,6 +193,10 @@ class StructuredMesh(MeshBase): s1 = (slice(1, None),)*ndim + (slice(None),) return (vertices[s0] + vertices[s1]) / 2 + @property + def num_mesh_cells(self): + return np.prod(self.dimension) + def write_data_to_vtk(self, points, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh @@ -1547,6 +1551,7 @@ class UnstructuredMesh(MeshBase): "been loaded from a statepoint file.") return len(self._centroids) + @centroids.setter def centroids(self, centroids): cv.check_type("Unstructured mesh centroids", centroids, From 52d59a4c1a924039ca6eb790a1786fe85fce7574 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 1 Jul 2022 09:43:44 +0000 Subject: [PATCH 0517/2654] minor refactoring --- openmc/mesh.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 925a63aee..d5a460baa 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -348,10 +348,6 @@ class RegularMesh(StructuredMesh): dims = self._dimension return [(u - l) / d for u, l, d in zip(us, ls, dims)] - @property - def num_mesh_cells(self): - return np.prod(self._dimension) - @property def volumes(self): """Return Volumes for every mesh cell From bc797c4df83b906bebe454cd1c9d7a17bd52c49c Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 5 Jul 2022 01:30:07 +0200 Subject: [PATCH 0518/2654] don't zip the output-file --- .../source_mcpl_file/gen_dummy_mcpl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c index 7b5a933f1..f35a07fc4 100644 --- a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -54,20 +54,20 @@ int main(int argc, char **argv){ int i; for (i=0;iposition[0]=0; particle->position[1]=0; particle->position[2]=0; - + /*generate a random direction on unit sphere*/ double nrm=2.0; double vx,vy,vz; int iter=0; do { if(iter>100){ - printf("warning: exceeed max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); + printf("Warning: Exceeded max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); } vx=rand01()*2.0-1.0; vy=rand01()*2.0-1.0; @@ -82,9 +82,9 @@ int main(int argc, char **argv){ particle->direction[1]=vy; particle->direction[2]=vz; - /*generate the kinetic energy (in MeV) of the particle*/ + /*generate the kinetic energy (in MeV) of the particle*/ particle->ekin=1e-3; - + /*set time=0*/ particle->time=0; /*set weight*/ @@ -93,5 +93,5 @@ int main(int argc, char **argv){ particle->userflags=0; mcpl_add_particle(outfile,particle); } - mcpl_closeandgzip_outfile(outfile); + mcpl_close_outfile(outfile); } From 80e69b2e0856d5af025087283964fd5a03e20339 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 5 Jul 2022 01:53:14 +0200 Subject: [PATCH 0519/2654] now compiles fine if mcpl is indeed installed --- .../regression_tests/source_mcpl_file/test.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 5a6a87d87..0adf67f1a 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -3,16 +3,13 @@ import os import shutil import subprocess import textwrap - +import glob import openmc import pytest from tests.testing_harness import TestHarness -def model(): - subprocess.run(['gcc','-o gen_dummt_mcpl.out','-lm','-lmcpl','gen_dummy_mcpl.c'] ) - subprocess.run(['./gen_dummy_mcpl.out']) - + class SourceMCPLFileTestHarness(TestHarness): def execute_test(self): """Run OpenMC with the appropriate arguments and check the outputs.""" @@ -26,6 +23,10 @@ class SourceMCPLFileTestHarness(TestHarness): finally: self._cleanup() + def _create_input(self): + subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) + subprocess.run(['./gen_dummy_mcpl.out']) + def update_results(self): """Update the results_true using the current version of OpenMC.""" try: @@ -40,13 +41,19 @@ class SourceMCPLFileTestHarness(TestHarness): def _test_output_created(self): """Check that the output files were created""" - stat epoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' assert statepoint[0].endswith('h5'), \ 'statepoint file does not end with h5.' + def _cleanup(self): + super()._cleanup() + source_mcpl=glob.glob(os.path.join(os.getcwd(),'source*.mcpl')) + for f in source_mcpl: + if (os.path.exists(f)): + os.remove(f) + def test_mcpl_source_file(): harness = SourceMCPLFileTestHarness('statepoint.10.h5') harness.main() - From 9d3573d89052e08894d3e671d2bdde3e7a828869 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 5 Jul 2022 16:30:55 -0500 Subject: [PATCH 0520/2654] unit tests for FluxDepleteOperator - fix value checking syntax in static methods - add convenicece function to D.R.Y. - initial unit tests - add csv file for toy 1g cross sections --- openmc/deplete/flux_operator.py | 34 ++++++--- tests/micro_xs_simple.csv | 13 ++++ .../unit_tests/test_flux_deplete_operator.py | 73 +++++++++++++++++++ 3 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 tests/micro_xs_simple.csv create mode 100644 tests/unit_tests/test_flux_deplete_operator.py diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 3ca046cf2..37100ac5b 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -16,7 +16,7 @@ import pandas as pd from uncertainties import ufloat import openmc -from openmc.checkvalue import check_type +from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.data import DataLibrary from openmc.exceptions import DataError from openmc.mpi import comm @@ -27,8 +27,19 @@ from .reaction_rates import ReactionRates from .results import Results from .helpers import ConstantFissionYieldHelper +valid_rxns = list(REACTIONS.keys()) +valid_rxns += ['fission'] -class FluxSpectraDepletionOperator(TransportOperator): +# Convenience function for the micro_xs static methods +def _validate_micro_xs_inputs(nuclides, reactions, data): + check_iterable_type('nuclides', nuclides, str) + check_iterable_type('reactions', reactions, str) + check_type('data', data, np.ndarray, expected_iter_type=float) + [check_value('reactions', reaction, valid_rxns) for reaction in reactions] + + + +class FluxDepletionOperator(TransportOperator): """Depletion operator that uses a user-provided flux spectrum and one-group cross sections to calculate reaction rates. @@ -318,15 +329,13 @@ class FluxSpectraDepletionOperator(TransportOperator): assert data.shape == (len(nuclides), len(reactions)) except AssertionError: raise SyntaxError( - 'Nuclides list of length {len(nuclides)} and' - 'reactions array of length {len(reactions)} do not' - 'match dimensions of data array of shape {data.shape}') + f'Nuclides list of length {len(nuclides)} and ' + f'reactions array of length {len(reactions)} do not ' + f'match dimensions of data array of shape {data.shape}') - check_iterable_type('nuclides', nuclides, str) - check_iterable_type('reactions', reactions, str) - check_type('data', data, float, expected_iter_type=np.array) - check_value('reactions', reactions, chain.REACTIONS) + _validate_micro_xs_inputs(nuclides, reactions, data) + # Convert to cm^2 if units == 'barn': data /= 1e24 @@ -351,7 +360,12 @@ class FluxSpectraDepletionOperator(TransportOperator): A DataFrame object correctly formatted for use in ``FluxOperator`` """ - micro_xs = pd.DataFrame.read_csv(csv_file) + micro_xs = pd.read_csv(csv_file, index_col=0) + + _validate_micro_xs_inputs(list(micro_xs.index), + list(micro_xs.columns), + micro_xs.to_numpy()) + if units == 'barn': micro_xs /= 1e24 diff --git a/tests/micro_xs_simple.csv b/tests/micro_xs_simple.csv new file mode 100644 index 000000000..40142f543 --- /dev/null +++ b/tests/micro_xs_simple.csv @@ -0,0 +1,13 @@ +,fission,"(n,gamma)" +U234,0.1,0.0 +U235,0.1,0.0 +U238,0.9,0.0 +U236,0.4,0.0 +O16,0.0,0.0 +O17,0.0,0.0 +I135,0.0,0.1 +Xe135,0.0,0.9 +Xe136,0.0,0.0 +Cs135,0.0,0.0 +Gd157,0.0,0.1 +Gd156,0.0,0.1 diff --git a/tests/unit_tests/test_flux_deplete_operator.py b/tests/unit_tests/test_flux_deplete_operator.py new file mode 100644 index 000000000..a2b150493 --- /dev/null +++ b/tests/unit_tests/test_flux_deplete_operator.py @@ -0,0 +1,73 @@ +"""Basic unit tests for openmc.deplete.FluxDepletionOperator instantiation + +Modifies and resets environment variable OPENMC_CROSS_SECTIONS +to a custom file with new depletion_chain node +""" + +from pathlib import Path + +import pytest +from openmc.deplete.flux_operator import FluxDepletionOperator +import pandas as pd +import numpy as np + +FLUX_SPECTRA = 5e16 +CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" +ONE_GROUP_XS = Path(__file__).parents[1] / "micro_xs_simple.csv" + + +def test_create_micro_xs_from_data_array(): + nuclides = [ + 'U234', + 'U235', + 'U238', + 'U236', + 'O16', + 'O17', + 'I135', + 'Xe135', + 'Xe136', + 'Cs135', + 'Gd157', + 'Gd156'] + reactions = ['fission', '(n,gamma)'] + # These values are placeholders and are not at all + # physically meaningful. + data = np.array([[0.1, 0.], + [0.1, 0.], + [0.9, 0.], + [0.4, 0.], + [0., 0.], + [0., 0.], + [0., 0.1], + [0., 0.9], + [0., 0.], + [0., 0.], + [0., 0.1], + [0., 0.1]]) + + FluxDepletionOperator.create_micro_xs_from_data_array( + nuclides, reactions, data) + with pytest.raises(SyntaxError, match=r'Nuclides list of length \d* and ' + r'reactions array of length \d* do not ' + r'match dimensions of data array of shape \(\d*\,d*\)'): + FluxDepletionOperator.create_micro_xs_from_data_array( + nuclides, reactions, data[:, 0]) + + +def test_create_micro_xs_from_csv(): + FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) + + +def test_operator_init(): + """The test uses a temporary dummy chain. This file will be removed + at the end of the test, and only contains a depletion_chain node.""" + nuclides = {'U234': 8.922411359424315e+18, + 'U235': 9.98240191860822e+20, + 'U238': 2.2192386373095893e+22, + 'U236': 4.5724195495061115e+18, + 'O16': 4.639065406771322e+22, + 'O17': 1.7588724018066158e+19} + micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) + my_flux_operator = FluxDepletionOperator( + 1, nuclides, micro_xs, FLUX_SPECTRA, CHAIN_PATH) From 1d81b553de628889c6f0004ad4e5cb8f9975d57d Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 14:30:48 -0500 Subject: [PATCH 0521/2654] allow None-valued keff in stepresult.py --- openmc/deplete/stepresult.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index 6e2373c45..80a664c6f 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -495,7 +495,13 @@ class StepResult: for mat_i in range(n_mat): results[i, mat_i, :] = x[i][mat_i] - results.k = [(r.k.nominal_value, r.k.std_dev) for r in op_results] + ks = [] + for r in op_results: + if isinstance(r.k, type(None)): + ks += [(None, None)] + else: + ks += [(r.k.nominal_value, r.k.std_dev)] + results.k = ks results.rates = [r.rates for r in op_results] results.time = t results.source_rate = source_rate From 516c117533818ca25d33ea72e39f61efbefa64f5 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 14:31:59 -0500 Subject: [PATCH 0522/2654] Add type checking for keff; typo fixes in flux_operator.py --- openmc/deplete/flux_operator.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 37100ac5b..1da7cf9f9 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -90,6 +90,9 @@ class FluxDepletionOperator(TransportOperator): Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. + round_number : bool + Whether or not to round output to OpenMC to 8 digits. + Useful in testing, as OpenMC is incredibly sensitive to exact values. prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. @@ -120,6 +123,7 @@ class FluxDepletionOperator(TransportOperator): reduce_chain_level=None, fission_yield_opts=None): super().__init__(chain_file, fission_q, dilute_initial, prev_results) + self.round_number = False self.flux_spectra = flux_spectra self._init_nuclides = nuclides self._volume = volume @@ -134,6 +138,10 @@ class FluxDepletionOperator(TransportOperator): check_type('micro_xs', micro_xs, pd.DataFrame) self._micro_xs = micro_xs + if not isinstance(keff, type(None)): + check_type('keff', keff, tuple, float) + keff = ufloat(keff) + self._keff = keff self._all_nuclides = self._get_all_nuclides_in_simulation() @@ -210,12 +218,13 @@ class FluxDepletionOperator(TransportOperator): number.fill(0.0) # Get new number densities - for nuc, i_nuc_results in zip(nuclides, nuc_ind): + for nuc, i_nuc_results in zip(rxn_nuclides, nuc_ind): number[i_nuc_results] = self.number[0, nuc] + # Calculate macroscopic cross sections and store them in rates array - for nuc in nuclides: - density = number.get_atom_density('0', nuc) + for nuc in rxn_nuclides: + density = self.number.get_atom_density('0', nuc) for rxn in self.chain.reactions: rates.set( '0', @@ -236,7 +245,7 @@ class FluxDepletionOperator(TransportOperator): # vector. Since what we want is the depletion matrix, we need to # divide the reaction rates by the number of atoms to get the right # units. - mask = nonzero(number) + mask = np.nonzero(number) results = rates[0] for col in range(results.shape[1]): results[mask, col] /= number[mask] From 596359339894f01f5be56bc2f28715d129d3dbbd Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 15:12:38 -0500 Subject: [PATCH 0523/2654] created regression test for FluxDepleteOperator - new data file: tests/micro_xs_simple.csv - created regression test based on pincell example - moved old depletion regression test to new folder: tests/regression_tests/deplete/transport_deplete --- tests/micro_xs_simple.csv | 20 ++-- .../deplete/no_transport_deplete/test.py | 106 ++++++++++++++++++ .../deplete/test_reference.h5 | Bin 166224 -> 0 bytes .../example_geometry.py | 0 .../last_step_reference_materials.xml | 0 .../deplete/{ => transport_deplete}/test.py | 2 +- 6 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 tests/regression_tests/deplete/no_transport_deplete/test.py delete mode 100644 tests/regression_tests/deplete/test_reference.h5 rename tests/regression_tests/deplete/{ => transport_deplete}/example_geometry.py (100%) rename tests/regression_tests/deplete/{ => transport_deplete}/last_step_reference_materials.xml (100%) rename tests/regression_tests/deplete/{ => transport_deplete}/test.py (98%) diff --git a/tests/micro_xs_simple.csv b/tests/micro_xs_simple.csv index 40142f543..bc43600ba 100644 --- a/tests/micro_xs_simple.csv +++ b/tests/micro_xs_simple.csv @@ -1,13 +1,7 @@ -,fission,"(n,gamma)" -U234,0.1,0.0 -U235,0.1,0.0 -U238,0.9,0.0 -U236,0.4,0.0 -O16,0.0,0.0 -O17,0.0,0.0 -I135,0.0,0.1 -Xe135,0.0,0.9 -Xe136,0.0,0.0 -Cs135,0.0,0.0 -Gd157,0.0,0.1 -Gd156,0.0,0.1 +nuclide,"(n,gamma)",fission +U234,23.518634203050645,0.49531930067650976 +U235,10.621118186344665,49.10955932965905 +U238,0.8652742788116043,0.10579281644765708 +U236,9.095623870006154,0.32315392339237936 +O16,0.0029535689693132015,0.0 +O17,0.05980775766572907,0.0 diff --git a/tests/regression_tests/deplete/no_transport_deplete/test.py b/tests/regression_tests/deplete/no_transport_deplete/test.py new file mode 100644 index 000000000..3fb2bf7f2 --- /dev/null +++ b/tests/regression_tests/deplete/no_transport_deplete/test.py @@ -0,0 +1,106 @@ +""" Full system test suite. """ + +from math import floor +import shutil +from pathlib import Path + +from difflib import unified_diff +import numpy as np +import pytest +import openmc +from openmc.data import JOULE_PER_EV +import openmc.deplete +from openmc.deplete import FluxDepletionOperator + + +from tests.regression_tests import config + + +@pytest.fixture(scope="module") +def vol_nuc(): + fuel = openmc.Material(name="uo2") + fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) + fuel.add_element("O", 2) + fuel.set_density("g/cc", 10.4) + + fuel.volume = np.pi * 0.42 ** 2 + + nuclides = {} + for nuc, t in fuel.get_nuclide_atom_densities().items(): + nuclides[nuc] = t[1] * 1e24 + + # Load geometry from example + return (fuel.volume, nuclides) + + +@pytest.mark.parametrize("multiproc", [True, False]) +def test_full(run_in_tmpdir, vol_nuc, multiproc): + """Full system test suite. + + Runs an OpenMC depletion calculation and verifies + that the outputs match a reference file. Sensitive to changes in + OpenMC. + + """ + + # Create operator + micro_xs_file = Path(__file__).parents[3] / 'micro_xs_simple.csv' + micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) + chain_file = Path(__file__).parents[3] / 'chain_simple.xml' + flux = 1164719970082145.0 # flux from pincell example + op = FluxDepletionOperator(vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file, dilute_initial=0.0) + + # Power and timesteps + dt = [30] # single step + power = 174 # W/cm + + # Perform simulation using the predictor algorithm + openmc.deplete.pool.USE_MULTIPROCESSING = multiproc + openmc.deplete.PredictorIntegrator(op, dt, power, timestep_units='d').integrate() + + # Get path to test and reference results + path_test = op.output_dir / 'depletion_results.h5' + path_reference = Path(__file__).with_name('test_reference.h5') + + # If updating results, do so and return + if config['update']: + shutil.copyfile(str(path_test), str(path_reference)) + return + + # Load the reference/test results + res_test = openmc.deplete.Results(path_test) + res_ref = openmc.deplete.Results(path_reference) + + # Assert same mats + for mat in res_ref[0].mat_to_ind: + assert mat in res_test[0].mat_to_ind, \ + "Material {} not in new results.".format(mat) + for nuc in res_ref[0].nuc_to_ind: + assert nuc in res_test[0].nuc_to_ind, \ + "Nuclide {} not in new results.".format(nuc) + + for mat in res_test[0].mat_to_ind: + assert mat in res_ref[0].mat_to_ind, \ + "Material {} not in old results.".format(mat) + for nuc in res_test[0].nuc_to_ind: + assert nuc in res_ref[0].nuc_to_ind, \ + "Nuclide {} not in old results.".format(nuc) + + tol = 1.0e-6 + for mat in res_test[0].mat_to_ind: + for nuc in res_test[0].nuc_to_ind: + _, y_test = res_test.get_atoms(mat, nuc) + _, y_old = res_ref.get_atoms(mat, nuc) + + # Test each point + correct = True + for i, ref in enumerate(y_old): + if ref != y_test[i]: + if ref != 0.0: + correct = np.abs(y_test[i] - ref) / ref <= tol + else: + correct = False + + assert correct, "Discrepancy in mat {} and nuc {}\n{}\n{}".format( + mat, nuc, y_old, y_test) + diff --git a/tests/regression_tests/deplete/test_reference.h5 b/tests/regression_tests/deplete/test_reference.h5 deleted file mode 100644 index d478d628ef662ac0ccb996ac9aa26a241df084e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166224 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≫yzV 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 Date: Thu, 7 Jul 2022 15:26:26 -0500 Subject: [PATCH 0524/2654] update docstring for no-transport depletion test --- .../regression_tests/deplete/no_transport_deplete/test.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/regression_tests/deplete/no_transport_deplete/test.py b/tests/regression_tests/deplete/no_transport_deplete/test.py index 3fb2bf7f2..51402dd60 100644 --- a/tests/regression_tests/deplete/no_transport_deplete/test.py +++ b/tests/regression_tests/deplete/no_transport_deplete/test.py @@ -35,11 +35,10 @@ def vol_nuc(): @pytest.mark.parametrize("multiproc", [True, False]) def test_full(run_in_tmpdir, vol_nuc, multiproc): - """Full system test suite. + """Transport free system test suite. - Runs an OpenMC depletion calculation and verifies - that the outputs match a reference file. Sensitive to changes in - OpenMC. + Runs an OpenMC transport-free depletion calculation and verifies + that the outputs match a reference file. """ From bbec47e1e5fb2c1911b2efaaddce80f2eb2e19ff Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 15:29:05 -0500 Subject: [PATCH 0525/2654] move the depelteion regression tests to their own directories to avoid collection error --- .../no_transport_deplete => deplete_no_transport}/test.py | 4 ++-- .../example_geometry.py | 0 .../last_step_reference_materials.xml | 0 .../transport_deplete => deplete_with_transport}/test.py | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename tests/regression_tests/{deplete/no_transport_deplete => deplete_no_transport}/test.py (96%) rename tests/regression_tests/{deplete/transport_deplete => deplete_with_transport}/example_geometry.py (100%) rename tests/regression_tests/{deplete/transport_deplete => deplete_with_transport}/last_step_reference_materials.xml (100%) rename tests/regression_tests/{deplete/transport_deplete => deplete_with_transport}/test.py (98%) diff --git a/tests/regression_tests/deplete/no_transport_deplete/test.py b/tests/regression_tests/deplete_no_transport/test.py similarity index 96% rename from tests/regression_tests/deplete/no_transport_deplete/test.py rename to tests/regression_tests/deplete_no_transport/test.py index 51402dd60..98ce0facd 100644 --- a/tests/regression_tests/deplete/no_transport_deplete/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -43,9 +43,9 @@ def test_full(run_in_tmpdir, vol_nuc, multiproc): """ # Create operator - micro_xs_file = Path(__file__).parents[3] / 'micro_xs_simple.csv' + micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) - chain_file = Path(__file__).parents[3] / 'chain_simple.xml' + chain_file = Path(__file__).parents[2] / 'chain_simple.xml' flux = 1164719970082145.0 # flux from pincell example op = FluxDepletionOperator(vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file, dilute_initial=0.0) diff --git a/tests/regression_tests/deplete/transport_deplete/example_geometry.py b/tests/regression_tests/deplete_with_transport/example_geometry.py similarity index 100% rename from tests/regression_tests/deplete/transport_deplete/example_geometry.py rename to tests/regression_tests/deplete_with_transport/example_geometry.py diff --git a/tests/regression_tests/deplete/transport_deplete/last_step_reference_materials.xml b/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml similarity index 100% rename from tests/regression_tests/deplete/transport_deplete/last_step_reference_materials.xml rename to tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml diff --git a/tests/regression_tests/deplete/transport_deplete/test.py b/tests/regression_tests/deplete_with_transport/test.py similarity index 98% rename from tests/regression_tests/deplete/transport_deplete/test.py rename to tests/regression_tests/deplete_with_transport/test.py index caf292936..6c431fb33 100644 --- a/tests/regression_tests/deplete/transport_deplete/test.py +++ b/tests/regression_tests/deplete_with_transport/test.py @@ -52,7 +52,7 @@ def test_full(run_in_tmpdir, problem, multiproc): model = openmc.Model(geometry=geometry, settings=settings) # Create operator - chain_file = Path(__file__).parents[3] / 'chain_simple.xml' + chain_file = Path(__file__).parents[2] / 'chain_simple.xml' op = openmc.deplete.Operator(model, chain_file) op.round_number = True From 2053b6cf1ded5f53b9e5f38ef9e9daa0b3140dc6 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 16:00:47 -0500 Subject: [PATCH 0526/2654] update docstrings and comments in no transport regression test --- tests/regression_tests/deplete_no_transport/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 98ce0facd..3641edf58 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -1,4 +1,4 @@ -""" Full system test suite. """ +""" Transport-free depletion test suite """ from math import floor import shutil @@ -34,7 +34,7 @@ def vol_nuc(): @pytest.mark.parametrize("multiproc", [True, False]) -def test_full(run_in_tmpdir, vol_nuc, multiproc): +def test_no_transport(run_in_tmpdir, vol_nuc, multiproc): """Transport free system test suite. Runs an OpenMC transport-free depletion calculation and verifies From ff044e7b1346f65b83a5b0902bea78f96da25bd3 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 16:01:28 -0500 Subject: [PATCH 0527/2654] added __init__.py files to deplete regression test modules --- tests/regression_tests/deplete_no_transport/__init__.py | 0 tests/regression_tests/deplete_with_transport/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/regression_tests/deplete_no_transport/__init__.py create mode 100644 tests/regression_tests/deplete_with_transport/__init__.py diff --git a/tests/regression_tests/deplete_no_transport/__init__.py b/tests/regression_tests/deplete_no_transport/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/deplete_with_transport/__init__.py b/tests/regression_tests/deplete_with_transport/__init__.py new file mode 100644 index 000000000..e69de29bb From 3e5f47b0be136a3b29b9b029dfe0f993d29a748b Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 16:22:30 -0500 Subject: [PATCH 0528/2654] Added references to the new class in the docs --- docs/source/pythonapi/deplete.rst | 10 +++--- docs/source/usersguide/depletion.rst | 51 +++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 9f7d8c447..151e728d5 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -40,18 +40,18 @@ transport-depletion coupling algorithms `_. SICELIIntegrator SILEQIIntegrator -Each of these classes expects a "transport operator" to be passed. An operator -specific to OpenMC is available using the following class: - +Each of these classes expects a "transport operator" to be passed. .. autosummary:: :toctree: generated :nosignatures: :template: mycallable.rst Operator + FluxDepletionOperator -The :class:`Operator` must also have some knowledge of how nuclides transmute -and decay. This is handled by the :class:`Chain`. +The :class:`Operator` and :class:`FluxDepletionOperator` classes must also have +some knowledge of how nuclides transmute and decay. This is handled by the +:class:`Chain`. Minimal Example --------------- diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 57619611f..f4f0ac869 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -19,14 +19,13 @@ transmutation equations and the method used for advancing time. At present, the :class:`openmc.deplete.Operator` (which uses the OpenMC transport solver), but in principle additional operator classes based on other transport codes could be implemented and no changes to the depletion solver itself would be needed. The -operator class requires a :class:`openmc.Geometry` instance and a -:class:`openmc.Settings` instance:: +operator class requires a :class:`openmc.model.Model` instance containing +material, geometry, and settings information:: - geom = openmc.Geometry() - settings = openmc.Settings() + model = openmc.model.Model() ... - op = openmc.deplete.Operator(geom, settings) + op = openmc.deplete.Operator(model) Any material that contains a fissionable nuclide is depleted by default, but this can behavior can be changed with the :attr:`Material.depletable` attribute. @@ -81,7 +80,7 @@ When constructing the :class:`~openmc.deplete.Operator`, you should indicate that normalization of tally results will be done based on the source rate rather than a power or power density:: - op = openmc.deplete.Operator(geometry, settings, normalization_mode='source-rate') + op = openmc.deplete.Operator(model, normalization_mode='source-rate') Finally, when creating a depletion integrator, use the ``source_rates`` argument:: @@ -127,7 +126,7 @@ A more complete way to model the energy deposition is to use the modified heating reactions described in :ref:`methods_heating`. These values can be used to normalize reaction rates instead of using the fission reaction rates with:: - op = openmc.deplete.Operator(geometry, settings, "chain.xml", + op = openmc.deplete.Operator(model, "chain.xml", normalization_mode="energy-deposition") These modified heating libraries can be generated by running the latest version @@ -160,7 +159,7 @@ the next transport step. This can be countered by instructing the operator to treat repeated instances of the same material as a unique material definition with:: - op = openmc.deplete.Operator(geometry, settings, chain_file, + op = openmc.deplete.Operator(model, chain_file, diff_burnable_mats=True) For our example problem, this would deplete fuel on the outer region of the @@ -177,3 +176,39 @@ across all material instances. This will increase the total memory usage and run time due to an increased number of tallies and material definitions. +Transport-independent depletion +------------------------------- + +.. note:: + + This is a brand-new feature and is under heavy development. API changes are + possible and likely in the near future. + +OpenMC also supports transport-independent depletion calculations using the +:class:`FluxDepletionOperator` class. Rather than taking a +:class:`openmc.model.Model` object, this class accepts a volume, +a dictionary of nuclide concentrations, a flux spectra, and one-group +microscopic cross sections as a pandas dataframe. The class includes +helper functions to constructe the dataframe from a csv file or from +data arrays:: + + ... + micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_path) + nuclides = {'U234':8.92e18, + 'U235':9.98e20, + 'U238':2.22e22, + 'U236':4.57e18, + 'O16':4.64e22, + 'O17':1.76e19} + volume = 0.5 + flux = 1.16e15 + + op = FluxDepletionOperator(volume, nuclides, micro_xs, flux. chain_file) + + +A user can then define an integrator class as they would for a coupled +transport-depletion calculation and follow the steps from there. +present in the depletion chain. + +.. note:: Ideally, one-group cross section data should be available for every reaction + in the depletion chain. From c91a6d65d880666565414c3b43776d9cf65be3d3 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 16:35:51 -0500 Subject: [PATCH 0529/2654] make import of example_geometry relative to fix pytest error --- tests/regression_tests/deplete_with_transport/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/deplete_with_transport/test.py b/tests/regression_tests/deplete_with_transport/test.py index 6c431fb33..0c2a4cd97 100644 --- a/tests/regression_tests/deplete_with_transport/test.py +++ b/tests/regression_tests/deplete_with_transport/test.py @@ -12,7 +12,7 @@ from openmc.data import JOULE_PER_EV import openmc.deplete from tests.regression_tests import config -from example_geometry import generate_problem +from .example_geometry import generate_problem @pytest.fixture(scope="module") From c67f889d99aa2dadbcf8016ac9c4733145a910ae Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 16:44:09 -0500 Subject: [PATCH 0530/2654] typo fix in depete api page --- docs/source/pythonapi/deplete.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 151e728d5..32b449a13 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -41,6 +41,7 @@ transport-depletion coupling algorithms `_. SILEQIIntegrator Each of these classes expects a "transport operator" to be passed. + .. autosummary:: :toctree: generated :nosignatures: From 1c9a5be73835bb00805b8d194dc69a5474e03ff0 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 7 Jul 2022 17:44:59 -0500 Subject: [PATCH 0531/2654] add test_reference.h5 files --- .../deplete_no_transport/test_reference.h5 | Bin 0 -> 35688 bytes .../deplete_with_transport/test_reference.h5 | Bin 0 -> 166224 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/regression_tests/deplete_no_transport/test_reference.h5 create mode 100644 tests/regression_tests/deplete_with_transport/test_reference.h5 diff --git a/tests/regression_tests/deplete_no_transport/test_reference.h5 b/tests/regression_tests/deplete_no_transport/test_reference.h5 new file mode 100644 index 0000000000000000000000000000000000000000..e4fbf5029d56bd9169e688fb477bc7e6c0688d9e GIT binary patch literal 35688 zcmeHPU1(fI6rSBp>b6Erv}&w>D;ABl+O0-if0}IFRJSiS7^RCy-OXlew&sug)QEzL zKSTu;1nHZ3j4zr8g{mNdqU6C!qX_X$txBGxAktEiI&;tYa~o#zGsh8L52DuIa`fwpiqnxQoAXT=D3LS8-e7W-L0mFzc62_jKfp&z-lfv4E*jF)nwJ+N{eR?(G`t)~lDgNHgE7xN5vuHJ-El zZ1$!0y;EQP+U&1Ptcp46TEE!-ccFbm!{t}$vFrTjh;v%dk&4&$S+j(~pO6@~gT@6JLdfg%WC{H8b$^WX`y zIh=E0KE(K*lT}ub=H05z8J?- z*HC(dgoZ1YCY6$>Rv6!1I;zJK&4$H>RV`6Rg;^r51J@rudf;%m;6ap^3j9KftO7X>BM=qByeqU|A z6n`HYjZlfBTu|0yK7taOkARCW(>E6CR*El2*uNj;_Lj>Rygu^l+3f9u`g55qz2?je z=H~2#T>Buu_lx7**v(Wzc;_Q0AvXdp-nH^LLdi<;uJ$HsAiWOa2wTJEJ}_2gZ5HyT|njhc}$ zBU3q2Fw&HReQA?ffeYvPnBJ<7_mgPX-d{%9hM5Qjpl7d#z0PQrG|$)2v*+(PRimbP z9SS|$-y~Ttd^-i87v*@XbzfP1)db#;*!C>fPrB9>^jyk)J~-`-D*v3rssSMltqTNf z{}*Aa`uN-ojBM!H{%oeZJ98T+9Lx`R=jXvM@EH0FNqJtn5JDGrzCA9n{|d9e0y-Ff zD>X0EJQtjOYZkN4%}g>cX1rP1_nY-*($*L3iE})CKc!!2znJH2yvjYV>LXnoN!PiV zX~tjn1I2NZ)ItPYe&-d7$Kd%&`5o}Z_8Uv(3+!5$FZ7%j4lAI)k26=GifX`m67@lD zWVrCXC(!KJRq zbde%gw|DLwL%v}E2T+iW5*AN#S%$u(b zlp5$A>d)q$Fd-8 zlWEHQS@$JPxfTAMj|U+b2oeJ5CnRt{eChqK_j(ixhK9STZ&u%jE8OGK)h`wgLdXA( z4)JB+G5)-dhpCP^y58`h`)7aujB!zZ|ARBH`u(5dpGHdGuvN~*dHFcEn|iRc0mLSK zzT4U#*x#LWay2pi#Z;*)&6y2NrL@+6p4rz2w9CV|flMyZ^!m4{0Lp=f3sp10<)DXh zw!}Im3`LQGfFK|U2m*qDARq_`0)l`bAP5KoYl47l9~mvvnl$eVQ6Brj#a0*Q|ECCj zl((h*oLBajKun|{AP5Kof`A|(2nYg#fFK|U2m*qDAW(S(T+b6~7uodt{QLm=*!R1N z#};^AfO9tTe87dEqzeLqfFK|U2m*qDARq_`0&9mrx%-FFMeZAtj{Sn{6V~pYOUr_Q zARq_`0)l`bAPAI$fNR~j&~x8$UN=I|^}IRdST{l+<;$^M$_N62fFK|U2m*qDARq{= z9s)~UHy&MJy_j~a6J>q4diPXX5(ESRK|l}?1lAgXpATg}{^ZuF#23e!o9_E>SIehu zt>29P^m@zpXL~37 zIkGLg<-NalQ9sVSTqr5_%D0K#UT7j0H*$OE^XA{5oBr{5s3Y-ZTjP$`4)i1rp8PZW z&M(IjPwczt&f_0`mq^`^dau1bk$7>UKED5tCle2TbnSINUptjJ+4l5b*Z+NQ%Tph` ZdF8u5xa~}^omsZ?bO}3QAEcUN=l?V|d4T`` literal 0 HcmV?d00001 diff --git a/tests/regression_tests/deplete_with_transport/test_reference.h5 b/tests/regression_tests/deplete_with_transport/test_reference.h5 new file mode 100644 index 0000000000000000000000000000000000000000..d478d628ef662ac0ccb996ac9aa26a241df084e1 GIT binary patch literal 166224 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≫yzV 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 Date: Thu, 7 Jul 2022 20:35:09 -0500 Subject: [PATCH 0532/2654] test suite typo fixes --- tests/regression_tests/deplete_no_transport/test.py | 4 ++-- tests/unit_tests/test_deplete_resultslist.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 3641edf58..1133a039c 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -26,8 +26,8 @@ def vol_nuc(): fuel.volume = np.pi * 0.42 ** 2 nuclides = {} - for nuc, t in fuel.get_nuclide_atom_densities().items(): - nuclides[nuc] = t[1] * 1e24 + for nuc, dens in fuel.get_nuclide_atom_densities().items(): + nuclides[nuc] = dens * 1e24 # Load geometry from example return (fuel.volume, nuclides) diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 6ce15601f..9d81c4a15 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -11,7 +11,7 @@ import openmc.deplete @pytest.fixture def res(): """Load the reference results""" - filename = (Path(__file__).parents[1] / 'regression_tests' / 'deplete' + filename = (Path(__file__).parents[1] / 'regression_tests' / 'deplete_with_transport' / 'test_reference.h5') return openmc.deplete.Results(filename) From a95d02dd91c9ac51d16843f04c503df4ed9d4261 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 7 Jul 2022 22:29:56 -0500 Subject: [PATCH 0533/2654] Update version pins of sphinx and sphinx_rtd_theme --- docs/requirements-rtd.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/requirements-rtd.txt b/docs/requirements-rtd.txt index c3d1c0372..9591d482f 100644 --- a/docs/requirements-rtd.txt +++ b/docs/requirements-rtd.txt @@ -1,4 +1,5 @@ -sphinx==4.3.0 +sphinx==5.0.2 +sphinx_rtd_theme==1.0.0 sphinx-numfig jupyter sphinxcontrib-katex From ff15c98b67dc231de6e4e22f70de1892f6ec7746 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 8 Jul 2022 08:05:51 -0500 Subject: [PATCH 0534/2654] Add test checking that collision/tracklength estimators agree for sph/cyl mesh --- tests/unit_tests/test_filter_mesh.py | 109 +++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 tests/unit_tests/test_filter_mesh.py diff --git a/tests/unit_tests/test_filter_mesh.py b/tests/unit_tests/test_filter_mesh.py new file mode 100644 index 000000000..265642360 --- /dev/null +++ b/tests/unit_tests/test_filter_mesh.py @@ -0,0 +1,109 @@ +import numpy as np +import openmc +from uncertainties import unumpy + + +def test_spherical_mesh_estimators(run_in_tmpdir): + """Test that collision/tracklength estimators agree for SphericalMesh""" + + mat = openmc.Material() + mat.add_nuclide('U235', 1.0) + mat.set_density('g/cm3', 10.0) + + sphere = openmc.Sphere(r=10.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sphere) + model = openmc.Model() + model.geometry = openmc.Geometry([cell]) + model.settings.particles = 1_000 + model.settings.inactive = 10 + model.settings.batches = 20 + + sph_mesh = openmc.SphericalMesh() + sph_mesh.r_grid = np.linspace(0.0, 5.0**3, 20)**(1/3) + tally1 = openmc.Tally() + tally1.filters = [openmc.MeshFilter(sph_mesh)] + tally1.scores = ['flux'] + tally1.estimator = 'collision' + + sph_mesh = openmc.SphericalMesh() + sph_mesh.r_grid = np.linspace(0.0, 5.0**3, 20)**(1/3) + tally2 = openmc.Tally() + tally2.filters = [openmc.MeshFilter(sph_mesh)] + tally2.scores = ['flux'] + tally2.estimator = 'tracklength' + + model.tallies = openmc.Tallies([tally1, tally2]) + + # Run OpenMC + sp_filename = model.run() + + # Get radial flux distribution + with openmc.StatePoint(sp_filename) as sp: + flux_collision = sp.tallies[tally1.id].mean.ravel() + flux_collision_unc = sp.tallies[tally1.id].std_dev.ravel() + flux_tracklength = sp.tallies[tally2.id].mean.ravel() + flux_tracklength_unc = sp.tallies[tally2.id].std_dev.ravel() + + # Construct arrays with uncertainties + collision = unumpy.uarray(flux_collision, flux_collision_unc) + tracklength = unumpy.uarray(flux_tracklength, flux_tracklength_unc) + delta = collision - tracklength + + # Check that difference is within uncertainty + diff = unumpy.nominal_values(delta) + std_dev = unumpy.std_devs(delta) + assert np.all(diff < 3*std_dev) + + +def test_cylindrical_mesh_estimators(run_in_tmpdir): + """Test that collision/tracklength estimators agree for CylindricalMesh""" + + mat = openmc.Material() + mat.add_nuclide('U235', 1.0) + mat.set_density('g/cm3', 10.0) + + cyl = openmc.model.RightCircularCylinder((0., 0., -5.), 10., 10.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-cyl) + model = openmc.Model() + model.geometry = openmc.Geometry([cell]) + model.settings.particles = 1_000 + model.settings.inactive = 10 + model.settings.batches = 20 + + cyl_mesh = openmc.CylindricalMesh() + cyl_mesh.r_grid = np.linspace(0.0, 5.0**3, 20)**(1/3) + cyl_mesh.z_grid = [-5., 5.] + tally1 = openmc.Tally() + tally1.filters = [openmc.MeshFilter(cyl_mesh)] + tally1.scores = ['flux'] + tally1.estimator = 'collision' + + cyl_mesh = openmc.CylindricalMesh() + cyl_mesh.r_grid = np.linspace(0.0, 5.0**3, 20)**(1/3) + cyl_mesh.z_grid = [-5., 5.] + tally2 = openmc.Tally() + tally2.filters = [openmc.MeshFilter(cyl_mesh)] + tally2.scores = ['flux'] + tally2.estimator = 'tracklength' + + model.tallies = openmc.Tallies([tally1, tally2]) + + # Run OpenMC + sp_filename = model.run() + + # Get radial flux distribution + with openmc.StatePoint(sp_filename) as sp: + flux_collision = sp.tallies[tally1.id].mean.ravel() + flux_collision_unc = sp.tallies[tally1.id].std_dev.ravel() + flux_tracklength = sp.tallies[tally2.id].mean.ravel() + flux_tracklength_unc = sp.tallies[tally2.id].std_dev.ravel() + + # Construct arrays with uncertainties + collision = unumpy.uarray(flux_collision, flux_collision_unc) + tracklength = unumpy.uarray(flux_tracklength, flux_tracklength_unc) + delta = collision - tracklength + + # Check that difference is within uncertainty + diff = unumpy.nominal_values(delta) + std_dev = unumpy.std_devs(delta) + assert np.all(diff < 3*std_dev) From 620aaec5ee46400f5bde6bc63906deedf031f56d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 8 Jul 2022 08:09:16 -0500 Subject: [PATCH 0535/2654] Fix indexing bug in SphericalMesh and CylindricalMesh --- src/mesh.cpp | 14 ++++++-------- .../regression_tests/filter_mesh/results_true.dat | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index de29233fb..e8f79aa37 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -379,7 +379,7 @@ void StructuredMesh::raytrace_mesh( // TODO: when c++-17 is available, use "if constexpr ()" to compile-time // enable/disable tally calls for now, T template type needs to provide both // surface and track methods, which might be empty. modern optimizing - // compilers will (hopefully) eleminate the complete code (including + // compilers will (hopefully) eliminate the complete code (including // calculation of parameters) but for the future: be explicit // Compute the length of the entire track. @@ -957,7 +957,7 @@ double CylindricalMesh::find_r_crossing( const Position& r, const Direction& u, double l, int shell) const { - if ((shell < 0) || (shell >= shape_[0])) + if ((shell < 0) || (shell > shape_[0])) return INFTY; // solve r.x^2 + r.y^2 == r0^2 @@ -1190,7 +1190,7 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( double SphericalMesh::find_r_crossing( const Position& r, const Direction& u, double l, int shell) const { - if ((shell < 0) || (shell >= shape_[0])) + if ((shell < 0) || (shell > shape_[0])) return INFTY; // solve |r+s*u| = r0 @@ -1312,20 +1312,17 @@ StructuredMesh::MeshDistance SphericalMesh::distance_to_grid_boundary( { if (i == 0) { - return std::min( MeshDistance(ijk[i] + 1, true, find_r_crossing(r0, u, l, ijk[i])), MeshDistance(ijk[i] - 1, false, find_r_crossing(r0, u, l, ijk[i] - 1))); } else if (i == 1) { - return std::min(MeshDistance(sanitize_theta(ijk[i] + 1), true, find_theta_crossing(r0, u, l, ijk[i])), MeshDistance(sanitize_theta(ijk[i] - 1), false, find_theta_crossing(r0, u, l, ijk[i] - 1))); } else { - return std::min(MeshDistance(sanitize_phi(ijk[i] + 1), true, find_phi_crossing(r0, u, l, ijk[i])), MeshDistance(sanitize_phi(ijk[i] - 1), false, @@ -2567,8 +2564,9 @@ void read_meshes(pugi::xml_node root) // Check to make sure multiple meshes in the same file don't share IDs int id = std::stoi(get_node_value(node, "id")); if (contains(mesh_ids, id)) { - fatal_error( - fmt::format("Two or more meshes use the same unique ID '{}' in the same input file", id)); + fatal_error(fmt::format( + "Two or more meshes use the same unique ID '{}' in the same input file", + id)); } mesh_ids.insert(id); diff --git a/tests/regression_tests/filter_mesh/results_true.dat b/tests/regression_tests/filter_mesh/results_true.dat index 97735130e..ef52af2c7 100644 --- a/tests/regression_tests/filter_mesh/results_true.dat +++ b/tests/regression_tests/filter_mesh/results_true.dat @@ -1 +1 @@ -6e02d01fc115c54e4c60477a9f963149bc83c82e6a7bdb2d29125b131546150c59de5ac3aae5b9469b89b343ecf2574f6c949b918ccb43231e8666ee2b7c1b7c \ No newline at end of file +70243ebdb882e4367bf821667a9f4d41dea03eaf8b27d734e014a13e14922b5158cd47b0a7edf3733d4e23ca6a5ab06457220c9138b7e9720acf547f2eaa06e2 \ No newline at end of file From 6d352aa55c8fab8bf427bceeb165c6b870d94e53 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 22 Jun 2022 22:50:07 +0200 Subject: [PATCH 0536/2654] add placeholder skeleton for MCPL-input --- include/openmc/source.h | 19 +++++++++++++++++++ src/source.cpp | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/openmc/source.h b/include/openmc/source.h index 18fddc689..cadbfe93b 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -100,6 +100,25 @@ private: vector sites_; //!< Source sites from a file }; +//============================================================================== +// MCPL-file input source +//============================================================================== +class MCPLFileSource : public Source { +public: + // Constructors, destructors + MCPLFileSource(std::string path); + ~MCPLFileSource(); + + // Defer implementation to custom source library + SourceSite sample(uint64_t* seed) const override + +private: + vector sites_; //! Date: Thu, 23 Jun 2022 11:34:53 +0200 Subject: [PATCH 0537/2654] include mcpl header --- src/source.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/source.cpp b/src/source.cpp index cd8b5e574..5e26fa0a8 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -31,6 +31,10 @@ #include "openmc/state_point.h" #include "openmc/xml_interface.h" +#ifdef HAS_MCPL +#include +#endif + namespace openmc { //============================================================================== From c43989af9c222b20413ee3b892feaf20919b8707 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 23 Jun 2022 11:35:46 +0200 Subject: [PATCH 0538/2654] declarations of MCPL-internals --- include/openmc/source.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index cadbfe93b..69dd47eae 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -109,11 +109,20 @@ public: MCPLFileSource(std::string path); ~MCPLFileSource(); - // Defer implementation to custom source library - SourceSite sample(uint64_t* seed) const override + // Properties + ParticleType particle_type() const { return particle_; } + + //! Sample from the external source distribution + //! \param[inout] seed Pseudorandom seed pointer + //! \return Site read from MCPL-file + SourceSite sample(uint64_t* seed) const override; private: + ParticleType particle_ {ParticleType::neutron}; //!< Type of particle emitted vector sites_; //! Date: Thu, 23 Jun 2022 11:37:05 +0200 Subject: [PATCH 0539/2654] internals of sample and constructor --- src/source.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 5e26fa0a8..231f355fc 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -337,7 +337,7 @@ CustomSourceWrapper::~CustomSourceWrapper() } //=========================================================================== -// Read an MCPL-file +// Read particles from an MCPL-file //=========================================================================== MCPLFileSource::MCPLFileSource(std::string path) { @@ -348,12 +348,55 @@ MCPLFileSource::MCPLFileSource(std::string path) // Read the source from a binary file instead of sampling from some // assumed source distribution - write_message(6, "Reading source file from {}...", path); + write_message(6, "Reading mcpl source file from {}",path); // Open the mcpl file - id_t file_id = mcpl_open(path.c_str) - + mcpl_file = mcpl_open(path.c_str); + //do checks on the mcpl_file to see if particles are many enough. + // should model this on the example source shown in the docs. + uint64_t nparticles=mcpl_hdr_nparticles(mcpl_file); + +} + +MCPLFileSource::~MCPLFilsSource(){ + mcpl_close_file(mcpl_file); +} + +SourceSite MCPLFileSource::sample(uint64_t *seed){ + SourceSite omc_particle; + mcpl_particle *mcpl_particle; + //extract particle from mcpl-file + mcpl_particle=mcpl_reazd(mcplfile); + // check if it is a neutron or a photon. otherwise skip + while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) + { + mcpl_particle(mcpl_read(mcplfile); + //check for file exhaustion + } + + if(mcpl_particle->pdgcode=2112) { + omc_particle_=ParticleType::neutron; + } else { + omc_particle_=Particletype::photon; + } + + //particle is good, convert to openmc-formalism + omc_particle.r.x=mcpl_particle.x; + omc_particle.r.y=mcpl_particle.y; + omc_particle.r.z=mcpl_particle.z; + + omc_particle.u.x=mcpl_particle->direction[0]; + omc_particle.u.y=mcpl_particle->direction[1]; + omc_particle.u.z=mcpl_particle->direction[2]; + + //mcpl stores particles in MeV + omc_particle.E=mcpl_particle->ekin*1e6; + + omc_particle.t=mcpl_particle->time*1e-3; + omc_particle.wgt=mcpl_particle->weight; + omc_particle.delayed_group=0; + return omc_particle; } From 103c6ffa0330ab1313489a27b2d9504cfb30f7ba Mon Sep 17 00:00:00 2001 From: erkn Date: Mon, 27 Jun 2022 23:25:35 +0200 Subject: [PATCH 0540/2654] (wip): skeleton for input only test --- .../regression_tests/source_mcpl_file/test.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/test.py diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py new file mode 100644 index 000000000..5a6a87d87 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -0,0 +1,52 @@ +import pathlib as pl +import os +import shutil +import subprocess +import textwrap + +import openmc +import pytest + +from tests.testing_harness import TestHarness + +def model(): + subprocess.run(['gcc','-o gen_dummt_mcpl.out','-lm','-lmcpl','gen_dummy_mcpl.c'] ) + subprocess.run(['./gen_dummy_mcpl.out']) + +class SourceMCPLFileTestHarness(TestHarness): + def execute_test(self): + """Run OpenMC with the appropriate arguments and check the outputs.""" + try: + self._create_input() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._compare_results() + finally: + self._cleanup() + + def update_results(self): + """Update the results_true using the current version of OpenMC.""" + try: + self._create_input() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._overwrite_results() + finally: + self._cleanup() + + def _test_output_created(self): + """Check that the output files were created""" + stat epoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) + assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ + 'exist.' + assert statepoint[0].endswith('h5'), \ + 'statepoint file does not end with h5.' + +def test_mcpl_source_file(): + harness = SourceMCPLFileTestHarness('statepoint.10.h5') + harness.main() + From 73fb335350bb3b6ed0199e9c3cc4ee19d73b163e Mon Sep 17 00:00:00 2001 From: erkn Date: Mon, 27 Jun 2022 23:26:01 +0200 Subject: [PATCH 0541/2654] c-prog to generate a dummy mcpl --- .../source_mcpl_file/gen_dummy_mcpl.c | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c new file mode 100644 index 000000000..7b5a933f1 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include + +const int batches=10; +const int particles=10000; + +double rand01(){ + double r=rand()/((double) RAND_MAX); + return r; +} + + +int main(int argc, char **argv){ + char outfilename[128]; + snprintf(outfilename,127,"source.%d.mcpl",batches); + + /*generate an mcpl_header_of sorts*/ + mcpl_outfile_t outfile=mcpl_create_outfile(outfilename); + mcpl_particle_t *particle, Particle; + + char line[256]; + snprintf(line,255,"gen_dummy_mcpl.c"); + mcpl_hdr_set_srcname(outfile,line); + mcpl_enable_universal_pdgcode(outfile,2112);/*all particles are neutrons*/ + snprintf(line,255,"Dummy MCPL-file for testing OpenMC mcpl input"); + mcpl_hdr_add_comment(outfile,line); + + /*also add the instrument file and the command line as blobs*/ + FILE *fp; + if( (fp=fopen("gen_dummy_mcpl.c","rb"))!=NULL){ + unsigned char *buffer; + int size,status; + /*find the file size by seeking to end, "tell" the position, and then go back again*/ + fseek(fp, 0L, SEEK_END); + size = ftell(fp); // get current file pointer + fseek(fp, 0L, SEEK_SET); // seek back to beginning of file + if ( size && (buffer=malloc(size))!=NULL){ + if (size!=(fread(buffer,1,size,fp))){ + fprintf(stderr,"Warning: c source generator file not read cleanly\n"); + } + mcpl_hdr_add_data(outfile, "mcpl_point_source_file_generator", size, buffer); + free(buffer); + } + fclose(fp); + } else { + fprintf(stderr,"Warning: could not open c source generator file, hence not embedded.\n"); + } + + + /*the main particle loop*/ + particle=&Particle; + int i; + for (i=0;iposition[0]=0; + particle->position[1]=0; + particle->position[2]=0; + + /*generate a random direction on unit sphere*/ + double nrm=2.0; + double vx,vy,vz; + int iter=0; + do { + if(iter>100){ + printf("warning: exceeed max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); + } + vx=rand01()*2.0-1.0; + vy=rand01()*2.0-1.0; + vz=rand01()*2.0-1.0; + nrm=(vx*vx + vy*vy + vz*vz); + iter++; + } while (nrm>1.0); + vx/=sqrt(nrm); + vy/=sqrt(nrm); + vz/=sqrt(nrm); + particle->direction[0]=vx; + particle->direction[1]=vy; + particle->direction[2]=vz; + + /*generate the kinetic energy (in MeV) of the particle*/ + particle->ekin=1e-3; + + /*set time=0*/ + particle->time=0; + /*set weight*/ + particle->weight=1; + + particle->userflags=0; + mcpl_add_particle(outfile,particle); + } + mcpl_closeandgzip_outfile(outfile); +} From c6c876d835fe2177426ee64f4ae8dc15d5e616f2 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 5 Jul 2022 01:30:07 +0200 Subject: [PATCH 0542/2654] don't zip the output-file --- .../source_mcpl_file/gen_dummy_mcpl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c index 7b5a933f1..f35a07fc4 100644 --- a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -54,20 +54,20 @@ int main(int argc, char **argv){ int i; for (i=0;iposition[0]=0; particle->position[1]=0; particle->position[2]=0; - + /*generate a random direction on unit sphere*/ double nrm=2.0; double vx,vy,vz; int iter=0; do { if(iter>100){ - printf("warning: exceeed max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); + printf("Warning: Exceeded max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); } vx=rand01()*2.0-1.0; vy=rand01()*2.0-1.0; @@ -82,9 +82,9 @@ int main(int argc, char **argv){ particle->direction[1]=vy; particle->direction[2]=vz; - /*generate the kinetic energy (in MeV) of the particle*/ + /*generate the kinetic energy (in MeV) of the particle*/ particle->ekin=1e-3; - + /*set time=0*/ particle->time=0; /*set weight*/ @@ -93,5 +93,5 @@ int main(int argc, char **argv){ particle->userflags=0; mcpl_add_particle(outfile,particle); } - mcpl_closeandgzip_outfile(outfile); + mcpl_close_outfile(outfile); } From 8719a539f9f8c9134ded079b2eec64c6cdf3aa82 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 5 Jul 2022 01:53:14 +0200 Subject: [PATCH 0543/2654] now compiles fine if mcpl is indeed installed --- .../regression_tests/source_mcpl_file/test.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 5a6a87d87..0adf67f1a 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -3,16 +3,13 @@ import os import shutil import subprocess import textwrap - +import glob import openmc import pytest from tests.testing_harness import TestHarness -def model(): - subprocess.run(['gcc','-o gen_dummt_mcpl.out','-lm','-lmcpl','gen_dummy_mcpl.c'] ) - subprocess.run(['./gen_dummy_mcpl.out']) - + class SourceMCPLFileTestHarness(TestHarness): def execute_test(self): """Run OpenMC with the appropriate arguments and check the outputs.""" @@ -26,6 +23,10 @@ class SourceMCPLFileTestHarness(TestHarness): finally: self._cleanup() + def _create_input(self): + subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) + subprocess.run(['./gen_dummy_mcpl.out']) + def update_results(self): """Update the results_true using the current version of OpenMC.""" try: @@ -40,13 +41,19 @@ class SourceMCPLFileTestHarness(TestHarness): def _test_output_created(self): """Check that the output files were created""" - stat epoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' assert statepoint[0].endswith('h5'), \ 'statepoint file does not end with h5.' + def _cleanup(self): + super()._cleanup() + source_mcpl=glob.glob(os.path.join(os.getcwd(),'source*.mcpl')) + for f in source_mcpl: + if (os.path.exists(f)): + os.remove(f) + def test_mcpl_source_file(): harness = SourceMCPLFileTestHarness('statepoint.10.h5') harness.main() - From 7e890037051dad5760ea5f010165017b864f389f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 8 Jul 2022 23:44:32 +0100 Subject: [PATCH 0544/2654] [skip ci] Apply suggestions from code review by @paulromano Co-authored-by: Paul Romano --- openmc/material.py | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 352959fe9..3592a35e6 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -3,7 +3,6 @@ from collections.abc import Iterable from copy import deepcopy from numbers import Real from pathlib import Path - import os import math import re @@ -345,7 +344,7 @@ class Material(IDManagerMixin): raise ValueError('No volume information found for material ID={}.' .format(self.id)) - def set_density(self, units: str, density:Optional[float]=None): + def set_density(self, units: str, density: Optional[float] = None): """Set the density of the material Parameters @@ -377,7 +376,7 @@ class Material(IDManagerMixin): density, Real) self._density = density - def add_nuclide(self, nuclide: str, percent: float, percent_type: str='ao'): + def add_nuclide(self, nuclide: str, percent: float, percent_type: str = 'ao'): """Add a nuclide to the material Parameters @@ -505,10 +504,10 @@ class Material(IDManagerMixin): if macroscopic == self._macroscopic: self._macroscopic = None - def add_element(self, element: str, percent: float, percent_type: str='ao', - enrichment: Optional[float]=None, - enrichment_target: Optional[str]=None, - enrichment_type: Optional[str]=None): + def add_element(self, element: str, percent: float, percent_type: str = 'ao', + enrichment: Optional[float] = None, + enrichment_target: Optional[str] = None, + enrichment_type: Optional[str] = None): """Add a natural element to the material Parameters @@ -613,10 +612,10 @@ class Material(IDManagerMixin): enrichment_type): self.add_nuclide(*nuclide) - def add_elements_from_formula(self, formula: str, percent_type: str='ao', - enrichment: Optional[float]=None, - enrichment_target: Optional[float]=None, - enrichment_type: Optional[str]=None): + def add_elements_from_formula(self, formula: str, percent_type: str = 'ao', + enrichment: Optional[float] = None, + enrichment_target: Optional[str] = None, + enrichment_type: Optional[str] = None): """Add a elements from a chemical formula to the material. .. versionadded:: 0.12 @@ -713,7 +712,7 @@ class Material(IDManagerMixin): else: self.add_element(element, percent, percent_type) - def add_s_alpha_beta(self, name: str, fraction: float=1.0): + def add_s_alpha_beta(self, name: str, fraction: float = 1.0): r"""Add an :math:`S(\alpha,\beta)` table to the material Parameters @@ -862,7 +861,7 @@ class Material(IDManagerMixin): return nuclides - def get_mass_density(self, nuclide: Optional[str]=None): + def get_mass_density(self, nuclide: Optional[str] = None): """Return mass density of one or all nuclides Parameters @@ -885,7 +884,7 @@ class Material(IDManagerMixin): mass_density += density_i return mass_density - def get_mass(self, nuclide: Optional[str]=None): + def get_mass(self, nuclide: Optional[str] = None): """Return mass of one or all nuclides. Note that this method requires that the :attr:`Material.volume` has @@ -907,7 +906,7 @@ class Material(IDManagerMixin): raise ValueError("Volume must be set in order to determine mass.") return self.volume*self.get_mass_density(nuclide) - def clone(self, memo: Optional[dict]=None): + def clone(self, memo: Optional[dict] = None): """Create a copy of this material with a new unique ID. Parameters @@ -1031,7 +1030,7 @@ class Material(IDManagerMixin): @classmethod def mix_materials(cls, materials, fracs: typing.Iterable[float], - percent_type: str='ao', name: Optional[str]=None): + percent_type: str = 'ao', name: Optional[str] = None): """Mix materials together based on atom, weight, or volume fractions .. versionadded:: 0.12 @@ -1260,7 +1259,7 @@ class Materials(cv.CheckedList): for material in self: material.make_isotropic_in_lab() - def export_to_xml(self, path: Union[str, os.PathLike]='materials.xml'): + def export_to_xml(self, path: Union[str, os.PathLike] = 'materials.xml'): """Export material collection to an XML file. Parameters @@ -1307,7 +1306,7 @@ class Materials(cv.CheckedList): fh.write('\n') @classmethod - def from_xml(cls, path: Union[str, os.PathLike]='materials.xml'): + def from_xml(cls, path: Union[str, os.PathLike] = 'materials.xml'): """Generate materials collection from XML file Parameters From 69cb024882bd1d711c88370504833931a365424d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 8 Jul 2022 23:52:27 +0100 Subject: [PATCH 0545/2654] Adding type hint h5py.Group --- openmc/material.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index 3592a35e6..dcb33ff29 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -11,6 +11,7 @@ import warnings from typing import Optional, Union from xml.etree import ElementTree as ET +import h5py import numpy as np import openmc @@ -270,7 +271,7 @@ class Material(IDManagerMixin): return density*self.volume @classmethod - def from_hdf5(cls, group: str): + def from_hdf5(cls, group: h5py.Group): """Create material from HDF5 group Parameters From 0d1c346b5a12d2a452450b435a80cf4a2fbbe608 Mon Sep 17 00:00:00 2001 From: erkn Date: Sat, 9 Jul 2022 16:31:00 +0200 Subject: [PATCH 0546/2654] fix misprints --- src/source.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 231f355fc..37e580b18 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -345,7 +345,7 @@ MCPLFileSource::MCPLFileSource(std::string path) if (!file_exists(path)) { fatal_error(fmt::format("Source file '{}' does not exist.", path)); } - + // Read the source from a binary file instead of sampling from some // assumed source distribution write_message(6, "Reading mcpl source file from {}",path); @@ -367,7 +367,7 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ SourceSite omc_particle; mcpl_particle *mcpl_particle; //extract particle from mcpl-file - mcpl_particle=mcpl_reazd(mcplfile); + mcpl_particle=mcpl_read(mcplfile); // check if it is a neutron or a photon. otherwise skip while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { @@ -375,9 +375,9 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ //check for file exhaustion } - if(mcpl_particle->pdgcode=2112) { + if(mcpl_particle->pdgcode==2112) { omc_particle_=ParticleType::neutron; - } else { + } else if (mcpl_particle->pdgcode==22){ omc_particle_=Particletype::photon; } From 7a6c69fbd5daefcca4b612affdbac6ecd46e9d32 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 11 Jul 2022 09:49:29 +0200 Subject: [PATCH 0547/2654] fix misprints --- src/source.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 231f355fc..9ec1ff798 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -367,7 +367,7 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ SourceSite omc_particle; mcpl_particle *mcpl_particle; //extract particle from mcpl-file - mcpl_particle=mcpl_reazd(mcplfile); + mcpl_particle=mcpl_read(mcplfile); // check if it is a neutron or a photon. otherwise skip while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { @@ -375,9 +375,9 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ //check for file exhaustion } - if(mcpl_particle->pdgcode=2112) { + if(mcpl_particle->pdgcode==2112) { omc_particle_=ParticleType::neutron; - } else { + } else if (mcpl_particle->pdgcode==22){ omc_particle_=Particletype::photon; } @@ -390,9 +390,9 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ omc_particle.u.y=mcpl_particle->direction[1]; omc_particle.u.z=mcpl_particle->direction[2]; - //mcpl stores particles in MeV + //mcpl stores kinetic energy in MeV omc_particle.E=mcpl_particle->ekin*1e6; - + //mcpl stores time in ms omc_particle.t=mcpl_particle->time*1e-3; omc_particle.wgt=mcpl_particle->weight; omc_particle.delayed_group=0; From 0fe895e195c8bfe916910f3219fcff6eec643d75 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 11 Jul 2022 12:29:10 +0000 Subject: [PATCH 0548/2654] Fixed number of dimensions in vtk file --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d5a460baa..1fe5429d0 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -240,7 +240,7 @@ class StructuredMesh(MeshBase): vtk_grid = vtk.vtkStructuredGrid() - vtk_grid.SetDimensions(*self.dimension) + vtk_grid.SetDimensions(*[dim + 1 for dim in self.dimension]) vtkPts = vtk.vtkPoints() vtkPts.SetData(nps.numpy_to_vtk(points, deep=True)) From ef452850bee91c7dc0d5a6ba2272c64e69ded873 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 11 Jul 2022 10:28:06 -0500 Subject: [PATCH 0549/2654] Don't skip CI for non-code files (reverting changes from #2010) --- .github/workflows/ci.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 670b76cd9..050c8e287 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,13 +5,6 @@ on: workflow_dispatch: pull_request: - paths-ignore: - - 'docs/**' - - 'examples/**' - - 'man/**' - - '**.md' - - CODEOWNERS - - LICENSE branches: - develop - master From 34746926d349d0e04134893aa987c49d9508e121 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 13:48:55 +0200 Subject: [PATCH 0550/2654] add necessary xmls --- tests/regression_tests/source_mcpl_file/geometry.xml | 8 ++++++++ tests/regression_tests/source_mcpl_file/materials.xml | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/geometry.xml create mode 100644 tests/regression_tests/source_mcpl_file/materials.xml diff --git a/tests/regression_tests/source_mcpl_file/geometry.xml b/tests/regression_tests/source_mcpl_file/geometry.xml new file mode 100644 index 000000000..bc56030e1 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/geometry.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/regression_tests/source_mcpl_file/materials.xml b/tests/regression_tests/source_mcpl_file/materials.xml new file mode 100644 index 000000000..2472a7471 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/materials.xml @@ -0,0 +1,9 @@ + + + + + + + + + From 25cfc328d04c930a8d75ba41eb46ed7e26c64cae Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 13:49:56 +0200 Subject: [PATCH 0551/2654] set seed to make test deteministic --- tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c index f35a07fc4..61eea95c6 100644 --- a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -52,6 +52,7 @@ int main(int argc, char **argv){ /*the main particle loop*/ particle=&Particle; int i; + srand(1234); for (i=0;i Date: Tue, 12 Jul 2022 13:50:35 +0200 Subject: [PATCH 0552/2654] test target result --- tests/regression_tests/source_mcpl_file/results_true.dat | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/results_true.dat diff --git a/tests/regression_tests/source_mcpl_file/results_true.dat b/tests/regression_tests/source_mcpl_file/results_true.dat new file mode 100644 index 000000000..f2209006a --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +3.017557E-01 3.398770E-03 From b0bb63cb3508d0dff59fd950a60dc35db2188b19 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 13:50:53 +0200 Subject: [PATCH 0553/2654] yet another necessary file --- tests/regression_tests/source_mcpl_file/settings.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/settings.xml diff --git a/tests/regression_tests/source_mcpl_file/settings.xml b/tests/regression_tests/source_mcpl_file/settings.xml new file mode 100644 index 000000000..8b1510e0c --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/settings.xml @@ -0,0 +1,11 @@ + + + + 10 + 5 + 1000 + + + source.10.mcpl + + From e480b5c851c542e53ff6e83236994f23c2bfdba3 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 14:40:01 +0200 Subject: [PATCH 0554/2654] add a check that the test input got created as intended --- tests/regression_tests/source_mcpl_file/test.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 0adf67f1a..922ddddd3 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -15,6 +15,7 @@ class SourceMCPLFileTestHarness(TestHarness): """Run OpenMC with the appropriate arguments and check the outputs.""" try: self._create_input() + self._test_input_created() self._run_openmc() self._test_output_created() results = self._get_results() @@ -31,6 +32,7 @@ class SourceMCPLFileTestHarness(TestHarness): """Update the results_true using the current version of OpenMC.""" try: self._create_input() + self._test_input_created() self._run_openmc() self._test_output_created() results = self._get_results() @@ -39,6 +41,14 @@ class SourceMCPLFileTestHarness(TestHarness): finally: self._cleanup() + def _test_input_created(self): + """Check that the input mcpl.file was generated as it should""" + mcplfile=glob.glob(os.path.join(os.getcwd(),'source.10.mcpl')) + assert len(mcplfile) == 1, 'Either multiple or no mcpl files ' \ + 'exist.' + assert mcplfile[0].endswith('mcpl'), \ + 'output file does not end with mcpl.' + def _test_output_created(self): """Check that the output files were created""" statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) @@ -55,5 +65,5 @@ class SourceMCPLFileTestHarness(TestHarness): os.remove(f) def test_mcpl_source_file(): - harness = SourceMCPLFileTestHarness('statepoint.10.h5') + harness = SourceMCPLFileTestHarness('source.10.mcpl') harness.main() From 6c78d129c3db8b09b0e8b21cb3a4965460127666 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 12 Jul 2022 15:49:40 +0100 Subject: [PATCH 0555/2654] added bbox by @pshriwise --- openmc/universe.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openmc/universe.py b/openmc/universe.py index f3f95aebb..bb1554de8 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -7,6 +7,7 @@ from pathlib import Path from tempfile import TemporaryDirectory from xml.etree import ElementTree as ET +import h5py import numpy as np import openmc @@ -630,6 +631,9 @@ class DAGMCUniverse(UniverseBase): auto_mat_ids : bool Set IDs automatically on initialization (True) or report overlaps in ID space between OpenMC and UWUW materials (False) + bounding_box : 2-tuple of numpy.array + Lower-left and upper-right coordinates of an axis-aligned bounding box + of the universe. """ def __init__(self, @@ -650,6 +654,15 @@ class DAGMCUniverse(UniverseBase): string += '{: <16}=\t{}\n'.format('\tFile', self.filename) return string + @property + def bounding_box(self): + dagmc_file = h5py.File(self.filename) + coords = dagmc_file['tstt']['nodes']['coordinates'][()] + lower_left_corner = coords.min(axis=0) + upper_right_corner = coords.max(axis=0) + bounding_box = (lower_left_corner, upper_right_corner) + return bounding_box + @property def filename(self): return self._filename From 48a3484c39ebd5737e1ced1a576160b0efb78c69 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 12 Jul 2022 16:36:43 +0100 Subject: [PATCH 0556/2654] context manager review suggestion from @pshriwise --- openmc/universe.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index bb1554de8..e7be46822 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -656,12 +656,12 @@ class DAGMCUniverse(UniverseBase): @property def bounding_box(self): - dagmc_file = h5py.File(self.filename) - coords = dagmc_file['tstt']['nodes']['coordinates'][()] - lower_left_corner = coords.min(axis=0) - upper_right_corner = coords.max(axis=0) - bounding_box = (lower_left_corner, upper_right_corner) - return bounding_box + with h5py.File(self.filename) as dagmc_file: + coords = dagmc_file['tstt']['nodes']['coordinates'][()] + lower_left_corner = coords.min(axis=0) + upper_right_corner = coords.max(axis=0) + bounding_box = (lower_left_corner, upper_right_corner) + return bounding_box @property def filename(self): From 8b06863b37ff3a258080a33058ceb9311f15dea3 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 12 Jul 2022 16:52:02 +0100 Subject: [PATCH 0557/2654] added dagmc bounding box test --- tests/regression_tests/dagmc/universes/test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 01963986c..6726b4b44 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -46,6 +46,11 @@ class DAGMCUniverseTest(PyAPITestHarness): # create the DAGMC universe pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True) + # checks that the bounding box is calculated correctly + bounding_box = pincell_univ.bounding_box + assert bounding_box[0].tolist() == [-25., -25., -25.] + assert bounding_box[1].tolist() == [25., 25., 25.] + # create a 2 x 2 lattice using the DAGMC pincell pitch = np.asarray((24.0, 24.0)) lattice = openmc.RectLattice() From 5f8e1ff9d99f7dea76c097cf91f78344c9e3633d Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 12 Jul 2022 11:44:12 -0500 Subject: [PATCH 0558/2654] Address paulromano's comments - various syntax adjustments and cleanups - remove unneeded import statements - add more information to new section in user's guide - typo fixes - remove dilute_initial - move _validate_micro_xs_inputs back into the class as a static method - update tests to reflect changes --- docs/source/usersguide/depletion.rst | 34 ++++---- openmc/deplete/flux_operator.py | 74 ++++++----------- openmc/deplete/helpers.py | 79 +++++++++++++++++++ .../unit_tests/test_flux_deplete_operator.py | 2 +- 4 files changed, 123 insertions(+), 66 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index f4f0ac869..fe3f12dc4 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -181,25 +181,25 @@ Transport-independent depletion .. note:: - This is a brand-new feature and is under heavy development. API changes are + This feature is still under heavy development. API changes are possible and likely in the near future. -OpenMC also supports transport-independent depletion calculations using the -:class:`FluxDepletionOperator` class. Rather than taking a -:class:`openmc.model.Model` object, this class accepts a volume, +OpenMC supports running depletion calculations independent of the OpenMC +transport solver using the :class:`FluxDepletionOperator` class. Rather than +taking a :class:`openmc.model.Model` object, this class accepts a volume, a dictionary of nuclide concentrations, a flux spectra, and one-group -microscopic cross sections as a pandas dataframe. The class includes -helper functions to constructe the dataframe from a csv file or from +microscopic cross sections as a :class:`pandas.DataFrame`. The class includes +helper functions to construct the dataframe from a csv file or from data arrays:: ... micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_path) - nuclides = {'U234':8.92e18, - 'U235':9.98e20, - 'U238':2.22e22, - 'U236':4.57e18, - 'O16':4.64e22, - 'O17':1.76e19} + nuclides = {'U234': 8.92e18, + 'U235': 9.98e20, + 'U238': 2.22e22, + 'U236': 4.57e18, + 'O16': 4.64e22, + 'O17': 1.76e19} volume = 0.5 flux = 1.16e15 @@ -207,8 +207,10 @@ data arrays:: A user can then define an integrator class as they would for a coupled -transport-depletion calculation and follow the steps from there. -present in the depletion chain. +transport-depletion calculation and follow the same steps from there. -.. note:: Ideally, one-group cross section data should be available for every reaction - in the depletion chain. +.. note:: Ideally, one-group cross section data should be available for every + reaction in the depletion chain. If a nuclide that has a reaction + associated with it in the depletion chain is present in the `nuclides` + parameter but not the cross section data, that reaction will not be + simulated. diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 1da7cf9f9..562967e6c 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -6,36 +6,22 @@ and one-group cross sections. """ -import copy -from collections import OrderedDict -import os from warnings import warn import numpy as np import pandas as pd from uncertainties import ufloat -import openmc from openmc.checkvalue import check_type, check_value, check_iterable_type -from openmc.data import DataLibrary -from openmc.exceptions import DataError from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber -from .chain import _find_chain_file, REACTIONS +from .chain import REACTIONS from .reaction_rates import ReactionRates -from .results import Results from .helpers import ConstantFissionYieldHelper -valid_rxns = list(REACTIONS.keys()) -valid_rxns += ['fission'] - -# Convenience function for the micro_xs static methods -def _validate_micro_xs_inputs(nuclides, reactions, data): - check_iterable_type('nuclides', nuclides, str) - check_iterable_type('reactions', reactions, str) - check_type('data', data, np.ndarray, expected_iter_type=float) - [check_value('reactions', reaction, valid_rxns) for reaction in reactions] +valid_rxns = list(REACTIONS) +valid_rxns.append('fission') @@ -51,10 +37,10 @@ class FluxDepletionOperator(TransportOperator): Parameters ---------- volume : float - Volume of the material being depleted in cm^3 + Volume of the material being depleted in [cm^3] nuclides : dict of str to float Dictionary with nuclide names as keys and nuclide concentrations as - values. Nuclide concentration units are [at/cm^3]. + values. Nuclide concentration units are [atom/cm^3]. micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. @@ -64,15 +50,10 @@ class FluxDepletionOperator(TransportOperator): Path to the depletion chain XML file. keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. - Defualt is None. + Default is None. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. - dilute_initial : float, optional - Initial atom density [atoms/cm^3] to add for nuclides that are zero - in initial condition to ensure they exist in the decay chain. - Only done for nuclides with reaction rates. - Defaults to 1.0e3. prev_results : Results, optional Results from a previous depletion calculation. reduce_chain : bool, optional @@ -86,10 +67,6 @@ class FluxDepletionOperator(TransportOperator): Attributes ---------- - dilute_initial : float - Initial atom density [atoms/cm^3] to add for nuclides that are zero - in initial condition to ensure they exist in the decay chain. - Only done for nuclides with reaction rates. round_number : bool Whether or not to round output to OpenMC to 8 digits. Useful in testing, as OpenMC is incredibly sensitive to exact values. @@ -117,12 +94,11 @@ class FluxDepletionOperator(TransportOperator): chain_file, keff=None, fission_q=None, - dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None, fission_yield_opts=None): - super().__init__(chain_file, fission_q, dilute_initial, prev_results) + super().__init__(chain_file, fission_q, 0.0, prev_results) self.round_number = False self.flux_spectra = flux_spectra self._init_nuclides = nuclides @@ -138,7 +114,7 @@ class FluxDepletionOperator(TransportOperator): check_type('micro_xs', micro_xs, pd.DataFrame) self._micro_xs = micro_xs - if not isinstance(keff, type(None)): + if keff is not None: check_type('keff', keff, tuple, float) keff = ufloat(keff) @@ -221,7 +197,6 @@ class FluxDepletionOperator(TransportOperator): for nuc, i_nuc_results in zip(rxn_nuclides, nuc_ind): number[i_nuc_results] = self.number[0, nuc] - # Calculate macroscopic cross sections and store them in rates array for nuc in rxn_nuclides: density = self.number.get_atom_density('0', nuc) @@ -230,8 +205,7 @@ class FluxDepletionOperator(TransportOperator): '0', nuc, rxn, - self._micro_xs[rxn].loc[nuc] * - density) + self._micro_xs[rxn, rxn] * density) # Get reaction rate in reactions/sec rates *= self.flux_spectra @@ -334,15 +308,13 @@ class FluxDepletionOperator(TransportOperator): """ # Validate inputs - try: - assert data.shape == (len(nuclides), len(reactions)) - except AssertionError: - raise SyntaxError( + if data.shape != (len(nuclides), len(reactions)): + raise ValueError( f'Nuclides list of length {len(nuclides)} and ' f'reactions array of length {len(reactions)} do not ' f'match dimensions of data array of shape {data.shape}') - _validate_micro_xs_inputs(nuclides, reactions, data) + FluxDepletionOperator._validate_micro_xs_inputs(nuclides, reactions, data) # Convert to cm^2 if units == 'barn': @@ -371,7 +343,7 @@ class FluxDepletionOperator(TransportOperator): """ micro_xs = pd.read_csv(csv_file, index_col=0) - _validate_micro_xs_inputs(list(micro_xs.index), + FluxDepletionOperator._validate_micro_xs_inputs(list(micro_xs.index), list(micro_xs.columns), micro_xs.to_numpy()) @@ -380,6 +352,16 @@ class FluxDepletionOperator(TransportOperator): return micro_xs + # Convenience function for the micro_xs static methods + @staticmethod + def _validate_micro_xs_inputs(nuclides, reactions, data): + check_iterable_type('nuclides', nuclides, str) + check_iterable_type('reactions', reactions, str) + check_type('data', data, np.ndarray, expected_iter_type=float) + for reaction in reactions: + check_value('reactions', reaction, valid_rxns) + + def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" @@ -464,7 +446,7 @@ class FluxDepletionOperator(TransportOperator): return [nuc for nuc in nuc_list if nuc in self.chain] def _get_all_nuclides_in_simulation(self): - """Determine nuclides that will show up in the simulation. + """Determine nuclides that will show up in the depletion matrix. This is the union of the nuclides provided by the user and the nuclides present in the depletion chain. @@ -487,9 +469,8 @@ class FluxDepletionOperator(TransportOperator): def _get_nuclides_with_data(self): """Finds nuclides with cross section data""" - nuclides_with_data = set(self._micro_xs.index) + return set(self._micro_xs.index) - return nuclides_with_data def _extract_number(self, local_mats, volume, nuclides, prev_res=None): """Construct AtomNumber using geometry @@ -508,11 +489,6 @@ class FluxDepletionOperator(TransportOperator): """ self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) - if self.dilute_initial != 0.0: - for nuc in self._burnable_nucs: - self.number.set_atom_density( - np.s_[:], nuc, self.dilute_initial) - # Now extract and store the number densities # From the geometry if no previous depletion results if prev_res is None: diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 33bd182d7..5adb43998 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -2,6 +2,7 @@ Class for normalizing fission energy deposition """ import bisect +import pandas as pd from abc import abstractmethod from collections import defaultdict from copy import deepcopy @@ -124,6 +125,84 @@ class TalliedFissionYieldHelper(FissionYieldHelper): # ------------------------------------- +class FluxReactionRateHelper(ReactionRateHelper): + """Class for generating one-group reaction rates with flux and + one-group cross sections. + + This class does not generate tallies, and instead stores cross sections + for each nuclides and transmutation reaction relevant for a depletion + calculation. + + Parameters + ---------- + n_nucs : int + Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` + n_react : int + Number of reactions tracked by :class:`openmc.deplete.Operator` + + Attributes + ---------- + flux : + + xs : + + + """ + def __init__(self, n_nuc, n_react): + super().__init__(n_nuc, n_react) + self._flux = None + self._micro_xs = None + + def generate_tallies(self, materials, scores): + """Unused in this case""" + + + @property + def flux(self): + """Flux in n cm^-2 s^-1""" + return self._flux + + @flux.setter + def flux(self, flux): + check_type("flux", flux, float) + self._flux = flux + + @property + def micro_xs(self): + """DataFrame of microscopic cross sections with requested reaction + for all nuclides""" + return self._micro_xs + + @micro_xs.setter + def micro_xs(self, micro_xs): + # TODO : validate micro_xs + self._micro_xs = micro_xs + + def get_material_rates(self, mat_id, nuc_index, react_index): + """Return 2D array of [nuclide, reaction] reaction rates + + Parameters + ---------- + mat_id : int + Unique ID for the requested material + nuc_index : list of str + Ordering of desired nuclides + react_index : list of str + Ordering of reactions + """ + self._results_cache.fill(0.0) + full_tally_res = self._rate_tally.mean[mat_id] + for i_tally, (i_nuc, i_react) in enumerate( + product(nuc_index, react_index)): + self._results_cache[i_nuc, i_react] = full_tally_res[i_tally] + + return self._results_cache + + + + + + class DirectReactionRateHelper(ReactionRateHelper): """Class for generating one-group reaction rates with direct tallies diff --git a/tests/unit_tests/test_flux_deplete_operator.py b/tests/unit_tests/test_flux_deplete_operator.py index a2b150493..99c4e7c8a 100644 --- a/tests/unit_tests/test_flux_deplete_operator.py +++ b/tests/unit_tests/test_flux_deplete_operator.py @@ -48,7 +48,7 @@ def test_create_micro_xs_from_data_array(): FluxDepletionOperator.create_micro_xs_from_data_array( nuclides, reactions, data) - with pytest.raises(SyntaxError, match=r'Nuclides list of length \d* and ' + with pytest.raises(ValueError, match=r'Nuclides list of length \d* and ' r'reactions array of length \d* do not ' r'match dimensions of data array of shape \(\d*\,d*\)'): FluxDepletionOperator.create_micro_xs_from_data_array( From 8e4ce676ff56359cf962e016d0c8c3e5013319d5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 12 Jul 2022 13:50:48 -0500 Subject: [PATCH 0559/2654] Make sure weight window lower/upper bounds are flattened before writing to XML --- openmc/weight_windows.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 2e5b7d8e0..257a17e9a 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -291,10 +291,10 @@ class WeightWindows(IDManagerMixin): subelement.text = ' '.join(str(e) for e in self.energy_bounds) subelement = ET.SubElement(element, 'lower_ww_bounds') - subelement.text = ' '.join(str(b) for b in self.lower_ww_bounds) + subelement.text = ' '.join(str(b) for b in self.lower_ww_bounds.ravel()) subelement = ET.SubElement(element, 'upper_ww_bounds') - subelement.text = ' '.join(str(b) for b in self.upper_ww_bounds) + subelement.text = ' '.join(str(b) for b in self.upper_ww_bounds.ravel()) subelement = ET.SubElement(element, 'survival_ratio') subelement.text = str(self.survival_ratio) From 4784be1fc96d5b688681bedf22c752a55b719b0a Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 12 Jul 2022 21:03:24 +0100 Subject: [PATCH 0560/2654] review line removal from @paulromano Co-authored-by: Paul Romano --- openmc/universe.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index e7be46822..b65263ef9 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -660,8 +660,7 @@ class DAGMCUniverse(UniverseBase): coords = dagmc_file['tstt']['nodes']['coordinates'][()] lower_left_corner = coords.min(axis=0) upper_right_corner = coords.max(axis=0) - bounding_box = (lower_left_corner, upper_right_corner) - return bounding_box + return (lower_left_corner, upper_right_corner) @property def filename(self): From 5b4453c3a9a15a6f0b1e47c61f40194ef1bd4db0 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 12 Jul 2022 15:39:29 -0500 Subject: [PATCH 0561/2654] remove dilute_inital from regression test --- tests/regression_tests/deplete_no_transport/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 1133a039c..cdc8c057c 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -47,7 +47,7 @@ def test_no_transport(run_in_tmpdir, vol_nuc, multiproc): micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) chain_file = Path(__file__).parents[2] / 'chain_simple.xml' flux = 1164719970082145.0 # flux from pincell example - op = FluxDepletionOperator(vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file, dilute_initial=0.0) + op = FluxDepletionOperator(vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file) # Power and timesteps dt = [30] # single step From 39b008df26a449c737caa41238725eb4ed47fd04 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 12 Jul 2022 16:07:59 -0500 Subject: [PATCH 0562/2654] Remove __enter__, __exit__ methods from TransportOperator This commit removes the context manager for switching directories from the TransportOperator class, and moves this functionality to a module-level function, change_directory. --- openmc/deplete/abc.py | 45 +++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index a4f80e3d6..a7cde4afa 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -10,6 +10,7 @@ from collections.abc import Iterable, Callable from copy import deepcopy from inspect import signature from numbers import Real, Integral +from contextlib import contextmanager import os from pathlib import Path import sys @@ -56,6 +57,23 @@ except AttributeError: # Can't set __doc__ on properties on Python 3.4 pass +@contextmanager +def change_directory(output_dir): + """ + Helper function for managing the current directory. + + Parameters + ---------- + output_dir : pathlib.Path + Directory to switch to. + """ + _orig_dir = os.getcwd() + try: + output_dir.mkdir(exist_ok=True) + os.chdir(output_dir) + yield + finally: + os.chdir(_orig_dir) class TransportOperator(ABC): """Abstract class defining a transport operator @@ -87,9 +105,14 @@ class TransportOperator(ABC): Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. + output_dir : pathlib.Path + Path to output directory to save results. prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. + chain : openmc.deplete.Chain + The depletion chain information necessary to form matrices and tallies. + """ def __init__(self, chain_file, fission_q=None, dilute_initial=1.0e3, prev_results=None): @@ -133,18 +156,6 @@ class TransportOperator(ABC): """ - def __enter__(self): - # Save current directory and move to specific output directory - self._orig_dir = os.getcwd() - self.output_dir.mkdir(exist_ok=True) - os.chdir(self.output_dir) - - return self.initial_condition() - - def __exit__(self, exc_type, exc_value, traceback): - self.finalize() - os.chdir(self._orig_dir) - @property def output_dir(self): return self._output_dir @@ -775,7 +786,8 @@ class Integrator(ABC): .. versionadded:: 0.13.1 """ - with self.operator as conc: + with change_directory(self.operator.output_dir): + conc = self.operator.initial_condition() t, self._i_res = self._get_start_data() for i, (dt, source_rate) in enumerate(self): @@ -814,6 +826,8 @@ class Integrator(ABC): source_rate, self._i_res + len(self), proc_time) self.operator.write_bos_data(len(self) + self._i_res) + self.operator.finalize() + @add_params class SIIntegrator(Integrator): @@ -931,7 +945,8 @@ class SIIntegrator(Integrator): .. versionadded:: 0.13.1 """ - with self.operator as conc: + with change_directory(self.operator.output_dir): + conc = self.operator.initial_condition() t, self._i_res = self._get_start_data() for i, (dt, p) in enumerate(self): @@ -967,6 +982,8 @@ class SIIntegrator(Integrator): p, self._i_res + len(self), proc_time) self.operator.write_bos_data(self._i_res + len(self)) + self.operator.finalize() + class DepSystemSolver(ABC): r"""Abstract class for solving depletion equations From f5db4e3afb41ff1b56639ccf157e0256b0b5a19f Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 12 Jul 2022 18:30:29 -0500 Subject: [PATCH 0563/2654] move reuasble code to new parent class; 1st pass - new class OpenMCOperator to contain shared bits of code between the currently existing Operator class and the as-of-yet to be created FluxDepletionOperator class - Operator is now a subclass of OpenMCOperator - move _distribute method to OpenMCOperator - move _get_burnable_mats, _extract_number, _set_number_from_mat, _set_number_from_results to OpenMCOperator - split initial condition into openmc.lib dependent and non-dependent parts; dependent part goes to Operator, non-dependent part goes to OpenMCOperator - move _update_materials to OpenMCOperator - move _get_tally_nuclides to OpenMCOperator - rename _unpack_tallies_and_normalize to _calculate_reaction_rates; move to OpenMCOperator - move get_results_info to OpenMCOperator --- openmc/deplete/__init__.py | 1 + openmc/deplete/openmc_operator.py | 522 ++++++++++++++++++++++++++++++ openmc/deplete/operator.py | 331 +------------------ 3 files changed, 535 insertions(+), 319 deletions(-) create mode 100644 openmc/deplete/openmc_operator.py diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py index 5891555a2..95264308c 100644 --- a/openmc/deplete/__init__.py +++ b/openmc/deplete/__init__.py @@ -7,6 +7,7 @@ A depletion front-end tool. from .nuclide import * from .chain import * +from .openmc_operator import * from .operator import * from .reaction_rates import * from .atom_number import * diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py new file mode 100644 index 000000000..303a5208f --- /dev/null +++ b/openmc/deplete/openmc_operator.py @@ -0,0 +1,522 @@ +"""OpenMC transport operator + +This module implements a transport operator for OpenMC so that it can be used by +depletion integrators. The implementation makes use of the Python bindings to +OpenMC's C API so that reading tally results and updating material number +densities is all done in-memory instead of through the filesystem. + +""" + +import copy +from abc import abstractmethod +from collections import OrderedDict +import os +from warnings import warn + +import numpy as np + +import openmc +from openmc.exceptions import DataError +from openmc.mpi import comm +from .abc import TransportOperator, OperatorResult +from .atom_number import AtomNumber +from .reaction_rates import ReactionRates +from .results import Results +from .helpers import ( + DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper, + FissionYieldCutoffHelper, AveragedFissionYieldHelper, EnergyScoreHelper, + SourceRateHelper, FluxCollapseHelper) + + +__all__ = ["OpenMCOperator", "OperatorResult"] + + +def _distribute(items): + """Distribute items across MPI communicator + + Parameters + ---------- + items : list + List of items of distribute + + Returns + ------- + list + Items assigned to process that called + + """ + min_size, extra = divmod(len(items), comm.size) + j = 0 + for i in range(comm.size): + chunk_size = min_size + int(i < extra) + if comm.rank == i: + return items[j:j + chunk_size] + j += chunk_size + +class OpenMCOperator(TransportOperator): + """OpenMC transport operator for depletion. + + Instances of this class can be used to perform depletion using OpenMC as the + transport operator. Normally, a user needn't call methods of this class + directly. Instead, an instance of this class is passed to an integrator + class, such as :class:`openmc.deplete.CECMIntegrator`. + + .. versionchanged:: 0.13.0 + The geometry and settings parameters have been replaced with a + model parameter that takes a :class:`~openmc.model.Model` object + + Parameters + ---------- + chain_file : str, optional + Path to the depletion chain XML file. Defaults to the file + listed under ``depletion_chain`` in + :envvar:`OPENMC_CROSS_SECTIONS` environment variable. + prev_results : Results, optional + Results from a previous depletion calculation. If this argument is + specified, the depletion calculation will start from the latest state + in the previous results. + fission_q : dict, optional + Dictionary of nuclides and their fission Q values [eV]. If not given, + values will be pulled from the ``chain_file``. Only applicable + if ``"normalization_mode" == "fission-q"`` + dilute_initial : float, optional + Initial atom density [atoms/cm^3] to add for nuclides that are zero + in initial condition to ensure they exist in the decay chain. + Only done for nuclides with reaction rates. + Defaults to 1.0e3. + + Attributes + ---------- + model : openmc.model.Model + OpenMC model object + geometry : openmc.Geometry + OpenMC geometry object + settings : openmc.Settings + OpenMC settings object + dilute_initial : float + Initial atom density [atoms/cm^3] to add for nuclides that + are zero in initial condition to ensure they exist in the decay + chain. Only done for nuclides with reaction rates. + output_dir : pathlib.Path + Path to output directory to save results. + round_number : bool + Whether or not to round output to OpenMC to 8 digits. + Useful in testing, as OpenMC is incredibly sensitive to exact values. + number : openmc.deplete.AtomNumber + Total number of atoms in simulation. + nuclides_with_data : set of str + A set listing all unique nuclides available from cross_sections.xml. + chain : openmc.deplete.Chain + The depletion chain information necessary to form matrices and tallies. + reaction_rates : openmc.deplete.ReactionRates + Reaction rates from the last operator step. + burnable_mats : list of str + All burnable material IDs + heavy_metal : float + Initial heavy metal inventory [g] + local_mats : list of str + All burnable material IDs being managed by a single process + prev_res : Results or None + Results from a previous depletion calculation. ``None`` if no + results are to be used. + cleanup_when_done : bool + Whether to finalize and clear the shared library memory when the + depletion operation is complete. Defaults to clearing the library. + """ + + ## modify + def __init__(self, chain_file=None, fission_q=None, dilute_initial=0.0, prev_results=None): + + super().__init__(chain_file, fission_q, dilute_initial, prev_results) + + ## clear, but we must keep the method + def __call__(self, vec, source_rate): + """Runs a simulation. + + Simulation will abort under the following circumstances: + + 1) No energy is computed using OpenMC tallies. + + Parameters + ---------- + vec : list of numpy.ndarray + Total atoms to be used in function. + source_rate : float + Power in [W] or source rate in [neutron/sec] + + Returns + ------- + openmc.deplete.OperatorResult + Eigenvalue and reaction rates resulting from transport operator + + """ + + ## clear, but must keep the method + def write_bos_data(step): + """Write a state-point file with beginning of step data + + Parameters + ---------- + step : int + Current depletion step including restarts + """ + pass + + ## keep + def _get_burnable_mats(self): + """Determine depletable materials, volumes, and nuclides + + Returns + ------- + burnable_mats : list of str + List of burnable material IDs + volume : OrderedDict of str to float + Volume of each material in [cm^3] + nuclides : list of str + Nuclides in order of how they'll appear in the simulation. + + """ + + burnable_mats = set() + model_nuclides = set() + volume = OrderedDict() + + self.heavy_metal = 0.0 + + # Iterate once through the geometry to get dictionaries + for mat in self.materials: + for nuclide in mat.get_nuclides(): + model_nuclides.add(nuclide) + if mat.depletable: + burnable_mats.add(str(mat.id)) + if mat.volume is None: + raise RuntimeError("Volume not specified for depletable " + "material with ID={}.".format(mat.id)) + volume[str(mat.id)] = mat.volume + self.heavy_metal += mat.fissionable_mass + + # Make sure there are burnable materials + if not burnable_mats: + raise RuntimeError( + "No depletable materials were found in the model.") + + # Sort the sets + burnable_mats = sorted(burnable_mats, key=int) + model_nuclides = sorted(model_nuclides) + + # Construct a global nuclide dictionary, burned first + nuclides = list(self.chain.nuclide_dict) + for nuc in model_nuclides: + if nuc not in nuclides: + nuclides.append(nuc) + + return burnable_mats, volume, nuclides + + ## keep + def _extract_number(self, local_mats, volume, nuclides, prev_res=None): + """Construct AtomNumber using geometry + + Parameters + ---------- + local_mats : list of str + Material IDs to be managed by this process + volume : OrderedDict of str to float + Volumes for the above materials in [cm^3] + nuclides : list of str + Nuclides to be used in the simulation. + prev_res : Results, optional + Results from a previous depletion calculation + + """ + self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) + + if self.dilute_initial != 0.0: + for nuc in self._burnable_nucs: + self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) + + # Now extract and store the number densities + # From the geometry if no previous depletion results + if prev_res is None: + for mat in self.materials: + if str(mat.id) in local_mats: + self._set_number_from_mat(mat) + + # Else from previous depletion results + else: + for mat in self.materials: + if str(mat.id) in local_mats: + self._set_number_from_results(mat, prev_res) + + def _set_number_from_mat(self, mat): + """Extracts material and number densities from openmc.Material + + Parameters + ---------- + mat : openmc.Material + The material to read from + + """ + mat_id = str(mat.id) + + for nuclide, atom_per_bcm in mat.get_nuclide_atom_densities().items(): + atom_per_cc = atom_per_bcm * 1.0e24 + self.number.set_atom_density(mat_id, nuclide, atom_per_cc) + + def _set_number_from_results(self, mat, prev_res): + """Extracts material nuclides and number densities. + + If the nuclide concentration's evolution is tracked, the densities come + from depletion results. Else, densities are extracted from the geometry + in the summary. + + Parameters + ---------- + mat : openmc.Material + The material to read from + prev_res : Results + Results from a previous depletion calculation + + """ + mat_id = str(mat.id) + + # Get nuclide lists from geometry and depletion results + depl_nuc = prev_res[-1].nuc_to_ind + geom_nuc_densities = mat.get_nuclide_atom_densities() + + # Merge lists of nuclides, with the same order for every calculation + geom_nuc_densities.update(depl_nuc) + + for nuclide, atom_per_bcm in geom_nuc_densities.items(): + if nuclide in depl_nuc: + concentration = prev_res.get_atoms(mat_id, nuclide)[1][-1] + volume = prev_res[-1].volume[mat_id] + atom_per_cc = concentration / volume + else: + atom_per_cc = atom_per_bcm * 1.0e24 + + self.number.set_atom_density(mat_id, nuclide, atom_per_cc) + + ## keep, will need to modify + def initial_condition(self, materials): + """Performs final setup and returns initial condition. + + Parameters + ---------- + materials : ??? + + Returns + ------- + list of numpy.ndarray + Total density for initial conditions. + """ + + self._rate_helper.generate_tallies(materials, self.chain.reactions) + self._normalization_helper.prepare( + self.chain.nuclides, self.reaction_rates.index_nuc) + # Tell fission yield helper what materials this process is + # responsible for + self._yield_helper.generate_tallies( + materials, tuple(sorted(self._mat_index_map.values()))) + + # Return number density vector + return list(self.number.get_mat_slice(np.s_[:])) + + ## keep? there is a non-removable part of this + ## that needs the openmc c executable + def _update_materials(self): + """Updates material compositions in OpenMC on all processes.""" + + for rank in range(comm.size): + number_i = comm.bcast(self.number, root=rank) + + for mat in number_i.materials: + nuclides = [] + densities = [] + for nuc in number_i.nuclides: + if nuc in self.nuclides_with_data: + val = 1.0e-24 * number_i.get_atom_density(mat, nuc) + + # If nuclide is zero, do not add to the problem. + if val > 0.0: + if self.round_number: + val_magnitude = np.floor(np.log10(val)) + val_scaled = val / 10**val_magnitude + val_round = round(val_scaled, 8) + + val = val_round * 10**val_magnitude + + nuclides.append(nuc) + densities.append(val) + else: + # Only output warnings if values are significantly + # negative. CRAM does not guarantee positive values. + if val < -1.0e-21: + print("WARNING: nuclide ", nuc, " in material ", mat, + " is negative (density = ", val, " at/barn-cm)") + number_i[mat, nuc] = 0.0 + + # Update densities on C API side + mat_internal = openmc.lib.materials[int(mat)] + mat_internal.set_densities(nuclides, densities) + + #TODO Update densities on the Python side, otherwise the + # summary.h5 file contains densities at the first time step + + ## keep, but rename and modify docstring + ## get_tally_nuclides + def _get_tally_nuclides(self): + """Determine nuclides that should be tallied for reaction rates. + + This method returns a list of all nuclides that have neutron data and + are listed in the depletion chain. Technically, we should tally nuclides + that may not appear in the depletion chain because we still need to get + the fission reaction rate for these nuclides in order to normalize + power, but that is left as a future exercise. + + Returns + ------- + list of str + Tally nuclides + + """ + nuc_set = set() + + # Create the set of all nuclides in the decay chain in materials marked + # for burning in which the number density is greater than zero. + for nuc in self.number.nuclides: + if nuc in self.nuclides_with_data: + if np.sum(self.number[:, nuc]) > 0.0: + nuc_set.add(nuc) + + # Communicate which nuclides have nonzeros to rank 0 + if comm.rank == 0: + for i in range(1, comm.size): + nuc_newset = comm.recv(source=i, tag=i) + nuc_set |= nuc_newset + else: + comm.send(nuc_set, dest=0, tag=comm.rank) + + if comm.rank == 0: + # Sort nuclides in the same order as self.number + nuc_list = [nuc for nuc in self.number.nuclides + if nuc in nuc_set] + else: + nuc_list = None + + # Store list of tally nuclides on each process + nuc_list = comm.bcast(nuc_list) + return [nuc for nuc in nuc_list if nuc in self.chain] + + ## modify + ## the tally-specific methods + ## for the normalization and fission helper classes + ## will already work with the current implementation. + ## For transport-less depletion, we'll need to write + ## a new ReactionRateHelper + def _calculate_reaction_rates(self, source_rate): + """Unpack tallies from OpenMC and return an operator result + + This method uses OpenMC's C API bindings to determine the k-effective + value and reaction rates from the simulation. The reaction rates are + normalized by a helper class depending on the method being used. + + Parameters + ---------- + source_rate : float + Power in [W] or source rate in [neutron/sec] + + Returns + ------- + rates : openmc.deplete.ReactionRates + Reaction rates for nuclides + + """ + rates = self.reaction_rates + rates.fill(0.0) + + # Extract tally bins + nuclides = self._rate_helper.nuclides + + # Form fast map + nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides] + react_ind = [rates.index_rx[react] for react in self.chain.reactions] + + # Keep track of energy produced from all reactions in eV per source + # particle + self._normalization_helper.reset() + self._yield_helper.unpack() + + # Store fission yield dictionaries + fission_yields = [] + + # Create arrays to store fission Q values, reaction rates, and nuclide + # numbers, zeroed out in material iteration + number = np.empty(rates.n_nuc) + + fission_ind = rates.index_rx.get("fission") + + # Extract results + for i, mat in enumerate(self.local_mats): + # Get tally index + mat_index = self._mat_index_map[mat] + + # Zero out reaction rates and nuclide numbers + number.fill(0.0) + + # Get new number densities + for nuc, i_nuc_results in zip(nuclides, nuc_ind): + number[i_nuc_results] = self.number[mat, nuc] + + tally_rates = self._rate_helper.get_material_rates( + mat_index, nuc_ind, react_ind) + + # Compute fission yields for this material + fission_yields.append(self._yield_helper.weighted_yields(i)) + + # Accumulate energy from fission + if fission_ind is not None: + self._normalization_helper.update(tally_rates[:, fission_ind]) + + # Divide by total number and store + rates[i] = self._rate_helper.divide_by_adens(number) + + # Scale reaction rates to obtain units of reactions/sec + rates *= self._normalization_helper.factor(source_rate) + + # Store new fission yields on the chain + self.chain.fission_yields = fission_yields + + return rates + + @abstractmethod + def _get_nuclides_with_data(self): + """Find nuclides with cross section data""" + + ## Keep + def get_results_info(self): + """Returns volume list, material lists, and nuc lists. + + Returns + ------- + volume : dict of str float + Volumes corresponding to materials in full_burn_dict + nuc_list : list of str + A list of all nuclide names. Used for sorting the simulation. + burn_list : list of int + A list of all material IDs to be burned. Used for sorting the simulation. + full_burn_list : list + List of all burnable material IDs + + """ + nuc_list = self.number.burnable_nuclides + burn_list = self.local_mats + + volume = {} + for i, mat in enumerate(burn_list): + volume[mat] = self.number.volume[i] + + # Combine volume dictionaries across processes + volume_list = comm.allgather(volume) + volume = {k: v for d in volume_list for k, v in d.items()} + + return volume, nuc_list, burn_list, self.burnable_mats diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 7ef874e87..665de1999 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -24,6 +24,7 @@ from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .chain import _find_chain_file +from .openmc_operator import OpenMCOperator, _distribute from .reaction_rates import ReactionRates from .results import Results from .helpers import ( @@ -34,30 +35,6 @@ from .helpers import ( __all__ = ["Operator", "OperatorResult"] - -def _distribute(items): - """Distribute items across MPI communicator - - Parameters - ---------- - items : list - List of items of distribute - - Returns - ------- - list - Items assigned to process that called - - """ - min_size, extra = divmod(len(items), comm.size) - j = 0 - for i in range(comm.size): - chunk_size = min_size + int(i < extra) - if comm.rank == i: - return items[j:j + chunk_size] - j += chunk_size - - def _find_cross_sections(model): """Determine cross sections to use for depletion""" if model.materials and model.materials.cross_sections is not None: @@ -74,7 +51,7 @@ def _find_cross_sections(model): return cross_sections -class Operator(TransportOperator): +class Operator(OpenMCOperator): """OpenMC transport operator for depletion. Instances of this class can be used to perform depletion using OpenMC as the @@ -267,7 +244,7 @@ class Operator(TransportOperator): # Clear out OpenMC, create task lists, distribute openmc.reset_auto_ids() - self.burnable_mats, volume, nuclides = self._get_burnable_mats() + self.burnable_mats, volume, nuclides = super()._get_burnable_mats() self.local_mats = _distribute(self.burnable_mats) # Generate map from local materials => material index @@ -298,7 +275,7 @@ class Operator(TransportOperator): if nuc.name in self.nuclides_with_data] # Extract number densities from the geometry / previous depletion run - self._extract_number(self.local_mats, volume, nuclides, self.prev_res) + super()._extract_number(self.local_mats, volume, nuclides, self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( @@ -380,7 +357,7 @@ class Operator(TransportOperator): openmc.reset_auto_ids() # Update tally nuclides data in preparation for transport solve - nuclides = self._get_tally_nuclides() + nuclides = super()._get_tally_nuclides() self._rate_helper.nuclides = nuclides self._normalization_helper.nuclides = nuclides self._yield_helper.update_tally_nuclides(nuclides) @@ -390,7 +367,12 @@ class Operator(TransportOperator): openmc.lib.reset_timers() # Extract results - op_result = self._unpack_tallies_and_normalize(source_rate) + rates = self._calculate_reaction_rates(source_rate) + + # Get k and uncertainty + keff = ufloat(*openmc.lib.keff()) + + op_result = OperatorResult(keff, rates) return copy.deepcopy(op_result) @@ -434,138 +416,6 @@ class Operator(TransportOperator): cell.fill = [mat.clone() for i in range(cell.num_instances)] - def _get_burnable_mats(self): - """Determine depletable materials, volumes, and nuclides - - Returns - ------- - burnable_mats : list of str - List of burnable material IDs - volume : OrderedDict of str to float - Volume of each material in [cm^3] - nuclides : list of str - Nuclides in order of how they'll appear in the simulation. - - """ - - burnable_mats = set() - model_nuclides = set() - volume = OrderedDict() - - self.heavy_metal = 0.0 - - # Iterate once through the geometry to get dictionaries - for mat in self.materials: - for nuclide in mat.get_nuclides(): - model_nuclides.add(nuclide) - if mat.depletable: - burnable_mats.add(str(mat.id)) - if mat.volume is None: - raise RuntimeError("Volume not specified for depletable " - "material with ID={}.".format(mat.id)) - volume[str(mat.id)] = mat.volume - self.heavy_metal += mat.fissionable_mass - - # Make sure there are burnable materials - if not burnable_mats: - raise RuntimeError( - "No depletable materials were found in the model.") - - # Sort the sets - burnable_mats = sorted(burnable_mats, key=int) - model_nuclides = sorted(model_nuclides) - - # Construct a global nuclide dictionary, burned first - nuclides = list(self.chain.nuclide_dict) - for nuc in model_nuclides: - if nuc not in nuclides: - nuclides.append(nuc) - - return burnable_mats, volume, nuclides - - def _extract_number(self, local_mats, volume, nuclides, prev_res=None): - """Construct AtomNumber using geometry - - Parameters - ---------- - local_mats : list of str - Material IDs to be managed by this process - volume : OrderedDict of str to float - Volumes for the above materials in [cm^3] - nuclides : list of str - Nuclides to be used in the simulation. - prev_res : Results, optional - Results from a previous depletion calculation - - """ - self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) - - if self.dilute_initial != 0.0: - for nuc in self._burnable_nucs: - self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) - - # Now extract and store the number densities - # From the geometry if no previous depletion results - if prev_res is None: - for mat in self.materials: - if str(mat.id) in local_mats: - self._set_number_from_mat(mat) - - # Else from previous depletion results - else: - for mat in self.materials: - if str(mat.id) in local_mats: - self._set_number_from_results(mat, prev_res) - - def _set_number_from_mat(self, mat): - """Extracts material and number densities from openmc.Material - - Parameters - ---------- - mat : openmc.Material - The material to read from - - """ - mat_id = str(mat.id) - - for nuclide, atom_per_bcm in mat.get_nuclide_atom_densities().items(): - atom_per_cc = atom_per_bcm * 1.0e24 - self.number.set_atom_density(mat_id, nuclide, atom_per_cc) - - def _set_number_from_results(self, mat, prev_res): - """Extracts material nuclides and number densities. - - If the nuclide concentration's evolution is tracked, the densities come - from depletion results. Else, densities are extracted from the geometry - in the summary. - - Parameters - ---------- - mat : openmc.Material - The material to read from - prev_res : Results - Results from a previous depletion calculation - - """ - mat_id = str(mat.id) - - # Get nuclide lists from geometry and depletion results - depl_nuc = prev_res[-1].nuc_to_ind - geom_nuc_densities = mat.get_nuclide_atom_densities() - - # Merge lists of nuclides, with the same order for every calculation - geom_nuc_densities.update(depl_nuc) - - for nuclide, atom_per_bcm in geom_nuc_densities.items(): - if nuclide in depl_nuc: - concentration = prev_res.get_atoms(mat_id, nuclide)[1][-1] - volume = prev_res[-1].volume[mat_id] - atom_per_cc = concentration / volume - else: - atom_per_cc = atom_per_bcm * 1.0e24 - - self.number.set_atom_density(mat_id, nuclide, atom_per_cc) - def initial_condition(self): """Performs final setup and returns initial condition. @@ -589,16 +439,8 @@ class Operator(TransportOperator): # Generate tallies in memory materials = [openmc.lib.materials[int(i)] for i in self.burnable_mats] - self._rate_helper.generate_tallies(materials, self.chain.reactions) - self._normalization_helper.prepare( - self.chain.nuclides, self.reaction_rates.index_nuc) - # Tell fission yield helper what materials this process is - # responsible for - self._yield_helper.generate_tallies( - materials, tuple(sorted(self._mat_index_map.values()))) - # Return number density vector - return list(self.number.get_mat_slice(np.s_[:])) + return super().initial_condition(materials) def finalize(self): """Finalize a depletion simulation and release resources.""" @@ -659,127 +501,6 @@ class Operator(TransportOperator): self.materials.export_to_xml() - def _get_tally_nuclides(self): - """Determine nuclides that should be tallied for reaction rates. - - This method returns a list of all nuclides that have neutron data and - are listed in the depletion chain. Technically, we should tally nuclides - that may not appear in the depletion chain because we still need to get - the fission reaction rate for these nuclides in order to normalize - power, but that is left as a future exercise. - - Returns - ------- - list of str - Tally nuclides - - """ - nuc_set = set() - - # Create the set of all nuclides in the decay chain in materials marked - # for burning in which the number density is greater than zero. - for nuc in self.number.nuclides: - if nuc in self.nuclides_with_data: - if np.sum(self.number[:, nuc]) > 0.0: - nuc_set.add(nuc) - - # Communicate which nuclides have nonzeros to rank 0 - if comm.rank == 0: - for i in range(1, comm.size): - nuc_newset = comm.recv(source=i, tag=i) - nuc_set |= nuc_newset - else: - comm.send(nuc_set, dest=0, tag=comm.rank) - - if comm.rank == 0: - # Sort nuclides in the same order as self.number - nuc_list = [nuc for nuc in self.number.nuclides - if nuc in nuc_set] - else: - nuc_list = None - - # Store list of tally nuclides on each process - nuc_list = comm.bcast(nuc_list) - return [nuc for nuc in nuc_list if nuc in self.chain] - - def _unpack_tallies_and_normalize(self, source_rate): - """Unpack tallies from OpenMC and return an operator result - - This method uses OpenMC's C API bindings to determine the k-effective - value and reaction rates from the simulation. The reaction rates are - normalized by a helper class depending on the method being used. - - Parameters - ---------- - source_rate : float - Power in [W] or source rate in [neutron/sec] - - Returns - ------- - openmc.deplete.OperatorResult - Eigenvalue and reaction rates resulting from transport operator - - """ - rates = self.reaction_rates - rates.fill(0.0) - - # Get k and uncertainty - keff = ufloat(*openmc.lib.keff()) - - # Extract tally bins - nuclides = self._rate_helper.nuclides - - # Form fast map - nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides] - react_ind = [rates.index_rx[react] for react in self.chain.reactions] - - # Keep track of energy produced from all reactions in eV per source - # particle - self._normalization_helper.reset() - self._yield_helper.unpack() - - # Store fission yield dictionaries - fission_yields = [] - - # Create arrays to store fission Q values, reaction rates, and nuclide - # numbers, zeroed out in material iteration - number = np.empty(rates.n_nuc) - - fission_ind = rates.index_rx.get("fission") - - # Extract results - for i, mat in enumerate(self.local_mats): - # Get tally index - mat_index = self._mat_index_map[mat] - - # Zero out reaction rates and nuclide numbers - number.fill(0.0) - - # Get new number densities - for nuc, i_nuc_results in zip(nuclides, nuc_ind): - number[i_nuc_results] = self.number[mat, nuc] - - tally_rates = self._rate_helper.get_material_rates( - mat_index, nuc_ind, react_ind) - - # Compute fission yields for this material - fission_yields.append(self._yield_helper.weighted_yields(i)) - - # Accumulate energy from fission - if fission_ind is not None: - self._normalization_helper.update(tally_rates[:, fission_ind]) - - # Divide by total number and store - rates[i] = self._rate_helper.divide_by_adens(number) - - # Scale reaction rates to obtain units of reactions/sec - rates *= self._normalization_helper.factor(source_rate) - - # Store new fission yields on the chain - self.chain.fission_yields = fission_yields - - return OperatorResult(keff, rates) - def _get_nuclides_with_data(self, cross_sections): """Loads cross_sections.xml file to find nuclides with neutron data""" nuclides = set() @@ -792,31 +513,3 @@ class Operator(TransportOperator): nuclides.add(name) return nuclides - - def get_results_info(self): - """Returns volume list, material lists, and nuc lists. - - Returns - ------- - volume : dict of str float - Volumes corresponding to materials in full_burn_dict - nuc_list : list of str - A list of all nuclide names. Used for sorting the simulation. - burn_list : list of int - A list of all material IDs to be burned. Used for sorting the simulation. - full_burn_list : list - List of all burnable material IDs - - """ - nuc_list = self.number.burnable_nuclides - burn_list = self.local_mats - - volume = {} - for i, mat in enumerate(burn_list): - volume[mat] = self.number.volume[i] - - # Combine volume dictionaries across processes - volume_list = comm.allgather(volume) - volume = {k: v for d in volume_list for k, v in d.items()} - - return volume, nuc_list, burn_list, self.burnable_mats From 8c9bb761e5d3838a33822f7fa283acab106cc736 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 10:25:55 +0200 Subject: [PATCH 0564/2654] fix bugs and finalize interface to MCPL --- include/openmc/source.h | 22 +++++++------ src/source.cpp | 73 +++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index 69dd47eae..4d7ec104a 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -12,6 +12,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { //============================================================================== @@ -100,6 +104,7 @@ private: vector sites_; //!< Source sites from a file }; +#ifdef OPENMC_MCPL //============================================================================== // MCPL-file input source //============================================================================== @@ -109,24 +114,21 @@ public: MCPLFileSource(std::string path); ~MCPLFileSource(); - // Properties - ParticleType particle_type() const { return particle_; } - + // Methods //! Sample from the external source distribution //! \param[inout] seed Pseudorandom seed pointer //! \return Site read from MCPL-file - SourceSite sample(uint64_t* seed) const override; + SourceSite sample(uint64_t* seed) const; private: - ParticleType particle_ {ParticleType::neutron}; //!< Type of particle emitted + SourceSite read_single_particle() const; + void read_source_bank(vector &sites_); + vector sites_; //! #endif @@ -336,6 +336,7 @@ CustomSourceWrapper::~CustomSourceWrapper() #endif } +#ifdef OPENMC_MCPL //=========================================================================== // Read particles from an MCPL-file //=========================================================================== @@ -351,54 +352,70 @@ MCPLFileSource::MCPLFileSource(std::string path) write_message(6, "Reading mcpl source file from {}",path); // Open the mcpl file - mcpl_file = mcpl_open(path.c_str); + mcpl_file = mcpl_open_file(path.c_str()); //do checks on the mcpl_file to see if particles are many enough. // should model this on the example source shown in the docs. - uint64_t nparticles=mcpl_hdr_nparticles(mcpl_file); + n_sites=mcpl_hdr_nparticles(mcpl_file); + read_source_bank(sites_); } -MCPLFileSource::~MCPLFilsSource(){ +MCPLFileSource::~MCPLFileSource(){ mcpl_close_file(mcpl_file); } -SourceSite MCPLFileSource::sample(uint64_t *seed){ - SourceSite omc_particle; - mcpl_particle *mcpl_particle; +SourceSite MCPLFileSource::sample(uint64_t* seed) const +{ + size_t i_site = sites_.size() * prn(seed); + return sites_[i_site]; +} + +void MCPLFileSource::read_source_bank(vector &sites_) +{ + sites_.resize(n_sites); + for (int i=0;ipdgcode!=2112 && mcpl_particle->pdgcode!=22 ) - { - mcpl_particle(mcpl_read(mcplfile); - //check for file exhaustion + mcpl_particle=mcpl_read(mcpl_file); + // check if it is a neutron or a photon. otherwise skip + while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { + mcpl_particle=mcpl_read(mcpl_file); + //should check for file exhaustion This could happen if particles are other than + //neutrons or photons } if(mcpl_particle->pdgcode==2112) { - omc_particle_=ParticleType::neutron; - } else if (mcpl_particle->pdgcode==22){ - omc_particle_=Particletype::photon; + omc_particle_.particle=ParticleType::neutron; + } else if (mcpl_particle->pdgcode==22) { + omc_particle_.particle=ParticleType::photon; } //particle is good, convert to openmc-formalism - omc_particle.r.x=mcpl_particle.x; - omc_particle.r.y=mcpl_particle.y; - omc_particle.r.z=mcpl_particle.z; + omc_particle_.r.x=mcpl_particle->position[0]; + omc_particle_.r.y=mcpl_particle->position[1]; + omc_particle_.r.z=mcpl_particle->position[2]; - omc_particle.u.x=mcpl_particle->direction[0]; - omc_particle.u.y=mcpl_particle->direction[1]; - omc_particle.u.z=mcpl_particle->direction[2]; + omc_particle_.u.x=mcpl_particle->direction[0]; + omc_particle_.u.y=mcpl_particle->direction[1]; + omc_particle_.u.z=mcpl_particle->direction[2]; //mcpl stores kinetic energy in MeV - omc_particle.E=mcpl_particle->ekin*1e6; + omc_particle_.E=mcpl_particle->ekin*1e6; //mcpl stores time in ms - omc_particle.t=mcpl_particle->time*1e-3; - omc_particle.wgt=mcpl_particle->weight; - omc_particle.delayed_group=0; - return omc_particle; + omc_particle_.time=mcpl_particle->time*1e-3; + omc_particle_.wgt=mcpl_particle->weight; + omc_particle_.delayed_group=0; + return omc_particle_; } - +#endif //OPENMC_MCPL //============================================================================== // Non-member functions From 915d69fb3d217cf705158dba680b8f02a99208c7 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 10:26:24 +0200 Subject: [PATCH 0565/2654] add an option to turn on mcpl-support --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85dcd7084..6af9643cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) option(OPENMC_USE_MPI "Enable MPI" OFF) +option(OPENMC_USE_MCPL "Enable MPCPL" OFF) #=============================================================================== # Set a default build configuration if not explicitly specified @@ -154,6 +155,10 @@ if(OPENMC_ENABLE_COVERAGE) list(APPEND ldflags --coverage) endif() +if(OPENMC_USE_MCPL) + list(APPEND ldflags -lmcpl) +endif() + # Show flags being used message(STATUS "OpenMC C++ flags: ${cxxflags}") message(STATUS "OpenMC Linker flags: ${ldflags}") @@ -408,6 +413,10 @@ endif() if (OPENMC_USE_MPI) target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) endif() +if(OPENMC_USE_MCPL) + target_compile_definitions(libopenmc PUBLIC -DOPENMC_MCPL) +endif() + # Set git SHA1 hash as a compile definition if(GIT_FOUND) From b140eeb7cb4c7a1ee76172cd21c32c2e9951a24b Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 10:27:18 +0200 Subject: [PATCH 0566/2654] add a source type to the settings interface --- src/settings.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/settings.cpp b/src/settings.cpp index eb0d4936c..12e0a8050 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -430,6 +430,9 @@ void read_settings_xml() if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); model::external_sources.push_back(make_unique(path)); + } else if (check_for_node(node, "mcpl")) { + auto path = get_node_value(node, "mcpl", false, true); + model::external_sources.push_back(make_unique(path)); } else if (check_for_node(node, "library")) { // Get shared library path and parameters auto path = get_node_value(node, "library", false, true); From cd163ef0b91fb4acc30630528b0728d8bab3098e Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 12:13:10 +0200 Subject: [PATCH 0567/2654] only add mcpl-support if OPENMC_MCPL is defined --- src/settings.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/settings.cpp b/src/settings.cpp index 12e0a8050..d419cab06 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -430,9 +430,11 @@ void read_settings_xml() if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); model::external_sources.push_back(make_unique(path)); +#ifdef OPENMC_MCPL } else if (check_for_node(node, "mcpl")) { auto path = get_node_value(node, "mcpl", false, true); model::external_sources.push_back(make_unique(path)); +#endif } else if (check_for_node(node, "library")) { // Get shared library path and parameters auto path = get_node_value(node, "library", false, true); From a79233b3ec85f59647fb800da7db0973ce9365e8 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 14:13:33 +0200 Subject: [PATCH 0568/2654] needed to avoid name clashes with other tests --- tests/regression_tests/source_mcpl_file/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/regression_tests/source_mcpl_file/__init__.py diff --git a/tests/regression_tests/source_mcpl_file/__init__.py b/tests/regression_tests/source_mcpl_file/__init__.py new file mode 100644 index 000000000..e69de29bb From 1e849fe16239883531c1bb27ce80d826f4583dad Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 13 Jul 2022 11:09:35 -0500 Subject: [PATCH 0569/2654] Apply @JoffreyDorville suggestions from code review Co-authored-by: Joffrey Dorville <54550047+JoffreyDorville@users.noreply.github.com> --- openmc/data/kalbach_mann.py | 6 +++--- tests/unit_tests/test_data_kalbach_mann.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index 02403b3cc..a036da694 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -133,7 +133,7 @@ def _separation_energy(compound, nucleus, particle): N_a = nucleus.n # Determine breakup energy of incident particle (ENDF-6 Formats Manual, - # Appendix H, Table 3) + # Appendix H, Table 3) in MeV za_to_breaking_energy = { 1: 0.0, 1001: 0.0, @@ -142,7 +142,7 @@ def _separation_energy(compound, nucleus, particle): 2003: 7.718043, 2004: 28.29566 } - I_b = za_to_breaking_energy[particle.za] + I_a = za_to_breaking_energy[particle.za] # Eq. 4 in in doi:10.1103/PhysRevC.37.2350 or ENDF-6 Formats Manual section # 6.2.3.2 @@ -153,7 +153,7 @@ def _separation_energy(compound, nucleus, particle): 33.22 * ((N_c - Z_c)**2 / A_c**(4./3.) - (N_a - Z_a)**2 / A_a**(4./3.)) - 0.717 * (Z_c**2 / A_c**(1./3.) - Z_a**2 / A_a**(1./3.)) + 1.211 * (Z_c**2 / A_c - Z_a**2 / A_a) - - I_b + I_a ) diff --git a/tests/unit_tests/test_data_kalbach_mann.py b/tests/unit_tests/test_data_kalbach_mann.py index 931e236bd..3b837af7d 100644 --- a/tests/unit_tests/test_data_kalbach_mann.py +++ b/tests/unit_tests/test_data_kalbach_mann.py @@ -75,7 +75,7 @@ def test_atomic_representation(neutron, triton, b10, c12, c13, na23): assert triton.n == 2 assert triton.za == 1003 - # Test instanciation errors + # Test instantiation errors with pytest.raises(ValueError): _AtomicRepresentation(z=5, a=1) with pytest.raises(ValueError): @@ -129,7 +129,7 @@ def test_kalbach_slope(): ('Hg204.h5', 'n-080_Hg_204.endf') ] ) -def test_comparison_slope_hdf5(hdf5_filename, endf_type, endf_filename): +def test_comparison_slope_hdf5(hdf5_filename, endf_filename): """Test the calculation of the Kalbach-Mann slope done by OpenMC by comparing it to HDF5 data. The test is based on the first product of MT=5 (neutron). The isotopes tested have been selected because the From cd60109a77dd7a3e6a492ef734684af272fb5cce Mon Sep 17 00:00:00 2001 From: shimwell Date: Wed, 13 Jul 2022 19:14:14 +0100 Subject: [PATCH 0570/2654] added bounding_region --- openmc/universe.py | 43 +++++++++++++++++++ .../regression_tests/dagmc/universes/test.py | 14 ++++++ 2 files changed, 57 insertions(+) diff --git a/openmc/universe.py b/openmc/universe.py index b65263ef9..2fd931506 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -713,6 +713,49 @@ class DAGMCUniverse(UniverseBase): dagmc_element.set('filename', self.filename) xml_element.append(dagmc_element) + def bounding_region(self, bounded_type='box', boundary_type='vacuum'): + """Creates a either a spherical or box shaped bounding region around + the DAGMC geometry. + Parameters + ---------- + bounded_type : str + The type of bounding surface(s) to use when constructing the region. + Options include a single spherical surface (sphere) or a rectangle + made from siz planes (box). + boundary_type : str + Boundary condition that defines the behavior for particles hitting + the surface. Defaults to vacuum boundary condition. Passed into + Returns + ------- + openmc.Region + Region instance + """ + + bounding_box = self.bounding_box + + if bounded_type == 'sphere': + import math + bounding_box_center = (bounding_box[0] + bounding_box[1])/2 + radius = math.dist(bounding_box[0], bounding_box[1]) + bounding_surface = openmc.Sphere(x0=bounding_box_center[0], y0=bounding_box_center[1], z0=bounding_box_center[2], r=radius) + + return -bounding_surface + + if bounded_type == 'box': + # defines plane surfaces for all six faces of the bounding box + lower_x = openmc.XPlane(bounding_box[0][0], boundary_type=boundary_type) + upper_x = openmc.XPlane(bounding_box[1][0], boundary_type=boundary_type) + lower_y = openmc.YPlane(bounding_box[0][1], boundary_type=boundary_type) + upper_y = openmc.YPlane(bounding_box[1][1], boundary_type=boundary_type) + lower_z = openmc.ZPlane(bounding_box[0][2], boundary_type=boundary_type) + upper_z = openmc.ZPlane(bounding_box[1][2], boundary_type=boundary_type) + + return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z + + def bounded_universe(self, **kwargs): + bounding_cell = openmc.Cell(fill=self, region=self.bounding_region(**kwargs)) + return openmc.Universe(cells=[bounding_cell]) + @classmethod def from_hdf5(cls, group): """Create DAGMC universe from HDF5 group diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 6726b4b44..f6964857d 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -51,6 +51,20 @@ class DAGMCUniverseTest(PyAPITestHarness): assert bounding_box[0].tolist() == [-25., -25., -25.] assert bounding_box[1].tolist() == [25., 25., 25.] + # checks that the bounding region is six surfaces each with a vacuum boundary type + b_region = pincell_univ.bounding_region(bounded_type='box', boundary_type='vacuum') + assert isinstance(b_region, openmc.Region) + assert len(b_region.get_surfaces()) == 6 + for surface in list(b_region.get_surfaces().values()): + assert surface.boundary_type == 'vacuum' + + # checks that the bounding region is a single surface with a reflective boundary type + b_region = pincell_univ.bounding_region(bounded_type='sphere', boundary_type='reflective') + assert isinstance(b_region, openmc.Region) + assert len(b_region.get_surfaces()) == 1 + for surface in list(b_region.get_surfaces().values()): + assert surface.boundary_type == 'reflective' + # create a 2 x 2 lattice using the DAGMC pincell pitch = np.asarray((24.0, 24.0)) lattice = openmc.RectLattice() From eff690fd90032abd0d4a5e68f5babcc38c476de1 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 20:55:53 +0200 Subject: [PATCH 0571/2654] fail without tripping the entire test-process --- tests/regression_tests/source_mcpl_file/test.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 922ddddd3..f55a76904 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -1,11 +1,6 @@ -import pathlib as pl import os -import shutil import subprocess -import textwrap import glob -import openmc -import pytest from tests.testing_harness import TestHarness @@ -25,7 +20,8 @@ class SourceMCPLFileTestHarness(TestHarness): self._cleanup() def _create_input(self): - subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) + compiled=subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) + assert compiled==0, 'Could not compile mcpl-file generator code' subprocess.run(['./gen_dummy_mcpl.out']) def update_results(self): From 5d5a2d6fa5fa3c3f6f0fada60115f1e3e7add984 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Wed, 13 Jul 2022 15:55:15 -0500 Subject: [PATCH 0572/2654] _orig_dir -> orig_dir Co-authored-by: Paul Romano --- openmc/deplete/abc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index a7cde4afa..8bbe126df 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -67,13 +67,14 @@ def change_directory(output_dir): output_dir : pathlib.Path Directory to switch to. """ - _orig_dir = os.getcwd() + orig_dir = os.getcwd() try: output_dir.mkdir(exist_ok=True) os.chdir(output_dir) yield finally: - os.chdir(_orig_dir) + os.chdir(orig_dir) + class TransportOperator(ABC): """Abstract class defining a transport operator From 8f1db414589f11bbc0511c1ba81064a33d638cf9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 13 Jul 2022 15:55:48 -0500 Subject: [PATCH 0573/2654] overhaul FluxTimexXSHelper class --- openmc/deplete/helpers.py | 42 +++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 5adb43998..67a88fa16 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -25,7 +25,7 @@ __all__ = ( "DirectReactionRateHelper", "ChainFissionHelper", "EnergyScoreHelper" "SourceRateHelper", "TalliedFissionYieldHelper", "ConstantFissionYieldHelper", "FissionYieldCutoffHelper", - "AveragedFissionYieldHelper", "FluxCollapseHelper") + "AveragedFissionYieldHelper", "FluxCollapseHelper", "FluxTimesXSHelper") class TalliedFissionYieldHelper(FissionYieldHelper): """Abstract class for computing fission yields with tallies @@ -125,16 +125,21 @@ class TalliedFissionYieldHelper(FissionYieldHelper): # ------------------------------------- -class FluxReactionRateHelper(ReactionRateHelper): +class FluxTimesXSHelper(ReactionRateHelper): """Class for generating one-group reaction rates with flux and one-group cross sections. This class does not generate tallies, and instead stores cross sections - for each nuclides and transmutation reaction relevant for a depletion - calculation. + for each nuclide and transmutation reaction relevant for a depletion + calculation. The reaction rate is calculated by multiplying the flux by the + cross sections. Parameters ---------- + flux : float + Neutron flux + micro_xs : pandas.DataFrame + Microscopic cross-section data n_nucs : int Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` n_react : int @@ -142,16 +147,22 @@ class FluxReactionRateHelper(ReactionRateHelper): Attributes ---------- - flux : - - xs : - + nuc_ind_map : dict of int to str + Dictionary mapping the nuclide index to nuclide name + rxn_ind_map : dict of int to str + Dictionary mapping reaction index to reaction name + number : AtomNumber + AtomNumber object. Needed to convert the microscopic cross-sections + to macroscopic cross sections. """ - def __init__(self, n_nuc, n_react): + def __init__(self, flux, micro_xs, n_nuc, n_react): super().__init__(n_nuc, n_react) - self._flux = None - self._micro_xs = None + self._flux = flux + self._micro_xs = micro_xs + self.nuc_ind_map = None + self.rxn_ind_map = None + self.number = None def generate_tallies(self, materials, scores): """Unused in this case""" @@ -191,10 +202,11 @@ class FluxReactionRateHelper(ReactionRateHelper): Ordering of reactions """ self._results_cache.fill(0.0) - full_tally_res = self._rate_tally.mean[mat_id] - for i_tally, (i_nuc, i_react) in enumerate( - product(nuc_index, react_index)): - self._results_cache[i_nuc, i_react] = full_tally_res[i_tally] + for i, (i_nuc, i_react) in enumerate(product(nuc_index, react_index)): + nuc = self.nuc_ind_map[i_nuc] + rxn = self.rxn_ind_map[i_react] + density = self.number.get_atom_density(mat_id, nuc) + self._results_cache[i_nuc, i_react] = self._micro_xs[rxn][nuc] * density return self._results_cache From a1aa66c1fda8b103d1c8cb094911fc0d913e1c6b Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 13 Jul 2022 15:56:29 -0500 Subject: [PATCH 0574/2654] make FluxDepletionOperator work with multiple materials; update regression test --- openmc/deplete/flux_operator.py | 330 +++++++++++++----- .../deplete_no_transport/test_reference.h5 | Bin 35688 -> 35688 bytes 2 files changed, 243 insertions(+), 87 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 562967e6c..5e23ec203 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -5,25 +5,44 @@ and one-group cross sections. """ - +import copy +from collections import OrderedDict from warnings import warn import numpy as np import pandas as pd from uncertainties import ufloat +import openmc from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .chain import REACTIONS from .reaction_rates import ReactionRates -from .helpers import ConstantFissionYieldHelper +from .helpers import ConstantFissionYieldHelper, SourceRateHelper, FluxTimesXSHelper valid_rxns = list(REACTIONS) valid_rxns.append('fission') - +def _distribute(items): + """Distribute items across MPI communicator + Parameters + ---------- + items : list + List of items of distribute + Returns + ------- + list + Items assigned to process that called + """ + min_size, extra = divmod(len(items), comm.size) + j = 0 + for i in range(comm.size): + chunk_size = min_size + int(i < extra) + if comm.rank == i: + return items[j:j + chunk_size] + j += chunk_size class FluxDepletionOperator(TransportOperator): """Depletion operator that uses a user-provided flux spectrum and one-group @@ -98,57 +117,76 @@ class FluxDepletionOperator(TransportOperator): reduce_chain=False, reduce_chain_level=None, fission_yield_opts=None): - super().__init__(chain_file, fission_q, 0.0, prev_results) - self.round_number = False - self.flux_spectra = flux_spectra - self._init_nuclides = nuclides - self._volume = volume - - # Reduce the chain to only those nuclides present - if reduce_chain: - init_nuc_names = set(nuclides.keys()) - self.chain = self.chain.reduce(init_nuc_names, reduce_chain_level) - # Validate nuclides and micro-xs parameters check_type('nuclides', nuclides, dict, str) check_type('micro_xs', micro_xs, pd.DataFrame) - self._micro_xs = micro_xs + self.cross_sections = micro_xs if keff is not None: check_type('keff', keff, tuple, float) keff = ufloat(keff) self._keff = keff + self.flux_spectra = flux_spectra + materials = self._consolidate_nuclides_to_material(nuclides, volume) - self._all_nuclides = self._get_all_nuclides_in_simulation() + diff_burnable_mats=False + # super().__init__(materials, diff_burnable_mats, chain_file, fission_q, dilute_initial, prev_results, helper_class_kwargs) - # TODO: add support for loading previous results + + ## this part goes to OpenMCOperator + super().__init__(chain_file, fission_q, 0.0, prev_results) + self.round_number = False + self.materials = materials + + # Reduce the chain to only those nuclides present + if reduce_chain: + init_nuclides = set() + for material in self.materials: + if not material.depletable: + continue + for name, _dens_percent, _dens_type in material.nuclides: + init_nuclides.add(name) + + self.chain = self.chain.reduce(init_nuclides, reduce_chain_level) + + if diff_burnable_mats: + ## to implement + self._differentiate_burnable_mats() # Determine which nuclides have cross section data # This nuclides variables contains every nuclides # for which there is an entry in the micro_xs parameter - self.nuclides_with_data = self._get_nuclides_with_data() + openmc.reset_auto_ids() + self.burnable_mats, volumes, all_nuclides = self._get_burnable_mats() + self._all_nuclides = all_nuclides + self.local_mats = _distribute(self.burnable_mats) + + self._mat_index_map = { + lm: self.burnable_mats.index(lm) for lm in self.local_mats} + + if self.prev_res is not None: + ## will be an abstract function for OpenMCOperator + self._load_previous_results() + + + self.nuclides_with_data = self._get_nuclides_with_data(self.cross_sections) # Select nuclides with data that are also in the chain self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides if nuc.name in self.nuclides_with_data] # Extract number densities from the geometry / previous depletion run - self._extract_number(['0'], - {'0': volume}, - self._all_nuclides, + self._extract_number(self.local_mats, + volumes, + all_nuclides, self.prev_res) # Create reaction rates array self.reaction_rates = ReactionRates( - ['0'], self._burnable_nucs, self.chain.reactions) + self.local_mats, self._burnable_nucs, self.chain.reactions) - # Select and create fission yield helper - fission_helper = ConstantFissionYieldHelper - fission_yield_opts = ( - {} if fission_yield_opts is None else fission_yield_opts) - self._yield_helper = fission_helper.from_operator( - self, **fission_yield_opts) + self._get_helper_classes(None, fission_yield_opts) def __call__(self, vec, source_rate): """Obtain the reaction rates @@ -173,14 +211,31 @@ class FluxDepletionOperator(TransportOperator): # Get all nuclides for which we will calculate reaction rates rxn_nuclides = self._get_reaction_nuclides() + self._rate_helper.nuclides = rxn_nuclides + self._normalization_helper.nuclides = rxn_nuclides + self._yield_helper.update_tally_nuclides(rxn_nuclides) + + # Use the flux spectra as a "source rate" + rates = self._calculate_reaction_rates(self.flux_spectra) + keff = self._keff + + op_result = OperatorResult(keff, rates) + return copy.deepcopy(op_result) + + def _calculate_reaction_rates(self, source_rate): rates = self.reaction_rates rates.fill(0.0) + rxn_nuclides = self._rate_helper.nuclides + # Form fast map nuc_ind = [rates.index_nuc[nuc] for nuc in rxn_nuclides] react_ind = [rates.index_rx[react] for react in self.chain.reactions] + self._normalization_helper.reset() + self._yield_helper.unpack() + # Store fission yield dictionaries fission_yields = [] @@ -190,45 +245,55 @@ class FluxDepletionOperator(TransportOperator): fission_ind = rates.index_rx.get("fission") - # Zero out reaction rates and nuclide numbers - number.fill(0.0) + for i, mat in enumerate(self.local_mats): + mat_index = self._mat_index_map[mat] - # Get new number densities - for nuc, i_nuc_results in zip(rxn_nuclides, nuc_ind): - number[i_nuc_results] = self.number[0, nuc] + # Zero out reaction rates and nuclide numbers + number.fill(0.0) - # Calculate macroscopic cross sections and store them in rates array - for nuc in rxn_nuclides: - density = self.number.get_atom_density('0', nuc) - for rxn in self.chain.reactions: - rates.set( - '0', - nuc, - rxn, - self._micro_xs[rxn, rxn] * density) + # Get new number densities + for nuc, i_nuc_results in zip(rxn_nuclides, nuc_ind): + number[i_nuc_results] = self.number[mat, nuc] + # Calculate macroscopic cross sections and store them in rates array + rxn_rates = self._rate_helper.get_material_rates( + mat_index, nuc_ind, react_ind) + + ## replace + #for nuc in rxn_nuclides: + # density = self.number.get_atom_density(i, nuc) + # for rxn in self.chain.reactions: + # rates.set( + # i, + # nuc, + # rxn, + # self.cross_sections[rxn, nuc] * density) + + # Compute fission yields for this material + fission_yields.append(self._yield_helper.weighted_yields(i)) + + # Accumulate energy from fission + if fission_ind is not None: + self._normalization_helper.update(rxn_rates[:, fission_ind]) + + # Divide by total number of atoms and store + # the reason we do this is based on the mathematical equation; + # in the equation, we multiply the depletion matrix by the nuclide + # vector. Since what we want is the depletion matrix, we need to + # divide the reaction rates by the number of atoms to get the right + # units. + rates[i] = self._rate_helper.divide_by_adens(number) + + rates *= self._normalization_helper.factor(source_rate) + ##replace # Get reaction rate in reactions/sec - rates *= self.flux_spectra + #rates *= self.flux_spectra - # Compute fission yields for this material - fission_yields.append(self._yield_helper.weighted_yields(0)) - - # Divide by total number of atoms and store - # the reason we do this is based on the mathematical equation; - # in the equation, we multiply the depletion matrix by the nuclide - # vector. Since what we want is the depletion matrix, we need to - # divide the reaction rates by the number of atoms to get the right - # units. - mask = np.nonzero(number) - results = rates[0] - for col in range(results.shape[1]): - results[mask, col] /= number[mask] - rates[0] = results # Store new fission yields on the chain self.chain.fission_yields = fission_yields - return OperatorResult(self._keff, rates) + return rates def initial_condition(self): """Performs final setup and returns initial condition. @@ -272,9 +337,11 @@ class FluxDepletionOperator(TransportOperator): All burnable materials in the geometry. """ nuc_list = self.number.burnable_nuclides - burn_list = ['0'] + burn_list = self.local_mats - volume = {'0': self._volume} + volume = {} + for i, mat in enumerate(burn_list): + volume[mat] = self.number.volume[i] # Combine volume dictionaries across processes volume_list = comm.allgather(volume) @@ -404,6 +471,54 @@ class FluxDepletionOperator(TransportOperator): # TODO Update densities on the Python side, otherwise the # summary.h5 file contains densities at the first time step + def _consolidate_nuclides_to_material(self, nuclides, volume): + """Puts nuclide list into an openmc.Materials object. + + """ + openmc.reset_auto_ids() + mat = openmc.Material() + for nuc, conc in nuclides.items(): + mat.add_nuclide(nuc, conc / 1e24) #convert to at/b-cm + + mat.volume = volume + mat.depleteable = True + + return openmc.Materials([mat]) + + def _get_helper_classes(self, reaction_rate_opts, fission_yield_opts): + """Get helper classes for calculating reation rates and fission yields""" + rates = self.reaction_rates + # Get classes to assit working with tallies + nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} + rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} + + + self._rate_helper = FluxTimesXSHelper(self.flux_spectra, self.cross_sections, self.reaction_rates.n_nuc, self.reaction_rates.n_react) + + self._rate_helper.nuc_ind_map = nuc_ind_map + self._rate_helper.rxn_ind_map = rxn_ind_map + # We'll need to find a way to update number as time goes on. + # perhaps in this classes version of _update_materials()? + self._rate_helper.number = self.number + + self._normalization_helper = SourceRateHelper() + + # Select and create fission yield helper + fission_helper = ConstantFissionYieldHelper + fission_yield_opts = ( + {} if fission_yield_opts is None else fission_yield_opts) + self._yield_helper = fission_helper.from_operator( + self, **fission_yield_opts) + + + def _load_previous_results(): + """Load in results from a previous depletion calculation.""" + pass + + def _differentiate_burnable_materials(): + """Assign distribmats for each burnable material""" + pass + def _get_reaction_nuclides(self): """Determine nuclides that should have reaction rates @@ -421,10 +536,12 @@ class FluxDepletionOperator(TransportOperator): """ # Create the set of all nuclides in the decay chain in materials marked # for burning in which the number density is greater than zero. - nuc_set = set(self._all_nuclides).intersection(self.nuclides_with_data) - for nuc in nuc_set: - if not np.sum(self.number[:, nuc]) > 0.0: - nuc_set.remove(nuc) + nuc_set = set() + + for nuc in self.number.nuclides: + if nuc in self.nuclides_with_data: + if np.sum(self.number[:,nuc]) > 0.0: + nuc_set.add(nuc) # Communicate which nuclides have nonzeros to rank 0 if comm.rank == 0: @@ -445,31 +562,57 @@ class FluxDepletionOperator(TransportOperator): nuc_list = comm.bcast(nuc_list) return [nuc for nuc in nuc_list if nuc in self.chain] - def _get_all_nuclides_in_simulation(self): - """Determine nuclides that will show up in the depletion matrix. - This is the union of the nuclides provided by the user and - the nuclides present in the depletion chain. - + def _get_burnable_mats(self): + """Determine depletable materials, volumes, and nuclides Returns ------- - all_nuclides : list of str + burnable_mats : list of str + List of burnable material IDs + volume : OrderedDict of str to float + Volume of each material in [cm^3] + nuclides : list of str Nuclides in order of how they'll appear in the simulation. - """ - init_nuclides = sorted(self._init_nuclides.keys()) + burnable_mats = set() + model_nuclides = set() + volume = OrderedDict() + + self.heavy_metal = 0.0 + + # Iterate once through the geometry to get dictionaries + for mat in self.materials: + for nuclide in mat.get_nuclides(): + model_nuclides.add(nuclide) + if mat.depletable: + burnable_mats.add(str(mat.id)) + if mat.volume is None: + raise RuntimeError("Volume not specified for depletable " + "material with ID={}.".format(mat.id)) + volume[str(mat.id)] = mat.volume + self.heavy_metal += mat.fissionable_mass + + # Make sure there are burnable materials + if not burnable_mats: + raise RuntimeError( + "No depletable materials were found in the model.") + + # Sort the sets + burnable_mats = sorted(burnable_mats, key=int) + model_nuclides = sorted(model_nuclides) # Construct a global nuclide dictionary, burned first - all_nuclides = list(self.chain.nuclide_dict) - for nuc in init_nuclides: - if nuc not in all_nuclides: - all_nuclides.append(nuc) + nuclides = list(self.chain.nuclide_dict) + for nuc in model_nuclides: + if nuc not in nuclides: + nuclides.append(nuc) - return all_nuclides + return burnable_mats, volume, nuclides - def _get_nuclides_with_data(self): - """Finds nuclides with cross section data""" - return set(self._micro_xs.index) + def _get_nuclides_with_data(self, cross_sections): + """Finds nuclides with cross section data + """ + return set(cross_sections.index) def _extract_number(self, local_mats, volume, nuclides, prev_res=None): @@ -489,17 +632,30 @@ class FluxDepletionOperator(TransportOperator): """ self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) + if self.dilute_initial != 0.0: + for nuc in self._burnable_nucs: + self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) + # Now extract and store the number densities # From the geometry if no previous depletion results if prev_res is None: - for nuclide in nuclides: - if nuclide in self._init_nuclides: - self.number.set_atom_density( - '0', nuclide, self._init_nuclides[nuclide]) - elif nuclide not in self._burnable_nucs: - self.number.set_atom_density('0', nuclide, 0) - + for mat in self.materials: + if str(mat.id) in local_mats: + self._set_number_from_mat(mat) # Else from previous depletion results else: raise RuntimeError( "Loading from previous results not yet supported") + + def _set_number_from_mat(self, mat): + """Extracts material and number densities from openmc.Material + Parameters + ---------- + mat : openmc.Material + The material to read from + """ + mat_id = str(mat.id) + + for nuclide, atom_per_bcm in mat.get_nuclide_atom_densities().items(): + atom_per_cc = atom_per_bcm * 1.0e24 + self.number.set_atom_density(mat_id, nuclide, atom_per_cc) diff --git a/tests/regression_tests/deplete_no_transport/test_reference.h5 b/tests/regression_tests/deplete_no_transport/test_reference.h5 index e4fbf5029d56bd9169e688fb477bc7e6c0688d9e..55675f9d082cd29b63a028131888b31f384f5418 100644 GIT binary patch delta 77 zcmV-T0J8t+mICOO06j`1e;nL|!EK(X@L$Vel>G j7(O39_LDJ-8 Date: Wed, 13 Jul 2022 17:17:26 -0500 Subject: [PATCH 0575/2654] move reusable code to new parent class; 2nd pass; some minor docstring edits --- openmc/deplete/openmc_operator.py | 167 +++++++++++++---------------- openmc/deplete/operator.py | 168 +++++++++++++----------------- 2 files changed, 143 insertions(+), 192 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 303a5208f..a2296d88a 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -1,9 +1,6 @@ """OpenMC transport operator -This module implements a transport operator for OpenMC so that it can be used by -depletion integrators. The implementation makes use of the Python bindings to -OpenMC's C API so that reading tally results and updating material number -densities is all done in-memory instead of through the filesystem. +This module implements functions used by both OpenMC transport operators as well as pure depletion operators. """ @@ -11,9 +8,9 @@ import copy from abc import abstractmethod from collections import OrderedDict import os -from warnings import warn import numpy as np +from uncertainties import ufloat import openmc from openmc.exceptions import DataError @@ -22,10 +19,6 @@ from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .reaction_rates import ReactionRates from .results import Results -from .helpers import ( - DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper, - FissionYieldCutoffHelper, AveragedFissionYieldHelper, EnergyScoreHelper, - SourceRateHelper, FluxCollapseHelper) __all__ = ["OpenMCOperator", "OperatorResult"] @@ -124,45 +117,61 @@ class OpenMCOperator(TransportOperator): depletion operation is complete. Defaults to clearing the library. """ - ## modify - def __init__(self, chain_file=None, fission_q=None, dilute_initial=0.0, prev_results=None): + def __init__(self, materials=None, cross_sections=None, chain_file=None, prev_results=None, diff_burnable_mats=False, normalization_mode=None, fission_q=None, dilute_initial=0.0, fission_yield_mode=None, fission_yield_opts=None, + reaction_rate_mode=None, reaction_rate_opts=None, + reduce_chain=False, reduce_chain_level=None): super().__init__(chain_file, fission_q, dilute_initial, prev_results) + self.round_number=False + self.materials = materials + self.cross_sections = cross_sections - ## clear, but we must keep the method - def __call__(self, vec, source_rate): - """Runs a simulation. + # Reduce the chain to only those nuclides present + if reduce_chain: + init_nuclides = set() + for material in self.materials: + if not material.depletable: + continue + for name, _dens_percent, _dens_type in material.nuclides: + init_nuclides.add(name) - Simulation will abort under the following circumstances: + self.chain = self.chain.reduce(init_nuclides, reduce_chain_level) - 1) No energy is computed using OpenMC tallies. + if diff_burnable_mats: + self._differentiate_burnable_mats() - Parameters - ---------- - vec : list of numpy.ndarray - Total atoms to be used in function. - source_rate : float - Power in [W] or source rate in [neutron/sec] + # Determine which nuclides have cross section data + # This nuclides variables contains every nuclides + # for which there is an entry in the micro_xs parameter + openmc.reset_auto_ids() + self.burnable_mats, volumes, all_nuclides = self._get_burnable_mats() + self.local_mats = _distribute(self.burnable_mats) - Returns - ------- - openmc.deplete.OperatorResult - Eigenvalue and reaction rates resulting from transport operator + self._mat_index_map = { + lm: self.burnable_mats.index(lm) for lm in self.local_mats} - """ + if self.prev_res is not None: + self._load_previous_results() - ## clear, but must keep the method - def write_bos_data(step): - """Write a state-point file with beginning of step data - Parameters - ---------- - step : int - Current depletion step including restarts - """ - pass + self.nuclides_with_data = self._get_nuclides_with_data(self.cross_sections) + + # Select nuclides with data that are also in the chain + self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides + if nuc.name in self.nuclides_with_data] + + # Extract number densities from the geometry / previous depletion run + self._extract_number(self.local_mats, + volumes, + all_nuclides, + self.prev_res) + + # Create reaction rates array + self.reaction_rates = ReactionRates( + self.local_mats, self._burnable_nucs, self.chain.reactions) + + self._get_helper_classes(reaction_rate_mode, reaction_rate_opts, normalization_mode, fission_yield_mode, fission_yield_opts) - ## keep def _get_burnable_mats(self): """Determine depletable materials, volumes, and nuclides @@ -212,8 +221,7 @@ class OpenMCOperator(TransportOperator): return burnable_mats, volume, nuclides - ## keep - def _extract_number(self, local_mats, volume, nuclides, prev_res=None): + def _extract_number(self, local_mats, volume, all_nuclides, prev_res=None): """Construct AtomNumber using geometry Parameters @@ -222,13 +230,13 @@ class OpenMCOperator(TransportOperator): Material IDs to be managed by this process volume : OrderedDict of str to float Volumes for the above materials in [cm^3] - nuclides : list of str + all_nuclides : list of str Nuclides to be used in the simulation. prev_res : Results, optional Results from a previous depletion calculation """ - self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) + self.number = AtomNumber(local_mats, all_nuclides, volume, len(self.chain)) if self.dilute_initial != 0.0: for nuc in self._burnable_nucs: @@ -296,7 +304,6 @@ class OpenMCOperator(TransportOperator): self.number.set_atom_density(mat_id, nuclide, atom_per_cc) - ## keep, will need to modify def initial_condition(self, materials): """Performs final setup and returns initial condition. @@ -321,50 +328,11 @@ class OpenMCOperator(TransportOperator): # Return number density vector return list(self.number.get_mat_slice(np.s_[:])) - ## keep? there is a non-removable part of this - ## that needs the openmc c executable + @abstractmethod def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" - for rank in range(comm.size): - number_i = comm.bcast(self.number, root=rank) - - for mat in number_i.materials: - nuclides = [] - densities = [] - for nuc in number_i.nuclides: - if nuc in self.nuclides_with_data: - val = 1.0e-24 * number_i.get_atom_density(mat, nuc) - - # If nuclide is zero, do not add to the problem. - if val > 0.0: - if self.round_number: - val_magnitude = np.floor(np.log10(val)) - val_scaled = val / 10**val_magnitude - val_round = round(val_scaled, 8) - - val = val_round * 10**val_magnitude - - nuclides.append(nuc) - densities.append(val) - else: - # Only output warnings if values are significantly - # negative. CRAM does not guarantee positive values. - if val < -1.0e-21: - print("WARNING: nuclide ", nuc, " in material ", mat, - " is negative (density = ", val, " at/barn-cm)") - number_i[mat, nuc] = 0.0 - - # Update densities on C API side - mat_internal = openmc.lib.materials[int(mat)] - mat_internal.set_densities(nuclides, densities) - - #TODO Update densities on the Python side, otherwise the - # summary.h5 file contains densities at the first time step - - ## keep, but rename and modify docstring - ## get_tally_nuclides - def _get_tally_nuclides(self): + def _get_reaction_nuclides(self): """Determine nuclides that should be tallied for reaction rates. This method returns a list of all nuclides that have neutron data and @@ -407,12 +375,6 @@ class OpenMCOperator(TransportOperator): nuc_list = comm.bcast(nuc_list) return [nuc for nuc in nuc_list if nuc in self.chain] - ## modify - ## the tally-specific methods - ## for the normalization and fission helper classes - ## will already work with the current implementation. - ## For transport-less depletion, we'll need to write - ## a new ReactionRateHelper def _calculate_reaction_rates(self, source_rate): """Unpack tallies from OpenMC and return an operator result @@ -434,11 +396,11 @@ class OpenMCOperator(TransportOperator): rates = self.reaction_rates rates.fill(0.0) - # Extract tally bins - nuclides = self._rate_helper.nuclides + # Extract reaction nuclides + rxn_nuclides = self._rate_helper.nuclides # Form fast map - nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides] + nuc_ind = [rates.index_nuc[nuc] for nuc in rxn_nuclides] react_ind = [rates.index_rx[react] for react in self.chain.reactions] # Keep track of energy produced from all reactions in eV per source @@ -464,7 +426,7 @@ class OpenMCOperator(TransportOperator): number.fill(0.0) # Get new number densities - for nuc, i_nuc_results in zip(nuclides, nuc_ind): + for nuc, i_nuc_results in zip(rxn_nuclides, nuc_ind): number[i_nuc_results] = self.number[mat, nuc] tally_rates = self._rate_helper.get_material_rates( @@ -488,11 +450,26 @@ class OpenMCOperator(TransportOperator): return rates + @abstractmethod - def _get_nuclides_with_data(self): + def _get_helper_classes(self, reaction_rate_mode, reaction_rate_opts, normalization_mode, fission_yield_mode, fission_yield_opts): + """Create the ``_rate_helper``, ``normalization_helper``, and + ``_yield_helper`` attributes""" + + @abstractmethod + def _load_previous_results(self): + """Load reuslts from a previous depletion simulation""" + + @abstractmethod + def _get_nuclides_with_data(self, cross_sections): """Find nuclides with cross section data""" - ## Keep + @abstractmethod + def _differentiate_burnable_mats(self): + """Assign distribmats for each burnable material + + """ + def get_results_info(self): """Returns volume list, material lists, and nuc lists. diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 665de1999..2770494ba 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -210,8 +210,6 @@ class Operator(OpenMCOperator): if fission_q is not None: warn("Fission Q dictionary will not be used") fission_q = None - super().__init__(chain_file, fission_q, dilute_initial, prev_results) - self.round_number = False self.model = model self.settings = model.settings self.geometry = model.geometry @@ -221,103 +219,15 @@ class Operator(OpenMCOperator): model.materials = openmc.Materials( model.geometry.get_all_materials().values() ) - self.materials = model.materials self.cleanup_when_done = True - # Reduce the chain before we create more materials - if reduce_chain: - all_isotopes = set() - for material in self.materials: - if not material.depletable: - continue - for name, _dens_percent, _dens_type in material.nuclides: - all_isotopes.add(name) - self.chain = self.chain.reduce(all_isotopes, reduce_chain_level) - - # Differentiate burnable materials with multiple instances - if diff_burnable_mats: - self._differentiate_burnable_mats() - self.materials = openmc.Materials( - model.geometry.get_all_materials().values() - ) - - # Clear out OpenMC, create task lists, distribute - openmc.reset_auto_ids() - self.burnable_mats, volume, nuclides = super()._get_burnable_mats() - self.local_mats = _distribute(self.burnable_mats) - - # Generate map from local materials => material index - self._mat_index_map = { - lm: self.burnable_mats.index(lm) for lm in self.local_mats} - - if self.prev_res is not None: - # Reload volumes into geometry - prev_results[-1].transfer_volumes(self.model) - - # Store previous results in operator - # Distribute reaction rates according to those tracked - # on this process - if comm.size == 1: - self.prev_res = prev_results - else: - self.prev_res = Results() - mat_indexes = _distribute(range(len(self.burnable_mats))) - for res_obj in prev_results: - new_res = res_obj.distribute(self.local_mats, mat_indexes) - self.prev_res.append(new_res) - - # Determine which nuclides have incident neutron data - self.nuclides_with_data = self._get_nuclides_with_data(cross_sections) - - # Select nuclides with data that are also in the chain - self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides - if nuc.name in self.nuclides_with_data] - - # Extract number densities from the geometry / previous depletion run - super()._extract_number(self.local_mats, volume, nuclides, self.prev_res) - - # Create reaction rates array - self.reaction_rates = ReactionRates( - self.local_mats, self._burnable_nucs, self.chain.reactions) - - # Get classes to assist working with tallies - if reaction_rate_mode == "direct": - self._rate_helper = DirectReactionRateHelper( - self.reaction_rates.n_nuc, self.reaction_rates.n_react) - elif reaction_rate_mode == "flux": - if reaction_rate_opts is None: - reaction_rate_opts = {} - - # Ensure energy group boundaries were specified - if 'energies' not in reaction_rate_opts: - raise ValueError( - "Energy group boundaries must be specified in the " - "reaction_rate_opts argument when reaction_rate_mode is" - "set to 'flux'.") - - self._rate_helper = FluxCollapseHelper( - self.reaction_rates.n_nuc, - self.reaction_rates.n_react, - **reaction_rate_opts - ) - else: - raise ValueError("Invalid reaction rate mode.") - - if normalization_mode == "fission-q": - self._normalization_helper = ChainFissionHelper() - elif normalization_mode == "energy-deposition": - score = "heating" if self.settings.photon_transport else "heating-local" - self._normalization_helper = EnergyScoreHelper(score) - else: - self._normalization_helper = SourceRateHelper() - - # Select and create fission yield helper - fission_helper = self._fission_helpers[fission_yield_mode] - fission_yield_opts = ( - {} if fission_yield_opts is None else fission_yield_opts) - self._yield_helper = fission_helper.from_operator( - self, **fission_yield_opts) + super().__init__(model.materials, cross_sections, chain_file, prev_results, + diff_burnable_mats, normalization_mode, + fission_q, dilute_initial, + fission_yield_mode, fission_yield_opts, + reaction_rate_mode, reaction_rate_opts, + reduce_chain, reduce_chain_level) def __call__(self, vec, source_rate): """Runs a simulation. @@ -357,11 +267,12 @@ class Operator(OpenMCOperator): openmc.reset_auto_ids() # Update tally nuclides data in preparation for transport solve - nuclides = super()._get_tally_nuclides() + nuclides = self._get_reaction_nuclides() self._rate_helper.nuclides = nuclides self._normalization_helper.nuclides = nuclides self._yield_helper.update_tally_nuclides(nuclides) + # Run OpenMC openmc.lib.run() openmc.lib.reset_timers() @@ -416,6 +327,10 @@ class Operator(OpenMCOperator): cell.fill = [mat.clone() for i in range(cell.num_instances)] + self.materials = openmc.Materials( + model.geometry.get_all_materials().values() + ) + def initial_condition(self): """Performs final setup and returns initial condition. @@ -513,3 +428,62 @@ class Operator(OpenMCOperator): nuclides.add(name) return nuclides + + def _load_previous_results(self): + """Load reuslts from a previous depletion simulation""" + # Reload volumes into geometry + prev_results[-1].transfer_volumes(self.model) + + # Store previous results in operator + # Distribute reaction rates according to those tracked + # on this process + if comm.size == 1: + self.prev_res = prev_results + else: + self.prev_res = Results() + mat_indexes = _distribute(range(len(self.burnable_mats))) + for res_obj in prev_results: + new_res = res_obj.distribute(self.local_mats, mat_indexes) + self.prev_res.append(new_res) + + def _get_helper_classes(self, reaction_rate_mode, reaction_rate_opts, normalization_mode, fission_yield_mode, fission_yield_opts): + """Create the ``_rate_helper``, ``normalization_helper``, and + ``_yield_helper`` attributes""" + # Get classes to assist working with tallies + if reaction_rate_mode == "direct": + self._rate_helper = DirectReactionRateHelper( + self.reaction_rates.n_nuc, self.reaction_rates.n_react) + elif reaction_rate_mode == "flux": + if reaction_rate_opts is None: + reaction_rate_opts = {} + + # Ensure energy group boundaries were specified + if 'energies' not in reaction_rate_opts: + raise ValueError( + "Energy group boundaries must be specified in the " + "reaction_rate_opts argument when reaction_rate_mode is" + "set to 'flux'.") + + self._rate_helper = FluxCollapseHelper( + self.reaction_rates.n_nuc, + self.reaction_rates.n_react, + **reaction_rate_opts + ) + else: + raise ValueError("Invalid reaction rate mode.") + + if normalization_mode == "fission-q": + self._normalization_helper = ChainFissionHelper() + elif normalization_mode == "energy-deposition": + score = "heating" if self.settings.photon_transport else "heating-local" + self._normalization_helper = EnergyScoreHelper(score) + else: + self._normalization_helper = SourceRateHelper() + + # Select and create fission yield helper + fission_helper = self._fission_helpers[fission_yield_mode] + fission_yield_opts = ( + {} if fission_yield_opts is None else fission_yield_opts) + self._yield_helper = fission_helper.from_operator( + self, **fission_yield_opts) + From 227c4e330fa2a339afa9cb3e5fb5f536683f3689 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 14 Jul 2022 09:36:17 +0100 Subject: [PATCH 0576/2654] improved doc strings added checks --- openmc/universe.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 2fd931506..06807bab3 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -12,9 +12,12 @@ import numpy as np import openmc import openmc.checkvalue as cv + from ._xml import get_text +from .checkvalue import check_type, check_value from .mixin import IDManagerMixin from .plots import _SVG_COLORS +from .surface import _BOUNDARY_TYPES class UniverseBase(ABC, IDManagerMixin): @@ -724,13 +727,17 @@ class DAGMCUniverse(UniverseBase): made from siz planes (box). boundary_type : str Boundary condition that defines the behavior for particles hitting - the surface. Defaults to vacuum boundary condition. Passed into + the surface. Defaults to vacuum boundary condition. Passed into the + surface construction. Returns ------- openmc.Region Region instance """ + check_type('boundary type', boundary_type, str) + check_value('boundary type', boundary_type, _BOUNDARY_TYPES) + bounding_box = self.bounding_box if bounded_type == 'sphere': @@ -753,6 +760,10 @@ class DAGMCUniverse(UniverseBase): return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z def bounded_universe(self, **kwargs): + """Returns an openmc.Universe filled with the DAGMCUniverse and bounded + with a cell. Defaults to a box cell with a vacuum surface. kwargs are + passed directly to DAGMCUniverse.bounding_region()""" + bounding_cell = openmc.Cell(fill=self, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) From 28e203c8286acd83ccd97ce23d4c8e19b4ceb559 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 14 Jul 2022 15:10:27 +0100 Subject: [PATCH 0577/2654] typos fixed in review by @pshriwise Co-authored-by: Patrick Shriwise --- openmc/universe.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 06807bab3..7ecf489ce 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -724,7 +724,7 @@ class DAGMCUniverse(UniverseBase): bounded_type : str The type of bounding surface(s) to use when constructing the region. Options include a single spherical surface (sphere) or a rectangle - made from siz planes (box). + made from six planes (box). boundary_type : str Boundary condition that defines the behavior for particles hitting the surface. Defaults to vacuum boundary condition. Passed into the @@ -760,7 +760,7 @@ class DAGMCUniverse(UniverseBase): return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z def bounded_universe(self, **kwargs): - """Returns an openmc.Universe filled with the DAGMCUniverse and bounded + """Returns an openmc.Universe filled with this DAGMCUniverse and bounded with a cell. Defaults to a box cell with a vacuum surface. kwargs are passed directly to DAGMCUniverse.bounding_region()""" From 839b862d5645be785fd1f79dc6c3ba3f19e39b9e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 14 Jul 2022 15:15:04 +0100 Subject: [PATCH 0578/2654] added type value check for bounded type --- openmc/universe.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/universe.py b/openmc/universe.py index 7ecf489ce..e46d4d027 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -737,6 +737,8 @@ class DAGMCUniverse(UniverseBase): check_type('boundary type', boundary_type, str) check_value('boundary type', boundary_type, _BOUNDARY_TYPES) + check_type('bounded type', bounded_type, str) + check_value('bounded type', bounded_type, ('box', 'sphere')) bounding_box = self.bounding_box From 4c62517b1aa4cbc4b1c742c97e39473551be4682 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 14 Jul 2022 16:50:33 +0100 Subject: [PATCH 0579/2654] added test to check bounded_universe is usable in model (should fail) --- tests/regression_tests/dagmc/universes/test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index f6964857d..7abd80ef7 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -46,6 +46,13 @@ class DAGMCUniverseTest(PyAPITestHarness): # create the DAGMC universe pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True) + # creates another DAGMC universe, this time with within a bounded cell + bound_pincell_cell = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe() + # uses the bound_dag_cell as the root argument to test the type checks in openmc.Geometry + bound_pincell_geometry = openmc.Geometry(root=[bound_pincell_cell]) + # assigns the bound_dag_geometry to the model to test the type checks in model.Geometry setter + model.Geometry = bound_pincell_geometry + # checks that the bounding box is calculated correctly bounding_box = pincell_univ.bounding_box assert bounding_box[0].tolist() == [-25., -25., -25.] From 3d091a6cfbdb24242886e7a8d076852b8b085d4d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 14 Jul 2022 16:51:22 +0100 Subject: [PATCH 0580/2654] returning Cell instead of Universe --- openmc/universe.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index e46d4d027..9931724fb 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -762,12 +762,18 @@ class DAGMCUniverse(UniverseBase): return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z def bounded_universe(self, **kwargs): - """Returns an openmc.Universe filled with this DAGMCUniverse and bounded - with a cell. Defaults to a box cell with a vacuum surface. kwargs are - passed directly to DAGMCUniverse.bounding_region()""" + """Returns an openmc.Cell that bounds the DAGMCUniverse and is filled + with the DAGMCUniverse. Defaults to a box cell with a vacuum surface. + kwargs are passed directly to DAGMCUniverse.bounding_region() + + Returns + ------- + openmc.Cell + cell filled with the DAGMCUniverse + """ bounding_cell = openmc.Cell(fill=self, region=self.bounding_region(**kwargs)) - return openmc.Universe(cells=[bounding_cell]) + return bounding_cell @classmethod def from_hdf5(cls, group): From c3e60da1b9f2c04545200e8d5f16360304c166ca Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 14 Jul 2022 16:55:26 +0100 Subject: [PATCH 0581/2654] testing and returing openmc.Universe --- openmc/universe.py | 12 ++++++------ tests/regression_tests/dagmc/universes/test.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 9931724fb..811b27b31 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -762,18 +762,18 @@ class DAGMCUniverse(UniverseBase): return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z def bounded_universe(self, **kwargs): - """Returns an openmc.Cell that bounds the DAGMCUniverse and is filled - with the DAGMCUniverse. Defaults to a box cell with a vacuum surface. - kwargs are passed directly to DAGMCUniverse.bounding_region() + """Returns an openmc.Universe filled with this DAGMCUniverse and bounded + with a cell. Defaults to a box cell with a vacuum surface. kwargs are + passed directly to DAGMCUniverse.bounding_region() Returns ------- - openmc.Cell - cell filled with the DAGMCUniverse + openmc.Universe + Universe instance """ bounding_cell = openmc.Cell(fill=self, region=self.bounding_region(**kwargs)) - return bounding_cell + return openmc.Universe(cells=[bounding_cell]) @classmethod def from_hdf5(cls, group): diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 7abd80ef7..f2eb3882f 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -47,9 +47,9 @@ class DAGMCUniverseTest(PyAPITestHarness): pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True) # creates another DAGMC universe, this time with within a bounded cell - bound_pincell_cell = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe() + bound_pincell_universe = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe() # uses the bound_dag_cell as the root argument to test the type checks in openmc.Geometry - bound_pincell_geometry = openmc.Geometry(root=[bound_pincell_cell]) + bound_pincell_geometry = openmc.Geometry(root=bound_pincell_universe) # assigns the bound_dag_geometry to the model to test the type checks in model.Geometry setter model.Geometry = bound_pincell_geometry From 34e4a5efd12b8adc21ae9c3bb83fc073fc95df71 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 14 Jul 2022 18:06:07 +0100 Subject: [PATCH 0582/2654] setting auto_geom_ids to true for bounded universe --- openmc/universe.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 811b27b31..989b50c73 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -761,10 +761,18 @@ class DAGMCUniverse(UniverseBase): return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z - def bounded_universe(self, **kwargs): + def bounded_universe(self, auto_geom_ids=True, **kwargs): """Returns an openmc.Universe filled with this DAGMCUniverse and bounded - with a cell. Defaults to a box cell with a vacuum surface. kwargs are - passed directly to DAGMCUniverse.bounding_region() + with a cell. Defaults to a box cell with a vacuum surface however this + can be changed using the kwargs which are passed directly to + DAGMCUniverse.bounding_region(). + + Parameters + ---------- + auto_geom_ids : bool + Set IDs automatically on initialization (True) or report overlaps + in ID space between CSG and DAGMC (False). Defaults to True to avoid + overlapping ID numbers between the CSG and DAGMC geometry ID numbers Returns ------- @@ -772,6 +780,7 @@ class DAGMCUniverse(UniverseBase): Universe instance """ + self.auto_geom_ids = auto_geom_ids bounding_cell = openmc.Cell(fill=self, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) From 6ff164131c12db9c9b7c3d79a93095593e29c9d9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 12:53:41 -0500 Subject: [PATCH 0583/2654] clean up docstrings, function ordering --- openmc/deplete/openmc_operator.py | 141 +++++++++---- openmc/deplete/operator.py | 332 +++++++++++++++--------------- 2 files changed, 264 insertions(+), 209 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index a2296d88a..0a64c6fee 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -7,7 +7,6 @@ This module implements functions used by both OpenMC transport operators as well import copy from abc import abstractmethod from collections import OrderedDict -import os import numpy as np from uncertainties import ufloat @@ -18,8 +17,6 @@ from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .reaction_rates import ReactionRates -from .results import Results - __all__ = ["OpenMCOperator", "OperatorResult"] @@ -47,16 +44,11 @@ def _distribute(items): j += chunk_size class OpenMCOperator(TransportOperator): - """OpenMC transport operator for depletion. + """Abstrct class holding OpenMC-specific functions for running + depletion calculations. - Instances of this class can be used to perform depletion using OpenMC as the - transport operator. Normally, a user needn't call methods of this class - directly. Instead, an instance of this class is passed to an integrator - class, such as :class:`openmc.deplete.CECMIntegrator`. - - .. versionchanged:: 0.13.0 - The geometry and settings parameters have been replaced with a - model parameter that takes a :class:`~openmc.model.Model` object + Specific classes for running couples transport-depleton calculations or + depletion-only calculations are implemented as subclasses of OpenMCOperator Parameters ---------- @@ -68,6 +60,12 @@ class OpenMCOperator(TransportOperator): Results from a previous depletion calculation. If this argument is specified, the depletion calculation will start from the latest state in the previous results. + diff_burnable_mats : bool, optional + Whether to differentiate burnable materials with multiple instances. + Volumes are divided equally from the original material volume. + Default: False. + normalization_mode : str + Indicate how reaction rates should be normalized. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only applicable @@ -77,6 +75,30 @@ class OpenMCOperator(TransportOperator): in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. Defaults to 1.0e3. + fission_yield_mode : str + Key indicating what fission product yield scheme to use. + fission_yield_opts : dict of str to option, optional + Optional arguments to pass to the helper determined by + ``fission_yield_mode``. Will be passed directly on to the + helper. Passing a value of None will use the defaults for + the associated helper. + reaction_rate_mode : str, optional + Indicate how one-group reaction rates should be calculated. + reaction_rate_opts : dict, optional + Keyword arguments that are passed to the reaction rate helper class. + reduce_chain : bool, optional + If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the + depletion chain up to ``reduce_chain_level``. Default is False. + + .. versionadded:: 0.12 + reduce_chain_level : int, optional + Depth of the search when reducing the depletion chain. Only used + if ``reduce_chain`` evaluates to true. The default value of + ``None`` implies no limit on the depth. + + .. versionadded:: 0.12 + + Attributes ---------- @@ -112,9 +134,6 @@ class OpenMCOperator(TransportOperator): prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. - cleanup_when_done : bool - Whether to finalize and clear the shared library memory when the - depletion operation is complete. Defaults to clearing the library. """ def __init__(self, materials=None, cross_sections=None, chain_file=None, prev_results=None, diff_burnable_mats=False, normalization_mode=None, fission_q=None, dilute_initial=0.0, fission_yield_mode=None, fission_yield_opts=None, @@ -170,7 +189,11 @@ class OpenMCOperator(TransportOperator): self.reaction_rates = ReactionRates( self.local_mats, self._burnable_nucs, self.chain.reactions) - self._get_helper_classes(reaction_rate_mode, reaction_rate_opts, normalization_mode, fission_yield_mode, fission_yield_opts) + self._get_helper_classes(reaction_rate_mode, normalization_mode, fission_yield_mode, reaction_rate_opts, fission_yield_opts) + + @abstractmethod + def _differentiate_burnable_mats(self): + """Assign distribmats for each burnable material""" def _get_burnable_mats(self): """Determine depletable materials, volumes, and nuclides @@ -221,6 +244,15 @@ class OpenMCOperator(TransportOperator): return burnable_mats, volume, nuclides + + @abstractmethod + def _load_previous_results(self): + """Load reuslts from a previous depletion simulation""" + + @abstractmethod + def _get_nuclides_with_data(self, cross_sections): + """Find nuclides with cross section data""" + def _extract_number(self, local_mats, volume, all_nuclides, prev_res=None): """Construct AtomNumber using geometry @@ -304,12 +336,37 @@ class OpenMCOperator(TransportOperator): self.number.set_atom_density(mat_id, nuclide, atom_per_cc) + @abstractmethod + def _get_helper_classes(self, reaction_rate_mode, normalization_mode, fission_yield_mode, reaction_rate_opts, fission_yield_opts): + """Create the ``_rate_helper``, ``_normalization_helper``, and + ``_yield_helper`` objects. + + Parameters + ---------- + reaction_rate_mode : str + Indicates the subclass of :class:`ReactionRateHelper` to + instantiate. + normalization_mode : str + Indicates the subclass of :class:`NormalizationHelper` to + instatiate. + fission_yield_mode : str + Indicates the subclass of :class:`FissionYieldHelper` to instatiate. + reaction_rate_opts : dict + Keyword arguments that are passed to the :class:`ReactionRateHelper` + subclass. + fission_yield_opts : dict + Keyword arguments that are passed to the :class:`FissionYieldHelper` + subclass. + + """ + def initial_condition(self, materials): """Performs final setup and returns initial condition. Parameters ---------- - materials : ??? + materials : list of str + list of material IDs Returns ------- @@ -328,6 +385,22 @@ class OpenMCOperator(TransportOperator): # Return number density vector return list(self.number.get_mat_slice(np.s_[:])) + def _update_materials_and_nuclides(self, vec): + """Update the number density, material compositions, and nuclide + lists in helper objects""" + # Update the number densities regardless of the source rate + self.number.set_density(vec) + self._update_materials() + + # Prevent OpenMC from complaining about re-creating tallies + openmc.reset_auto_ids() + + # Update tally nuclides data in preparation for transport solve + nuclides = self._get_reaction_nuclides() + self._rate_helper.nuclides = nuclides + self._normalization_helper.nuclides = nuclides + self._yield_helper.update_tally_nuclides(nuclides) + @abstractmethod def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" @@ -335,16 +408,16 @@ class OpenMCOperator(TransportOperator): def _get_reaction_nuclides(self): """Determine nuclides that should be tallied for reaction rates. - This method returns a list of all nuclides that have neutron data and - are listed in the depletion chain. Technically, we should tally nuclides - that may not appear in the depletion chain because we still need to get - the fission reaction rate for these nuclides in order to normalize - power, but that is left as a future exercise. + This method returns a list of all nuclides that have cross section data + and are listed in the depletion chain. Technically, we should count + nuclides that may not appear in the depletion chain because we still + need to get the fission reaction rate for these nuclides in order to + normalize power, but that is left as a future exercise. Returns ------- list of str - Tally nuclides + Nuclides with reaction rates """ nuc_set = set() @@ -371,7 +444,7 @@ class OpenMCOperator(TransportOperator): else: nuc_list = None - # Store list of tally nuclides on each process + # Store list of nuclides on each process nuc_list = comm.bcast(nuc_list) return [nuc for nuc in nuc_list if nuc in self.chain] @@ -450,26 +523,6 @@ class OpenMCOperator(TransportOperator): return rates - - @abstractmethod - def _get_helper_classes(self, reaction_rate_mode, reaction_rate_opts, normalization_mode, fission_yield_mode, fission_yield_opts): - """Create the ``_rate_helper``, ``normalization_helper``, and - ``_yield_helper`` attributes""" - - @abstractmethod - def _load_previous_results(self): - """Load reuslts from a previous depletion simulation""" - - @abstractmethod - def _get_nuclides_with_data(self, cross_sections): - """Find nuclides with cross section data""" - - @abstractmethod - def _differentiate_burnable_mats(self): - """Assign distribmats for each burnable material - - """ - def get_results_info(self): """Returns volume list, material lists, and nuc lists. diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 2770494ba..30563623c 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -8,7 +8,6 @@ densities is all done in-memory instead of through the filesystem. """ import copy -from collections import OrderedDict import os from warnings import warn @@ -21,11 +20,9 @@ from openmc.data import DataLibrary from openmc.exceptions import DataError import openmc.lib from openmc.mpi import comm -from .abc import TransportOperator, OperatorResult -from .atom_number import AtomNumber +from .abc import OperatorResult from .chain import _find_chain_file from .openmc_operator import OpenMCOperator, _distribute -from .reaction_rates import ReactionRates from .results import Results from .helpers import ( DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper, @@ -229,81 +226,8 @@ class Operator(OpenMCOperator): reaction_rate_mode, reaction_rate_opts, reduce_chain, reduce_chain_level) - def __call__(self, vec, source_rate): - """Runs a simulation. - - Simulation will abort under the following circumstances: - - 1) No energy is computed using OpenMC tallies. - - Parameters - ---------- - vec : list of numpy.ndarray - Total atoms to be used in function. - source_rate : float - Power in [W] or source rate in [neutron/sec] - - Returns - ------- - openmc.deplete.OperatorResult - Eigenvalue and reaction rates resulting from transport operator - - """ - # Reset results in OpenMC - openmc.lib.reset() - - # Update the number densities regardless of the source rate - self.number.set_density(vec) - self._update_materials() - - # If the source rate is zero, return zero reaction rates without running - # a transport solve - if source_rate == 0.0: - rates = self.reaction_rates.copy() - rates.fill(0.0) - return OperatorResult(ufloat(0.0, 0.0), rates) - - # Prevent OpenMC from complaining about re-creating tallies - openmc.reset_auto_ids() - - # Update tally nuclides data in preparation for transport solve - nuclides = self._get_reaction_nuclides() - self._rate_helper.nuclides = nuclides - self._normalization_helper.nuclides = nuclides - self._yield_helper.update_tally_nuclides(nuclides) - - - # Run OpenMC - openmc.lib.run() - openmc.lib.reset_timers() - - # Extract results - rates = self._calculate_reaction_rates(source_rate) - - # Get k and uncertainty - keff = ufloat(*openmc.lib.keff()) - - op_result = OperatorResult(keff, rates) - - return copy.deepcopy(op_result) - - @staticmethod - def write_bos_data(step): - """Write a state-point file with beginning of step data - - Parameters - ---------- - step : int - Current depletion step including restarts - """ - openmc.lib.statepoint_write( - "openmc_simulation_n{}.h5".format(step), - write_source=False) - def _differentiate_burnable_mats(self): - """Assign distribmats for each burnable material - - """ + """Assign distribmats for each burnable material""" # Count the number of instances for each cell and material self.geometry.determine_paths(instances_only=True) @@ -331,6 +255,97 @@ class Operator(OpenMCOperator): model.geometry.get_all_materials().values() ) + def _load_previous_results(self): + """Load results from a previous depletion simulation""" + # Reload volumes into geometry + prev_results[-1].transfer_volumes(self.model) + + # Store previous results in operator + # Distribute reaction rates according to those tracked + # on this process + if comm.size == 1: + self.prev_res = prev_results + else: + self.prev_res = Results() + mat_indexes = _distribute(range(len(self.burnable_mats))) + for res_obj in prev_results: + new_res = res_obj.distribute(self.local_mats, mat_indexes) + self.prev_res.append(new_res) + + def _get_nuclides_with_data(self, cross_sections): + """Loads cross_sections.xml file to find nuclides with neutron data""" + nuclides = set() + data_lib = DataLibrary.from_xml(cross_sections) + for library in data_lib.libraries: + if library['type'] != 'neutron': + continue + for name in library['materials']: + if name not in nuclides: + nuclides.add(name) + + return nuclides + + def _get_helper_classes(self, reaction_rate_mode, normalization_mode, fission_yield_mode, + reaction_rate_opts, fission_yield_opts): + """Create the ``_rate_helper``, ``_normalization_helper``, and + ``_yield_helper`` objects. + + Parameters + ---------- + reaction_rate_mode : str + Indicates the subclass of :class:`ReactionRateHelper` to + instantiate. + normalization_mode : str + Indicates the subclass of :class:`NormalizationHelper` to + instatiate. + fission_yield_mode : str + Indicates the subclass of :class:`FissionYieldHelper` to instatiate. + reaction_rate_opts : dict + Keyword arguments that are passed to the :class:`ReactionRateHelper` + subclass. + fission_yield_opts : dict + Keyword arguments that are passed to the :class:`FissionYieldHelper` + subclass. + + """ + # Get classes to assist working with tallies + if reaction_rate_mode == "direct": + self._rate_helper = DirectReactionRateHelper( + self.reaction_rates.n_nuc, self.reaction_rates.n_react) + elif reaction_rate_mode == "flux": + if reaction_rate_opts is None: + reaction_rate_opts = {} + + # Ensure energy group boundaries were specified + if 'energies' not in reaction_rate_opts: + raise ValueError( + "Energy group boundaries must be specified in the " + "reaction_rate_opts argument when reaction_rate_mode is" + "set to 'flux'.") + + self._rate_helper = FluxCollapseHelper( + self.reaction_rates.n_nuc, + self.reaction_rates.n_react, + **reaction_rate_opts + ) + else: + raise ValueError("Invalid reaction rate mode.") + + if normalization_mode == "fission-q": + self._normalization_helper = ChainFissionHelper() + elif normalization_mode == "energy-deposition": + score = "heating" if self.settings.photon_transport else "heating-local" + self._normalization_helper = EnergyScoreHelper(score) + else: + self._normalization_helper = SourceRateHelper() + + # Select and create fission yield helper + fission_helper = self._fission_helpers[fission_yield_mode] + fission_yield_opts = ( + {} if fission_yield_opts is None else fission_yield_opts) + self._yield_helper = fission_helper.from_operator( + self, **fission_yield_opts) + def initial_condition(self): """Performs final setup and returns initial condition. @@ -357,10 +372,66 @@ class Operator(OpenMCOperator): return super().initial_condition(materials) - def finalize(self): - """Finalize a depletion simulation and release resources.""" - if self.cleanup_when_done: - openmc.lib.finalize() + def _generate_materials_xml(self): + """Creates materials.xml from self.number. + + Due to uncertainty with how MPI interacts with OpenMC API, this + constructs the XML manually. The long term goal is to do this + through direct memory writing. + + """ + # Sort nuclides according to order in AtomNumber object + nuclides = list(self.number.nuclides) + for mat in self.materials: + mat._nuclides.sort(key=lambda x: nuclides.index(x[0])) + + self.materials.export_to_xml() + + def __call__(self, vec, source_rate): + """Runs a simulation. + + Simulation will abort under the following circumstances: + + 1) No energy is computed using OpenMC tallies. + + Parameters + ---------- + vec : list of numpy.ndarray + Total atoms to be used in function. + source_rate : float + Power in [W] or source rate in [neutron/sec] + + Returns + ------- + openmc.deplete.OperatorResult + Eigenvalue and reaction rates resulting from transport operator + + """ + # Reset results in OpenMC + openmc.lib.reset() + + self._update_materials_and_nuclides(vec) + + # If the source rate is zero, return zero reaction rates without running + # a transport solve + if source_rate == 0.0: + rates = self.reaction_rates.copy() + rates.fill(0.0) + return OperatorResult(ufloat(0.0, 0.0), rates) + + # Run OpenMC + openmc.lib.run() + openmc.lib.reset_timers() + + # Extract results + rates = self._calculate_reaction_rates(source_rate) + + # Get k and uncertainty + keff = ufloat(*openmc.lib.keff()) + + op_result = OperatorResult(keff, rates) + + return copy.deepcopy(op_result) def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" @@ -401,89 +472,20 @@ class Operator(OpenMCOperator): #TODO Update densities on the Python side, otherwise the # summary.h5 file contains densities at the first time step - def _generate_materials_xml(self): - """Creates materials.xml from self.number. - - Due to uncertainty with how MPI interacts with OpenMC API, this - constructs the XML manually. The long term goal is to do this - through direct memory writing. + @staticmethod + def write_bos_data(step): + """Write a state-point file with beginning of step data + Parameters + ---------- + step : int + Current depletion step including restarts """ - # Sort nuclides according to order in AtomNumber object - nuclides = list(self.number.nuclides) - for mat in self.materials: - mat._nuclides.sort(key=lambda x: nuclides.index(x[0])) - - self.materials.export_to_xml() - - def _get_nuclides_with_data(self, cross_sections): - """Loads cross_sections.xml file to find nuclides with neutron data""" - nuclides = set() - data_lib = DataLibrary.from_xml(cross_sections) - for library in data_lib.libraries: - if library['type'] != 'neutron': - continue - for name in library['materials']: - if name not in nuclides: - nuclides.add(name) - - return nuclides - - def _load_previous_results(self): - """Load reuslts from a previous depletion simulation""" - # Reload volumes into geometry - prev_results[-1].transfer_volumes(self.model) - - # Store previous results in operator - # Distribute reaction rates according to those tracked - # on this process - if comm.size == 1: - self.prev_res = prev_results - else: - self.prev_res = Results() - mat_indexes = _distribute(range(len(self.burnable_mats))) - for res_obj in prev_results: - new_res = res_obj.distribute(self.local_mats, mat_indexes) - self.prev_res.append(new_res) - - def _get_helper_classes(self, reaction_rate_mode, reaction_rate_opts, normalization_mode, fission_yield_mode, fission_yield_opts): - """Create the ``_rate_helper``, ``normalization_helper``, and - ``_yield_helper`` attributes""" - # Get classes to assist working with tallies - if reaction_rate_mode == "direct": - self._rate_helper = DirectReactionRateHelper( - self.reaction_rates.n_nuc, self.reaction_rates.n_react) - elif reaction_rate_mode == "flux": - if reaction_rate_opts is None: - reaction_rate_opts = {} - - # Ensure energy group boundaries were specified - if 'energies' not in reaction_rate_opts: - raise ValueError( - "Energy group boundaries must be specified in the " - "reaction_rate_opts argument when reaction_rate_mode is" - "set to 'flux'.") - - self._rate_helper = FluxCollapseHelper( - self.reaction_rates.n_nuc, - self.reaction_rates.n_react, - **reaction_rate_opts - ) - else: - raise ValueError("Invalid reaction rate mode.") - - if normalization_mode == "fission-q": - self._normalization_helper = ChainFissionHelper() - elif normalization_mode == "energy-deposition": - score = "heating" if self.settings.photon_transport else "heating-local" - self._normalization_helper = EnergyScoreHelper(score) - else: - self._normalization_helper = SourceRateHelper() - - # Select and create fission yield helper - fission_helper = self._fission_helpers[fission_yield_mode] - fission_yield_opts = ( - {} if fission_yield_opts is None else fission_yield_opts) - self._yield_helper = fission_helper.from_operator( - self, **fission_yield_opts) + openmc.lib.statepoint_write( + "openmc_simulation_n{}.h5".format(step), + write_source=False) + def finalize(self): + """Finalize a depletion simulation and release resources.""" + if self.cleanup_when_done: + openmc.lib.finalize() From 0a05f9dcb4320ae0c7dbd88547ca2bf9b35b68f5 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 12:54:51 -0500 Subject: [PATCH 0584/2654] pep8 fixes --- openmc/deplete/openmc_operator.py | 49 ++++++++++++++++++++++------- openmc/deplete/operator.py | 52 ++++++++++++++++++++++--------- 2 files changed, 75 insertions(+), 26 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 0a64c6fee..2f1b93294 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -43,6 +43,7 @@ def _distribute(items): return items[j:j + chunk_size] j += chunk_size + class OpenMCOperator(TransportOperator): """Abstrct class holding OpenMC-specific functions for running depletion calculations. @@ -136,12 +137,25 @@ class OpenMCOperator(TransportOperator): results are to be used. """ - def __init__(self, materials=None, cross_sections=None, chain_file=None, prev_results=None, diff_burnable_mats=False, normalization_mode=None, fission_q=None, dilute_initial=0.0, fission_yield_mode=None, fission_yield_opts=None, - reaction_rate_mode=None, reaction_rate_opts=None, - reduce_chain=False, reduce_chain_level=None): + def __init__( + self, + materials=None, + cross_sections=None, + chain_file=None, + prev_results=None, + diff_burnable_mats=False, + normalization_mode=None, + fission_q=None, + dilute_initial=0.0, + fission_yield_mode=None, + fission_yield_opts=None, + reaction_rate_mode=None, + reaction_rate_opts=None, + reduce_chain=False, + reduce_chain_level=None): super().__init__(chain_file, fission_q, dilute_initial, prev_results) - self.round_number=False + self.round_number = False self.materials = materials self.cross_sections = cross_sections @@ -172,8 +186,8 @@ class OpenMCOperator(TransportOperator): if self.prev_res is not None: self._load_previous_results() - - self.nuclides_with_data = self._get_nuclides_with_data(self.cross_sections) + self.nuclides_with_data = self._get_nuclides_with_data( + self.cross_sections) # Select nuclides with data that are also in the chain self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides @@ -189,7 +203,12 @@ class OpenMCOperator(TransportOperator): self.reaction_rates = ReactionRates( self.local_mats, self._burnable_nucs, self.chain.reactions) - self._get_helper_classes(reaction_rate_mode, normalization_mode, fission_yield_mode, reaction_rate_opts, fission_yield_opts) + self._get_helper_classes( + reaction_rate_mode, + normalization_mode, + fission_yield_mode, + reaction_rate_opts, + fission_yield_opts) @abstractmethod def _differentiate_burnable_mats(self): @@ -244,7 +263,6 @@ class OpenMCOperator(TransportOperator): return burnable_mats, volume, nuclides - @abstractmethod def _load_previous_results(self): """Load reuslts from a previous depletion simulation""" @@ -268,11 +286,14 @@ class OpenMCOperator(TransportOperator): Results from a previous depletion calculation """ - self.number = AtomNumber(local_mats, all_nuclides, volume, len(self.chain)) + self.number = AtomNumber( + local_mats, all_nuclides, volume, len( + self.chain)) if self.dilute_initial != 0.0: for nuc in self._burnable_nucs: - self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) + self.number.set_atom_density( + np.s_[:], nuc, self.dilute_initial) # Now extract and store the number densities # From the geometry if no previous depletion results @@ -337,7 +358,13 @@ class OpenMCOperator(TransportOperator): self.number.set_atom_density(mat_id, nuclide, atom_per_cc) @abstractmethod - def _get_helper_classes(self, reaction_rate_mode, normalization_mode, fission_yield_mode, reaction_rate_opts, fission_yield_opts): + def _get_helper_classes( + self, + reaction_rate_mode, + normalization_mode, + fission_yield_mode, + reaction_rate_opts, + fission_yield_opts): """Create the ``_rate_helper``, ``_normalization_helper``, and ``_yield_helper`` objects. diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 30563623c..7149cddad 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -32,6 +32,7 @@ from .helpers import ( __all__ = ["Operator", "OperatorResult"] + def _find_cross_sections(model): """Determine cross sections to use for depletion""" if model.materials and model.materials.cross_sections is not None: @@ -219,12 +220,21 @@ class Operator(OpenMCOperator): self.cleanup_when_done = True - super().__init__(model.materials, cross_sections, chain_file, prev_results, - diff_burnable_mats, normalization_mode, - fission_q, dilute_initial, - fission_yield_mode, fission_yield_opts, - reaction_rate_mode, reaction_rate_opts, - reduce_chain, reduce_chain_level) + super().__init__( + model.materials, + cross_sections, + chain_file, + prev_results, + diff_burnable_mats, + normalization_mode, + fission_q, + dilute_initial, + fission_yield_mode, + fission_yield_opts, + reaction_rate_mode, + reaction_rate_opts, + reduce_chain, + reduce_chain_level) def _differentiate_burnable_mats(self): """Assign distribmats for each burnable material""" @@ -240,7 +250,7 @@ class Operator(OpenMCOperator): for mat in distribmats: if mat.volume is None: raise RuntimeError("Volume not specified for depletable " - "material with ID={}.".format(mat.id)) + "material with ID={}.".format(mat.id)) mat.volume /= mat.num_instances if distribmats: @@ -252,8 +262,8 @@ class Operator(OpenMCOperator): for i in range(cell.num_instances)] self.materials = openmc.Materials( - model.geometry.get_all_materials().values() - ) + model.geometry.get_all_materials().values() + ) def _load_previous_results(self): """Load results from a previous depletion simulation""" @@ -285,8 +295,13 @@ class Operator(OpenMCOperator): return nuclides - def _get_helper_classes(self, reaction_rate_mode, normalization_mode, fission_yield_mode, - reaction_rate_opts, fission_yield_opts): + def _get_helper_classes( + self, + reaction_rate_mode, + normalization_mode, + fission_yield_mode, + reaction_rate_opts, + fission_yield_opts): """Create the ``_rate_helper``, ``_normalization_helper``, and ``_yield_helper`` objects. @@ -459,17 +474,24 @@ class Operator(OpenMCOperator): densities.append(val) else: # Only output warnings if values are significantly - # negative. CRAM does not guarantee positive values. + # negative. CRAM does not guarantee positive + # values. if val < -1.0e-21: - print("WARNING: nuclide ", nuc, " in material ", mat, - " is negative (density = ", val, " at/barn-cm)") + print( + "WARNING: nuclide ", + nuc, + " in material ", + mat, + " is negative (density = ", + val, + " at/barn-cm)") number_i[mat, nuc] = 0.0 # Update densities on C API side mat_internal = openmc.lib.materials[int(mat)] mat_internal.set_densities(nuclides, densities) - #TODO Update densities on the Python side, otherwise the + # TODO Update densities on the Python side, otherwise the # summary.h5 file contains densities at the first time step @staticmethod From 39472e286c34f01e1379c457beacf9dc84cd3abc Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 12:56:19 -0500 Subject: [PATCH 0585/2654] add OpenMCOperator to docs, fix referecne to TalliedFissionYieldHelper --- docs/source/pythonapi/deplete.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 9f7d8c447..11062cd87 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -204,6 +204,7 @@ prior to depleting materials :template: mycallable.rst abc.TransportOperator + openmc_operator.OpenMCOperator The following classes are abstract classes used to pass information from OpenMC simulations back on to the :class:`abc.TransportOperator` @@ -216,7 +217,7 @@ OpenMC simulations back on to the :class:`abc.TransportOperator` abc.NormalizationHelper abc.FissionYieldHelper abc.ReactionRateHelper - abc.TalliedFissionYieldHelper + helpers.TalliedFissionYieldHelper Custom integrators or depletion solvers can be developed by subclassing from the following abstract base classes: From 47344ca5cb18441e59910c734e2a7c5a88f6e7d1 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 14:22:33 -0500 Subject: [PATCH 0586/2654] spell checker typo fixes --- openmc/deplete/openmc_operator.py | 8 ++++---- openmc/deplete/operator.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 2f1b93294..6b7ff2920 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -45,10 +45,10 @@ def _distribute(items): class OpenMCOperator(TransportOperator): - """Abstrct class holding OpenMC-specific functions for running + """Abstract class holding OpenMC-specific functions for running depletion calculations. - Specific classes for running couples transport-depleton calculations or + Specific classes for running coupled transport-depletion calculations or depletion-only calculations are implemented as subclasses of OpenMCOperator Parameters @@ -265,7 +265,7 @@ class OpenMCOperator(TransportOperator): @abstractmethod def _load_previous_results(self): - """Load reuslts from a previous depletion simulation""" + """Load results from a previous depletion simulation""" @abstractmethod def _get_nuclides_with_data(self, cross_sections): @@ -375,7 +375,7 @@ class OpenMCOperator(TransportOperator): instantiate. normalization_mode : str Indicates the subclass of :class:`NormalizationHelper` to - instatiate. + instantiate. fission_yield_mode : str Indicates the subclass of :class:`FissionYieldHelper` to instatiate. reaction_rate_opts : dict diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 7149cddad..a86eb182f 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -314,7 +314,7 @@ class Operator(OpenMCOperator): Indicates the subclass of :class:`NormalizationHelper` to instatiate. fission_yield_mode : str - Indicates the subclass of :class:`FissionYieldHelper` to instatiate. + Indicates the subclass of :class:`FissionYieldHelper` to instantiate. reaction_rate_opts : dict Keyword arguments that are passed to the :class:`ReactionRateHelper` subclass. From 7b041114209c6073793ad8c33d87db7e07afda6b Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 14:23:11 -0500 Subject: [PATCH 0587/2654] add small blurb about OpenMCOperator; move TalliedFissionYieldHelper to different section --- docs/source/pythonapi/deplete.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 11062cd87..d09a665d8 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -188,6 +188,7 @@ total system energy. helpers.EnergyScoreHelper helpers.FissionYieldCutoffHelper helpers.FluxCollapseHelper + helpers.TalliedFissionYieldHelper Abstract Base Classes --------------------- @@ -204,7 +205,16 @@ prior to depleting materials :template: mycallable.rst abc.TransportOperator - openmc_operator.OpenMCOperator + +Methods common to OpenMC-specific implementations are stored in :class:`openmc_operator.OpenMCOperator` + +.. autosummary:: + :toctree: generated + :nosignatures: + :template: mycallable.rst + + abc.TransportOperator + The following classes are abstract classes used to pass information from OpenMC simulations back on to the :class:`abc.TransportOperator` @@ -217,7 +227,6 @@ OpenMC simulations back on to the :class:`abc.TransportOperator` abc.NormalizationHelper abc.FissionYieldHelper abc.ReactionRateHelper - helpers.TalliedFissionYieldHelper Custom integrators or depletion solvers can be developed by subclassing from the following abstract base classes: From 80fbcdcdf380e583c346d140f0fa8724b526cfa9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 15:14:35 -0500 Subject: [PATCH 0588/2654] move intermediate classes to their own section in the api docs --- docs/source/pythonapi/deplete.rst | 38 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index d09a665d8..e275f38f2 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -188,8 +188,36 @@ total system energy. helpers.EnergyScoreHelper helpers.FissionYieldCutoffHelper helpers.FluxCollapseHelper + + +Intermediate Classes +-------------------- + +Specific implementations of abstract base classes may utilize some of +the same methods and data structures. These methods and data are stored +in intermediate classes. + +Methods common to tally-based implementation of :class:`FissionYieldHelper` +are stored in :class:`helpers.TalliedFissionYieldHelper` + +.. autosummary:: + :toctree: generated + :nosignatures: + :template: myclass.rst + helpers.TalliedFissionYieldHelper +Methods common to OpenMC-specific implementations of :class:`TransportOperator` +are stored in :class:`openmc_operator.OpenMCOperator` + +.. autosummary:: + :toctree: generated + :nosignatures: + :template: mycallable.rst + + openmc_operator.OpenMCOperator + + Abstract Base Classes --------------------- @@ -206,16 +234,6 @@ prior to depleting materials abc.TransportOperator -Methods common to OpenMC-specific implementations are stored in :class:`openmc_operator.OpenMCOperator` - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: mycallable.rst - - abc.TransportOperator - - The following classes are abstract classes used to pass information from OpenMC simulations back on to the :class:`abc.TransportOperator` From 86caa75df49e63f4091ec6ac4423c8fe1dbc97a6 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 16:30:36 -0500 Subject: [PATCH 0589/2654] Add an alternate constructor using an openmc Model instance --- openmc/deplete/flux_operator.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 5e23ec203..014770551 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -105,6 +105,13 @@ class FluxDepletionOperator(TransportOperator): results are to be used. """ + # Alternate constructor using a full-fledges Model object + #def __init__(self, model, micro_xs, ...): + # ... + # mode.materials = openmc.Materials(model.geometry.get_all_materials().values()) + # super().__init__(model.materials, ...) + + def __init__(self, volume, nuclides, @@ -131,7 +138,7 @@ class FluxDepletionOperator(TransportOperator): materials = self._consolidate_nuclides_to_material(nuclides, volume) diff_burnable_mats=False - # super().__init__(materials, diff_burnable_mats, chain_file, fission_q, dilute_initial, prev_results, helper_class_kwargs) + # super().__init__(materials, cross_sections, diff_burnable_mats, chain_file, fission_q, dilute_initial, prev_results, helper_class_kwargs) ## this part goes to OpenMCOperator From 8bf4465b27ac32b2e1a7d152e93276620541d39d Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 16:50:05 -0500 Subject: [PATCH 0590/2654] docstring updates --- openmc/deplete/openmc_operator.py | 49 +++++++++++++++++++++---------- openmc/deplete/operator.py | 25 ++++++++++++++-- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 6b7ff2920..047a7f967 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -53,6 +53,11 @@ class OpenMCOperator(TransportOperator): Parameters ---------- + materials : openmc.Materials + List of all materials in the model + cross_sections : str or pandas.DataFrame + Path to continuous energy cross section library, or object containing + one-group cross-sections. chain_file : str, optional Path to the depletion chain XML file. Defaults to the file listed under ``depletion_chain`` in @@ -68,9 +73,7 @@ class OpenMCOperator(TransportOperator): normalization_mode : str Indicate how reaction rates should be normalized. fission_q : dict, optional - Dictionary of nuclides and their fission Q values [eV]. If not given, - values will be pulled from the ``chain_file``. Only applicable - if ``"normalization_mode" == "fission-q"`` + Dictionary of nuclides and their fission Q values [eV]. dilute_initial : float, optional Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay chain. @@ -90,25 +93,16 @@ class OpenMCOperator(TransportOperator): reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. Default is False. - - .. versionadded:: 0.12 reduce_chain_level : int, optional Depth of the search when reducing the depletion chain. Only used if ``reduce_chain`` evaluates to true. The default value of ``None`` implies no limit on the depth. - .. versionadded:: 0.12 - - Attributes ---------- - model : openmc.model.Model - OpenMC model object - geometry : openmc.Geometry - OpenMC geometry object - settings : openmc.Settings - OpenMC settings object + materials : openmc.Materials + All materials present in the model dilute_initial : float Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay @@ -135,6 +129,7 @@ class OpenMCOperator(TransportOperator): prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. + """ def __init__( @@ -269,7 +264,20 @@ class OpenMCOperator(TransportOperator): @abstractmethod def _get_nuclides_with_data(self, cross_sections): - """Find nuclides with cross section data""" + """Find nuclides with cross section data + + Parameters + ---------- + cross_sections : str or pandas.DataFrame + Path to continuous energy cross section library, or object + containing one-group cross-sections. + + Returns + ------- + nuclides : set of str + Set of nuclide names that have cross secton data + + """ def _extract_number(self, local_mats, volume, all_nuclides, prev_res=None): """Construct AtomNumber using geometry @@ -399,6 +407,7 @@ class OpenMCOperator(TransportOperator): ------- list of numpy.ndarray Total density for initial conditions. + """ self._rate_helper.generate_tallies(materials, self.chain.reactions) @@ -414,7 +423,15 @@ class OpenMCOperator(TransportOperator): def _update_materials_and_nuclides(self, vec): """Update the number density, material compositions, and nuclide - lists in helper objects""" + lists in helper objects + + Parameters + ---------- + vec : list of numpy.ndarray + Total atoms. + + """ + # Update the number densities regardless of the source rate self.number.set_density(vec) self._update_materials() diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index a86eb182f..d8b84f5a0 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -34,7 +34,14 @@ __all__ = ["Operator", "OperatorResult"] def _find_cross_sections(model): - """Determine cross sections to use for depletion""" + """Determine cross sections to use for depletion + + Parameters + ---------- + model : openmc.model.Model + Reactor model + + """ if model.materials and model.materials.cross_sections is not None: # Prefer info from Model class if available return model.materials.cross_sections @@ -283,7 +290,19 @@ class Operator(OpenMCOperator): self.prev_res.append(new_res) def _get_nuclides_with_data(self, cross_sections): - """Loads cross_sections.xml file to find nuclides with neutron data""" + """Loads cross_sections.xml file to find nuclides with neutron data + + Parameters + ---------- + cross_sections : str + Path to cross_sections.xml file + + Returns + ------- + nuclides : set of str + Set of nuclide names that have cross secton data + + """ nuclides = set() data_lib = DataLibrary.from_xml(cross_sections) for library in data_lib.libraries: @@ -368,6 +387,7 @@ class Operator(OpenMCOperator): ------- list of numpy.ndarray Total density for initial conditions. + """ # Create XML files @@ -502,6 +522,7 @@ class Operator(OpenMCOperator): ---------- step : int Current depletion step including restarts + """ openmc.lib.statepoint_write( "openmc_simulation_n{}.h5".format(step), From a5f15aec57334c7160642395149812e296a059a3 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 14 Jul 2022 17:55:18 -0500 Subject: [PATCH 0591/2654] rearrange functions; move FluxTimesXSHelper to be inner class of FluxDepletionOperator We move FluxTimesXSHelper to be an inner class of FluxDepletionOperator so we can avoid needing to copy the number and cross_sections attributes. --- openmc/deplete/flux_operator.py | 580 ++++++++++++++++++-------------- openmc/deplete/helpers.py | 93 +---- 2 files changed, 330 insertions(+), 343 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 014770551..eaa59cbde 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -8,6 +8,7 @@ and one-group cross sections. import copy from collections import OrderedDict from warnings import warn +from itertools import product import numpy as np import pandas as pd @@ -16,15 +17,16 @@ from uncertainties import ufloat import openmc from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.mpi import comm -from .abc import TransportOperator, OperatorResult +from .abc import TransportOperator, ReactionRateHelper, OperatorResult from .atom_number import AtomNumber from .chain import REACTIONS from .reaction_rates import ReactionRates -from .helpers import ConstantFissionYieldHelper, SourceRateHelper, FluxTimesXSHelper +from .helpers import ConstantFissionYieldHelper, SourceRateHelper valid_rxns = list(REACTIONS) valid_rxns.append('fission') +## delete def _distribute(items): """Distribute items across MPI communicator Parameters @@ -138,10 +140,23 @@ class FluxDepletionOperator(TransportOperator): materials = self._consolidate_nuclides_to_material(nuclides, volume) diff_burnable_mats=False - # super().__init__(materials, cross_sections, diff_burnable_mats, chain_file, fission_q, dilute_initial, prev_results, helper_class_kwargs) + #super().__init__( + # materials, + # cross_sections, + # chain_file, + # prev_results, + # diff_burnable_mats, + # normalization_mode, + # None, + # 0.0, + # None, + # fission_yield_opts, + # None, + # None, + # reduce_chain, + # reduce_chain_level) - - ## this part goes to OpenMCOperator + ##delete till end of function super().__init__(chain_file, fission_q, 0.0, prev_results) self.round_number = False self.materials = materials @@ -195,6 +210,219 @@ class FluxDepletionOperator(TransportOperator): self._get_helper_classes(None, fission_yield_opts) + def _consolidate_nuclides_to_material(self, nuclides, volume): + """Puts nuclide list into an openmc.Materials object. + + """ + openmc.reset_auto_ids() + mat = openmc.Material() + for nuc, conc in nuclides.items(): + mat.add_nuclide(nuc, conc / 1e24) #convert to at/b-cm + + mat.volume = volume + mat.depleteable = True + + return openmc.Materials([mat]) + + def _differentiate_burnable_materials(): + """Assign distribmats for each burnable material""" + pass + + ##delete + def _get_burnable_mats(self): + """Determine depletable materials, volumes, and nuclides + Returns + ------- + burnable_mats : list of str + List of burnable material IDs + volume : OrderedDict of str to float + Volume of each material in [cm^3] + nuclides : list of str + Nuclides in order of how they'll appear in the simulation. + """ + + burnable_mats = set() + model_nuclides = set() + volume = OrderedDict() + + self.heavy_metal = 0.0 + + # Iterate once through the geometry to get dictionaries + for mat in self.materials: + for nuclide in mat.get_nuclides(): + model_nuclides.add(nuclide) + if mat.depletable: + burnable_mats.add(str(mat.id)) + if mat.volume is None: + raise RuntimeError("Volume not specified for depletable " + "material with ID={}.".format(mat.id)) + volume[str(mat.id)] = mat.volume + self.heavy_metal += mat.fissionable_mass + + # Make sure there are burnable materials + if not burnable_mats: + raise RuntimeError( + "No depletable materials were found in the model.") + + # Sort the sets + burnable_mats = sorted(burnable_mats, key=int) + model_nuclides = sorted(model_nuclides) + + # Construct a global nuclide dictionary, burned first + nuclides = list(self.chain.nuclide_dict) + for nuc in model_nuclides: + if nuc not in nuclides: + nuclides.append(nuc) + + return burnable_mats, volume, nuclides + + def _load_previous_results(): + """Load in results from a previous depletion calculation.""" + pass + + def _get_nuclides_with_data(self, cross_sections): + """Finds nuclides with cross section data + """ + return set(cross_sections.index) + + ##delete + def _extract_number(self, local_mats, volume, nuclides, prev_res=None): + """Construct AtomNumber using geometry + + Parameters + ---------- + local_mats : list of str + Material IDs to be managed by this process + volume : OrderedDict of str to float + Volumes for the above materials in [cm^3] + nuclides : list of str + Nuclides to be used in the simulation. + prev_res : Results, optional + Results from a previous depletion calculation + + """ + self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) + + if self.dilute_initial != 0.0: + for nuc in self._burnable_nucs: + self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) + + # Now extract and store the number densities + # From the geometry if no previous depletion results + if prev_res is None: + for mat in self.materials: + if str(mat.id) in local_mats: + self._set_number_from_mat(mat) + # Else from previous depletion results + else: + raise RuntimeError( + "Loading from previous results not yet supported") + + ##delete + def _set_number_from_mat(self, mat): + """Extracts material and number densities from openmc.Material + Parameters + ---------- + mat : openmc.Material + The material to read from + """ + mat_id = str(mat.id) + + for nuclide, atom_per_bcm in mat.get_nuclide_atom_densities().items(): + atom_per_cc = atom_per_bcm * 1.0e24 + self.number.set_atom_density(mat_id, nuclide, atom_per_cc) + + class FluxTimesXSHelper(ReactionRateHelper): + """Class for generating one-group reaction rates with flux and + one-group cross sections. + + This class does not generate tallies, and instead stores cross sections + for each nuclide and transmutation reaction relevant for a depletion + calculation. The reaction rate is calculated by multiplying the flux by the + cross sections. + + Parameters + ---------- + outer : openmc.deplete.FluxDepletionOperator + Reference to the object encapsulate FluxTimesXSHelper. + We pass this so we don't have to duplicate the ``number`` object. + n_nucs : int + Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` + n_react : int + Number of reactions tracked by :class:`openmc.deplete.Operator` + + Attributes + ---------- + nuc_ind_map : dict of int to str + Dictionary mapping the nuclide index to nuclide name + rxn_ind_map : dict of int to str + Dictionary mapping reaction index to reaction name + + """ + def __init__(self, n_nuc, n_react, outer): + super().__init__(n_nuc, n_react) + self.outer = outer + self.nuc_ind_map = None + self.rxn_ind_map = None + + def generate_tallies(self, materials, scores): + """Unused in this case""" + + def get_material_rates(self, mat_id, nuc_index, react_index): + """Return 2D array of [nuclide, reaction] reaction rates + + Parameters + ---------- + mat_id : int + Unique ID for the requested material + nuc_index : list of str + Ordering of desired nuclides + react_index : list of str + Ordering of reactions + """ + self._results_cache.fill(0.0) + for i, (i_nuc, i_react) in enumerate(product(nuc_index, react_index)): + nuc = self.nuc_ind_map[i_nuc] + rxn = self.rxn_ind_map[i_react] + density = self.outer.number.get_atom_density(mat_id, nuc) + self._results_cache[i_nuc, i_react] = self.outer.cross_sections[rxn][nuc] * density + + return self._results_cache + + def _get_helper_classes(self, reaction_rate_opts, fission_yield_opts): + """Get helper classes for calculating reation rates and fission yields""" + rates = self.reaction_rates + # Get classes to assit working with tallies + nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} + rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} + + self._rate_helper = self.FluxTimesXSHelper(self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) + self._rate_helper.nuc_ind_map = nuc_ind_map + self._rate_helper.rxn_ind_map = rxn_ind_map + + self._normalization_helper = SourceRateHelper() + + # Select and create fission yield helper + fission_helper = ConstantFissionYieldHelper + fission_yield_opts = ( + {} if fission_yield_opts is None else fission_yield_opts) + self._yield_helper = fission_helper.from_operator( + self, **fission_yield_opts) + + def initial_condition(self): + """Performs final setup and returns initial condition. + + Returns + ------- + list of numpy.ndarray + Total density for initial conditions. + """ + + # Return number density vector + #return super().initial_condition() + ##delete + return list(self.number.get_mat_slice(np.s_[:])) + def __call__(self, vec, source_rate): """Obtain the reaction rates @@ -212,6 +440,17 @@ class FluxDepletionOperator(TransportOperator): """ + self._update_materials_and_nuclides(vec) + + # Use the flux spectra as a "source rate" + rates = self._calculate_reaction_rates(self.flux_spectra) + keff = self._keff + + op_result = OperatorResult(keff, rates) + return copy.deepcopy(op_result) + + ##delete + def _update_materials_and_nuclides(self, vec): # Update the number densities regardless of the source rate self.number.set_density(vec) self._update_materials() @@ -222,13 +461,92 @@ class FluxDepletionOperator(TransportOperator): self._normalization_helper.nuclides = rxn_nuclides self._yield_helper.update_tally_nuclides(rxn_nuclides) - # Use the flux spectra as a "source rate" - rates = self._calculate_reaction_rates(self.flux_spectra) - keff = self._keff + def _update_materials(self): + """Updates material compositions in OpenMC on all processes.""" - op_result = OperatorResult(keff, rates) - return copy.deepcopy(op_result) + for rank in range(comm.size): + number_i = comm.bcast(self.number, root=rank) + for mat in number_i.materials: + nuclides = [] + densities = [] + for nuc in number_i.nuclides: + if nuc in self.nuclides_with_data: + val = 1.0e-24 * number_i.get_atom_density(mat, nuc) + + # If nuclide is zero, do not add to the problem. + if val > 0.0: + if self.round_number: + val_magnitude = np.floor(np.log10(val)) + val_scaled = val / 10**val_magnitude + val_round = round(val_scaled, 8) + + val = val_round * 10**val_magnitude + + nuclides.append(nuc) + densities.append(val) + else: + # Only output warnings if values are significantly + # negative. CRAM does not guarantee positive + # values. + if val < -1.0e-21: + print( + "WARNING: nuclide ", + nuc, + " in material ", + mat, + " is negative (density = ", + val, + " at/barn-cm)") + number_i[mat, nuc] = 0.0 + + # TODO Update densities on the Python side, otherwise the + # summary.h5 file contains densities at the first time step + ##delete + def _get_reaction_nuclides(self): + """Determine nuclides that should have reaction rates + + This method returns a list of all nuclides that have neutron data and + are listed in the depletion chain. Technically, we should list nuclides + that may not appear in the depletion chain because we still need to get + the fission reaction rate for these nuclides in order to normalize + power, but that is left as a future exercise. + + Returns + ------- + list of str + nuclides with reaction rates + + """ + # Create the set of all nuclides in the decay chain in materials marked + # for burning in which the number density is greater than zero. + nuc_set = set() + + for nuc in self.number.nuclides: + if nuc in self.nuclides_with_data: + if np.sum(self.number[:,nuc]) > 0.0: + nuc_set.add(nuc) + + # Communicate which nuclides have nonzeros to rank 0 + if comm.rank == 0: + for i in range(1, comm.size): + nuc_newset = comm.recv(source=i, tag=i) + nuc_set |= nuc_newset + else: + comm.send(nuc_set, dest=0, tag=comm.rank) + + if comm.rank == 0: + # Sort nuclides in the same order as self.number + nuc_list = [nuc for nuc in self.number.nuclides + if nuc in nuc_set] + else: + nuc_list = None + + # Store list of tally nuclides on each process + nuc_list = comm.bcast(nuc_list) + return [nuc for nuc in nuc_list if nuc in self.chain] + + ##delete def _calculate_reaction_rates(self, source_rate): rates = self.reaction_rates @@ -302,18 +620,6 @@ class FluxDepletionOperator(TransportOperator): return rates - def initial_condition(self): - """Performs final setup and returns initial condition. - - Returns - ------- - list of numpy.ndarray - Total density for initial conditions. - """ - - # Return number density vector - return list(self.number.get_mat_slice(np.s_[:])) - def write_bos_data(self, step): """Document beginning of step data for a given step @@ -328,6 +634,7 @@ class FluxDepletionOperator(TransportOperator): # Since we aren't running a transport simulation, we simply pass pass + ##delete def get_results_info(self): """Returns volume list, cell lists, and nuc lists. @@ -436,233 +743,4 @@ class FluxDepletionOperator(TransportOperator): check_value('reactions', reaction, valid_rxns) - def _update_materials(self): - """Updates material compositions in OpenMC on all processes.""" - for rank in range(comm.size): - number_i = comm.bcast(self.number, root=rank) - - for mat in number_i.materials: - nuclides = [] - densities = [] - for nuc in number_i.nuclides: - if nuc in self.nuclides_with_data: - val = 1.0e-24 * number_i.get_atom_density(mat, nuc) - - # If nuclide is zero, do not add to the problem. - if val > 0.0: - if self.round_number: - val_magnitude = np.floor(np.log10(val)) - val_scaled = val / 10**val_magnitude - val_round = round(val_scaled, 8) - - val = val_round * 10**val_magnitude - - nuclides.append(nuc) - densities.append(val) - else: - # Only output warnings if values are significantly - # negative. CRAM does not guarantee positive - # values. - if val < -1.0e-21: - print( - "WARNING: nuclide ", - nuc, - " in material ", - mat, - " is negative (density = ", - val, - " at/barn-cm)") - number_i[mat, nuc] = 0.0 - - # TODO Update densities on the Python side, otherwise the - # summary.h5 file contains densities at the first time step - - def _consolidate_nuclides_to_material(self, nuclides, volume): - """Puts nuclide list into an openmc.Materials object. - - """ - openmc.reset_auto_ids() - mat = openmc.Material() - for nuc, conc in nuclides.items(): - mat.add_nuclide(nuc, conc / 1e24) #convert to at/b-cm - - mat.volume = volume - mat.depleteable = True - - return openmc.Materials([mat]) - - def _get_helper_classes(self, reaction_rate_opts, fission_yield_opts): - """Get helper classes for calculating reation rates and fission yields""" - rates = self.reaction_rates - # Get classes to assit working with tallies - nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} - rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} - - - self._rate_helper = FluxTimesXSHelper(self.flux_spectra, self.cross_sections, self.reaction_rates.n_nuc, self.reaction_rates.n_react) - - self._rate_helper.nuc_ind_map = nuc_ind_map - self._rate_helper.rxn_ind_map = rxn_ind_map - # We'll need to find a way to update number as time goes on. - # perhaps in this classes version of _update_materials()? - self._rate_helper.number = self.number - - self._normalization_helper = SourceRateHelper() - - # Select and create fission yield helper - fission_helper = ConstantFissionYieldHelper - fission_yield_opts = ( - {} if fission_yield_opts is None else fission_yield_opts) - self._yield_helper = fission_helper.from_operator( - self, **fission_yield_opts) - - - def _load_previous_results(): - """Load in results from a previous depletion calculation.""" - pass - - def _differentiate_burnable_materials(): - """Assign distribmats for each burnable material""" - pass - - def _get_reaction_nuclides(self): - """Determine nuclides that should have reaction rates - - This method returns a list of all nuclides that have neutron data and - are listed in the depletion chain. Technically, we should list nuclides - that may not appear in the depletion chain because we still need to get - the fission reaction rate for these nuclides in order to normalize - power, but that is left as a future exercise. - - Returns - ------- - list of str - nuclides with reaction rates - - """ - # Create the set of all nuclides in the decay chain in materials marked - # for burning in which the number density is greater than zero. - nuc_set = set() - - for nuc in self.number.nuclides: - if nuc in self.nuclides_with_data: - if np.sum(self.number[:,nuc]) > 0.0: - nuc_set.add(nuc) - - # Communicate which nuclides have nonzeros to rank 0 - if comm.rank == 0: - for i in range(1, comm.size): - nuc_newset = comm.recv(source=i, tag=i) - nuc_set |= nuc_newset - else: - comm.send(nuc_set, dest=0, tag=comm.rank) - - if comm.rank == 0: - # Sort nuclides in the same order as self.number - nuc_list = [nuc for nuc in self.number.nuclides - if nuc in nuc_set] - else: - nuc_list = None - - # Store list of tally nuclides on each process - nuc_list = comm.bcast(nuc_list) - return [nuc for nuc in nuc_list if nuc in self.chain] - - def _get_burnable_mats(self): - """Determine depletable materials, volumes, and nuclides - Returns - ------- - burnable_mats : list of str - List of burnable material IDs - volume : OrderedDict of str to float - Volume of each material in [cm^3] - nuclides : list of str - Nuclides in order of how they'll appear in the simulation. - """ - - burnable_mats = set() - model_nuclides = set() - volume = OrderedDict() - - self.heavy_metal = 0.0 - - # Iterate once through the geometry to get dictionaries - for mat in self.materials: - for nuclide in mat.get_nuclides(): - model_nuclides.add(nuclide) - if mat.depletable: - burnable_mats.add(str(mat.id)) - if mat.volume is None: - raise RuntimeError("Volume not specified for depletable " - "material with ID={}.".format(mat.id)) - volume[str(mat.id)] = mat.volume - self.heavy_metal += mat.fissionable_mass - - # Make sure there are burnable materials - if not burnable_mats: - raise RuntimeError( - "No depletable materials were found in the model.") - - # Sort the sets - burnable_mats = sorted(burnable_mats, key=int) - model_nuclides = sorted(model_nuclides) - - # Construct a global nuclide dictionary, burned first - nuclides = list(self.chain.nuclide_dict) - for nuc in model_nuclides: - if nuc not in nuclides: - nuclides.append(nuc) - - return burnable_mats, volume, nuclides - - def _get_nuclides_with_data(self, cross_sections): - """Finds nuclides with cross section data - """ - return set(cross_sections.index) - - - def _extract_number(self, local_mats, volume, nuclides, prev_res=None): - """Construct AtomNumber using geometry - - Parameters - ---------- - local_mats : list of str - Material IDs to be managed by this process - volume : OrderedDict of str to float - Volumes for the above materials in [cm^3] - nuclides : list of str - Nuclides to be used in the simulation. - prev_res : Results, optional - Results from a previous depletion calculation - - """ - self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) - - if self.dilute_initial != 0.0: - for nuc in self._burnable_nucs: - self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) - - # Now extract and store the number densities - # From the geometry if no previous depletion results - if prev_res is None: - for mat in self.materials: - if str(mat.id) in local_mats: - self._set_number_from_mat(mat) - # Else from previous depletion results - else: - raise RuntimeError( - "Loading from previous results not yet supported") - - def _set_number_from_mat(self, mat): - """Extracts material and number densities from openmc.Material - Parameters - ---------- - mat : openmc.Material - The material to read from - """ - mat_id = str(mat.id) - - for nuclide, atom_per_bcm in mat.get_nuclide_atom_densities().items(): - atom_per_cc = atom_per_bcm * 1.0e24 - self.number.set_atom_density(mat_id, nuclide, atom_per_cc) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 67a88fa16..33bd182d7 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -2,7 +2,6 @@ Class for normalizing fission energy deposition """ import bisect -import pandas as pd from abc import abstractmethod from collections import defaultdict from copy import deepcopy @@ -25,7 +24,7 @@ __all__ = ( "DirectReactionRateHelper", "ChainFissionHelper", "EnergyScoreHelper" "SourceRateHelper", "TalliedFissionYieldHelper", "ConstantFissionYieldHelper", "FissionYieldCutoffHelper", - "AveragedFissionYieldHelper", "FluxCollapseHelper", "FluxTimesXSHelper") + "AveragedFissionYieldHelper", "FluxCollapseHelper") class TalliedFissionYieldHelper(FissionYieldHelper): """Abstract class for computing fission yields with tallies @@ -125,96 +124,6 @@ class TalliedFissionYieldHelper(FissionYieldHelper): # ------------------------------------- -class FluxTimesXSHelper(ReactionRateHelper): - """Class for generating one-group reaction rates with flux and - one-group cross sections. - - This class does not generate tallies, and instead stores cross sections - for each nuclide and transmutation reaction relevant for a depletion - calculation. The reaction rate is calculated by multiplying the flux by the - cross sections. - - Parameters - ---------- - flux : float - Neutron flux - micro_xs : pandas.DataFrame - Microscopic cross-section data - n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` - n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` - - Attributes - ---------- - nuc_ind_map : dict of int to str - Dictionary mapping the nuclide index to nuclide name - rxn_ind_map : dict of int to str - Dictionary mapping reaction index to reaction name - number : AtomNumber - AtomNumber object. Needed to convert the microscopic cross-sections - to macroscopic cross sections. - - """ - def __init__(self, flux, micro_xs, n_nuc, n_react): - super().__init__(n_nuc, n_react) - self._flux = flux - self._micro_xs = micro_xs - self.nuc_ind_map = None - self.rxn_ind_map = None - self.number = None - - def generate_tallies(self, materials, scores): - """Unused in this case""" - - - @property - def flux(self): - """Flux in n cm^-2 s^-1""" - return self._flux - - @flux.setter - def flux(self, flux): - check_type("flux", flux, float) - self._flux = flux - - @property - def micro_xs(self): - """DataFrame of microscopic cross sections with requested reaction - for all nuclides""" - return self._micro_xs - - @micro_xs.setter - def micro_xs(self, micro_xs): - # TODO : validate micro_xs - self._micro_xs = micro_xs - - def get_material_rates(self, mat_id, nuc_index, react_index): - """Return 2D array of [nuclide, reaction] reaction rates - - Parameters - ---------- - mat_id : int - Unique ID for the requested material - nuc_index : list of str - Ordering of desired nuclides - react_index : list of str - Ordering of reactions - """ - self._results_cache.fill(0.0) - for i, (i_nuc, i_react) in enumerate(product(nuc_index, react_index)): - nuc = self.nuc_ind_map[i_nuc] - rxn = self.rxn_ind_map[i_react] - density = self.number.get_atom_density(mat_id, nuc) - self._results_cache[i_nuc, i_react] = self._micro_xs[rxn][nuc] * density - - return self._results_cache - - - - - - class DirectReactionRateHelper(ReactionRateHelper): """Class for generating one-group reaction rates with direct tallies From 4d321bc98babefd1496150eb49b2406fa8325071 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Mon, 22 Nov 2021 15:20:01 -0600 Subject: [PATCH 0592/2654] Replace centroid() with vertex_average(). Refs #1914 --- cmake/Modules/FindLIBMESH.cmake | 4 ++-- cmake/OpenMCConfig.cmake.in | 2 +- src/mesh.cpp | 2 +- tools/ci/gha-install-libmesh.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/Modules/FindLIBMESH.cmake b/cmake/Modules/FindLIBMESH.cmake index 82d806343..df5b5b9d8 100644 --- a/cmake/Modules/FindLIBMESH.cmake +++ b/cmake/Modules/FindLIBMESH.cmake @@ -17,5 +17,5 @@ endif() include(FindPkgConfig) set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${LIBMESH_PC}") set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH True) -pkg_check_modules(LIBMESH REQUIRED ${LIBMESH_PC_FILE}>=1.6.0 IMPORTED_TARGET) -pkg_get_variable(LIBMESH_PREFIX ${LIBMESH_PC_FILE} prefix) \ No newline at end of file +pkg_check_modules(LIBMESH REQUIRED ${LIBMESH_PC_FILE}>=1.7.0 IMPORTED_TARGET) +pkg_get_variable(LIBMESH_PREFIX ${LIBMESH_PC_FILE} prefix) diff --git a/cmake/OpenMCConfig.cmake.in b/cmake/OpenMCConfig.cmake.in index 3279e5ba8..d0e2beb82 100644 --- a/cmake/OpenMCConfig.cmake.in +++ b/cmake/OpenMCConfig.cmake.in @@ -13,7 +13,7 @@ if(@OPENMC_USE_LIBMESH@) include(FindPkgConfig) list(APPEND CMAKE_PREFIX_PATH @LIBMESH_PREFIX@) set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH True) - pkg_check_modules(LIBMESH REQUIRED @LIBMESH_PC_FILE@>=1.6.0 IMPORTED_TARGET) + pkg_check_modules(LIBMESH REQUIRED @LIBMESH_PC_FILE@>=1.7.0 IMPORTED_TARGET) endif() find_package(PNG) diff --git a/src/mesh.cpp b/src/mesh.cpp index de29233fb..664036885 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2393,7 +2393,7 @@ void LibMesh::initialize() Position LibMesh::centroid(int bin) const { const auto& elem = this->get_element_from_bin(bin); - auto centroid = elem.centroid(); + auto centroid = elem.vertex_average(); return {centroid(0), centroid(1), centroid(2)}; } diff --git a/tools/ci/gha-install-libmesh.sh b/tools/ci/gha-install-libmesh.sh index 132963820..d592616ed 100755 --- a/tools/ci/gha-install-libmesh.sh +++ b/tools/ci/gha-install-libmesh.sh @@ -5,7 +5,7 @@ set -ex # libMESH install pushd $HOME mkdir LIBMESH && cd LIBMESH -git clone https://github.com/libmesh/libmesh -b v1.6.0 --recurse-submodules +git clone https://github.com/libmesh/libmesh -b v1.7.0 --recurse-submodules mkdir build && cd build export METHODS="opt" From 953b35e742d4526b4bf4c5429d876f21506ec5c3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 15 Jul 2022 07:21:08 -0500 Subject: [PATCH 0593/2654] Add openmc_sample_external_source function and Python binding --- openmc/lib/core.py | 39 ++++++++++++++++++++++++++++++++++++++- openmc/lib/math.py | 11 +++++------ src/source.cpp | 10 ++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/openmc/lib/core.py b/openmc/lib/core.py index de5f4adf2..3f4a301cd 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -1,8 +1,10 @@ from contextlib import contextmanager from ctypes import (c_bool, c_int, c_int32, c_int64, c_double, c_char_p, - c_char, POINTER, Structure, c_void_p, create_string_buffer) + c_char, POINTER, Structure, c_void_p, create_string_buffer, + c_uint64) import sys import os +from random import getrandbits import numpy as np from numpy.ctypeslib import as_array @@ -10,6 +12,7 @@ from numpy.ctypeslib import as_array from . import _dll from .error import _error_handler import openmc.lib +import openmc class _SourceSite(Structure): @@ -95,6 +98,9 @@ _dll.openmc_global_bounding_box.argtypes = [POINTER(c_double), POINTER(c_double)] _dll.openmc_global_bounding_box.restype = c_int _dll.openmc_global_bounding_box.errcheck = _error_handler +_dll.openmc_sample_external_source.argtypes = [POINTER(c_uint64), POINTER(_SourceSite)] +_dll.openmc_sample_external_source.restype = c_int +_dll.openmc_sample_external_source.errcheck = _error_handler def global_bounding_box(): @@ -415,6 +421,37 @@ def run(output=True): _dll.openmc_run() +def sample_external_source(prn_seed=None): + """Sample external source + + .. versionadded:: 0.13.1 + + Parameters + ---------- + prn_seed : int + PRNG seed; if None, one will be generated randomly + + Returns + ------- + openmc.SourceParticle + Sampled source particle + + """ + if prn_seed is None: + prn_seed = getrandbits(63) + + # Call into C API to sample source + site = _SourceSite() + _dll.openmc_sample_external_source(c_uint64(prn_seed), site) + + # Convert to SourceParticle and return + return openmc.SourceParticle( + r=site.r, u=site.u, E=site.E, time=site.time, wgt=site.wgt, + delayed_group=site.delayed_group, surf_id=site.surf_id, + particle=openmc.ParticleType(site.particle) + ) + + def simulation_init(): """Initialize simulation""" _dll.openmc_simulation_init() diff --git a/openmc/lib/math.py b/openmc/lib/math.py index bdb09b2d1..d70c20a9f 100644 --- a/openmc/lib/math.py +++ b/openmc/lib/math.py @@ -1,12 +1,11 @@ from ctypes import c_int, c_double, POINTER, c_uint64 +from random import getrandbits import numpy as np from numpy.ctypeslib import ndpointer from . import _dll -from random import getrandbits - _dll.t_percentile.restype = c_double _dll.t_percentile.argtypes = [c_double, c_int] @@ -240,10 +239,10 @@ def maxwell_spectrum(T, prn_seed=None): Sampled outgoing energy """ - + if prn_seed is None: prn_seed = getrandbits(63) - + return _dll.maxwell_spectrum(T, c_uint64(prn_seed)) @@ -265,7 +264,7 @@ def watt_spectrum(a, b, prn_seed=None): Sampled outgoing energy """ - + if prn_seed is None: prn_seed = getrandbits(63) @@ -290,7 +289,7 @@ def normal_variate(mean_value, std_dev, prn_seed=None): Sampled outgoing normally distributed value """ - + if prn_seed is None: prn_seed = getrandbits(63) diff --git a/src/source.cpp b/src/source.cpp index 11ede5fc4..8b634ec45 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -399,4 +399,14 @@ void free_memory_source() model::external_sources.clear(); } +//============================================================================== +// C API +//============================================================================== + +extern "C" int openmc_sample_external_source(uint64_t* seed, SourceSite* site) +{ + *site = sample_external_source(seed); + return 0; +} + } // namespace openmc From 1ba696741412b17ac676cc2a0b4a78c606906d35 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 15 Jul 2022 21:35:59 +0200 Subject: [PATCH 0594/2654] fix typo Co-authored-by: Paul Romano --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6af9643cd..be56f1c12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) option(OPENMC_USE_MPI "Enable MPI" OFF) -option(OPENMC_USE_MCPL "Enable MPCPL" OFF) +option(OPENMC_USE_MCPL "Enable MCPL" OFF) #=============================================================================== # Set a default build configuration if not explicitly specified From b1267f05448d80bce3069779f03de68749c44297 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 15 Jul 2022 13:23:07 -0500 Subject: [PATCH 0595/2654] Allow openmc_sample_external_source to produce multiple samples --- docs/source/pythonapi/capi.rst | 1 + include/openmc/capi.h | 1 + openmc/lib/core.py | 33 ++++++++++++++++++++------------- src/source.cpp | 13 +++++++++++-- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/docs/source/pythonapi/capi.rst b/docs/source/pythonapi/capi.rst index 03be25abf..882e3c71b 100644 --- a/docs/source/pythonapi/capi.rst +++ b/docs/source/pythonapi/capi.rst @@ -29,6 +29,7 @@ Functions reset run run_in_memory + sample_external_source simulation_init simulation_finalize source_bank diff --git a/include/openmc/capi.h b/include/openmc/capi.h index 0929a11f7..69d3ff1f6 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -121,6 +121,7 @@ int openmc_regular_mesh_set_params(int32_t index, int n, const double* ll, int openmc_reset(); int openmc_reset_timers(); int openmc_run(); +int openmc_sample_external_source(size_t n, uint64_t* seed, void* sites); void openmc_set_seed(int64_t new_seed); int openmc_set_n_batches( int32_t n_batches, bool set_max_batches, bool add_statepoint_batch); diff --git a/openmc/lib/core.py b/openmc/lib/core.py index 3f4a301cd..3a437a295 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -1,7 +1,7 @@ from contextlib import contextmanager from ctypes import (c_bool, c_int, c_int32, c_int64, c_double, c_char_p, c_char, POINTER, Structure, c_void_p, create_string_buffer, - c_uint64) + c_uint64, c_size_t) import sys import os from random import getrandbits @@ -98,7 +98,7 @@ _dll.openmc_global_bounding_box.argtypes = [POINTER(c_double), POINTER(c_double)] _dll.openmc_global_bounding_box.restype = c_int _dll.openmc_global_bounding_box.errcheck = _error_handler -_dll.openmc_sample_external_source.argtypes = [POINTER(c_uint64), POINTER(_SourceSite)] +_dll.openmc_sample_external_source.argtypes = [c_size_t, POINTER(c_uint64), POINTER(_SourceSite)] _dll.openmc_sample_external_source.restype = c_int _dll.openmc_sample_external_source.errcheck = _error_handler @@ -421,35 +421,42 @@ def run(output=True): _dll.openmc_run() -def sample_external_source(prn_seed=None): +def sample_external_source(n_samples=1, prn_seed=None): """Sample external source .. versionadded:: 0.13.1 Parameters ---------- + n_samples : int + Number of samples prn_seed : int PRNG seed; if None, one will be generated randomly Returns ------- - openmc.SourceParticle - Sampled source particle + list of openmc.SourceParticle + List of samples source particles """ + if n_samples <= 0: + raise ValueError("Number of samples must be positive") if prn_seed is None: prn_seed = getrandbits(63) # Call into C API to sample source - site = _SourceSite() - _dll.openmc_sample_external_source(c_uint64(prn_seed), site) + sites_array = (_SourceSite * n_samples)() + _dll.openmc_sample_external_source(c_size_t(n_samples), c_uint64(prn_seed), sites_array) - # Convert to SourceParticle and return - return openmc.SourceParticle( - r=site.r, u=site.u, E=site.E, time=site.time, wgt=site.wgt, - delayed_group=site.delayed_group, surf_id=site.surf_id, - particle=openmc.ParticleType(site.particle) - ) + # Convert to list of SourceParticle and return + return [ + openmc.SourceParticle( + r=site.r, u=site.u, E=site.E, time=site.time, wgt=site.wgt, + delayed_group=site.delayed_group, surf_id=site.surf_id, + particle=openmc.ParticleType(site.particle) + ) + for site in sites_array + ] def simulation_init(): diff --git a/src/source.cpp b/src/source.cpp index 8b634ec45..3716720df 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -403,9 +403,18 @@ void free_memory_source() // C API //============================================================================== -extern "C" int openmc_sample_external_source(uint64_t* seed, SourceSite* site) +extern "C" int openmc_sample_external_source( + size_t n, uint64_t* seed, void* sites) { - *site = sample_external_source(seed); + if (!sites || !seed) { + set_errmsg("Received null pointer."); + return OPENMC_E_INVALID_ARGUMENT; + } + + auto sites_array = static_cast(sites); + for (size_t i = 0; i < n; ++i) { + sites_array[i] = sample_external_source(seed); + } return 0; } From ba5f6f58fad0b28a2c69d4cc63d7dff0ac069067 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 15 Jul 2022 19:57:58 -0500 Subject: [PATCH 0596/2654] Add test for openmc.lib.sample_external_source --- tests/unit_tests/test_lib.py | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index a0f18f851..f1f84bff2 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -807,3 +807,44 @@ def test_cell_rotation(pincell_model_w_univ, mpi_intracomm): cell.rotation = (180., 0., 0.) assert cell.rotation == pytest.approx([180., 0., 0.]) openmc.lib.finalize() + + +def test_sample_external_source(run_in_tmpdir, mpi_intracomm): + # Define a simple model and export + mat = openmc.Material() + mat.add_nuclide('U235', 1.0e-2) + sph = openmc.Sphere(r=100.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sph) + model = openmc.Model() + model.geometry = openmc.Geometry([cell]) + model.settings.source = openmc.Source( + space=openmc.stats.Box([-5., -5., -5.], [5., 5., 5.]), + angle=openmc.stats.Monodirectional((0., 0., 1.)), + energy=openmc.stats.Discrete([1.0e5], [1.0]) + ) + model.settings.particles = 1000 + model.settings.batches = 10 + model.export_to_xml() + + # Sample some particles and make sure they match specified source + openmc.lib.init() + particles = openmc.lib.sample_external_source(10, prn_seed=3) + for p in particles: + assert -5. < p.r[0] < 5. + assert -5. < p.r[1] < 5. + assert -5. < p.r[2] < 5. + assert p.u[0] == 0.0 + assert p.u[1] == 0.0 + assert p.u[2] == 1.0 + assert p.E == 1.0e5 + + # Using the same seed should produce the same particles + other_particles = openmc.lib.sample_external_source(10, prn_seed=3) + for p1, p2 in zip(particles, other_particles): + assert p1.r == p2.r + assert p1.u == p2.u + assert p1.E == p2.E + assert p1.time == p2.time + assert p1.wgt == p2.wgt + + openmc.lib.finalize() From 38df4f6928cdef6ef92196b92e79565d1e42c078 Mon Sep 17 00:00:00 2001 From: Richard Morrison Date: Sun, 17 Jul 2022 20:54:02 +0100 Subject: [PATCH 0597/2654] Fixed std::cout sync bug in output.cpp --- src/output.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/output.cpp b/src/output.cpp index ece475de0..0bd9693a8 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -93,7 +93,7 @@ void title() // Write number of OpenMP threads fmt::print(" OpenMP Threads | {}\n", omp_get_max_threads()); #endif - std::cout << std::endl; + fmt::print("\n"); } //============================================================================== @@ -133,7 +133,7 @@ void header(const char* msg, int level) // Print header based on verbosity level. if (settings::verbosity >= level) - std::cout << '\n' << out << "\n" << std::endl; + fmt::print("\n{}\n\n", out); } //============================================================================== @@ -379,7 +379,7 @@ void print_generation() if (n > 1) { fmt::print(" {:8.5f} +/-{:8.5f}", simulation::keff, simulation::keff_std); } - std::cout << std::endl; + fmt::print("\n"); } //============================================================================== @@ -546,7 +546,7 @@ void print_results() fmt::print(" Leakage Fraction = {:.5f}\n", gt(GlobalTally::LEAKAGE, TallyResult::SUM) / n); } - std::cout << std::endl; + fmt::print("\n"); } //============================================================================== From a42ce82396ed3f3e40718894a3208b3b3bbfc6a3 Mon Sep 17 00:00:00 2001 From: Richard Morrison Date: Sun, 17 Jul 2022 21:11:17 +0100 Subject: [PATCH 0598/2654] ARG & ENV scoping fix in Dockerfile --- Dockerfile | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 341390c9a..c83460f35 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,10 +27,6 @@ ARG compile_cores=1 # Set default value of HOME to /root ENV HOME=/root -# OpenMC variables -ARG openmc_branch=master -ENV OPENMC_REPO='https://github.com/openmc-dev/openmc' - # Embree variables ENV EMBREE_TAG='v3.12.2' ENV EMBREE_REPO='https://github.com/embree/embree' @@ -174,6 +170,17 @@ RUN if [ "$build_libmesh" = "on" ]; then \ FROM dependencies AS build +ENV HOME=/root + +ARG openmc_branch=master +ENV OPENMC_REPO='https://github.com/openmc-dev/openmc' + +ARG build_dagmc +ARG build_libmesh + +ENV DAGMC_INSTALL_DIR=$HOME/DAGMC/ +ENV LIBMESH_INSTALL_DIR=$HOME/LIBMESH + # clone and install openmc RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ && git clone --shallow-submodules --recurse-submodules --single-branch -b ${openmc_branch} --depth=1 ${OPENMC_REPO} \ @@ -211,5 +218,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ FROM build AS release +ENV HOME=/root + # Download cross sections (NNDC and WMP) and ENDF data needed by test suite RUN ${HOME}/OpenMC/openmc/tools/ci/download-xs.sh From d8425d2669b71efbda64a3fbdaf645cf8468e291 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 18 Jul 2022 06:48:51 -0500 Subject: [PATCH 0599/2654] Apply @shimwell suggestions from code review Co-authored-by: Jonathan Shimwell --- tests/unit_tests/test_lib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index f1f84bff2..b57242983 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -829,6 +829,7 @@ def test_sample_external_source(run_in_tmpdir, mpi_intracomm): # Sample some particles and make sure they match specified source openmc.lib.init() particles = openmc.lib.sample_external_source(10, prn_seed=3) + assert len(particles) == 10 for p in particles: assert -5. < p.r[0] < 5. assert -5. < p.r[1] < 5. @@ -840,6 +841,7 @@ def test_sample_external_source(run_in_tmpdir, mpi_intracomm): # Using the same seed should produce the same particles other_particles = openmc.lib.sample_external_source(10, prn_seed=3) + assert len(other_particles) == 10 for p1, p2 in zip(particles, other_particles): assert p1.r == p2.r assert p1.u == p2.u From 476fdd1bf7169ac08d17cc529ae9fe1f8bbabcc8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 18 Jul 2022 06:49:14 -0500 Subject: [PATCH 0600/2654] Improve description of prn_seed argument in openmc.lib functions --- openmc/lib/core.py | 3 ++- openmc/lib/math.py | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/openmc/lib/core.py b/openmc/lib/core.py index 3a437a295..479e414ae 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -431,7 +431,8 @@ def sample_external_source(n_samples=1, prn_seed=None): n_samples : int Number of samples prn_seed : int - PRNG seed; if None, one will be generated randomly + Pseudorandom number generator (PRNG) seed; if None, one will be + generated randomly. Returns ------- diff --git a/openmc/lib/math.py b/openmc/lib/math.py index d70c20a9f..0f61450bf 100644 --- a/openmc/lib/math.py +++ b/openmc/lib/math.py @@ -199,7 +199,8 @@ def rotate_angle(uvw0, mu, phi, prn_seed=None): phi : float Azimuthal angle; if None, one will be sampled uniformly prn_seed : int - PRNG seed; if None, one will be generated randomly + Pseudorandom number generator (PRNG) seed; if None, one will be + generated randomly. Returns ------- @@ -231,7 +232,8 @@ def maxwell_spectrum(T, prn_seed=None): T : float Spectrum parameter prn_seed : int - PRNG seed; if None, one will be generated randomly + Pseudorandom number generator (PRNG) seed; if None, one will be + generated randomly. Returns ------- @@ -256,7 +258,8 @@ def watt_spectrum(a, b, prn_seed=None): b : float Spectrum parameter b prn_seed : int - PRNG seed; if None, one will be generated randomly + Pseudorandom number generator (PRNG) seed; if None, one will be + generated randomly. Returns ------- @@ -281,7 +284,8 @@ def normal_variate(mean_value, std_dev, prn_seed=None): std_dev : float Standard deviation of the normal distribution prn_seed : int - PRNG seed; if None, one will be generated randomly + Pseudorandom number generator (PRNG) seed; if None, one will be + generated randomly. Returns ------- From dc7851dda262980943eb5d0c4461862248a6809e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 18 Jul 2022 15:30:52 -0500 Subject: [PATCH 0601/2654] Apply @pshriwise suggestions from code review Co-authored-by: Patrick Shriwise --- openmc/weight_windows.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 257a17e9a..c5b7a00b6 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -291,10 +291,10 @@ class WeightWindows(IDManagerMixin): subelement.text = ' '.join(str(e) for e in self.energy_bounds) subelement = ET.SubElement(element, 'lower_ww_bounds') - subelement.text = ' '.join(str(b) for b in self.lower_ww_bounds.ravel()) + subelement.text = ' '.join(str(b) for b in self.lower_ww_bounds.ravel('F')) subelement = ET.SubElement(element, 'upper_ww_bounds') - subelement.text = ' '.join(str(b) for b in self.upper_ww_bounds.ravel()) + subelement.text = ' '.join(str(b) for b in self.upper_ww_bounds.ravel('F')) subelement = ET.SubElement(element, 'survival_ratio') subelement.text = str(self.survival_ratio) From fbb15496db978693cb5df9e963d69853b6f1ee9f Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 18 Jul 2022 21:33:37 +0100 Subject: [PATCH 0602/2654] boundary_type review suggestion from @pshriwise --- openmc/universe.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 989b50c73..959717b6a 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -746,7 +746,13 @@ class DAGMCUniverse(UniverseBase): import math bounding_box_center = (bounding_box[0] + bounding_box[1])/2 radius = math.dist(bounding_box[0], bounding_box[1]) - bounding_surface = openmc.Sphere(x0=bounding_box_center[0], y0=bounding_box_center[1], z0=bounding_box_center[2], r=radius) + bounding_surface = openmc.Sphere( + x0=bounding_box_center[0], + y0=bounding_box_center[1], + z0=bounding_box_center[2], + boundary_type=boundary_type, + r=radius, + ) return -bounding_surface From ae4556adda4112565f99e1c5b9153a143a322a41 Mon Sep 17 00:00:00 2001 From: Richard Morrison Date: Mon, 18 Jul 2022 23:51:14 +0100 Subject: [PATCH 0603/2654] flushing stdout --- src/output.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/output.cpp b/src/output.cpp index 0bd9693a8..56fea4db9 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -2,6 +2,7 @@ #include // for transform, max #include // for strlen +#include // for stdout #include // for time, localtime #include #include // for setw, setprecision, put_time @@ -94,6 +95,7 @@ void title() fmt::print(" OpenMP Threads | {}\n", omp_get_max_threads()); #endif fmt::print("\n"); + std::fflush(stdout); } //============================================================================== @@ -134,6 +136,7 @@ void header(const char* msg, int level) // Print header based on verbosity level. if (settings::verbosity >= level) fmt::print("\n{}\n\n", out); + std::fflush(stdout); } //============================================================================== @@ -380,6 +383,7 @@ void print_generation() fmt::print(" {:8.5f} +/-{:8.5f}", simulation::keff, simulation::keff_std); } fmt::print("\n"); + std::fflush(stdout); } //============================================================================== @@ -547,6 +551,7 @@ void print_results() gt(GlobalTally::LEAKAGE, TallyResult::SUM) / n); } fmt::print("\n"); + std::fflush(stdout); } //============================================================================== From e72f97c4ed25e9b7c271bdd4f106afc89a4dd2ae Mon Sep 17 00:00:00 2001 From: Richard Morrison Date: Tue, 19 Jul 2022 00:04:28 +0100 Subject: [PATCH 0604/2654] Dockerfile ARGS to global scope --- Dockerfile | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index c83460f35..158fed43d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,14 +15,16 @@ # sudo docker run image_name:tag_name or ID with no tag sudo docker run ID number -FROM debian:bullseye-slim AS dependencies + +# global ARG as these ARGS are used in multiple stages +# By default one core is used to compile +ARG compile_cores=1 # By default this Dockerfile builds OpenMC without DAGMC and LIBMESH support ARG build_dagmc=off ARG build_libmesh=off -# By default one core is used to compile -ARG compile_cores=1 +FROM debian:bullseye-slim AS dependencies # Set default value of HOME to /root ENV HOME=/root @@ -56,7 +58,6 @@ ENV NJOY_REPO='https://github.com/njoy/NJOY2016' # Setup environment variables for Docker image ENV LD_LIBRARY_PATH=${DAGMC_INSTALL_DIR}/lib:$LD_LIBRARY_PATH \ - OPENMC_CROSS_SECTIONS=/root/nndc_hdf5/cross_sections.xml \ OPENMC_ENDF_DATA=/root/endf-b-vii.1 \ DEBIAN_FRONTEND=noninteractive @@ -175,9 +176,6 @@ ENV HOME=/root ARG openmc_branch=master ENV OPENMC_REPO='https://github.com/openmc-dev/openmc' -ARG build_dagmc -ARG build_libmesh - ENV DAGMC_INSTALL_DIR=$HOME/DAGMC/ ENV LIBMESH_INSTALL_DIR=$HOME/LIBMESH @@ -219,6 +217,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ FROM build AS release ENV HOME=/root +ENV OPENMC_CROSS_SECTIONS=/root/nndc_hdf5/cross_sections.xml # Download cross sections (NNDC and WMP) and ENDF data needed by test suite RUN ${HOME}/OpenMC/openmc/tools/ci/download-xs.sh From c8fb5eb2bdbacfc53d4280030ecae99cf25f0157 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 19 Jul 2022 11:43:28 +0100 Subject: [PATCH 0605/2654] updated comparison input --- .../dagmc/universes/inputs_true.dat | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index 4443f9a35..1a5ca7486 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,8 +1,8 @@ - + - + 24.0 24.0 2 2 -24.0 -24.0 @@ -10,12 +10,12 @@ 9 9 9 9 - - - - - - + + + + + + From efa92ad865d7abee86bd21524164433d96957185 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 19 Jul 2022 10:05:47 -0500 Subject: [PATCH 0606/2654] Address pauromano's comments --- openmc/deplete/openmc_operator.py | 3 --- openmc/deplete/operator.py | 9 ++++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 047a7f967..e057b3467 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -4,15 +4,12 @@ This module implements functions used by both OpenMC transport operators as well """ -import copy from abc import abstractmethod from collections import OrderedDict import numpy as np -from uncertainties import ufloat import openmc -from openmc.exceptions import DataError from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index d8b84f5a0..b3c0756b8 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -269,20 +269,19 @@ class Operator(OpenMCOperator): for i in range(cell.num_instances)] self.materials = openmc.Materials( - model.geometry.get_all_materials().values() + self.model.geometry.get_all_materials().values() ) def _load_previous_results(self): """Load results from a previous depletion simulation""" # Reload volumes into geometry - prev_results[-1].transfer_volumes(self.model) + self.prev_res[-1].transfer_volumes(self.model) # Store previous results in operator # Distribute reaction rates according to those tracked # on this process - if comm.size == 1: - self.prev_res = prev_results - else: + if comm.size != 1: + prev_results = self.prev_res self.prev_res = Results() mat_indexes = _distribute(range(len(self.burnable_mats))) for res_obj in prev_results: From 3aad43a3baca31897a2b66bbcc9e3c69a73df688 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 19 Jul 2022 11:25:45 -0500 Subject: [PATCH 0607/2654] remove unneeded parameters from OpenMCOperator --- openmc/deplete/flux_operator.py | 369 ++---------------------------- openmc/deplete/openmc_operator.py | 36 +-- openmc/deplete/operator.py | 28 ++- 3 files changed, 43 insertions(+), 390 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index eaa59cbde..9483c324c 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -20,33 +20,14 @@ from openmc.mpi import comm from .abc import TransportOperator, ReactionRateHelper, OperatorResult from .atom_number import AtomNumber from .chain import REACTIONS +from .openmc_operator import OpenMCOperator from .reaction_rates import ReactionRates from .helpers import ConstantFissionYieldHelper, SourceRateHelper valid_rxns = list(REACTIONS) valid_rxns.append('fission') -## delete -def _distribute(items): - """Distribute items across MPI communicator - Parameters - ---------- - items : list - List of items of distribute - Returns - ------- - list - Items assigned to process that called - """ - min_size, extra = divmod(len(items), comm.size) - j = 0 - for i in range(comm.size): - chunk_size = min_size + int(i < extra) - if comm.rank == i: - return items[j:j + chunk_size] - j += chunk_size - -class FluxDepletionOperator(TransportOperator): +class FluxDepletionOperator(OpenMCOperator): """Depletion operator that uses a user-provided flux spectrum and one-group cross sections to calculate reaction rates. @@ -130,7 +111,7 @@ class FluxDepletionOperator(TransportOperator): check_type('nuclides', nuclides, dict, str) check_type('micro_xs', micro_xs, pd.DataFrame) - self.cross_sections = micro_xs + cross_sections = micro_xs if keff is not None: check_type('keff', keff, tuple, float) keff = ufloat(keff) @@ -140,75 +121,20 @@ class FluxDepletionOperator(TransportOperator): materials = self._consolidate_nuclides_to_material(nuclides, volume) diff_burnable_mats=False - #super().__init__( - # materials, - # cross_sections, - # chain_file, - # prev_results, - # diff_burnable_mats, - # normalization_mode, - # None, - # 0.0, - # None, - # fission_yield_opts, - # None, - # None, - # reduce_chain, - # reduce_chain_level) + helper_kwargs = dict() + helper_kwargs['fission_yield_opts'] = fission_yield_opts - ##delete till end of function - super().__init__(chain_file, fission_q, 0.0, prev_results) - self.round_number = False - self.materials = materials - - # Reduce the chain to only those nuclides present - if reduce_chain: - init_nuclides = set() - for material in self.materials: - if not material.depletable: - continue - for name, _dens_percent, _dens_type in material.nuclides: - init_nuclides.add(name) - - self.chain = self.chain.reduce(init_nuclides, reduce_chain_level) - - if diff_burnable_mats: - ## to implement - self._differentiate_burnable_mats() - - # Determine which nuclides have cross section data - # This nuclides variables contains every nuclides - # for which there is an entry in the micro_xs parameter - openmc.reset_auto_ids() - self.burnable_mats, volumes, all_nuclides = self._get_burnable_mats() - self._all_nuclides = all_nuclides - self.local_mats = _distribute(self.burnable_mats) - - self._mat_index_map = { - lm: self.burnable_mats.index(lm) for lm in self.local_mats} - - if self.prev_res is not None: - ## will be an abstract function for OpenMCOperator - self._load_previous_results() - - - self.nuclides_with_data = self._get_nuclides_with_data(self.cross_sections) - - # Select nuclides with data that are also in the chain - self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides - if nuc.name in self.nuclides_with_data] - - # Extract number densities from the geometry / previous depletion run - self._extract_number(self.local_mats, - volumes, - all_nuclides, - self.prev_res) - - # Create reaction rates array - self.reaction_rates = ReactionRates( - self.local_mats, self._burnable_nucs, self.chain.reactions) - - self._get_helper_classes(None, fission_yield_opts) + super().__init__( + materials, + cross_sections, + chain_file, + prev_results, + diff_burnable_mats, + fission_q, + 0.0, + helper_kwargs, + reduce_chain, + reduce_chain_level) def _consolidate_nuclides_to_material(self, nuclides, volume): """Puts nuclide list into an openmc.Materials object. @@ -224,58 +150,10 @@ class FluxDepletionOperator(TransportOperator): return openmc.Materials([mat]) - def _differentiate_burnable_materials(): + def _differentiate_burnable_mats(): """Assign distribmats for each burnable material""" pass - ##delete - def _get_burnable_mats(self): - """Determine depletable materials, volumes, and nuclides - Returns - ------- - burnable_mats : list of str - List of burnable material IDs - volume : OrderedDict of str to float - Volume of each material in [cm^3] - nuclides : list of str - Nuclides in order of how they'll appear in the simulation. - """ - - burnable_mats = set() - model_nuclides = set() - volume = OrderedDict() - - self.heavy_metal = 0.0 - - # Iterate once through the geometry to get dictionaries - for mat in self.materials: - for nuclide in mat.get_nuclides(): - model_nuclides.add(nuclide) - if mat.depletable: - burnable_mats.add(str(mat.id)) - if mat.volume is None: - raise RuntimeError("Volume not specified for depletable " - "material with ID={}.".format(mat.id)) - volume[str(mat.id)] = mat.volume - self.heavy_metal += mat.fissionable_mass - - # Make sure there are burnable materials - if not burnable_mats: - raise RuntimeError( - "No depletable materials were found in the model.") - - # Sort the sets - burnable_mats = sorted(burnable_mats, key=int) - model_nuclides = sorted(model_nuclides) - - # Construct a global nuclide dictionary, burned first - nuclides = list(self.chain.nuclide_dict) - for nuc in model_nuclides: - if nuc not in nuclides: - nuclides.append(nuc) - - return burnable_mats, volume, nuclides - def _load_previous_results(): """Load in results from a previous depletion calculation.""" pass @@ -285,53 +163,6 @@ class FluxDepletionOperator(TransportOperator): """ return set(cross_sections.index) - ##delete - def _extract_number(self, local_mats, volume, nuclides, prev_res=None): - """Construct AtomNumber using geometry - - Parameters - ---------- - local_mats : list of str - Material IDs to be managed by this process - volume : OrderedDict of str to float - Volumes for the above materials in [cm^3] - nuclides : list of str - Nuclides to be used in the simulation. - prev_res : Results, optional - Results from a previous depletion calculation - - """ - self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain)) - - if self.dilute_initial != 0.0: - for nuc in self._burnable_nucs: - self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial) - - # Now extract and store the number densities - # From the geometry if no previous depletion results - if prev_res is None: - for mat in self.materials: - if str(mat.id) in local_mats: - self._set_number_from_mat(mat) - # Else from previous depletion results - else: - raise RuntimeError( - "Loading from previous results not yet supported") - - ##delete - def _set_number_from_mat(self, mat): - """Extracts material and number densities from openmc.Material - Parameters - ---------- - mat : openmc.Material - The material to read from - """ - mat_id = str(mat.id) - - for nuclide, atom_per_bcm in mat.get_nuclide_atom_densities().items(): - atom_per_cc = atom_per_bcm * 1.0e24 - self.number.set_atom_density(mat_id, nuclide, atom_per_cc) - class FluxTimesXSHelper(ReactionRateHelper): """Class for generating one-group reaction rates with flux and one-group cross sections. @@ -389,8 +220,11 @@ class FluxDepletionOperator(TransportOperator): return self._results_cache - def _get_helper_classes(self, reaction_rate_opts, fission_yield_opts): + def _get_helper_classes(self, helper_kwargs): """Get helper classes for calculating reation rates and fission yields""" + + fission_yield_opts = helper_kwargs['fission_yield_opts'] + rates = self.reaction_rates # Get classes to assit working with tallies nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} @@ -419,9 +253,7 @@ class FluxDepletionOperator(TransportOperator): """ # Return number density vector - #return super().initial_condition() - ##delete - return list(self.number.get_mat_slice(np.s_[:])) + return super().initial_condition(self.materials) def __call__(self, vec, source_rate): """Obtain the reaction rates @@ -449,18 +281,6 @@ class FluxDepletionOperator(TransportOperator): op_result = OperatorResult(keff, rates) return copy.deepcopy(op_result) - ##delete - def _update_materials_and_nuclides(self, vec): - # Update the number densities regardless of the source rate - self.number.set_density(vec) - self._update_materials() - - # Get all nuclides for which we will calculate reaction rates - rxn_nuclides = self._get_reaction_nuclides() - self._rate_helper.nuclides = rxn_nuclides - self._normalization_helper.nuclides = rxn_nuclides - self._yield_helper.update_tally_nuclides(rxn_nuclides) - def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" @@ -502,123 +322,6 @@ class FluxDepletionOperator(TransportOperator): # TODO Update densities on the Python side, otherwise the # summary.h5 file contains densities at the first time step - ##delete - def _get_reaction_nuclides(self): - """Determine nuclides that should have reaction rates - - This method returns a list of all nuclides that have neutron data and - are listed in the depletion chain. Technically, we should list nuclides - that may not appear in the depletion chain because we still need to get - the fission reaction rate for these nuclides in order to normalize - power, but that is left as a future exercise. - - Returns - ------- - list of str - nuclides with reaction rates - - """ - # Create the set of all nuclides in the decay chain in materials marked - # for burning in which the number density is greater than zero. - nuc_set = set() - - for nuc in self.number.nuclides: - if nuc in self.nuclides_with_data: - if np.sum(self.number[:,nuc]) > 0.0: - nuc_set.add(nuc) - - # Communicate which nuclides have nonzeros to rank 0 - if comm.rank == 0: - for i in range(1, comm.size): - nuc_newset = comm.recv(source=i, tag=i) - nuc_set |= nuc_newset - else: - comm.send(nuc_set, dest=0, tag=comm.rank) - - if comm.rank == 0: - # Sort nuclides in the same order as self.number - nuc_list = [nuc for nuc in self.number.nuclides - if nuc in nuc_set] - else: - nuc_list = None - - # Store list of tally nuclides on each process - nuc_list = comm.bcast(nuc_list) - return [nuc for nuc in nuc_list if nuc in self.chain] - - ##delete - def _calculate_reaction_rates(self, source_rate): - - rates = self.reaction_rates - rates.fill(0.0) - - rxn_nuclides = self._rate_helper.nuclides - - # Form fast map - nuc_ind = [rates.index_nuc[nuc] for nuc in rxn_nuclides] - react_ind = [rates.index_rx[react] for react in self.chain.reactions] - - self._normalization_helper.reset() - self._yield_helper.unpack() - - # Store fission yield dictionaries - fission_yields = [] - - # Create arrays to store fission Q values, reaction rates, and nuclide - # numbers, zeroed out in material iteration - number = np.empty(rates.n_nuc) - - fission_ind = rates.index_rx.get("fission") - - for i, mat in enumerate(self.local_mats): - mat_index = self._mat_index_map[mat] - - # Zero out reaction rates and nuclide numbers - number.fill(0.0) - - # Get new number densities - for nuc, i_nuc_results in zip(rxn_nuclides, nuc_ind): - number[i_nuc_results] = self.number[mat, nuc] - - # Calculate macroscopic cross sections and store them in rates array - rxn_rates = self._rate_helper.get_material_rates( - mat_index, nuc_ind, react_ind) - - ## replace - #for nuc in rxn_nuclides: - # density = self.number.get_atom_density(i, nuc) - # for rxn in self.chain.reactions: - # rates.set( - # i, - # nuc, - # rxn, - # self.cross_sections[rxn, nuc] * density) - - # Compute fission yields for this material - fission_yields.append(self._yield_helper.weighted_yields(i)) - - # Accumulate energy from fission - if fission_ind is not None: - self._normalization_helper.update(rxn_rates[:, fission_ind]) - - # Divide by total number of atoms and store - # the reason we do this is based on the mathematical equation; - # in the equation, we multiply the depletion matrix by the nuclide - # vector. Since what we want is the depletion matrix, we need to - # divide the reaction rates by the number of atoms to get the right - # units. - rates[i] = self._rate_helper.divide_by_adens(number) - - rates *= self._normalization_helper.factor(source_rate) - ##replace - # Get reaction rate in reactions/sec - #rates *= self.flux_spectra - - - # Store new fission yields on the chain - self.chain.fission_yields = fission_yields - - return rates def write_bos_data(self, step): """Document beginning of step data for a given step @@ -634,34 +337,6 @@ class FluxDepletionOperator(TransportOperator): # Since we aren't running a transport simulation, we simply pass pass - ##delete - def get_results_info(self): - """Returns volume list, cell lists, and nuc lists. - - Returns - ------- - volume : dict of str to float - Volumes corresponding to materials in burn_list - nuc_list : list of str - A list of all nuclide names. Used for sorting the simulation. - burn_list : list of int - A list of all cell IDs to be burned. Used for sorting the - simulation. - full_burn_list : list of int - All burnable materials in the geometry. - """ - nuc_list = self.number.burnable_nuclides - burn_list = self.local_mats - - volume = {} - for i, mat in enumerate(burn_list): - volume[mat] = self.number.volume[i] - - # Combine volume dictionaries across processes - volume_list = comm.allgather(volume) - volume = {k: v for d in volume_list for k, v in d.items()} - - return volume, nuc_list, burn_list, burn_list @staticmethod def create_micro_xs_from_data_array( diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index e057b3467..536f67c4b 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -67,8 +67,6 @@ class OpenMCOperator(TransportOperator): Whether to differentiate burnable materials with multiple instances. Volumes are divided equally from the original material volume. Default: False. - normalization_mode : str - Indicate how reaction rates should be normalized. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. dilute_initial : float, optional @@ -76,17 +74,8 @@ class OpenMCOperator(TransportOperator): in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. Defaults to 1.0e3. - fission_yield_mode : str - Key indicating what fission product yield scheme to use. - fission_yield_opts : dict of str to option, optional - Optional arguments to pass to the helper determined by - ``fission_yield_mode``. Will be passed directly on to the - helper. Passing a value of None will use the defaults for - the associated helper. - reaction_rate_mode : str, optional - Indicate how one-group reaction rates should be calculated. - reaction_rate_opts : dict, optional - Keyword arguments that are passed to the reaction rate helper class. + helper_kwargs : dict + Arguments for helper classes reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. Default is False. @@ -136,13 +125,9 @@ class OpenMCOperator(TransportOperator): chain_file=None, prev_results=None, diff_burnable_mats=False, - normalization_mode=None, fission_q=None, dilute_initial=0.0, - fission_yield_mode=None, - fission_yield_opts=None, - reaction_rate_mode=None, - reaction_rate_opts=None, + helper_kwargs=None, reduce_chain=False, reduce_chain_level=None): @@ -195,12 +180,7 @@ class OpenMCOperator(TransportOperator): self.reaction_rates = ReactionRates( self.local_mats, self._burnable_nucs, self.chain.reactions) - self._get_helper_classes( - reaction_rate_mode, - normalization_mode, - fission_yield_mode, - reaction_rate_opts, - fission_yield_opts) + self._get_helper_classes(helper_kwargs) @abstractmethod def _differentiate_burnable_mats(self): @@ -363,13 +343,7 @@ class OpenMCOperator(TransportOperator): self.number.set_atom_density(mat_id, nuclide, atom_per_cc) @abstractmethod - def _get_helper_classes( - self, - reaction_rate_mode, - normalization_mode, - fission_yield_mode, - reaction_rate_opts, - fission_yield_opts): + def _get_helper_classes(self, helper_kwargs): """Create the ``_rate_helper``, ``_normalization_helper``, and ``_yield_helper`` objects. diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index b3c0756b8..c5538712d 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -227,19 +227,22 @@ class Operator(OpenMCOperator): self.cleanup_when_done = True + helper_kwargs = dict() + helper_kwargs['reaction_rate_mode'] = reaction_rate_mode + helper_kwargs['normalization_mode'] = normalization_mode + helper_kwargs['fission_yield_mode'] = fission_yield_mode + helper_kwargs['reaction_rate_opts'] = reaction_rate_opts + helper_kwargs['fission_yield_opts'] = fission_yield_opts + super().__init__( model.materials, cross_sections, chain_file, prev_results, diff_burnable_mats, - normalization_mode, fission_q, dilute_initial, - fission_yield_mode, - fission_yield_opts, - reaction_rate_mode, - reaction_rate_opts, + helper_kwargs, reduce_chain, reduce_chain_level) @@ -313,18 +316,13 @@ class Operator(OpenMCOperator): return nuclides - def _get_helper_classes( - self, - reaction_rate_mode, - normalization_mode, - fission_yield_mode, - reaction_rate_opts, - fission_yield_opts): + def _get_helper_classes(self, helper_kwargs): """Create the ``_rate_helper``, ``_normalization_helper``, and ``_yield_helper`` objects. Parameters ---------- + **kwargs : ... reaction_rate_mode : str Indicates the subclass of :class:`ReactionRateHelper` to instantiate. @@ -341,6 +339,12 @@ class Operator(OpenMCOperator): subclass. """ + reaction_rate_mode = helper_kwargs['reaction_rate_mode'] + normalization_mode = helper_kwargs['normalization_mode'] + fission_yield_mode = helper_kwargs['fission_yield_mode'] + reaction_rate_opts = helper_kwargs['reaction_rate_opts'] + fission_yield_opts = helper_kwargs['fission_yield_opts'] + # Get classes to assist working with tallies if reaction_rate_mode == "direct": self._rate_helper = DirectReactionRateHelper( From 3817750bff837c8c47b58c0e141ea57be5881df2 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 19 Jul 2022 12:20:22 -0500 Subject: [PATCH 0608/2654] fix Operator syntax in UG Chapter 8 example --- docs/source/usersguide/depletion.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index fe3f12dc4..07a7c9645 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -112,13 +112,16 @@ should be, including indirect components. Some examples are provided below:: # use a dictionary of fission_q values fission_q = {"U235": 202e+6} # energy in eV + # create a Model object + model = openmc.model.Model(geometry, settings) + # create a modified chain and write it to a new file chain = openmc.deplete.Chain.from_xml("chain.xml", fission_q) chain.export_to_xml("chain_mod_q.xml") - op = openmc.deplete.Operator(geometry, setting, "chain_mod_q.xml") + op = openmc.deplete.Operator(model, "chain_mod_q.xml") # alternatively, pass the modified fission Q directly to the operator - op = openmc.deplete.Operator(geometry, setting, "chain.xml", + op = openmc.deplete.Operator(model, "chain.xml", fission_q=fission_q) From 7e671d4e57918ef396fdf2a02cdc6008351a90f3 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 19 Jul 2022 12:33:56 -0500 Subject: [PATCH 0609/2654] Change defualt constructor to accept a Materials object The classmethod, from_nuclides, retains the volume-nuclide constructor --- docs/source/usersguide/depletion.rst | 24 +++--- openmc/deplete/flux_operator.py | 79 ++++++++++++++----- .../deplete_no_transport/test.py | 2 +- .../unit_tests/test_flux_deplete_operator.py | 2 +- 4 files changed, 76 insertions(+), 31 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 07a7c9645..c58a147a2 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -188,15 +188,22 @@ Transport-independent depletion possible and likely in the near future. OpenMC supports running depletion calculations independent of the OpenMC -transport solver using the :class:`FluxDepletionOperator` class. Rather than -taking a :class:`openmc.model.Model` object, this class accepts a volume, -a dictionary of nuclide concentrations, a flux spectra, and one-group -microscopic cross sections as a :class:`pandas.DataFrame`. The class includes -helper functions to construct the dataframe from a csv file or from -data arrays:: +transport solver using the :class:`FluxDepletionOperator` class. This class +has two ways to initalize it; the default constructor accepts an +:class:`openmc.Materials` object, a flux spectra, and one-group microscopic +cross sections as a :class:`pandas.Dataframe`, while the `from_nuclides` +method accepts a volume and dictionary of nuclide concentrations in place of +the :class:`openmc.Materials` object in addition to the other parameters. +The class includes helper functions to construct the dataframe from a csv file +or from data arrays:: ... + # load in the microscopic cross sections micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_path) + flux = 1.16e15 + op = FluxDepletionOperator(materials, micro_xs, flux, chain_file) + + # alternate construtor nuclides = {'U234': 8.92e18, 'U235': 9.98e20, 'U238': 2.22e22, @@ -204,10 +211,7 @@ data arrays:: 'O16': 4.64e22, 'O17': 1.76e19} volume = 0.5 - flux = 1.16e15 - - op = FluxDepletionOperator(volume, nuclides, micro_xs, flux. chain_file) - + op = FluxDepletionOperator.from_nuclide_dict(volume, nuclides, micro_xs, flux, chain_file) A user can then define an integrator class as they would for a coupled transport-depletion calculation and follow the same steps from there. diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 9483c324c..b52ebd159 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -38,11 +38,8 @@ class FluxDepletionOperator(OpenMCOperator): Parameters ---------- - volume : float - Volume of the material being depleted in [cm^3] - nuclides : dict of str to float - Dictionary with nuclide names as keys and nuclide concentrations as - values. Nuclide concentration units are [atom/cm^3]. + materials : openmc.Materials + Materials to deplete. micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. @@ -88,16 +85,62 @@ class FluxDepletionOperator(OpenMCOperator): results are to be used. """ - # Alternate constructor using a full-fledges Model object - #def __init__(self, model, micro_xs, ...): - # ... - # mode.materials = openmc.Materials(model.geometry.get_all_materials().values()) - # super().__init__(model.materials, ...) + @classmethod + def from_nuclides(cls, volume, nuclides, micro_xs, + flux_spectra, + chain_file, + keff=None, + fission_q=None, + prev_results=None, + reduce_chain=False, + reduce_chain_level=None, + fission_yield_opts=None): + """ + Alternate constructor from a dictionary of nuclide concentrations + volume : float + Volume of the material being depleted in [cm^3] + nuclides : dict of str to float + Dictionary with nuclide names as keys and nuclide concentrations as + values. Nuclide concentration units are [atom/cm^3]. + micro_xs : pandas.DataFrame + DataFrame with nuclides names as index and microscopic cross section + data in the columns. Cross section units are [cm^-2]. + flux_spectra : float + Flux spectrum [n cm^-2 s^-1] + chain_file : str + Path to the depletion chain XML file. + keff : 2-tuple of float, optional + keff eigenvalue and uncertainty from transport calculation. + Default is None. + fission_q : dict, optional + Dictionary of nuclides and their fission Q values [eV]. If not given, + values will be pulled from the ``chain_file``. + prev_results : Results, optional + Results from a previous depletion calculation. + reduce_chain : bool, optional + If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the + depletion chain up to ``reduce_chain_level``. Default is False. + reduce_chain_level : int, optional + Depth of the search when reducing the depletion chain. Only used + if ``reduce_chain`` evaluates to true. The default value of + ``None`` implies no limit on the depth. + """ + check_type('nuclides', nuclides, dict, str) + materials = cls._consolidate_nuclides_to_material(nuclides, volume) + return cls(materials, + micro_xs, + flux_spectra, + chain_file, + keff, + fission_q, + prev_results, + reduce_chain, + reduce_chain_level, + fission_yield_opts) def __init__(self, - volume, - nuclides, + materials, micro_xs, flux_spectra, chain_file, @@ -107,18 +150,15 @@ class FluxDepletionOperator(OpenMCOperator): reduce_chain=False, reduce_chain_level=None, fission_yield_opts=None): - # Validate nuclides and micro-xs parameters - check_type('nuclides', nuclides, dict, str) + # Validate micro-xs parameters + check_type('materials', materials, openmc.Materials) check_type('micro_xs', micro_xs, pd.DataFrame) - - cross_sections = micro_xs if keff is not None: check_type('keff', keff, tuple, float) keff = ufloat(keff) self._keff = keff self.flux_spectra = flux_spectra - materials = self._consolidate_nuclides_to_material(nuclides, volume) diff_burnable_mats=False helper_kwargs = dict() @@ -126,7 +166,7 @@ class FluxDepletionOperator(OpenMCOperator): super().__init__( materials, - cross_sections, + micro_xs, chain_file, prev_results, diff_burnable_mats, @@ -136,7 +176,8 @@ class FluxDepletionOperator(OpenMCOperator): reduce_chain, reduce_chain_level) - def _consolidate_nuclides_to_material(self, nuclides, volume): + @staticmethod + def _consolidate_nuclides_to_material(nuclides, volume): """Puts nuclide list into an openmc.Materials object. """ diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index cdc8c057c..d326a17c1 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -47,7 +47,7 @@ def test_no_transport(run_in_tmpdir, vol_nuc, multiproc): micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) chain_file = Path(__file__).parents[2] / 'chain_simple.xml' flux = 1164719970082145.0 # flux from pincell example - op = FluxDepletionOperator(vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file) + op = FluxDepletionOperator.from_nuclides(vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file) # Power and timesteps dt = [30] # single step diff --git a/tests/unit_tests/test_flux_deplete_operator.py b/tests/unit_tests/test_flux_deplete_operator.py index 99c4e7c8a..315e22cdc 100644 --- a/tests/unit_tests/test_flux_deplete_operator.py +++ b/tests/unit_tests/test_flux_deplete_operator.py @@ -69,5 +69,5 @@ def test_operator_init(): 'O16': 4.639065406771322e+22, 'O17': 1.7588724018066158e+19} micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) - my_flux_operator = FluxDepletionOperator( + nuclide_flux_operator = FluxDepletionOperator.from_nuclides( 1, nuclides, micro_xs, FLUX_SPECTRA, CHAIN_PATH) From 030e14a799fc3f6000b7377b9cebb2b22a70d186 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 19 Jul 2022 12:55:05 -0500 Subject: [PATCH 0610/2654] update name of function in example --- docs/source/usersguide/depletion.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index c58a147a2..8b960f01f 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -211,7 +211,7 @@ or from data arrays:: 'O16': 4.64e22, 'O17': 1.76e19} volume = 0.5 - op = FluxDepletionOperator.from_nuclide_dict(volume, nuclides, micro_xs, flux, chain_file) + op = FluxDepletionOperator.from_nuclides(volume, nuclides, micro_xs, flux, chain_file) A user can then define an integrator class as they would for a coupled transport-depletion calculation and follow the same steps from there. From eefb4020afe5eb59cdcb2a64dc104226a883e88d Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 19 Jul 2022 12:56:12 -0500 Subject: [PATCH 0611/2654] pep8 fixes --- openmc/deplete/flux_operator.py | 60 ++++++++++--------- .../deplete_no_transport/test.py | 13 ++-- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index b52ebd159..f63e72405 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -27,6 +27,7 @@ from .helpers import ConstantFissionYieldHelper, SourceRateHelper valid_rxns = list(REACTIONS) valid_rxns.append('fission') + class FluxDepletionOperator(OpenMCOperator): """Depletion operator that uses a user-provided flux spectrum and one-group cross sections to calculate reaction rates. @@ -87,14 +88,14 @@ class FluxDepletionOperator(OpenMCOperator): @classmethod def from_nuclides(cls, volume, nuclides, micro_xs, - flux_spectra, - chain_file, - keff=None, - fission_q=None, - prev_results=None, - reduce_chain=False, - reduce_chain_level=None, - fission_yield_opts=None): + flux_spectra, + chain_file, + keff=None, + fission_q=None, + prev_results=None, + reduce_chain=False, + reduce_chain_level=None, + fission_yield_opts=None): """ Alternate constructor from a dictionary of nuclide concentrations @@ -129,15 +130,15 @@ class FluxDepletionOperator(OpenMCOperator): check_type('nuclides', nuclides, dict, str) materials = cls._consolidate_nuclides_to_material(nuclides, volume) return cls(materials, - micro_xs, - flux_spectra, - chain_file, - keff, - fission_q, - prev_results, - reduce_chain, - reduce_chain_level, - fission_yield_opts) + micro_xs, + flux_spectra, + chain_file, + keff, + fission_q, + prev_results, + reduce_chain, + reduce_chain_level, + fission_yield_opts) def __init__(self, materials, @@ -160,7 +161,7 @@ class FluxDepletionOperator(OpenMCOperator): self._keff = keff self.flux_spectra = flux_spectra - diff_burnable_mats=False + diff_burnable_mats = False helper_kwargs = dict() helper_kwargs['fission_yield_opts'] = fission_yield_opts @@ -184,7 +185,7 @@ class FluxDepletionOperator(OpenMCOperator): openmc.reset_auto_ids() mat = openmc.Material() for nuc, conc in nuclides.items(): - mat.add_nuclide(nuc, conc / 1e24) #convert to at/b-cm + mat.add_nuclide(nuc, conc / 1e24) # convert to at/b-cm mat.volume = volume mat.depleteable = True @@ -231,6 +232,7 @@ class FluxDepletionOperator(OpenMCOperator): Dictionary mapping reaction index to reaction name """ + def __init__(self, n_nuc, n_react, outer): super().__init__(n_nuc, n_react) self.outer = outer @@ -253,11 +255,13 @@ class FluxDepletionOperator(OpenMCOperator): Ordering of reactions """ self._results_cache.fill(0.0) - for i, (i_nuc, i_react) in enumerate(product(nuc_index, react_index)): + for i, (i_nuc, i_react) in enumerate( + product(nuc_index, react_index)): nuc = self.nuc_ind_map[i_nuc] rxn = self.rxn_ind_map[i_react] density = self.outer.number.get_atom_density(mat_id, nuc) - self._results_cache[i_nuc, i_react] = self.outer.cross_sections[rxn][nuc] * density + self._results_cache[i_nuc, + i_react] = self.outer.cross_sections[rxn][nuc] * density return self._results_cache @@ -271,7 +275,8 @@ class FluxDepletionOperator(OpenMCOperator): nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} - self._rate_helper = self.FluxTimesXSHelper(self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) + self._rate_helper = self.FluxTimesXSHelper( + self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) self._rate_helper.nuc_ind_map = nuc_ind_map self._rate_helper.rxn_ind_map = rxn_ind_map @@ -378,7 +383,6 @@ class FluxDepletionOperator(OpenMCOperator): # Since we aren't running a transport simulation, we simply pass pass - @staticmethod def create_micro_xs_from_data_array( nuclides, reactions, data, units='barn'): @@ -411,7 +415,8 @@ class FluxDepletionOperator(OpenMCOperator): f'reactions array of length {len(reactions)} do not ' f'match dimensions of data array of shape {data.shape}') - FluxDepletionOperator._validate_micro_xs_inputs(nuclides, reactions, data) + FluxDepletionOperator._validate_micro_xs_inputs( + nuclides, reactions, data) # Convert to cm^2 if units == 'barn': @@ -441,8 +446,8 @@ class FluxDepletionOperator(OpenMCOperator): micro_xs = pd.read_csv(csv_file, index_col=0) FluxDepletionOperator._validate_micro_xs_inputs(list(micro_xs.index), - list(micro_xs.columns), - micro_xs.to_numpy()) + list(micro_xs.columns), + micro_xs.to_numpy()) if units == 'barn': micro_xs /= 1e24 @@ -457,6 +462,3 @@ class FluxDepletionOperator(OpenMCOperator): check_type('data', data, np.ndarray, expected_iter_type=float) for reaction in reactions: check_value('reactions', reaction, valid_rxns) - - - diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index d326a17c1..f82a342cf 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -46,16 +46,18 @@ def test_no_transport(run_in_tmpdir, vol_nuc, multiproc): micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) chain_file = Path(__file__).parents[2] / 'chain_simple.xml' - flux = 1164719970082145.0 # flux from pincell example - op = FluxDepletionOperator.from_nuclides(vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file) + flux = 1164719970082145.0 # flux from pincell example + op = FluxDepletionOperator.from_nuclides( + vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file) # Power and timesteps - dt = [30] # single step - power = 174 # W/cm + dt = [30] # single step + power = 174 # W/cm # Perform simulation using the predictor algorithm openmc.deplete.pool.USE_MULTIPROCESSING = multiproc - openmc.deplete.PredictorIntegrator(op, dt, power, timestep_units='d').integrate() + openmc.deplete.PredictorIntegrator( + op, dt, power, timestep_units='d').integrate() # Get path to test and reference results path_test = op.output_dir / 'depletion_results.h5' @@ -102,4 +104,3 @@ def test_no_transport(run_in_tmpdir, vol_nuc, multiproc): assert correct, "Discrepancy in mat {} and nuc {}\n{}\n{}".format( mat, nuc, y_old, y_test) - From b144f1a0fae08d0069d3bdbb1f24d71e6cff78a5 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 20 Jul 2022 13:22:01 +0100 Subject: [PATCH 0612/2654] added return types to openmc.Settings --- openmc/settings.py | 94 +++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 2d8121659..83a08fd77 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -298,191 +298,191 @@ class Settings: self._max_tracks = None @property - def run_mode(self): + def run_mode(self) -> str: return self._run_mode.value @property - def batches(self): + def batches(self) -> int: return self._batches @property - def generations_per_batch(self): + def generations_per_batch(self) -> int: return self._generations_per_batch @property - def inactive(self): + def inactive(self) -> int: return self._inactive @property - def max_lost_particles(self): + def max_lost_particles(self) -> int: return self._max_lost_particles @property - def rel_max_lost_particles(self): + def rel_max_lost_particles(self) -> int: return self._rel_max_lost_particles @property - def particles(self): + def particles(self) -> int: return self._particles @property - def keff_trigger(self): + def keff_trigger(self) -> dict: return self._keff_trigger @property - def energy_mode(self): + def energy_mode(self) -> str: return self._energy_mode @property - def max_order(self): + def max_order(self) -> int: return self._max_order @property - def source(self): + def source(self) -> Union[Source, typing.Iterable[Source]]: return self._source @property - def confidence_intervals(self): + def confidence_intervals(self) -> bool: return self._confidence_intervals @property - def electron_treatment(self): + def electron_treatment(self) -> str: return self._electron_treatment @property - def ptables(self): + def ptables(self) -> bool: return self._ptables @property - def photon_transport(self): + def photon_transport(self) -> bool: return self._photon_transport @property - def seed(self): + def seed(self) -> int: return self._seed @property - def survival_biasing(self): + def survival_biasing(self) -> bool: return self._survival_biasing @property - def entropy_mesh(self): + def entropy_mesh(self) -> RegularMesh: return self._entropy_mesh @property - def trigger_active(self): + def trigger_active(self) -> bool: return self._trigger_active @property - def trigger_max_batches(self): + def trigger_max_batches(self) -> int: return self._trigger_max_batches @property - def trigger_batch_interval(self): + def trigger_batch_interval(self) -> int: return self._trigger_batch_interval @property - def output(self): + def output(self) -> dict: return self._output @property - def sourcepoint(self): + def sourcepoint(self) -> dict: return self._sourcepoint @property - def statepoint(self): + def statepoint(self) -> dict: return self._statepoint @property - def surf_source_read(self): + def surf_source_read(self) -> dict: return self._surf_source_read @property - def surf_source_write(self): + def surf_source_write(self) -> dict: return self._surf_source_write @property - def no_reduce(self): + def no_reduce(self) -> bool: return self._no_reduce @property - def verbosity(self): + def verbosity(self) -> int: return self._verbosity @property - def tabular_legendre(self): + def tabular_legendre(self) -> dict: return self._tabular_legendre @property - def temperature(self): + def temperature(self) -> dict: return self._temperature @property - def trace(self): + def trace(self) -> typing.Iterable: return self._trace @property - def track(self): + def track(self) -> typing.Iterable[int]: return self._track @property - def cutoff(self): + def cutoff(self) -> dict: return self._cutoff @property - def ufs_mesh(self): + def ufs_mesh(self) -> RegularMesh: return self._ufs_mesh @property - def resonance_scattering(self): + def resonance_scattering(self) -> dict: return self._resonance_scattering @property - def volume_calculations(self): + def volume_calculations(self) -> Union[VolumeCalculation, typing.Iterable[VolumeCalculation]]: return self._volume_calculations @property - def create_fission_neutrons(self): + def create_fission_neutrons(self) -> bool: return self._create_fission_neutrons @property - def delayed_photon_scaling(self): + def delayed_photon_scaling(self) -> bool: return self._delayed_photon_scaling @property - def material_cell_offsets(self): + def material_cell_offsets(self) -> bool: return self._material_cell_offsets @property - def log_grid_bins(self): + def log_grid_bins(self) -> int: return self._log_grid_bins @property - def event_based(self): + def event_based(self) -> bool: return self._event_based @property - def max_particles_in_flight(self): + def max_particles_in_flight(self) -> int: return self._max_particles_in_flight @property - def write_initial_source(self): + def write_initial_source(self) -> bool: return self._write_initial_source @property - def weight_windows(self): + def weight_windows(self) -> Union[WeightWindows, typing.Iterable[WeightWindows]]: return self._weight_windows @property - def weight_windows_on(self): + def weight_windows_on(self) -> bool: return self._weight_windows_on @property - def max_splits(self): + def max_splits(self) -> int: return self._max_splits @property - def max_tracks(self): + def max_tracks(self) -> int: return self._max_tracks @run_mode.setter From 61ad9c977c52df40e012a9818098dbce04974040 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 20 Jul 2022 11:04:39 -0500 Subject: [PATCH 0613/2654] fix Minimal example syntax --- docs/source/pythonapi/deplete.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 1f4321642..cb9adfaaf 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -40,7 +40,8 @@ transport-depletion coupling algorithms `_. SICELIIntegrator SILEQIIntegrator -Each of these classes expects a "transport operator" to be passed. +Each of these classes expects a "transport operator" to be passed. Operators +specific to OpenMC are available using the following classes: .. autosummary:: :toctree: generated @@ -65,11 +66,12 @@ A minimal example for performing depletion would be: >>> import openmc.deplete >>> geometry = openmc.Geometry.from_xml() >>> settings = openmc.Settings.from_xml() + >>> model = openmc.model.Model(geometry, settings) # Representation of a depletion chain >>> chain_file = "chain_casl.xml" >>> operator = openmc.deplete.Operator( - ... geometry, settings, chain_file) + ... model, chain_file) # Set up 5 time steps of one day each >>> dt = [24 * 60 * 60] * 5 From 66206f8b147075e00af37ab0fe867e1a0ada055e Mon Sep 17 00:00:00 2001 From: Richard Morrison Date: Wed, 20 Jul 2022 20:31:12 +0100 Subject: [PATCH 0614/2654] ARG reference, use mpicxx --- Dockerfile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Dockerfile b/Dockerfile index 158fed43d..70bccc041 100644 --- a/Dockerfile +++ b/Dockerfile @@ -176,6 +176,9 @@ ENV HOME=/root ARG openmc_branch=master ENV OPENMC_REPO='https://github.com/openmc-dev/openmc' +ARG build_dagmc +ARG build_libmesh + ENV DAGMC_INSTALL_DIR=$HOME/DAGMC/ ENV LIBMESH_INSTALL_DIR=$HOME/LIBMESH @@ -185,6 +188,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ && mkdir build && cd build ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ + -DCMAKE_CXX_COMPILER=mpicxx \ -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on \ -DOPENMC_USE_DAGMC=on \ @@ -193,6 +197,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ fi ; \ if [ ${build_dagmc} = "on" ] && [ ${build_libmesh} = "off" ]; then \ cmake ../openmc \ + -DCMAKE_CXX_COMPILER=mpicxx \ -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on \ -DOPENMC_USE_DAGMC=ON \ @@ -200,6 +205,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "on" ]; then \ cmake ../openmc \ + -DCMAKE_CXX_COMPILER=mpicxx \ -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on \ -DOPENMC_USE_LIBMESH=on \ @@ -207,6 +213,7 @@ RUN mkdir -p ${HOME}/OpenMC && cd ${HOME}/OpenMC \ fi ; \ if [ ${build_dagmc} = "off" ] && [ ${build_libmesh} = "off" ]; then \ cmake ../openmc \ + -DCMAKE_CXX_COMPILER=mpicxx \ -DOPENMC_USE_MPI=on \ -DHDF5_PREFER_PARALLEL=on ; \ fi ; \ From 56b593d0b5632592260807f84288564968046f66 Mon Sep 17 00:00:00 2001 From: Richard Morrison Date: Wed, 20 Jul 2022 20:40:17 +0100 Subject: [PATCH 0615/2654] compile_cores ARG included in build stages --- Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Dockerfile b/Dockerfile index 70bccc041..d408b9de5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,10 @@ ARG build_libmesh=off FROM debian:bullseye-slim AS dependencies +ARG compile_cores +ARG build_dagmc +ARG build_libmesh + # Set default value of HOME to /root ENV HOME=/root @@ -176,6 +180,7 @@ ENV HOME=/root ARG openmc_branch=master ENV OPENMC_REPO='https://github.com/openmc-dev/openmc' +ARG compile_cores ARG build_dagmc ARG build_libmesh From 4df20f2d6c796cb76af8d8b9eaef73ff272ea60b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 20 Jul 2022 22:32:03 -0500 Subject: [PATCH 0616/2654] Account for neutron wave number in SLBW competitve rho. Closes #907 --- openmc/data/reconstruct.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/data/reconstruct.pyx b/openmc/data/reconstruct.pyx index f63a155b1..cd0bbc38b 100644 --- a/openmc/data/reconstruct.pyx +++ b/openmc/data/reconstruct.pyx @@ -299,8 +299,8 @@ def reconstruct_slbw(slbw, double E): # Determine shift and penetration at modified energy if slbw._competitive[i]: Ex = E + slbw.q_value[l]*(A + 1)/A - rhoc = slbw.channel_radius[l](Ex) - rhochat = slbw.scattering_radius[l](Ex) + rhoc = k*slbw.channel_radius[l](Ex) + rhochat = k*slbw.scattering_radius[l](Ex) P_c, S_c = penetration_shift(l, rhoc) if Ex < 0: P_c = 0 From a27d0e079fe1d69f227e21d55b2d72e8e3e176f5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 20 Jul 2022 22:43:20 -0500 Subject: [PATCH 0617/2654] Allow inplace argument on Region.translate --- openmc/region.py | 13 ++++++++----- openmc/surface.py | 19 +++++++++---------- tests/unit_tests/test_region.py | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/openmc/region.py b/openmc/region.py index 56926187d..4e74a08ad 100644 --- a/openmc/region.py +++ b/openmc/region.py @@ -259,13 +259,16 @@ class Region(ABC): clone[:] = [n.clone(memo) for n in self] return clone - def translate(self, vector, memo=None): + def translate(self, vector, inplace=False, memo=None): """Translate region in given direction Parameters ---------- vector : iterable of float Direction in which region should be translated + inplace : bool + Whether or not to return a region based on new surfaces or one based + on the original surfaces that have been modified. memo : dict or None Dictionary used for memoization. This parameter is used internally and should not be specified by the user. @@ -279,7 +282,7 @@ class Region(ABC): if memo is None: memo = {} - return type(self)(n.translate(vector, memo) for n in self) + return type(self)(n.translate(vector, inplace, memo) for n in self) def rotate(self, rotation, pivot=(0., 0., 0.), order='xyz', inplace=False, memo=None): @@ -308,7 +311,7 @@ class Region(ABC): :math:`\psi` about z. This corresponds to an x-y-z extrinsic rotation as well as a z-y'-x'' intrinsic rotation using Tait-Bryan angles :math:`(\phi, \theta, \psi)`. - inplace : boolean + inplace : bool Whether or not to return a new instance of Surface or to modify the coefficients of this Surface in place. Defaults to False. memo : dict or None @@ -622,10 +625,10 @@ class Complement(Region): clone.node = self.node.clone(memo) return clone - def translate(self, vector, memo=None): + def translate(self, vector, inplace=False, memo=None): if memo is None: memo = {} - return type(self)(self.node.translate(vector, memo)) + return type(self)(self.node.translate(vector, inplace, memo)) def rotate(self, rotation, pivot=(0., 0., 0.), order='xyz', inplace=False, memo=None): diff --git a/openmc/surface.py b/openmc/surface.py index b3bcebb11..2996897a4 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -336,9 +336,9 @@ class Surface(IDManagerMixin, ABC): ---------- vector : iterable of float Direction in which surface should be translated - inplace : boolean + inplace : bool Whether or not to return a new instance of this Surface or to - modify the coefficients of this Surface. Defaults to False + modify the coefficients of this Surface. Returns ------- @@ -374,7 +374,7 @@ class Surface(IDManagerMixin, ABC): :math:`\psi` about z. This corresponds to an x-y-z extrinsic rotation as well as a z-y'-x'' intrinsic rotation using Tait-Bryan angles :math:`(\phi, \theta, \psi)`. - inplace : boolean + inplace : bool Whether or not to return a new instance of Surface or to modify the coefficients of this Surface in place. Defaults to False. @@ -568,9 +568,9 @@ class PlaneMixin: ---------- vector : iterable of float Direction in which surface should be translated - inplace : boolean + inplace : bool Whether or not to return a new instance of a Plane or to modify the - coefficients of this plane. Defaults to False + coefficients of this plane. Returns ------- @@ -1012,9 +1012,8 @@ class QuadricMixin: ---------- vector : iterable of float Direction in which surface should be translated - inplace : boolean + inplace : bool Whether to return a clone of the Surface or the Surface itself. - Defaults to False Returns ------- @@ -2563,7 +2562,7 @@ class Halfspace(Region): clone.surface = self.surface.clone(memo) return clone - def translate(self, vector, memo=None): + def translate(self, vector, inplace=False, memo=None): """Translate half-space in given direction Parameters @@ -2585,7 +2584,7 @@ class Halfspace(Region): # If translated surface not in memo, add it key = (self.surface, tuple(vector)) if key not in memo: - memo[key] = self.surface.translate(vector) + memo[key] = self.surface.translate(vector, inplace) # Return translated half-space return type(self)(memo[key], self.side) @@ -2617,7 +2616,7 @@ class Halfspace(Region): :math:`\psi` about z. This corresponds to an x-y-z extrinsic rotation as well as a z-y'-x'' intrinsic rotation using Tait-Bryan angles :math:`(\phi, \theta, \psi)`. - inplace : boolean + inplace : bool Whether or not to return a new instance of Surface or to modify the coefficients of this Surface in place. Defaults to False. memo : dict or None diff --git a/tests/unit_tests/test_region.py b/tests/unit_tests/test_region.py index 8537e3b80..086ce6401 100644 --- a/tests/unit_tests/test_region.py +++ b/tests/unit_tests/test_region.py @@ -208,3 +208,17 @@ def test_from_expression(reset): # Opening parenthesis immediately after halfspace r = openmc.Region.from_expression('1(2|-3)', surfs) assert str(r) == '(1 (2 | -3))' + + +def test_translate_inplace(): + sph = openmc.Sphere() + x = openmc.XPlane() + region = -sph & +x + + # Translating a region should produce new surfaces + region2 = region.translate((0.5, -6.7, 3.9), inplace=False) + assert str(region) != str(region2) + + # Translating a region in-place should *not* produce new surfaces + region3 = region.translate((0.5, -6.7, 3.9), inplace=True) + assert str(region) == str(region3) From 8bf727022f18d87878d3837b663d33bae0aa4b7b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 21 Jul 2022 09:12:08 +0100 Subject: [PATCH 0618/2654] return types corrections by @paulromano Co-authored-by: Paul Romano --- openmc/settings.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 83a08fd77..5b5c265f6 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -318,7 +318,7 @@ class Settings: return self._max_lost_particles @property - def rel_max_lost_particles(self) -> int: + def rel_max_lost_particles(self) -> float: return self._rel_max_lost_particles @property @@ -338,7 +338,7 @@ class Settings: return self._max_order @property - def source(self) -> Union[Source, typing.Iterable[Source]]: + def source(self) -> typing.List[Source]: return self._source @property @@ -422,7 +422,7 @@ class Settings: return self._trace @property - def track(self) -> typing.Iterable[int]: + def track(self) -> typing.Iterable[typing.Iterable[int]]: return self._track @property @@ -438,7 +438,7 @@ class Settings: return self._resonance_scattering @property - def volume_calculations(self) -> Union[VolumeCalculation, typing.Iterable[VolumeCalculation]]: + def volume_calculations(self) -> typing.List[VolumeCalculation]: return self._volume_calculations @property @@ -470,7 +470,7 @@ class Settings: return self._write_initial_source @property - def weight_windows(self) -> Union[WeightWindows, typing.Iterable[WeightWindows]]: + def weight_windows(self) -> typing.List[WeightWindows]: return self._weight_windows @property From 035b0df3d85e22693d8206cc662efdee1b7557e7 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 21 Jul 2022 09:14:15 +0100 Subject: [PATCH 0619/2654] corrected rel_max_lost_particles type --- openmc/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 5b5c265f6..47c61e6ae 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -75,7 +75,7 @@ class Settings: Maximum number of lost particles .. versionadded:: 0.12 - rel_max_lost_particles : int + rel_max_lost_particles : float Maximum number of lost particles, relative to the total number of particles .. versionadded:: 0.12 @@ -517,7 +517,7 @@ class Settings: self._max_lost_particles = max_lost_particles @rel_max_lost_particles.setter - def rel_max_lost_particles(self, rel_max_lost_particles: int): + def rel_max_lost_particles(self, rel_max_lost_particles: float): cv.check_type('rel_max_lost_particles', rel_max_lost_particles, Real) cv.check_greater_than('rel_max_lost_particles', rel_max_lost_particles, 0) cv.check_less_than('rel_max_lost_particles', rel_max_lost_particles, 1) From ada2493a6b901aba7e404da2ca90f14ea9c166f6 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 21 Jul 2022 12:05:31 +0100 Subject: [PATCH 0620/2654] changed auto_geom_ids approach --- openmc/universe.py | 10 +--------- src/dagmc.cpp | 4 +++- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 959717b6a..5bcbfde46 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -767,26 +767,18 @@ class DAGMCUniverse(UniverseBase): return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z - def bounded_universe(self, auto_geom_ids=True, **kwargs): + def bounded_universe(self, **kwargs): """Returns an openmc.Universe filled with this DAGMCUniverse and bounded with a cell. Defaults to a box cell with a vacuum surface however this can be changed using the kwargs which are passed directly to DAGMCUniverse.bounding_region(). - Parameters - ---------- - auto_geom_ids : bool - Set IDs automatically on initialization (True) or report overlaps - in ID space between CSG and DAGMC (False). Defaults to True to avoid - overlapping ID numbers between the CSG and DAGMC geometry ID numbers - Returns ------- openmc.Universe Universe instance """ - self.auto_geom_ids = auto_geom_ids bounding_cell = openmc.Cell(fill=self, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 8ce5aabda..c9a6e6ad2 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -183,7 +183,9 @@ void DAGUniverse::init_geometry() } else { warning(fmt::format("DAGMC Cell IDs: {}", dagmc_ids_for_dim(3))); fatal_error(fmt::format("Cell ID {} exists in both DAGMC Universe {} " - "and the CSG geometry.", + "and the CSG geometry. Setting auto_geom_ids + to True when initiating the DAGMC Universe may + resolve this issue", c->id_, this->id_)); } From 0256fe90d47a642ace88b5c6168fde50f832920b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 21 Jul 2022 16:11:57 +0100 Subject: [PATCH 0621/2654] corrected end of line --- src/dagmc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index c9a6e6ad2..dc3bc2b2c 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -183,9 +183,9 @@ void DAGUniverse::init_geometry() } else { warning(fmt::format("DAGMC Cell IDs: {}", dagmc_ids_for_dim(3))); fatal_error(fmt::format("Cell ID {} exists in both DAGMC Universe {} " - "and the CSG geometry. Setting auto_geom_ids - to True when initiating the DAGMC Universe may - resolve this issue", + "and the CSG geometry. Setting auto_geom_ids " + "to True when initiating the DAGMC Universe may " + "resolve this issue", c->id_, this->id_)); } From 06f34b9f232256c0968b1a3ab10132754018bef9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 11:00:45 -0500 Subject: [PATCH 0622/2654] address most of paulromano's comments --- docs/source/usersguide/depletion.rst | 8 +- openmc/deplete/flux_operator.py | 234 +++++++++--------- openmc/deplete/openmc_operator.py | 46 ++-- openmc/deplete/operator.py | 58 ++--- .../unit_tests/test_flux_deplete_operator.py | 2 +- 5 files changed, 159 insertions(+), 189 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 8b960f01f..4ce495623 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -113,7 +113,7 @@ should be, including indirect components. Some examples are provided below:: fission_q = {"U235": 202e+6} # energy in eV # create a Model object - model = openmc.model.Model(geometry, settings) + model = openmc.Model(geometry, settings) # create a modified chain and write it to a new file chain = openmc.deplete.Chain.from_xml("chain.xml", fission_q) @@ -180,7 +180,7 @@ across all material instances. number of tallies and material definitions. Transport-independent depletion -------------------------------- +=============================== .. note:: @@ -188,10 +188,10 @@ Transport-independent depletion possible and likely in the near future. OpenMC supports running depletion calculations independent of the OpenMC -transport solver using the :class:`FluxDepletionOperator` class. This class +transport solver using the :class:`~openmc.deplete.FluxDepletionOperator` class. This class has two ways to initalize it; the default constructor accepts an :class:`openmc.Materials` object, a flux spectra, and one-group microscopic -cross sections as a :class:`pandas.Dataframe`, while the `from_nuclides` +cross sections as a :class:`pandas.DataFrame`, while the `from_nuclides` method accepts a volume and dictionary of nuclide concentrations in place of the :class:`openmc.Materials` object in addition to the other parameters. The class includes helper functions to construct the dataframe from a csv file diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index f63e72405..cfcec242a 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -1,6 +1,6 @@ """Pure depletion operator -This module implements a pure depletion operator that uses user provided fluxes +This module implements a pure depletion operator that uses user- provided fluxes and one-group cross sections. """ @@ -17,25 +17,23 @@ from uncertainties import ufloat import openmc from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.mpi import comm -from .abc import TransportOperator, ReactionRateHelper, OperatorResult -from .atom_number import AtomNumber +from .abc import ReactionRateHelper, OperatorResult from .chain import REACTIONS from .openmc_operator import OpenMCOperator -from .reaction_rates import ReactionRates from .helpers import ConstantFissionYieldHelper, SourceRateHelper -valid_rxns = list(REACTIONS) -valid_rxns.append('fission') +_valid_rxns = list(REACTIONS) +_valid_rxns.append('fission') class FluxDepletionOperator(OpenMCOperator): - """Depletion operator that uses a user-provided flux spectrum and one-group + """Depletion operator that uses a user-provided flux and one-group cross sections to calculate reaction rates. - Instances of this class can be used to perform depletion using one group + Instances of this class can be used to perform depletion using one-group cross sections and constant flux. Normally, a user needn't call methods of this class directly. Instead, an instance of this class is passed to an - integrator class, such as :class:`openmc.deplete.CECMIntegrator` + integrator class, such as :class:`openmc.deplete.CECMIntegrator`. Parameters ---------- @@ -44,8 +42,8 @@ class FluxDepletionOperator(OpenMCOperator): micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. - flux_spectra : float - Flux spectrum [n cm^-2 s^-1] + flux : float + Neutron flux [n cm^-2 s^-1] chain_file : str Path to the depletion chain XML file. keff : 2-tuple of float, optional @@ -63,16 +61,27 @@ class FluxDepletionOperator(OpenMCOperator): Depth of the search when reducing the depletion chain. Only used if ``reduce_chain`` evaluates to true. The default value of ``None`` implies no limit on the depth. + fission_yield_opts : dict of str to option, optional + Optional arguments to pass to the `FissionYieldHelper`. Will be + passed directly on to the helper. Passing a value of None will use + the defaults for the associated helper. Attributes ---------- + materials : openmc.Materials + All materials present in the model + cross_sections : pandas.DataFrame + Object containing one-group cross-sections. + dilute_initial : float + Initial atom density [atoms/cm^3] to add for nuclides that + are zero in initial condition to ensure they exist in the decay + chain. Only done for nuclides with reaction rates. + output_dir : pathlib.Path + Path to output directory to save results. round_number : bool Whether or not to round output to OpenMC to 8 digits. Useful in testing, as OpenMC is incredibly sensitive to exact values. - prev_res : Results or None - Results from a previous depletion calculation. ``None`` if no - results are to be used. number : openmc.deplete.AtomNumber Total number of atoms in simulation. nuclides_with_data : set of str @@ -81,14 +90,55 @@ class FluxDepletionOperator(OpenMCOperator): The depletion chain information necessary to form matrices and tallies. reaction_rates : openmc.deplete.ReactionRates Reaction rates from the last operator step. + burnable_mats : list of str + All burnable material IDs + heavy_metal : float + Initial heavy metal inventory [g] + local_mats : list of str + All burnable material IDs being managed by a single process prev_res : Results or None Results from a previous depletion calculation. ``None`` if no results are to be used. - """ + + """ + + def __init__(self, + materials, + micro_xs, + flux, + chain_file, + keff=None, + fission_q=None, + prev_results=None, + reduce_chain=False, + reduce_chain_level=None, + fission_yield_opts=None): + # Validate micro-xs parameters + check_type('materials', materials, openmc.Materials) + check_type('micro_xs', micro_xs, pd.DataFrame) + if keff is not None: + check_type('keff', keff, tuple, float) + keff = ufloat(*keff) + + self._keff = keff + self.flux = flux + + helper_kwargs = dict() + helper_kwargs = {'fission_yield_opts': fission_yield_opts} + + super().__init__( + materials, + micro_xs, + chain_file, + prev_results, + fission_q=fission_q, + helper_kwargs=helper_kwargs, + reduce_chain=reduce_chain, + reduce_chain_level=reduce_chain_level) @classmethod def from_nuclides(cls, volume, nuclides, micro_xs, - flux_spectra, + flux, chain_file, keff=None, fission_q=None, @@ -107,8 +157,8 @@ class FluxDepletionOperator(OpenMCOperator): micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. - flux_spectra : float - Flux spectrum [n cm^-2 s^-1] + flux : float + Neutron flux [n cm^-2 s^-1] chain_file : str Path to the depletion chain XML file. keff : 2-tuple of float, optional @@ -126,12 +176,17 @@ class FluxDepletionOperator(OpenMCOperator): Depth of the search when reducing the depletion chain. Only used if ``reduce_chain`` evaluates to true. The default value of ``None`` implies no limit on the depth. + fission_yield_opts : dict of str to option, optional + Optional arguments to pass to the `FissionYieldHelper`. Will be + passed directly on to the helper. Passing a value of None will use + the defaults for the associated helper. + """ check_type('nuclides', nuclides, dict, str) materials = cls._consolidate_nuclides_to_material(nuclides, volume) return cls(materials, micro_xs, - flux_spectra, + flux, chain_file, keff, fission_q, @@ -140,42 +195,6 @@ class FluxDepletionOperator(OpenMCOperator): reduce_chain_level, fission_yield_opts) - def __init__(self, - materials, - micro_xs, - flux_spectra, - chain_file, - keff=None, - fission_q=None, - prev_results=None, - reduce_chain=False, - reduce_chain_level=None, - fission_yield_opts=None): - # Validate micro-xs parameters - check_type('materials', materials, openmc.Materials) - check_type('micro_xs', micro_xs, pd.DataFrame) - if keff is not None: - check_type('keff', keff, tuple, float) - keff = ufloat(keff) - - self._keff = keff - self.flux_spectra = flux_spectra - - diff_burnable_mats = False - helper_kwargs = dict() - helper_kwargs['fission_yield_opts'] = fission_yield_opts - - super().__init__( - materials, - micro_xs, - chain_file, - prev_results, - diff_burnable_mats, - fission_q, - 0.0, - helper_kwargs, - reduce_chain, - reduce_chain_level) @staticmethod def _consolidate_nuclides_to_material(nuclides, volume): @@ -185,27 +204,18 @@ class FluxDepletionOperator(OpenMCOperator): openmc.reset_auto_ids() mat = openmc.Material() for nuc, conc in nuclides.items(): - mat.add_nuclide(nuc, conc / 1e24) # convert to at/b-cm + mat.add_nuclide(nuc, conc * 1e-24) # convert to at/b-cm mat.volume = volume - mat.depleteable = True + mat.depletable = True return openmc.Materials([mat]) - def _differentiate_burnable_mats(): - """Assign distribmats for each burnable material""" - pass - - def _load_previous_results(): - """Load in results from a previous depletion calculation.""" - pass - def _get_nuclides_with_data(self, cross_sections): - """Finds nuclides with cross section data - """ + """Finds nuclides with cross section data""" return set(cross_sections.index) - class FluxTimesXSHelper(ReactionRateHelper): + class _FluxDepletionRateHelper(ReactionRateHelper): """Class for generating one-group reaction rates with flux and one-group cross sections. @@ -216,13 +226,14 @@ class FluxDepletionOperator(OpenMCOperator): Parameters ---------- - outer : openmc.deplete.FluxDepletionOperator - Reference to the object encapsulate FluxTimesXSHelper. - We pass this so we don't have to duplicate the ``number`` object. n_nucs : int Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` n_react : int Number of reactions tracked by :class:`openmc.deplete.Operator` + op : openmc.deplete.FluxDepletionOperator + Reference to the object encapsulate _FluxDepletionRateHelper. + We pass this so we don't have to duplicate the ``number`` object. + Attributes ---------- @@ -233,14 +244,17 @@ class FluxDepletionOperator(OpenMCOperator): """ - def __init__(self, n_nuc, n_react, outer): + def __init__(self, n_nuc, n_react, op, nuc_ind_map. rxn_ind_map) super().__init__(n_nuc, n_react) - self.outer = outer - self.nuc_ind_map = None - self.rxn_ind_map = None + self._op = op + rates = self.reaction_rates + # Get classes to assit working with tallies + self.nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} + self.rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} def generate_tallies(self, materials, scores): """Unused in this case""" + pass def get_material_rates(self, mat_id, nuc_index, react_index): """Return 2D array of [nuclide, reaction] reaction rates @@ -255,37 +269,35 @@ class FluxDepletionOperator(OpenMCOperator): Ordering of reactions """ self._results_cache.fill(0.0) - for i, (i_nuc, i_react) in enumerate( - product(nuc_index, react_index)): + for i_nuc, i_react in product(nuc_index, react_index): nuc = self.nuc_ind_map[i_nuc] rxn = self.rxn_ind_map[i_react] - density = self.outer.number.get_atom_density(mat_id, nuc) + density = self._op.number.get_atom_density(mat_id, nuc) self._results_cache[i_nuc, - i_react] = self.outer.cross_sections[rxn][nuc] * density + i_react] = self._op.cross_sections[rxn][nuc] * density return self._results_cache def _get_helper_classes(self, helper_kwargs): - """Get helper classes for calculating reation rates and fission yields""" + """Get helper classes for calculating reation rates and fission yields - fission_yield_opts = helper_kwargs['fission_yield_opts'] + Parameters + ---------- + helper_kwargs : dict + Keyword arguments for helper classes - rates = self.reaction_rates - # Get classes to assit working with tallies - nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} - rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} - self._rate_helper = self.FluxTimesXSHelper( + """ + + fission_yield_opts = helper_kwargs.get('fission_yield_opts', {}) + + self._rate_helper = self._FluxDepletionRateHelper( self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) - self._rate_helper.nuc_ind_map = nuc_ind_map - self._rate_helper.rxn_ind_map = rxn_ind_map self._normalization_helper = SourceRateHelper() # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper - fission_yield_opts = ( - {} if fission_yield_opts is None else fission_yield_opts) self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) @@ -320,8 +332,8 @@ class FluxDepletionOperator(OpenMCOperator): self._update_materials_and_nuclides(vec) - # Use the flux spectra as a "source rate" - rates = self._calculate_reaction_rates(self.flux_spectra) + # Use the flux as a "source rate" + rates = self._calculate_reaction_rates(self.flux) keff = self._keff op_result = OperatorResult(keff, rates) @@ -356,36 +368,14 @@ class FluxDepletionOperator(OpenMCOperator): # negative. CRAM does not guarantee positive # values. if val < -1.0e-21: - print( - "WARNING: nuclide ", - nuc, - " in material ", - mat, - " is negative (density = ", - val, - " at/barn-cm)") + print(f'WARNING: nuclide {nuc} in material' + f'{mat} is negative (density = {val}' + + ' at/barn-cm)') number_i[mat, nuc] = 0.0 - # TODO Update densities on the Python side, otherwise the - # summary.h5 file contains densities at the first time step - - def write_bos_data(self, step): - """Document beginning of step data for a given step - - Called at the beginning of a depletion step and at - the final point in the simulation. - - Parameters - ---------- - step : int - Current depletion step including restarts - """ - # Since we aren't running a transport simulation, we simply pass - pass - @staticmethod - def create_micro_xs_from_data_array( - nuclides, reactions, data, units='barn'): + def create_micro_xs_from_data_array(nuclides, reactions, data, units='barn'): """ Creates a ``micro_xs`` parameter from a dictionary. @@ -420,7 +410,7 @@ class FluxDepletionOperator(OpenMCOperator): # Convert to cm^2 if units == 'barn': - data /= 1e24 + data *= 1e-24 return pd.DataFrame(index=nuclides, columns=reactions, data=data) @@ -450,7 +440,7 @@ class FluxDepletionOperator(OpenMCOperator): micro_xs.to_numpy()) if units == 'barn': - micro_xs /= 1e24 + micro_xs *= 1e-24 return micro_xs @@ -461,4 +451,4 @@ class FluxDepletionOperator(OpenMCOperator): check_iterable_type('reactions', reactions, str) check_type('data', data, np.ndarray, expected_iter_type=float) for reaction in reactions: - check_value('reactions', reaction, valid_rxns) + check_value('reactions', reaction, _valid_rxns) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 536f67c4b..0ea1f093c 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -66,16 +66,14 @@ class OpenMCOperator(TransportOperator): diff_burnable_mats : bool, optional Whether to differentiate burnable materials with multiple instances. Volumes are divided equally from the original material volume. - Default: False. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. dilute_initial : float, optional Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. - Defaults to 1.0e3. helper_kwargs : dict - Arguments for helper classes + Keyword arguments for helper classes reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. Default is False. @@ -89,6 +87,10 @@ class OpenMCOperator(TransportOperator): ---------- materials : openmc.Materials All materials present in the model + cross_sections : str or pandas.DataFrame + Path to continuous energy cross section library, or object + containing one-group cross-sections. + dilute_initial : float Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay @@ -182,9 +184,9 @@ class OpenMCOperator(TransportOperator): self._get_helper_classes(helper_kwargs) - @abstractmethod def _differentiate_burnable_mats(self): """Assign distribmats for each burnable material""" + pass def _get_burnable_mats(self): """Determine depletable materials, volumes, and nuclides @@ -235,9 +237,9 @@ class OpenMCOperator(TransportOperator): return burnable_mats, volume, nuclides - @abstractmethod def _load_previous_results(self): """Load results from a previous depletion simulation""" + pass @abstractmethod def _get_nuclides_with_data(self, cross_sections): @@ -271,9 +273,7 @@ class OpenMCOperator(TransportOperator): Results from a previous depletion calculation """ - self.number = AtomNumber( - local_mats, all_nuclides, volume, len( - self.chain)) + self.number = AtomNumber(local_mats, all_nuclides, volume, len(self.chain)) if self.dilute_initial != 0.0: for nuc in self._burnable_nucs: @@ -349,20 +349,8 @@ class OpenMCOperator(TransportOperator): Parameters ---------- - reaction_rate_mode : str - Indicates the subclass of :class:`ReactionRateHelper` to - instantiate. - normalization_mode : str - Indicates the subclass of :class:`NormalizationHelper` to - instantiate. - fission_yield_mode : str - Indicates the subclass of :class:`FissionYieldHelper` to instatiate. - reaction_rate_opts : dict - Keyword arguments that are passed to the :class:`ReactionRateHelper` - subclass. - fission_yield_opts : dict - Keyword arguments that are passed to the :class:`FissionYieldHelper` - subclass. + helper_kwargs : dict + Keyword arguments for helper classes """ @@ -420,6 +408,20 @@ class OpenMCOperator(TransportOperator): def _update_materials(self): """Updates material compositions in OpenMC on all processes.""" + def write_bos_data(self, step): + """Document beginning of step data for a given step + + Called at the beginning of a depletion step and at + the final point in the simulation. + + Parameters + ---------- + step : int + Current depletion step including restarts + """ + # Since we aren't running a transport simulation, we simply pass + pass + def _get_reaction_nuclides(self): """Determine nuclides that should be tallied for reaction rates. diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index c5538712d..9b083ffe9 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -83,7 +83,6 @@ class Operator(OpenMCOperator): diff_burnable_mats : bool, optional Whether to differentiate burnable materials with multiple instances. Volumes are divided equally from the original material volume. - Default: False. normalization_mode : {"energy-deposition", "fission-q", "source-rate"} Indicate how tally results should be normalized. ``"energy-deposition"`` computes the total energy deposited in the system and uses the ratio of @@ -99,7 +98,6 @@ class Operator(OpenMCOperator): Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay chain. Only done for nuclides with reaction rates. - Defaults to 1.0e3. fission_yield_mode : {"constant", "cutoff", "average"} Key indicating what fission product yield scheme to use. The key determines what fission energy helper is used: @@ -228,11 +226,13 @@ class Operator(OpenMCOperator): self.cleanup_when_done = True helper_kwargs = dict() - helper_kwargs['reaction_rate_mode'] = reaction_rate_mode - helper_kwargs['normalization_mode'] = normalization_mode - helper_kwargs['fission_yield_mode'] = fission_yield_mode - helper_kwargs['reaction_rate_opts'] = reaction_rate_opts - helper_kwargs['fission_yield_opts'] = fission_yield_opts + helper_kwargs = { + 'reaction_rate_mode': reaction_rate_mode, + 'normalization_mode': normalization_mode, + 'fission_yield_mode': fission_yield_mode, + 'reaction_rate_opts': reaction_rate_opts, + 'fission_yield_opts': fission_yield_opts + } super().__init__( model.materials, @@ -322,37 +322,21 @@ class Operator(OpenMCOperator): Parameters ---------- - **kwargs : ... - reaction_rate_mode : str - Indicates the subclass of :class:`ReactionRateHelper` to - instantiate. - normalization_mode : str - Indicates the subclass of :class:`NormalizationHelper` to - instatiate. - fission_yield_mode : str - Indicates the subclass of :class:`FissionYieldHelper` to instantiate. - reaction_rate_opts : dict - Keyword arguments that are passed to the :class:`ReactionRateHelper` - subclass. - fission_yield_opts : dict - Keyword arguments that are passed to the :class:`FissionYieldHelper` - subclass. + helper_kwargs : dict + Keyword arguments for helper classes """ reaction_rate_mode = helper_kwargs['reaction_rate_mode'] normalization_mode = helper_kwargs['normalization_mode'] fission_yield_mode = helper_kwargs['fission_yield_mode'] - reaction_rate_opts = helper_kwargs['reaction_rate_opts'] - fission_yield_opts = helper_kwargs['fission_yield_opts'] + reaction_rate_opts = helper_kwargs.get('reaction_rate_opts', {}) + fission_yield_opts = helper_kwargs.get('fission_yield_opts', {}) # Get classes to assist working with tallies if reaction_rate_mode == "direct": self._rate_helper = DirectReactionRateHelper( self.reaction_rates.n_nuc, self.reaction_rates.n_react) elif reaction_rate_mode == "flux": - if reaction_rate_opts is None: - reaction_rate_opts = {} - # Ensure energy group boundaries were specified if 'energies' not in reaction_rate_opts: raise ValueError( @@ -378,8 +362,6 @@ class Operator(OpenMCOperator): # Select and create fission yield helper fission_helper = self._fission_helpers[fission_yield_mode] - fission_yield_opts = ( - {} if fission_yield_opts is None else fission_yield_opts) self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) @@ -405,8 +387,7 @@ class Operator(OpenMCOperator): openmc.lib.init(intracomm=comm) # Generate tallies in memory - materials = [openmc.lib.materials[int(i)] - for i in self.burnable_mats] + materials = [openmc.lib.materials[int(i)] for i in self.burnable_mats] return super().initial_condition(materials) @@ -500,15 +481,12 @@ class Operator(OpenMCOperator): # negative. CRAM does not guarantee positive # values. if val < -1.0e-21: - print( - "WARNING: nuclide ", - nuc, - " in material ", - mat, - " is negative (density = ", - val, - " at/barn-cm)") - number_i[mat, nuc] = 0.0 + print(f'WARNING: nuclide {nuc} in material' + f'{mat} is negative (density = {val}' + + ' at/barn-cm)') + + number_i[mat, nuc] = 0.0 # Update densities on C API side mat_internal = openmc.lib.materials[int(mat)] diff --git a/tests/unit_tests/test_flux_deplete_operator.py b/tests/unit_tests/test_flux_deplete_operator.py index 315e22cdc..3ae098490 100644 --- a/tests/unit_tests/test_flux_deplete_operator.py +++ b/tests/unit_tests/test_flux_deplete_operator.py @@ -11,7 +11,7 @@ from openmc.deplete.flux_operator import FluxDepletionOperator import pandas as pd import numpy as np -FLUX_SPECTRA = 5e16 +FLUX = 5e16 CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" ONE_GROUP_XS = Path(__file__).parents[1] / "micro_xs_simple.csv" From 0984b29f67099e876ae97435ba1fa85d7e86d06a Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 12:14:47 -0500 Subject: [PATCH 0623/2654] add machinery to do constant-power depletion with FluxDepletionOperator --- openmc/deplete/abc.py | 10 +++- openmc/deplete/atom_number.py | 17 ++++++ openmc/deplete/flux_operator.py | 86 +++++++++++++++++++++++++++---- openmc/deplete/helpers.py | 4 +- openmc/deplete/openmc_operator.py | 2 +- 5 files changed, 104 insertions(+), 15 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 8bbe126df..c00c80399 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -329,7 +329,7 @@ class NormalizationHelper(ABC): `fission_rates` for :meth:`update`. """ - def update(self, fission_rates): + def update(self, fission_rates, mat_index=None): """Update the normalization based on fission rates (only used for energy-based normalization) @@ -339,6 +339,8 @@ class NormalizationHelper(ABC): fission reaction rate for each isotope in the specified material. Should be ordered corresponding to initial ``rate_index`` used in :meth:`prepare` + mat_index : int + Material index """ @property @@ -523,6 +525,8 @@ class Integrator(ABC): Power density of the reactor in [W/gHM]. It is multiplied by initial heavy metal inventory to get total power if ``power`` is not speficied. + flux : float or iterable of float, optional + Neutron flux in [neur/s-cm^2] for each interval in :attr: `timesteps` source_rates : float or iterable of float, optional Source rate in [neutron/sec] for each interval in :attr:`timesteps` @@ -597,8 +601,10 @@ class Integrator(ABC): source_rates = power_density * operator.heavy_metal else: source_rates = [p*operator.heavy_metal for p in power_density] + elif flux is not None: + source_rates = flux elif source_rates is None: - raise ValueError("Either power, power_density, or source_rates must be set") + raise ValueError("Either power, power_density, flux, or source_rates must be set") if not isinstance(source_rates, Iterable): # Ensure that rate is single value if that is the case diff --git a/openmc/deplete/atom_number.py b/openmc/deplete/atom_number.py index 5430ddc35..78ceecca6 100644 --- a/openmc/deplete/atom_number.py +++ b/openmc/deplete/atom_number.py @@ -126,6 +126,23 @@ class AtomNumber: return [nuc for nuc, ind in self.index_nuc.items() if ind < self.n_nuc_burn] + def get_mat_volume(self, mat): + """Return material volume + + Parameters + ---------- + mat : str, int, openmc.Material, or slice + Material index. + + Returns + ------- + float + Material volume in [cm^3] + + """ + mat = self._get_mat_index(mat) + return self.volume[mat] + def get_atom_density(self, mat, nuc): """Return atom density of given material and nuclide diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index cfcec242a..9ff0dee5d 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -54,6 +54,15 @@ class FluxDepletionOperator(OpenMCOperator): values will be pulled from the ``chain_file``. prev_results : Results, optional Results from a previous depletion calculation. + normalization_mode : {"constant-power", "constant-flux"} + Indicate how reaction rates should be calculated. + ``"constant-power"`` uses the fission Q values from the depletion chain to + compute the flux based on the power. ``"constant-flux"`` uses the value stored in `_normalization_helper` as the flux. + fission_q : dict, optional + Dictionary of nuclides and their fission Q values [eV]. If not given, + values will be pulled from the ``chain_file``. Only applicable + if ``"normalization_mode" == "constant-power"``. + reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. Default is False. @@ -108,6 +117,7 @@ class FluxDepletionOperator(OpenMCOperator): flux, chain_file, keff=None, + normalization_mode = 'constant-flux', fission_q=None, prev_results=None, reduce_chain=False, @@ -124,7 +134,8 @@ class FluxDepletionOperator(OpenMCOperator): self.flux = flux helper_kwargs = dict() - helper_kwargs = {'fission_yield_opts': fission_yield_opts} + helper_kwargs = {'normalization_mode': normalization_mode, + 'fission_yield_opts': fission_yield_opts} super().__init__( materials, @@ -152,7 +163,7 @@ class FluxDepletionOperator(OpenMCOperator): volume : float Volume of the material being depleted in [cm^3] nuclides : dict of str to float - Dictionary with nuclide names as keys and nuclide concentrations as + ,Dictionary with nuclide names as keys and nuclide concentrations as values. Nuclide concentration units are [atom/cm^3]. micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section @@ -164,9 +175,15 @@ class FluxDepletionOperator(OpenMCOperator): keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. Default is None. + normalization_mode : {"constant-power", "constant-flux"} + Indicate how reaction rates should be calculated. + ``"constant-power"`` uses the fission Q values from the depletion + chain to compute the flux based on the power. ``"constant-flux"`` + uses the value stored in `_normalization_helper` as the flux. fission_q : dict, optional - Dictionary of nuclides and their fission Q values [eV]. If not given, - values will be pulled from the ``chain_file``. + Dictionary of nuclides and their fission Q values [eV]. If not + given, values will be pulled from the ``chain_file``. Only + applicable if ``"normalization_mode" == "constant-power"``. prev_results : Results, optional Results from a previous depletion calculation. reduce_chain : bool, optional @@ -215,6 +232,49 @@ class FluxDepletionOperator(OpenMCOperator): """Finds nuclides with cross section data""" return set(cross_sections.index) + class _FluxDepletionNormalizationHelper(ChainFissionHelper): + """Class for calculating one-group flux + based on a power. + + flux = Power / X, where X = volume * sum_i(Q_i * fission_micro_xs_i * density_i) + + Parameters + ---------- + op : openmc.deplete.FluxDepletionOperator + Reference to the object encapsulate _FluxDepletionNormalizationHelper. + We pass this so we don't have to duplicate the ``number`` object. + + """ + + def __init__(self, op): + self._op = op + rates = self.reaction_rates + self.nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} + super().__init__() + + def update(self, fission_rates, mat_index=None): + """Update 'energy' produced with fission rates in a material. What this + actually calculates is the quantity X. + + Parameters + ---------- + fission_rates : numpy.ndarray + fission reaction rate for each isotope in the specified + material. Should be ordered corresponding to initial + ``rate_index`` used in :meth:`prepare` + mat_index : int + Material index + + """ + volume = self._op.number.get_mat_volume(mat_index) + densities = np.empty(shape(fission_rates)) + for i_nuc in nuc_ind_map: + nuc = self.nuc_ind_map[i_nuc] + densities[i_nuc] = self._op.number.get_atom_density(mat_index, nuc) + fission_rates = fission_rates * volume * densities + + super.update(fission_rates) + class _FluxDepletionRateHelper(ReactionRateHelper): """Class for generating one-group reaction rates with flux and one-group cross sections. @@ -246,11 +306,11 @@ class FluxDepletionOperator(OpenMCOperator): def __init__(self, n_nuc, n_react, op, nuc_ind_map. rxn_ind_map) super().__init__(n_nuc, n_react) - self._op = op - rates = self.reaction_rates - # Get classes to assit working with tallies + rates = op.reaction_rates + self.nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} self.rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} + self._op = op def generate_tallies(self, materials, scores): """Unused in this case""" @@ -269,12 +329,14 @@ class FluxDepletionOperator(OpenMCOperator): Ordering of reactions """ self._results_cache.fill(0.0) + + volume = self._op.number.get_mat_volume(mat_id) for i_nuc, i_react in product(nuc_index, react_index): nuc = self.nuc_ind_map[i_nuc] rxn = self.rxn_ind_map[i_react] density = self._op.number.get_atom_density(mat_id, nuc) self._results_cache[i_nuc, - i_react] = self._op.cross_sections[rxn][nuc] * density + i_react] = self._op.cross_sections[rxn][nuc] * density * volume return self._results_cache @@ -286,15 +348,17 @@ class FluxDepletionOperator(OpenMCOperator): helper_kwargs : dict Keyword arguments for helper classes - """ + normalization_mode = helper_kwargs['normalization_mode'] fission_yield_opts = helper_kwargs.get('fission_yield_opts', {}) self._rate_helper = self._FluxDepletionRateHelper( self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) - - self._normalization_helper = SourceRateHelper() + if normalization_mode == "constant-power": + self._normalization_helper = self.FluxDepletionNormalizationHelper() + else: + self._normalization_helper = SourceRateHelper() # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 33bd182d7..0aaa3b08a 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -423,7 +423,7 @@ class ChainFissionHelper(EnergyNormalizationHelper): self._fission_q_vector = fission_qs - def update(self, fission_rates): + def update(self, fission_rates, mat_index=None): """Update energy produced with fission rates in a material Parameters @@ -432,6 +432,8 @@ class ChainFissionHelper(EnergyNormalizationHelper): fission reaction rate for each isotope in the specified material. Should be ordered corresponding to initial ``rate_index`` used in :meth:`prepare` + mat_index : int + Unused """ self._energy += dot(fission_rates, self._fission_q_vector) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 0ea1f093c..aafa1adf9 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -527,7 +527,7 @@ class OpenMCOperator(TransportOperator): # Accumulate energy from fission if fission_ind is not None: - self._normalization_helper.update(tally_rates[:, fission_ind]) + self._normalization_helper.update(tally_rates[:, fission_ind], mat_index=mat_index) # Divide by total number and store rates[i] = self._rate_helper.divide_by_adens(number) From 2f43656f34305fe8bca3390d22d91c37ce3f2bc0 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 12:27:36 -0500 Subject: [PATCH 0624/2654] update user guide --- docs/source/usersguide/depletion.rst | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 4ce495623..4be554b3c 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -188,9 +188,19 @@ Transport-independent depletion possible and likely in the near future. OpenMC supports running depletion calculations independent of the OpenMC -transport solver using the :class:`~openmc.deplete.FluxDepletionOperator` class. This class -has two ways to initalize it; the default constructor accepts an -:class:`openmc.Materials` object, a flux spectra, and one-group microscopic +transport solver using the :class:`~openmc.deplete.FluxDepletionOperator` class. +This class supports both constant-flux and constant-power depletion. + +.. important:: + + Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` class. Use the ``flux`` parameter when ``normalization_mode == constant-flux``, and use ``power`` or ``power_density`` when ``normalization_mode == constant-power``. + +.. warning:: + + The accuracy of results when using ``constant-power`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the dynamics of your particular scenario. + +This class has two ways to initalize it; the default constructor accepts an +:class:`openmc.Materials` object and one-group microscopic cross sections as a :class:`pandas.DataFrame`, while the `from_nuclides` method accepts a volume and dictionary of nuclide concentrations in place of the :class:`openmc.Materials` object in addition to the other parameters. @@ -201,7 +211,7 @@ or from data arrays:: # load in the microscopic cross sections micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_path) flux = 1.16e15 - op = FluxDepletionOperator(materials, micro_xs, flux, chain_file) + op = FluxDepletionOperator(materials, micro_xs, chain_file) # alternate construtor nuclides = {'U234': 8.92e18, From 8adefaad71240557974e413af1d597ac6e65878a Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 12:32:09 -0500 Subject: [PATCH 0625/2654] use source_rate in __call__ --- openmc/deplete/flux_operator.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 9ff0dee5d..1774eb000 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -27,11 +27,11 @@ _valid_rxns.append('fission') class FluxDepletionOperator(OpenMCOperator): - """Depletion operator that uses a user-provided flux and one-group + """Depletion operator that uses one-group cross sections to calculate reaction rates. Instances of this class can be used to perform depletion using one-group - cross sections and constant flux. Normally, a user needn't call methods of + cross sections and constant flux or constant power. Normally, a user needn't call methods of this class directly. Instead, an instance of this class is passed to an integrator class, such as :class:`openmc.deplete.CECMIntegrator`. @@ -42,8 +42,6 @@ class FluxDepletionOperator(OpenMCOperator): micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. - flux : float - Neutron flux [n cm^-2 s^-1] chain_file : str Path to the depletion chain XML file. keff : 2-tuple of float, optional @@ -114,7 +112,6 @@ class FluxDepletionOperator(OpenMCOperator): def __init__(self, materials, micro_xs, - flux, chain_file, keff=None, normalization_mode = 'constant-flux', @@ -131,7 +128,6 @@ class FluxDepletionOperator(OpenMCOperator): keff = ufloat(*keff) self._keff = keff - self.flux = flux helper_kwargs = dict() helper_kwargs = {'normalization_mode': normalization_mode, @@ -149,7 +145,6 @@ class FluxDepletionOperator(OpenMCOperator): @classmethod def from_nuclides(cls, volume, nuclides, micro_xs, - flux, chain_file, keff=None, fission_q=None, @@ -168,8 +163,6 @@ class FluxDepletionOperator(OpenMCOperator): micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. - flux : float - Neutron flux [n cm^-2 s^-1] chain_file : str Path to the depletion chain XML file. keff : 2-tuple of float, optional @@ -203,7 +196,6 @@ class FluxDepletionOperator(OpenMCOperator): materials = cls._consolidate_nuclides_to_material(nuclides, volume) return cls(materials, micro_xs, - flux, chain_file, keff, fission_q, @@ -396,8 +388,7 @@ class FluxDepletionOperator(OpenMCOperator): self._update_materials_and_nuclides(vec) - # Use the flux as a "source rate" - rates = self._calculate_reaction_rates(self.flux) + rates = self._calculate_reaction_rates(source_rate) keff = self._keff op_result = OperatorResult(keff, rates) From d024a3e00842a6535d8d0711a4131e4bee1ee841 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 13 Oct 2021 07:26:43 -0500 Subject: [PATCH 0626/2654] Implementation of C++ Sum1D function --- include/openmc/endf.h | 20 ++++++++++++++++++++ src/endf.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/openmc/endf.h b/include/openmc/endf.h index 7beb8e452..e580874b4 100644 --- a/include/openmc/endf.h +++ b/include/openmc/endf.h @@ -126,6 +126,26 @@ private: debye_waller_; //!< Debye-Waller integral divided by atomic mass in [eV^-1] }; +//============================================================================== +//! Sum of multiple 1D functions +//============================================================================== + +class Sum1D : public Function1D { +public: + // Constructors + explicit Sum1D(hid_t group); + + //! Evaluate each function and sum results + //! \param[in] x independent variable + //! \return Function evaluated at x + double operator()(double E) const override; + + const unique_ptr& functions(int i) const { return functions_[i]; } + +private: + vector> functions_; //!< individual functions +}; + //! Read 1D function from HDF5 dataset //! \param[in] group HDF5 group containing dataset //! \param[in] name Name of dataset diff --git a/src/endf.cpp b/src/endf.cpp index b42c8641d..60db3efa4 100644 --- a/src/endf.cpp +++ b/src/endf.cpp @@ -271,4 +271,30 @@ double IncoherentElasticXS::operator()(double E) const return bound_xs_ / 2.0 * ((1 - std::exp(-4.0 * E * W)) / (2.0 * E * W)); } +//============================================================================== +// Sum1D implementation +//============================================================================== + +Sum1D::Sum1D(hid_t group) +{ + // Get number of functions + int n; + read_attribute(group, "n", n); + + // Get each function + for (int i = 0; i < n; ++i) { + auto dset_name = fmt::format("func_{}", i + 1); + functions_.push_back(read_function(group, dset_name.c_str())); + } +} + +double Sum1D::operator()(double x) const +{ + double result = 0.0; + for (auto& func : functions_) { + result += (*func)(x); + } + return result; +} + } // namespace openmc From 8bb2002d8f8bebd58f11d84d88fc88df20552e8d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 13 Oct 2021 07:27:56 -0500 Subject: [PATCH 0627/2654] Add open_object, close_object functions in HDF5 interface --- include/openmc/hdf5_interface.h | 2 ++ src/endf.cpp | 16 ++++++++-------- src/hdf5_interface.cpp | 12 ++++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/openmc/hdf5_interface.h b/include/openmc/hdf5_interface.h index e9d9b4f96..0092c08f8 100644 --- a/include/openmc/hdf5_interface.h +++ b/include/openmc/hdf5_interface.h @@ -61,6 +61,8 @@ void ensure_exists(hid_t obj_id, const char* name, bool attribute = false); vector group_names(hid_t group_id); vector object_shape(hid_t obj_id); std::string object_name(hid_t obj_id); +hid_t open_object(hid_t group_id, const std::string& name); +void close_object(hid_t obj_id); //============================================================================== // Fortran compatibility functions diff --git a/src/endf.cpp b/src/endf.cpp index 60db3efa4..3ccfdbd21 100644 --- a/src/endf.cpp +++ b/src/endf.cpp @@ -90,23 +90,23 @@ bool is_inelastic_scatter(int mt) unique_ptr read_function(hid_t group, const char* name) { - hid_t dset = open_dataset(group, name); + hid_t obj_id = open_object(group, name); std::string func_type; - read_attribute(dset, "type", func_type); + read_attribute(obj_id, "type", func_type); unique_ptr func; if (func_type == "Tabulated1D") { - func = make_unique(dset); + func = make_unique(obj_id); } else if (func_type == "Polynomial") { - func = make_unique(dset); + func = make_unique(obj_id); } else if (func_type == "CoherentElastic") { - func = make_unique(dset); + func = make_unique(obj_id); } else if (func_type == "IncoherentElastic") { - func = make_unique(dset); + func = make_unique(obj_id); } else { throw std::runtime_error {"Unknown function type " + func_type + - " for dataset " + object_name(dset)}; + " for dataset " + object_name(obj_id)}; } - close_dataset(dset); + close_object(obj_id); return func; } diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index d53ad3879..27b750b93 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -118,6 +118,12 @@ void close_group(hid_t group_id) fatal_error("Failed to close group"); } +void close_object(hid_t obj_id) +{ + if (H5Oclose(obj_id) < 0) + fatal_error("Failed to close object"); +} + int dataset_ndims(hid_t dset) { hid_t dspace = H5Dget_space(dset); @@ -394,6 +400,12 @@ hid_t open_group(hid_t group_id, const char* name) return H5Gopen(group_id, name, H5P_DEFAULT); } +hid_t open_object(hid_t group_id, const std::string& name) +{ + ensure_exists(group_id, name.c_str()); + return H5Oopen(group_id, name.c_str(), H5P_DEFAULT); +} + void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer) { hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); From ce077567aeb621a3b3954150bdbbca702d5da321 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 14:08:53 -0500 Subject: [PATCH 0628/2654] bugfix in operator.py --- openmc/deplete/operator.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 9b083ffe9..61573832c 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -337,6 +337,9 @@ class Operator(OpenMCOperator): self._rate_helper = DirectReactionRateHelper( self.reaction_rates.n_nuc, self.reaction_rates.n_react) elif reaction_rate_mode == "flux": + if reaction_rate_opts is None: + reaction_rate_opts = {} + # Ensure energy group boundaries were specified if 'energies' not in reaction_rate_opts: raise ValueError( @@ -362,6 +365,8 @@ class Operator(OpenMCOperator): # Select and create fission yield helper fission_helper = self._fission_helpers[fission_yield_mode] + if fission_yield_opts is None: + fission_yield_opts = {} self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) From 4667cee8b874b9e265482027bf13bf39ac37f786 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 16:49:19 -0500 Subject: [PATCH 0629/2654] Added helper function to generate one-group cross sections --- openmc/deplete/flux_operator.py | 106 ++++++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 18 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 1774eb000..8b4999f23 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -17,10 +17,11 @@ from uncertainties import ufloat import openmc from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.mpi import comm +from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS from .abc import ReactionRateHelper, OperatorResult from .chain import REACTIONS from .openmc_operator import OpenMCOperator -from .helpers import ConstantFissionYieldHelper, SourceRateHelper +from .helpers import ChainFissionHelper, ConstantFissionYieldHelper, SourceRateHelper _valid_rxns = list(REACTIONS) _valid_rxns.append('fission') @@ -147,6 +148,7 @@ class FluxDepletionOperator(OpenMCOperator): def from_nuclides(cls, volume, nuclides, micro_xs, chain_file, keff=None, + normalization_mode='constant-flux', fission_q=None, prev_results=None, reduce_chain=False, @@ -197,12 +199,13 @@ class FluxDepletionOperator(OpenMCOperator): return cls(materials, micro_xs, chain_file, - keff, - fission_q, - prev_results, - reduce_chain, - reduce_chain_level, - fission_yield_opts) + keff=keff, + normalization_mode=normalization_mode, + fission_q=fission_q, + prev_results=prev_results, + reduce_chain=reduce_chain, + reduce_chain_level=reduce_chain_level, + fission_yield_opts=fission_yield_opts) @staticmethod @@ -245,17 +248,17 @@ class FluxDepletionOperator(OpenMCOperator): super().__init__() def update(self, fission_rates, mat_index=None): - """Update 'energy' produced with fission rates in a material. What this - actually calculates is the quantity X. + """Update 'energy' produced with fission rates in a material. What + this actually calculates is the quantity X. - Parameters - ---------- - fission_rates : numpy.ndarray - fission reaction rate for each isotope in the specified - material. Should be ordered corresponding to initial - ``rate_index`` used in :meth:`prepare` - mat_index : int - Material index + Parameters + ---------- + fission_rates : numpy.ndarray + fission reaction rate for each isotope in the specified + material. Should be ordered corresponding to initial + ``rate_index`` used in :meth:`prepare` + mat_index : int + Material index """ volume = self._op.number.get_mat_volume(mat_index) @@ -296,7 +299,7 @@ class FluxDepletionOperator(OpenMCOperator): """ - def __init__(self, n_nuc, n_react, op, nuc_ind_map. rxn_ind_map) + def __init__(self, n_nuc, n_react, op): super().__init__(n_nuc, n_react) rates = op.reaction_rates @@ -354,6 +357,8 @@ class FluxDepletionOperator(OpenMCOperator): # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper + if fission_yield_opts is None: + fission_yield_opts = {} self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) @@ -507,3 +512,68 @@ class FluxDepletionOperator(OpenMCOperator): check_type('data', data, np.ndarray, expected_iter_type=float) for reaction in reactions: check_value('reactions', reaction, _valid_rxns) + + + @staticmethod + def generate_1g_cross_sections(model, reaction_domain, reactions=['(n,gamma)', '(n,2n)', '(n,p)', '(n,a)', '(n,3n)', '(n,4n)', 'fission'], energy_bounds=(0, 20e6), write_to_csv=True, filename='micro_xs.csv'): + """Helper function to generate a one-group cross-section dataframe + using OpenMC. Note that the ``openmc`` C executable must be compiled. + + Parameters + ---------- + model : openmc.model.Model + OpenMC model object. Must contain geometry, materials, and settings. + reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh + Domain in which to tally reaction rates. + reactions : list of str, optional + Reaction names to tally + energy_bound : 2-tuple of float, optional + Bounds for the energy group. + write_to_csv : bool, optional + Option to write the DataFrame to a `.csv` file. If `False`, + returns the dataframe object. + filename : str + Name for csv file. Only applicable if ``write_to_csv == True`` + + Returns + ------- + None or pandas.DataFrame + + """ + groups = EnergyGroups() + groups.group_edges = np.array(list(energy_bounds)) + + # Set up the reaction tallies + tallies = openmc.Tallies() + xs = dict() + for rxn in reactions: + if rxn == 'fission': + xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) + else: + xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) + tallies += xs[rxn].tallies.values() + + model.tallies = tallies + statepoint_path = model.run() + + sp = openmc.StatePoint(statepoint_path) + + for rxn in xs: + xs[rxn].load_from_statepoint(sp) + + sp.close() + + # Build the DataFrame + micro_xs = pd.DataFrame() + for rxn in xs: + df = xs[rxn].get_pandas_dataframe(xs_type='micro') + df.index = df['nuclide'] + df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) + df.rename({'mean':rxn}, axis=1, inplace=True) + micro_xs = pd.concat([micro_xs, df], axis=1) + + if write_to_csv: + micro_xs.to_csv(filename) + return None + else: + return micro_xs From ef238b4a4fd3034c5bf6be3238b58322bc9fb8e9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 16:50:29 -0500 Subject: [PATCH 0630/2654] test_flux_deplete_operator.py -> test_deplete_flux_operator.py --- ...est_flux_deplete_operator.py => test_deplete_flux_operator.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/unit_tests/{test_flux_deplete_operator.py => test_deplete_flux_operator.py} (100%) diff --git a/tests/unit_tests/test_flux_deplete_operator.py b/tests/unit_tests/test_deplete_flux_operator.py similarity index 100% rename from tests/unit_tests/test_flux_deplete_operator.py rename to tests/unit_tests/test_deplete_flux_operator.py From 34598609b805f8bc6566c654c57b587c36fee069 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 17:24:16 -0500 Subject: [PATCH 0631/2654] add flux parameter to Integrator.__init__ signature --- openmc/deplete/abc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index c00c80399..c9e0d566b 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -579,7 +579,7 @@ class Integrator(ABC): """ def __init__(self, operator, timesteps, power=None, power_density=None, - source_rates=None, timestep_units='s', solver="cram48"): + flux=None, source_rates=None, timestep_units='s', solver="cram48"): # Check number of stages previously used if operator.prev_res is not None: res = operator.prev_res[-1] From 61b1d82544fc95ce30a40f25eceffac7e17e3b07 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 17:25:05 -0500 Subject: [PATCH 0632/2654] update test suite --- .../deplete_no_transport/test.py | 20 ++++++++++++------ ...nce.h5 => test_reference_constant_flux.h5} | Bin 35688 -> 35688 bytes .../test_reference_constant_power.h5 | Bin 0 -> 35688 bytes .../unit_tests/test_deplete_flux_operator.py | 5 +++-- 4 files changed, 17 insertions(+), 8 deletions(-) rename tests/regression_tests/deplete_no_transport/{test_reference.h5 => test_reference_constant_flux.h5} (99%) create mode 100644 tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index f82a342cf..3a9fbe135 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -33,8 +33,12 @@ def vol_nuc(): return (fuel.volume, nuclides) -@pytest.mark.parametrize("multiproc", [True, False]) -def test_no_transport(run_in_tmpdir, vol_nuc, multiproc): +@pytest.mark.parametrize("multiproc, normalization_mode, power, flux", [ + (True, 'constant-flux', None, 1164719970082145.0), + (False, 'constant-flux', None, 1164719970082145.0), + (True, 'constant-power', 174, None), + (False, 'constant-power', 174, None)]) +def test_no_transport_constant_flux(run_in_tmpdir, vol_nuc, multiproc): """Transport free system test suite. Runs an OpenMC transport-free depletion calculation and verifies @@ -46,22 +50,26 @@ def test_no_transport(run_in_tmpdir, vol_nuc, multiproc): micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) chain_file = Path(__file__).parents[2] / 'chain_simple.xml' - flux = 1164719970082145.0 # flux from pincell example op = FluxDepletionOperator.from_nuclides( - vol_nuc[0], vol_nuc[1], micro_xs, flux, chain_file) + vol_nuc[0], vol_nuc[1], micro_xs, chain_file, normalization_mode=normalization_mode) # Power and timesteps dt = [30] # single step + flux = 1164719970082145.0 # n/cm^2-s, flux from pincell example power = 174 # W/cm # Perform simulation using the predictor algorithm openmc.deplete.pool.USE_MULTIPROCESSING = multiproc openmc.deplete.PredictorIntegrator( - op, dt, power, timestep_units='d').integrate() + op, dt, power=power, flux=flux, timestep_units='d').integrate() # Get path to test and reference results path_test = op.output_dir / 'depletion_results.h5' - path_reference = Path(__file__).with_name('test_reference.h5') + if flux is None: + ref_path = 'test_reference_constant_flux.h5' + else: + ref_path = 'test_reference_constant_power.h5' + path_reference = Path(__file__).with_name(ref_path) # If updating results, do so and return if config['update']: diff --git a/tests/regression_tests/deplete_no_transport/test_reference.h5 b/tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 similarity index 99% rename from tests/regression_tests/deplete_no_transport/test_reference.h5 rename to tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 index 55675f9d082cd29b63a028131888b31f384f5418..1f4319b3e576dbb6ad692f8452e74c69e21c574d 100644 GIT binary patch delta 223 zcmaDcjp@ZSrVR;Q`X3+9s9ca4YnM{9?Q7>HX1fW~mg-)f;ANK-H1lfI);zlu(UO9g z06{y+-?NmH-anY!-=$dJQX0r$)hpo400ad_yX*stUYVsnh;Y7f4!pVC d;)2U92~fABLfpb(Ck=Ou=wzR69szU*0RRuxV#)vj delta 223 zcmaDcjp@ZSrVR;Q`saS-Z*A?&vNPY8=~?th(C+u|R@NWi!|hz+RK8!_Qf-&`LHDVI zoxI(*8CuCw{qH9CcPZ90fWU!N2N2b>e24v$>>HQQGN(B23O3Pij>~gSd;Bc9`@v!7 z5PwCzv(wHvN61C=CnY&MS09jY2!9&tY&~CE=BD&T=f}Y@?_@ulxkOEF6Yaay;)3p$ eUr@I=L*0@LaSMmtcerCjC;N2s2!I@d>>vP=sbQr6 diff --git a/tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 b/tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 new file mode 100644 index 0000000000000000000000000000000000000000..2c04addfbf4a1be16e5144fed5caad5ea1a57f06 GIT binary patch literal 35688 zcmeHPU2IfE6rSB}VS%dUCs+}~`Uh1}mjbdyXt%VLMH8(8$-cQuyU->5%eKXu5X1zN zqAxY^fkz&URvxszL5xWiG<{M?Y*KviFU0f_--wC9nS0LH+nw&+ZnxdGfpe4YnV&N= zXTCe%nVEa%_I#}Al?PUDTCL0#45~6!=>+j}m#_AZCr73zoNY&E=sLJ>}gH&7tKaS``60^2zd(bBbAlk`v(E=FwR}ZY|+Bw2T1JT0LE(!8AZy&ufNe`=8^#}AB*O% z$Z-~0rD}hEJ>sfTlRO{6UYi%-&2RBUO&17_Bx>-I{LXs3!ZB9pv#@=?&$B-tCzK*dcIdtwQG&qb=UH< zt*4J2y7A4Q_3p~Vs+gl*>lfSq&bE)JUPl#%xZZ&mC=lbghXY0$nI|Z2pav*^58|OUCgV)XG zaN33W5aWAVR#8Ekcgv>c-S&s58niRS@e#J8l3V$M$2atX8z`fCBgrW~Je*x$gyZo? zC_O|%MK@*ZwR3!MGb=1}fqB=)%iaI4bLQP-Uw3DytH1MDDigvSY`W$(5A(FDH83Iw z2rs{Lk@1J062C)u$!~51y!=j##}P__=L_X`z!%$Z%$G0aFt|XzTxUNde3=4H0(lVd z;>!S!BNQzaU+npFzI@@w#Mw$^o};)}hGoG)M8zS?}r z{XR4tq7s+6psdGS1SK>R0WZExY{}Lw6<;o}f4|J_&6h8DedN}&!Py68Qpr|&&6(^= zP1^~1?StIj7sk8cC#i(+&P7f_-UxW{u7$@DN|uUum5);kVQ$amOL5N)`1OhA8qOaS z$2;_Q=K3)Ad>7hA{Se+^#E8s?fEVw^wq}>YI9%xG4}(upJHy zJkdS74K9vwGiU=T)q^?JJ?w$Uq)Y~_JuFF z(<1XB;Ki37e!q;e7>5frPodt%-W@x4>&U^j9lOn|Xe0M%d5DtL(VCsRjINeO&B%z6 z@f0Z-Y0AOAgvl(yh4Xw&Z`H&5NwjP4FT-rZWQYRLv)98;XS7O!=WFQM^LLc0Q4_ol zg`VwiVyqW@jsnmNbG*g6udKdk0`Es`d* zFT_^$@VOZnS>3h$M6$Cp`3xr}JomtuSn^k7g))(xFay(H>>G#_&<~bX$V$Z9(Nase<>)gx) z<1hPx+_*_@n<5#||=##T1&FegQx%RLo-ya|gf-2cXxqcq!_>k{~i>)_ze5xG-0{#_~i~z7P(o}Cuz%;3Yb6t_? zA~~*3{TeTmPIlmX#jgI=j&xfJQHA$?NT4H-YAQXH(G}>-RQg1!>r}F%pNsaT&DRD> z^>+7XT2pTuEvI$&J4w<2-qiaX26EEO`$zrv1*itxAJm7qeZP=C_xlraED89_B1y8z zG-dv*`;wsC693M`gAnxj2?6vI5;!0}_x@KoJqq{(1D(`2tM3CP?s5L=3&n%balfNO zd>(j=yyN0ws$-5WH$3S6+2227Tom7b|K$5_|EKwvF*_VqsP@-S{7V{O(4ka^T@?)r@jE=%Jh~ zu}%p>QKTRs2nYg#fFK|U2m*qDARq_`0)oJjAmFu+3>Rrlg7<|ekNsew)dl(gDMBCR zZD~K}mHj0U6DbG?0)l`bAP5Kof`A|(2nYg#fFK|UlpX=E=LwYsHa*1851@~IzgO|d zEYAyY&PJXOcp)h1f`A|(2nYg#fFK|U2m*q@(jidn{^4SQ`-YguenIvLOLxzuWkEm? z5CjAPK|l}?1d2hxYuz~8bKenOH$uV3C1j^F(Gm%2-5whrCS{9acx@m<}c zH8u4QHr%ZLzHD#(r-M&4p4|R*-Hp$>H+}xW)w*BV&TrYy5w^3L?fi}He3R`w$aWrP PJ2&UC6ZS!>X?Fe(f}(Zj literal 0 HcmV?d00001 diff --git a/tests/unit_tests/test_deplete_flux_operator.py b/tests/unit_tests/test_deplete_flux_operator.py index 3ae098490..b7a225398 100644 --- a/tests/unit_tests/test_deplete_flux_operator.py +++ b/tests/unit_tests/test_deplete_flux_operator.py @@ -11,7 +11,6 @@ from openmc.deplete.flux_operator import FluxDepletionOperator import pandas as pd import numpy as np -FLUX = 5e16 CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" ONE_GROUP_XS = Path(__file__).parents[1] / "micro_xs_simple.csv" @@ -62,6 +61,7 @@ def test_create_micro_xs_from_csv(): def test_operator_init(): """The test uses a temporary dummy chain. This file will be removed at the end of the test, and only contains a depletion_chain node.""" + volume = 1 nuclides = {'U234': 8.922411359424315e+18, 'U235': 9.98240191860822e+20, 'U238': 2.2192386373095893e+22, @@ -70,4 +70,5 @@ def test_operator_init(): 'O17': 1.7588724018066158e+19} micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) nuclide_flux_operator = FluxDepletionOperator.from_nuclides( - 1, nuclides, micro_xs, FLUX_SPECTRA, CHAIN_PATH) + volume, nuclides, micro_xs, CHAIN_PATH) + nuclide_flux_operator = FluxDepletionOperator(materials, micro_xs, CHAIN_PATH) From f4aefa9db63f54ea97a7e9f4587260a2de80baf4 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 17:27:08 -0500 Subject: [PATCH 0633/2654] added function to help users create one-group cross sections; typo and bug fixes --- openmc/deplete/flux_operator.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 8b4999f23..615fa090d 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -242,9 +242,9 @@ class FluxDepletionOperator(OpenMCOperator): """ def __init__(self, op): - self._op = op - rates = self.reaction_rates + rates = op.reaction_rates self.nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} + self._op = op super().__init__() def update(self, fission_rates, mat_index=None): @@ -262,13 +262,13 @@ class FluxDepletionOperator(OpenMCOperator): """ volume = self._op.number.get_mat_volume(mat_index) - densities = np.empty(shape(fission_rates)) - for i_nuc in nuc_ind_map: + densities = np.empty(np.shape(fission_rates)) + for i_nuc in self.nuc_ind_map: nuc = self.nuc_ind_map[i_nuc] densities[i_nuc] = self._op.number.get_atom_density(mat_index, nuc) fission_rates = fission_rates * volume * densities - super.update(fission_rates) + super().update(fission_rates) class _FluxDepletionRateHelper(ReactionRateHelper): """Class for generating one-group reaction rates with flux and @@ -351,7 +351,7 @@ class FluxDepletionOperator(OpenMCOperator): self._rate_helper = self._FluxDepletionRateHelper( self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) if normalization_mode == "constant-power": - self._normalization_helper = self.FluxDepletionNormalizationHelper() + self._normalization_helper = self._FluxDepletionNormalizationHelper(self) else: self._normalization_helper = SourceRateHelper() From cc871495268c71127396d12f02175928f6a6e877 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 17:39:26 -0500 Subject: [PATCH 0634/2654] Add function to load previous results --- openmc/deplete/flux_operator.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 615fa090d..55888b233 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -48,9 +48,6 @@ class FluxDepletionOperator(OpenMCOperator): keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. Default is None. - fission_q : dict, optional - Dictionary of nuclides and their fission Q values [eV]. If not given, - values will be pulled from the ``chain_file``. prev_results : Results, optional Results from a previous depletion calculation. normalization_mode : {"constant-power", "constant-flux"} @@ -61,7 +58,6 @@ class FluxDepletionOperator(OpenMCOperator): Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only applicable if ``"normalization_mode" == "constant-power"``. - reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. Default is False. @@ -223,6 +219,23 @@ class FluxDepletionOperator(OpenMCOperator): return openmc.Materials([mat]) + def _load_previous_results(self): + """Load results from a previous depletion simulation""" + # Reload volumes into geometry + self.prev_res[-1].transfer_volumes(self.materials) + + # Store previous results in operator + # Distribute reaction rates according to those tracked + # on this process + if comm.size != 1: + prev_results = self.prev_res + self.prev_res = Results() + mat_indexes = _distribute(range(len(self.burnable_mats))) + for res_obj in prev_results: + new_res = res_obj.distribute(self.local_mats, mat_indexes) + self.prev_res.append(new_res) + + def _get_nuclides_with_data(self, cross_sections): """Finds nuclides with cross section data""" return set(cross_sections.index) From 657a94b0c10bb137dfa6bd58274ac363c726d536 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 17:43:37 -0500 Subject: [PATCH 0635/2654] clean up docs for micro_xs helper functions --- openmc/deplete/flux_operator.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 55888b233..974255753 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -463,12 +463,13 @@ class FluxDepletionOperator(OpenMCOperator): Array containing one-group microscopic cross section information for each nuclide and reaction. units : {'barn', 'cm^2'}, optional - Units for microscopic cross section data. Defaults to ``barn``. + Units of cross section values in ``data`` array. Defaults to ``barn``. Returns ------- micro_xs : pandas.DataFrame - A DataFrame object correctly formatted for use in ``FluxOperator`` + A DataFrame object correctly formatted for use in ``FluxOperator``. + Cross section data is in [cm^2] """ # Validate inputs @@ -498,12 +499,13 @@ class FluxDepletionOperator(OpenMCOperator): Relative path to csv-file containing microscopic cross section data. units : {'barn', 'cm^2'}, optional - Units for microscopic cross section data. Defaults to ``barn``. + Units of cross section values in the ``.csv`` file array. Defaults to ``barn``. Returns ------- micro_xs : pandas.DataFrame - A DataFrame object correctly formatted for use in ``FluxOperator`` + A DataFrame object correctly formatted for use in ``FluxOperator``. + Cross section data is in [cm^2] """ micro_xs = pd.read_csv(csv_file, index_col=0) From 018ed9f58a0c98525f981a18bc04a873ea965988 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 17:47:50 -0500 Subject: [PATCH 0636/2654] add flux parameter to SII integrator --- openmc/deplete/abc.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index c9e0d566b..24859151f 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -526,9 +526,9 @@ class Integrator(ABC): initial heavy metal inventory to get total power if ``power`` is not speficied. flux : float or iterable of float, optional - Neutron flux in [neur/s-cm^2] for each interval in :attr: `timesteps` + neutron flux in [neut/s-cm^2] for each interval in :attr:`timesteps` source_rates : float or iterable of float, optional - Source rate in [neutron/sec] for each interval in :attr:`timesteps` + source rate in [neutron/sec] for each interval in :attr:`timesteps` .. versionadded:: 0.12.1 timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} @@ -866,6 +866,8 @@ class SIIntegrator(Integrator): Power density of the reactor in [W/gHM]. It is multiplied by initial heavy metal inventory to get total power if ``power`` is not speficied. + flux : float or iterable of float, optional + neutron flux in [neut/s-cm^2] for each interval in :attr:`timesteps` source_rates : float or iterable of float, optional Source rate in [neutron/sec] for each interval in :attr:`timesteps` @@ -922,12 +924,12 @@ class SIIntegrator(Integrator): """ def __init__(self, operator, timesteps, power=None, power_density=None, - source_rates=None, timestep_units='s', n_steps=10, + flux=None, source_rates=None, timestep_units='s', n_steps=10, solver="cram48"): check_type("n_steps", n_steps, Integral) check_greater_than("n_steps", n_steps, 0) super().__init__( - operator, timesteps, power, power_density, source_rates, + operator, timesteps, power, power_density, flux, source_rates, timestep_units=timestep_units, solver=solver) self.n_steps = n_steps From 18cc291c9db8845781b66bfa0ee234ad0adf0497 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 17:52:18 -0500 Subject: [PATCH 0637/2654] formatting adjustment in usersguide --- docs/source/usersguide/depletion.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 4be554b3c..e95e098c4 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -199,9 +199,9 @@ This class supports both constant-flux and constant-power depletion. The accuracy of results when using ``constant-power`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the dynamics of your particular scenario. -This class has two ways to initalize it; the default constructor accepts an +This class has two ways to initalize it: the default constructor accepts an :class:`openmc.Materials` object and one-group microscopic -cross sections as a :class:`pandas.DataFrame`, while the `from_nuclides` +cross sections as a :class:`pandas.DataFrame`, while the ``from_nuclides`` method accepts a volume and dictionary of nuclide concentrations in place of the :class:`openmc.Materials` object in addition to the other parameters. The class includes helper functions to construct the dataframe from a csv file From 5d004230f47018f4a4612aa6182833f5811b0075 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 19:15:52 -0500 Subject: [PATCH 0638/2654] added refernce libraries for each case --- .../test_reference_constant_flux.h5 | Bin 35688 -> 35688 bytes .../test_reference_constant_power.h5 | Bin 35688 -> 35688 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 b/tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 index 1f4319b3e576dbb6ad692f8452e74c69e21c574d..ff75648b8a3f02225665861a54d03d3acc53ee32 100644 GIT binary patch delta 22 dcmaDcjp@ZSrVV?#m`k?qpS-_oDGQLc2LOjn3yuH) delta 22 dcmaDcjp@ZSrVV?#mYEVPTt?Olm$rJ0|0<`3XlK* delta 22 dcmaDcjp@ZSrVV?#n2*%$oV>qlDGQLc2LOo!3$y?L From 8ec8826ed8a2b150e89e10720bd33699f063f389 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 19:19:51 -0500 Subject: [PATCH 0639/2654] fix regression test --- .../deplete_no_transport/test.py | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 3a9fbe135..9ae0f84f4 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -17,46 +17,52 @@ from tests.regression_tests import config @pytest.fixture(scope="module") -def vol_nuc(): +def fuel(): fuel = openmc.Material(name="uo2") fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) fuel.add_element("O", 2) fuel.set_density("g/cc", 10.4) + fuel.depletable=True fuel.volume = np.pi * 0.42 ** 2 - nuclides = {} - for nuc, dens in fuel.get_nuclide_atom_densities().items(): - nuclides[nuc] = dens * 1e24 - - # Load geometry from example - return (fuel.volume, nuclides) + return fuel -@pytest.mark.parametrize("multiproc, normalization_mode, power, flux", [ - (True, 'constant-flux', None, 1164719970082145.0), - (False, 'constant-flux', None, 1164719970082145.0), - (True, 'constant-power', 174, None), - (False, 'constant-power', 174, None)]) -def test_no_transport_constant_flux(run_in_tmpdir, vol_nuc, multiproc): +@pytest.mark.parametrize("multiproc, from_nuclides, normalization_mode, power, flux", [ + (True, True,'constant-flux', None, 1164719970082145.0), + (False, True, 'constant-flux', None, 1164719970082145.0), + (True, True, 'constant-power', 174, None), + (False, True, 'constant-power', 174, None), + (True, False,'constant-flux', None, 1164719970082145.0), + (False, False, 'constant-flux', None, 1164719970082145.0), + (True, False, 'constant-power', 174, None), + (False, False, 'constant-power', 174, None)]) +def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclides, normalization_mode, power, flux): """Transport free system test suite. Runs an OpenMC transport-free depletion calculation and verifies that the outputs match a reference file. """ - # Create operator micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) chain_file = Path(__file__).parents[2] / 'chain_simple.xml' - op = FluxDepletionOperator.from_nuclides( - vol_nuc[0], vol_nuc[1], micro_xs, chain_file, normalization_mode=normalization_mode) + + if from_nuclides: + nuclides = {} + for nuc, dens in fuel.get_nuclide_atom_densities().items(): + nuclides[nuc] = dens * 1e24 + + op = FluxDepletionOperator.from_nuclides( + fuel.volume, nuclides, micro_xs, chain_file, normalization_mode=normalization_mode) + + else: + op = FluxDepletionOperator(openmc.Materials([fuel]), micro_xs, chain_file, normalization_mode=normalization_mode) # Power and timesteps dt = [30] # single step - flux = 1164719970082145.0 # n/cm^2-s, flux from pincell example - power = 174 # W/cm # Perform simulation using the predictor algorithm openmc.deplete.pool.USE_MULTIPROCESSING = multiproc @@ -65,17 +71,12 @@ def test_no_transport_constant_flux(run_in_tmpdir, vol_nuc, multiproc): # Get path to test and reference results path_test = op.output_dir / 'depletion_results.h5' - if flux is None: + if flux is not None: ref_path = 'test_reference_constant_flux.h5' else: ref_path = 'test_reference_constant_power.h5' path_reference = Path(__file__).with_name(ref_path) - # If updating results, do so and return - if config['update']: - shutil.copyfile(str(path_test), str(path_reference)) - return - # Load the reference/test results res_test = openmc.deplete.Results(path_test) res_ref = openmc.deplete.Results(path_reference) From 8102226e7055d5391910e406fcda4460d9544ecb Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 21 Jul 2022 20:27:52 -0500 Subject: [PATCH 0640/2654] fix unit test --- tests/unit_tests/test_deplete_flux_operator.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/unit_tests/test_deplete_flux_operator.py b/tests/unit_tests/test_deplete_flux_operator.py index b7a225398..9019d123d 100644 --- a/tests/unit_tests/test_deplete_flux_operator.py +++ b/tests/unit_tests/test_deplete_flux_operator.py @@ -8,6 +8,7 @@ from pathlib import Path import pytest from openmc.deplete.flux_operator import FluxDepletionOperator +from openmc import Material, Materials import pandas as pd import numpy as np @@ -71,4 +72,12 @@ def test_operator_init(): micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) nuclide_flux_operator = FluxDepletionOperator.from_nuclides( volume, nuclides, micro_xs, CHAIN_PATH) + + fuel = Material(name="uo2") + fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) + fuel.add_element("O", 2) + fuel.set_density("g/cc", 10.4) + fuel.depletable=True + fuel.volume = 1 + materials = Materials([fuel]) nuclide_flux_operator = FluxDepletionOperator(materials, micro_xs, CHAIN_PATH) From 8cc815d4f2ebf56460f0f0f6f9195bf46afc968a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 21 Jul 2022 22:24:17 -0500 Subject: [PATCH 0641/2654] Add numpy arrays to a list so they persist to the time of the VTK write --- openmc/mesh.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 1fe5429d0..d08213f77 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -248,8 +248,10 @@ class StructuredMesh(MeshBase): # create VTK arrays for each of # the data sets + datasets_out = [] for label, dataset in datasets.items(): dataset = np.asarray(dataset).flatten() + datasets_out.append(dataset) if volume_normalization: dataset /= self.volumes.flatten() @@ -692,7 +694,7 @@ class RegularMesh(StructuredMesh): root_cell.fill = lattice return root_cell, cells - + def write_data_to_vtk(self, filename, datasets, volume_normalization=True): """Creates a VTK object of the mesh @@ -1605,7 +1607,7 @@ class UnstructuredMesh(MeshBase): Raises ------ RuntimeError - when the size of a dataset doesn't match the number of cells + when the size of a dataset doesn't match the number of cells """ import vtk From ff5490e3ba432209a95cb75ce07d21b167f90efd Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 22 Jul 2022 08:01:28 +0100 Subject: [PATCH 0642/2654] User able to set bounding cell id --- openmc/universe.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 5bcbfde46..fe41674d5 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -767,19 +767,25 @@ class DAGMCUniverse(UniverseBase): return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z - def bounded_universe(self, **kwargs): + def bounded_universe(self, bounding_cell_id=10000, **kwargs): """Returns an openmc.Universe filled with this DAGMCUniverse and bounded with a cell. Defaults to a box cell with a vacuum surface however this can be changed using the kwargs which are passed directly to DAGMCUniverse.bounding_region(). + Parameters + ---------- + bounding_cell_id : int + The cell ID number to use for the bounding cell, defaults to 1000 to reduce + the chance of overlapping ID numbers with the DAGMC geometry. + Returns ------- openmc.Universe Universe instance """ - bounding_cell = openmc.Cell(fill=self, region=self.bounding_region(**kwargs)) + bounding_cell = openmc.Cell(fill=self, id=bounding_cell_id, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) @classmethod From f0cda31e73311a2673bc7fb0dac698f396cf2933 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 22 Jul 2022 10:45:15 +0100 Subject: [PATCH 0643/2654] corrected arg name --- openmc/universe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index fe41674d5..78f75bbfc 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -785,7 +785,7 @@ class DAGMCUniverse(UniverseBase): Universe instance """ - bounding_cell = openmc.Cell(fill=self, id=bounding_cell_id, region=self.bounding_region(**kwargs)) + bounding_cell = openmc.Cell(fill=self, cell_id =bounding_cell_id, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) @classmethod From e453901c84e57eca983a52124e7dc903b06dfb00 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 13 Oct 2021 07:28:35 -0500 Subject: [PATCH 0644/2654] Implement to/from_hdf5 methods for Python Sum class --- openmc/data/function.py | 39 +++++++++++++++++++++++++++++++++++++++ src/endf.cpp | 2 ++ 2 files changed, 41 insertions(+) diff --git a/openmc/data/function.py b/openmc/data/function.py index b5aa2117d..7a73987df 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -578,6 +578,45 @@ class Sum(EqualityMixin): cv.check_type('functions', functions, Iterable, Callable) self._functions = functions + def to_hdf5(self, group, name='xy'): + """Write sum of functions to an HDF5 group + + Parameters + ---------- + group : h5py.Group + HDF5 group to write to + name : str + Name of the dataset to create + + """ + sum_group = group.create_group(name) + sum_group.attrs['type'] = np.string_(type(self).__name__) + sum_group.attrs['n'] = len(self.functions) + for i, f in enumerate(self.functions): + f.to_hdf5(sum_group, f'func_{i+1}') + + @classmethod + def from_hdf5(cls, group): + """Generate sum of functions from an HDF5 group + + Parameters + ---------- + group : h5py.Group + Group to read from + + Returns + ------- + openmc.data.Sum + Functions read from the group + + """ + n = group.attrs['n'] + functions = [ + Function1D.from_hdf5(group[f'func_{i+1}']) + for i in range(n) + ] + return cls(functions) + class Regions1D(EqualityMixin): r"""Piecewise composition of multiple functions. diff --git a/src/endf.cpp b/src/endf.cpp index 3ccfdbd21..c0c1d2e7e 100644 --- a/src/endf.cpp +++ b/src/endf.cpp @@ -102,6 +102,8 @@ unique_ptr read_function(hid_t group, const char* name) func = make_unique(obj_id); } else if (func_type == "IncoherentElastic") { func = make_unique(obj_id); + } else if (func_type == "Sum") { + func = make_unique(obj_id); } else { throw std::runtime_error {"Unknown function type " + func_type + " for dataset " + object_name(obj_id)}; From 70c16d4b04a60606742f6b1c6825bfd04adcad6d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 13 Oct 2021 07:30:56 -0500 Subject: [PATCH 0645/2654] Implement mixed coherent/incoheret thermal elastic --- include/openmc/secondary_thermal.h | 28 +++++++++ openmc/data/angle_energy.py | 2 + openmc/data/thermal.py | 91 ++++++++++++++++++++--------- openmc/data/thermal_angle_energy.py | 57 ++++++++++++++++++ src/secondary_thermal.cpp | 35 +++++++++++ src/thermal.cpp | 25 +++++--- 6 files changed, 203 insertions(+), 35 deletions(-) diff --git a/include/openmc/secondary_thermal.h b/include/openmc/secondary_thermal.h index 84ed68f51..81de5c451 100644 --- a/include/openmc/secondary_thermal.h +++ b/include/openmc/secondary_thermal.h @@ -150,6 +150,34 @@ private: //!< each incident energy }; +//============================================================================== +//! Mixed coherent/incoherent elastic angle-energy distribution +//============================================================================== + +class MixedElasticAE : public AngleEnergy { +public: + //! Construct from HDF5 file + // + //! \param[in] group HDF5 group + explicit MixedElasticAE( + hid_t group, const CoherentElasticXS& coh_xs, const Tabulated1D& incoh_xs); + + //! Sample distribution for an angle and energy + //! \param[in] E_in Incoming energy in [eV] + //! \param[out] E_out Outgoing energy in [eV] + //! \param[out] mu Outgoing cosine with respect to current direction + //! \param[inout] seed Pseudorandom number seed pointer + void sample( + double E_in, double& E_out, double& mu, uint64_t* seed) const override; + +private: + CoherentElasticAE coherent_dist_; //!< Coherent distribution + unique_ptr incoherent_dist_; //!< Incoherent distribution + + const CoherentElasticXS& coherent_xs_; //!< Ref. to coherent XS + const Tabulated1D& incoherent_xs_; //!< Ref. to incoherent XS +}; + } // namespace openmc #endif // OPENMC_SECONDARY_THERMAL_H diff --git a/openmc/data/angle_energy.py b/openmc/data/angle_energy.py index 6009dc748..b8fde5478 100644 --- a/openmc/data/angle_energy.py +++ b/openmc/data/angle_energy.py @@ -44,6 +44,8 @@ class AngleEnergy(EqualityMixin, ABC): return openmc.data.IncoherentInelasticAEDiscrete.from_hdf5(group) elif dist_type == 'incoherent_inelastic': return openmc.data.IncoherentInelasticAE.from_hdf5(group) + elif dist_type == 'mixed_elastic': + return openmc.data.MixedElasticAE.from_hdf5(group) @staticmethod def from_ace(ace, location_dist, location_start, rx=None): diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index 4e0a30b64..6cf5a4e9e 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -19,12 +19,12 @@ from . import HDF5_VERSION, HDF5_VERSION_MAJOR, endf from .data import K_BOLTZMANN, ATOMIC_SYMBOL, EV_PER_MEV, isotopes from .ace import Table, get_table, Library from .angle_energy import AngleEnergy -from .function import Tabulated1D, Function1D +from .function import Tabulated1D, Function1D, Sum from .njoy import make_ace_thermal from .thermal_angle_energy import (CoherentElasticAE, IncoherentElasticAE, IncoherentElasticAEDiscrete, IncoherentInelasticAEDiscrete, - IncoherentInelasticAE) + IncoherentInelasticAE, MixedElasticAE) _THERMAL_NAMES = { @@ -694,29 +694,53 @@ class ThermalScattering(EqualityMixin): # Incoherent/coherent elastic scattering cross section idx = ace.jxs[4] - n_mu = ace.nxs[6] + 1 if idx != 0: - n_energy = int(ace.xss[idx]) - energy = ace.xss[idx + 1: idx + 1 + n_energy]*EV_PER_MEV - P = ace.xss[idx + 1 + n_energy: idx + 1 + 2 * n_energy] - - if ace.nxs[5] == 4: + if ace.nxs[5] in (4, 5): # Coherent elastic - xs = CoherentElastic(energy, P*EV_PER_MEV) - distribution = CoherentElasticAE(xs) + n_energy = int(ace.xss[idx]) + energy = ace.xss[idx + 1: idx + 1 + n_energy]*EV_PER_MEV + P = ace.xss[idx + 1 + n_energy: idx + 1 + 2 * n_energy] + coherent_xs = CoherentElastic(energy, P*EV_PER_MEV) + coherent_dist = CoherentElasticAE(xs) # Coherent elastic shouldn't have angular distributions listed + n_mu = ace.nxs[6] + 1 assert n_mu == 0 - else: - # Incoherent elastic - xs = Tabulated1D(energy, P) + + if ace.nxs[5] in (3, 5): + # Incoherent elastic scattering -- first determine if both + # incoherent and coherent are present (mixed) + mixed = (ace.nxs[5] == 5) + + # Get cross section values + idx = ace.jxs[7] if mixed else ace.jxs[4] + n_energy = int(ace.xss[idx]) + energy = ace.xss[idx + 1: idx + 1 + n_energy]*EV_PER_MEV + values = ace.xss[idx + 1 + n_energy: idx + 1 + 2 * n_energy] + + incoherent_xs = Tabulated1D(energy, values) # Angular distribution + n_mu = (ace.nxs[8] if mixed else ace.nxs[6]) + 1 assert n_mu > 0 - idx = ace.jxs[6] + idx = ace.jxs[9] if mixed else ace.jxs[6] mu_out = ace.xss[idx:idx + n_energy * n_mu] mu_out.shape = (n_energy, n_mu) - distribution = IncoherentElasticAEDiscrete(mu_out) + incoherent_dist = IncoherentElasticAEDiscrete(mu_out) + + if ace.nxs[5] == 3: + xs = incoherent_xs + dist = incoherent_dist + elif ace.nxs[5] == 4: + xs = coherent_xs + dist = coherent_dist + else: + # Create mixed cross section -- note that coherent must come + # first due to assumption on C++ side + xs = Sum([coherent_xs, incoherent_xs]) + + # Create mixed distribution + distribution = MixedElasticAE(coherent_dist, incoherent_dist) table.elastic = ThermalScatteringReaction({T: xs}, {T: distribution}) @@ -802,7 +826,7 @@ class ThermalScattering(EqualityMixin): # Replace ACE data with ENDF data rx, rx_endf = data.elastic, data_endf.elastic for t in temperatures: - if isinstance(rx_endf.xs[t], IncoherentElastic): + if isinstance(rx_endf.xs[t], (IncoherentElastic, Sum)): rx.xs[t] = rx_endf.xs[t] rx.distribution[t] = rx_endf.distribution[t] @@ -832,20 +856,14 @@ class ThermalScattering(EqualityMixin): # Read coherent/incoherent elastic data elastic = None if (7, 2) in ev.section: - xs = {} - distribution = {} - - file_obj = StringIO(ev.section[7, 2]) - lhtr = endf.get_head_record(file_obj)[2] - if lhtr == 1: - # coherent elastic - + # Define helper functions to avoid duplication + def get_coherent_elastic(file_obj): # Get structure factor at first temperature params, S = endf.get_tab1_record(file_obj) strT = _temperature_str(params[0]) n_temps = params[2] bragg_edges = S.x - xs[strT] = CoherentElastic(bragg_edges, S.y) + xs = {strT: CoherentElastic(bragg_edges, S.y)} distribution = {strT: CoherentElasticAE(xs[strT])} # Get structure factor for subsequent temperatures @@ -854,15 +872,34 @@ class ThermalScattering(EqualityMixin): strT = _temperature_str(params[0]) xs[strT] = CoherentElastic(bragg_edges, S) distribution[strT] = CoherentElasticAE(xs[strT]) + return xs, distribution - elif lhtr == 2: - # incoherent elastic + def get_incoherent_elastic(file_obj): params, W = endf.get_tab1_record(file_obj) bound_xs = params[0] + xs = {} + distribution = {} for T, debye_waller in zip(W.x, W.y): strT = _temperature_str(T) xs[strT] = IncoherentElastic(bound_xs, debye_waller) distribution[strT] = IncoherentElasticAE(debye_waller) + return xs, distribution + + file_obj = StringIO(ev.section[7, 2]) + lhtr = endf.get_head_record(file_obj)[2] + if lhtr == 1: + # coherent elastic + xs, distribution = get_coherent_elastic(file_obj) + elif lhtr == 2: + # incoherent elastic + xs, distribution = get_incoherent_elastic(file_obj) + elif lhtr == 3: + # mixed coherent / incoherent elastic + xs_c, dist_c = get_coherent_elastic(file_obj) + xs_i, dist_i = get_incoherent_elastic(file_obj) + assert sorted(xs_c) == sorted(xs_i) + xs = {T: Sum([xs_c[T], xs_i[T]]) for T in xs_c} + distribution = {T: MixedElasticAE(dist_c[T], dist_i[T]) for T in dist_c} elastic = ThermalScatteringReaction(xs, distribution) diff --git a/openmc/data/thermal_angle_energy.py b/openmc/data/thermal_angle_energy.py index 05393e7bb..6ef874600 100644 --- a/openmc/data/thermal_angle_energy.py +++ b/openmc/data/thermal_angle_energy.py @@ -210,3 +210,60 @@ class IncoherentInelasticAEDiscrete(AngleEnergy): class IncoherentInelasticAE(CorrelatedAngleEnergy): _name = 'incoherent_inelastic' + + +class MixedElasticAE(AngleEnergy): + """Secondary distribution for mixed coherent/incoherent thermal elastic + + Parameters + ---------- + coherent : AngleEnergy + Secondary distribution for coherent elastic scattering + incoherent : AngleEnergy + Secondary distribution for incoherent elastic scattering + + Attributes + ---------- + coherent : AngleEnergy + Secondary distribution for coherent elastic scattering + incoherent : AngleEnergy + Secondary distribution for incoherent elastic scattering + + """ + def __init__(self, coherent, incoherent): + self.coherent = coherent + self.incoherent = incoherent + + def to_hdf5(self, group): + """Write mixed elastic distribution to an HDF5 group + + Parameters + ---------- + group : h5py.Group + HDF5 group to write to + + """ + group.attrs['type'] = np.string_('mixed_elastic') + coherent_group = group.create_group('coherent') + self.coherent.to_hdf5(coherent_group) + incoherent_group = group.create_group('incoherent') + self.incoherent.to_hdf5(incoherent_group) + + @classmethod + def from_hdf5(cls, group): + """Generate mixed thermal elastic distribution from HDF5 data + + Parameters + ---------- + group : h5py.Group + HDF5 group to read from + + Returns + ------- + openmc.data.MixedElasticAE + Mixed thermal elastic distribution + + """ + coherent = AngleEnergy.from_hdf5(group['coherent']) + incoherent = AngleEnergy.from_hdf5(group['incoherent']) + return cls(coherent, incoherent) diff --git a/src/secondary_thermal.cpp b/src/secondary_thermal.cpp index 3677f6ed3..e5e8274da 100644 --- a/src/secondary_thermal.cpp +++ b/src/secondary_thermal.cpp @@ -332,4 +332,39 @@ void IncoherentInelasticAE::sample( mu += std::min(mu - mu_left, mu_right - mu) * (prn(seed) - 0.5); } +//============================================================================== +// MixedElasticAE implementation +//============================================================================== + +MixedElasticAE::MixedElasticAE( + hid_t group, const CoherentElasticXS& coh_xs, const Tabulated1D& incoh_xs) + : coherent_dist_(coh_xs), coherent_xs_(coh_xs), incoherent_xs_(incoh_xs) +{ + // Read incoherent elastic distribution + hid_t incoherent_group = open_group(group, "incoherent"); + std::string temp; + read_attribute(incoherent_group, "type", temp); + if (temp == "incoherent_elastic") { + incoherent_dist_ = make_unique(incoherent_group); + } else if (temp == "incoherent_elastic_discrete") { + incoherent_dist_ = + make_unique(incoherent_group, incoh_xs.x()); + } + close_group(incoherent_group); +} + +void MixedElasticAE::sample( + double E_in, double& E_out, double& mu, uint64_t* seed) const +{ + // Evaluate coherent and incoherent elastic cross sections + double xs_coh = coherent_xs_(E_in); + double xs_incoh = incoherent_xs_(E_in); + + if (prn(seed) * (xs_coh + xs_incoh) < xs_coh) { + coherent_dist_.sample(E_in, E_out, mu, seed); + } else { + incoherent_dist_->sample(E_in, E_out, mu, seed); + } +} + } // namespace openmc diff --git a/src/thermal.cpp b/src/thermal.cpp index 1101d5485..303786915 100644 --- a/src/thermal.cpp +++ b/src/thermal.cpp @@ -210,14 +210,23 @@ ThermalData::ThermalData(hid_t group) if (temp == "coherent_elastic") { auto xs = dynamic_cast(elastic_.xs.get()); elastic_.distribution = make_unique(*xs); - } else { - if (temp == "incoherent_elastic") { - elastic_.distribution = make_unique(dgroup); - } else if (temp == "incoherent_elastic_discrete") { - auto xs = dynamic_cast(elastic_.xs.get()); - elastic_.distribution = - make_unique(dgroup, xs->x()); - } + } else if (temp == "incoherent_elastic") { + elastic_.distribution = make_unique(dgroup); + } else if (temp == "incoherent_elastic_discrete") { + auto xs = dynamic_cast(elastic_.xs.get()); + elastic_.distribution = + make_unique(dgroup, xs->x()); + } else if (temp == "mixed_elastic") { + // Get coherent/incoherent cross sections + auto mixed_xs = dynamic_cast(elastic_.xs.get()); + const auto& coh_xs = + dynamic_cast(mixed_xs->functions(0).get()); + const auto& incoh_xs = + dynamic_cast(mixed_xs->functions(1).get()); + + // Create mixed elastic distribution + elastic_.distribution = + make_unique(dgroup, *coh_xs, *incoh_xs); } close_group(elastic_group); From edf023adb9d48b5b8078ad3ca4886b0176457902 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 19 Oct 2021 17:05:49 -0500 Subject: [PATCH 0646/2654] Fix HDF5 export of mixed elastic distribution --- openmc/data/thermal_angle_energy.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openmc/data/thermal_angle_energy.py b/openmc/data/thermal_angle_energy.py index 6ef874600..d7dfe92f9 100644 --- a/openmc/data/thermal_angle_energy.py +++ b/openmc/data/thermal_angle_energy.py @@ -33,17 +33,22 @@ class CoherentElasticAE(AngleEnergy): def __init__(self, coherent_xs): self.coherent_xs = coherent_xs - def to_hdf5(self, group): + def to_hdf5(self, group, xs_group=None): """Write coherent elastic distribution to an HDF5 group Parameters ---------- group : h5py.Group HDF5 group to write to + xs_group : h5py.Group, optional + Group containing 'xs' dataset """ group.attrs['type'] = np.string_('coherent_elastic') - group['coherent_xs'] = group.parent['xs'] + if xs_group is not None: + group['coherent_xs'] = xs_group['xs'] + else: + group['coherent_xs'] = group.parent['xs'] class IncoherentElasticAE(AngleEnergy): @@ -245,7 +250,7 @@ class MixedElasticAE(AngleEnergy): """ group.attrs['type'] = np.string_('mixed_elastic') coherent_group = group.create_group('coherent') - self.coherent.to_hdf5(coherent_group) + self.coherent.to_hdf5(coherent_group, group.parent) incoherent_group = group.create_group('incoherent') self.incoherent.to_hdf5(incoherent_group) From 4e611f59b9ac60839fa0224a91be929572f0dbc3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 20 Oct 2021 06:53:20 -0500 Subject: [PATCH 0647/2654] Make incoherent XS polymorphic in MixedElasticAE --- include/openmc/secondary_thermal.h | 4 ++-- src/secondary_thermal.cpp | 5 +++-- src/thermal.cpp | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/openmc/secondary_thermal.h b/include/openmc/secondary_thermal.h index 81de5c451..5b18902af 100644 --- a/include/openmc/secondary_thermal.h +++ b/include/openmc/secondary_thermal.h @@ -160,7 +160,7 @@ public: // //! \param[in] group HDF5 group explicit MixedElasticAE( - hid_t group, const CoherentElasticXS& coh_xs, const Tabulated1D& incoh_xs); + hid_t group, const CoherentElasticXS& coh_xs, const Function1D& incoh_xs); //! Sample distribution for an angle and energy //! \param[in] E_in Incoming energy in [eV] @@ -175,7 +175,7 @@ private: unique_ptr incoherent_dist_; //!< Incoherent distribution const CoherentElasticXS& coherent_xs_; //!< Ref. to coherent XS - const Tabulated1D& incoherent_xs_; //!< Ref. to incoherent XS + const Function1D& incoherent_xs_; //!< Polymorphic ref. to incoherent XS }; } // namespace openmc diff --git a/src/secondary_thermal.cpp b/src/secondary_thermal.cpp index e5e8274da..0b8e1ab42 100644 --- a/src/secondary_thermal.cpp +++ b/src/secondary_thermal.cpp @@ -337,7 +337,7 @@ void IncoherentInelasticAE::sample( //============================================================================== MixedElasticAE::MixedElasticAE( - hid_t group, const CoherentElasticXS& coh_xs, const Tabulated1D& incoh_xs) + hid_t group, const CoherentElasticXS& coh_xs, const Function1D& incoh_xs) : coherent_dist_(coh_xs), coherent_xs_(coh_xs), incoherent_xs_(incoh_xs) { // Read incoherent elastic distribution @@ -347,8 +347,9 @@ MixedElasticAE::MixedElasticAE( if (temp == "incoherent_elastic") { incoherent_dist_ = make_unique(incoherent_group); } else if (temp == "incoherent_elastic_discrete") { + auto xs = dynamic_cast(&incoh_xs); incoherent_dist_ = - make_unique(incoherent_group, incoh_xs.x()); + make_unique(incoherent_group, xs->x()); } close_group(incoherent_group); } diff --git a/src/thermal.cpp b/src/thermal.cpp index 303786915..1a9592d0a 100644 --- a/src/thermal.cpp +++ b/src/thermal.cpp @@ -221,8 +221,7 @@ ThermalData::ThermalData(hid_t group) auto mixed_xs = dynamic_cast(elastic_.xs.get()); const auto& coh_xs = dynamic_cast(mixed_xs->functions(0).get()); - const auto& incoh_xs = - dynamic_cast(mixed_xs->functions(1).get()); + const auto& incoh_xs = mixed_xs->functions(1).get(); // Create mixed elastic distribution elastic_.distribution = From e8294d52a0162b484a0961195dc330ef58b5f051 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Jul 2022 14:37:34 -0500 Subject: [PATCH 0648/2654] Update documentation for mixed thermal elastic --- docs/source/io_formats/nuclear_data.rst | 23 +++++++++++++++++++++++ docs/source/pythonapi/data.rst | 1 + openmc/data/function.py | 4 ++++ openmc/data/thermal_angle_energy.py | 5 +++++ 4 files changed, 33 insertions(+) diff --git a/docs/source/io_formats/nuclear_data.rst b/docs/source/io_formats/nuclear_data.rst index ef61604cb..8174108e1 100644 --- a/docs/source/io_formats/nuclear_data.rst +++ b/docs/source/io_formats/nuclear_data.rst @@ -339,6 +339,16 @@ Incoherent elastic scattering [eV\ :math:`^{-1}`]. :Attributes: - **type** (*char[]*) -- 'IncoherentElastic' +Sum of functions +---------------- + +:Object type: Group +:Attributes: - **type** (*char[]*) -- "Sum" + - **n** (*int*) -- Number of functions +:Datasets: + - ***func_** (:ref:`function <1d_functions>`) -- Dataset for the + i-th function (indexing starts at 1) + .. _angle_energy: -------------------------- @@ -501,6 +511,19 @@ equiprobable bins. - **skewed** (*int8_t*) -- Whether discrete angles are equi-probable (0) or have a skewed distribution (1). +Mixed Elastic +------------- + +This angle-energy distribution is used when an evaluation specifies both +coherent and incoherent elastic thermal neutron scattering. + +:Object type: Group +:Attributes: - **type** (*char[]*) -- "mixed_elastic" +:Groups: - **coherent** -- Distribution for coherent elastic scattering. The + format is given in :ref:`angle_energy`. + - **incoherent** -- Distribution for incoherent elastic scattering. + The format is given in :ref:`angle_energy`. + .. _energy_distribution: -------------------- diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 287738774..c74769be6 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -116,6 +116,7 @@ Angle-Energy Distributions IncoherentElasticAE IncoherentElasticAEDiscrete IncoherentInelasticAEDiscrete + MixedElasticAE Resonance Data -------------- diff --git a/openmc/data/function.py b/openmc/data/function.py index 7a73987df..751f6cdb5 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -581,6 +581,8 @@ class Sum(EqualityMixin): def to_hdf5(self, group, name='xy'): """Write sum of functions to an HDF5 group + .. versionadded:: 0.13.1 + Parameters ---------- group : h5py.Group @@ -599,6 +601,8 @@ class Sum(EqualityMixin): def from_hdf5(cls, group): """Generate sum of functions from an HDF5 group + .. versionadded:: 0.13.1 + Parameters ---------- group : h5py.Group diff --git a/openmc/data/thermal_angle_energy.py b/openmc/data/thermal_angle_energy.py index d7dfe92f9..b7ca349f1 100644 --- a/openmc/data/thermal_angle_energy.py +++ b/openmc/data/thermal_angle_energy.py @@ -36,6 +36,9 @@ class CoherentElasticAE(AngleEnergy): def to_hdf5(self, group, xs_group=None): """Write coherent elastic distribution to an HDF5 group + .. versionchanged:: 0.13.1 + The *xs_group* argument was added. + Parameters ---------- group : h5py.Group @@ -220,6 +223,8 @@ class IncoherentInelasticAE(CorrelatedAngleEnergy): class MixedElasticAE(AngleEnergy): """Secondary distribution for mixed coherent/incoherent thermal elastic + .. versionadded:: 0.13.1 + Parameters ---------- coherent : AngleEnergy From 0f03710e367094db1a822f00db7a1e857ea89dcc Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Jul 2022 16:09:49 -0500 Subject: [PATCH 0649/2654] Fix hdf5 write/read for coherent and mixed elastic --- openmc/data/function.py | 2 +- openmc/data/thermal.py | 2 +- openmc/data/thermal_angle_energy.py | 35 ++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/openmc/data/function.py b/openmc/data/function.py index 751f6cdb5..b0390d19c 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -544,7 +544,7 @@ class Combination(EqualityMixin): self._operations = operations -class Sum(EqualityMixin): +class Sum(Function1D): """Sum of multiple functions. This class allows you to create a callable object which represents the sum diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index 6cf5a4e9e..3d5f2df64 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -701,7 +701,7 @@ class ThermalScattering(EqualityMixin): energy = ace.xss[idx + 1: idx + 1 + n_energy]*EV_PER_MEV P = ace.xss[idx + 1 + n_energy: idx + 1 + 2 * n_energy] coherent_xs = CoherentElastic(energy, P*EV_PER_MEV) - coherent_dist = CoherentElasticAE(xs) + coherent_dist = CoherentElasticAE(coherent_xs) # Coherent elastic shouldn't have angular distributions listed n_mu = ace.nxs[6] + 1 diff --git a/openmc/data/thermal_angle_energy.py b/openmc/data/thermal_angle_energy.py index b7ca349f1..1f37863ea 100644 --- a/openmc/data/thermal_angle_energy.py +++ b/openmc/data/thermal_angle_energy.py @@ -2,6 +2,7 @@ import numpy as np from .angle_energy import AngleEnergy from .correlated import CorrelatedAngleEnergy +import openmc.data class CoherentElasticAE(AngleEnergy): @@ -33,25 +34,37 @@ class CoherentElasticAE(AngleEnergy): def __init__(self, coherent_xs): self.coherent_xs = coherent_xs - def to_hdf5(self, group, xs_group=None): + def to_hdf5(self, group): """Write coherent elastic distribution to an HDF5 group - .. versionchanged:: 0.13.1 - The *xs_group* argument was added. - Parameters ---------- group : h5py.Group HDF5 group to write to - xs_group : h5py.Group, optional - Group containing 'xs' dataset """ group.attrs['type'] = np.string_('coherent_elastic') - if xs_group is not None: - group['coherent_xs'] = xs_group['xs'] - else: - group['coherent_xs'] = group.parent['xs'] + self.coherent_xs.to_hdf5(group, 'coherent_xs') + + @classmethod + def from_hdf5(cls, group): + """Generate coherent elastic distribution from HDF5 data + + .. versionadded:: 0.13.1 + + Parameters + ---------- + group : h5py.Group + HDF5 group to read from + + Returns + ------- + openmc.data.CoherentElasticAE + Coherent elastic distribution + + """ + coherent_xs = openmc.data.CoherentElastic.from_hdf5(group['coherent_xs']) + return cls(coherent_xs) class IncoherentElasticAE(AngleEnergy): @@ -255,7 +268,7 @@ class MixedElasticAE(AngleEnergy): """ group.attrs['type'] = np.string_('mixed_elastic') coherent_group = group.create_group('coherent') - self.coherent.to_hdf5(coherent_group, group.parent) + self.coherent.to_hdf5(coherent_group) incoherent_group = group.create_group('incoherent') self.incoherent.to_hdf5(incoherent_group) From 425dba5d25f6a3d737838f9cb408dd57bf45c24e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 22 Jul 2022 07:46:34 -0500 Subject: [PATCH 0650/2654] Add test for mixed elastic thermal scattering --- openmc/mixin.py | 7 +- tests/unit_tests/test_data_thermal.py | 105 ++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/openmc/mixin.py b/openmc/mixin.py index 516162464..31c26ec76 100644 --- a/openmc/mixin.py +++ b/openmc/mixin.py @@ -14,8 +14,11 @@ class EqualityMixin: def __eq__(self, other): if isinstance(other, type(self)): for key, value in self.__dict__.items(): - if not np.array_equal(value, other.__dict__.get(key)): - return False + if isinstance(value, np.ndarray): + if not np.array_equal(value, other.__dict__.get(key)): + return False + else: + return value == other.__dict__.get(key) else: return False diff --git a/tests/unit_tests/test_data_thermal.py b/tests/unit_tests/test_data_thermal.py index dc4d24628..61ae61b24 100644 --- a/tests/unit_tests/test_data_thermal.py +++ b/tests/unit_tests/test_data_thermal.py @@ -262,3 +262,108 @@ def test_get_thermal_name(): # Names that don't remotely match anything assert f('boogie_monster') == 'c_boogie_monster' + + +@pytest.fixture +def fake_mixed_elastic(): + fake_tsl = openmc.data.ThermalScattering("c_D_in_7LiD", 1.9968, 4.9, [0.0253]) + fake_tsl.nuclides = ['H2'] + + # Create elastic reaction + bragg_edges = [0.00370672, 0.00494229, 0.00988458, 0.01359131, 0.01482688, + 0.01976918, 0.02347589, 0.02471147, 0.02965376, 0.03336048, + 0.03953834, 0.04324506, 0.04448063, 0.04942292, 0.05312964, + 0.05436522, 0.05930751, 0.06301423, 0.0642498 , 0.06919209, + 0.07289881, 0.07907667, 0.08278339, 0.08401896, 0.08896126, + 0.09266798, 0.09390355, 0.09884584, 0.1025526 , 0.1037882 , + 0.1087305 , 0.1124372 , 0.1186151 , 0.1223218 , 0.1235574 , + 0.1284997 , 0.1322064 , 0.133442 , 0.142091 , 0.1433266 , + 0.1482688 , 0.1519756 , 0.1581534 , 0.1618601 , 0.1630957 , + 0.168038 , 0.1717447 , 0.1729803 , 0.1779226 , 0.1816293 , + 0.1828649 , 0.1878072 , 0.1915139 , 0.1976918 , 0.2026341 , + 0.2075763 , 0.2125186 , 0.2174609 , 0.2224032 , 0.2273455 , + 0.2421724 , 0.2471147 , 0.252057 , 0.2569993 , 0.2619415 , + 0.2668838 , 0.2767684 , 0.2817107 , 0.2915953 , 0.3064222 , + 0.3261913 , 0.366965] + factors = [0.00375735, 0.01386287, 0.02595574, 0.02992438, 0.03549502, + 0.03855745, 0.04058831, 0.04986305, 0.05703106, 0.05855471, + 0.06078031, 0.06212291, 0.06656602, 0.06930339, 0.0697072 , + 0.07201456, 0.07263853, 0.07313129, 0.07465531, 0.07714482, + 0.07759976, 0.077809 , 0.07790282, 0.07927957, 0.08013058, + 0.08026637, 0.08073475, 0.08112202, 0.08123039, 0.08187171, + 0.08213756, 0.08218236, 0.08236572, 0.08240729, 0.08259795, + 0.08297893, 0.08300455, 0.08314566, 0.08315611, 0.08337715, + 0.08350026, 0.08350663, 0.08352815, 0.08353776, 0.0836098 , + 0.08367017, 0.08367361, 0.0837242 , 0.08375069, 0.08375227, + 0.08377006, 0.08381488, 0.08381644, 0.08382698, 0.08386266, + 0.08387756, 0.08388445, 0.08388974, 0.08390341, 0.08391088, + 0.08391695, 0.08392361, 0.08392684, 0.08392818, 0.08393161, + 0.08393546, 0.08393685, 0.08393801, 0.08393976, 0.08394167, + 0.08394288, 0.08394398] + coherent_xs = openmc.data.CoherentElastic(bragg_edges, factors) + incoherent_xs = openmc.data.Tabulated1D([0.00370672, 0.00370672], [0.00370672, 0.00370672]) + elastic_xs = {'294K': openmc.data.Sum((coherent_xs, incoherent_xs))} + coherent_dist = openmc.data.CoherentElasticAE(coherent_xs) + incoherent_dist = openmc.data.IncoherentElasticAEDiscrete([ + [-0.6, -0.18, 0.18, 0.6], [-0.6, -0.18, 0.18, 0.6] + ]) + elastic_dist = {'294K': openmc.data.MixedElasticAE(coherent_dist, incoherent_dist)} + fake_tsl.elastic = openmc.data.ThermalScatteringReaction(elastic_xs, elastic_dist) + + # Create inelastic reaction + inelastic_xs = {'294K': openmc.data.Tabulated1D([1.0e-5, 4.9], [13.4, 3.35])} + breakpoints = [3] + interpolation = [2] + energy = [1.0e-5, 4.3e-2, 4.9] + energy_out = [ + openmc.data.Tabular([0.0002, 0.067, 0.146, 0.366], [0.25, 0.25, 0.25, 0.25]), + openmc.data.Tabular([0.0001, 0.009, 0.137, 0.277], [0.25, 0.25, 0.25, 0.25]), + openmc.data.Tabular([0.0579, 4.555, 4.803, 4.874], [0.25, 0.25, 0.25, 0.25]), + ] + for eout in energy_out: + eout.normalize() + eout.c = eout.cdf() + discrete = openmc.stats.Discrete([-0.9, -0.6, -0.3, -0.1, 0.1, 0.3, 0.6, 0.9], [1/8]*8) + discrete.c = discrete.cdf()[1:] + mu = [[discrete]*4]*3 + inelastic_dist = {'294K': openmc.data.IncoherentInelasticAE( + breakpoints, interpolation, energy, energy_out, mu)} + inelastic = openmc.data.ThermalScatteringReaction(inelastic_xs, inelastic_dist) + fake_tsl.inelastic = inelastic + + return fake_tsl + + +def test_mixed_elastic(fake_mixed_elastic, run_in_tmpdir): + # Write data to HDF5 and then read back + original = fake_mixed_elastic + original.export_to_hdf5('c_D_in_7LiD.h5') + copy = openmc.data.ThermalScattering.from_hdf5('c_D_in_7LiD.h5') + + # Make sure data did not change as a result of HDF5 writing/reading + assert original == copy + + # Create modified cross_sections.xml file that includes the above data + xs = openmc.data.DataLibrary.from_xml() + xs.register_file('c_D_in_7LiD.h5') + xs.export_to_xml('cross_sections_mixed.xml') + + # Create a minimal model that includes the new data and run it + mat = openmc.Material() + mat.add_nuclide('H2', 1.0) + mat.add_nuclide('Li7', 1.0) + mat.set_density('g/cm3', 1.0) + mat.add_s_alpha_beta('c_D_in_7LiD') + sph = openmc.Sphere(r=10.0, boundary_type="vacuum") + cell = openmc.Cell(fill=mat, region=-sph) + model = openmc.Model() + model.geometry = openmc.Geometry([cell]) + model.materials = openmc.Materials([mat]) + model.materials.cross_sections = "cross_sections_mixed.xml" + model.settings.particles = 1000 + model.settings.batches = 10 + model.settings.run_mode = 'fixed source' + model.settings.source = openmc.Source( + energy=openmc.stats.Discrete([3.0], [1.0]) # 3 eV source + ) + model.run() From 3b33fb830624d8c0e7959e6326214f52ae988eb0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 22 Jul 2022 07:55:22 -0500 Subject: [PATCH 0651/2654] Adding comment as suggested by @paulromano --- openmc/mesh.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index d08213f77..4af701892 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -248,6 +248,10 @@ class StructuredMesh(MeshBase): # create VTK arrays for each of # the data sets + + # maintain a list of the datasets as added + # to the VTK arrays to ensure they persist + # in memory until the file is written datasets_out = [] for label, dataset in datasets.items(): dataset = np.asarray(dataset).flatten() From 443c2ac4c99c06866798ca14b2944d8d50e0141a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 11:59:30 -0500 Subject: [PATCH 0652/2654] Add integral method on Discrete, Tabular, and Mixture classes --- openmc/stats/univariate.py | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 5528bdb30..733b7eaa6 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -220,6 +220,16 @@ class Discrete(Univariate): p_arr = np.array([p_merged[x] for x in x_arr]) return cls(x_arr, p_arr) + def integral(self): + """Return integral of distribution + + Returns + ------- + float + Integral of discrete distribution + """ + return np.sum(self.p) + class Uniform(Univariate): """Distribution with constant probability over a finite interval [a,b] @@ -1027,6 +1037,22 @@ class Tabular(Univariate): p = params[len(params)//2:] return cls(x, p, interpolation) + def integral(self): + """Return integral of distribution + + Returns + ------- + float + Integral of tabular distrbution + """ + if self.interpolation == 'histogram': + return np.sum(np.diff(self.x) * self.p[:-1]) + elif self.interpolation == 'linear-linear': + return np.trapz(self.p, self.x) + else: + raise NotImplementedError( + f'integral() not supported for {self.inteprolation} interpolation') + class Legendre(Univariate): r"""Probability density given by a Legendre polynomial expansion @@ -1199,3 +1225,16 @@ class Mixture(Univariate): distribution.append(Univariate.from_xml_element(pair.find("dist"))) return cls(probability, distribution) + + def integral(self): + """Return integral of the distribution + + Returns + ------- + float + Integral of the distribution + """ + return sum([ + p*dist.integral() + for p, dist in zip(self.probability, self.distribution) + ]) From c4a9b2c8b13592e2e761985eef3f2eef3dc092f0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 5 Apr 2022 11:34:09 -0500 Subject: [PATCH 0653/2654] Get gamma and xray decay sources as distributions --- openmc/data/decay.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 51a594bc8..2855a9434 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -9,7 +9,9 @@ from uncertainties import ufloat, UFloat import openmc.checkvalue as cv from openmc.mixin import EqualityMixin +from openmc.stats import Discrete, Tabular from .data import ATOMIC_SYMBOL, ATOMIC_NUMBER +from .function import INTERPOLATION_SCHEME from .endf import Evaluation, get_head_record, get_list_record, get_tab1_record @@ -495,3 +497,43 @@ class Decay(EqualityMixin): """ return cls(ev_or_filename) + + def get_sources(self): + sources = {} + name = self.nuclide['name'] + for particle, spectra in self.spectra.items(): + # Only handle gammas for now + if particle not in ('gamma', 'xray'): + continue + + # Create distribution for discrete + distributions = [] + if spectra['continuous_flag'] in ('discrete', 'both'): + energies = [] + intensities = [] + for discrete_data in spectra['discrete']: + energies.append(discrete_data['energy'].n) + intensities.append(discrete_data['intensity'].n) + energies = np.array(energies) + intensities = np.array(intensities) + dist_discrete = Discrete(energies, intensities) # <-- not normalized yet + dist_discrete._normalization = spectra['discrete_normalization'].n + distributions.append(dist_discrete) + + # Create distribution for continuous + if spectra['continuous_flag'] in ('continuous', 'both'): + f = spectra['continuous']['probability'] + if len(f.interpolation) > 1: + raise NotImplementedError("Multiple interpolation regions: {name}, {particle}") + interpolation = INTERPOLATION_SCHEME[f.interpolation[0]] + if interpolation not in ('histogram', 'linear-linear'): + raise NotImplementedError("Continuous spectra with {interpolation} interpolation ({name}, {particle}) not supported") + + dist_continuous = Tabular(f.x, f.y, interpolation) + dist_continuous._intensity = spectra['continuous_normalization'].n + distributions.append(dist_continuous) + + # Combine distribution for discrete and continuous + sources[particle] = distributions + + return sources From b7596245f2af6c5484c9bb73e323e39ee6fb2de9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 5 Apr 2022 12:50:22 -0500 Subject: [PATCH 0654/2654] Combined decay distributions --- openmc/data/decay.py | 46 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 2855a9434..5de07f465 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -9,7 +9,7 @@ from uncertainties import ufloat, UFloat import openmc.checkvalue as cv from openmc.mixin import EqualityMixin -from openmc.stats import Discrete, Tabular +from openmc.stats import Discrete, Tabular, Mixture from .data import ATOMIC_SYMBOL, ATOMIC_NUMBER from .function import INTERPOLATION_SCHEME from .endf import Evaluation, get_head_record, get_list_record, get_tab1_record @@ -499,15 +499,27 @@ class Decay(EqualityMixin): return cls(ev_or_filename) def get_sources(self): + """Get radioactive decay source distributions + + Returns + ------- + sources : dict + Dictionary mapping particle types (e.g., 'photon') to instances of + :class:`openmc.stats.Univariate` + + """ sources = {} name = self.nuclide['name'] for particle, spectra in self.spectra.items(): # Only handle gammas for now if particle not in ('gamma', 'xray'): continue + # TODO: Set particle type based on 'particle' above + particle_type = 'photon' + if particle_type not in sources: + sources[particle_type] = [] # Create distribution for discrete - distributions = [] if spectra['continuous_flag'] in ('discrete', 'both'): energies = [] intensities = [] @@ -516,9 +528,10 @@ class Decay(EqualityMixin): intensities.append(discrete_data['intensity'].n) energies = np.array(energies) intensities = np.array(intensities) + intensities *= spectra['discrete_normalization'].n dist_discrete = Discrete(energies, intensities) # <-- not normalized yet - dist_discrete._normalization = spectra['discrete_normalization'].n - distributions.append(dist_discrete) + dist_discrete._intensity = intensities.sum() + sources[particle_type].append(dist_discrete) # Create distribution for continuous if spectra['continuous_flag'] in ('continuous', 'both'): @@ -531,9 +544,28 @@ class Decay(EqualityMixin): dist_continuous = Tabular(f.x, f.y, interpolation) dist_continuous._intensity = spectra['continuous_normalization'].n - distributions.append(dist_continuous) + sources[particle_type].append(dist_continuous) - # Combine distribution for discrete and continuous - sources[particle] = distributions + # Combine discrete distributions + for dist_list in sources.values(): + # Get list of discrete distributions + discrete_index = [i for i, d in enumerate(dist_list) if isinstance(d, Discrete)] + dist_discrete = [dist_list[i] for i in discrete_index] + if len(dist_discrete) > 1: + # Create combined discrete distribution + probs = [1.0] * len(dist_discrete) + combined_dist = Discrete.merge(dist_discrete, probs) + combined_dist._intensity = np.sum(combined_dist.p) + + for idx in reversed(discrete_index): + dist_list.pop(idx) + dist_list.append(combined_dist) + + # Combine discrete and continuous if present + if len(dist_list) > 1: + probs = [d._intensity for d in dist_list] + dist_list[:] = Mixture(probs, dist_list.copy()) + + sources = {k: (v[0] if v else None) for k, v in sources.items()} return sources From 1b2b5e169c7dcf9d504ed505edc76f96ee25e87d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 23 May 2022 14:44:08 -0500 Subject: [PATCH 0655/2654] Map radiation type to particle type properly in Decay.get_sources --- openmc/data/decay.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 5de07f465..142be35e4 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -511,11 +511,21 @@ class Decay(EqualityMixin): sources = {} name = self.nuclide['name'] for particle, spectra in self.spectra.items(): - # Only handle gammas for now - if particle not in ('gamma', 'xray'): - continue - # TODO: Set particle type based on 'particle' above - particle_type = 'photon' + # Set particle type based on 'particle' above + particle_type = { + 'gamma': 'photon', + 'beta-': 'electron', + 'ec/beta+': 'positron', + 'alpha': 'alpha', + 'n': 'neutron', + 'sf': 'fragment', + 'p': 'proton', + 'e-': 'electron', + 'xray': 'photon', + 'anti-neutrino': 'anti-neutrino', + 'neutrino': 'neutrino', + }[particle] + if particle_type not in sources: sources[particle_type] = [] From 6388c8f994b6587cd2d0de1e3aea2d6c3b514ec6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 12:02:31 -0500 Subject: [PATCH 0656/2654] Separate out a function for combine_distributions --- openmc/data/decay.py | 73 +++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 18 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 142be35e4..edf9c1c0b 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -1,4 +1,5 @@ from collections.abc import Iterable +from copy import deepcopy from io import StringIO from math import log import re @@ -552,30 +553,66 @@ class Decay(EqualityMixin): if interpolation not in ('histogram', 'linear-linear'): raise NotImplementedError("Continuous spectra with {interpolation} interpolation ({name}, {particle}) not supported") + # TODO: work normalization into tabular itself dist_continuous = Tabular(f.x, f.y, interpolation) dist_continuous._intensity = spectra['continuous_normalization'].n sources[particle_type].append(dist_continuous) # Combine discrete distributions - for dist_list in sources.values(): - # Get list of discrete distributions - discrete_index = [i for i, d in enumerate(dist_list) if isinstance(d, Discrete)] - dist_discrete = [dist_list[i] for i in discrete_index] + merged_sources = {} + for particle_type, dist_list in sources.items(): + merged_sources[particle_type] = combine_distributions( + dist_list, [1.0]*len(dist_list)) - if len(dist_discrete) > 1: - # Create combined discrete distribution - probs = [1.0] * len(dist_discrete) - combined_dist = Discrete.merge(dist_discrete, probs) - combined_dist._intensity = np.sum(combined_dist.p) + return merged_sources - for idx in reversed(discrete_index): - dist_list.pop(idx) - dist_list.append(combined_dist) - # Combine discrete and continuous if present - if len(dist_list) > 1: - probs = [d._intensity for d in dist_list] - dist_list[:] = Mixture(probs, dist_list.copy()) +def combine_distributions(dists, probs): + """Combine distributions with specified probabilities - sources = {k: (v[0] if v else None) for k, v in sources.items()} - return sources + This function can be used to combine multiple instances of + :class:`~openmc.stats.Discrete` and `~openmc.stats.Tabular` into a single + distribution. Multiple discrete distributions are merged into a single + distribution and the remainder of the distributions are put into a + :class:`~openmc.stats.Mixture` distribution. + + Parameters + ---------- + dists : iterable of openmc.stats.Univariate + Distributions to combine + probs : iterable of float + Probability (or intensity) of each distribution + + """ + # Get copy of distribution list so as not to modify the argument + dist_list = deepcopy(dists) + + # Get list of discrete/continuous distribution indices + discrete_index = [i for i, d in enumerate(dist_list) if isinstance(d, Discrete)] + cont_index = [i for i, d in enumerate(dist_list) if isinstance(d, Tabular)] + + # Apply probabilites to continuous distributions + for i in cont_index: + dist = dist_list[i] + dist.p *= probs[i] + dist._intensity *= probs[i] + + if discrete_index: + # Create combined discrete distribution + dist_discrete = [dist_list[i] for i in discrete_index] + discrete_probs = [probs[i] for i in discrete_index] + combined_dist = Discrete.merge(dist_discrete, discrete_probs) + combined_dist._intensity = np.sum(combined_dist.p) + + # Replace multiple discrete distributions with merged + for idx in reversed(discrete_index): + dist_list.pop(idx) + dist_list.append(combined_dist) + + # Combine discrete and continuous if present + if len(dist_list) > 1: + probs = [d._intensity for d in dist_list] + dist_list[:] = [Mixture(probs, dist_list.copy())] + dist_list[0]._intensity = sum(probs) + + return dist_list[0] From d4989ae64226f0e11d75220277bfb13e3bdb538f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 May 2022 12:48:06 -0500 Subject: [PATCH 0657/2654] Use integral() methods instead of _intensity hidden attribute --- openmc/data/decay.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index edf9c1c0b..874981e2b 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -511,6 +511,7 @@ class Decay(EqualityMixin): """ sources = {} name = self.nuclide['name'] + decay_constant = self.decay_constant.n for particle, spectra in self.spectra.items(): # Set particle type based on 'particle' above particle_type = { @@ -538,10 +539,9 @@ class Decay(EqualityMixin): energies.append(discrete_data['energy'].n) intensities.append(discrete_data['intensity'].n) energies = np.array(energies) - intensities = np.array(intensities) - intensities *= spectra['discrete_normalization'].n - dist_discrete = Discrete(energies, intensities) # <-- not normalized yet - dist_discrete._intensity = intensities.sum() + intensity = spectra['discrete_normalization'].n + rates = decay_constant * intensity * np.array(intensities) + dist_discrete = Discrete(energies, rates) sources[particle_type].append(dist_discrete) # Create distribution for continuous @@ -553,9 +553,9 @@ class Decay(EqualityMixin): if interpolation not in ('histogram', 'linear-linear'): raise NotImplementedError("Continuous spectra with {interpolation} interpolation ({name}, {particle}) not supported") - # TODO: work normalization into tabular itself - dist_continuous = Tabular(f.x, f.y, interpolation) - dist_continuous._intensity = spectra['continuous_normalization'].n + intensity = spectra['continuous_normalization'].n + rates = decay_constant * intensity * f.y + dist_continuous = Tabular(f.x, rates, interpolation) sources[particle_type].append(dist_continuous) # Combine discrete distributions @@ -595,14 +595,12 @@ def combine_distributions(dists, probs): for i in cont_index: dist = dist_list[i] dist.p *= probs[i] - dist._intensity *= probs[i] if discrete_index: # Create combined discrete distribution dist_discrete = [dist_list[i] for i in discrete_index] discrete_probs = [probs[i] for i in discrete_index] combined_dist = Discrete.merge(dist_discrete, discrete_probs) - combined_dist._intensity = np.sum(combined_dist.p) # Replace multiple discrete distributions with merged for idx in reversed(discrete_index): @@ -611,8 +609,7 @@ def combine_distributions(dists, probs): # Combine discrete and continuous if present if len(dist_list) > 1: - probs = [d._intensity for d in dist_list] + probs = [d.integral() for d in dist_list] dist_list[:] = [Mixture(probs, dist_list.copy())] - dist_list[0]._intensity = sum(probs) return dist_list[0] From 7c779f73f8aa70c43283e4bbed2404ece2b2ab3a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 18 Jul 2022 07:18:23 -0500 Subject: [PATCH 0658/2654] Move combine_distributions to univariate.py --- docs/source/pythonapi/data.rst | 1 + openmc/data/decay.py | 49 +--------------------------------- openmc/stats/univariate.py | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 287738774..6f56938b8 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -61,6 +61,7 @@ Core Functions atomic_mass atomic_weight + combine_distributions decay_constant dose_coefficients gnd_name diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 874981e2b..f358dadf7 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -1,5 +1,4 @@ from collections.abc import Iterable -from copy import deepcopy from io import StringIO from math import log import re @@ -10,7 +9,7 @@ from uncertainties import ufloat, UFloat import openmc.checkvalue as cv from openmc.mixin import EqualityMixin -from openmc.stats import Discrete, Tabular, Mixture +from openmc.stats import Discrete, Tabular, combine_distributions from .data import ATOMIC_SYMBOL, ATOMIC_NUMBER from .function import INTERPOLATION_SCHEME from .endf import Evaluation, get_head_record, get_list_record, get_tab1_record @@ -567,49 +566,3 @@ class Decay(EqualityMixin): return merged_sources -def combine_distributions(dists, probs): - """Combine distributions with specified probabilities - - This function can be used to combine multiple instances of - :class:`~openmc.stats.Discrete` and `~openmc.stats.Tabular` into a single - distribution. Multiple discrete distributions are merged into a single - distribution and the remainder of the distributions are put into a - :class:`~openmc.stats.Mixture` distribution. - - Parameters - ---------- - dists : iterable of openmc.stats.Univariate - Distributions to combine - probs : iterable of float - Probability (or intensity) of each distribution - - """ - # Get copy of distribution list so as not to modify the argument - dist_list = deepcopy(dists) - - # Get list of discrete/continuous distribution indices - discrete_index = [i for i, d in enumerate(dist_list) if isinstance(d, Discrete)] - cont_index = [i for i, d in enumerate(dist_list) if isinstance(d, Tabular)] - - # Apply probabilites to continuous distributions - for i in cont_index: - dist = dist_list[i] - dist.p *= probs[i] - - if discrete_index: - # Create combined discrete distribution - dist_discrete = [dist_list[i] for i in discrete_index] - discrete_probs = [probs[i] for i in discrete_index] - combined_dist = Discrete.merge(dist_discrete, discrete_probs) - - # Replace multiple discrete distributions with merged - for idx in reversed(discrete_index): - dist_list.pop(idx) - dist_list.append(combined_dist) - - # Combine discrete and continuous if present - if len(dist_list) > 1: - probs = [d.integral() for d in dist_list] - dist_list[:] = [Mixture(probs, dist_list.copy())] - - return dist_list[0] diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 733b7eaa6..f571377bf 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod from collections import defaultdict from collections.abc import Iterable +from copy import deepcopy from numbers import Real from xml.etree import ElementTree as ET @@ -1238,3 +1239,51 @@ class Mixture(Univariate): p*dist.integral() for p, dist in zip(self.probability, self.distribution) ]) + + +def combine_distributions(dists, probs): + """Combine distributions with specified probabilities + + This function can be used to combine multiple instances of + :class:`~openmc.stats.Discrete` and `~openmc.stats.Tabular` into a single + distribution. Multiple discrete distributions are merged into a single + distribution and the remainder of the distributions are put into a + :class:`~openmc.stats.Mixture` distribution. + + Parameters + ---------- + dists : iterable of openmc.stats.Univariate + Distributions to combine + probs : iterable of float + Probability (or intensity) of each distribution + + """ + # Get copy of distribution list so as not to modify the argument + dist_list = deepcopy(dists) + + # Get list of discrete/continuous distribution indices + discrete_index = [i for i, d in enumerate(dist_list) if isinstance(d, Discrete)] + cont_index = [i for i, d in enumerate(dist_list) if isinstance(d, Tabular)] + + # Apply probabilites to continuous distributions + for i in cont_index: + dist = dist_list[i] + dist.p *= probs[i] + + if discrete_index: + # Create combined discrete distribution + dist_discrete = [dist_list[i] for i in discrete_index] + discrete_probs = [probs[i] for i in discrete_index] + combined_dist = Discrete.merge(dist_discrete, discrete_probs) + + # Replace multiple discrete distributions with merged + for idx in reversed(discrete_index): + dist_list.pop(idx) + dist_list.append(combined_dist) + + # Combine discrete and continuous if present + if len(dist_list) > 1: + probs = [d.integral() for d in dist_list] + dist_list[:] = [Mixture(probs, dist_list.copy())] + + return dist_list[0] From 5a9662aa9fbe0743a10a0f778910475dc9507a3a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 18 Jul 2022 10:54:58 -0500 Subject: [PATCH 0659/2654] Add test for combine_distributions, use np.array in Discrete/Tabular setters --- openmc/stats/univariate.py | 22 +++++++++---------- tests/unit_tests/test_stats.py | 39 ++++++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index f571377bf..e11c9b50e 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -96,9 +96,9 @@ class Discrete(Univariate): Attributes ---------- - x : Iterable of float + x : numpy.ndarray Values of the random variable - p : Iterable of float + p : numpy.ndarray Discrete probability for each value """ @@ -123,7 +123,7 @@ class Discrete(Univariate): if isinstance(x, Real): x = [x] cv.check_type('discrete values', x, Iterable, Real) - self._x = x + self._x = np.array(x, dtype=float) @p.setter def p(self, p): @@ -132,7 +132,7 @@ class Discrete(Univariate): cv.check_type('discrete probabilities', p, Iterable, Real) for pk in p: cv.check_greater_than('discrete probability', pk, 0.0, True) - self._p = p + self._p = np.array(p, dtype=float) def cdf(self): return np.insert(np.cumsum(self.p), 0, 0.0) @@ -836,9 +836,9 @@ class Tabular(Univariate): Attributes ---------- - x : Iterable of float + x : numpy.ndarray Tabulated values of the random variable - p : Iterable of float + p : numpy.ndarray Tabulated probabilities interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'}, optional Indicate whether the density function is constant between tabulated @@ -871,7 +871,7 @@ class Tabular(Univariate): @x.setter def x(self, x): cv.check_type('tabulated values', x, Iterable, Real) - self._x = x + self._x = np.array(x, dtype=float) @p.setter def p(self, p): @@ -879,7 +879,7 @@ class Tabular(Univariate): if not self._ignore_negative: for pk in p: cv.check_greater_than('tabulated probability', pk, 0.0, True) - self._p = p + self._p = np.array(p, dtype=float) @interpolation.setter def interpolation(self, interpolation): @@ -892,8 +892,8 @@ class Tabular(Univariate): 'distributions using histogram or ' 'linear-linear interpolation') c = np.zeros_like(self.x) - x = np.asarray(self.x) - p = np.asarray(self.p) + x = self.x + p = self.p if self.interpolation == 'histogram': c[1:] = p[:-1] * np.diff(x) @@ -933,7 +933,7 @@ class Tabular(Univariate): def normalize(self): """Normalize the probabilities stored on the distribution""" - self.p = np.asarray(self.p) / self.cdf().max() + self.p /= self.cdf().max() def sample(self, n_samples=1, seed=None): if not self.interpolation in ('histogram', 'linear-linear'): diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index b57f9578a..404cecd13 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -13,8 +13,8 @@ def test_discrete(): elem = d.to_xml_element('distribution') d = openmc.stats.Discrete.from_xml_element(elem) - assert d.x == x - assert d.p == p + np.testing.assert_array_equal(d.x, x) + np.testing.assert_array_equal(d.p, p) assert len(d) == len(x) d = openmc.stats.Univariate.from_xml_element(elem) @@ -76,8 +76,8 @@ def test_uniform(): assert len(d) == 2 t = d.to_tabular() - assert t.x == [a, b] - assert t.p == [1/(b-a), 1/(b-a)] + np.testing.assert_array_equal(t.x, [a, b]) + np.testing.assert_array_equal(t.p, [1/(b-a), 1/(b-a)]) assert t.interpolation == 'histogram' exp_mean = 0.5 * (a + b) @@ -396,3 +396,34 @@ def test_muir(): assert within_2_sigma / n_samples >= 0.95 within_3_sigma = np.count_nonzero(samples < 3*d.std_dev) assert within_3_sigma / n_samples >= 0.99 + + +def test_combine_distributions(): + # Combine two discrete (same data as in test_merge_discrete) + x1 = [0.0, 1.0, 10.0] + p1 = [0.3, 0.2, 0.5] + d1 = openmc.stats.Discrete(x1, p1) + x2 = [0.5, 1.0, 5.0] + p2 = [0.4, 0.5, 0.1] + d2 = openmc.stats.Discrete(x2, p2) + + # Merged distribution should have x values sorted and probabilities + # appropriately combined. Duplicate x values should appear once. + merged = openmc.stats.combine_distributions([d1, d2], [0.6, 0.4]) + assert isinstance(merged, openmc.stats.Discrete) + assert merged.x == pytest.approx([0.0, 0.5, 1.0, 5.0, 10.0]) + assert merged.p == pytest.approx( + [0.6*0.3, 0.4*0.4, 0.6*0.2 + 0.4*0.5, 0.4*0.1, 0.6*0.5]) + + # Probabilities add up but are not normalized + d1 = openmc.stats.Discrete([3.0], [1.0]) + triple = openmc.stats.combine_distributions([d1, d1, d1], [1.0, 2.0, 3.0]) + assert triple.x == pytest.approx([3.0]) + assert triple.p == pytest.approx([6.0]) + + # Combine discrete and tabular + t1 = openmc.stats.Tabular(x2, p2) + mixed = openmc.stats.combine_distributions([d1, t1], [0.5, 0.5]) + assert isinstance(mixed, openmc.stats.Mixture) + assert len(mixed.distribution) == 2 + assert len(mixed.probability) == 2 From a68a3ede6a6fc85d0b8ac6eacd7b139fbbe6278e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 18 Jul 2022 13:30:31 -0500 Subject: [PATCH 0660/2654] Change get_sources() -> sources property and add test --- openmc/data/decay.py | 27 ++++++++++++---------- openmc/stats/univariate.py | 8 +++++++ tests/unit_tests/test_data_decay.py | 35 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index f358dadf7..96c3f562a 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -316,6 +316,12 @@ class Decay(EqualityMixin): 'excited_state', 'mass', 'stable', 'spin', and 'parity'. spectra : dict Resulting radiation spectra for each radiation type. + sources : dict + Radioactive decay source distributions represented as a dictionary + mapping particle types (e.g., 'photon') to instances of + :class:`openmc.stats.Univariate`. + + .. versionadded:: 0.13.1 """ def __init__(self, ev_or_filename): @@ -498,16 +504,14 @@ class Decay(EqualityMixin): """ return cls(ev_or_filename) - def get_sources(self): - """Get radioactive decay source distributions + @property + def sources(self): + """Radioactive decay source distributions""" + # If property has been computed already, return it + # TODO: Replace with functools.cached_property when support is Python 3.9+ + if self._sources is not None: + return self._sources - Returns - ------- - sources : dict - Dictionary mapping particle types (e.g., 'photon') to instances of - :class:`openmc.stats.Univariate` - - """ sources = {} name = self.nuclide['name'] decay_constant = self.decay_constant.n @@ -563,6 +567,5 @@ class Decay(EqualityMixin): merged_sources[particle_type] = combine_distributions( dist_list, [1.0]*len(dist_list)) - return merged_sources - - + self._sources = merged_sources + return self._sources diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index e11c9b50e..66c6e5f06 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -224,6 +224,8 @@ class Discrete(Univariate): def integral(self): """Return integral of distribution + .. versionadded:: 0.13.1 + Returns ------- float @@ -1041,6 +1043,8 @@ class Tabular(Univariate): def integral(self): """Return integral of distribution + .. versionadded: 0.13.1 + Returns ------- float @@ -1230,6 +1234,8 @@ class Mixture(Univariate): def integral(self): """Return integral of the distribution + .. versionadded:: 0.13.1 + Returns ------- float @@ -1250,6 +1256,8 @@ def combine_distributions(dists, probs): distribution and the remainder of the distributions are put into a :class:`~openmc.stats.Mixture` distribution. + .. versionadded:: 0.13.1 + Parameters ---------- dists : iterable of openmc.stats.Univariate diff --git a/tests/unit_tests/test_data_decay.py b/tests/unit_tests/test_data_decay.py index 06b8e6bed..f0bda1bd9 100644 --- a/tests/unit_tests/test_data_decay.py +++ b/tests/unit_tests/test_data_decay.py @@ -23,6 +23,14 @@ def nb90(): return openmc.data.Decay.from_endf(filename) +@pytest.fixture(scope='module') +def ba137m(): + """Ba137_m1 decay data.""" + endf_data = os.environ['OPENMC_ENDF_DATA'] + filename = os.path.join(endf_data, 'decay', 'dec-056_Ba_137m1.endf') + return openmc.data.Decay.from_endf(filename) + + @pytest.fixture(scope='module') def u235_yields(): """U235 fission product yield data.""" @@ -48,6 +56,7 @@ def test_nb90_halflife(nb90): ufloat_close(nb90.decay_constant, log(2.)/nb90.half_life) ufloat_close(nb90.decay_energy, ufloat(2265527.5, 25159.400474401213)) + def test_nb90_nuclide(nb90): assert nb90.nuclide['atomic_number'] == 41 assert nb90.nuclide['mass_number'] == 90 @@ -91,3 +100,29 @@ def test_fpy(u235_yields): assert len(u235_yields.independent) == 3 thermal = u235_yields.independent[0] ufloat_close(thermal['I135'], ufloat(0.0292737, 0.000819663)) + + +def test_sources(ba137m, nb90): + # Running .sources twice should give same objects + sources = ba137m.sources + sources2 = ba137m.sources + for key in sources: + assert sources[key] is sources2[key] + + # Each source should be a univariate distribution + for dist in sources.values(): + assert isinstance(dist, openmc.stats.Univariate) + + # Check for presence of 662 keV gamma ray in decay of Ba137m + gamma_source = ba137m.sources['photon'] + assert isinstance(gamma_source, openmc.stats.Discrete) + b = np.isclose(gamma_source.x, 661657.) + assert np.count_nonzero(b) == 1 + + # Check value of decay/s/atom + idx = np.flatnonzero(b)[0] + assert gamma_source.p[idx] == pytest.approx(0.004069614) + + # Nb90 decays by β+ and should emit positrons, electrons, and photons + sources = nb90.sources + assert len(set(sources.keys()) ^ {'positron', 'electron', 'photon'}) == 0 From 3e5afd21eb67512c05111ad49e848b52f85dc981 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 22 Jul 2022 16:42:24 -0500 Subject: [PATCH 0661/2654] Add missing definition of _sources in Decay.__init__ --- openmc/data/decay.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 96c3f562a..2c2505bf5 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -337,6 +337,7 @@ class Decay(EqualityMixin): self.modes = [] self.spectra = {} self.average_energies = {} + self._sources = None # Get head record items = get_head_record(file_obj) From 717115938df14c8561da1052dd2e849bdc26b4bb Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 25 Jul 2022 16:25:29 +0100 Subject: [PATCH 0662/2654] updating fill id to match --- tests/regression_tests/dagmc/universes/inputs_true.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index 1a5ca7486..2165a78b6 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,6 +1,6 @@ - + 24.0 24.0 From 29a741a441269d511b824e106b0b29a63493333a Mon Sep 17 00:00:00 2001 From: myerspat Date: Mon, 25 Jul 2022 11:58:16 -0500 Subject: [PATCH 0663/2654] added infix evaluation and removed conversion of infix to postfix --- src/cell.cpp | 79 +++++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index f9786ce3e..2e26e2c17 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -515,7 +515,8 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } // Convert the infix region spec to RPN. - rpn_ = generate_rpn(id_, region_); + //rpn_ = generate_rpn(id_, region_); + rpn_ = region_; // Check if this is a simple cell. simple_ = true; @@ -768,50 +769,46 @@ bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const bool CSGCell::contains_complex( Position r, Direction u, int32_t on_surface) const { - // Make a stack of booleans. We don't know how big it needs to be, but we do - // know that rpn.size() is an upper-bound. - vector stack(rpn_.size()); - int i_stack = -1; + bool in_cell = true; + bool negate = false; + int paren_depth = 0; + int negate_depth = 0; for (int32_t token : rpn_) { - // If the token is a binary operator (intersection/union), apply it to - // the last two items on the stack. If the token is a unary operator - // (complement), apply it to the last item on the stack. - if (token == OP_UNION) { - stack[i_stack - 1] = stack[i_stack - 1] || stack[i_stack]; - i_stack--; - } else if (token == OP_INTERSECTION) { - stack[i_stack - 1] = stack[i_stack - 1] && stack[i_stack]; - i_stack--; - } else if (token == OP_COMPLEMENT) { - stack[i_stack] = !stack[i_stack]; - } else { - // If the token is not an operator, evaluate the sense of particle with - // respect to the surface and see if the token matches the sense. If the - // particle's surface attribute is set and matches the token, that - // overrides the determination based on sense(). - i_stack++; - if (token == on_surface) { - stack[i_stack] = true; - } else if (-token == on_surface) { - stack[i_stack] = false; - } else { - // Note the off-by-one indexing - bool sense = model::surfaces[abs(token) - 1]->sense(r, u); - stack[i_stack] = (sense == (token > 0)); - } - } - } + if (token < OP_UNION && in_cell == true) { + if (token == on_surface) { + in_cell = true; + } else if (-token == on_surface) { + in_cell = false; + } else { + // Note the off-by-one + bool sense = model::surfaces[abs(token) - 1]->sense(r, u); + in_cell = (sense == (token > 0)); + } + } else if (token == OP_UNION) { + if (in_cell == false) { + in_cell = true; + } else if (paren_depth == 0) { + break; + } + } else if (token == OP_RIGHT_PAREN) { + paren_depth--; + } else if (token == OP_LEFT_PAREN) { + paren_depth++; + } else if (token == OP_COMPLEMENT) { + negate = true; + negate_depth = paren_depth; + continue; + } else if (paren_depth == 0) { + break; + } - if (i_stack == 0) { - // The one remaining bool on the stack indicates whether the particle is - // in the cell. - return stack[i_stack]; - } else { - // This case occurs if there is no region specification since i_stack will - // still be -1. - return true; + if (negate == true && negate_depth == paren_depth) { + in_cell = !in_cell; + negate = false; + } } + return in_cell; } //============================================================================== From b93ab95ba14e7af55442cc9d9ec154e1d34b48ed Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 31 May 2022 08:33:43 -0500 Subject: [PATCH 0664/2654] Adding more mesh interrogation options for the libmesh Finishing methods for connectivity and coordinates. Writing vertices and connectivity to statepoint file Loading vertices and connectivity from statepoint. Correcting string repr Correcting connectivity length Adding method to write the mesh elements to VTK with data applied. Updating hdf5 output to include element types Adding support for hex elements when writing unstructured meshes to VTK Adding simple check for VTK writing if the module is present Removing centroids from the statepoint file and Python UM class Updating test check for vtk Adding warning for skipped elements. Correcting element type Adding warning for skipped elements. Using an enum to indicate element types for readability Updating to element types on the Python side as well Handling integer data applied to VTK files. Doc updates for Python API UM class Incrementing statepoint version number Refactor of unstructured mesh tests to extract model Updating inputs for floating point surface coefficients Adding test for hexes and refactoring comparison funcs Updating reference mesh files Adding reference file for the hexes test case Passing test for hex mesh Adding inputs for the hexes test case. Adding hex test meshes. Skipping hex mesh test if not built with libmesh Adding small VTK write tests for unstructured mesh. Allowing file path to be a pathlib path. Adding skips if libmesh or dagmc not enabled Adding a few comments to test file Changing where conversion to str happens for mesh filename. Setting output to false. Removing VTK check from unstructured mesh regression test Removnig VTK test files for regression test -- too large Adding __init__.py file for pytest --- include/openmc/constants.h | 2 +- include/openmc/mesh.h | 39 +++ openmc/mesh.py | 239 +++++++++----- openmc/statepoint.py | 2 +- src/mesh.cpp | 134 +++++++- .../unstructured_mesh/inputs_true.dat | 91 ++++++ .../unstructured_mesh/inputs_true0.dat | 12 +- .../unstructured_mesh/inputs_true1.dat | 12 +- .../unstructured_mesh/inputs_true10.dat | 12 +- .../unstructured_mesh/inputs_true11.dat | 12 +- .../unstructured_mesh/inputs_true12.dat | 12 +- .../unstructured_mesh/inputs_true13.dat | 12 +- .../unstructured_mesh/inputs_true14.dat | 12 +- .../unstructured_mesh/inputs_true15.dat | 12 +- .../unstructured_mesh/inputs_true2.dat | 12 +- .../unstructured_mesh/inputs_true3.dat | 12 +- .../unstructured_mesh/inputs_true8.dat | 12 +- .../unstructured_mesh/inputs_true9.dat | 12 +- .../unstructured_mesh/test.py | 213 ++++++++----- .../unstructured_mesh/test_mesh_hexes.e | 1 + .../unstructured_mesh/test_mesh_hexes.exo | Bin 0 -> 79668 bytes tests/unit_tests/mesh_to_vtk/__init__.py | 0 tests/unit_tests/mesh_to_vtk/hexes.exo | Bin 0 -> 4700 bytes .../mesh_to_vtk/libmesh_hexes_ref.vtk | 76 +++++ .../mesh_to_vtk/libmesh_tets_ref.vtk | 292 ++++++++++++++++++ .../unit_tests/mesh_to_vtk/moab_tets_ref.vtk | 1 + tests/unit_tests/mesh_to_vtk/test.py | 70 +++++ tests/unit_tests/mesh_to_vtk/tets.exo | Bin 0 -> 7708 bytes tests/unit_tests/mesh_to_vtk/umesh.vtk | 292 ++++++++++++++++++ 29 files changed, 1344 insertions(+), 252 deletions(-) create mode 100644 tests/regression_tests/unstructured_mesh/inputs_true.dat create mode 120000 tests/regression_tests/unstructured_mesh/test_mesh_hexes.e create mode 100644 tests/regression_tests/unstructured_mesh/test_mesh_hexes.exo create mode 100644 tests/unit_tests/mesh_to_vtk/__init__.py create mode 100644 tests/unit_tests/mesh_to_vtk/hexes.exo create mode 100644 tests/unit_tests/mesh_to_vtk/libmesh_hexes_ref.vtk create mode 100644 tests/unit_tests/mesh_to_vtk/libmesh_tets_ref.vtk create mode 120000 tests/unit_tests/mesh_to_vtk/moab_tets_ref.vtk create mode 100644 tests/unit_tests/mesh_to_vtk/test.py create mode 100644 tests/unit_tests/mesh_to_vtk/tets.exo create mode 100644 tests/unit_tests/mesh_to_vtk/umesh.vtk diff --git a/include/openmc/constants.h b/include/openmc/constants.h index 73f96ff95..a7362ea9e 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -24,7 +24,7 @@ using double_4dvec = vector>>>; constexpr int HDF5_VERSION[] {3, 0}; // Version numbers for binary files -constexpr array VERSION_STATEPOINT {17, 0}; +constexpr array VERSION_STATEPOINT {18, 0}; constexpr array VERSION_PARTICLE_RESTART {2, 0}; constexpr array VERSION_TRACK {3, 0}; constexpr array VERSION_SUMMARY {6, 0}; diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 21c58862d..1ff20dc11 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -36,6 +36,12 @@ namespace openmc { +//============================================================================== +// Constants +//============================================================================== + +enum class ElementType { UNSUPPORTED=-1, LINEAR_TET, LINEAR_HEX }; + //============================================================================== // Global variables //============================================================================== @@ -485,6 +491,23 @@ public: //! \return The centroid of the bin virtual Position centroid(int bin) const = 0; + //! Get the number of vertices in the mesh + // + //! \return Number of vertices + virtual int n_vertices() const = 0; + + //! Retrieve a vertex of the mesh + // + //! \param[in] vertex ID + //! \return vertex coordinates + virtual Position vertex(int id) const = 0; + + //! Retrieve connectivity of a mesh element + // + //! \param[in] element ID + //! \return element connectivity as IDs of the vertices + virtual std::vector connectivity(int id) const = 0; + //! Get the volume of a mesh bin // //! \param[in] bin Bin to return the volume for @@ -557,6 +580,12 @@ public: Position centroid(int bin) const override; + int n_vertices() const override; + + Position vertex(int id) const override; + + std::vector connectivity(int id) const override; + double volume(int bin) const override; private: @@ -621,6 +650,9 @@ private: //! \return MOAB EntityHandle of tet moab::EntityHandle get_ent_handle_from_bin(int bin) const; + //! Get a vertex index into the global range from a handle + int get_vert_idx_from_handle(moab::EntityHandle vert) const; + //! Get the bin for a given mesh cell index // //! \param[in] idx Index of the mesh cell. @@ -655,6 +687,7 @@ private: // Data members moab::Range ehs_; //!< Range of tetrahedra EntityHandle's in the mesh + moab::Range verts_; //!< Range of vertex EntityHandle's in the mesh moab::EntityHandle tetset_; //!< EntitySet containing all tetrahedra moab::EntityHandle kdtree_root_; //!< Root of the MOAB KDTree std::shared_ptr mbi_; //!< MOAB instance @@ -701,6 +734,12 @@ public: Position centroid(int bin) const override; + int n_vertices() const override; + + Position vertex(int id) const override; + + std::vector connectivity(int id) const override; + double volume(int bin) const override; private: diff --git a/openmc/mesh.py b/openmc/mesh.py index 4af701892..601d0ac94 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -2,6 +2,7 @@ from abc import ABC, abstractmethod from collections.abc import Iterable from math import pi from numbers import Real, Integral +from pathlib import Path import warnings from xml.etree import ElementTree as ET @@ -1440,7 +1441,7 @@ class UnstructuredMesh(MeshBase): Parameters ---------- - filename : str + filename : str or pathlib.Path Location of the unstructured mesh file library : {'moab', 'libmesh'} Mesh library used for the unstructured mesh tally @@ -1468,20 +1469,41 @@ class UnstructuredMesh(MeshBase): be generated for this mesh volumes : Iterable of float Volumes of the unstructured mesh elements + centroids : np.narray (3, n_elements) + Centroids of the mesh elements + + vertices : np.ndarray (3,) + Coordinates of the mesh vertices + + .. versionadded:: 0.13 + + connectivity : np.ndarray (8, n_elements) + Connectivity of the elements + + .. versionadded:: 0.13 + + element_types : Iterable of integers + Mesh element types + + .. versionadded:: 0.13 total_volume : float Volume of the unstructured mesh in total - centroids : Iterable of tuple - An iterable of element centroid coordinates, e.g. [(0.0, 0.0, 0.0), - (1.0, 1.0, 1.0), ...] """ + + _UNSUPPORTED_ELEM = -1 + _LINEAR_TET = 0 + _LINEAR_HEX = 1 + def __init__(self, filename, library, mesh_id=None, name='', length_multiplier=1.0): super().__init__(mesh_id, name) self.filename = filename self._volumes = None - self._centroids = None + self._n_elements = None + self._conectivity = None + self._vertices = None self.library = library - self._output = True + self._output = False self.length_multiplier = length_multiplier @property @@ -1490,7 +1512,7 @@ class UnstructuredMesh(MeshBase): @filename.setter def filename(self, filename): - cv.check_type('Unstructured Mesh filename', filename, str) + cv.check_type('Unstructured Mesh filename', filename, (str, Path)) self._filename = filename @property @@ -1546,12 +1568,33 @@ class UnstructuredMesh(MeshBase): def centroids(self): return self._centroids + @property + def vertices(self): + return self._vertices + + @property + def connectivity(self): + return self._connectivity + + @property + def element_types(self): + return self._element_types + + @property + def centroids(self): + return np.array([self.centroid(i) for i in range(self.n_elements)]) + @property def n_elements(self): - if self._centroids is None: + if self._n_elements is None: raise RuntimeError("No information about this mesh has " "been loaded from a statepoint file.") - return len(self._centroids) + return self._n_elements + + @n_elements.setter + def n_elements(self, val): + cv.check_type('Number of elements', val, Integral) + self._n_elements = val @centroids.setter @@ -1579,23 +1622,27 @@ class UnstructuredMesh(MeshBase): def n_dimension(self): return 3 - @property - def vertices(self): - raise NotImplementedError("Vertices for UnstructuredMesh objects are " - "not yet available") - def __repr__(self): string = super().__repr__() string += '{: <16}=\t{}\n'.format('\tFilename', self.filename) - string += '{: <16}=\t{}\n'.format('\tMesh Library', self.mesh_lib) + string += '{: <16}=\t{}\n'.format('\tMesh Library', self.library) if self.length_multiplier != 1.0: string += '{: <16}=\t{}\n'.format('\tLength multiplier', self.length_multiplier) return string - def write_data_to_vtk(self, filename, datasets, volume_normalization=True): - """Map data to the unstructured mesh element centroids - to create a VTK point-cloud dataset. + def centroid(self, bin): + """Return the vertex averaged centroid of an element + """ + conn = self.connectivity[bin] + coords = self.vertices[conn] + return coords.mean(axis=0) + + def write_vtk_mesh(self, **kwargs): + """Map data to unstructured VTK mesh elements. + + .. deprecated:: 0.13 + Use :func:`UnstructuredMesh.write_data_to_vtk` instead. Parameters ---------- @@ -1607,83 +1654,105 @@ class UnstructuredMesh(MeshBase): volume_normalization : bool Whether or not to normalize the data by the volume of the mesh elements - - Raises - ------ - RuntimeError - when the size of a dataset doesn't match the number of cells """ + warnings.warn( + "The 'UnstructuredMesh.write_vtk_mesh' method has been renamed " + "to 'write_data_to_vtk' and will be removed in a future version " + " of OpenMC.", FutureWarning + ) + self.write_data_to_vtk(**kwargs) + def write_data_to_vtk(self, filename=None, datasets=None, volume_normalization=True): + """Map data to unstructured VTK mesh elements. + + Parameters + ---------- + filename : str or pathlib.Path + Name of the VTK file to write + datasets : dict + Dictionary whose keys are the data labels + and values are numpy appropriately sized arrays + of the data + volume_normalization : bool + Whether or not to normalize the data by the + volume of the mesh elements + """ import vtk - from vtk.util import numpy_support as vtk_npsup + from vtk.util import numpy_support as nps - if self.centroids is None: - raise RuntimeError("No centroid information is present on this " - "unstructured mesh. Please load this " - "information from a relevant statepoint file.") + if self.connectivity is None or self.vertices is None: + raise RuntimeError('This mesh has not been ' + 'loaded from a statepoint file.') - if self.volumes is None and volume_normalization: - raise RuntimeError("No volume data is present on this " - "unstructured mesh. Please load the " - " mesh information from a statepoint file.") + if filename is None: + filename = f'mesh_{self.id}.vtk' - # check that the data sets are appropriately sized - errmsg = "The size of the dataset {} should be equal to the number of cells" - for label, dataset in datasets.items(): - if isinstance(dataset, np.ndarray): - if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) + writer = vtk.vtkUnstructuredGridWriter() + + writer.SetFileName(str(filename)) + + grid = vtk.vtkUnstructuredGrid() + + vtk_pnts = vtk.vtkPoints() + vtk_pnts.SetData(nps.numpy_to_vtk(self.vertices)) + grid.SetPoints(vtk_pnts) + + n_skipped = 0 + elems = [] + for elem_type, conn in zip(self.element_types, self.connectivity): + if elem_type == self._LINEAR_TET: + elem = vtk.vtkTetra() + elif elem_type == self._LINEAR_HEX: + elem = vtk.vtkHexahedron() + elif elem_type == self._UNSUPPORTED_ELEM: + n_skipped += 1 else: - if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) - cv.check_type('label', label, str) + raise RuntimeError(f'Invalid element type {elem_type} found') + for i, c in enumerate(conn): + if c == -1: + break + elem.GetPointIds().SetId(i, c) + elems.append(elem) - # create data arrays for the cells/points - cell_dim = 1 - vertices = vtk.vtkCellArray() - points = vtk.vtkPoints() + if n_skipped > 0: + warnings.warn(f'{n_skipped} elements were not written because ' + 'they are not of type linear tet/hex') - for centroid in self.centroids: - # create a point for each centroid - point_id = points.InsertNextPoint(centroid * self.length_multiplier) - # create a cell of type "Vertex" for each point - cell_id = vertices.InsertNextCell(cell_dim, (point_id,)) + for elem in elems: + grid.InsertNextCell(elem.GetCellType(), elem.GetPointIds()) - # create a VTK data object - poly_data = vtk.vtkPolyData() - poly_data.SetPoints(points) - poly_data.SetVerts(vertices) - - # strange VTK nuance: - # data must be held in some container - # until the vtk file is written - data_holder = [] - - # create VTK arrays for each of - # the data sets - for label, dataset in datasets.items(): - dataset = np.asarray(dataset).flatten() + # check that datasets are the correct size + if datasets is not None: + for name, data in datasets.items(): + if data.shape != (self.dimension,): + raise ValueError(f'Cannot apply dataset {name} with ' + f'shape {data.shape} to mesh {self.id} ' + f'with dimensions {self.dimension}') if volume_normalization: - dataset /= self.volumes.flatten() + for name, data in datasets.items(): + if np.issubdtype(data.dtype, np.integer): + warnings.warn(f'Integer data set {name} will ' + 'not be volume-normalized.') + continue + data /= self.volumes - array = vtk.vtkDoubleArray() - array.SetName(label) - array.SetNumberOfComponents(1) - array.SetArray(vtk_npsup.numpy_to_vtk(dataset), - dataset.size, - True) + # add data to the mesh + for name, data in datasets.items(): + arr = vtk.vtkDoubleArray() + arr.SetName(name) + arr.SetNumberOfTuples(data.size) - data_holder.append(dataset) - poly_data.GetPointData().AddArray(array) + for i in range(data.size): + arr.SetTuple1(i, data.flat[i]) + grid.GetCellData().AddArray(arr) - # set filename - if not filename.endswith(".vtk"): - filename += ".vtk" + if vtk.VTK_MAJOR_VERSION == 5: + grid.update() + writer.SetInput(grid) + else: + writer.SetInputData(grid) - writer = vtk.vtkGenericDataObjectWriter() - writer.SetFileName(filename) - writer.SetInputData(poly_data) writer.Write() @classmethod @@ -1694,10 +1763,14 @@ class UnstructuredMesh(MeshBase): mesh = cls(filename, library, mesh_id=mesh_id) vol_data = group['volumes'][()] - centroids = group['centroids'][()] mesh.volumes = np.reshape(vol_data, (vol_data.shape[0],)) - mesh.centroids = np.reshape(centroids, (vol_data.shape[0], 3)) - mesh.size = mesh.volumes.size + mesh.n_elements = mesh.volumes.size + + vertices = group['vertices'][()] + mesh._vertices = vertices.reshape((-1, 3)) + connectvity = group['connectivity'][()] + mesh._connectivity = connectvity.reshape((-1, 8)) + mesh._element_types = group['element_types'][()] if 'length_multiplier' in group: mesh.length_multiplier = group['length_multiplier'][()] @@ -1719,7 +1792,7 @@ class UnstructuredMesh(MeshBase): element.set("type", "unstructured") element.set("library", self._library) subelement = ET.SubElement(element, "filename") - subelement.text = self.filename + subelement.text = str(self.filename) if self._length_multiplier != 1.0: element.set("length_multiplier", str(self.length_multiplier)) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 630675816..138c0c718 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -11,7 +11,7 @@ from uncertainties import ufloat import openmc import openmc.checkvalue as cv -_VERSION_STATEPOINT = 17 +_VERSION_STATEPOINT = 18 class StatePoint: diff --git a/src/mesh.cpp b/src/mesh.cpp index e8f79aa37..e701f954e 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -220,21 +220,56 @@ void UnstructuredMesh::to_hdf5(hid_t group) const write_dataset(mesh_group, "type", mesh_type); write_dataset(mesh_group, "filename", filename_); write_dataset(mesh_group, "library", this->library()); - // write volume of each element - vector tet_vols; - xt::xtensor centroids({static_cast(this->n_bins()), 3}); - for (int i = 0; i < this->n_bins(); i++) { - tet_vols.emplace_back(this->volume(i)); - auto c = this->centroid(i); - xt::view(centroids, i, xt::all()) = xt::xarray({c.x, c.y, c.z}); - } - - write_dataset(mesh_group, "volumes", tet_vols); - write_dataset(mesh_group, "centroids", centroids); if (specified_length_multiplier_) write_dataset(mesh_group, "length_multiplier", length_multiplier_); + // write vertex coordinates + xt::xtensor vertices({static_cast(this->n_vertices()), 3}); + for (int i = 0; i < this->n_vertices(); i++) { + auto v = this->vertex(i); + xt::view(vertices, i, xt::all()) = xt::xarray({v.x, v.y, v.z}); + } + write_dataset(mesh_group, "vertices", vertices); + + int num_elem_skipped = 0; + + // write element types and connectivity + vector volumes; + xt::xtensor connectivity ({static_cast(this->n_bins()), 8}); + xt::xtensor elem_types ({static_cast(this->n_bins()), 1}); + for (int i = 0; i < this->n_bins(); i++) { + auto conn = this->connectivity(i); + + volumes.emplace_back(this->volume(i)); + + // write linear tet element + if (conn.size() == 4) { + xt::view(elem_types, i, xt::all()) = static_cast(ElementType::LINEAR_TET); + xt::view(connectivity, i, xt::all()) = xt::xarray({conn[0], conn[1], conn[2], conn[3], + -1, -1, -1, -1}); + // write linear hex element + } else if (conn.size() == 8) { + xt::view(elem_types, i, xt::all()) = static_cast(ElementType::LINEAR_HEX); + xt::view(connectivity, i, xt::all()) = xt::xarray({conn[0], conn[1], conn[2], conn[3], + conn[4], conn[5], conn[6], conn[7]}); + } else { + num_elem_skipped++; + xt::view(elem_types, i, xt::all()) = static_cast(ElementType::UNSUPPORTED); + xt::view(connectivity, i, xt::all()) = xt::xarray({-1, -1, -1, -1, -1, -1, -1, -1}); + } + } + + // warn users that some elements were skipped + if (num_elem_skipped > 0) { + warning(fmt::format("The connectivity of {} elements on mesh {} were not written " + "because they are not of type linear tet/hex.", num_elem_skipped, this->id_)); + } + + write_dataset(mesh_group, "volumes", volumes); + write_dataset(mesh_group, "connectivity", connectivity); + write_dataset(mesh_group, "element_types", elem_types); + close_group(mesh_group); } @@ -1775,6 +1810,14 @@ void MOABMesh::initialize() filename_); } + // set member range of vertices + int vertex_dim = 0; + rval = mbi_->get_entities_by_dimension(0, vertex_dim, verts_); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to get all vertex handles"); + } + + // make an entity set for all tetrahedra // this is used for convenience later in output rval = mbi_->create_meshset(moab::MESHSET_SET, tetset_); @@ -2124,6 +2167,14 @@ std::pair, vector> MOABMesh::plot( return {}; } +int MOABMesh::get_vert_idx_from_handle(moab::EntityHandle vert) const { + int idx = vert - verts_[0]; + if (idx >= n_vertices()) { + fatal_error(fmt::format("Invalid vertex idx {} (# vertices {})", idx, n_vertices())); + } + return idx; +} + int MOABMesh::get_bin_from_ent_handle(moab::EntityHandle eh) const { int bin = eh - ehs_[0]; @@ -2191,6 +2242,46 @@ Position MOABMesh::centroid(int bin) const return {centroid[0], centroid[1], centroid[2]}; } +int MOABMesh::n_vertices() const { + return verts_.size(); +} + +Position MOABMesh::vertex(int id) const { + + moab::ErrorCode rval; + + moab::EntityHandle vert = verts_[id]; + + moab::CartVect coords; + rval = mbi_->get_coords(&vert, 1, coords.array()); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to get the coordinates of a vertex."); + } + + return {coords[0], coords[1], coords[2]}; +} + +std::vector MOABMesh::connectivity(int bin) const { + moab::ErrorCode rval; + + auto tet = get_ent_handle_from_bin(bin); + + // look up the tet connectivity + vector conn; + rval = mbi_->get_connectivity(&tet, 1, conn); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to get connectivity of a mesh element."); + return {}; + } + + std::vector verts(4); + for (int i = 0; i < verts.size(); i++) { + verts[i] = get_vert_idx_from_handle(conn[i]); + } + + return verts; +} + std::pair MOABMesh::get_score_tags( std::string score) const { @@ -2394,6 +2485,27 @@ Position LibMesh::centroid(int bin) const return {centroid(0), centroid(1), centroid(2)}; } +int LibMesh::n_vertices() const +{ + return m_->n_nodes(); +} + +Position LibMesh::vertex(int vertex_id) const +{ + const auto node_ref = m_->node_ref(vertex_id); + return {node_ref(0), node_ref(1), node_ref(2)}; +} + +std::vector LibMesh::connectivity(int elem_id) const +{ + std::vector conn; + const auto* elem_ptr = m_->elem_ptr(elem_id); + for (int i = 0; i < elem_ptr->n_nodes(); i++) { + conn.push_back(elem_ptr->node_id(i)); + } + return conn; +} + std::string LibMesh::library() const { return mesh_lib_type; diff --git a/tests/regression_tests/unstructured_mesh/inputs_true.dat b/tests/regression_tests/unstructured_mesh/inputs_true.dat new file mode 100644 index 000000000..e556782ad --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/inputs_true.dat @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_hexes.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/inputs_true0.dat index 1ed60d507..2e2594cde 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true0.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/inputs_true1.dat index 67dde56a9..84a3b186b 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true1.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true10.dat b/tests/regression_tests/unstructured_mesh/inputs_true10.dat index 9ca47a356..e9272a333 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true10.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true10.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true11.dat b/tests/regression_tests/unstructured_mesh/inputs_true11.dat index 683e1fade..0b89d280c 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true11.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true11.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true12.dat b/tests/regression_tests/unstructured_mesh/inputs_true12.dat index 8ce9f3cf2..b3673a254 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true12.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true12.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true13.dat b/tests/regression_tests/unstructured_mesh/inputs_true13.dat index bca0bee4c..c466396b6 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true13.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true13.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true14.dat b/tests/regression_tests/unstructured_mesh/inputs_true14.dat index 226331ba8..8c6a5120a 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true14.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true14.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true15.dat b/tests/regression_tests/unstructured_mesh/inputs_true15.dat index a6a084165..1b9abbd83 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true15.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true15.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true2.dat b/tests/regression_tests/unstructured_mesh/inputs_true2.dat index 4b442c757..7136d485a 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true2.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true2.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true3.dat b/tests/regression_tests/unstructured_mesh/inputs_true3.dat index 52e53498e..23900a060 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true3.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true3.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true8.dat b/tests/regression_tests/unstructured_mesh/inputs_true8.dat index e484c95a2..a0cbbcae7 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true8.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true8.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true9.dat b/tests/regression_tests/unstructured_mesh/inputs_true9.dat index 5e83d71bd..930bd8579 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true9.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true9.dat @@ -15,12 +15,12 @@ - - - - - - + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/test.py b/tests/regression_tests/unstructured_mesh/test.py index daebe7948..090a47599 100644 --- a/tests/regression_tests/unstructured_mesh/test.py +++ b/tests/regression_tests/unstructured_mesh/test.py @@ -1,6 +1,8 @@ +import filecmp import glob from itertools import product import os +import warnings import openmc import openmc.lib @@ -9,15 +11,29 @@ import numpy as np import pytest from tests.testing_harness import PyAPITestHarness -TETS_PER_VOXEL = 12 - class UnstructuredMeshTest(PyAPITestHarness): - def __init__(self, statepoint_name, model, inputs_true, holes): + ELEM_PER_VOXEL = 12 + + def __init__(self, + statepoint_name, + model, + inputs_true='inputs_true.dat', + holes=False, + scale_factor=10.0): super().__init__(statepoint_name, model, inputs_true) self.holes = holes # holes in the test mesh + self.scale_bounding_cell(scale_factor) + + def scale_bounding_cell(self, scale_factor): + geometry = self._model.geometry + for surface in geometry.get_all_surfaces().values(): + if surface.boundary_type != 'vacuum': + continue + for coeff in surface._coefficients: + surface._coefficients[coeff] *= scale_factor def _compare_results(self): with openmc.StatePoint(self._sp_name) as sp: @@ -28,32 +44,27 @@ class UnstructuredMeshTest(PyAPITestHarness): flt = tally.find_filter(openmc.MeshFilter) if isinstance(flt.mesh, openmc.RegularMesh): - reg_mesh_data, reg_mesh_std_dev = self.get_mesh_tally_data(tally) + reg_mesh_data = self.get_mesh_tally_data(tally) if self.holes: reg_mesh_data = np.delete(reg_mesh_data, self.holes) - reg_mesh_std_dev = np.delete(reg_mesh_std_dev, self.holes) else: umesh_tally = tally - unstructured_data, unstructured_std_dev = self.get_mesh_tally_data(tally, True) + unstructured_data = self.get_mesh_tally_data(tally, True) - # we expect these results to be the same to within at least ten - # decimal places - decimals = 10 if umesh_tally.estimator == 'collision' else 8 - np.testing.assert_array_almost_equal(unstructured_data, - reg_mesh_data, - decimals) + # we expect these results to be the same to within at least ten + # decimal places + decimals = 10 if umesh_tally.estimator == 'collision' else 8 + np.testing.assert_array_almost_equal(np.sort(unstructured_data), + np.sort(reg_mesh_data), + decimals) - @staticmethod - def get_mesh_tally_data(tally, structured=False): + def get_mesh_tally_data(self, tally, structured=False): data = tally.get_reshaped_data(value='mean') - std_dev = tally.get_reshaped_data(value='std_dev') if structured: - data.shape = (data.size // TETS_PER_VOXEL, TETS_PER_VOXEL) - std_dev.shape = (std_dev.size // TETS_PER_VOXEL, TETS_PER_VOXEL) + data = data.reshape((-1, self.ELEM_PER_VOXEL)) else: data.shape = (data.size, 1) - std_dev.shape = (std_dev.size, 1) - return np.sum(data, axis=1), np.sum(std_dev, axis=1) + return np.sum(data, axis=1) def _cleanup(self): super()._cleanup() @@ -64,35 +75,11 @@ class UnstructuredMeshTest(PyAPITestHarness): os.remove(f) -param_values = (['libmesh', 'moab'], # mesh libraries - ['collision', 'tracklength'], # estimators - [True, False], # geometry outside of the mesh - [(333, 90, 77), None]) # location of holes in the mesh -test_cases = [] -for i, (lib, estimator, ext_geom, holes) in enumerate(product(*param_values)): - test_cases.append({'library' : lib, - 'estimator' : estimator, - 'external_geom' : ext_geom, - 'holes' : holes, - 'inputs_true' : 'inputs_true{}.dat'.format(i)}) - - -@pytest.mark.parametrize("test_opts", test_cases) -def test_unstructured_mesh(test_opts): - +@pytest.fixture +def model(): openmc.reset_auto_ids() - # skip the test if the library is not enabled - if test_opts['library'] == 'moab' and not openmc.lib._dagmc_enabled(): - pytest.skip("DAGMC (and MOAB) mesh not enbaled in this build.") - - if test_opts['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): - pytest.skip("LibMesh is not enabled in this build.") - - # skip the tracklength test for libmesh - if test_opts['library'] == 'libmesh' and \ - test_opts['estimator'] == 'tracklength': - pytest.skip("Tracklength tallies are not supported using libmesh.") + model = openmc.Model() ### Materials ### materials = openmc.Materials() @@ -113,7 +100,7 @@ def test_unstructured_mesh(test_opts): water_mat.set_density("atom/b-cm", 0.07416) materials.append(water_mat) - materials.export_to_xml() + model.materials = materials ### Geometry ### fuel_min_x = openmc.XPlane(-5.0, name="minimum x") @@ -149,29 +136,26 @@ def test_unstructured_mesh(test_opts): +clad_min_z & -clad_max_z) clad_cell.fill = zirc_mat - if test_opts['external_geom']: - bounds = (15, 15, 15) - else: - bounds = (10, 10, 10) - - water_min_x = openmc.XPlane(x0=-bounds[0], + # set bounding cell dimension to one + # this will be updated later according to the test case parameters + water_min_x = openmc.XPlane(x0=-1.0, name="minimum x", boundary_type='vacuum') - water_max_x = openmc.XPlane(x0=bounds[0], + water_max_x = openmc.XPlane(x0=1.0, name="maximum x", boundary_type='vacuum') - water_min_y = openmc.YPlane(y0=-bounds[1], + water_min_y = openmc.YPlane(y0=-1.0, name="minimum y", boundary_type='vacuum') - water_max_y = openmc.YPlane(y0=bounds[1], + water_max_y = openmc.YPlane(y0=1.0, name="maximum y", boundary_type='vacuum') - water_min_z = openmc.ZPlane(z0=-bounds[2], + water_min_z = openmc.ZPlane(z0=-1.0, name="minimum z", boundary_type='vacuum') - water_max_z = openmc.ZPlane(z0=bounds[2], + water_max_z = openmc.ZPlane(z0=1.0, name="maximum z", boundary_type='vacuum') @@ -185,9 +169,9 @@ def test_unstructured_mesh(test_opts): water_cell.fill = water_mat # create a containing universe - geometry = openmc.Geometry([fuel_cell, clad_cell, water_cell]) + model.geometry = openmc.Geometry([fuel_cell, clad_cell, water_cell]) - ### Tallies ### + ### Reference Tally ### # create meshes and mesh filters regular_mesh = openmc.RegularMesh() @@ -196,29 +180,11 @@ def test_unstructured_mesh(test_opts): regular_mesh.upper_right = (10.0, 10.0, 10.0) regular_mesh_filter = openmc.MeshFilter(mesh=regular_mesh) - - if test_opts['holes']: - mesh_filename = "test_mesh_tets_w_holes.e" - else: - mesh_filename = "test_mesh_tets.e" - - uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_opts['library']) - uscd_filter = openmc.MeshFilter(mesh=uscd_mesh) - - # create tallies - tallies = openmc.Tallies() - regular_mesh_tally = openmc.Tally(name="regular mesh tally") regular_mesh_tally.filters = [regular_mesh_filter] regular_mesh_tally.scores = ['flux'] - regular_mesh_tally.estimator = test_opts['estimator'] - tallies.append(regular_mesh_tally) - uscd_tally = openmc.Tally(name="unstructured mesh tally") - uscd_tally.filters = [uscd_filter] - uscd_tally.scores = ['flux'] - uscd_tally.estimator = test_opts['estimator'] - tallies.append(uscd_tally) + model.tallies = openmc.Tallies([regular_mesh_tally]) ### Settings ### settings = openmc.Settings() @@ -236,13 +202,92 @@ def test_unstructured_mesh(test_opts): source = openmc.Source(space=space, energy=energy) settings.source = source - model = openmc.model.Model(geometry=geometry, - materials=materials, - tallies=tallies, - settings=settings) + model.settings = settings + + return model + + +param_values = (['libmesh', 'moab'], # mesh libraries + ['collision', 'tracklength'], # estimators + [True, False], # geometry outside of the mesh + [(333, 90, 77), None]) # location of holes in the mesh +test_cases = [] +for i, (lib, estimator, ext_geom, holes) in enumerate(product(*param_values)): + test_cases.append({'library' : lib, + 'estimator' : estimator, + 'external_geom' : ext_geom, + 'holes' : holes, + 'inputs_true' : 'inputs_true{}.dat'.format(i)}) + + +@pytest.mark.parametrize("test_opts", test_cases) +def test_unstructured_mesh_tets(model, test_opts): + # skip the test if the library is not enabled + if test_opts['library'] == 'moab' and not openmc.lib._dagmc_enabled(): + pytest.skip("DAGMC (and MOAB) mesh not enbaled in this build.") + + if test_opts['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): + pytest.skip("LibMesh is not enabled in this build.") + + # skip the tracklength test for libmesh + if test_opts['library'] == 'libmesh' and \ + test_opts['estimator'] == 'tracklength': + pytest.skip("Tracklength tallies are not supported using libmesh.") + + if test_opts['holes']: + mesh_filename = "test_mesh_tets_w_holes.e" + else: + mesh_filename = "test_mesh_tets.e" + + # add reference mesh tally + regular_mesh_tally = model.tallies[0] + regular_mesh_tally.estimator = test_opts['estimator'] + + # add analagous unstructured mesh tally + uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_opts['library']) + uscd_filter = openmc.MeshFilter(mesh=uscd_mesh) + + # create tallies + uscd_tally = openmc.Tally(name="unstructured mesh tally") + uscd_tally.filters = [uscd_filter] + uscd_tally.scores = ['flux'] + uscd_tally.estimator = test_opts['estimator'] + model.tallies.append(uscd_tally) + + # modify model geometry according to test opts + if test_opts['external_geom']: + scale_factor = 15.0 + else: + scale_factor = 10.0 harness = UnstructuredMeshTest('statepoint.10.h5', model, test_opts['inputs_true'], - test_opts['holes']) + test_opts['holes'], + scale_factor) harness.main() + + +@pytest.mark.skipif(not openmc.lib._libmesh_enabled(), + reason='LibMesh is not enabled in this build.') +def test_unstructured_mesh_hexes(model): + regular_mesh_tally = model.tallies[0] + regular_mesh_tally.estimator = 'collision' + + # add analagous unstructured mesh tally + uscd_mesh = openmc.UnstructuredMesh('test_mesh_hexes.e', 'libmesh') + uscd_filter = openmc.MeshFilter(mesh=uscd_mesh) + + # create tallies + uscd_tally = openmc.Tally(name="unstructured mesh tally") + uscd_tally.filters = [uscd_filter] + uscd_tally.scores = ['flux'] + uscd_tally.estimator = 'collision' + model.tallies.append(uscd_tally) + + harness = UnstructuredMeshTest('statepoint.10.h5', + model) + harness.ELEM_PER_VOXEL = 1 + + harness.main() + diff --git a/tests/regression_tests/unstructured_mesh/test_mesh_hexes.e b/tests/regression_tests/unstructured_mesh/test_mesh_hexes.e new file mode 120000 index 000000000..421bf6a89 --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/test_mesh_hexes.e @@ -0,0 +1 @@ +test_mesh_hexes.exo \ No newline at end of file diff --git a/tests/regression_tests/unstructured_mesh/test_mesh_hexes.exo b/tests/regression_tests/unstructured_mesh/test_mesh_hexes.exo new file mode 100644 index 0000000000000000000000000000000000000000..03682c27564b6857b4397ecded768766e948377b GIT binary patch literal 79668 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 A;s5{u literal 0 HcmV?d00001 diff --git a/tests/unit_tests/mesh_to_vtk/umesh.vtk b/tests/unit_tests/mesh_to_vtk/umesh.vtk new file mode 100644 index 000000000..90f226121 --- /dev/null +++ b/tests/unit_tests/mesh_to_vtk/umesh.vtk @@ -0,0 +1,292 @@ +# vtk DataFile Version 5.1 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 58 double +-0.02593964576 -1 -1.1195739536 -0.40239958217 -0.40962166746 -1.9256035383 -1 0.02593964576 -1.1195739536 +-0.2248833639 0.23189144433 -1.2841109811 0.02593964576 1 -1.1195739536 1 -0.02593964576 -1.1195739536 +-0.042928712675 0.066425810853 -0.54270728017 -1 1 -1.5 -1 1 -0.5 +-0.49265312381 0.49332495053 -1.9656359509 -0.02608137991 -1 1.121521147 0.30281888252 -0.30293622513 1.8067963894 +1 -0.02608137991 1.121521147 -0.23236342389 0.26314805583 1.2867556783 0.074337770194 0.074337770194 2.5 +-0.40005770996 -0.36909660956 1.8768871762 -0.4896743493 0.49451064621 1.952829049 -1 1 1.5 +0.02608137991 1 1.121521147 -1 1 0.5 -0.038567136385 0.14628887118 0.55111724874 +-1 0.02608137991 1.121521147 0 -1 -2.5 0.37543954218 -0.36967061971 -1.8691105401 +1 -1 -2.5 0.074337770194 -0.074337770194 -2.5 1 0 -2.5 +0.4135797166 0.38351746262 -1.9274856063 1 -1 -1.5 -1 0 -2.5 +-1 -1 -1.5 -1 -1 -2.5 -1 0 2.5 +-1 1 2.5 0 1 2.5 0.46519182209 0.49356920409 1.95286052 +0 -1 2.5 -1 -1 1.5 -1 -1 2.5 +1 -1 2.5 1 -1 1.5 1 0 2.5 +1 1 2.5 1 1 1.5 0 1 -2.5 +-1 1 -2.5 1 -1 -0.5 1 1 -0.5 +0.038669824604 1 0.0046021677516 -1 -1 0.5 -0.038669824604 -1 0.0046021677516 +1 1 0.5 -1 0.038669824604 0.0046021677516 1 -0.038669824604 0.0046021677516 +1 1 -2.5 1 1 -1.5 1 -1 0.5 +-1 -1 -0.5 +CELLS 155 616 +OFFSETS vtktypeint64 +0 4 8 12 16 20 24 28 32 +36 40 44 48 52 56 60 64 68 +72 76 80 84 88 92 96 100 104 +108 112 116 120 124 128 132 136 140 +144 148 152 156 160 164 168 172 176 +180 184 188 192 196 200 204 208 212 +216 220 224 228 232 236 240 244 248 +252 256 260 264 268 272 276 280 284 +288 292 296 300 304 308 312 316 320 +324 328 332 336 340 344 348 352 356 +360 364 368 372 376 380 384 388 392 +396 400 404 408 412 416 420 424 428 +432 436 440 444 448 452 456 460 464 +468 472 476 480 484 488 492 496 500 +504 508 512 516 520 524 528 532 536 +540 544 548 552 556 560 564 568 572 +576 580 584 588 592 596 600 604 608 +612 616 +CONNECTIVITY vtktypeint64 +0 1 2 3 4 3 5 6 7 +4 8 3 7 3 2 9 8 3 +4 6 10 11 12 13 14 13 15 +16 17 13 18 16 19 18 13 20 +10 13 21 15 22 1 0 23 22 +24 25 23 25 1 3 9 26 23 +5 27 24 28 26 23 0 1 3 +23 29 30 31 1 22 31 30 1 +2 3 1 9 29 2 1 9 22 +0 28 23 32 15 21 16 14 13 +11 15 33 17 34 16 33 34 32 +16 34 16 18 35 10 11 13 15 +18 13 12 35 36 11 10 15 36 +37 38 15 32 38 37 15 32 21 +17 16 36 10 37 15 36 39 40 +11 41 40 39 11 41 12 11 35 +17 21 13 16 10 13 12 20 12 +13 11 35 14 13 16 35 34 17 +18 16 42 34 43 35 41 12 40 +11 14 41 11 35 42 41 14 35 +0 3 5 23 0 5 3 6 44 +4 9 27 29 2 30 1 44 45 +29 9 29 45 7 9 0 46 5 +6 47 48 4 6 0 3 2 6 +4 5 3 27 49 10 50 20 8 +2 3 6 51 18 48 20 49 50 +52 20 19 13 21 20 51 53 12 +20 19 48 18 20 25 3 1 23 +7 4 3 9 25 3 23 27 44 +4 7 9 25 23 26 27 54 55 +44 27 54 26 55 27 18 12 13 +20 14 16 34 35 19 21 52 20 +30 2 0 1 22 25 29 1 5 +23 3 27 25 26 44 27 22 29 +31 1 54 44 26 27 25 44 9 +27 22 28 24 23 26 5 55 27 +25 24 26 23 22 25 1 23 25 +44 29 9 25 29 1 9 48 6 +53 20 8 4 48 6 10 40 56 +12 10 40 12 11 17 19 18 13 +30 57 0 2 25 9 3 27 7 +8 2 3 26 28 5 23 29 7 +2 9 28 0 5 23 37 10 49 +21 49 50 57 52 56 12 53 20 +10 12 56 20 43 18 12 35 32 +37 21 15 14 11 13 35 19 52 +8 48 19 52 48 20 41 39 36 +11 50 6 52 20 46 53 5 6 +4 3 9 27 44 7 45 9 55 +47 4 5 28 0 46 5 8 52 +2 6 57 2 52 6 50 56 53 +20 10 56 50 20 57 50 0 6 +37 10 21 15 33 32 17 16 34 +18 43 35 57 52 50 6 51 48 +47 53 18 16 13 35 50 56 46 +53 14 36 32 15 14 11 36 15 +17 21 19 13 10 21 13 20 51 +12 18 20 50 53 46 6 14 15 +32 16 42 43 41 35 14 41 36 +11 49 52 21 20 36 40 10 11 +47 53 48 6 49 21 10 20 21 +15 13 16 51 48 53 20 55 5 +4 27 44 55 4 27 47 4 5 +6 8 48 52 6 47 5 53 6 +50 53 6 20 57 0 2 6 50 +46 0 6 52 6 48 20 42 14 +34 35 43 18 51 12 41 43 12 +35 22 30 0 1 14 32 34 16 +36 38 32 15 +CELL_TYPES 154 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 + +CELL_DATA 154 +FIELD FieldData 1 +ids 1 154 double +0 1 2 3 4 5 6 7 8 +9 10 11 12 13 14 15 16 17 +18 19 20 21 22 23 24 25 26 +27 28 29 30 31 32 33 34 35 +36 37 38 39 40 41 42 43 44 +45 46 47 48 49 50 51 52 53 +54 55 56 57 58 59 60 61 62 +63 64 65 66 67 68 69 70 71 +72 73 74 75 76 77 78 79 80 +81 82 83 84 85 86 87 88 89 +90 91 92 93 94 95 96 97 98 +99 100 101 102 103 104 105 106 107 +108 109 110 111 112 113 114 115 116 +117 118 119 120 121 122 123 124 125 +126 127 128 129 130 131 132 133 134 +135 136 137 138 139 140 141 142 143 +144 145 146 147 148 149 150 151 152 +153 From 46e98156ac105926d3c2f0b158fc12da51f3e807 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 18 Jul 2022 16:49:44 -0500 Subject: [PATCH 0665/2654] Adding notice about MOAB meshes --- src/state_point.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 9ea045915..a2d8b8881 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -812,12 +812,18 @@ void write_unstructured_mesh_results() auto umesh = dynamic_cast(model::meshes[mesh_idx].get()); + if (!umesh) continue; if (!umesh->output_) continue; + if (umesh->library() == "moab" && !mpi::master) { + warning(fmt::format("Output for a MOAB mesh (mesh {}) was requested but will not be written. Please use the Python API to generated the desired VTK tetrahedral mesh.", umesh->id_)); + continue; + } + // if this tally has more than one filter, print // warning and skip writing the mesh if (tally->filters().size() > 1) { @@ -889,12 +895,10 @@ void write_unstructured_mesh_results() std::string filename = fmt::format("tally_{0}.{1:0{2}}", tally->id_, simulation::current_batch, batch_width); - if (umesh->library() == "moab" && !mpi::master) - continue; - // Write the unstructured mesh and data to file umesh->write(filename); + // remove score data added for this mesh write umesh->remove_scores(); } } From 2f8d2fe003a7713672e8b61be16da453ddab882a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 20 Jul 2022 09:33:14 -0500 Subject: [PATCH 0666/2654] Empty commit attempting to fix CI. From 782c2411906041c8db1c01bb65b3ad1c6692d1af Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 21 Jul 2022 05:38:58 -0500 Subject: [PATCH 0667/2654] Always continue, but only write warning on mpi master rank --- src/state_point.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index a2d8b8881..b4200ffe2 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -819,7 +819,8 @@ void write_unstructured_mesh_results() if (!umesh->output_) continue; - if (umesh->library() == "moab" && !mpi::master) { + if (umesh->library() == "moab") { + if (mpi::master) warning(fmt::format("Output for a MOAB mesh (mesh {}) was requested but will not be written. Please use the Python API to generated the desired VTK tetrahedral mesh.", umesh->id_)); continue; } From f4bb731687acfe003080e9614c117795d69c71aa Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 21 Jul 2022 22:29:51 -0500 Subject: [PATCH 0668/2654] Keep outgoing datasets in a list until VTK file is written --- openmc/mesh.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 601d0ac94..d88f6e363 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1722,6 +1722,7 @@ class UnstructuredMesh(MeshBase): grid.InsertNextCell(elem.GetCellType(), elem.GetPointIds()) # check that datasets are the correct size + datasets_out = [] if datasets is not None: for name, data in datasets.items(): if data.shape != (self.dimension,): @@ -1739,6 +1740,7 @@ class UnstructuredMesh(MeshBase): # add data to the mesh for name, data in datasets.items(): + datasets_out.append(data) arr = vtk.vtkDoubleArray() arr.SetName(name) arr.SetNumberOfTuples(data.size) From 0118067e2f7cc1fd37f50591f998b2f97ce897ae Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 25 Jul 2022 16:00:50 -0500 Subject: [PATCH 0669/2654] Fix for IncoherentElasticAE.from_hdf5 --- openmc/data/thermal_angle_energy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/data/thermal_angle_energy.py b/openmc/data/thermal_angle_energy.py index 1f37863ea..17a560092 100644 --- a/openmc/data/thermal_angle_energy.py +++ b/openmc/data/thermal_angle_energy.py @@ -122,7 +122,7 @@ class IncoherentElasticAE(AngleEnergy): Incoherent elastic distribution """ - return cls(group['debye_waller']) + return cls(group['debye_waller'][()]) class IncoherentElasticAEDiscrete(AngleEnergy): From 91000f3ea0dac86e4129c22b75937bec85f64e75 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Fri, 1 Jul 2022 16:51:39 -0500 Subject: [PATCH 0670/2654] refactored mesh.cpp to allow mesh pointer or filename and reduced copied code --- include/openmc/mesh.h | 9 ++++++--- src/mesh.cpp | 27 ++++++++++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 21c58862d..4d5ebc46e 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -53,7 +53,7 @@ extern vector> meshes; #ifdef LIBMESH namespace settings { -// used when creating new libMesh::Mesh instances +// used when creating new libMesh::MeshBase instances extern unique_ptr libmesh_init; extern const libMesh::Parallel::Communicator* libmesh_comm; } // namespace settings @@ -671,7 +671,8 @@ class LibMesh : public UnstructuredMesh { public: // Constructors LibMesh(pugi::xml_node node); - LibMesh(const std::string& filename, double length_multiplier = 1.0); + LibMesh(const std::string & filename, double length_multiplier = 1.0); + LibMesh(libMesh::MeshBase & input_mesh, double length_multiplier = 1.0); static const std::string mesh_lib_type; @@ -705,6 +706,7 @@ public: private: void initialize() override; + void set_mesh_pointer_from_filename(const std::string& filename); // Methods @@ -715,7 +717,8 @@ private: int get_bin_from_element(const libMesh::Elem* elem) const; // Data members - unique_ptr m_; //!< pointer to the libMesh mesh instance + unique_ptr unique_m_; //!< pointer to the libMesh MeshBase instance, only used if mesh is created inside OpenMC + libMesh::MeshBase * m_; //!< pointer to libMesh MeshBase instance vector> pl_; //!< per-thread point locators unique_ptr diff --git a/src/mesh.cpp b/src/mesh.cpp index e8f79aa37..68675b969 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2327,13 +2327,31 @@ LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) initialize(); } -LibMesh::LibMesh(const std::string& filename, double length_multiplier) +// create the mesh from a pointer to a libMesh Mesh +LibMesh::LibMesh(libMesh::MeshBase & input_mesh, double length_multiplier) { - filename_ = filename; + m_ = &input_mesh; set_length_multiplier(length_multiplier); initialize(); } +// create the mesh from an input file +LibMesh::LibMesh(const std::string& filename, double length_multiplier) +{ + set_mesh_pointer_from_filename(filename); + set_length_multiplier(length_multiplier); + initialize(); +} + +void LibMesh::set_mesh_pointer_from_filename(const std::string& filename) +{ + filename_ = filename; + unique_m_ = make_unique(*settings::libmesh_comm, n_dimension_); + m_ = unique_m_.get(); + m_->read(filename_); +} + +// intialize from mesh file void LibMesh::initialize() { if (!settings::libmesh_comm) { @@ -2344,15 +2362,10 @@ void LibMesh::initialize() // assuming that unstructured meshes used in OpenMC are 3D n_dimension_ = 3; - m_ = make_unique(*settings::libmesh_comm, n_dimension_); - m_->read(filename_); - if (specified_length_multiplier_) { libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); } - m_->prepare_for_use(); - // ensure that the loaded mesh is 3 dimensional if (m_->mesh_dimension() != n_dimension_) { fatal_error(fmt::format("Mesh file {} specified for use in an unstructured " From 23646c3c7cf8beec9de07a02ea8a9caa38bf7086 Mon Sep 17 00:00:00 2001 From: David Andrs Date: Sat, 23 Jul 2022 08:56:12 -0600 Subject: [PATCH 0671/2654] Allow OpenMC to compile against fmt v9 --- include/openmc/position.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/openmc/position.h b/include/openmc/position.h index 5ab0774f4..4fde420cc 100644 --- a/include/openmc/position.h +++ b/include/openmc/position.h @@ -5,6 +5,7 @@ #include #include // for out_of_range +#include "fmt/format.h" #include "openmc/array.h" #include "openmc/vector.h" @@ -210,4 +211,14 @@ using Direction = Position; } // namespace openmc +template<> +struct fmt::formatter : formatter { + template + auto format(const openmc::Position& pos, FormatContext& ctx) + { + return fmt::formatter::format( + fmt::format("({}, {}, {})", pos.x, pos.y, pos.z), ctx); + } +}; + #endif // OPENMC_POSITION_H From 7fc9d20a3011d6aec405f6c22669da365502de1e Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 12:20:19 -0500 Subject: [PATCH 0672/2654] added back accidentally deleted line --- src/mesh.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mesh.cpp b/src/mesh.cpp index 68675b969..e4ede6a04 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2366,6 +2366,8 @@ void LibMesh::initialize() libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); } + m_->prepare_for_use() + // ensure that the loaded mesh is 3 dimensional if (m_->mesh_dimension() != n_dimension_) { fatal_error(fmt::format("Mesh file {} specified for use in an unstructured " From deda82d6319e628d4ca549e741730a6c1821386e Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 12:20:47 -0500 Subject: [PATCH 0673/2654] added clarification to comment --- include/openmc/mesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 4d5ebc46e..ce512c767 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -718,7 +718,7 @@ private: // Data members unique_ptr unique_m_; //!< pointer to the libMesh MeshBase instance, only used if mesh is created inside OpenMC - libMesh::MeshBase * m_; //!< pointer to libMesh MeshBase instance + libMesh::MeshBase * m_; //!< pointer to libMesh MeshBase instance, always set during intialization vector> pl_; //!< per-thread point locators unique_ptr From 6a9be64d7112ebb65cb671076385c564c9462747 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 12:22:59 -0500 Subject: [PATCH 0674/2654] left off semicolon --- src/mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index e4ede6a04..44580d81b 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2366,7 +2366,7 @@ void LibMesh::initialize() libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); } - m_->prepare_for_use() + m_->prepare_for_use(); // ensure that the loaded mesh is 3 dimensional if (m_->mesh_dimension() != n_dimension_) { From fd8a8207082522a7a454931c49453ee5f0c833e9 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 12:40:13 -0500 Subject: [PATCH 0675/2654] added public mesh_ptr() accessor. moved m->prepare_for_use() to filename constructor since it only happens there. for consistency, added theh length_multiplier scale modification to constructors --- include/openmc/mesh.h | 2 ++ src/mesh.cpp | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index ce512c767..cd2e56bb0 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -704,6 +704,8 @@ public: double volume(int bin) const override; + libMesh::MeshBase * mesh_ptr() const; + private: void initialize() override; void set_mesh_pointer_from_filename(const std::string& filename); diff --git a/src/mesh.cpp b/src/mesh.cpp index 44580d81b..5c2c8ea25 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2332,6 +2332,9 @@ LibMesh::LibMesh(libMesh::MeshBase & input_mesh, double length_multiplier) { m_ = &input_mesh; set_length_multiplier(length_multiplier); + if (specified_length_multiplier_) { + libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); + } initialize(); } @@ -2340,6 +2343,10 @@ LibMesh::LibMesh(const std::string& filename, double length_multiplier) { set_mesh_pointer_from_filename(filename); set_length_multiplier(length_multiplier); + if (specified_length_multiplier_) { + libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); + } + m_->prepare_for_use(); initialize(); } @@ -2362,12 +2369,6 @@ void LibMesh::initialize() // assuming that unstructured meshes used in OpenMC are 3D n_dimension_ = 3; - if (specified_length_multiplier_) { - libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); - } - - m_->prepare_for_use(); - // ensure that the loaded mesh is 3 dimensional if (m_->mesh_dimension() != n_dimension_) { fatal_error(fmt::format("Mesh file {} specified for use in an unstructured " @@ -2565,6 +2566,11 @@ double LibMesh::volume(int bin) const return m_->elem_ref(bin).volume(); } +libMesh::MeshBase * mesh_ptr() const +{ + return m_; +} + #endif // LIBMESH //============================================================================== From 045bc34ec4353ed0ff94448198e61027a26efe66 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 12:59:43 -0500 Subject: [PATCH 0676/2654] moved accessor to one liner in header --- include/openmc/mesh.h | 4 ++-- src/mesh.cpp | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index cd2e56bb0..6d2c2f029 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -704,7 +704,7 @@ public: double volume(int bin) const override; - libMesh::MeshBase * mesh_ptr() const; + libMesh::MeshBase* mesh_ptr() const { return m_; }; private: void initialize() override; @@ -720,7 +720,7 @@ private: // Data members unique_ptr unique_m_; //!< pointer to the libMesh MeshBase instance, only used if mesh is created inside OpenMC - libMesh::MeshBase * m_; //!< pointer to libMesh MeshBase instance, always set during intialization + libMesh::MeshBase* m_; //!< pointer to libMesh MeshBase instance, always set during intialization vector> pl_; //!< per-thread point locators unique_ptr diff --git a/src/mesh.cpp b/src/mesh.cpp index 5c2c8ea25..d849e5d55 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2566,11 +2566,6 @@ double LibMesh::volume(int bin) const return m_->elem_ref(bin).volume(); } -libMesh::MeshBase * mesh_ptr() const -{ - return m_; -} - #endif // LIBMESH //============================================================================== From e4a10c8d05cb587a40a1711fed6cd55c4ddc756c Mon Sep 17 00:00:00 2001 From: myerspat Date: Tue, 26 Jul 2022 16:38:54 -0500 Subject: [PATCH 0677/2654] Added new algorithm for complex cell finding using infix --- src/cell.cpp | 120 +++++++++++++++++++++++++-------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index 2e26e2c17..578fb024d 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -514,14 +514,16 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } } - // Convert the infix region spec to RPN. - //rpn_ = generate_rpn(id_, region_); + // Convert the infix region spec to infix with no complements + // using De Morgan's law. + // TODO: Convert rpn to something that makes sense rpn_ = region_; + remove_complement_ops(rpn_); // Check if this is a simple cell. simple_ = true; for (int32_t token : rpn_) { - if ((token == OP_COMPLEMENT) || (token == OP_UNION)) { + if (token == OP_UNION) { simple_ = false; break; } @@ -529,16 +531,11 @@ CSGCell::CSGCell(pugi::xml_node cell_node) // If this cell is simple, remove all the superfluous operator tokens. if (simple_) { - size_t i0 = 0; - size_t i1 = 0; - while (i1 < rpn_.size()) { - if (rpn_[i1] < OP_UNION) { - rpn_[i0] = rpn_[i1]; - ++i0; + for (auto it = rpn_.begin(); it != rpn_.end(); it++) { + if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { + rpn_.erase(it); } - ++i1; } - rpn_.resize(i0); } rpn_.shrink_to_fit(); @@ -648,7 +645,7 @@ BoundingBox CSGCell::bounding_box_simple() const void CSGCell::apply_demorgan( vector::iterator start, vector::iterator stop) { - while (start < stop) { + do { if (*start < OP_UNION) { *start *= -1; } else if (*start == OP_UNION) { @@ -657,16 +654,16 @@ void CSGCell::apply_demorgan( *start = OP_UNION; } start++; - } + } while (start < stop); } vector::iterator CSGCell::find_left_parenthesis( - vector::iterator start, const vector& rpn) + vector::iterator start, const vector& infix) { // start search at zero int parenthesis_level = 0; auto it = start; - while (it != rpn.begin()) { + while (it != infix.begin()) { // look at two tokens at a time int32_t one = *it; int32_t two = *(it - 1); @@ -693,21 +690,25 @@ vector::iterator CSGCell::find_left_parenthesis( return it; } -void CSGCell::remove_complement_ops(vector& rpn) +void CSGCell::remove_complement_ops(vector& infix) { - auto it = std::find(rpn.begin(), rpn.end(), OP_COMPLEMENT); - while (it != rpn.end()) { - // find the opening parenthesis (if any) - auto left = find_left_parenthesis(it, rpn); - vector tmp(left, it + 1); + auto it = std::find(infix.begin(), infix.end(), OP_COMPLEMENT); + while (it != infix.end()) { + // Erase complement + infix.erase(it); + + // Define stop given left parenthesis or not + auto stop = it; + if (*it == OP_LEFT_PAREN) { + stop = std::find(infix.begin(), infix.end(), OP_RIGHT_PAREN); + it++; + } // apply DeMorgan's law to any surfaces/operators between these // positions in the RPN - apply_demorgan(left, it); - // remove complement operator - rpn.erase(it); + apply_demorgan(it, stop); // update iterator position - it = std::find(rpn.begin(), rpn.end(), OP_COMPLEMENT); + it = std::find(infix.begin(), infix.end(), OP_COMPLEMENT); } } @@ -770,43 +771,42 @@ bool CSGCell::contains_complex( Position r, Direction u, int32_t on_surface) const { bool in_cell = true; - bool negate = false; - int paren_depth = 0; - int negate_depth = 0; + + // For each token + for (auto it = rpn_.begin(); it != rpn_.end(); it++) { + int32_t token = *it; - for (int32_t token : rpn_) { - if (token < OP_UNION && in_cell == true) { - if (token == on_surface) { - in_cell = true; - } else if (-token == on_surface) { - in_cell = false; - } else { - // Note the off-by-one - bool sense = model::surfaces[abs(token) - 1]->sense(r, u); - in_cell = (sense == (token > 0)); - } - } else if (token == OP_UNION) { - if (in_cell == false) { - in_cell = true; - } else if (paren_depth == 0) { - break; - } - } else if (token == OP_RIGHT_PAREN) { - paren_depth--; - } else if (token == OP_LEFT_PAREN) { - paren_depth++; - } else if (token == OP_COMPLEMENT) { - negate = true; - negate_depth = paren_depth; - continue; - } else if (paren_depth == 0) { - break; - } - - if (negate == true && negate_depth == paren_depth) { - in_cell = !in_cell; - negate = false; + // If the token is a surface evaluate the sense + // If the token is a union or intersection check to + // short circuit + if (token < OP_UNION) { + if (token == on_surface) { + in_cell = true; + } else if (-token == on_surface) { + in_cell = false; + } else { + // Note the off-by-one indexing + bool sense = model::surfaces[abs(token) - 1]->sense(r, u); + in_cell = (sense == (token > 0)); } + } else if ((token == OP_UNION && in_cell == true) || + (token == OP_INTERSECTION && in_cell == false)) { + // While the iterator is within the bounds of the vector + do { + // Get next token + it++; + int32_t next_token = *it; + + // If the next token is a left parenthesis skip until + // the next right parenthesis, if the token is a right + // parenthesis leave short circuiting + if (next_token == OP_LEFT_PAREN) { + it = std::find(it, rpn_.end(), OP_RIGHT_PAREN); + } else if (next_token == OP_RIGHT_PAREN) { + break; + } + } while (it < rpn_.end() - 1); + } } return in_cell; } From 5161da8031ce97d2c5b19a98614d9d5fc2a52f27 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 16:39:54 -0500 Subject: [PATCH 0678/2654] retrireve filename and length_multiplier from XML file and call methods similar to filename case for XML constructor --- include/openmc/mesh.h | 2 +- src/mesh.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 6d2c2f029..0ace6dfea 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -7,13 +7,13 @@ #include #include "hdf5.h" -#include "pugixml.hpp" #include "xtensor/xtensor.hpp" #include "openmc/memory.h" // for unique_ptr #include "openmc/particle.h" #include "openmc/position.h" #include "openmc/vector.h" +#include "openmc/xml_interface.h" #ifdef DAGMC #include "moab/AdaptiveKDTree.hpp" diff --git a/src/mesh.cpp b/src/mesh.cpp index d849e5d55..771d6f81f 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2324,6 +2324,14 @@ const std::string LibMesh::mesh_lib_type = "libmesh"; LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { + std::string& filename = node.get_node_value(node, "filename"); + double length_multiplier = std::stod(node.get_node_value(node, "length_multiplier")); + set_mesh_pointer_from_filename(filename); + set_length_multiplier(length_multiplier); + if (specified_length_multiplier_) { + libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); + } + m_->prepare_for_use(); initialize(); } From 3c2d79a24198b87a1ed4a6473c920c02da773374 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 17:01:50 -0500 Subject: [PATCH 0679/2654] added back in header (despite redundancy) due to use in mesh files --- include/openmc/mesh.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 0ace6dfea..13138a739 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -8,6 +8,7 @@ #include "hdf5.h" #include "xtensor/xtensor.hpp" +#include "pugixml.hpp" #include "openmc/memory.h" // for unique_ptr #include "openmc/particle.h" From 5f1f0827aed488f1fde8876fcf28961c2ebd7d31 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 17:55:43 -0500 Subject: [PATCH 0680/2654] not supposed to call method on node object, other places use it from no object. following those examples --- src/mesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 771d6f81f..e2c1e50ec 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2324,8 +2324,8 @@ const std::string LibMesh::mesh_lib_type = "libmesh"; LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { - std::string& filename = node.get_node_value(node, "filename"); - double length_multiplier = std::stod(node.get_node_value(node, "length_multiplier")); + std::string& filename = get_node_value(node, "filename"); + double length_multiplier = std::stod(get_node_value(node, "length_multiplier")); set_mesh_pointer_from_filename(filename); set_length_multiplier(length_multiplier); if (specified_length_multiplier_) { From 35c3ef9e2dbfccfe212267a02a6a72a2a1849821 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 26 Jul 2022 18:18:26 -0500 Subject: [PATCH 0681/2654] filenanme shouldn't be a reference since the RHS initializes with a non-const rvalue, causing an error --- src/mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index e2c1e50ec..ca19a02b6 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2324,7 +2324,7 @@ const std::string LibMesh::mesh_lib_type = "libmesh"; LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { - std::string& filename = get_node_value(node, "filename"); + std::string filename = get_node_value(node, "filename"); double length_multiplier = std::stod(get_node_value(node, "length_multiplier")); set_mesh_pointer_from_filename(filename); set_length_multiplier(length_multiplier); From 1e4371549c6a3478a79d064933c2f8edd451e528 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 27 Jul 2022 09:41:56 -0500 Subject: [PATCH 0682/2654] Returning unstructured mesh dimension as a tuple. Improving error message format --- openmc/mesh.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d88f6e363..9c837fd8e 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1616,7 +1616,7 @@ class UnstructuredMesh(MeshBase): @property def dimension(self): - return self.n_elements + return (self.n_elements,) @property def n_dimension(self): @@ -1725,15 +1725,15 @@ class UnstructuredMesh(MeshBase): datasets_out = [] if datasets is not None: for name, data in datasets.items(): - if data.shape != (self.dimension,): - raise ValueError(f'Cannot apply dataset {name} with ' + if data.shape != self.dimension: + raise ValueError(f'Cannot apply dataset "{name}" with ' f'shape {data.shape} to mesh {self.id} ' f'with dimensions {self.dimension}') if volume_normalization: for name, data in datasets.items(): if np.issubdtype(data.dtype, np.integer): - warnings.warn(f'Integer data set {name} will ' + warnings.warn(f'Integer data set "{name}" will ' 'not be volume-normalized.') continue data /= self.volumes From 67d01417b7c3092d7333702971da357b9d3c4e33 Mon Sep 17 00:00:00 2001 From: myerspat Date: Wed, 27 Jul 2022 11:18:02 -0500 Subject: [PATCH 0683/2654] Fixed errors due to iterators --- src/cell.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index 578fb024d..edd4da84d 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -700,7 +700,7 @@ void CSGCell::remove_complement_ops(vector& infix) // Define stop given left parenthesis or not auto stop = it; if (*it == OP_LEFT_PAREN) { - stop = std::find(infix.begin(), infix.end(), OP_RIGHT_PAREN); + stop = std::find(it, infix.end(), OP_RIGHT_PAREN); it++; } @@ -708,7 +708,7 @@ void CSGCell::remove_complement_ops(vector& infix) // positions in the RPN apply_demorgan(it, stop); // update iterator position - it = std::find(infix.begin(), infix.end(), OP_COMPLEMENT); + it = std::find(it, infix.end(), OP_COMPLEMENT); } } @@ -801,7 +801,7 @@ bool CSGCell::contains_complex( // the next right parenthesis, if the token is a right // parenthesis leave short circuiting if (next_token == OP_LEFT_PAREN) { - it = std::find(it, rpn_.end(), OP_RIGHT_PAREN); + it = std::find(it, rpn_.end() - 1, OP_RIGHT_PAREN); } else if (next_token == OP_RIGHT_PAREN) { break; } From 7dfb35a39a553bcb7abe06447a2d8e0a2ff6dc46 Mon Sep 17 00:00:00 2001 From: myerspat Date: Wed, 27 Jul 2022 12:15:46 -0500 Subject: [PATCH 0684/2654] removed rpn_ and changed to only region_ --- include/openmc/cell.h | 2 -- src/cell.cpp | 32 ++++++++++++++------------------ src/geometry_aux.cpp | 2 +- src/universe.cpp | 4 ++-- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 01f037586..887901707 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -202,8 +202,6 @@ public: //! Definition of spatial region as Boolean expression of half-spaces vector region_; - //! Reverse Polish notation for region expression - vector rpn_; bool simple_; //!< Does the region contain only intersections? //! \brief Neighboring cells in the same universe. diff --git a/src/cell.cpp b/src/cell.cpp index edd4da84d..943722f35 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -497,8 +497,10 @@ CSGCell::CSGCell(pugi::xml_node cell_node) region_spec = get_node_value(cell_node, "region"); } - // Get a tokenized representation of the region specification. + // Get a tokenized representation of the region specification + // and apply De Morgan's laws to remove complements. region_ = tokenize(region_spec); + remove_complement_ops(region_); region_.shrink_to_fit(); // Convert user IDs to surface indices. @@ -514,15 +516,9 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } } - // Convert the infix region spec to infix with no complements - // using De Morgan's law. - // TODO: Convert rpn to something that makes sense - rpn_ = region_; - remove_complement_ops(rpn_); - // Check if this is a simple cell. simple_ = true; - for (int32_t token : rpn_) { + for (int32_t token : region_) { if (token == OP_UNION) { simple_ = false; break; @@ -531,13 +527,13 @@ CSGCell::CSGCell(pugi::xml_node cell_node) // If this cell is simple, remove all the superfluous operator tokens. if (simple_) { - for (auto it = rpn_.begin(); it != rpn_.end(); it++) { + for (auto it = region_.begin(); it != region_.end(); it++) { if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { - rpn_.erase(it); + region_.erase(it); } } } - rpn_.shrink_to_fit(); + region_.shrink_to_fit(); // Read the translation vector. if (check_for_node(cell_node, "translation")) { @@ -581,7 +577,7 @@ std::pair CSGCell::distance( double min_dist {INFTY}; int32_t i_surf {std::numeric_limits::max()}; - for (int32_t token : rpn_) { + for (int32_t token : region_) { // Ignore this token if it corresponds to an operator rather than a region. if (token >= OP_UNION) continue; @@ -636,7 +632,7 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const BoundingBox CSGCell::bounding_box_simple() const { BoundingBox bbox; - for (int32_t token : rpn_) { + for (int32_t token : region_) { bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); } return bbox; @@ -739,14 +735,14 @@ BoundingBox CSGCell::bounding_box_complex(vector rpn) BoundingBox CSGCell::bounding_box() const { - return simple_ ? bounding_box_simple() : bounding_box_complex(rpn_); + return simple_ ? bounding_box_simple() : bounding_box_complex(region_); } //============================================================================== bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const { - for (int32_t token : rpn_) { + for (int32_t token : region_) { // Assume that no tokens are operators. Evaluate the sense of particle with // respect to the surface and see if the token matches the sense. If the // particle's surface attribute is set and matches the token, that @@ -773,7 +769,7 @@ bool CSGCell::contains_complex( bool in_cell = true; // For each token - for (auto it = rpn_.begin(); it != rpn_.end(); it++) { + for (auto it = region_.begin(); it != region_.end(); it++) { int32_t token = *it; // If the token is a surface evaluate the sense @@ -801,11 +797,11 @@ bool CSGCell::contains_complex( // the next right parenthesis, if the token is a right // parenthesis leave short circuiting if (next_token == OP_LEFT_PAREN) { - it = std::find(it, rpn_.end() - 1, OP_RIGHT_PAREN); + it = std::find(it, region_.end() - 1, OP_RIGHT_PAREN); } else if (next_token == OP_RIGHT_PAREN) { break; } - } while (it < rpn_.end() - 1); + } while (it < region_.end() - 1); } } return in_cell; diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index ddce2469b..c3458d469 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -154,7 +154,7 @@ void partition_universes() // Collect the set of surfaces in this universe. std::unordered_set surf_inds; for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->rpn_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) surf_inds.insert(std::abs(token) - 1); } diff --git a/src/universe.cpp b/src/universe.cpp index f3f9cf8e8..873d03bb7 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -98,7 +98,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find all of the z-planes in this universe. A set is used here for the // O(log(n)) insertions that will ensure entries are not repeated. for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->rpn_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) { auto i_surf = std::abs(token) - 1; const auto* surf = model::surfaces[i_surf].get(); @@ -125,7 +125,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find the tokens for bounding z-planes. int32_t lower_token = 0, upper_token = 0; double min_z, max_z; - for (auto token : model::cells[i_cell]->rpn_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) { const auto* surf = model::surfaces[std::abs(token) - 1].get(); if (const auto* zplane = dynamic_cast(surf)) { From 3010c5e9ad27cff6c4f3a54e8d202f0ef796ef5e Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 27 Jul 2022 12:48:30 -0500 Subject: [PATCH 0685/2654] moved m->prepare_for_use() back to initialize, but only occurs if unique_m exists. XML constructor can access member variables from UnstucturedMesh constructor --- src/mesh.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index ca19a02b6..8e9d4bcec 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2324,14 +2324,8 @@ const std::string LibMesh::mesh_lib_type = "libmesh"; LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { - std::string filename = get_node_value(node, "filename"); - double length_multiplier = std::stod(get_node_value(node, "length_multiplier")); - set_mesh_pointer_from_filename(filename); - set_length_multiplier(length_multiplier); - if (specified_length_multiplier_) { - libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); - } - m_->prepare_for_use(); + set_mesh_pointer_from_filename(filename_); + set_length_multiplier(length_multiplier_); initialize(); } @@ -2340,9 +2334,6 @@ LibMesh::LibMesh(libMesh::MeshBase & input_mesh, double length_multiplier) { m_ = &input_mesh; set_length_multiplier(length_multiplier); - if (specified_length_multiplier_) { - libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); - } initialize(); } @@ -2351,10 +2342,6 @@ LibMesh::LibMesh(const std::string& filename, double length_multiplier) { set_mesh_pointer_from_filename(filename); set_length_multiplier(length_multiplier); - if (specified_length_multiplier_) { - libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); - } - m_->prepare_for_use(); initialize(); } @@ -2377,6 +2364,15 @@ void LibMesh::initialize() // assuming that unstructured meshes used in OpenMC are 3D n_dimension_ = 3; + if (specified_length_multiplier_) { + libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); + } + // if OpenMC is managing the libMesh::MeshBase instance, prepare the mesh. + // Otherwise assume that it is prepared by it's owning application + if (unique_m_) { + m_->prepare_for_use(); + } + // ensure that the loaded mesh is 3 dimensional if (m_->mesh_dimension() != n_dimension_) { fatal_error(fmt::format("Mesh file {} specified for use in an unstructured " From 7c215543ebe7f3090683096b93047082b325179a Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 27 Jul 2022 12:53:19 -0500 Subject: [PATCH 0686/2654] added comment to XML constructor. initialized unique_m_ to nullptr to help some compilers --- include/openmc/mesh.h | 2 +- src/mesh.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 13138a739..02bd3bc5a 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -720,7 +720,7 @@ private: int get_bin_from_element(const libMesh::Elem* elem) const; // Data members - unique_ptr unique_m_; //!< pointer to the libMesh MeshBase instance, only used if mesh is created inside OpenMC + unique_ptr unique_m_ = nullptr; //!< pointer to the libMesh MeshBase instance, only used if mesh is created inside OpenMC libMesh::MeshBase* m_; //!< pointer to libMesh MeshBase instance, always set during intialization vector> pl_; //!< per-thread point locators diff --git a/src/mesh.cpp b/src/mesh.cpp index 8e9d4bcec..dfa443b7f 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2324,6 +2324,7 @@ const std::string LibMesh::mesh_lib_type = "libmesh"; LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { + // filename_ and length_multiplier_ will already be set by the UnstructuredMesh constructor set_mesh_pointer_from_filename(filename_); set_length_multiplier(length_multiplier_); initialize(); From b3d0f20a0010dd930e4f403848d72164f32b294e Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 27 Jul 2022 13:15:10 -0500 Subject: [PATCH 0687/2654] added add_nuclides method --- openmc/material.py | 14 ++++++++++++++ tests/unit_tests/test_material.py | 28 +++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index a837b1f17..cd181539c 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -403,6 +403,20 @@ class Material(IDManagerMixin): self._nuclides.append(NuclideTuple(nuclide, percent, percent_type)) + def add_nuclides(self, nuclides: dict): + """ Add multiple nuclides to a material + + Parameters + ---------- + nuclides : dict of str to tuple + Dictionary mapping nuclide names to a tuple containing their + atom or weight percent. + + """ + + for nuclide, (percent, percent_type) in nuclides.items(): + self.add_nuclide(nuclide, percent, percent_type) + def remove_nuclide(self, nuclide: str): """Remove a nuclide from the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index fd0e4f624..8dde30485 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -25,6 +25,32 @@ def test_add_nuclide(): with pytest.raises(ValueError): m.add_nuclide('H1', 1.0, 'oa') +def test_add_nuclides(): + """Test adding multipe nuclides at once""" + m = openmc.Material() + nuclides = {'H1': (2.0, 'ao'), + 'O16': (1.0, 'wo')} + m.add_nuclides(nuclides) + + # wt-% + m = openmc.Material() + nuclides = {'H1': (2.0, 'wo'), + 'O16': (1.0, 'wo')} + m.add_nuclides(nuclides) + + # mixed + m = openmc.Material() + nuclides = {'H1': (2.0, 'ao'), + 'O16': (1.0, 'wo')} + m.add_nuclides(nuclides) + + with pytest.raises(TypeError): + m.add_nuclides({'H1': ('1.0', 'ao')}) + with pytest.raises(TypeError): + m.add_nuclides({1.0: ('H1', 'wo')}) + with pytest.raises(ValueError): + m.add_nuclides({'H1': (1.0, 'oa')}) + def test_remove_nuclide(): """Test removing nuclides.""" @@ -441,7 +467,7 @@ def test_activity_of_tritium(): m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) m1.volume = 1 - assert pytest.approx(m1.activity) == 3.559778e14 + assert pytest.approx(m1.activity) == 3.559778e14 def test_activity_of_metastable(): From 4818a296d4893a809baf5f3b171413dcdd3ff7ee Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 27 Jul 2022 12:27:16 -0500 Subject: [PATCH 0688/2654] Made changes from paulromano's 2nd round of comments - Syntax improvements and fixes - removed `flux` parameter from Integrator - Moved generate_1g_cross_sections to a top level function in flux_operator.py - changed normalization modes: constant-flux -> source-rate; constant-power -> fission-q - fixed regression tests (fission-q reference solution was bad before, but is now much more reasonable and comparable to the source-rate reference solution) - added `nuc_units` parameter to the `from_nuclides` method. - docstring fixes - RST doc fixes - spelling fixes --- docs/source/usersguide/depletion.rst | 16 +- openmc/deplete/abc.py | 26 +- openmc/deplete/flux_operator.py | 247 +++++++++--------- openmc/deplete/helpers.py | 8 +- openmc/deplete/integrators.py | 2 +- openmc/deplete/openmc_operator.py | 5 +- openmc/deplete/operator.py | 16 +- .../deplete_no_transport/test.py | 31 ++- ...t_power.h5 => test_reference_fission_q.h5} | Bin 35688 -> 35688 bytes ..._flux.h5 => test_reference_source_rate.h5} | Bin .../unit_tests/test_deplete_flux_operator.py | 2 +- 11 files changed, 178 insertions(+), 175 deletions(-) rename tests/regression_tests/deplete_no_transport/{test_reference_constant_power.h5 => test_reference_fission_q.h5} (99%) rename tests/regression_tests/deplete_no_transport/{test_reference_constant_flux.h5 => test_reference_source_rate.h5} (100%) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index e95e098c4..cfb373e13 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -19,10 +19,10 @@ transmutation equations and the method used for advancing time. At present, the :class:`openmc.deplete.Operator` (which uses the OpenMC transport solver), but in principle additional operator classes based on other transport codes could be implemented and no changes to the depletion solver itself would be needed. The -operator class requires a :class:`openmc.model.Model` instance containing +operator class requires a :class:`~openmc.Model` instance containing material, geometry, and settings information:: - model = openmc.model.Model() + model = openmc.Model() ... op = openmc.deplete.Operator(model) @@ -189,17 +189,18 @@ Transport-independent depletion OpenMC supports running depletion calculations independent of the OpenMC transport solver using the :class:`~openmc.deplete.FluxDepletionOperator` class. -This class supports both constant-flux and constant-power depletion. +This class supports both constant-flux (``source-rate`` normalization) and +constant-power depletion (``fission-q`` normalization). .. important:: - Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` class. Use the ``flux`` parameter when ``normalization_mode == constant-flux``, and use ``power`` or ``power_density`` when ``normalization_mode == constant-power``. + Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` class. Use the ``source_rates`` parameter when ``normalization_mode == source-rate``, and use ``power`` or ``power_density`` when ``normalization_mode == fission-q``. .. warning:: - The accuracy of results when using ``constant-power`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the dynamics of your particular scenario. + The accuracy of results when using ``fission-q`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the dynamics of your particular scenario. -This class has two ways to initalize it: the default constructor accepts an +This class has two ways to initialize it: the default constructor accepts an :class:`openmc.Materials` object and one-group microscopic cross sections as a :class:`pandas.DataFrame`, while the ``from_nuclides`` method accepts a volume and dictionary of nuclide concentrations in place of @@ -221,7 +222,8 @@ or from data arrays:: 'O16': 4.64e22, 'O17': 1.76e19} volume = 0.5 - op = FluxDepletionOperator.from_nuclides(volume, nuclides, micro_xs, flux, chain_file) + op = FluxDepletionOperator.from_nuclides(volume, nuclides, 'atom/cm3', + micro_xs, flux, chain_file) A user can then define an integrator class as they would for a coupled transport-depletion calculation and follow the same steps from there. diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 24859151f..90a353d93 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -524,11 +524,10 @@ class Integrator(ABC): power_density : float or iterable of float, optional Power density of the reactor in [W/gHM]. It is multiplied by initial heavy metal inventory to get total power if ``power`` - is not speficied. - flux : float or iterable of float, optional - neutron flux in [neut/s-cm^2] for each interval in :attr:`timesteps` + is not specified. source_rates : float or iterable of float, optional - source rate in [neutron/sec] for each interval in :attr:`timesteps` + Source rate in [neutron/sec] or neutron flux in [neut/s-cm^2] for each + interval in :attr:`timesteps` .. versionadded:: 0.12.1 timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} @@ -579,7 +578,7 @@ class Integrator(ABC): """ def __init__(self, operator, timesteps, power=None, power_density=None, - flux=None, source_rates=None, timestep_units='s', solver="cram48"): + source_rates=None, timestep_units='s', solver="cram48"): # Check number of stages previously used if operator.prev_res is not None: res = operator.prev_res[-1] @@ -601,10 +600,8 @@ class Integrator(ABC): source_rates = power_density * operator.heavy_metal else: source_rates = [p*operator.heavy_metal for p in power_density] - elif flux is not None: - source_rates = flux elif source_rates is None: - raise ValueError("Either power, power_density, flux, or source_rates must be set") + raise ValueError("Either power, power_density, source_rates must be set") if not isinstance(source_rates, Iterable): # Ensure that rate is single value if that is the case @@ -865,11 +862,10 @@ class SIIntegrator(Integrator): power_density : float or iterable of float, optional Power density of the reactor in [W/gHM]. It is multiplied by initial heavy metal inventory to get total power if ``power`` - is not speficied. - flux : float or iterable of float, optional - neutron flux in [neut/s-cm^2] for each interval in :attr:`timesteps` + is not specified. source_rates : float or iterable of float, optional - Source rate in [neutron/sec] for each interval in :attr:`timesteps` + Source rate in [neutron/sec] or neutron flux in [neut/s-cm^2] for each + interval in :attr:`timesteps` .. versionadded:: 0.12.1 timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} @@ -924,12 +920,12 @@ class SIIntegrator(Integrator): """ def __init__(self, operator, timesteps, power=None, power_density=None, - flux=None, source_rates=None, timestep_units='s', n_steps=10, + source_rates=None, timestep_units='s', n_steps=10, solver="cram48"): check_type("n_steps", n_steps, Integral) check_greater_than("n_steps", n_steps, 0) super().__init__( - operator, timesteps, power, power_density, flux, source_rates, + operator, timesteps, power, power_density, source_rates, timestep_units=timestep_units, solver=solver) self.n_steps = n_steps @@ -1014,7 +1010,7 @@ class DepSystemSolver(ABC): Parameters ---------- A : scipy.sparse.csr_matrix - Sparse transmutation matrix ``A[j, i]`` desribing rates at + Sparse transmutation matrix ``A[j, i]`` describing rates at which isotope ``i`` transmutes to isotope ``j`` n0 : numpy.ndarray Initial compositions, typically given in number of atoms in some diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 974255753..410552671 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -1,7 +1,7 @@ """Pure depletion operator -This module implements a pure depletion operator that uses user- provided fluxes -and one-group cross sections. +This module implements a pure depletion operator that user-provided one-group +cross sections. """ @@ -20,12 +20,84 @@ from openmc.mpi import comm from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS from .abc import ReactionRateHelper, OperatorResult from .chain import REACTIONS -from .openmc_operator import OpenMCOperator +from .openmc_operator import OpenMCOperator, _distribute +from .results import Results from .helpers import ChainFissionHelper, ConstantFissionYieldHelper, SourceRateHelper _valid_rxns = list(REACTIONS) _valid_rxns.append('fission') +def generate_1g_cross_sections(model, + reaction_domain, + reactions=['(n,gamma)', + '(n,2n)', + '(n,p)', + '(n,a)', + '(n,3n)', + '(n,4n)', + 'fission'], + energy_bounds=(0, 20e6), + write_to_csv=False, + filename='micro_xs.csv'): + """Helper function to generate a one-group cross-section dataframe using + OpenMC. Note that the ``openmc`` executable must be compiled. + + Parameters + ---------- + model : openmc.model.Model + OpenMC model object. Must contain geometry, materials, and settings. + reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh + Domain in which to tally reaction rates. + reactions : list of str, optional + Reaction names to tally + energy_bound : 2-tuple of float, optional + Bounds for the energy group. + write_to_csv : bool, optional + Option to write the DataFrame to a `.csv` file. + filename : str + Name for csv file. Only applicable if ``write_to_csv == True`` + + Returns + ------- + None or pandas.DataFrame + + """ + groups = EnergyGroups(energy_bounds) + + # Set up the reaction tallies + original_tallies = model.tallies + tallies = openmc.Tallies() + xs = {} + for rxn in reactions: + if rxn == 'fission': + xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) + else: + xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) + tallies += xs[rxn].tallies.values() + + model.tallies = tallies + statepoint_path = model.run() + + # Revert to the original tallies + model.tallies = old_tallies + + with openmc.StatePoint(statepoint_path) as sp: + for rxn in xs: + xs[rxn].load_from_statepoint(sp) + + # Build the DataFrame + micro_xs = pd.DataFrame() + for rxn in xs: + df = xs[rxn].get_pandas_dataframe(xs_type='micro') + df.index = df['nuclide'] + df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) + df.rename({'mean':rxn}, axis=1, inplace=True) + micro_xs = pd.concat([micro_xs, df], axis=1) + + if write_to_csv: + micro_xs.to_csv(filename) + + return micro_xs class FluxDepletionOperator(OpenMCOperator): """Depletion operator that uses one-group @@ -50,14 +122,16 @@ class FluxDepletionOperator(OpenMCOperator): Default is None. prev_results : Results, optional Results from a previous depletion calculation. - normalization_mode : {"constant-power", "constant-flux"} + normalization_mode : {"fission-q", "source-rate"} Indicate how reaction rates should be calculated. - ``"constant-power"`` uses the fission Q values from the depletion chain to - compute the flux based on the power. ``"constant-flux"`` uses the value stored in `_normalization_helper` as the flux. + ``"fission-q"`` uses the fission Q values from the depletion chain to + compute the flux based on the power. ``"source-rate"`` uses a the + source rate (assumed to be neutron flux) to calculate the + reaction rates. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only applicable - if ``"normalization_mode" == "constant-power"``. + if ``"normalization_mode" == "fission-q"``. reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. Default is False. @@ -104,14 +178,14 @@ class FluxDepletionOperator(OpenMCOperator): Results from a previous depletion calculation. ``None`` if no results are to be used. - """ + """ def __init__(self, materials, micro_xs, chain_file, keff=None, - normalization_mode = 'constant-flux', + normalization_mode='source-rate', fission_q=None, prev_results=None, reduce_chain=False, @@ -126,7 +200,8 @@ class FluxDepletionOperator(OpenMCOperator): self._keff = keff - helper_kwargs = dict() + if fission_yield_opts is None: + fission_yield_opts = {} helper_kwargs = {'normalization_mode': normalization_mode, 'fission_yield_opts': fission_yield_opts} @@ -141,10 +216,11 @@ class FluxDepletionOperator(OpenMCOperator): reduce_chain_level=reduce_chain_level) @classmethod - def from_nuclides(cls, volume, nuclides, micro_xs, + def from_nuclides(cls, volume, nuclides, nuc_units, + micro_xs, chain_file, keff=None, - normalization_mode='constant-flux', + normalization_mode='source-rate', fission_q=None, prev_results=None, reduce_chain=False, @@ -156,8 +232,10 @@ class FluxDepletionOperator(OpenMCOperator): volume : float Volume of the material being depleted in [cm^3] nuclides : dict of str to float - ,Dictionary with nuclide names as keys and nuclide concentrations as - values. Nuclide concentration units are [atom/cm^3]. + Dictionary with nuclide names as keys and nuclide concentrations as + values. + nuc_units : {'atom/cm3', 'atom/b-cm'} + Units for nuclide concentration. micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. @@ -166,15 +244,16 @@ class FluxDepletionOperator(OpenMCOperator): keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. Default is None. - normalization_mode : {"constant-power", "constant-flux"} + normalization_mode : {"fission-q", "source-rate"} Indicate how reaction rates should be calculated. - ``"constant-power"`` uses the fission Q values from the depletion - chain to compute the flux based on the power. ``"constant-flux"`` - uses the value stored in `_normalization_helper` as the flux. + ``"fission-q"`` uses the fission Q values from the depletion + chain to compute the flux based on the power. ``"source-rate"`` uses + the source rate (assumed to be neutron flux) to calculate the + reaction rates. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only - applicable if ``"normalization_mode" == "constant-power"``. + applicable if ``"normalization_mode" == "fission-q"``. prev_results : Results, optional Results from a previous depletion calculation. reduce_chain : bool, optional @@ -191,7 +270,7 @@ class FluxDepletionOperator(OpenMCOperator): """ check_type('nuclides', nuclides, dict, str) - materials = cls._consolidate_nuclides_to_material(nuclides, volume) + materials = cls._consolidate_nuclides_to_material(nuclides, nuc_units, volume) return cls(materials, micro_xs, chain_file, @@ -205,14 +284,20 @@ class FluxDepletionOperator(OpenMCOperator): @staticmethod - def _consolidate_nuclides_to_material(nuclides, volume): + def _consolidate_nuclides_to_material(nuclides, nuc_units, volume): """Puts nuclide list into an openmc.Materials object. """ openmc.reset_auto_ids() mat = openmc.Material() - for nuc, conc in nuclides.items(): - mat.add_nuclide(nuc, conc * 1e-24) # convert to at/b-cm + if nuc_units == 'atom/b-cm': + for nuc, conc in nuclides.items(): + mat.add_nuclide(nuc, conc) + elif nuc_units == 'atom/cm3': + for nuc, conc in nuclides.items(): + mat.add_nuclide(nuc, conc * 1e-24) # convert to at/b-cm + else: + raise ValueError(f"Unit '{nuc_units}' is invalid.") mat.volume = volume mat.depletable = True @@ -273,13 +358,12 @@ class FluxDepletionOperator(OpenMCOperator): mat_index : int Material index - """ + """ volume = self._op.number.get_mat_volume(mat_index) - densities = np.empty(np.shape(fission_rates)) - for i_nuc in self.nuc_ind_map: - nuc = self.nuc_ind_map[i_nuc] + densities = np.empty_like(fission_rates) + for i_nuc, nuc in self.nuc_ind_map.items(): densities[i_nuc] = self._op.number.get_atom_density(mat_index, nuc) - fission_rates = fission_rates * volume * densities + fission_rates *= volume * densities super().update(fission_rates) @@ -294,10 +378,6 @@ class FluxDepletionOperator(OpenMCOperator): Parameters ---------- - n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` - n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` op : openmc.deplete.FluxDepletionOperator Reference to the object encapsulate _FluxDepletionRateHelper. We pass this so we don't have to duplicate the ``number`` object. @@ -312,9 +392,9 @@ class FluxDepletionOperator(OpenMCOperator): """ - def __init__(self, n_nuc, n_react, op): - super().__init__(n_nuc, n_react) + def __init__(self, op): rates = op.reaction_rates + super().__init__(rates.n_nuc, rates.n_react) self.nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} self.rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} @@ -349,7 +429,7 @@ class FluxDepletionOperator(OpenMCOperator): return self._results_cache def _get_helper_classes(self, helper_kwargs): - """Get helper classes for calculating reation rates and fission yields + """Get helper classes for calculating reaction rates and fission yields Parameters ---------- @@ -359,19 +439,16 @@ class FluxDepletionOperator(OpenMCOperator): """ normalization_mode = helper_kwargs['normalization_mode'] - fission_yield_opts = helper_kwargs.get('fission_yield_opts', {}) + fission_yield_opts = helper_kwargs['fission_yield_opts'] - self._rate_helper = self._FluxDepletionRateHelper( - self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) - if normalization_mode == "constant-power": + self._rate_helper = self._FluxDepletionRateHelper(self) + if normalization_mode == "fission-q": self._normalization_helper = self._FluxDepletionNormalizationHelper(self) else: self._normalization_helper = SourceRateHelper() # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper - if fission_yield_opts is None: - fission_yield_opts = {} self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) @@ -395,7 +472,7 @@ class FluxDepletionOperator(OpenMCOperator): vec : list of numpy.ndarray Total atoms to be used in function. source_rate : float - Power in [W] or source rate in [neutron/sec] + Power in [W] or flux in [neut/s-cm^2] Returns ------- @@ -444,11 +521,11 @@ class FluxDepletionOperator(OpenMCOperator): print(f'WARNING: nuclide {nuc} in material' f'{mat} is negative (density = {val}' - ' at/barn-cm)') + ' atom/b-cm)') number_i[mat, nuc] = 0.0 @staticmethod - def create_micro_xs_from_data_array(nuclides, reactions, data, units='barn'): + def create_micro_xs_from_data_array(nuclides, reactions, data): """ Creates a ``micro_xs`` parameter from a dictionary. @@ -458,12 +535,10 @@ class FluxDepletionOperator(OpenMCOperator): List of nuclide symbols for that have data for at least one reaction. reactions : list of str - List of reactions. All reactions must match those in ``chain.REACTONS`` + List of reactions. All reactions must match those in ``chain.REACTIONS`` data : ndarray of floats - Array containing one-group microscopic cross section information for each - nuclide and reaction. - units : {'barn', 'cm^2'}, optional - Units of cross section values in ``data`` array. Defaults to ``barn``. + Array containing one-group microscopic cross section values, in + [barn], for each nuclide and reaction. Returns ------- @@ -483,8 +558,7 @@ class FluxDepletionOperator(OpenMCOperator): nuclides, reactions, data) # Convert to cm^2 - if units == 'barn': - data *= 1e-24 + data *= 1e-24 return pd.DataFrame(index=nuclides, columns=reactions, data=data) @@ -497,9 +571,7 @@ class FluxDepletionOperator(OpenMCOperator): ---------- csv_file : str Relative path to csv-file containing microscopic cross section - data. - units : {'barn', 'cm^2'}, optional - Units of cross section values in the ``.csv`` file array. Defaults to ``barn``. + data. Cross section values should be in [barn]. Returns ------- @@ -514,8 +586,7 @@ class FluxDepletionOperator(OpenMCOperator): list(micro_xs.columns), micro_xs.to_numpy()) - if units == 'barn': - micro_xs *= 1e-24 + micro_xs *= 1e-24 return micro_xs @@ -528,67 +599,3 @@ class FluxDepletionOperator(OpenMCOperator): for reaction in reactions: check_value('reactions', reaction, _valid_rxns) - - @staticmethod - def generate_1g_cross_sections(model, reaction_domain, reactions=['(n,gamma)', '(n,2n)', '(n,p)', '(n,a)', '(n,3n)', '(n,4n)', 'fission'], energy_bounds=(0, 20e6), write_to_csv=True, filename='micro_xs.csv'): - """Helper function to generate a one-group cross-section dataframe - using OpenMC. Note that the ``openmc`` C executable must be compiled. - - Parameters - ---------- - model : openmc.model.Model - OpenMC model object. Must contain geometry, materials, and settings. - reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain in which to tally reaction rates. - reactions : list of str, optional - Reaction names to tally - energy_bound : 2-tuple of float, optional - Bounds for the energy group. - write_to_csv : bool, optional - Option to write the DataFrame to a `.csv` file. If `False`, - returns the dataframe object. - filename : str - Name for csv file. Only applicable if ``write_to_csv == True`` - - Returns - ------- - None or pandas.DataFrame - - """ - groups = EnergyGroups() - groups.group_edges = np.array(list(energy_bounds)) - - # Set up the reaction tallies - tallies = openmc.Tallies() - xs = dict() - for rxn in reactions: - if rxn == 'fission': - xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) - else: - xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) - tallies += xs[rxn].tallies.values() - - model.tallies = tallies - statepoint_path = model.run() - - sp = openmc.StatePoint(statepoint_path) - - for rxn in xs: - xs[rxn].load_from_statepoint(sp) - - sp.close() - - # Build the DataFrame - micro_xs = pd.DataFrame() - for rxn in xs: - df = xs[rxn].get_pandas_dataframe(xs_type='micro') - df.index = df['nuclide'] - df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) - df.rename({'mean':rxn}, axis=1, inplace=True) - micro_xs = pd.concat([micro_xs, df], axis=1) - - if write_to_csv: - micro_xs.to_csv(filename) - return None - else: - return micro_xs diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 0aaa3b08a..7b863b69a 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -612,7 +612,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): Default: 0.0253 [eV] fast_energy : float, optional Energy of yield data corresponding to fast yields. - Default: 500 [kev] + Default: 500 [KeV] Attributes ---------- @@ -634,7 +634,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): Array of fission rate fractions with shape ``(n_mats, 2, n_nucs)``. ``results[:, 0]`` corresponds to the fraction of all fissions - that occured below ``cutoff``. The number + that occurred below ``cutoff``. The number of materials in the first axis corresponds to the number of materials burned by the :class:`openmc.deplete.Operator` @@ -790,7 +790,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): class AveragedFissionYieldHelper(TalliedFissionYieldHelper): r"""Class that computes fission yields based on average fission energy - Computes average energy at which fission events occured with + Computes average energy at which fission events occurred with .. math:: @@ -908,7 +908,7 @@ class AveragedFissionYieldHelper(TalliedFissionYieldHelper): Use the computed average energy of fission events to determine fission yields. If average energy is between two sets of yields, linearly - interpolate bewteen the two. + interpolate between the two. Otherwise take the closet set of yields. Parameters diff --git a/openmc/deplete/integrators.py b/openmc/deplete/integrators.py index c19ef076a..74a3cebdb 100644 --- a/openmc/deplete/integrators.py +++ b/openmc/deplete/integrators.py @@ -103,7 +103,7 @@ class CECMIntegrator(Integrator): op_results : list of openmc.deplete.OperatorResult Eigenvalue and reaction rates from transport simulations """ - # deplete across first half of inteval + # deplete across first half of interval time0, x_middle = self._timed_deplete(conc, rates, dt / 2) res_middle = self.operator(x_middle, source_rate) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index aafa1adf9..7c0bb6678 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -90,7 +90,6 @@ class OpenMCOperator(TransportOperator): cross_sections : str or pandas.DataFrame Path to continuous energy cross section library, or object containing one-group cross-sections. - dilute_initial : float Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay @@ -527,7 +526,9 @@ class OpenMCOperator(TransportOperator): # Accumulate energy from fission if fission_ind is not None: - self._normalization_helper.update(tally_rates[:, fission_ind], mat_index=mat_index) + self._normalization_helper.update( + tally_rates[:, fission_ind], + mat_index=mat_index) # Divide by total number and store rates[i] = self._rate_helper.divide_by_adens(number) diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 61573832c..db4e80b19 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -225,7 +225,10 @@ class Operator(OpenMCOperator): self.cleanup_when_done = True - helper_kwargs = dict() + if reaction_rate_opts is None: + reaction_rate_opts = {} + if fission_yield_opts is None: + fission_yield_opts = {} helper_kwargs = { 'reaction_rate_mode': reaction_rate_mode, 'normalization_mode': normalization_mode, @@ -329,17 +332,14 @@ class Operator(OpenMCOperator): reaction_rate_mode = helper_kwargs['reaction_rate_mode'] normalization_mode = helper_kwargs['normalization_mode'] fission_yield_mode = helper_kwargs['fission_yield_mode'] - reaction_rate_opts = helper_kwargs.get('reaction_rate_opts', {}) - fission_yield_opts = helper_kwargs.get('fission_yield_opts', {}) + reaction_rate_opts = helper_kwargs['reaction_rate_opts'] + fission_yield_opts = helper_kwargs['fission_yield_opts'] # Get classes to assist working with tallies if reaction_rate_mode == "direct": self._rate_helper = DirectReactionRateHelper( self.reaction_rates.n_nuc, self.reaction_rates.n_react) elif reaction_rate_mode == "flux": - if reaction_rate_opts is None: - reaction_rate_opts = {} - # Ensure energy group boundaries were specified if 'energies' not in reaction_rate_opts: raise ValueError( @@ -365,8 +365,6 @@ class Operator(OpenMCOperator): # Select and create fission yield helper fission_helper = self._fission_helpers[fission_yield_mode] - if fission_yield_opts is None: - fission_yield_opts = {} self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) @@ -489,7 +487,7 @@ class Operator(OpenMCOperator): print(f'WARNING: nuclide {nuc} in material' f'{mat} is negative (density = {val}' - ' at/barn-cm)') + ' atom/b-cm)') number_i[mat, nuc] = 0.0 diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 9ae0f84f4..38d4aaf2e 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -3,8 +3,8 @@ from math import floor import shutil from pathlib import Path - from difflib import unified_diff + import numpy as np import pytest import openmc @@ -12,7 +12,6 @@ from openmc.data import JOULE_PER_EV import openmc.deplete from openmc.deplete import FluxDepletionOperator - from tests.regression_tests import config @@ -22,7 +21,7 @@ def fuel(): fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) fuel.add_element("O", 2) fuel.set_density("g/cc", 10.4) - fuel.depletable=True + fuel.depletable = True fuel.volume = np.pi * 0.42 ** 2 @@ -30,14 +29,14 @@ def fuel(): @pytest.mark.parametrize("multiproc, from_nuclides, normalization_mode, power, flux", [ - (True, True,'constant-flux', None, 1164719970082145.0), - (False, True, 'constant-flux', None, 1164719970082145.0), - (True, True, 'constant-power', 174, None), - (False, True, 'constant-power', 174, None), - (True, False,'constant-flux', None, 1164719970082145.0), - (False, False, 'constant-flux', None, 1164719970082145.0), - (True, False, 'constant-power', 174, None), - (False, False, 'constant-power', 174, None)]) + (True, True,'source-rate', None, 1164719970082145.0), + (False, True, 'source-rate', None, 1164719970082145.0), + (True, True, 'fission-q', 174, None), + (False, True, 'fission-q', 174, None), + (True, False,'source-rate', None, 1164719970082145.0), + (False, False, 'source-rate', None, 1164719970082145.0), + (True, False, 'fission-q', 174, None), + (False, False, 'fission-q', 174, None)]) def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclides, normalization_mode, power, flux): """Transport free system test suite. @@ -53,10 +52,10 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide if from_nuclides: nuclides = {} for nuc, dens in fuel.get_nuclide_atom_densities().items(): - nuclides[nuc] = dens * 1e24 + nuclides[nuc] = dens op = FluxDepletionOperator.from_nuclides( - fuel.volume, nuclides, micro_xs, chain_file, normalization_mode=normalization_mode) + fuel.volume, nuclides,'atom/b-cm', micro_xs, chain_file, normalization_mode=normalization_mode) else: op = FluxDepletionOperator(openmc.Materials([fuel]), micro_xs, chain_file, normalization_mode=normalization_mode) @@ -67,14 +66,14 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide # Perform simulation using the predictor algorithm openmc.deplete.pool.USE_MULTIPROCESSING = multiproc openmc.deplete.PredictorIntegrator( - op, dt, power=power, flux=flux, timestep_units='d').integrate() + op, dt, power=power, source_rates=flux, timestep_units='d').integrate() # Get path to test and reference results path_test = op.output_dir / 'depletion_results.h5' if flux is not None: - ref_path = 'test_reference_constant_flux.h5' + ref_path = 'test_reference_source_rate.h5' else: - ref_path = 'test_reference_constant_power.h5' + ref_path = 'test_reference_fission_q.h5' path_reference = Path(__file__).with_name(ref_path) # Load the reference/test results diff --git a/tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 b/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 similarity index 99% rename from tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 rename to tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 index c6e1a40808c135aafe1065b2cc95357c3fede0a2..6c1b3de849e1a8792b9ce9398c7e2e41ae410b5e 100644 GIT binary patch delta 195 zcmV;!06hQbmICOO0*|BlmMJyliu@d`x4IkRRgf8^dYK3F&`gw7m^Ie>Y) z5+(faJ(G}%EPtS$v_CI|yv+VQEJGD17m5@ghV(jJx%GE)j5EL0c^iFUp>2- xffA~M!#OE`I{yLRG(K~X!@6#6i8bXv~IbXv-2A#e3j8DX_-aLQBZdIMygbzjc?Tl_5w39Y6vgdQWX@7{t%6>_Ql5>{M zM!Sp4@}-uy9=5xcmArDD`bFoxhwbgm|Ju522o5;9;A)GD>qK^oDIr%a??D|92z7uv b)B(Xz2gpDjz`(#Td2*NFWS?#c7LYpt(gRg~ diff --git a/tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 b/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 similarity index 100% rename from tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 rename to tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 diff --git a/tests/unit_tests/test_deplete_flux_operator.py b/tests/unit_tests/test_deplete_flux_operator.py index 9019d123d..8f17538ed 100644 --- a/tests/unit_tests/test_deplete_flux_operator.py +++ b/tests/unit_tests/test_deplete_flux_operator.py @@ -71,7 +71,7 @@ def test_operator_init(): 'O17': 1.7588724018066158e+19} micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) nuclide_flux_operator = FluxDepletionOperator.from_nuclides( - volume, nuclides, micro_xs, CHAIN_PATH) + volume, nuclides, 'atom/cm3', micro_xs, CHAIN_PATH) fuel = Material(name="uo2") fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) From 9ae0c6bd55e045681b1cef213fd6081f9b694534 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Thu, 28 Jul 2022 08:50:48 -0500 Subject: [PATCH 0689/2654] add `add_elements` Co-authored-by: Jonathan Shimwell --- openmc/material.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openmc/material.py b/openmc/material.py index cd181539c..40b495883 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -417,6 +417,18 @@ class Material(IDManagerMixin): for nuclide, (percent, percent_type) in nuclides.items(): self.add_nuclide(nuclide, percent, percent_type) + def add_elements(self, elements: dict): + """ Add multiple elements to a material + + Parameters + ---------- + elements : dict of str to tuple + Dictionary mapping element names to a tuple containing their + atom or weight percent. + """ + + for element, (percent, percent_type) in elements.items(): + self.add_element(element, percent, percent_type) def remove_nuclide(self, nuclide: str): """Remove a nuclide from the material From 3374ec12f5a305e83b4d853208bd1912be03c6b5 Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:39:56 -0500 Subject: [PATCH 0690/2654] Update src/mesh.cpp grammar Co-authored-by: Patrick Shriwise --- src/mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index dfa443b7f..a8d57eef1 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2369,7 +2369,7 @@ void LibMesh::initialize() libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); } // if OpenMC is managing the libMesh::MeshBase instance, prepare the mesh. - // Otherwise assume that it is prepared by it's owning application + // Otherwise assume that it is prepared by its owning application if (unique_m_) { m_->prepare_for_use(); } From 623658870d3a51320465aabed254acd64c7671f6 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 28 Jul 2022 10:58:08 -0500 Subject: [PATCH 0691/2654] merged add_nuclides and add_elements into one function --- openmc/material.py | 45 ++++++++++++++---------- tests/unit_tests/test_material.py | 57 +++++++++++++++++-------------- 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 40b495883..1463c7fa1 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -403,32 +403,41 @@ class Material(IDManagerMixin): self._nuclides.append(NuclideTuple(nuclide, percent, percent_type)) - def add_nuclides(self, nuclides: dict): - """ Add multiple nuclides to a material + def add_elements_or_nuclides(self, components: dict): + """ Add multiple elements or nuclides to a material Parameters ---------- - nuclides : dict of str to tuple - Dictionary mapping nuclide names to a tuple containing their - atom or weight percent. + components : dict of str to tuple + Dictionary mapping element or nuclide names to a tuple containing + their atom or weight percent, as well as any other arguments. + + Examples + -------- + >> mat = openmc.Material() + >> components = {'Li': (1.0, {'enrichment': 60.0, 'enrichment_target': 'Li7'}), + 'Fl': 1.0, + 'Be6': (0.5, 'wo')} + >> mat.add_elements_or_nuclides(components) """ - for nuclide, (percent, percent_type) in nuclides.items(): - self.add_nuclide(nuclide, percent, percent_type) + for component, args in components.items(): + cv.check_type('component', component, str) + percent_type = 'ao' + if isinstance(args, float): + args = (args,) - def add_elements(self, elements: dict): - """ Add multiple elements to a material + ## check if nuclide + if str.isdigit(component[-1]): + self.add_nuclide(component, *args) + else: # is element + kwargs = {} + if isinstance(args[-1], dict): + kwargs = args[-1] + args = args[:-1] + self.add_element(component, *args, **kwargs) - Parameters - ---------- - elements : dict of str to tuple - Dictionary mapping element names to a tuple containing their - atom or weight percent. - """ - - for element, (percent, percent_type) in elements.items(): - self.add_element(element, percent, percent_type) def remove_nuclide(self, nuclide: str): """Remove a nuclide from the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 8dde30485..69ca87f2e 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -25,31 +25,39 @@ def test_add_nuclide(): with pytest.raises(ValueError): m.add_nuclide('H1', 1.0, 'oa') -def test_add_nuclides(): - """Test adding multipe nuclides at once""" +def test_add_elements_or_nuclides(): + """Test adding multipe elements or nuclides at once""" m = openmc.Material() - nuclides = {'H1': (2.0, 'ao'), - 'O16': (1.0, 'wo')} - m.add_nuclides(nuclides) - - # wt-% - m = openmc.Material() - nuclides = {'H1': (2.0, 'wo'), - 'O16': (1.0, 'wo')} - m.add_nuclides(nuclides) - - # mixed - m = openmc.Material() - nuclides = {'H1': (2.0, 'ao'), - 'O16': (1.0, 'wo')} - m.add_nuclides(nuclides) - - with pytest.raises(TypeError): - m.add_nuclides({'H1': ('1.0', 'ao')}) - with pytest.raises(TypeError): - m.add_nuclides({1.0: ('H1', 'wo')}) + components = {'H1': 2.0, + 'O16': (1.0, 'wo'), + 'Zr': 1.0, + 'O': (1.0, 'wo'), + 'U': (1.0, {'enrichment': 4.5}), + 'Li': (1.0, 'ao', {'enrichment': 60.0, 'enrichment_target': 'Li7'}), + 'H': (1.0, 'ao', {'enrichment': 50.0, 'enrichment_target': 'H2', 'enrichment_type': 'wo'})} + m.add_elements_or_nuclides(components) with pytest.raises(ValueError): - m.add_nuclides({'H1': (1.0, 'oa')}) + m.add_elements_or_nuclides({'U': (1.0, 'ao', {'enrichment': 100.0})}) + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'Pu': (1.0, 'ao', {'enrichment': 3.0})}) + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'U': (1.0, 'ao', {'enrichment': 70.0, 'enrichment_target': 'U235'})}) + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'He': (1.0, 'ao', {'enrichment': 17.0, 'enrichment_target': 'He6'})}) + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'li': (1.0, 'ao')}) # should fail as 1st char is lowercase + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'LI': (1.0, 'ao')}) # should fail as 2nd char is uppercase + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'Xx': (1.0, 'ao')}) # should fail as Xx is not an element + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'n': (1.0, 'ao')}) # check to avoid n for neutron being accepted + with pytest.raises(TypeError): + m.add_elements_or_nuclides({'H1': ('1.0', 'ao')}) + with pytest.raises(TypeError): + m.add_elements_or_nuclides({1.0: ('H1', 'wo')}) + with pytest.raises(ValueError): + m.add_elements_or_nuclides({'H1': (1.0, 'oa')}) def test_remove_nuclide(): @@ -75,7 +83,7 @@ def test_remove_elements(): assert m.nuclides[0].percent == 1.0 -def test_elements(): +def test_add_element(): """Test adding elements.""" m = openmc.Material() m.add_element('Zr', 1.0) @@ -100,7 +108,6 @@ def test_elements(): with pytest.raises(ValueError): m.add_element('n', 1.0) # check to avoid n for neutron being accepted - def test_elements_by_name(): """Test adding elements by name""" m = openmc.Material() From 8a5df89ea5c899579deaa806f151519db2472aef Mon Sep 17 00:00:00 2001 From: myerspat Date: Thu, 28 Jul 2022 12:22:28 -0500 Subject: [PATCH 0692/2654] enforced precedence if intersections proceed unions without parenthesis --- include/openmc/cell.h | 2 + src/cell.cpp | 135 +++++++++++++++++++++++++++++++++--------- src/geometry_aux.cpp | 2 +- src/universe.cpp | 4 +- 4 files changed, 111 insertions(+), 32 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 887901707..e812fc88f 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -202,6 +202,8 @@ public: //! Definition of spatial region as Boolean expression of half-spaces vector region_; + //! Revised infix notation with no complements + vector region_no_complements_; bool simple_; //!< Does the region contain only intersections? //! \brief Neighboring cells in the same universe. diff --git a/src/cell.cpp b/src/cell.cpp index 943722f35..633cf1bc0 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -107,6 +107,66 @@ vector tokenize(const std::string region_spec) return tokens; } + +//============================================================================== +//! Add precedence for infix cell finding so intersections have higher +//! precedence than unions using parenthesis. +//============================================================================== + +std::vector::iterator +add_parenthesis(std::vector::iterator start, + std::vector &infix) { + // Add left parenthesis + start = infix.insert(start, OP_LEFT_PAREN); + start = start + 2; + + // Initialize return iterator + std::vector::iterator return_iterator = infix.end() - 1; + + // Add right parenthesis + // While the start iterator is within the bounds of infix + while (start < infix.end()) { + start++; + + // If we find a union or right parenthesis not wrapped by + // left and right parenthesis then place a right parenthesis, + // If we find a wrapped region return an iterator pointing to + // that wrapped region and continue looking to place a + // right parenthesis + if (*start == OP_UNION || *start == OP_RIGHT_PAREN) { + start = infix.insert(start, OP_RIGHT_PAREN); + return start - 1; + + } else if (*start == OP_LEFT_PAREN) { + return_iterator = start; + start = std::find(start, infix.end(), OP_RIGHT_PAREN); + } + } + + // If we get here a right parenthesis hasn't been placed, + // return iterator + infix.push_back(OP_RIGHT_PAREN); + return return_iterator; +} + +void add_precedence(std::vector &infix) { + int32_t current_op = 0; + + for (auto it = infix.begin(); it != infix.end(); it++) { + int32_t token = *it; + + if (token == OP_UNION && current_op == 0) { + current_op = OP_UNION; + + } else if (current_op == OP_UNION && token == OP_INTERSECTION) { + it = add_parenthesis(it - 1, infix); + + } else if (token > OP_COMPLEMENT) { + current_op = 0; + } + } +} + //============================================================================== //! Convert infix region specification to Reverse Polish Notation (RPN) //! @@ -498,9 +558,7 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } // Get a tokenized representation of the region specification - // and apply De Morgan's laws to remove complements. region_ = tokenize(region_spec); - remove_complement_ops(region_); region_.shrink_to_fit(); // Convert user IDs to surface indices. @@ -516,9 +574,13 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } } + // Remove complement operators using De Morgan's law + region_no_complements_ = region_; + remove_complement_ops(region_no_complements_); + // Check if this is a simple cell. simple_ = true; - for (int32_t token : region_) { + for (int32_t token : region_no_complements_) { if (token == OP_UNION) { simple_ = false; break; @@ -527,13 +589,17 @@ CSGCell::CSGCell(pugi::xml_node cell_node) // If this cell is simple, remove all the superfluous operator tokens. if (simple_) { - for (auto it = region_.begin(); it != region_.end(); it++) { + for (auto it = region_no_complements_.begin(); + it != region_no_complements_.end(); it++) { if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { - region_.erase(it); + region_no_complements_.erase(it); } } + } else { + // Ensure intersections have precedence over unions + add_precedence(region_no_complements_); } - region_.shrink_to_fit(); + region_no_complements_.shrink_to_fit(); // Read the translation vector. if (check_for_node(cell_node, "translation")) { @@ -577,7 +643,7 @@ std::pair CSGCell::distance( double min_dist {INFTY}; int32_t i_surf {std::numeric_limits::max()}; - for (int32_t token : region_) { + for (int32_t token : region_no_complements_) { // Ignore this token if it corresponds to an operator rather than a region. if (token >= OP_UNION) continue; @@ -632,7 +698,7 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const BoundingBox CSGCell::bounding_box_simple() const { BoundingBox bbox; - for (int32_t token : region_) { + for (int32_t token : region_no_complements_) { bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); } return bbox; @@ -735,14 +801,15 @@ BoundingBox CSGCell::bounding_box_complex(vector rpn) BoundingBox CSGCell::bounding_box() const { - return simple_ ? bounding_box_simple() : bounding_box_complex(region_); + return simple_ ? bounding_box_simple() + : bounding_box_complex(region_no_complements_); } //============================================================================== bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const { - for (int32_t token : region_) { + for (int32_t token : region_no_complements_) { // Assume that no tokens are operators. Evaluate the sense of particle with // respect to the surface and see if the token matches the sense. If the // particle's surface attribute is set and matches the token, that @@ -767,13 +834,14 @@ bool CSGCell::contains_complex( Position r, Direction u, int32_t on_surface) const { bool in_cell = true; - + // For each token - for (auto it = region_.begin(); it != region_.end(); it++) { + for (auto it = region_no_complements_.begin(); + it != region_no_complements_.end(); it++) { int32_t token = *it; // If the token is a surface evaluate the sense - // If the token is a union or intersection check to + // If the token is a union or intersection check to // short circuit if (token < OP_UNION) { if (token == on_surface) { @@ -794,14 +862,21 @@ bool CSGCell::contains_complex( int32_t next_token = *it; // If the next token is a left parenthesis skip until - // the next right parenthesis, if the token is a right - // parenthesis leave short circuiting - if (next_token == OP_LEFT_PAREN) { - it = std::find(it, region_.end() - 1, OP_RIGHT_PAREN); - } else if (next_token == OP_RIGHT_PAREN) { - break; + // the next right parenthesis, if the token is a right + // parenthesis leave short circuiting, if we go from + // intersections to union operators without parenthesis + // break shortc circuiting one behind the union + if (next_token >= OP_UNION) { + if (next_token == OP_LEFT_PAREN) { + it = std::find(it, region_no_complements_.end() - 1, OP_RIGHT_PAREN); + } else if (token == OP_RIGHT_PAREN) { + break; + } else if (token - next_token == 1) { + it--; + break; + } } - } while (it < region_.end() - 1); + } while (it < region_no_complements_.end() - 1); } } return in_cell; @@ -1108,7 +1183,8 @@ struct ParentCellStack { }; vector Cell::find_parent_cells( - int32_t instance, const Position& r) const { + int32_t instance, const Position& r) const +{ // create a temporary particle Particle dummy_particle {}; @@ -1118,8 +1194,8 @@ vector Cell::find_parent_cells( return find_parent_cells(instance, dummy_particle); } -vector Cell::find_parent_cells( - int32_t instance, Particle& p) const { +vector Cell::find_parent_cells(int32_t instance, Particle& p) const +{ // look up the particle's location exhaustive_find_cell(p); const auto& coords = p.coord(); @@ -1130,7 +1206,8 @@ vector Cell::find_parent_cells( for (auto it = coords.begin(); it != coords.end(); it++) { const auto& coord = *it; const auto& cell = model::cells[coord.cell]; - // if the cell at this level matches the current cell, stop adding to the stack + // if the cell at this level matches the current cell, stop adding to the + // stack if (coord.cell == model::cell_map[this->id_]) { cell_found = true; break; @@ -1141,7 +1218,8 @@ vector Cell::find_parent_cells( int lattice_idx = C_NONE; if (cell->type_ == Fill::LATTICE) { const auto& next_coord = *(it + 1); - lattice_idx = model::lattices[next_coord.lattice]->get_flat_index(next_coord.lattice_i); + lattice_idx = model::lattices[next_coord.lattice]->get_flat_index( + next_coord.lattice_i); } stack.push(coord.universe, {coord.cell, lattice_idx}); } @@ -1149,7 +1227,8 @@ vector Cell::find_parent_cells( // if this loop finished because the cell was found and // the instance matches the one requested in the call // we have the correct path and can return the stack - if (cell_found && stack.compute_instance(this->distribcell_index_) == instance) { + if (cell_found && + stack.compute_instance(this->distribcell_index_) == instance) { return stack.parent_cells(); } @@ -1157,9 +1236,7 @@ vector Cell::find_parent_cells( return exhaustive_find_parent_cells(instance); } - -vector Cell::exhaustive_find_parent_cells( - int32_t instance) const +vector Cell::exhaustive_find_parent_cells(int32_t instance) const { ParentCellStack stack; // start with this cell's universe diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index c3458d469..881af15b7 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -154,7 +154,7 @@ void partition_universes() // Collect the set of surfaces in this universe. std::unordered_set surf_inds; for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_no_complements_) { if (token < OP_UNION) surf_inds.insert(std::abs(token) - 1); } diff --git a/src/universe.cpp b/src/universe.cpp index 873d03bb7..dc6f751c2 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -98,7 +98,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find all of the z-planes in this universe. A set is used here for the // O(log(n)) insertions that will ensure entries are not repeated. for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_no_complements_) { if (token < OP_UNION) { auto i_surf = std::abs(token) - 1; const auto* surf = model::surfaces[i_surf].get(); @@ -125,7 +125,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find the tokens for bounding z-planes. int32_t lower_token = 0, upper_token = 0; double min_z, max_z; - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_no_complements_) { if (token < OP_UNION) { const auto* surf = model::surfaces[std::abs(token) - 1].get(); if (const auto* zplane = dynamic_cast(surf)) { From 9317724a5ba3ff2b6a8ea15eb34a1e3628828c41 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 28 Jul 2022 16:03:42 -0500 Subject: [PATCH 0693/2654] fix examples formatting --- openmc/material.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 1463c7fa1..8fee0585c 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -414,11 +414,11 @@ class Material(IDManagerMixin): Examples -------- - >> mat = openmc.Material() - >> components = {'Li': (1.0, {'enrichment': 60.0, 'enrichment_target': 'Li7'}), - 'Fl': 1.0, - 'Be6': (0.5, 'wo')} - >> mat.add_elements_or_nuclides(components) + >>> mat = openmc.Material() + >>> components = {'Li': (1.0, {'enrichment': 60.0, 'enrichment_target': 'Li7'}), + >>> 'Fl': 1.0, + >>> 'Be6': (0.5, 'wo')} + >>> mat.add_elements_or_nuclides(components) """ From 6351b49ea2acf13f90914ef756c6fbf89a296d0a Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 28 Jul 2022 16:06:19 -0500 Subject: [PATCH 0694/2654] add reference to add_elements_or_nuclides in the docstring for Material --- openmc/material.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index 8fee0585c..14bec12f3 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -34,7 +34,9 @@ class Material(IDManagerMixin): To create a material, one should create an instance of this class, add nuclides or elements with :meth:`Material.add_nuclide` or :meth:`Material.add_element`, respectively, and set the total material - density with :meth:`Material.set_density()`. The material can then be + density with :meth:`Material.set_density()`. Alternatively, you can + use :meth:`Material.add_elements_or_nuclides()` to pass a dictionary + containing all the component information. The material can then be assigned to a cell using the :attr:`Cell.fill` attribute. Parameters From b2fed3c3cec856b85f7fb75aa8f4a20e1e974a84 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Jul 2022 17:06:13 -0500 Subject: [PATCH 0695/2654] Fix bugs in Discrete, Tabular, and Mixture sample methods --- openmc/stats/univariate.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 66c6e5f06..c19f45365 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -139,7 +139,8 @@ class Discrete(Univariate): def sample(self, n_samples=1, seed=None): np.random.seed(seed) - return np.random.choice(self.x, n_samples, p=self.p) + p = self.p / self.p.sum() + return np.random.choice(self.x, n_samples, p=p) def normalize(self): """Normalize the probabilities stored on the distribution""" @@ -944,10 +945,11 @@ class Tabular(Univariate): 'linear-linear interpolation') np.random.seed(seed) xi = np.random.rand(n_samples) - cdf = self.cdf() - cdf /= cdf.max() + # always use normalized probabilities when sampling + cdf = self.cdf() p = self.p / cdf.max() + cdf /= cdf.max() # get CDF bins that are above the # sampled values @@ -962,7 +964,7 @@ class Tabular(Univariate): # the random number is less than the next cdf # entry x_i = self.x[cdf_idx] - p_i = self.p[cdf_idx] + p_i = p[cdf_idx] if self.interpolation == 'histogram': # mask where probability is greater than zero @@ -980,7 +982,7 @@ class Tabular(Univariate): # get variable and probability values for the # next entry x_i1 = self.x[cdf_idx + 1] - p_i1 = self.p[cdf_idx + 1] + p_i1 = p[cdf_idx + 1] # compute slope between entries m = (p_i1 - p_i) / (x_i1 - x_i) # set values for zero slope @@ -1166,9 +1168,10 @@ class Mixture(Univariate): def sample(self, n_samples=1, seed=None): np.random.seed(seed) - idx = np.random.choice(self.distribution, n_samples, p=self.probability) + idx = np.random.choice(range(len(self.distribution)), + n_samples, p=self.probability) - out = np.zeros_like(idx) + out = np.empty_like(idx, dtype=float) for i in np.unique(idx): n_dist_samples = np.count_nonzero(idx == i) samples = self.distribution[i].sample(n_dist_samples) From cc7aa092be7b7a9eed9c9ddd85a9e1edb0a1f14b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Jul 2022 17:07:06 -0500 Subject: [PATCH 0696/2654] Address @eepeterson comments on #2135 --- openmc/stats/univariate.py | 8 ++-- tests/unit_tests/test_stats.py | 69 ++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index c19f45365..58b7c6172 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -1254,10 +1254,10 @@ def combine_distributions(dists, probs): """Combine distributions with specified probabilities This function can be used to combine multiple instances of - :class:`~openmc.stats.Discrete` and `~openmc.stats.Tabular` into a single - distribution. Multiple discrete distributions are merged into a single - distribution and the remainder of the distributions are put into a - :class:`~openmc.stats.Mixture` distribution. + :class:`~openmc.stats.Discrete` and `~openmc.stats.Tabular`. Multiple + discrete distributions are merged into a single distribution and the + remainder of the distributions are put into a :class:`~openmc.stats.Mixture` + distribution. .. versionadded:: 0.13.1 diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 404cecd13..1cfcf00c3 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -6,6 +6,12 @@ import openmc import openmc.stats +def assert_sample_mean(samples, expected_mean): + std_dev = samples.std() / np.sqrt(samples.size) + assert np.abs(expected_mean - samples.mean()) < 3*std_dev + + + def test_discrete(): x = [0.0, 1.0, 10.0] p = [0.3, 0.2, 0.5] @@ -33,13 +39,11 @@ def test_discrete(): d3 = openmc.stats.Discrete(vals, probs) - # sample discrete distribution + # sample discrete distribution and check that the mean of the samples is + # within 3 std. dev. of the expected mean n_samples = 1_000_000 samples = d3.sample(n_samples, seed=100) - # check that the mean of the samples is within 3 std. dev. - # of the expected mean - std_dev = samples.std() / np.sqrt(n_samples) - assert np.abs(exp_mean - samples.mean()) < 3*std_dev + assert_sample_mean(samples, exp_mean) def test_merge_discrete(): @@ -80,13 +84,12 @@ def test_uniform(): np.testing.assert_array_equal(t.p, [1/(b-a), 1/(b-a)]) assert t.interpolation == 'histogram' + # Sample distribution and check that the mean of the samples is within 3 + # std. dev. of the expected mean exp_mean = 0.5 * (a + b) n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - # check that the mean of the samples is within 3 std. dev. - # of the expected mean - std_dev = samples.std() / np.sqrt(n_samples) - assert np.abs(exp_mean - samples.mean()) < 3*std_dev + assert_sample_mean(samples, exp_mean) def test_powerlaw(): @@ -102,13 +105,11 @@ def test_powerlaw(): exp_mean = 100.0 * (n+1) / (n+2) - # sample power law distribution + # sample power law distribution and check that the mean of the samples is + # within 3 std. dev. of the expected mean n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - # check that the mean of the samples is within 3 std. dev. - # of the expected mean - std_dev = samples.std() / np.sqrt(n_samples) - assert np.abs(exp_mean - samples.mean()) < 3*std_dev + assert_sample_mean(samples, exp_mean) def test_maxwell(): @@ -122,21 +123,15 @@ def test_maxwell(): exp_mean = 3/2 * theta - # sample maxwell distribution + # sample maxwell distribution and check that the mean of the samples is + # within 3 std. dev. of the expected mean n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - # check that the mean of the samples is within 3 std. dev. - # of the expected mean - std_dev = samples.std() / np.sqrt(n_samples) - assert np.abs(exp_mean - samples.mean()) < 3*std_dev + assert_sample_mean(samples, exp_mean) # A second sample with a different seed samples_2 = d.sample(n_samples, seed=200) - # check that the mean of the samples is within 3 std. dev. - # of the expected mean - std_dev = samples_2.std() / np.sqrt(n_samples) - assert np.abs(exp_mean - samples_2.mean()) < 3*std_dev - + assert_sample_mean(samples_2, exp_mean) assert samples_2.mean() != samples.mean() @@ -156,13 +151,11 @@ def test_watt(): # https://doi.org/10.1016/j.physletb.2003.09.048 exp_mean = 3/2 * a + a**2 * b / 4 - # sample Watt distribution + # sample Watt distribution and check that the mean of the samples is within + # 3 std. dev. of the expected mean n_samples = 1_000_000 samples = d.sample(n_samples, seed=100) - # check that the mean of the samples is within 3 std. dev. - # of the expected mean - std_dev = samples.std() / np.sqrt(n_samples) - assert np.abs(exp_mean - samples.mean()) < 3*std_dev + assert_sample_mean(samples, exp_mean) def test_tabular(): @@ -228,6 +221,11 @@ def test_mixture(): assert mix.distribution == [d1, d2] assert len(mix) == 4 + # Sample and make sure sample mean is close to expected mean + n_samples = 1_000_000 + samples = mix.sample(n_samples) + assert_sample_mean(samples, (2.5 + 5.0)/2) + elem = mix.to_xml_element('distribution') d = openmc.stats.Mixture.from_xml_element(elem) @@ -427,3 +425,16 @@ def test_combine_distributions(): assert isinstance(mixed, openmc.stats.Mixture) assert len(mixed.distribution) == 2 assert len(mixed.probability) == 2 + + # Combine 1 discrete and 2 tabular -- the tabular distributions should + # combine to produce a uniform distribution with mean 0.5. The combined + # distribution should have a mean of 0.25. + t1 = openmc.stats.Tabular([0., 1.], [2.0, 0.0]) + t2 = openmc.stats.Tabular([0., 1.], [0.0, 2.0]) + d1 = openmc.stats.Discrete([0.0], [1.0]) + combined = openmc.stats.combine_distributions([t1, t2, d1], [0.25, 0.25, 0.5]) + + # Sample the combined distribution and make sure the sample mean is within + # uncertainty of the expected value + samples = combined.sample(10) + assert_sample_mean(samples, 0.25) From 3e827530baef93dabcfa99a7141bba4db9997660 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 28 Jul 2022 15:55:07 -0500 Subject: [PATCH 0697/2654] make changes from @paulromano's 3rd review - syntax fixes and adjustments - change name of FluxDepletionOperator to IndependentOperator - flux_operator.py -> independent_operator.py - new class, MicroXS, for creating (for now) one-group microscopic cross section DataFrames. This class takes the functionality that was previously in static functions in IndependentOperator - Associated changes to the test suite and online docs --- docs/source/pythonapi/deplete.rst | 5 +- docs/source/usersguide/depletion.rst | 64 +++-- openmc/deplete/__init__.py | 3 +- openmc/deplete/abc.py | 4 +- ...ux_operator.py => independent_operator.py} | 234 +++--------------- openmc/deplete/microxs.py | 178 +++++++++++++ openmc/deplete/openmc_operator.py | 8 +- openmc/deplete/operator.py | 4 +- .../deplete_no_transport/test.py | 18 +- tests/regression_tests/microxs/__init.py__ | 0 tests/regression_tests/microxs/test.py | 52 ++++ .../microxs/test_reference.csv | 7 + .../unit_tests/test_deplete_flux_operator.py | 83 ------- .../test_deplete_independent_operator.py | 36 +++ tests/unit_tests/test_deplete_microxs.py | 60 +++++ 15 files changed, 437 insertions(+), 319 deletions(-) rename openmc/deplete/{flux_operator.py => independent_operator.py} (67%) create mode 100644 openmc/deplete/microxs.py create mode 100644 tests/regression_tests/microxs/__init.py__ create mode 100644 tests/regression_tests/microxs/test.py create mode 100644 tests/regression_tests/microxs/test_reference.csv delete mode 100644 tests/unit_tests/test_deplete_flux_operator.py create mode 100644 tests/unit_tests/test_deplete_independent_operator.py create mode 100644 tests/unit_tests/test_deplete_microxs.py diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index cb9adfaaf..246cea59f 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -49,9 +49,9 @@ specific to OpenMC are available using the following classes: :template: mycallable.rst Operator - FluxDepletionOperator + IndependentOperator -The :class:`Operator` and :class:`FluxDepletionOperator` classes must also have +The :class:`Operator` and :class:`IndependentOperator` classes must also have some knowledge of how nuclides transmute and decay. This is handled by the :class:`Chain`. @@ -134,6 +134,7 @@ data, such as number densities and reaction rates for each material. :template: myclass.rst AtomNumber + MicroXS OperatorResult ReactionRates Results diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index cfb373e13..0bc2a5af9 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -97,7 +97,7 @@ Energy Deposition ----------------- The default energy deposition mode, ``"fission-q"``, instructs the -:class:`openmc.deplete.Operator` to normalize reaction rates using the product +:class:`~openmc.deplete.Operator` to normalize reaction rates using the product of fission reaction rates and fission Q values taken from the depletion chain. This approach does not consider indirect contributions to energy deposition, such as neutron heating and energy from secondary photons. In doing this, the @@ -113,7 +113,7 @@ should be, including indirect components. Some examples are provided below:: fission_q = {"U235": 202e+6} # energy in eV # create a Model object - model = openmc.Model(geometry, settings) + model = openmc.Model(geometry, settings) # create a modified chain and write it to a new file chain = openmc.deplete.Chain.from_xml("chain.xml", fission_q) @@ -133,7 +133,7 @@ to normalize reaction rates instead of using the fission reaction rates with:: normalization_mode="energy-deposition") These modified heating libraries can be generated by running the latest version -of :meth:`openmc.data.IncidentNeutron.from_njoy`, and will eventually be bundled +of :meth:`openmc.data.IncidentNeutron.from_njoy()`, and will eventually be bundled into the distributed libraries. Local Spectra and Repeated Materials @@ -188,31 +188,57 @@ Transport-independent depletion possible and likely in the near future. OpenMC supports running depletion calculations independent of the OpenMC -transport solver using the :class:`~openmc.deplete.FluxDepletionOperator` class. +transport solver using the :class:`~openmc.deplete.IndependentOperator` class. This class supports both constant-flux (``source-rate`` normalization) and constant-power depletion (``fission-q`` normalization). .. important:: - Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` class. Use the ``source_rates`` parameter when ``normalization_mode == source-rate``, and use ``power`` or ``power_density`` when ``normalization_mode == fission-q``. + Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` + class. Use the ``source_rates`` parameter when + ``normalization_mode == source-rate``, and use ``power`` or ``power_density`` + when ``normalization_mode == fission-q``. .. warning:: - The accuracy of results when using ``fission-q`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the dynamics of your particular scenario. + The accuracy of results when using ``fission-q`` is entirely dependent on + your depletion chain. Make sure it has sufficient data to resolve the + dynamics of your particular scenario. -This class has two ways to initialize it: the default constructor accepts an -:class:`openmc.Materials` object and one-group microscopic -cross sections as a :class:`pandas.DataFrame`, while the ``from_nuclides`` -method accepts a volume and dictionary of nuclide concentrations in place of -the :class:`openmc.Materials` object in addition to the other parameters. -The class includes helper functions to construct the dataframe from a csv file -or from data arrays:: +:class:`~openmc.deplete.IndependentOperator` class uses one-group microscopic cross sections to calculate reaction +rates. Users can generate one-group microscopic cross sections using the +:class:`~openmc.deplete.MicroXS` class:: + + import openmc + from openmc.deplete import MicroXS + + model = openmc.Model.from_xml() + + micro_xs = MicroXS.from_model(model, model.materials[0]) + + micro_xs.to_csv(micro_xs_path) + +:class:`~openmc.deplete.MicroXS` also includes functions to read in cross +section data directly from a ``.csv`` file or from data arrays:: + + micro_xs = MicroXS.from_csv(micro_xs_path) + + nuclides = ['U234', 'U235', 'U238'] + reactions = ['fission', '(n,gamma)'] + data = np.array([[0.1, 0.2], + [0.3, 0.4], + [0.01, 0.5]]) + micro_xs = MicroXS.from_array(nuclides, reactions, data) + +:class:`~openmc.deplete.IndependentOperator` has two ways to initialize it: +the default constructor accepts an :class:`openmc.Materials` object and +one-group microscopic cross sections as a :class:`~openmc.deplete.MicroXS` +object, while the :meth:`~openmc.deplete.IndependentOperator.from_nuclides` +method accepts a volume and dictionary of nuclide concentrations in place of the +:class:`openmc.Materials` object in addition to the other parameters:: - ... # load in the microscopic cross sections - micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_path) - flux = 1.16e15 - op = FluxDepletionOperator(materials, micro_xs, chain_file) + op = IndependentOperator(materials, micro_xs, chain_file) # alternate construtor nuclides = {'U234': 8.92e18, @@ -222,8 +248,8 @@ or from data arrays:: 'O16': 4.64e22, 'O17': 1.76e19} volume = 0.5 - op = FluxDepletionOperator.from_nuclides(volume, nuclides, 'atom/cm3', - micro_xs, flux, chain_file) + op = IndependentOperator.from_nuclides(volume, nuclides, micro_xs, + chain_file, nuc_units='atom/cm3') A user can then define an integrator class as they would for a coupled transport-depletion calculation and follow the same steps from there. diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py index deddf1100..12e4abe87 100644 --- a/openmc/deplete/__init__.py +++ b/openmc/deplete/__init__.py @@ -9,7 +9,8 @@ from .nuclide import * from .chain import * from .openmc_operator import * from .operator import * -from .flux_operator import * +from .independent_operator import * +from .microxs import * from .reaction_rates import * from .atom_number import * from .stepresult import * diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 90a353d93..cdbd1361a 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -526,7 +526,7 @@ class Integrator(ABC): initial heavy metal inventory to get total power if ``power`` is not specified. source_rates : float or iterable of float, optional - Source rate in [neutron/sec] or neutron flux in [neut/s-cm^2] for each + Source rate in [neutron/sec] or neutron flux in [neut/cm^2-s] for each interval in :attr:`timesteps` .. versionadded:: 0.12.1 @@ -864,7 +864,7 @@ class SIIntegrator(Integrator): initial heavy metal inventory to get total power if ``power`` is not specified. source_rates : float or iterable of float, optional - Source rate in [neutron/sec] or neutron flux in [neut/s-cm^2] for each + Source rate in [neutron/sec] or neutron flux in [neutron/s-cm^2] for each interval in :attr:`timesteps` .. versionadded:: 0.12.1 diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/independent_operator.py similarity index 67% rename from openmc/deplete/flux_operator.py rename to openmc/deplete/independent_operator.py index 410552671..98ef6656d 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/independent_operator.py @@ -1,7 +1,7 @@ -"""Pure depletion operator +"""Independent depletion operator -This module implements a pure depletion operator that user-provided one-group -cross sections. +This module implements a depletion operator that runs independently of any +transport solver by using user-provided one-group cross sections. """ @@ -11,110 +11,33 @@ from warnings import warn from itertools import product import numpy as np -import pandas as pd from uncertainties import ufloat import openmc -from openmc.checkvalue import check_type, check_value, check_iterable_type +from openmc.checkvalue import check_type from openmc.mpi import comm -from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS from .abc import ReactionRateHelper, OperatorResult -from .chain import REACTIONS from .openmc_operator import OpenMCOperator, _distribute +from .microxs import MicroXS from .results import Results from .helpers import ChainFissionHelper, ConstantFissionYieldHelper, SourceRateHelper -_valid_rxns = list(REACTIONS) -_valid_rxns.append('fission') - -def generate_1g_cross_sections(model, - reaction_domain, - reactions=['(n,gamma)', - '(n,2n)', - '(n,p)', - '(n,a)', - '(n,3n)', - '(n,4n)', - 'fission'], - energy_bounds=(0, 20e6), - write_to_csv=False, - filename='micro_xs.csv'): - """Helper function to generate a one-group cross-section dataframe using - OpenMC. Note that the ``openmc`` executable must be compiled. - - Parameters - ---------- - model : openmc.model.Model - OpenMC model object. Must contain geometry, materials, and settings. - reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain in which to tally reaction rates. - reactions : list of str, optional - Reaction names to tally - energy_bound : 2-tuple of float, optional - Bounds for the energy group. - write_to_csv : bool, optional - Option to write the DataFrame to a `.csv` file. - filename : str - Name for csv file. Only applicable if ``write_to_csv == True`` - - Returns - ------- - None or pandas.DataFrame - - """ - groups = EnergyGroups(energy_bounds) - - # Set up the reaction tallies - original_tallies = model.tallies - tallies = openmc.Tallies() - xs = {} - for rxn in reactions: - if rxn == 'fission': - xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) - else: - xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) - tallies += xs[rxn].tallies.values() - - model.tallies = tallies - statepoint_path = model.run() - - # Revert to the original tallies - model.tallies = old_tallies - - with openmc.StatePoint(statepoint_path) as sp: - for rxn in xs: - xs[rxn].load_from_statepoint(sp) - - # Build the DataFrame - micro_xs = pd.DataFrame() - for rxn in xs: - df = xs[rxn].get_pandas_dataframe(xs_type='micro') - df.index = df['nuclide'] - df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) - df.rename({'mean':rxn}, axis=1, inplace=True) - micro_xs = pd.concat([micro_xs, df], axis=1) - - if write_to_csv: - micro_xs.to_csv(filename) - - return micro_xs - -class FluxDepletionOperator(OpenMCOperator): - """Depletion operator that uses one-group - cross sections to calculate reaction rates. +class IndependentOperator(OpenMCOperator): + """Depletion operator that uses one-group cross sections to calculate + reaction rates. Instances of this class can be used to perform depletion using one-group - cross sections and constant flux or constant power. Normally, a user needn't call methods of - this class directly. Instead, an instance of this class is passed to an - integrator class, such as :class:`openmc.deplete.CECMIntegrator`. + cross sections and constant flux or constant power. Normally, a user needn't + call methods of this class directly. Instead, an instance of this class is + passed to an integrator class, such as + :class:`openmc.deplete.CECMIntegrator`. Parameters ---------- materials : openmc.Materials Materials to deplete. - micro_xs : pandas.DataFrame - DataFrame with nuclides names as index and microscopic cross section - data in the columns. Cross section units are [cm^-2]. + micro_xs : MicroXS + One-group microscopic cross sections in [b] . chain_file : str Path to the depletion chain XML file. keff : 2-tuple of float, optional @@ -134,23 +57,23 @@ class FluxDepletionOperator(OpenMCOperator): if ``"normalization_mode" == "fission-q"``. reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the - depletion chain up to ``reduce_chain_level``. Default is False. + depletion chain up to ``reduce_chain_level``. reduce_chain_level : int, optional Depth of the search when reducing the depletion chain. Only used if ``reduce_chain`` evaluates to true. The default value of ``None`` implies no limit on the depth. fission_yield_opts : dict of str to option, optional - Optional arguments to pass to the `FissionYieldHelper`. Will be + Optional arguments to pass to the + :class:`openmc.deplete.helpers.FissionYieldHelper` object. Will be passed directly on to the helper. Passing a value of None will use the defaults for the associated helper. - Attributes ---------- materials : openmc.Materials All materials present in the model - cross_sections : pandas.DataFrame - Object containing one-group cross-sections. + cross_sections : MicroXS + Object containing one-group cross-sections in [cm^2]. dilute_initial : float Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay @@ -193,7 +116,7 @@ class FluxDepletionOperator(OpenMCOperator): fission_yield_opts=None): # Validate micro-xs parameters check_type('materials', materials, openmc.Materials) - check_type('micro_xs', micro_xs, pd.DataFrame) + check_type('micro_xs', micro_xs, MicroXS) if keff is not None: check_type('keff', keff, tuple, float) keff = ufloat(*keff) @@ -205,9 +128,11 @@ class FluxDepletionOperator(OpenMCOperator): helper_kwargs = {'normalization_mode': normalization_mode, 'fission_yield_opts': fission_yield_opts} + cross_sections = micro_xs * 1e-24 + cross_sections._units = 'cm^2' super().__init__( materials, - micro_xs, + cross_sections, chain_file, prev_results, fission_q=fission_q, @@ -216,9 +141,10 @@ class FluxDepletionOperator(OpenMCOperator): reduce_chain_level=reduce_chain_level) @classmethod - def from_nuclides(cls, volume, nuclides, nuc_units, + def from_nuclides(cls, volume, nuclides, micro_xs, chain_file, + nuc_units='atom/b-cm', keff=None, normalization_mode='source-rate', fission_q=None, @@ -234,13 +160,12 @@ class FluxDepletionOperator(OpenMCOperator): nuclides : dict of str to float Dictionary with nuclide names as keys and nuclide concentrations as values. - nuc_units : {'atom/cm3', 'atom/b-cm'} - Units for nuclide concentration. - micro_xs : pandas.DataFrame - DataFrame with nuclides names as index and microscopic cross section - data in the columns. Cross section units are [cm^-2]. + micro_xs : MicroXS + One-group microscopic cross sections. chain_file : str Path to the depletion chain XML file. + nuc_units : {'atom/cm3', 'atom/b-cm'} + Units for nuclide concentration. keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. Default is None. @@ -325,17 +250,16 @@ class FluxDepletionOperator(OpenMCOperator): """Finds nuclides with cross section data""" return set(cross_sections.index) - class _FluxDepletionNormalizationHelper(ChainFissionHelper): - """Class for calculating one-group flux - based on a power. + class _IndependentNormalizationHelper(ChainFissionHelper): + """Class for calculating one-group flux based on a power. flux = Power / X, where X = volume * sum_i(Q_i * fission_micro_xs_i * density_i) Parameters ---------- - op : openmc.deplete.FluxDepletionOperator - Reference to the object encapsulate _FluxDepletionNormalizationHelper. - We pass this so we don't have to duplicate the ``number`` object. + op : openmc.deplete.IndependentOperator + Reference to the object encapsulating _IndependentNormalizationHelper. + We pass this so we don't have to duplicate :attr:`IndependentOperator.number`. """ @@ -367,7 +291,7 @@ class FluxDepletionOperator(OpenMCOperator): super().update(fission_rates) - class _FluxDepletionRateHelper(ReactionRateHelper): + class _IndependentRateHelper(ReactionRateHelper): """Class for generating one-group reaction rates with flux and one-group cross sections. @@ -378,9 +302,9 @@ class FluxDepletionOperator(OpenMCOperator): Parameters ---------- - op : openmc.deplete.FluxDepletionOperator - Reference to the object encapsulate _FluxDepletionRateHelper. - We pass this so we don't have to duplicate the ``number`` object. + op : openmc.deplete.IndependentOperator + Reference to the object encapsulate _IndependentRateHelper. + We pass this so we don't have to duplicate the :attr:`IndependentOperator.number` object. Attributes @@ -441,9 +365,9 @@ class FluxDepletionOperator(OpenMCOperator): normalization_mode = helper_kwargs['normalization_mode'] fission_yield_opts = helper_kwargs['fission_yield_opts'] - self._rate_helper = self._FluxDepletionRateHelper(self) + self._rate_helper = self._IndependentRateHelper(self) if normalization_mode == "fission-q": - self._normalization_helper = self._FluxDepletionNormalizationHelper(self) + self._normalization_helper = self._IndependentNormalizationHelper(self) else: self._normalization_helper = SourceRateHelper() @@ -472,7 +396,7 @@ class FluxDepletionOperator(OpenMCOperator): vec : list of numpy.ndarray Total atoms to be used in function. source_rate : float - Power in [W] or flux in [neut/s-cm^2] + Power in [W] or flux in [neutron/cm^2-s] Returns ------- @@ -523,79 +447,3 @@ class FluxDepletionOperator(OpenMCOperator): ' atom/b-cm)') number_i[mat, nuc] = 0.0 - - @staticmethod - def create_micro_xs_from_data_array(nuclides, reactions, data): - """ - Creates a ``micro_xs`` parameter from a dictionary. - - Parameters - ---------- - nuclides : list of str - List of nuclide symbols for that have data for at least one - reaction. - reactions : list of str - List of reactions. All reactions must match those in ``chain.REACTIONS`` - data : ndarray of floats - Array containing one-group microscopic cross section values, in - [barn], for each nuclide and reaction. - - Returns - ------- - micro_xs : pandas.DataFrame - A DataFrame object correctly formatted for use in ``FluxOperator``. - Cross section data is in [cm^2] - """ - - # Validate inputs - if data.shape != (len(nuclides), len(reactions)): - raise ValueError( - f'Nuclides list of length {len(nuclides)} and ' - f'reactions array of length {len(reactions)} do not ' - f'match dimensions of data array of shape {data.shape}') - - FluxDepletionOperator._validate_micro_xs_inputs( - nuclides, reactions, data) - - # Convert to cm^2 - data *= 1e-24 - - return pd.DataFrame(index=nuclides, columns=reactions, data=data) - - @staticmethod - def create_micro_xs_from_csv(csv_file, units='barn'): - """ - Create the ``micro_xs`` parameter from a ``.csv`` file. - - Parameters - ---------- - csv_file : str - Relative path to csv-file containing microscopic cross section - data. Cross section values should be in [barn]. - - Returns - ------- - micro_xs : pandas.DataFrame - A DataFrame object correctly formatted for use in ``FluxOperator``. - Cross section data is in [cm^2] - - """ - micro_xs = pd.read_csv(csv_file, index_col=0) - - FluxDepletionOperator._validate_micro_xs_inputs(list(micro_xs.index), - list(micro_xs.columns), - micro_xs.to_numpy()) - - micro_xs *= 1e-24 - - return micro_xs - - # Convenience function for the micro_xs static methods - @staticmethod - def _validate_micro_xs_inputs(nuclides, reactions, data): - check_iterable_type('nuclides', nuclides, str) - check_iterable_type('reactions', reactions, str) - check_type('data', data, np.ndarray, expected_iter_type=float) - for reaction in reactions: - check_value('reactions', reaction, _valid_rxns) - diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py new file mode 100644 index 000000000..6abf8836f --- /dev/null +++ b/openmc/deplete/microxs.py @@ -0,0 +1,178 @@ +"""MicroXS module + +A pandas.DataFrame storing microscopic cross section data with +nuclides names as row indices and reaction names as column indices. +""" + +import tempfile +from pathlib import Path +from os import chdir + +from pandas import DataFrame, read_csv, concat +from numpy import ndarray + +from openmc.checkvalue import check_type, check_value, check_iterable_type +from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS +from openmc import Tallies, StatePoint + +from .chain import REACTIONS + +_valid_rxns = list(REACTIONS) +_valid_rxns.append('fission') + + +class MicroXS(DataFrame): + """Stores microscopic cross section data for use in + independent depletion. + """ + + @classmethod + def from_model(cls, + model, + reaction_domain, + reactions=['(n,gamma)', + '(n,2n)', + '(n,p)', + '(n,a)', + '(n,3n)', + '(n,4n)', + 'fission'], + energy_bounds=(0, 20e6)): + """Generate a one-group cross-section dataframe using + OpenMC. Note that the ``openmc`` executable must be compiled. + + Parameters + ---------- + model : openmc.Model + OpenMC model object. Must contain geometry, materials, and settings. + reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh + Domain in which to tally reaction rates. + reactions : list of str, optional + Reaction names to tally + energy_bound : 2-tuple of float, optional + Bounds for the energy group. + + Returns + ------- + MicroXS, cross section data in [b] + + """ + groups = EnergyGroups(energy_bounds) + + # Set up the reaction tallies + original_tallies = model.tallies + tallies = Tallies() + xs = {} + for rxn in reactions: + if rxn == 'fission': + xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) + else: + xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) + tallies += xs[rxn].tallies.values() + + model.tallies = tallies + + # create temporary run + original_dir = Path.cwd() + temp_dir = tempfile.TemporaryDirectory() + chdir(tempfile.gettempdir()) + statepoint_path = model.run() + chdir(original_dir) + + with StatePoint(statepoint_path) as sp: + for rxn in xs: + xs[rxn].load_from_statepoint(sp) + + # Build the DataFrame + micro_xs = cls() + for rxn in xs: + df = xs[rxn].get_pandas_dataframe(xs_type='micro') + df.index = df['nuclide'] + df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) + df.rename({'mean':rxn}, axis=1, inplace=True) + micro_xs = concat([micro_xs, df], axis=1) + + micro_xs._units = 'b' + + # Revert to the original tallies + model.tallies = original_tallies + + return micro_xs + + @classmethod + def from_array(cls, nuclides, reactions, data, units='b'): + """ + Creates a ``MicroXS`` object from arrays. + + Parameters + ---------- + nuclides : list of str + List of nuclide symbols for that have data for at least one + reaction. + reactions : list of str + List of reactions. All reactions must match those in + :data:`openmc.deplete.chain.REACTIONS` + data : ndarray of floats + Array containing one-group microscopic cross section values for + each nuclide and reaction + units : {'b', 'cm^2'} + Units of the cross section values in ``data`` + + Returns + ------- + MicroXS + """ + + # Validate inputs + if data.shape != (len(nuclides), len(reactions)): + raise ValueError( + f'Nuclides list of length {len(nuclides)} and ' + f'reactions array of length {len(reactions)} do not ' + f'match dimensions of data array of shape {data.shape}') + + cls._validate_micro_xs_inputs( + nuclides, reactions, data) + micro_xs = cls(index=nuclides, columns=reactions, data=data) + micro_xs._units = units + + return micro_xs + + @classmethod + def from_csv(cls, csv_file, units='b', **kwargs): + """ + Load a ``MicroXS`` object from a ``.csv`` file. + + Parameters + ---------- + csv_file : str + Relative path to csv-file containing microscopic cross section + data. + units : {'b', 'cm^2'} + Units of the cross section values in the ``.csv`` file + **kwargs : dict + Keyword arguments to pass to :func:`pandas.read_csv()`. + + Returns + ------- + MicroXS + + """ + if 'float_precision' not in kwargs: + kwargs['float_precision'] = 'round_trip' + + micro_xs = cls(read_csv(csv_file, index_col=0, **kwargs)) + + cls._validate_micro_xs_inputs(list(micro_xs.index), + list(micro_xs.columns), + micro_xs.to_numpy()) + micro_xs._units = units + + return micro_xs + + @staticmethod + def _validate_micro_xs_inputs(nuclides, reactions, data): + check_iterable_type('nuclides', nuclides, str) + check_iterable_type('reactions', reactions, str) + check_type('data', data, ndarray, expected_iter_type=float) + for reaction in reactions: + check_value('reactions', reaction, _valid_rxns) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 7c0bb6678..7235ab9bf 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -1,6 +1,6 @@ """OpenMC transport operator -This module implements functions used by both OpenMC transport operators as well as pure depletion operators. +This module implements functions shared by both OpenMC transport operators as well as indepenedent depletion operators. """ @@ -75,8 +75,8 @@ class OpenMCOperator(TransportOperator): helper_kwargs : dict Keyword arguments for helper classes reduce_chain : bool, optional - If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the - depletion chain up to ``reduce_chain_level``. Default is False. + If True, use :meth:`openmc.deplete.Chain.reduce()` to reduce the + depletion chain up to ``reduce_chain_level``. reduce_chain_level : int, optional Depth of the search when reducing the depletion chain. Only used if ``reduce_chain`` evaluates to true. The default value of @@ -87,7 +87,7 @@ class OpenMCOperator(TransportOperator): ---------- materials : openmc.Materials All materials present in the model - cross_sections : str or pandas.DataFrame + cross_sections : str or MicroXS Path to continuous energy cross section library, or object containing one-group cross-sections. dilute_initial : float diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index db4e80b19..53a1db3e9 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -131,7 +131,7 @@ class Operator(OpenMCOperator): .. versionadded:: 0.12.1 reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the - depletion chain up to ``reduce_chain_level``. Default is False. + depletion chain up to ``reduce_chain_level``. .. versionadded:: 0.12 reduce_chain_level : int, optional @@ -226,7 +226,7 @@ class Operator(OpenMCOperator): self.cleanup_when_done = True if reaction_rate_opts is None: - reaction_rate_opts = {} + reaction_rate_opts = {} if fission_yield_opts is None: fission_yield_opts = {} helper_kwargs = { diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 38d4aaf2e..95b842537 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -1,19 +1,12 @@ """ Transport-free depletion test suite """ -from math import floor -import shutil from pathlib import Path -from difflib import unified_diff import numpy as np import pytest import openmc -from openmc.data import JOULE_PER_EV import openmc.deplete -from openmc.deplete import FluxDepletionOperator - -from tests.regression_tests import config - +from openmc.deplete import IndependentOperator, MicroXS @pytest.fixture(scope="module") def fuel(): @@ -27,7 +20,6 @@ def fuel(): return fuel - @pytest.mark.parametrize("multiproc, from_nuclides, normalization_mode, power, flux", [ (True, True,'source-rate', None, 1164719970082145.0), (False, True, 'source-rate', None, 1164719970082145.0), @@ -46,7 +38,7 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide """ # Create operator micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' - micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(micro_xs_file) + micro_xs = MicroXS.from_csv(micro_xs_file) chain_file = Path(__file__).parents[2] / 'chain_simple.xml' if from_nuclides: @@ -54,11 +46,11 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide for nuc, dens in fuel.get_nuclide_atom_densities().items(): nuclides[nuc] = dens - op = FluxDepletionOperator.from_nuclides( - fuel.volume, nuclides,'atom/b-cm', micro_xs, chain_file, normalization_mode=normalization_mode) + op = IndependentOperator.from_nuclides( + fuel.volume, nuclides, micro_xs, chain_file, normalization_mode=normalization_mode) else: - op = FluxDepletionOperator(openmc.Materials([fuel]), micro_xs, chain_file, normalization_mode=normalization_mode) + op = IndependentOperator(openmc.Materials([fuel]), micro_xs, chain_file, normalization_mode=normalization_mode) # Power and timesteps dt = [30] # single step diff --git a/tests/regression_tests/microxs/__init.py__ b/tests/regression_tests/microxs/__init.py__ new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/microxs/test.py b/tests/regression_tests/microxs/test.py new file mode 100644 index 000000000..bebe1c302 --- /dev/null +++ b/tests/regression_tests/microxs/test.py @@ -0,0 +1,52 @@ +"""Test one-group cross section generation""" +import numpy as np +import pytest +import openmc + +from openmc.deplete import MicroXS + +@pytest.fixture(scope="module") +def model(): + fuel = openmc.Material(name="uo2") + fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) + fuel.add_element("O", 2) + fuel.set_density("g/cc", 10.4) + + clad = openmc.Material(name="clad") + clad.add_element("Zr", 1) + clad.set_density("g/cc", 6) + + water = openmc.Material(name="water") + water.add_element("O", 1) + water.add_element("H", 2) + water.set_density("g/cc", 1.0) + water.add_s_alpha_beta("c_H_in_H2O") + + radii = [0.42, 0.45] + fuel.volume = np.pi * radii[0] ** 2 + clad.volume = np.pi * (radii[1]**2 - radii[0]**2) + water.volume = 1.24**2 - (np.pi * radii[1]**2) + + materials = openmc.Materials([fuel, clad, water]) + + pin_surfaces = [openmc.ZCylinder(r=r) for r in radii] + pin_univ = openmc.model.pin(pin_surfaces, materials) + bound_box = openmc.rectangular_prism(1.24, 1.24, boundary_type="reflective") + root_cell = openmc.Cell(fill=pin_univ, region=bound_box) + geometry = openmc.Geometry([root_cell]) + + settings = openmc.Settings() + settings.particles = 1000 + settings.inactive = 10 + settings.batches = 50 + + return openmc.Model(geometry, materials, settings) + + +def test_from_model(model): + ref_xs = MicroXS.from_csv('test_reference.csv') + test_xs = MicroXS.from_model(model, model.materials[0]) + + assert ref_xs._units == test_xs._units + np.testing.assert_allclose(test_xs, ref_xs, rtol=1e-11) + diff --git a/tests/regression_tests/microxs/test_reference.csv b/tests/regression_tests/microxs/test_reference.csv new file mode 100644 index 000000000..0c47409b0 --- /dev/null +++ b/tests/regression_tests/microxs/test_reference.csv @@ -0,0 +1,7 @@ +nuclide,"(n,gamma)","(n,2n)","(n,p)","(n,a)","(n,3n)","(n,4n)",fission +U234,23.518634203050674,0.0008255330840536984,0.0,0.0,9.404554397521455e-07,0.0,0.49531930067650964 +U235,10.621118186344795,0.004359401013759254,0.0,0.0,7.2974901306692395e-06,0.0,49.10955932965902 +U238,0.8652742788116055,0.005661917442209096,0.0,0.0,4.92273921631416e-05,0.0,0.10579281644765708 +U236,9.095623870006163,0.0024373322002926834,0.0,0.0,1.966889146690413e-05,0.0,0.3231539233923791 +O16,7.511380881289377e-05,0.0,1.3764104470470622e-05,0.002862620940027927,0.0,0.0,0.0 +O17,0.00041221042693945085,1.9826700699084533e-05,7.764409141772239e-06,0.05938517754333328,0.0,0.0,0.0 diff --git a/tests/unit_tests/test_deplete_flux_operator.py b/tests/unit_tests/test_deplete_flux_operator.py deleted file mode 100644 index 8f17538ed..000000000 --- a/tests/unit_tests/test_deplete_flux_operator.py +++ /dev/null @@ -1,83 +0,0 @@ -"""Basic unit tests for openmc.deplete.FluxDepletionOperator instantiation - -Modifies and resets environment variable OPENMC_CROSS_SECTIONS -to a custom file with new depletion_chain node -""" - -from pathlib import Path - -import pytest -from openmc.deplete.flux_operator import FluxDepletionOperator -from openmc import Material, Materials -import pandas as pd -import numpy as np - -CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" -ONE_GROUP_XS = Path(__file__).parents[1] / "micro_xs_simple.csv" - - -def test_create_micro_xs_from_data_array(): - nuclides = [ - 'U234', - 'U235', - 'U238', - 'U236', - 'O16', - 'O17', - 'I135', - 'Xe135', - 'Xe136', - 'Cs135', - 'Gd157', - 'Gd156'] - reactions = ['fission', '(n,gamma)'] - # These values are placeholders and are not at all - # physically meaningful. - data = np.array([[0.1, 0.], - [0.1, 0.], - [0.9, 0.], - [0.4, 0.], - [0., 0.], - [0., 0.], - [0., 0.1], - [0., 0.9], - [0., 0.], - [0., 0.], - [0., 0.1], - [0., 0.1]]) - - FluxDepletionOperator.create_micro_xs_from_data_array( - nuclides, reactions, data) - with pytest.raises(ValueError, match=r'Nuclides list of length \d* and ' - r'reactions array of length \d* do not ' - r'match dimensions of data array of shape \(\d*\,d*\)'): - FluxDepletionOperator.create_micro_xs_from_data_array( - nuclides, reactions, data[:, 0]) - - -def test_create_micro_xs_from_csv(): - FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) - - -def test_operator_init(): - """The test uses a temporary dummy chain. This file will be removed - at the end of the test, and only contains a depletion_chain node.""" - volume = 1 - nuclides = {'U234': 8.922411359424315e+18, - 'U235': 9.98240191860822e+20, - 'U238': 2.2192386373095893e+22, - 'U236': 4.5724195495061115e+18, - 'O16': 4.639065406771322e+22, - 'O17': 1.7588724018066158e+19} - micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) - nuclide_flux_operator = FluxDepletionOperator.from_nuclides( - volume, nuclides, 'atom/cm3', micro_xs, CHAIN_PATH) - - fuel = Material(name="uo2") - fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) - fuel.add_element("O", 2) - fuel.set_density("g/cc", 10.4) - fuel.depletable=True - fuel.volume = 1 - materials = Materials([fuel]) - nuclide_flux_operator = FluxDepletionOperator(materials, micro_xs, CHAIN_PATH) diff --git a/tests/unit_tests/test_deplete_independent_operator.py b/tests/unit_tests/test_deplete_independent_operator.py new file mode 100644 index 000000000..f6cc7e200 --- /dev/null +++ b/tests/unit_tests/test_deplete_independent_operator.py @@ -0,0 +1,36 @@ +"""Basic unit tests for openmc.deplete.IndependentOperator instantiation + +""" + +from pathlib import Path + +import pytest +from openmc.deplete import IndependentOperator, MicroXS +from openmc import Material, Materials +import numpy as np + +CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" +ONE_GROUP_XS = Path(__file__).parents[1] / "micro_xs_simple.csv" + +def test_operator_init(): + """The test uses a temporary dummy chain. This file will be removed + at the end of the test, and only contains a depletion_chain node.""" + volume = 1 + nuclides = {'U234': 8.922411359424315e+18, + 'U235': 9.98240191860822e+20, + 'U238': 2.2192386373095893e+22, + 'U236': 4.5724195495061115e+18, + 'O16': 4.639065406771322e+22, + 'O17': 1.7588724018066158e+19} + micro_xs = MicroXS.from_csv(ONE_GROUP_XS) + IndependentOperator.from_nuclides( + volume, nuclides, micro_xs, CHAIN_PATH, nuc_units='atom/cm3') + + fuel = Material(name="uo2") + fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) + fuel.add_element("O", 2) + fuel.set_density("g/cc", 10.4) + fuel.depletable=True + fuel.volume = 1 + materials = Materials([fuel]) + IndependentOperator(materials, micro_xs, CHAIN_PATH) diff --git a/tests/unit_tests/test_deplete_microxs.py b/tests/unit_tests/test_deplete_microxs.py new file mode 100644 index 000000000..17d9cb38f --- /dev/null +++ b/tests/unit_tests/test_deplete_microxs.py @@ -0,0 +1,60 @@ +"""Basic unit tests for openmc.deplete.IndependentOperator instantiation + +Modifies and resets environment variable OPENMC_CROSS_SECTIONS +to a custom file with new depletion_chain node +""" + +from os import remove +from pathlib import Path + +import pytest +from openmc.deplete import MicroXS +import numpy as np + +ONE_GROUP_XS = Path(__file__).parents[1] / "micro_xs_simple.csv" + + +def test_from_array(): + nuclides = [ + 'U234', + 'U235', + 'U238', + 'U236', + 'O16', + 'O17', + 'I135', + 'Xe135', + 'Xe136', + 'Cs135', + 'Gd157', + 'Gd156'] + reactions = ['fission', '(n,gamma)'] + # These values are placeholders and are not at all + # physically meaningful. + data = np.array([[0.1, 0.], + [0.1, 0.], + [0.9, 0.], + [0.4, 0.], + [0., 0.], + [0., 0.], + [0., 0.1], + [0., 0.9], + [0., 0.], + [0., 0.], + [0., 0.1], + [0., 0.1]]) + + MicroXS.from_array(nuclides, reactions, data) + with pytest.raises(ValueError, match=r'Nuclides list of length \d* and ' + r'reactions array of length \d* do not ' + r'match dimensions of data array of shape \(\d*\,d*\)'): + MicroXS.from_array(nuclides, reactions, data[:, 0]) + +def test_csv(): + ref_xs = MicroXS.from_csv(ONE_GROUP_XS) + ref_xs.to_csv('temp_xs.csv') + temp_xs = MicroXS.from_csv('temp_xs.csv') + assert ref_xs._units == temp_xs._units + assert np.all(ref_xs == temp_xs) + remove('temp_xs.csv') + From 25ab9d28ce0c45f886639681aa9233eb1a2dfac1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 00:47:27 +0100 Subject: [PATCH 0698/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/mesh.py | 6 +++--- src/state_point.cpp | 1 - tests/unit_tests/mesh_to_vtk/test.py | 11 +++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 9c837fd8e..211c4075d 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1485,7 +1485,7 @@ class UnstructuredMesh(MeshBase): element_types : Iterable of integers Mesh element types - .. versionadded:: 0.13 + .. versionadded:: 0.13.1 total_volume : float Volume of the unstructured mesh in total """ @@ -1770,8 +1770,8 @@ class UnstructuredMesh(MeshBase): vertices = group['vertices'][()] mesh._vertices = vertices.reshape((-1, 3)) - connectvity = group['connectivity'][()] - mesh._connectivity = connectvity.reshape((-1, 8)) + connectivity = group['connectivity'][()] + mesh._connectivity = connectivity.reshape((-1, 8)) mesh._element_types = group['element_types'][()] if 'length_multiplier' in group: diff --git a/src/state_point.cpp b/src/state_point.cpp index b4200ffe2..11c93447d 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -812,7 +812,6 @@ void write_unstructured_mesh_results() auto umesh = dynamic_cast(model::meshes[mesh_idx].get()); - if (!umesh) continue; diff --git a/tests/unit_tests/mesh_to_vtk/test.py b/tests/unit_tests/mesh_to_vtk/test.py index 4ac875002..d9f050226 100644 --- a/tests/unit_tests/mesh_to_vtk/test.py +++ b/tests/unit_tests/mesh_to_vtk/test.py @@ -17,11 +17,10 @@ def ids_func(param): test_params = (['libmesh', 'moab'], ['tets', 'hexes']) -test_cases = [] -for library, elem_type in product(*test_params): - test_case = {'library' : library, - 'elem_type' : elem_type} - test_cases.append(test_case) +test_cases = [ + {'library' : library, 'elem_type' : elem_type} + for library, elem_type in product(*test_params) +] @pytest.mark.parametrize("test_opts", test_cases, ids=ids_func) def test_unstructured_mesh_to_vtk(run_in_tmpdir, request, test_opts): @@ -60,7 +59,7 @@ def test_unstructured_mesh_to_vtk(run_in_tmpdir, request, test_opts): with openmc.StatePoint(sp_file) as sp: umesh = sp.meshes[umesh.id] - test_data = {'ids' : np.arange(umesh.n_elements)} + test_data = {'ids': np.arange(umesh.n_elements)} umesh.write_data_to_vtk('umesh.vtk', datasets=test_data, volume_normalization=False) From 4564607eff50e69c77071e52ff71242d1d0a6083 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 18:48:11 -0500 Subject: [PATCH 0699/2654] Addressing comments from @paulromano --- docs/source/io_formats/statepoint.rst | 6 ++++-- openmc/mesh.py | 19 +++++++++++++------ src/mesh.cpp | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index f96d7181d..26dbd9c2e 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -80,8 +80,10 @@ The current version of the statepoint file format is 17.0. dimension. - **Unstructured Mesh Only:** - **volumes** (*double[]*) -- Volume of each mesh cell. - - **centroids** (*double[]*) -- Location of the mesh cell - centroids. + - **vertices** (*double[]*) -- Location of the mesh vertices. + - **connectivity** (*int[]*) -- Connectivity array for the mesh + cells. + - **element_types** (*int[]*) -- Mesh element types. **/tallies/filters/** diff --git a/openmc/mesh.py b/openmc/mesh.py index 211c4075d..f2aced9f8 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1477,7 +1477,7 @@ class UnstructuredMesh(MeshBase): .. versionadded:: 0.13 - connectivity : np.ndarray (8, n_elements) + connectivity : np.ndarray (n_elements, 8) Connectivity of the elements .. versionadded:: 0.13 @@ -1633,6 +1633,17 @@ class UnstructuredMesh(MeshBase): def centroid(self, bin): """Return the vertex averaged centroid of an element + + Parameters + ---------- + bin : int + Bin ID for the returned centroid + + Returns + ------- + numpy.ndarray + x, y, z values of the element centroid + """ conn = self.connectivity[bin] coords = self.vertices[conn] @@ -1749,11 +1760,7 @@ class UnstructuredMesh(MeshBase): arr.SetTuple1(i, data.flat[i]) grid.GetCellData().AddArray(arr) - if vtk.VTK_MAJOR_VERSION == 5: - grid.update() - writer.SetInput(grid) - else: - writer.SetInputData(grid) + writer.SetInputData(grid) writer.Write() diff --git a/src/mesh.cpp b/src/mesh.cpp index e701f954e..df5c7f2b3 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -256,7 +256,7 @@ void UnstructuredMesh::to_hdf5(hid_t group) const } else { num_elem_skipped++; xt::view(elem_types, i, xt::all()) = static_cast(ElementType::UNSUPPORTED); - xt::view(connectivity, i, xt::all()) = xt::xarray({-1, -1, -1, -1, -1, -1, -1, -1}); + xt::view(connectivity, i, xt::all()) = -1; } } From 8e747cc8747410326da04fbd4fcebc587a4a0081 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 00:51:25 +0100 Subject: [PATCH 0700/2654] Apply suggestion from @paulromano Co-authored-by: Paul Romano --- openmc/mesh.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 211c4075d..d7ea4bc11 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1469,19 +1469,17 @@ class UnstructuredMesh(MeshBase): be generated for this mesh volumes : Iterable of float Volumes of the unstructured mesh elements - centroids : np.narray (3, n_elements) - Centroids of the mesh elements + centroids : numpy.ndarray + Centroids of the mesh elements with array shape (3, n_elements) - vertices : np.ndarray (3,) - Coordinates of the mesh vertices + vertices : numpy.ndarray + Coordinates of the mesh vertices with array shape (3, n_elements) - .. versionadded:: 0.13 - - connectivity : np.ndarray (8, n_elements) - Connectivity of the elements - - .. versionadded:: 0.13 + .. versionadded:: 0.13.1 + connectivity : numpy.ndarray + Connectivity of the elements with array shape (8, n_elements) + .. versionadded:: 0.13.1 element_types : Iterable of integers Mesh element types From 044c28d6519b76ef72d8c4b79f48f0faeff78fd7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 18:50:21 -0500 Subject: [PATCH 0701/2654] Applying clang-format --- src/mesh.cpp | 8 ++++++-- src/state_point.cpp | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index df5c7f2b3..aa35f3064 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -262,8 +262,12 @@ void UnstructuredMesh::to_hdf5(hid_t group) const // warn users that some elements were skipped if (num_elem_skipped > 0) { - warning(fmt::format("The connectivity of {} elements on mesh {} were not written " - "because they are not of type linear tet/hex.", num_elem_skipped, this->id_)); + warning(fmt::format( + "The connectivity of {} elements + on mesh {} were not written + " + "because they are not of type linear tet/hex.", + num_elem_skipped, this->id_)); } write_dataset(mesh_group, "volumes", volumes); diff --git a/src/state_point.cpp b/src/state_point.cpp index 11c93447d..3b217a658 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -820,7 +820,8 @@ void write_unstructured_mesh_results() if (umesh->library() == "moab") { if (mpi::master) - warning(fmt::format("Output for a MOAB mesh (mesh {}) was requested but will not be written. Please use the Python API to generated the desired VTK tetrahedral mesh.", umesh->id_)); + warning(fmt::format("Output for a MOAB mesh (mesh {}) was + requested but will not be written. Please use the Python API to generated the desired VTK tetrahedral mesh.", umesh->id_)); continue; } From 2edd390d30d98c64282268034a469e0e607b0df3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 18:56:19 -0500 Subject: [PATCH 0702/2654] Newline at end of test file --- tests/unit_tests/mesh_to_vtk/test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/mesh_to_vtk/test.py b/tests/unit_tests/mesh_to_vtk/test.py index d9f050226..c433913ee 100644 --- a/tests/unit_tests/mesh_to_vtk/test.py +++ b/tests/unit_tests/mesh_to_vtk/test.py @@ -66,4 +66,5 @@ def test_unstructured_mesh_to_vtk(run_in_tmpdir, request, test_opts): # compare file content with reference file ref_file = Path(f"{test_opts['library']}_{test_opts['elem_type']}_ref.vtk") - assert filecmp.cmp('umesh.vtk', request.node.path.parent / ref_file) \ No newline at end of file + assert filecmp.cmp('umesh.vtk', request.node.path.parent / ref_file) + \ No newline at end of file From d5e963220601df0739449172cd249b24cf66c538 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 19:19:39 -0500 Subject: [PATCH 0703/2654] Updating statepoint doc a bit --- docs/source/io_formats/statepoint.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 26dbd9c2e..28a6849fd 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -80,7 +80,7 @@ The current version of the statepoint file format is 17.0. dimension. - **Unstructured Mesh Only:** - **volumes** (*double[]*) -- Volume of each mesh cell. - - **vertices** (*double[]*) -- Location of the mesh vertices. + - **vertices** (*double[]*) -- x, y, z values of the mesh vertices. - **connectivity** (*int[]*) -- Connectivity array for the mesh cells. - **element_types** (*int[]*) -- Mesh element types. From bdf6de5e516bc18a38f786cb09981905c74379fd Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 19:21:17 -0500 Subject: [PATCH 0704/2654] EOL for test --- tests/unit_tests/mesh_to_vtk/test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/mesh_to_vtk/test.py b/tests/unit_tests/mesh_to_vtk/test.py index c433913ee..5f6cd6a41 100644 --- a/tests/unit_tests/mesh_to_vtk/test.py +++ b/tests/unit_tests/mesh_to_vtk/test.py @@ -67,4 +67,3 @@ def test_unstructured_mesh_to_vtk(run_in_tmpdir, request, test_opts): # compare file content with reference file ref_file = Path(f"{test_opts['library']}_{test_opts['elem_type']}_ref.vtk") assert filecmp.cmp('umesh.vtk', request.node.path.parent / ref_file) - \ No newline at end of file From 7b083c7b0ce68b1a615ef3df521f6d253a1c20bc Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 02:03:03 -0500 Subject: [PATCH 0705/2654] Fixing output message syntax --- src/mesh.cpp | 8 +++----- src/state_point.cpp | 7 +++++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index aa35f3064..a8ee8e73f 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -262,11 +262,9 @@ void UnstructuredMesh::to_hdf5(hid_t group) const // warn users that some elements were skipped if (num_elem_skipped > 0) { - warning(fmt::format( - "The connectivity of {} elements - on mesh {} were not written - " - "because they are not of type linear tet/hex.", + warning(fmt::format("The connectivity of {} elements " + "on mesh {} were not written " + "because they are not of type linear tet/hex.", num_elem_skipped, this->id_)); } diff --git a/src/state_point.cpp b/src/state_point.cpp index 3b217a658..648d1a249 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -820,8 +820,11 @@ void write_unstructured_mesh_results() if (umesh->library() == "moab") { if (mpi::master) - warning(fmt::format("Output for a MOAB mesh (mesh {}) was - requested but will not be written. Please use the Python API to generated the desired VTK tetrahedral mesh.", umesh->id_)); + warning(fmt::format( + "Output for a MOAB mesh (mesh {}) was " + "requested but will not be written. Please use the Python " + "API to generated the desired VTK tetrahedral mesh.", + umesh->id_)); continue; } From 9413e4699899dd9d19c6b583c67bcbfee2c86ea3 Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 29 Jul 2022 11:15:53 -0500 Subject: [PATCH 0706/2654] changed break conditions for short ciruciting --- src/cell.cpp | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index 633cf1bc0..f2e4444d4 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -107,15 +107,14 @@ vector tokenize(const std::string region_spec) return tokens; } - //============================================================================== -//! Add precedence for infix cell finding so intersections have higher +//! Add precedence for infix cell finding so intersections have higher //! precedence than unions using parenthesis. //============================================================================== -std::vector::iterator -add_parenthesis(std::vector::iterator start, - std::vector &infix) { +std::vector::iterator add_parenthesis( + std::vector::iterator start, std::vector& infix) +{ // Add left parenthesis start = infix.insert(start, OP_LEFT_PAREN); start = start + 2; @@ -131,7 +130,7 @@ add_parenthesis(std::vector::iterator start, // If we find a union or right parenthesis not wrapped by // left and right parenthesis then place a right parenthesis, // If we find a wrapped region return an iterator pointing to - // that wrapped region and continue looking to place a + // that wrapped region and continue looking to place a // right parenthesis if (*start == OP_UNION || *start == OP_RIGHT_PAREN) { start = infix.insert(start, OP_RIGHT_PAREN); @@ -149,7 +148,8 @@ add_parenthesis(std::vector::iterator start, return return_iterator; } -void add_precedence(std::vector &infix) { +void add_precedence(std::vector& infix) +{ int32_t current_op = 0; for (auto it = infix.begin(); it != infix.end(); it++) { @@ -861,20 +861,16 @@ bool CSGCell::contains_complex( it++; int32_t next_token = *it; - // If the next token is a left parenthesis skip until - // the next right parenthesis, if the token is a right - // parenthesis leave short circuiting, if we go from - // intersections to union operators without parenthesis - // break shortc circuiting one behind the union - if (next_token >= OP_UNION) { + // If the next token is an operator and is not the same as the one that + // started the short circuiting, check if it is a left parenthesis to + // skip a section or break + if (next_token >= OP_UNION && token != next_token) { if (next_token == OP_LEFT_PAREN) { - it = std::find(it, region_no_complements_.end() - 1, OP_RIGHT_PAREN); - } else if (token == OP_RIGHT_PAREN) { + it = + std::find(it, region_no_complements_.end() - 1, OP_RIGHT_PAREN); + } else { break; - } else if (token - next_token == 1) { - it--; - break; - } + } } } while (it < region_no_complements_.end() - 1); } From d7904f7a137196b582b47b2e2d1b24f183ec7dd0 Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 29 Jul 2022 13:29:21 -0500 Subject: [PATCH 0707/2654] now can handle multiple depths of parenthesis --- src/cell.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index f2e4444d4..fc19c1c49 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -866,8 +866,17 @@ bool CSGCell::contains_complex( // skip a section or break if (next_token >= OP_UNION && token != next_token) { if (next_token == OP_LEFT_PAREN) { - it = - std::find(it, region_no_complements_.end() - 1, OP_RIGHT_PAREN); + int depth = 1; + while (depth > 0) { + it++; + if (*it > OP_COMPLEMENT) { + if (*it == OP_RIGHT_PAREN) { + depth--; + } else { + depth++; + } + } + } } else { break; } From 5bd2a14a2cd021594b52fe90a9475e145f1838a5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 15:30:35 -0500 Subject: [PATCH 0708/2654] Adding missing datasets to the statepoint docs --- docs/source/io_formats/statepoint.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 28a6849fd..c1598f2c3 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -79,6 +79,10 @@ The current version of the statepoint file format is 17.0. - **width** (*double[]*) -- Width of each mesh cell in each dimension. - **Unstructured Mesh Only:** + - **filename** (*char[]*) -- Name of the mesh file. + - **library** (*char[]*) -- Mesh library used to represent the + mesh ("moab" or "libmesh"). + - **length_multiplier** (*double*) Scaling factor applied to the mesh. - **volumes** (*double[]*) -- Volume of each mesh cell. - **vertices** (*double[]*) -- x, y, z values of the mesh vertices. - **connectivity** (*int[]*) -- Connectivity array for the mesh From 647863c7ace4c6c5736ae75ba04c82b258897b41 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 15:33:29 -0500 Subject: [PATCH 0709/2654] Removing centroids setter --- openmc/mesh.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 2b405bf6a..bb559a383 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1594,13 +1594,6 @@ class UnstructuredMesh(MeshBase): cv.check_type('Number of elements', val, Integral) self._n_elements = val - - @centroids.setter - def centroids(self, centroids): - cv.check_type("Unstructured mesh centroids", centroids, - Iterable, Real) - self._centroids = centroids - @property def length_multiplier(self): return self._length_multiplier From a3e2fcdcca22184f87ecf8ebbdddecf770360057 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 15:34:23 -0500 Subject: [PATCH 0710/2654] Correcting dimensions of attributes in um docstrings --- openmc/mesh.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index bb559a383..daff4dedc 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1470,14 +1470,14 @@ class UnstructuredMesh(MeshBase): volumes : Iterable of float Volumes of the unstructured mesh elements centroids : numpy.ndarray - Centroids of the mesh elements with array shape (3, n_elements) + Centroids of the mesh elements with array shape (n_elements, 3) vertices : numpy.ndarray - Coordinates of the mesh vertices with array shape (3, n_elements) + Coordinates of the mesh vertices with array shape (n_elements, 3) .. versionadded:: 0.13.1 connectivity : numpy.ndarray - Connectivity of the elements with array shape (8, n_elements) + Connectivity of the elements with array shape (n_elements, 8) .. versionadded:: 0.13.1 element_types : Iterable of integers From effc35b8eed3c33c63a56fdead9120143f5551ed Mon Sep 17 00:00:00 2001 From: yardasol Date: Fri, 29 Jul 2022 18:21:06 -0500 Subject: [PATCH 0711/2654] add_elements_or_nuclides -> add_components - changed the assumptions the function makes about the 'components' parameter - added 'percent_type' parameter - passed changes to unit test --- openmc/material.py | 48 ++++++++++++++++++----------- tests/unit_tests/test_material.py | 50 +++++++++++++++++++------------ 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 14bec12f3..9ba7360ff 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -35,7 +35,7 @@ class Material(IDManagerMixin): nuclides or elements with :meth:`Material.add_nuclide` or :meth:`Material.add_element`, respectively, and set the total material density with :meth:`Material.set_density()`. Alternatively, you can - use :meth:`Material.add_elements_or_nuclides()` to pass a dictionary + use :meth:`Material.add_components()` to pass a dictionary containing all the component information. The material can then be assigned to a cell using the :attr:`Cell.fill` attribute. @@ -405,41 +405,55 @@ class Material(IDManagerMixin): self._nuclides.append(NuclideTuple(nuclide, percent, percent_type)) - def add_elements_or_nuclides(self, components: dict): + def add_components(self, components: dict, percent_type: str = 'ao'): """ Add multiple elements or nuclides to a material Parameters ---------- - components : dict of str to tuple - Dictionary mapping element or nuclide names to a tuple containing - their atom or weight percent, as well as any other arguments. + components : dict of str to float or dict + Dictionary mapping element or nuclide names to their atom or weight + percent. To specify enrichment of an element, the entry of + ``components`` for that element must instead be a dictionary + containing the keyword arguments as well as a value for + ``'percent'`` + percent_type : {'ao', 'wo'} + 'ao' for atom percent and 'wo' for weight percent Examples -------- >>> mat = openmc.Material() - >>> components = {'Li': (1.0, {'enrichment': 60.0, 'enrichment_target': 'Li7'}), - >>> 'Fl': 1.0, - >>> 'Be6': (0.5, 'wo')} - >>> mat.add_elements_or_nuclides(components) + >>> components = {'Li': {'percent': 1.0, + >>> 'enrichment': 60.0, + >>> 'enrichment_target': 'Li7'}, + >>> 'Fl': 1.0, + >>> 'Be6': 0.5} + >>> mat.add_components(components) """ - for component, args in components.items(): + for component, params in components.items(): cv.check_type('component', component, str) - percent_type = 'ao' - if isinstance(args, float): - args = (args,) + if isinstance(params, float): + params = {'percent': params} + + else: + cv.check_type('params', params, dict) + if 'percent' not in params: + raise ValueError("An entry in the dictionary does not have " + "a required key: 'percent'") + + percent = params.pop('percent') + args = (percent, percent_type) ## check if nuclide if str.isdigit(component[-1]): self.add_nuclide(component, *args) else: # is element - kwargs = {} - if isinstance(args[-1], dict): - kwargs = args[-1] - args = args[:-1] + kwargs = params self.add_element(component, *args, **kwargs) + params['percent'] = percent + def remove_nuclide(self, nuclide: str): """Remove a nuclide from the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 69ca87f2e..2c5cc2874 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -25,39 +25,51 @@ def test_add_nuclide(): with pytest.raises(ValueError): m.add_nuclide('H1', 1.0, 'oa') -def test_add_elements_or_nuclides(): +def test_add_components(): """Test adding multipe elements or nuclides at once""" m = openmc.Material() components = {'H1': 2.0, - 'O16': (1.0, 'wo'), - 'Zr': 1.0, - 'O': (1.0, 'wo'), - 'U': (1.0, {'enrichment': 4.5}), - 'Li': (1.0, 'ao', {'enrichment': 60.0, 'enrichment_target': 'Li7'}), - 'H': (1.0, 'ao', {'enrichment': 50.0, 'enrichment_target': 'H2', 'enrichment_type': 'wo'})} - m.add_elements_or_nuclides(components) + 'O16': 1.0, + 'Zr': 1.0, + 'O': 1.0, + 'U': {'percent': 1.0, + 'enrichment': 4.5}, + 'Li': {'percent': 1.0, + 'enrichment': 60.0, + 'enrichment_target': 'Li7'}, + 'H': {'percent': 1.0, + 'enrichment': 50.0, + 'enrichment_target': 'H2', + 'enrichment_type': 'wo'}} + m.add_components(components) with pytest.raises(ValueError): - m.add_elements_or_nuclides({'U': (1.0, 'ao', {'enrichment': 100.0})}) + m.add_components({'U': {'percent': 1.0, + 'enrichment': 100.0}}) with pytest.raises(ValueError): - m.add_elements_or_nuclides({'Pu': (1.0, 'ao', {'enrichment': 3.0})}) + m.add_components({'Pu': {'percent': 1.0, + 'enrichment': 3.0}}) with pytest.raises(ValueError): - m.add_elements_or_nuclides({'U': (1.0, 'ao', {'enrichment': 70.0, 'enrichment_target': 'U235'})}) + m.add_components({'U': {'percent': 1.0, + 'enrichment': 70.0, + 'enrichment_target':'U235'}}) with pytest.raises(ValueError): - m.add_elements_or_nuclides({'He': (1.0, 'ao', {'enrichment': 17.0, 'enrichment_target': 'He6'})}) + m.add_components({'He': {'percent': 1.0, + 'enrichment': 17.0, + 'enrichment_target': 'He6'}}) with pytest.raises(ValueError): - m.add_elements_or_nuclides({'li': (1.0, 'ao')}) # should fail as 1st char is lowercase + m.add_components({'li': 1.0}) # should fail as 1st char is lowercase with pytest.raises(ValueError): - m.add_elements_or_nuclides({'LI': (1.0, 'ao')}) # should fail as 2nd char is uppercase + m.add_components({'LI': 1.0}) # should fail as 2nd char is uppercase with pytest.raises(ValueError): - m.add_elements_or_nuclides({'Xx': (1.0, 'ao')}) # should fail as Xx is not an element + m.add_components({'Xx': 1.0}) # should fail as Xx is not an element with pytest.raises(ValueError): - m.add_elements_or_nuclides({'n': (1.0, 'ao')}) # check to avoid n for neutron being accepted + m.add_components({'n': 1.0}) # check to avoid n for neutron being accepted with pytest.raises(TypeError): - m.add_elements_or_nuclides({'H1': ('1.0', 'ao')}) + m.add_components({'H1': '1.0'}) with pytest.raises(TypeError): - m.add_elements_or_nuclides({1.0: ('H1', 'wo')}) + m.add_components({1.0: 'H1'}, percent_type = 'wo') with pytest.raises(ValueError): - m.add_elements_or_nuclides({'H1': (1.0, 'oa')}) + m.add_components({'H1': 1.0}, percent_type = 'oa') def test_remove_nuclide(): From ea1e2d02c42465413341eb841f9ab5e3fa559260 Mon Sep 17 00:00:00 2001 From: yardasol Date: Fri, 29 Jul 2022 22:59:47 -0500 Subject: [PATCH 0712/2654] Adjust docpages to accomodate new transport-independent depletion scheme. --- docs/source/methods/depletion.rst | 81 ++++---- docs/source/pythonapi/deplete.rst | 27 +-- docs/source/usersguide/depletion.rst | 284 ++++++++++++++++++--------- 3 files changed, 248 insertions(+), 144 deletions(-) diff --git a/docs/source/methods/depletion.rst b/docs/source/methods/depletion.rst index dce1f2503..0e06b3a50 100644 --- a/docs/source/methods/depletion.rst +++ b/docs/source/methods/depletion.rst @@ -103,16 +103,16 @@ integrate over the entire timestep. Our aim here is not to exhaustively describe all integration methods but rather to give a few examples that elucidate the main considerations one must take into account when choosing a method. Generally, there is a tradeoff between the -accuracy of the method and its computational expense. The expense is driven -almost entirely by the time to compute a transport solution, i.e., to evaluate -:math:`\mathbf{A}` for a given :math:`\mathbf{n}`. Thus, the cost of a method -scales with the number of :math:`\mathbf{A}` evaluations that are performed per -timestep. On the other hand, methods that require more evaluations generally -achieve higher accuracy. The predictor method only requires one evaluation and -its error converges as :math:`\mathcal{O}(h)`. The CE/CM method requires two -evaluations and is thus twice as expensive as the predictor method, but achieves -an error of :math:`\mathcal{O}(h^2)`. An exhaustive description of time -integration methods and their merits can be found in the `thesis of Colin Josey +accuracy of the method and its computational expense. In the case of +transport-coupled depletion, the expense is driven almost entirely by the time +to compute a transport solution, i.e., to evaluate :math:`\mathbf{A}` for a +given :math:`\mathbf{n}`. Thus, the cost of a method scales with the number of +:math:`\mathbf{A}` evaluations that are performed per timestep. On the other +hand, methods that require more evaluations generally achieve higher accuracy. The predictor method only requires one evaluation and its error converges as +:math:`\mathcal{O}(h)`. The CE/CM method requires two evaluations and is thus +twice as expensive as the predictor method, but achieves an error of +:math:`\mathcal{O}(h^2)`. An exhaustive description of time integration methods +and their merits can be found in the `thesis of Colin Josey `_. OpenMC does not rely on a single time integration method but rather has several @@ -169,12 +169,14 @@ Data Considerations In principle, solving Eq. :eq:`depletion-matrix` using CRAM is fairly simple: just construct the burnup matrix at various times and solve a set of sparse -linear systems. However, constructing the burnup matrix itself involves not only -solving the transport equation to estimate transmutation reaction rates but also -a series of choices about what data to include. In OpenMC, the burnup matrix is -constructed based on data inside of a *depletion chain* file, which includes -fundamental data gathered from ENDF incident neutron, decay, and fission product -yield sublibraries. For each nuclide, this file includes: +linear systems. However, constructing the burnup matrix itself involves not +only solving the transport equation to estimate transmutation reaction rates +(in the case of transport-coupled depletion) or to obtain microscopic cross +sections (in the case of transport-independent depletion), but also a series of +choices about what data to include. In OpenMC, the burnup matrix is constructed +based on data inside of a *depletion chain* file, which includes fundamental +data gathered from ENDF incident neutron, decay, and fission product yield +sublibraries. For each nuclide, this file includes: - What transmutation reactions are possible, their Q values, and their products; - If a nuclide is not stable, what decay modes are possible, their branching @@ -185,9 +187,12 @@ yield sublibraries. For each nuclide, this file includes: Transmutation Reactions ----------------------- -OpenMC will setup tallies in a problem based on what transmutation reactions are -available in a depletion chain file, so any arbitrary number of transmutation -reactions can be tracked. The pregenerated chain files that are available on +In transport-coupled depletion, OpenMC will setup tallies in a problem based on +what transmutation reactions are available in a depletion chain file, so any +arbitrary number of transmutation reactions can be tracked. In +transport-independent depletion, OpenMC will calculate reaction rates for every +reaction that is present in both the available cross sections and the depletion +chain file. The pregenerated chain files that are available on https://openmc.org include the following transmutation reactions: fission, (n,\ :math:`\gamma`\ ), (n,2n), (n,3n), (n,4n), (n,p), and (n,\ :math:`\alpha`\ ). @@ -202,11 +207,12 @@ accurately model the branching of the capture reaction in Am241. This is complicated by the fact that the branching ratio may depend on the incident neutron energy causing capture. -OpenMC does not currently allow energy-dependent capture branching ratios. -However, the depletion chain file does allow a transmutation reaction to be -listed multiple times with different branching ratios resulting in different -products. Spectrum-averaged capture branching ratios have been computed in LWR -and SFR spectra and are available at https://openmc.org/depletion-chains. +OpenMC's transport solver does not currently allow energy-dependent capture +branching ratios. However, the depletion chain file does allow a transmutation +reaction to be listed multiple times with different branching ratios resulting +in different products. Spectrum-averaged capture branching ratios have been +computed in LWR and SFR spectra and are available at +https://openmc.org/depletion-chains. Fission Product Yields ---------------------- @@ -217,26 +223,31 @@ energies. It is an open question as to what the best way to handle this energy dependence is. OpenMC includes three methods for treating the energy dependence of FPY: -1. Use FPY data corresponding to a specified energy. +1. Use FPY data corresponding to a specified energy. This is used by default in + both transport-coupled and transport-independent depletion. 2. Tally fission rates above and below a specified cutoff energy. Assume that all fissions below the cutoff energy correspond to thermal FPY data and all - fission above the cutoff energy correspond to fast FPY data. + fission above the cutoff energy correspond to fast FPY data. Only applicable + to transport-coupled depletion. 3. Compute the average energy at which fission events occur and use an effective FPY by linearly interpolating between FPY provided at neighboring energies. + Only applicable to transport-coupled depletion -The method can be selected through the ``fission_yield_mode`` argument to the -:class:`openmc.deplete.Operator` constructor. +The method for transport-coupled depletion can be selected through the +``fission_yield_mode`` argument to the :class:`openmc.deplete.Operator` +constructor. Power Normalization ------------------- -The reaction rates provided OpenMC are given in units of reactions per source -particle. For depletion, it is necessary to compute an absolute reaction rate in -reactions per second. To do so, the reaction rates are normalized based on a -specified power. A complete description of how this normalization can be -performed is described in :ref:`usersguide_tally_normalization`. Here, we simply -note that the main depletion class, :class:`openmc.deplete.Operator`, allows the -user to choose one of two methods for estimating the heating rate, including: +In transport-coupled depletion, the reaction rates provided OpenMC are given in +units of reactions per source particle. For depletion, it is necessary to +compute an absolute reaction rate in reactions per second. To do so, the +reaction rates are normalized based on a specified power. A complete +description of how this normalization can be performed is described in +:ref:`usersguide_tally_normalization`. Here, we simply note that the main +depletion class, :class:`openmc.deplete.Operator`, allows the user to choose +one of two methods for estimating the heating rate, including: 1. Using fixed Q values from a depletion chain file (useful for comparisons to other codes that use fixed Q values), or diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 246cea59f..cc36a17c7 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -12,19 +12,20 @@ Primary API The two primary requirements to perform depletion with :mod:`openmc.deplete` are: - 1) A transport operator + 1) A reaction rate operator 2) A time-integration scheme -The former is responsible for executing a transport code, like OpenMC, -and retaining important information required for depletion. The most common examples -are reaction rates and power normalization data. The latter is responsible for -projecting reaction rates and compositions forward in calendar time across -some step size :math:`\Delta t`, and obtaining new compositions given a power -or power density. The :class:`Operator` is provided to handle communicating with -OpenMC. Several classes are provided that implement different time-integration -algorithms for depletion calculations, which are described in detail in Colin -Josey's thesis, `Development and analysis of high order neutron -transport-depletion coupling algorithms `_. +The former is responsible for obtaining transmuation reaction rates. The latter +is responsible for projecting reaction rates and compositions forward in +calendar time across some step size :math:`\Delta t`, and obtaining new +compositions given a power or power density. The :class:`Operator` class is +provided to obtain reaction rates via tallies through OpenMC's transport +solver, and the :class:`IndependentOperator` class is provided to obtain +reaction rates from cross-section data. Several classes are provided that +implement different time-integration algorithms for depletion calculations, +which are described in detail in Colin Josey's thesis, `Development and +analysis of high order neutron transport-depletion coupling algorithms +`_. .. autosummary:: :toctree: generated @@ -40,8 +41,8 @@ transport-depletion coupling algorithms `_. SICELIIntegrator SILEQIIntegrator -Each of these classes expects a "transport operator" to be passed. Operators -specific to OpenMC are available using the following classes: +Each of these classes expects a "reaction rate operator" to be passed. Operators +provided by OpenMC are available using the following classes: .. autosummary:: :toctree: generated diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 0bc2a5af9..7409c6610 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -4,23 +4,55 @@ Depletion and Transmutation =========================== -OpenMC supports coupled depletion, or burnup, calculations through the -:mod:`openmc.deplete` Python module. OpenMC solves the transport equation to -obtain transmutation reaction rates, and then the reaction rates are used to -solve a set of transmutation equations that determine the evolution of nuclide -densities within a material. The nuclide densities predicted as some future time -are then used to determine updated reaction rates, and the process is repeated -for as many timesteps as are requested. +OpenMC supports transport-coupled and transport-independent depletion, or +burnup, calculations through the :mod:`openmc.deplete` Python module. OpenMC +uses transmutation reaction rates to solve a set of transmutation equations +that determine the evolution of nuclide densities within a material. The +nuclide densities predicted as some future time are then used to determine +updated reaction rates, and the process is repeated for as many timesteps as +are requested. -The depletion module is designed such that the flux/reaction rate solution (the -transport "operator") is completely isolated from the solution of the -transmutation equations and the method used for advancing time. At present, the -:mod:`openmc.deplete` module offers a single transport operator, -:class:`openmc.deplete.Operator` (which uses the OpenMC transport solver), but -in principle additional operator classes based on other transport codes could be -implemented and no changes to the depletion solver itself would be needed. The -operator class requires a :class:`~openmc.Model` instance containing -material, geometry, and settings information:: +The depletion module is designed such that the reaction rate solution (the +"operator") is completely isolated from the solution of the transmutation +equations and the method used for advancing time. + +:mod:`openmc.deplete` supports multiple time-integration methods for determining +material compositions over time. Each method appears as a different class. +For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation +using the CE/CM algorithm (deplete over a timestep using the middle-of-step +reaction rates). An instance of :class:`~openmc.deplete.abc.TransportOperator` +is passed to one of these functions along with the timesteps and power level:: + + power = 1200.0e6 # watts + timesteps = [10.0, 10.0, 10.0] # days + openmc.deplete.CECMIntegrator(op, timesteps, power, timestep_units='d').integrate() + +The depletion problem is executed, and once it is done a +``depletion_results.h5`` file is written. The results can be analyzed using the +:class:`openmc.deplete.Results` class. This class has methods that allow for +easy retrieval of k-effective, nuclide concentrations, and reaction rates over +time:: + + results = openmc.deplete.Results("depletion_results.h5") + time, keff = results.get_keff() + +Note that the coupling between the reaction rate solver and the transmutation +solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of +operators for obtaining transmutation reaction rates. + +.. _coupled-depletion: + +Transport-coupled depletion +=========================== + +This category of operator solves the transport equation to obtain transmutation +reaction rates. At present, the :mod:`openmc.deplete` module offers a single +transport-coupled operator, :class:`openmc.deplete.Operator` (which uses the +OpenMC transport solver), but in principle additional transport-coupled operator +classes based on other transport codes could be implemented and no changes to +the depletion solver itself would be needed. The +:class:`openmc.deplete.Operator` class requires a :class:`~openmc.Model` +instance containing material, geometry, and settings information:: model = openmc.Model() ... @@ -30,36 +62,14 @@ material, geometry, and settings information:: Any material that contains a fissionable nuclide is depleted by default, but this can behavior can be changed with the :attr:`Material.depletable` attribute. -.. important:: The volume must be specified for each material that is depleted by - setting the :attr:`Material.volume` attribute. This is necessary - in order to calculate the proper normalization of tally results - based on the source rate. - -:mod:`openmc.deplete` supports multiple time-integration methods for determining -material compositions over time. Each method appears as a different class. -For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation -using the CE/CM algorithm (deplete over a timestep using the middle-of-step -reaction rates). An instance of :class:`openmc.deplete.Operator` is passed to -one of these functions along with the timesteps and power level:: - - power = 1200.0e6 # watts - timesteps = [10.0, 10.0, 10.0] # days - openmc.deplete.CECMIntegrator(op, timesteps, power, timestep_units='d').integrate() - -The coupled transport-depletion problem is executed, and once it is done a -``depletion_results.h5`` file is written. The results can be analyzed using the -:class:`openmc.deplete.Results` class. This class has methods that allow for -easy retrieval of k-effective, nuclide concentrations, and reaction rates over -time:: - - results = openmc.deplete.Results("depletion_results.h5") - time, keff = results.get_keff() - -Note that the coupling between the transport solver and the transmutation solver -happens in-memory rather than by reading/writing files on disk. +.. important:: + + The volume must be specified for each material that is depleted by setting + the :attr:`Material.volume` attribute. This is necessary in order to + calculate the proper normalization of tally results based on the source rate. Fixed-Source Transmutation -========================== +-------------------------- When the ``power`` or ``power_density`` argument is used for one of the Integrator classes, it is assumed that OpenMC is running in k-eigenvalue mode, @@ -91,10 +101,12 @@ timestep in the calculation. A zero source rate for a given timestep will result in a decay-only step, where all reaction rates are zero. Caveats -======= +------- + +.. _energy-deposition: Energy Deposition ------------------ +~~~~~~~~~~~~~~~~~ The default energy deposition mode, ``"fission-q"``, instructs the :class:`~openmc.deplete.Operator` to normalize reaction rates using the product @@ -126,7 +138,7 @@ should be, including indirect components. Some examples are provided below:: A more complete way to model the energy deposition is to use the modified -heating reactions described in :ref:`methods_heating`. These values can be used +heating reactions described in :ref:`methods_heating`. These values can be used to normalize reaction rates instead of using the fission reaction rates with:: op = openmc.deplete.Operator(model, "chain.xml", @@ -137,7 +149,7 @@ of :meth:`openmc.data.IncidentNeutron.from_njoy()`, and will eventually be bundl into the distributed libraries. Local Spectra and Repeated Materials ------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is not uncommon to explicitly create a single burnable material across many locations. From a pure transport perspective, there is nothing wrong with @@ -184,42 +196,81 @@ Transport-independent depletion .. note:: - This feature is still under heavy development. API changes are - possible and likely in the near future. + This feature is still under heavy development and has yet to be verifed + code-to-code . API changes and feature additions are possible and likely in + the near future. -OpenMC supports running depletion calculations independent of the OpenMC -transport solver using the :class:`~openmc.deplete.IndependentOperator` class. -This class supports both constant-flux (``source-rate`` normalization) and -constant-power depletion (``fission-q`` normalization). +This category of operator uses pre-calculated one-group microscopic cross +sections to obtain transmutation reaction rates. OpenMC provides the +:class:`~openmc.deplete.IndependentOperator` for this method of calculation. +While the one-group microscopic cross sections can be calculated using a +transport solver, :class:`~openmc.deplete.IndependentOperator` is not directly +coupled to any transport solver. The +:class:`~openmc.deplete.IndependentOperator` class requires a +:class:`openmc.Materials` object, a :class:`~openmc.deplete.MicroXS` object, +and a path to a depletion chain file:: -.. important:: + # load in the microscopic cross sections + materials = openmc.Materials() + ... - Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` - class. Use the ``source_rates`` parameter when - ``normalization_mode == source-rate``, and use ``power`` or ``power_density`` - when ``normalization_mode == fission-q``. + micro_xs = openmc.deplete.MicroXS() + ... -.. warning:: + op = IndependentOperator(materials, micro_xs, chain_file) - The accuracy of results when using ``fission-q`` is entirely dependent on - your depletion chain. Make sure it has sufficient data to resolve the - dynamics of your particular scenario. +.. note:: -:class:`~openmc.deplete.IndependentOperator` class uses one-group microscopic cross sections to calculate reaction -rates. Users can generate one-group microscopic cross sections using the + The same statements from :ref:`coupled-depletion` about which + materials are depleted and the requirement for depletable materials to have + a specified volume also apply here. + +An alternate constructor, +:meth:`~openmc.deplete.IndependentOperator.from_nuclides`, accepts a volume and +dictionary of nuclide concentrations in place of the :class:`openmc.Materials` +object:: + + nuclides = {'U234': 8.92e18, + 'U235': 9.98e20, + 'U238': 2.22e22, + 'U236': 4.57e18, + 'O16': 4.64e22, + 'O17': 1.76e19} + volume = 0.5 + op = openmc.deplete.IndependentOperator.from_nuclides(volume, + nuclides, + micro_xs, + chain_file, + nuc_units='atom/cm3') + +A user can then define an integrator class as they would for a coupled +transport-depletion calculation and follow the same steps from there. + +.. note:: + + Ideally, one-group cross section data should be available for every + reaction in the depletion chain. If a nuclide that has a reaction + associated with it in the depletion chain is present in the `nuclides` + parameter but not the cross section data, that reaction will not be + simulated. + +Generating Microscopic Cross Sections +------------------------------------- + +Users can generate the one-group microscopic cross sections needed by +:class:`~openmc.deplete.IndependentOperator` using the :class:`~openmc.deplete.MicroXS` class:: import openmc - from openmc.deplete import MicroXS model = openmc.Model.from_xml() - micro_xs = MicroXS.from_model(model, model.materials[0]) + micro_xs = openmc.deplete.MicroXS.from_model(model, model.materials[0]) - micro_xs.to_csv(micro_xs_path) - -:class:`~openmc.deplete.MicroXS` also includes functions to read in cross -section data directly from a ``.csv`` file or from data arrays:: +The :meth:`~openmc.deplete.MicroXS.from_model()` method will produce a +:class:`~openmc.deplete.MicroXS` object with microscopic cross section data in +units of ``b``, which is what :class:`~openmc.deplete.IndependentOperator` +expects the units to be. The :class:`~openmc.deplete.MicroXS` class also includes functions to read in cross section data directly from a ``.csv`` file or from data arrays:: micro_xs = MicroXS.from_csv(micro_xs_path) @@ -230,32 +281,73 @@ section data directly from a ``.csv`` file or from data arrays:: [0.01, 0.5]]) micro_xs = MicroXS.from_array(nuclides, reactions, data) -:class:`~openmc.deplete.IndependentOperator` has two ways to initialize it: -the default constructor accepts an :class:`openmc.Materials` object and -one-group microscopic cross sections as a :class:`~openmc.deplete.MicroXS` -object, while the :meth:`~openmc.deplete.IndependentOperator.from_nuclides` -method accepts a volume and dictionary of nuclide concentrations in place of the -:class:`openmc.Materials` object in addition to the other parameters:: +.. important :: - # load in the microscopic cross sections - op = IndependentOperator(materials, micro_xs, chain_file) + Both :meth:`~openmc.deplete.MicroXS.from_csv()` and + :meth:`~openmc.deplete.MicroXS.from_array()` assume the cross section values + provided are in barns by defualt, but have no way of verifying this. Make + sure your cross sections are in the correct units before passing to a + :class:`~openmc.deplete.IndependentOperator` object. - # alternate construtor - nuclides = {'U234': 8.92e18, - 'U235': 9.98e20, - 'U238': 2.22e22, - 'U236': 4.57e18, - 'O16': 4.64e22, - 'O17': 1.76e19} - volume = 0.5 - op = IndependentOperator.from_nuclides(volume, nuclides, micro_xs, - chain_file, nuc_units='atom/cm3') +Caveats +------- -A user can then define an integrator class as they would for a coupled -transport-depletion calculation and follow the same steps from there. +Reaction Rate Normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. note:: Ideally, one-group cross section data should be available for every - reaction in the depletion chain. If a nuclide that has a reaction - associated with it in the depletion chain is present in the `nuclides` - parameter but not the cross section data, that reaction will not be - simulated. +The :class:`~openmc.deplete.IndependentOperator` class supports two methods for +normalizing reaction rates: + +.. important:: + + Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` + class. Use the ``source_rates`` parameter when + ``normalization_mode == source-rate``, and use ``power`` or ``power_density`` + when ``normalization_mode == fission-q``. + +1. ``soure-rate`` normalization, which assumes the ``source-rate`` provided by + the time integrator is a flux, and obtains the reaction rates by multiplying + the cross-sections by the ``source-rate``. +2. ``fission-q`` normalization, which assumes the ``source-rate`` provided by + the time integrator is a power, and obtains the reaction rates by computing a + value for the flux based on this power. The general equation for the flux is + + .. math:: + + \phi = \frac{P}{V \cdot \sum_i (Q_i \cdot \Sigma^f_i \cdot \rho_i)} + + where :math:`\sum_i` is the sum over all nuclides :math:`i`. This equation + makes the same assumptions and issues as discussed in + :ref:`energy-deposition`. Unfortunately, the proposed solution in that + section does not apply here since we are decoupled from transport code. + However, there is a method to converge to a more accurate value for flux by + using substeps during time integration. + `This paper `_ provides a + good discussion of this method. Hopefully such a method will be implemented + in OpenMC in the near future. + +.. warning:: + + The accuracy of results when using ``fission-q`` is entirely dependent on + your depletion chain. Make sure it has sufficient data to resolve the + dynamics of your particular scenario. + +Multiple Materials +~~~~~~~~~~~~~~~~~~ + +Running a depletion simulation with multiple materials using the +``source-rate`` normalization method treats each material as completely +separate with respect to reaction rates. This can be useful for running many +different cases of a particular scenario. However, running a depletion +simulation with multiple materials using the ``fission-q`` normalization method +treats each material as part of the same "reactor" due to how ``fission-q`` +normalization conglomerates energy values from each material to a single value. +This behavior may change in the future. + +Time integration +~~~~~~~~~~~~~~~~ + +The one-group microscopic cross sections passed to +:class:`openmc.deplete.IndependentOperator` are fixed values for the entire +depletion simulation. This implicit assumption may produce inaccurate results +for certain scenarios. From 511464b53b590549b053b386ac336b47ad3ca1a6 Mon Sep 17 00:00:00 2001 From: yardasol Date: Sat, 30 Jul 2022 15:39:47 -0500 Subject: [PATCH 0713/2654] adjust top-level module descriptions --- openmc/deplete/abc.py | 9 ++++----- openmc/deplete/helpers.py | 2 +- openmc/deplete/independent_operator.py | 2 +- openmc/deplete/operator.py | 10 +++++----- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index cdbd1361a..5cb3b254a 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -1,7 +1,6 @@ -"""function module. +"""abc module. -This module contains the Operator class, which is then passed to an integrator -to run a full depletion simulation. +This module contains Abstract Base Classes for implementing operator, integrator, depletion system solver, and operator helper classes """ from abc import ABC, abstractmethod @@ -864,8 +863,8 @@ class SIIntegrator(Integrator): initial heavy metal inventory to get total power if ``power`` is not specified. source_rates : float or iterable of float, optional - Source rate in [neutron/sec] or neutron flux in [neutron/s-cm^2] for each - interval in :attr:`timesteps` + Source rate in [neutron/sec] or neutron flux in [neutron/s-cm^2] for + each interval in :attr:`timesteps` .. versionadded:: 0.12.1 timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 7b863b69a..4fcde4f6b 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -1,5 +1,5 @@ """ -Class for normalizing fission energy deposition +Classes for collecting and calculating quantities for reaction rate operators """ import bisect from abc import abstractmethod diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index 98ef6656d..a7eb54f57 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -1,4 +1,4 @@ -"""Independent depletion operator +"""Transport-independent operator for depletion. This module implements a depletion operator that runs independently of any transport solver by using user-provided one-group cross sections. diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 53a1db3e9..2f8dcfba2 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -1,9 +1,9 @@ -"""OpenMC transport operator +"""Transport-coupled operator for depletion. -This module implements a transport operator for OpenMC so that it can be used by -depletion integrators. The implementation makes use of the Python bindings to -OpenMC's C API so that reading tally results and updating material number -densities is all done in-memory instead of through the filesystem. +This module implements an operator coupled to OpenMC's transport sovler so that +it can be used by depletion integrators. The implementation makes use of the Python bindings to OpenMC's C API so that reading tally results and updating +material number densities is all done in-memory instead of through the +filesystem. """ From 773757246bbbd6a680a6bc1648c1ae7d2cbc88ed Mon Sep 17 00:00:00 2001 From: yardasol Date: Sat, 30 Jul 2022 16:46:31 -0500 Subject: [PATCH 0714/2654] Operator->CoupledOperator - update references in docstrings and docpages - minor adjustments to related docs in deplete module files - retain backwards compatiblity by exporint Operator alias --- docs/source/methods/depletion.rst | 8 ++--- docs/source/pythonapi/deplete.rst | 16 +++++----- docs/source/usersguide/depletion.rst | 43 +++++++++++++------------- openmc/deplete/abc.py | 46 +++++++++++++++------------- openmc/deplete/chain.py | 3 +- openmc/deplete/helpers.py | 25 ++++++++------- openmc/deplete/operator.py | 27 ++++++++-------- openmc/deplete/results.py | 10 +++--- 8 files changed, 96 insertions(+), 82 deletions(-) diff --git a/docs/source/methods/depletion.rst b/docs/source/methods/depletion.rst index 0e06b3a50..66ee50397 100644 --- a/docs/source/methods/depletion.rst +++ b/docs/source/methods/depletion.rst @@ -234,7 +234,7 @@ of FPY: Only applicable to transport-coupled depletion The method for transport-coupled depletion can be selected through the -``fission_yield_mode`` argument to the :class:`openmc.deplete.Operator` +``fission_yield_mode`` argument to the :class:`openmc.deplete.CoupledOperator` constructor. Power Normalization @@ -246,8 +246,8 @@ compute an absolute reaction rate in reactions per second. To do so, the reaction rates are normalized based on a specified power. A complete description of how this normalization can be performed is described in :ref:`usersguide_tally_normalization`. Here, we simply note that the main -depletion class, :class:`openmc.deplete.Operator`, allows the user to choose -one of two methods for estimating the heating rate, including: +depletion class, :class:`openmc.deplete.CoupledOperator`, allows the user to +choose one of two methods for estimating the heating rate, including: 1. Using fixed Q values from a depletion chain file (useful for comparisons to other codes that use fixed Q values), or @@ -255,4 +255,4 @@ one of two methods for estimating the heating rate, including: energy-dependent estimate of the true heating rate. The method for normalization can be chosen through the ``normalization_mode`` -argument to the :class:`openmc.deplete.Operator` class. +argument to the :class:`openmc.deplete.CoupledOperator` class. diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index cc36a17c7..bc07ed1b0 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -18,8 +18,8 @@ are: The former is responsible for obtaining transmuation reaction rates. The latter is responsible for projecting reaction rates and compositions forward in calendar time across some step size :math:`\Delta t`, and obtaining new -compositions given a power or power density. The :class:`Operator` class is -provided to obtain reaction rates via tallies through OpenMC's transport +compositions given a power or power density. The :class:`CoupledOperator` class +is provided to obtain reaction rates via tallies through OpenMC's transport solver, and the :class:`IndependentOperator` class is provided to obtain reaction rates from cross-section data. Several classes are provided that implement different time-integration algorithms for depletion calculations, @@ -49,11 +49,11 @@ provided by OpenMC are available using the following classes: :nosignatures: :template: mycallable.rst - Operator + CoupledOperator IndependentOperator -The :class:`Operator` and :class:`IndependentOperator` classes must also have -some knowledge of how nuclides transmute and decay. This is handled by the +The :class:`CoupledOperator` and :class:`IndependentOperator` classes must also +have some knowledge of how nuclides transmute and decay. This is handled by the :class:`Chain`. Minimal Example @@ -71,7 +71,7 @@ A minimal example for performing depletion would be: # Representation of a depletion chain >>> chain_file = "chain_casl.xml" - >>> operator = openmc.deplete.Operator( + >>> operator = openmc.deplete.CoupledOperator( ... model, chain_file) # Set up 5 time steps of one day each @@ -177,7 +177,7 @@ with :func:`cram.CRAM48` being the default. :class:`multiprocessing.pool.Pool` class. If set to ``None`` (default), the number returned by :func:`os.cpu_count` is used. -The following classes are used to help the :class:`openmc.deplete.Operator` +The following classes are used to help the :class:`openmc.deplete.CoupledOperator` compute quantities like effective fission yields, reaction rates, and total system energy. @@ -194,6 +194,8 @@ total system energy. helpers.FissionYieldCutoffHelper helpers.FluxCollapseHelper +The :class:`openmc.deplete.IndependentOperator` uses inner class subclassed from +those listed to perform similar calculations. Intermediate Classes -------------------- diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 7409c6610..990031c40 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -47,17 +47,17 @@ Transport-coupled depletion This category of operator solves the transport equation to obtain transmutation reaction rates. At present, the :mod:`openmc.deplete` module offers a single -transport-coupled operator, :class:`openmc.deplete.Operator` (which uses the -OpenMC transport solver), but in principle additional transport-coupled operator -classes based on other transport codes could be implemented and no changes to -the depletion solver itself would be needed. The -:class:`openmc.deplete.Operator` class requires a :class:`~openmc.Model` +transport-coupled operator, :class:`openmc.deplete.CoupledOperator` (which uses +the OpenMC transport solver), but in principle additional transport-coupled +operator classes based on other transport codes could be implemented and no +changes to the depletion solver itself would be needed. The +:class:`openmc.deplete.CoupledOperator` class requires a :class:`~openmc.Model` instance containing material, geometry, and settings information:: model = openmc.Model() ... - op = openmc.deplete.Operator(model) + op = openmc.deplete.CoupledOperator(model) Any material that contains a fissionable nuclide is depleted by default, but this can behavior can be changed with the :attr:`Material.depletable` attribute. @@ -86,11 +86,11 @@ using the :attr:`Material.depletable` attribute:: mat = openmc.Material() mat.depletable = True -When constructing the :class:`~openmc.deplete.Operator`, you should indicate -that normalization of tally results will be done based on the source rate rather -than a power or power density:: +When constructing the :class:`~openmc.deplete.CoupledOperator`, you should +indicate that normalization of tally results will be done based on the source +rate rather than a power or power density:: - op = openmc.deplete.Operator(model, normalization_mode='source-rate') + op = openmc.deplete.CoupledOperator(model, normalization_mode='source-rate') Finally, when creating a depletion integrator, use the ``source_rates`` argument:: @@ -109,13 +109,14 @@ Energy Deposition ~~~~~~~~~~~~~~~~~ The default energy deposition mode, ``"fission-q"``, instructs the -:class:`~openmc.deplete.Operator` to normalize reaction rates using the product -of fission reaction rates and fission Q values taken from the depletion chain. -This approach does not consider indirect contributions to energy deposition, -such as neutron heating and energy from secondary photons. In doing this, the -energy deposited during a transport calculation will be lower than expected. -This causes the reaction rates to be over-adjusted to hit the user-specific -power, or power density, leading to an over-depletion of burnable materials. +:class:`~openmc.deplete.CoupledOperator` to normalize reaction rates using the +product of fission reaction rates and fission Q values taken from the depletion +chain. This approach does not consider indirect contributions to energy +deposition, such as neutron heating and energy from secondary photons. In doing +this, the energy deposited during a transport calculation will be lower than +expected. This causes the reaction rates to be over-adjusted to hit the +user-specific power, or power density, leading to an over-depletion of burnable +materials. There are some remedies. First, the fission Q values can be directly set in a variety of ways. This requires knowing what the total fission energy release @@ -130,10 +131,10 @@ should be, including indirect components. Some examples are provided below:: # create a modified chain and write it to a new file chain = openmc.deplete.Chain.from_xml("chain.xml", fission_q) chain.export_to_xml("chain_mod_q.xml") - op = openmc.deplete.Operator(model, "chain_mod_q.xml") + op = openmc.deplete.CoupledOperator(model, "chain_mod_q.xml") # alternatively, pass the modified fission Q directly to the operator - op = openmc.deplete.Operator(model, "chain.xml", + op = openmc.deplete.CoupledOperator(model, "chain.xml", fission_q=fission_q) @@ -141,7 +142,7 @@ A more complete way to model the energy deposition is to use the modified heating reactions described in :ref:`methods_heating`. These values can be used to normalize reaction rates instead of using the fission reaction rates with:: - op = openmc.deplete.Operator(model, "chain.xml", + op = openmc.deplete.CoupledOperator(model, "chain.xml", normalization_mode="energy-deposition") These modified heating libraries can be generated by running the latest version @@ -174,7 +175,7 @@ the next transport step. This can be countered by instructing the operator to treat repeated instances of the same material as a unique material definition with:: - op = openmc.deplete.Operator(model, chain_file, + op = openmc.deplete.CoupledOperator(model, chain_file, diff_burnable_mats=True) For our example problem, this would deplete fuel on the outer region of the diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 5cb3b254a..dd1fd5b04 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -82,7 +82,8 @@ class TransportOperator(ABC): operator that takes a vector of material compositions and returns an eigenvalue and reaction rates. This abstract class sets the requirements for such a transport operator. Users should instantiate - :class:`openmc.deplete.Operator` rather than this class. + :class:`openmc.deplete.CoupledOperator` or + :class:`openmc.deplete.IndependentOperator` rather than this class. Parameters ---------- @@ -220,9 +221,11 @@ class ReactionRateHelper(ABC): Parameters ---------- n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` + Number of burnable nuclides tracked by + :class:`openmc.deplete.abc.TransportOperator` n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` + Number of reactions tracked by + :class:`openmc.deplete.abc.TransportOperator` Attributes ---------- @@ -291,9 +294,9 @@ class NormalizationHelper(ABC): """Abstract class for obtaining normalization factor on tallies This helper class determines how reaction rates calculated by an instance of - :class:`openmc.deplete.Operator` should be normalized for the purpose of - constructing a burnup matrix. Based on the method chosen, the power or - source rate provided by the user, and reaction rates from a + :class:`openmc.deplete.abc.TransportOperator` should be normalized for the + purpose of constructing a burnup matrix. Based on the method chosen, the + power or source rate provided by the user, and reaction rates from a :class:`ReactionRateHelper`, this class will scale reaction rates to the correct values. @@ -301,7 +304,7 @@ class NormalizationHelper(ABC): ---------- nuclides : list of str All nuclides with desired reaction rates. Ordered to be - consistent with :class:`openmc.deplete.Operator` + consistent with :class:`openmc.deplete.abc.TransportOperator` """ @@ -315,9 +318,9 @@ class NormalizationHelper(ABC): def prepare(self, chain_nucs, rate_index): """Perform work needed to obtain energy produced - This method is called prior to the transport simulations - in :meth:`openmc.deplete.Operator.initial_condition`. Only used for - energy-based normalization. + This method is called prior to calculating the reaction rates + in :meth:`openmc.deplete.abc.TransportOperator.initial_condition`. Only + used for energy-based normalization. Parameters ---------- @@ -430,7 +433,7 @@ class FissionYieldHelper(ABC): def unpack(): """Unpack tally data prior to compute fission yields. - Called after a :meth:`openmc.deplete.Operator.__call__` + Called after a :meth:`openmc.deplete.abc.TransportOperator.__call__` routine during the normalization of reaction rates. Not necessary for all subclasses to implement, unless tallies @@ -451,7 +454,7 @@ class FissionYieldHelper(ABC): mat_indexes : iterable of int Indices of tallied materials that will have their fission yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper + :class:`openmc.deplete.CoupledOperator` that uses this helper may only burn a subset of all materials when running in parallel mode. """ @@ -463,14 +466,15 @@ class FissionYieldHelper(ABC): ---------- nuclides : iterable of str Nuclides with non-zero densities from the - :class:`openmc.deplete.Operator` + :class:`openmc.deplete.abc.TransportOperator` Returns ------- nuclides : list of str - Union of nuclides that the :class:`openmc.deplete.Operator` - says have non-zero densities at this stage and those that - have yield data. Sorted by nuclide name + Union of nuclides that the + :class:`openmc.deplete.abc.TransportOperator` says have non-zero + densities at this stage and those that have yield data. Sorted by + nuclide name """ return sorted(self._chain_set & set(nuclides)) @@ -484,7 +488,7 @@ class FissionYieldHelper(ABC): Parameters ---------- - operator : openmc.deplete.TransportOperator + operator : openmc.deplete.abc.TransportOperator Operator with a depletion chain kwargs: optional Additional keyword arguments to be used in constuction @@ -505,7 +509,7 @@ class Integrator(ABC): _params = r""" Parameters ---------- - operator : openmc.deplete.TransportOperator + operator : openmc.deplete.abc.TransportOperator Operator to perform transport simulations timesteps : iterable of float or iterable of tuple Array of timesteps. Note that values are not cumulative. The units are @@ -548,7 +552,7 @@ class Integrator(ABC): Attributes ---------- - operator : openmc.deplete.TransportOperator + operator : openmc.deplete.abc.TransportOperator Operator to perform transport simulations chain : openmc.deplete.Chain Depletion chain @@ -843,7 +847,7 @@ class SIIntegrator(Integrator): _params = r""" Parameters ---------- - operator : openmc.deplete.TransportOperator + operator : openmc.deplete.abc.TransportOperator The operator object to simulate on. timesteps : iterable of float or iterable of tuple Array of timesteps. Note that values are not cumulative. The units are @@ -889,7 +893,7 @@ class SIIntegrator(Integrator): Attributes ---------- - operator : openmc.deplete.TransportOperator + operator : openmc.deplete.abc.TransportOperator Operator to perform transport simulations chain : openmc.deplete.Chain Depletion chain diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index 0c1c34cf7..d63bc6bfb 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -264,7 +264,8 @@ class Chain: requires a list of ENDF incident neutron, decay, and neutron fission product yield sublibrary files. The depletion chain used during a depletion simulation is indicated by either an argument to - :class:`openmc.deplete.Operator` or through the + :class:`openmc.deplete.CoupledOperator` or + :class:`openmc.deplete.IndependentOperator`, or through the ``depletion_chain`` item in the :envvar:`OPENMC_CROSS_SECTIONS` environment variable. diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 4fcde4f6b..262e61b35 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -68,7 +68,7 @@ class TalliedFissionYieldHelper(FissionYieldHelper): mat_indexes : iterable of int Indices of tallied materials that will have their fission yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper + :class:`openmc.deplete.CoupledOperator` that uses this helper may only burn a subset of all materials when running in parallel mode. """ @@ -133,9 +133,11 @@ class DirectReactionRateHelper(ReactionRateHelper): Parameters ---------- n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` + Number of burnable nuclides tracked by + :class:`openmc.deplete.CoupledOperator` n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` + Number of reactions tracked by an instance of + :class:`openmc.deplete.CoupledOperator` Attributes ---------- @@ -217,9 +219,10 @@ class FluxCollapseHelper(ReactionRateHelper): Parameters ---------- n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` + Number of burnable nuclides tracked by + :class:`openmc.deplete.CoupledOperator` n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` + Number of reactions tracked by :class:`openmc.deplete.CoupledOperator` energies : iterable of float Energy group boundaries for flux spectrum in [eV] reactions : iterable of str @@ -385,7 +388,7 @@ class ChainFissionHelper(EnergyNormalizationHelper): ---------- nuclides : list of str All nuclides with desired reaction rates. Ordered to be - consistent with :class:`openmc.deplete.Operator` + consistent with :class:`openmc.deplete.CoupledOperator` energy : float Total energy [J/s/source neutron] produced in a transport simulation. Updated in the material iteration with :meth:`update`. @@ -637,7 +640,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): that occurred below ``cutoff``. The number of materials in the first axis corresponds to the number of materials burned by the - :class:`openmc.deplete.Operator` + :class:`openmc.deplete.CoupledOperator` """ def __init__(self, chain_nuclides, n_bmats, cutoff=112.0, @@ -694,7 +697,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): Parameters ---------- - operator : openmc.deplete.Operator + operator : openmc.deplete.CoupledOperator Operator with a chain and burnable materials kwargs: Additional keyword arguments to be used in construction @@ -720,7 +723,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): mat_indexes : iterable of int Indices of tallied materials that will have their fission yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper + :class:`openmc.deplete.CoupledOperator` that uses this helper may only burn a subset of all materials when running in parallel mode. """ @@ -845,7 +848,7 @@ class AveragedFissionYieldHelper(TalliedFissionYieldHelper): mat_indexes : iterable of int Indices of tallied materials that will have their fission yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper + :class:`openmc.deplete.CoupledOperator` that uses this helper may only burn a subset of all materials when running in parallel mode. """ @@ -958,7 +961,7 @@ class AveragedFissionYieldHelper(TalliedFissionYieldHelper): Parameters ---------- - operator : openmc.deplete.TransportOperator + operator : openmc.deplete.CoupledOperator Operator with a depletion chain kwargs : Additional keyword arguments to be used in construction diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 2f8dcfba2..8bf031453 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -30,7 +30,7 @@ from .helpers import ( SourceRateHelper, FluxCollapseHelper) -__all__ = ["Operator", "OperatorResult"] +__all__ = ["CoupledOperator", "Operator", "OperatorResult"] def _find_cross_sections(model): @@ -56,13 +56,13 @@ def _find_cross_sections(model): return cross_sections -class Operator(OpenMCOperator): - """OpenMC transport operator for depletion. +class CoupledOperator(OpenMCOperator): + """Transport-coupled operator for depletion. - Instances of this class can be used to perform depletion using OpenMC as the - transport operator. Normally, a user needn't call methods of this class - directly. Instead, an instance of this class is passed to an integrator - class, such as :class:`openmc.deplete.CECMIntegrator`. + Instances of this class can be used to perform transport-coupled depletion + using OpenMC's transport solver. Normally, a user needn't call methods of + this class directly. Instead, an instance of this class is passed to an + integrator class, such as :class:`openmc.deplete.CECMIntegrator`. .. versionchanged:: 0.13.0 The geometry and settings parameters have been replaced with a @@ -193,11 +193,11 @@ class Operator(OpenMCOperator): reduce_chain=False, reduce_chain_level=None): # check for old call to constructor if isinstance(model, openmc.Geometry): - msg = "As of version 0.13.0 openmc.deplete.Operator requires an " \ - "openmc.Model object rather than the openmc.Geometry and " \ - "openmc.Settings parameters. Please use the geometry and " \ - "settings objects passed here to create a model with which " \ - "to generate the depletion Operator." + msg = "As of version 0.13.0 openmc.deplete.CoupledOperator " \ + "requires an openmc.Model object rather than the " \ + "openmc.Geometry and openmc.Settings parameters. Please use " \ + "the geometry and settings objects passed here to create a " \ + " model with which to generate the depletion Operator." raise TypeError(msg) # Determine cross sections / depletion chain @@ -516,3 +516,6 @@ class Operator(OpenMCOperator): """Finalize a depletion simulation and release resources.""" if self.cleanup_when_done: openmc.lib.finalize() + +# Retain deprecated name for the time being +Operator = CoupledOperator diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index c238002fe..1c5535601 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -81,9 +81,9 @@ class Results(list): .. note:: Initial values for some isotopes that do not appear in initial concentrations may be non-zero, depending on the - value of the :attr:`openmc.deplete.Operator.dilute_initial` - attribute. The :class:`openmc.deplete.Operator` class adds isotopes - according to this setting, which can be set to zero. + value of the :attr:`openmc.deplete.CoupledOperator.dilute_initial` + attribute. The :class:`openmc.deplete.CoupledOperator` class adds + isotopes according to this setting, which can be set to zero. Parameters ---------- @@ -145,8 +145,8 @@ class Results(list): Initial values for some isotopes that do not appear in initial concentrations may be non-zero, depending on the - value of :class:`openmc.deplete.Operator` ``dilute_initial`` - The :class:`openmc.deplete.Operator` adds isotopes according + value of :class:`openmc.deplete.CoupledOperator` ``dilute_initial`` + The :class:`openmc.deplete.CoupledOperator` adds isotopes according to this setting, which can be set to zero. Parameters From 467ae6b9fbe2e043510b0fb9587def567bd07dcd Mon Sep 17 00:00:00 2001 From: yardasol Date: Sat, 30 Jul 2022 16:55:36 -0500 Subject: [PATCH 0715/2654] operator.py -> coupled_operator.py --- openmc/deplete/__init__.py | 2 +- openmc/deplete/{operator.py => coupled_operator.py} | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) rename openmc/deplete/{operator.py => coupled_operator.py} (98%) diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py index 12e4abe87..329ee8b52 100644 --- a/openmc/deplete/__init__.py +++ b/openmc/deplete/__init__.py @@ -8,7 +8,7 @@ A depletion front-end tool. from .nuclide import * from .chain import * from .openmc_operator import * -from .operator import * +from .coupled_operator import * from .independent_operator import * from .microxs import * from .reaction_rates import * diff --git a/openmc/deplete/operator.py b/openmc/deplete/coupled_operator.py similarity index 98% rename from openmc/deplete/operator.py rename to openmc/deplete/coupled_operator.py index 8bf031453..35b63e9cf 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/coupled_operator.py @@ -191,6 +191,13 @@ class CoupledOperator(OpenMCOperator): fission_yield_mode="constant", fission_yield_opts=None, reaction_rate_mode="direct", reaction_rate_opts=None, reduce_chain=False, reduce_chain_level=None): + # warn of name change + warn( + "The Operator(...) class has been renamed and will " + "be removed in a future version of OpenMC. Use " + "CoupledOperator(...) instead.", + FutureWarning + ) # check for old call to constructor if isinstance(model, openmc.Geometry): msg = "As of version 0.13.0 openmc.deplete.CoupledOperator " \ From 3e81a86915881b952dbe26449c0101cc9c1104f5 Mon Sep 17 00:00:00 2001 From: yardasol Date: Sat, 30 Jul 2022 18:37:51 -0500 Subject: [PATCH 0716/2654] TransportOperator->DepletionOperator --- docs/source/pythonapi/deplete.rst | 42 +++++++++++---------- docs/source/usersguide/depletion.rst | 8 ++-- openmc/deplete/abc.py | 46 +++++++++++------------ openmc/deplete/coupled_operator.py | 7 ++-- openmc/deplete/helpers.py | 2 +- openmc/deplete/independent_operator.py | 9 +++-- openmc/deplete/openmc_operator.py | 11 +++--- openmc/deplete/stepresult.py | 2 +- tests/dummy_operator.py | 4 +- tests/unit_tests/test_deplete_operator.py | 4 +- 10 files changed, 70 insertions(+), 65 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index bc07ed1b0..9419244fe 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -12,20 +12,20 @@ Primary API The two primary requirements to perform depletion with :mod:`openmc.deplete` are: - 1) A reaction rate operator + 1) A depletion operator 2) A time-integration scheme -The former is responsible for obtaining transmuation reaction rates. The latter -is responsible for projecting reaction rates and compositions forward in -calendar time across some step size :math:`\Delta t`, and obtaining new -compositions given a power or power density. The :class:`CoupledOperator` class -is provided to obtain reaction rates via tallies through OpenMC's transport -solver, and the :class:`IndependentOperator` class is provided to obtain -reaction rates from cross-section data. Several classes are provided that -implement different time-integration algorithms for depletion calculations, -which are described in detail in Colin Josey's thesis, `Development and -analysis of high order neutron transport-depletion coupling algorithms -`_. +The former is responsible for calcuating retaining important information required for depletion. The most common examples are reaction rates and power +normalization data. The latter is responsible for projecting reaction rates and +compositions forward in calendar time across some step size :math:`\Delta t`, +and obtaining new compositions given a power or power density. The +:class:`CoupledOperator` class is provided to obtain reaction rates via tallies +through OpenMC's transport solver, and the :class:`IndependentOperator` class is +provided to obtain reaction rates from cross-section data. Several classes are +provided that implement different time-integration algorithms for depletion +calculations, which are described in detail in Colin Josey's thesis, +`Development and analysis of high order neutron transport-depletion coupling +algorithms `_. .. autosummary:: :toctree: generated @@ -41,8 +41,8 @@ analysis of high order neutron transport-depletion coupling algorithms SICELIIntegrator SILEQIIntegrator -Each of these classes expects a "reaction rate operator" to be passed. Operators -provided by OpenMC are available using the following classes: +Each of these classes expects a "depletion operator" to be passed. OpenMC +provides The following classes implementing depletion operators: .. autosummary:: :toctree: generated @@ -214,7 +214,7 @@ are stored in :class:`helpers.TalliedFissionYieldHelper` helpers.TalliedFissionYieldHelper -Methods common to OpenMC-specific implementations of :class:`TransportOperator` +Methods common to OpenMC-specific implementations of :class:`DepletionOperator` are stored in :class:`openmc_operator.OpenMCOperator` .. autosummary:: @@ -230,19 +230,21 @@ Abstract Base Classes A good starting point for extending capabilities in :mod:`openmc.deplete` is to examine the following abstract base classes. Custom classes can -inherit from :class:`abc.TransportOperator` to implement alternative -schemes for collecting reaction rates and other data from a transport code -prior to depleting materials +inherit from :class:`abc.DepletionOperator` to implement alternative +schemes for collecting reaction rates and other data prior to depleting +materials .. autosummary:: :toctree: generated :nosignatures: :template: mycallable.rst - abc.TransportOperator + abc.DepletionOperator The following classes are abstract classes used to pass information from -OpenMC simulations back on to the :class:`abc.TransportOperator` +transport simulations (in the case of transport-coupled depletion) or to +simply calculate these quantities directly (in the case of +transport-independent depletion) back on to the :class:`abc.DepletionOperator` .. autosummary:: :toctree: generated diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 990031c40..cc59efa6c 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -13,14 +13,14 @@ updated reaction rates, and the process is repeated for as many timesteps as are requested. The depletion module is designed such that the reaction rate solution (the -"operator") is completely isolated from the solution of the transmutation +depletion "operator") is completely isolated from the solution of the transmutation equations and the method used for advancing time. :mod:`openmc.deplete` supports multiple time-integration methods for determining material compositions over time. Each method appears as a different class. For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation using the CE/CM algorithm (deplete over a timestep using the middle-of-step -reaction rates). An instance of :class:`~openmc.deplete.abc.TransportOperator` +reaction rates). An instance of :class:`~openmc.deplete.abc.DepletionOperator` is passed to one of these functions along with the timesteps and power level:: power = 1200.0e6 # watts @@ -37,8 +37,8 @@ time:: time, keff = results.get_keff() Note that the coupling between the reaction rate solver and the transmutation -solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of -operators for obtaining transmutation reaction rates. +solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of depletion operators for obtaining transmutation reaction +rates. .. _coupled-depletion: diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index dd1fd5b04..e874479c0 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -28,8 +28,8 @@ from .pool import deplete __all__ = [ - "OperatorResult", "TransportOperator", "ReactionRateHelper", - "NormalizationHelper", "FissionYieldHelper", + "OperatorResult", "DepletionOperator", + "ReactionRateHelper", "NormalizationHelper", "FissionYieldHelper", "Integrator", "SIIntegrator", "DepSystemSolver", "add_params"] @@ -75,13 +75,13 @@ def change_directory(output_dir): os.chdir(orig_dir) -class TransportOperator(ABC): - """Abstract class defining a transport operator +class DepletionOperator(ABC): + """Abstract class defining a depletion operator - Each depletion integrator is written to work with a generic transport + Each depletion integrator is written to work with a generic depletion operator that takes a vector of material compositions and returns an eigenvalue and reaction rates. This abstract class sets the requirements - for such a transport operator. Users should instantiate + for such a depletion operator. Users should instantiate :class:`openmc.deplete.CoupledOperator` or :class:`openmc.deplete.IndependentOperator` rather than this class. @@ -222,10 +222,10 @@ class ReactionRateHelper(ABC): ---------- n_nucs : int Number of burnable nuclides tracked by - :class:`openmc.deplete.abc.TransportOperator` + :class:`openmc.deplete.abc.DepletionOperator` n_react : int Number of reactions tracked by - :class:`openmc.deplete.abc.TransportOperator` + :class:`openmc.deplete.abc.DepletionOperator` Attributes ---------- @@ -294,7 +294,7 @@ class NormalizationHelper(ABC): """Abstract class for obtaining normalization factor on tallies This helper class determines how reaction rates calculated by an instance of - :class:`openmc.deplete.abc.TransportOperator` should be normalized for the + :class:`openmc.deplete.abc.DepletionOperator` should be normalized for the purpose of constructing a burnup matrix. Based on the method chosen, the power or source rate provided by the user, and reaction rates from a :class:`ReactionRateHelper`, this class will scale reaction rates to the @@ -304,7 +304,7 @@ class NormalizationHelper(ABC): ---------- nuclides : list of str All nuclides with desired reaction rates. Ordered to be - consistent with :class:`openmc.deplete.abc.TransportOperator` + consistent with :class:`openmc.deplete.abc.DepletionOperator` """ @@ -319,7 +319,7 @@ class NormalizationHelper(ABC): """Perform work needed to obtain energy produced This method is called prior to calculating the reaction rates - in :meth:`openmc.deplete.abc.TransportOperator.initial_condition`. Only + in :meth:`openmc.deplete.abc.DepletionOperator.initial_condition`. Only used for energy-based normalization. Parameters @@ -433,7 +433,7 @@ class FissionYieldHelper(ABC): def unpack(): """Unpack tally data prior to compute fission yields. - Called after a :meth:`openmc.deplete.abc.TransportOperator.__call__` + Called after a :meth:`openmc.deplete.abc.DepletionOperator.__call__` routine during the normalization of reaction rates. Not necessary for all subclasses to implement, unless tallies @@ -466,13 +466,13 @@ class FissionYieldHelper(ABC): ---------- nuclides : iterable of str Nuclides with non-zero densities from the - :class:`openmc.deplete.abc.TransportOperator` + :class:`openmc.deplete.abc.DepletionOperator` Returns ------- nuclides : list of str Union of nuclides that the - :class:`openmc.deplete.abc.TransportOperator` says have non-zero + :class:`openmc.deplete.abc.DepletionOperator` says have non-zero densities at this stage and those that have yield data. Sorted by nuclide name @@ -488,7 +488,7 @@ class FissionYieldHelper(ABC): Parameters ---------- - operator : openmc.deplete.abc.TransportOperator + operator : openmc.deplete.abc.DepletionOperator Operator with a depletion chain kwargs: optional Additional keyword arguments to be used in constuction @@ -509,8 +509,8 @@ class Integrator(ABC): _params = r""" Parameters ---------- - operator : openmc.deplete.abc.TransportOperator - Operator to perform transport simulations + operator : openmc.deplete.abc.DepletionOperator + Operator that calculates reaction rates timesteps : iterable of float or iterable of tuple Array of timesteps. Note that values are not cumulative. The units are specified by the `timestep_units` argument when `timesteps` is an @@ -552,8 +552,8 @@ class Integrator(ABC): Attributes ---------- - operator : openmc.deplete.abc.TransportOperator - Operator to perform transport simulations + operator : openmc.deplete.abc.DepletionOperator + Operator that calculates reaction rates chain : openmc.deplete.Chain Depletion chain timesteps : iterable of float @@ -847,8 +847,8 @@ class SIIntegrator(Integrator): _params = r""" Parameters ---------- - operator : openmc.deplete.abc.TransportOperator - The operator object to simulate on. + operator : openmc.deplete.abc.DepletionOperator + Operator that calculates reaction rates timesteps : iterable of float or iterable of tuple Array of timesteps. Note that values are not cumulative. The units are specified by the `timestep_units` argument when `timesteps` is an @@ -893,8 +893,8 @@ class SIIntegrator(Integrator): Attributes ---------- - operator : openmc.deplete.abc.TransportOperator - Operator to perform transport simulations + operator : openmc.deplete.abc.DepletionOperator + Operator that calculates reaction rates chain : openmc.deplete.Chain Depletion chain timesteps : iterable of float diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index 35b63e9cf..39e46c882 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -1,7 +1,8 @@ """Transport-coupled operator for depletion. -This module implements an operator coupled to OpenMC's transport sovler so that -it can be used by depletion integrators. The implementation makes use of the Python bindings to OpenMC's C API so that reading tally results and updating +This module implements a depletion operator coupled to OpenMC's transport solver +so that it can be used by depletion integrators. The implementation makes use of +the Python bindings to OpenMC's C API so that reading tally results and updating material number densities is all done in-memory instead of through the filesystem. @@ -57,7 +58,7 @@ def _find_cross_sections(model): class CoupledOperator(OpenMCOperator): - """Transport-coupled operator for depletion. + """Transport-coupled depletion operator. Instances of this class can be used to perform transport-coupled depletion using OpenMC's transport solver. Normally, a user needn't call methods of diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 262e61b35..77f3da201 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -557,7 +557,7 @@ class ConstantFissionYieldHelper(FissionYieldHelper): Parameters ---------- - operator : openmc.deplete.TransportOperator + operator : openmc.deplete.abc.DepletionOperator operator with a depletion chain kwargs: Additional keyword arguments to be used in construction diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index a7eb54f57..631117403 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -1,4 +1,4 @@ -"""Transport-independent operator for depletion. +"""Transport-independent depletion operator. This module implements a depletion operator that runs independently of any transport solver by using user-provided one-group cross sections. @@ -23,8 +23,8 @@ from .results import Results from .helpers import ChainFissionHelper, ConstantFissionYieldHelper, SourceRateHelper class IndependentOperator(OpenMCOperator): - """Depletion operator that uses one-group cross sections to calculate - reaction rates. + """Transport-independent depletion operator that uses one-group cross + sections to calculate reaction rates. Instances of this class can be used to perform depletion using one-group cross sections and constant flux or constant power. Normally, a user needn't @@ -189,7 +189,8 @@ class IndependentOperator(OpenMCOperator): if ``reduce_chain`` evaluates to true. The default value of ``None`` implies no limit on the depth. fission_yield_opts : dict of str to option, optional - Optional arguments to pass to the `FissionYieldHelper`. Will be + Optional arguments to pass to the + :class:`openmc.deplete.helpers.FissionYieldHelper` class. Will be passed directly on to the helper. Passing a value of None will use the defaults for the associated helper. diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 7235ab9bf..bcf73a010 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -1,6 +1,7 @@ """OpenMC transport operator -This module implements functions shared by both OpenMC transport operators as well as indepenedent depletion operators. +This module implements functions shared by both OpenMC transport-coupled and +transport-independent depletion operators. """ @@ -11,7 +12,7 @@ import numpy as np import openmc from openmc.mpi import comm -from .abc import TransportOperator, OperatorResult +from .abc import DepletionOperator, OperatorResult from .atom_number import AtomNumber from .reaction_rates import ReactionRates @@ -41,12 +42,12 @@ def _distribute(items): j += chunk_size -class OpenMCOperator(TransportOperator): +class OpenMCOperator(DepletionOperator): """Abstract class holding OpenMC-specific functions for running depletion calculations. - Specific classes for running coupled transport-depletion calculations or - depletion-only calculations are implemented as subclasses of OpenMCOperator + Specific classes for running transport-coupled or transport-independent + depletion calculations are implemented as subclasses of OpenMCOperator. Parameters ---------- diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index 80a664c6f..3082cf304 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -462,7 +462,7 @@ class StepResult: Parameters ---------- - op : openmc.deplete.TransportOperator + op : openmc.deplete.abc.DepletionOperator The operator used to generate these results. x : list of list of numpy.array The prior x vectors. Indexed [i][cell] using the above equation. diff --git a/tests/dummy_operator.py b/tests/dummy_operator.py index 1bb00129d..c54269cc0 100644 --- a/tests/dummy_operator.py +++ b/tests/dummy_operator.py @@ -6,7 +6,7 @@ import scipy.sparse as sp from uncertainties import ufloat from openmc.deplete.reaction_rates import ReactionRates -from openmc.deplete.abc import TransportOperator, OperatorResult +from openmc.deplete.abc import DepletionOperator, OperatorResult from openmc.deplete import ( CECMIntegrator, PredictorIntegrator, CELIIntegrator, LEQIIntegrator, EPCRK4Integrator, CF4Integrator, SICELIIntegrator, SILEQIIntegrator @@ -117,7 +117,7 @@ class TestChain: return sp.csr_matrix(np.array([[a11, a12], [a21, a22]])) -class DummyOperator(TransportOperator): +class DummyOperator(DepletionOperator): """This is a dummy operator class with no statistical uncertainty. y_1' = sin(y_2) y_1 + cos(y_1) y_2 diff --git a/tests/unit_tests/test_deplete_operator.py b/tests/unit_tests/test_deplete_operator.py index 5fe8715ac..1910112b8 100644 --- a/tests/unit_tests/test_deplete_operator.py +++ b/tests/unit_tests/test_deplete_operator.py @@ -7,7 +7,7 @@ to a custom file with new depletion_chain node from pathlib import Path import pytest -from openmc.deplete.abc import TransportOperator +from openmc.deplete.abc import DepletionOperator from openmc.deplete.chain import Chain, _find_chain_file BARE_XS_FILE = "bare_cross_sections.xml" @@ -32,7 +32,7 @@ def bare_xs(run_in_tmpdir): yield BARE_XS_FILE -class BareDepleteOperator(TransportOperator): +class BareDepleteOperator(DepletionOperator): """Very basic class for testing the initialization.""" @staticmethod From 0dd8f70939d8103e11b205b559c2e71a254e4f22 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 09:22:10 -0500 Subject: [PATCH 0717/2654] add paulromano's 2nd round of suggestions --- openmc/material.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 9ba7360ff..6c2641680 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -408,6 +408,8 @@ class Material(IDManagerMixin): def add_components(self, components: dict, percent_type: str = 'ao'): """ Add multiple elements or nuclides to a material + .. versionadded:: 0.13.1 + Parameters ---------- components : dict of str to float or dict @@ -442,17 +444,14 @@ class Material(IDManagerMixin): raise ValueError("An entry in the dictionary does not have " "a required key: 'percent'") - percent = params.pop('percent') - args = (percent, percent_type) + params['percent_type'] = percent_type ## check if nuclide if str.isdigit(component[-1]): - self.add_nuclide(component, *args) + self.add_nuclide(component, **params) else: # is element kwargs = params - self.add_element(component, *args, **kwargs) - - params['percent'] = percent + self.add_element(component, **params) def remove_nuclide(self, nuclide: str): """Remove a nuclide from the material From eac4092362545db994f0653eaea134afcf864dbf Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 09:35:30 -0500 Subject: [PATCH 0718/2654] address @paulromano's fourth round of comments - syntax fixes - remove `units` argument from MicroXS.from_csv and MicroXS.from_array - make Operator warning display only when users call Operator --- openmc/deplete/abc.py | 4 ++-- openmc/deplete/coupled_operator.py | 18 ++++++++++-------- openmc/deplete/microxs.py | 29 ++++++++++++----------------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index e874479c0..8439fab34 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -529,8 +529,8 @@ class Integrator(ABC): initial heavy metal inventory to get total power if ``power`` is not specified. source_rates : float or iterable of float, optional - Source rate in [neutron/sec] or neutron flux in [neut/cm^2-s] for each - interval in :attr:`timesteps` + Source rate in [neutron/sec] or neutron flux in [neutron/s-cm^2] for + each interval in :attr:`timesteps` .. versionadded:: 0.12.1 timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index 39e46c882..2e457f4d7 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -192,13 +192,7 @@ class CoupledOperator(OpenMCOperator): fission_yield_mode="constant", fission_yield_opts=None, reaction_rate_mode="direct", reaction_rate_opts=None, reduce_chain=False, reduce_chain_level=None): - # warn of name change - warn( - "The Operator(...) class has been renamed and will " - "be removed in a future version of OpenMC. Use " - "CoupledOperator(...) instead.", - FutureWarning - ) + # check for old call to constructor if isinstance(model, openmc.Geometry): msg = "As of version 0.13.0 openmc.deplete.CoupledOperator " \ @@ -526,4 +520,12 @@ class CoupledOperator(OpenMCOperator): openmc.lib.finalize() # Retain deprecated name for the time being -Operator = CoupledOperator +def Operator(**args, **kwargs): + # warn of name change + warn( + "The Operator(...) class has been renamed and will " + "be removed in a future version of OpenMC. Use " + "CoupledOperator(...) instead.", + FutureWarning + ) + return CoupledOperator(*args, **kwargs) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 6abf8836f..68255d18a 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -6,7 +6,6 @@ nuclides names as row indices and reaction names as column indices. import tempfile from pathlib import Path -from os import chdir from pandas import DataFrame, read_csv, concat from numpy import ndarray @@ -54,7 +53,8 @@ class MicroXS(DataFrame): Returns ------- - MicroXS, cross section data in [b] + MicroXS + Cross section data in [b] """ groups = EnergyGroups(energy_bounds) @@ -73,15 +73,12 @@ class MicroXS(DataFrame): model.tallies = tallies # create temporary run - original_dir = Path.cwd() - temp_dir = tempfile.TemporaryDirectory() - chdir(tempfile.gettempdir()) - statepoint_path = model.run() - chdir(original_dir) + with tempfile.TemporaryDirectory() as temp_dir: + statepoint_path = model.run(cwd=temp_dir) - with StatePoint(statepoint_path) as sp: - for rxn in xs: - xs[rxn].load_from_statepoint(sp) + with StatePoint(statepoint_path) as sp: + for rxn in xs: + xs[rxn].load_from_statepoint(sp) # Build the DataFrame micro_xs = cls() @@ -89,7 +86,7 @@ class MicroXS(DataFrame): df = xs[rxn].get_pandas_dataframe(xs_type='micro') df.index = df['nuclide'] df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) - df.rename({'mean':rxn}, axis=1, inplace=True) + df.rename({'mean': rxn}, axis=1, inplace=True) micro_xs = concat([micro_xs, df], axis=1) micro_xs._units = 'b' @@ -100,7 +97,7 @@ class MicroXS(DataFrame): return micro_xs @classmethod - def from_array(cls, nuclides, reactions, data, units='b'): + def from_array(cls, nuclides, reactions, data): """ Creates a ``MicroXS`` object from arrays. @@ -115,8 +112,6 @@ class MicroXS(DataFrame): data : ndarray of floats Array containing one-group microscopic cross section values for each nuclide and reaction - units : {'b', 'cm^2'} - Units of the cross section values in ``data`` Returns ------- @@ -133,12 +128,12 @@ class MicroXS(DataFrame): cls._validate_micro_xs_inputs( nuclides, reactions, data) micro_xs = cls(index=nuclides, columns=reactions, data=data) - micro_xs._units = units + micro_xs._units = 'b' return micro_xs @classmethod - def from_csv(cls, csv_file, units='b', **kwargs): + def from_csv(cls, csv_file, **kwargs): """ Load a ``MicroXS`` object from a ``.csv`` file. @@ -165,7 +160,7 @@ class MicroXS(DataFrame): cls._validate_micro_xs_inputs(list(micro_xs.index), list(micro_xs.columns), micro_xs.to_numpy()) - micro_xs._units = units + micro_xs._units = 'b' return micro_xs From 51b1350f4a413f4c7a533d3f45a9ae2f3801d316 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 09:49:20 -0500 Subject: [PATCH 0719/2654] add basic unit test for initalizing CoupledOperator --- .../test_deplete_coupled_operator.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/unit_tests/test_deplete_coupled_operator.py diff --git a/tests/unit_tests/test_deplete_coupled_operator.py b/tests/unit_tests/test_deplete_coupled_operator.py new file mode 100644 index 000000000..6de0342b0 --- /dev/null +++ b/tests/unit_tests/test_deplete_coupled_operator.py @@ -0,0 +1,55 @@ +"""Basic unit tests for openmc.deplete.CoupledOperator instantiation + +""" + +from pathlib import Path + +import pytest +from openmc.deplete import CoupledOperator +import openmc +import numpy as np + +CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" + +@pytest.fixture(scope="module") +def model(): + fuel = openmc.Material(name="uo2") + fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) + fuel.add_element("O", 2) + fuel.set_density("g/cc", 10.4) + + clad = openmc.Material(name="clad") + clad.add_element("Zr", 1) + clad.set_density("g/cc", 6) + + water = openmc.Material(name="water") + water.add_element("O", 1) + water.add_element("H", 2) + water.set_density("g/cc", 1.0) + water.add_s_alpha_beta("c_H_in_H2O") + + radii = [0.42, 0.45] + fuel.volume = np.pi * radii[0] ** 2 + clad.volume = np.pi * (radii[1]**2 - radii[0]**2) + water.volume = 1.24**2 - (np.pi * radii[1]**2) + + materials = openmc.Materials([fuel, clad, water]) + + pin_surfaces = [openmc.ZCylinder(r=r) for r in radii] + pin_univ = openmc.model.pin(pin_surfaces, materials) + bound_box = openmc.rectangular_prism(1.24, 1.24, boundary_type="reflective") + root_cell = openmc.Cell(fill=pin_univ, region=bound_box) + geometry = openmc.Geometry([root_cell]) + + settings = openmc.Settings() + settings.particles = 1000 + settings.inactive = 10 + settings.batches = 50 + + return openmc.Model(geometry, materials, settings) + +def test_operator_init(model): + """The test uses a temporary dummy chain. This file will be removed + at the end of the test, and only contains a depletion_chain node.""" + + CoupledOperator(model, CHAIN_PATH) From 2f985a808609319ea763944285293b60c11dd6f3 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 09:58:52 -0500 Subject: [PATCH 0720/2654] syntax fix in CoupledOperator --- openmc/deplete/coupled_operator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index 2e457f4d7..448952b62 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -192,7 +192,7 @@ class CoupledOperator(OpenMCOperator): fission_yield_mode="constant", fission_yield_opts=None, reaction_rate_mode="direct", reaction_rate_opts=None, reduce_chain=False, reduce_chain_level=None): - + # check for old call to constructor if isinstance(model, openmc.Geometry): msg = "As of version 0.13.0 openmc.deplete.CoupledOperator " \ @@ -520,7 +520,7 @@ class CoupledOperator(OpenMCOperator): openmc.lib.finalize() # Retain deprecated name for the time being -def Operator(**args, **kwargs): +def Operator(*args, **kwargs): # warn of name change warn( "The Operator(...) class has been renamed and will " From 4bab1b5611a929ec7a0166711dd61f64c1f62735 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 12:09:21 -0500 Subject: [PATCH 0721/2654] remove attribute from MicroXS; specify xs values to be in barns --- openmc/deplete/independent_operator.py | 1 - openmc/deplete/microxs.py | 10 +++------- tests/unit_tests/test_deplete_microxs.py | 1 - 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index 631117403..cd5a4d454 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -129,7 +129,6 @@ class IndependentOperator(OpenMCOperator): 'fission_yield_opts': fission_yield_opts} cross_sections = micro_xs * 1e-24 - cross_sections._units = 'cm^2' super().__init__( materials, cross_sections, diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 68255d18a..aef3c26c2 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -111,7 +111,8 @@ class MicroXS(DataFrame): :data:`openmc.deplete.chain.REACTIONS` data : ndarray of floats Array containing one-group microscopic cross section values for - each nuclide and reaction + each nuclide and reaction. Cross section values are assumed to be + in [b]. Returns ------- @@ -128,7 +129,6 @@ class MicroXS(DataFrame): cls._validate_micro_xs_inputs( nuclides, reactions, data) micro_xs = cls(index=nuclides, columns=reactions, data=data) - micro_xs._units = 'b' return micro_xs @@ -141,9 +141,7 @@ class MicroXS(DataFrame): ---------- csv_file : str Relative path to csv-file containing microscopic cross section - data. - units : {'b', 'cm^2'} - Units of the cross section values in the ``.csv`` file + data. Cross section values are assumed to be in [b] **kwargs : dict Keyword arguments to pass to :func:`pandas.read_csv()`. @@ -160,8 +158,6 @@ class MicroXS(DataFrame): cls._validate_micro_xs_inputs(list(micro_xs.index), list(micro_xs.columns), micro_xs.to_numpy()) - micro_xs._units = 'b' - return micro_xs @staticmethod diff --git a/tests/unit_tests/test_deplete_microxs.py b/tests/unit_tests/test_deplete_microxs.py index 17d9cb38f..557082eda 100644 --- a/tests/unit_tests/test_deplete_microxs.py +++ b/tests/unit_tests/test_deplete_microxs.py @@ -54,7 +54,6 @@ def test_csv(): ref_xs = MicroXS.from_csv(ONE_GROUP_XS) ref_xs.to_csv('temp_xs.csv') temp_xs = MicroXS.from_csv('temp_xs.csv') - assert ref_xs._units == temp_xs._units assert np.all(ref_xs == temp_xs) remove('temp_xs.csv') From 78e4e0aedf43082409be060eee9a559525f76669 Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 12:20:46 -0500 Subject: [PATCH 0722/2654] doc adjustments from @paulromano's comments --- docs/source/methods/depletion.rst | 2 +- docs/source/pythonapi/deplete.rst | 6 +++--- docs/source/usersguide/depletion.rst | 21 ++++++++++----------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/source/methods/depletion.rst b/docs/source/methods/depletion.rst index 66ee50397..308a62e19 100644 --- a/docs/source/methods/depletion.rst +++ b/docs/source/methods/depletion.rst @@ -231,7 +231,7 @@ of FPY: to transport-coupled depletion. 3. Compute the average energy at which fission events occur and use an effective FPY by linearly interpolating between FPY provided at neighboring energies. - Only applicable to transport-coupled depletion + Only applicable to transport-coupled depletion. The method for transport-coupled depletion can be selected through the ``fission_yield_mode`` argument to the :class:`openmc.deplete.CoupledOperator` diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 9419244fe..a57ec915d 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -15,7 +15,7 @@ are: 1) A depletion operator 2) A time-integration scheme -The former is responsible for calcuating retaining important information required for depletion. The most common examples are reaction rates and power +The former is responsible for calcuating and retaining important information required for depletion. The most common examples are reaction rates and power normalization data. The latter is responsible for projecting reaction rates and compositions forward in calendar time across some step size :math:`\Delta t`, and obtaining new compositions given a power or power density. The @@ -194,8 +194,8 @@ total system energy. helpers.FissionYieldCutoffHelper helpers.FluxCollapseHelper -The :class:`openmc.deplete.IndependentOperator` uses inner class subclassed from -those listed to perform similar calculations. +The :class:`openmc.deplete.IndependentOperator` uses inner classes subclassed +from those listed above to perform similar calculations. Intermediate Classes -------------------- diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index cc59efa6c..5052f7263 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -8,7 +8,7 @@ OpenMC supports transport-coupled and transport-independent depletion, or burnup, calculations through the :mod:`openmc.deplete` Python module. OpenMC uses transmutation reaction rates to solve a set of transmutation equations that determine the evolution of nuclide densities within a material. The -nuclide densities predicted as some future time are then used to determine +nuclide densities predicted at some future time are then used to determine updated reaction rates, and the process is repeated for as many timesteps as are requested. @@ -197,8 +197,8 @@ Transport-independent depletion .. note:: - This feature is still under heavy development and has yet to be verifed - code-to-code . API changes and feature additions are possible and likely in + This feature is still under heavy development and has yet to be rigorously + verified. API changes and feature additions are possible and likely in the near future. This category of operator uses pre-calculated one-group microscopic cross @@ -282,7 +282,7 @@ expects the units to be. The :class:`~openmc.deplete.MicroXS` class also include [0.01, 0.5]]) micro_xs = MicroXS.from_array(nuclides, reactions, data) -.. important :: +.. important:: Both :meth:`~openmc.deplete.MicroXS.from_csv()` and :meth:`~openmc.deplete.MicroXS.from_array()` assume the cross section values @@ -306,12 +306,12 @@ normalizing reaction rates: ``normalization_mode == source-rate``, and use ``power`` or ``power_density`` when ``normalization_mode == fission-q``. -1. ``soure-rate`` normalization, which assumes the ``source-rate`` provided by +1. ``source-rate`` normalization, which assumes the ``source_rate`` provided by the time integrator is a flux, and obtains the reaction rates by multiplying the cross-sections by the ``source-rate``. -2. ``fission-q`` normalization, which assumes the ``source-rate`` provided by - the time integrator is a power, and obtains the reaction rates by computing a - value for the flux based on this power. The general equation for the flux is +2. ``fission-q`` normalization, which uses the ``power`` or ``power_density`` + provided by the time integrator to obtain reaction rates by computing a value + for the flux based on this power. The general equation for the flux is .. math:: @@ -324,8 +324,7 @@ normalizing reaction rates: However, there is a method to converge to a more accurate value for flux by using substeps during time integration. `This paper `_ provides a - good discussion of this method. Hopefully such a method will be implemented - in OpenMC in the near future. + good discussion of this method. .. warning:: @@ -342,7 +341,7 @@ separate with respect to reaction rates. This can be useful for running many different cases of a particular scenario. However, running a depletion simulation with multiple materials using the ``fission-q`` normalization method treats each material as part of the same "reactor" due to how ``fission-q`` -normalization conglomerates energy values from each material to a single value. +normalization accumulates energy values from each material to a single value. This behavior may change in the future. Time integration From 89d79310bb527d4e6cc171693f4584c513643aee Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 12:44:28 -0500 Subject: [PATCH 0723/2654] revert DepletionOperator to TransportOperator; doc updates --- docs/source/pythonapi/deplete.rst | 14 ++++---- docs/source/usersguide/depletion.rst | 8 ++--- openmc/deplete/abc.py | 42 +++++++++++------------ openmc/deplete/coupled_operator.py | 8 ++--- openmc/deplete/helpers.py | 2 +- openmc/deplete/independent_operator.py | 6 ++-- openmc/deplete/openmc_operator.py | 6 ++-- openmc/deplete/stepresult.py | 2 +- tests/dummy_operator.py | 4 +-- tests/unit_tests/test_deplete_operator.py | 4 +-- 10 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index a57ec915d..020251bd2 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -12,7 +12,7 @@ Primary API The two primary requirements to perform depletion with :mod:`openmc.deplete` are: - 1) A depletion operator + 1) A transpor operator 2) A time-integration scheme The former is responsible for calcuating and retaining important information required for depletion. The most common examples are reaction rates and power @@ -41,8 +41,8 @@ algorithms `_. SICELIIntegrator SILEQIIntegrator -Each of these classes expects a "depletion operator" to be passed. OpenMC -provides The following classes implementing depletion operators: +Each of these classes expects a "transport operator" to be passed. OpenMC +provides The following classes implementing transpor operators: .. autosummary:: :toctree: generated @@ -214,7 +214,7 @@ are stored in :class:`helpers.TalliedFissionYieldHelper` helpers.TalliedFissionYieldHelper -Methods common to OpenMC-specific implementations of :class:`DepletionOperator` +Methods common to OpenMC-specific implementations of :class:`TransportOperator` are stored in :class:`openmc_operator.OpenMCOperator` .. autosummary:: @@ -230,7 +230,7 @@ Abstract Base Classes A good starting point for extending capabilities in :mod:`openmc.deplete` is to examine the following abstract base classes. Custom classes can -inherit from :class:`abc.DepletionOperator` to implement alternative +inherit from :class:`abc.TransportOperator` to implement alternative schemes for collecting reaction rates and other data prior to depleting materials @@ -239,12 +239,12 @@ materials :nosignatures: :template: mycallable.rst - abc.DepletionOperator + abc.TransportOperator The following classes are abstract classes used to pass information from transport simulations (in the case of transport-coupled depletion) or to simply calculate these quantities directly (in the case of -transport-independent depletion) back on to the :class:`abc.DepletionOperator` +transport-independent depletion) back on to the :class:`abc.TransportOperator` .. autosummary:: :toctree: generated diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 5052f7263..d39ebb83e 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -13,14 +13,14 @@ updated reaction rates, and the process is repeated for as many timesteps as are requested. The depletion module is designed such that the reaction rate solution (the -depletion "operator") is completely isolated from the solution of the transmutation -equations and the method used for advancing time. +transport "operator") is completely isolated from the solution of the +transmutation equations and the method used for advancing time. :mod:`openmc.deplete` supports multiple time-integration methods for determining material compositions over time. Each method appears as a different class. For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation using the CE/CM algorithm (deplete over a timestep using the middle-of-step -reaction rates). An instance of :class:`~openmc.deplete.abc.DepletionOperator` +reaction rates). An instance of :class:`~openmc.deplete.abc.TransportOperator` is passed to one of these functions along with the timesteps and power level:: power = 1200.0e6 # watts @@ -37,7 +37,7 @@ time:: time, keff = results.get_keff() Note that the coupling between the reaction rate solver and the transmutation -solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of depletion operators for obtaining transmutation reaction +solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of transport operators for obtaining transmutation reaction rates. .. _coupled-depletion: diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 8439fab34..8cf0eceb2 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -28,7 +28,7 @@ from .pool import deplete __all__ = [ - "OperatorResult", "DepletionOperator", + "OperatorResult", "TransportOperator", "ReactionRateHelper", "NormalizationHelper", "FissionYieldHelper", "Integrator", "SIIntegrator", "DepSystemSolver", "add_params"] @@ -75,13 +75,13 @@ def change_directory(output_dir): os.chdir(orig_dir) -class DepletionOperator(ABC): - """Abstract class defining a depletion operator +class TransportOperator(ABC): + """Abstract class defining a transport operator Each depletion integrator is written to work with a generic depletion operator that takes a vector of material compositions and returns an eigenvalue and reaction rates. This abstract class sets the requirements - for such a depletion operator. Users should instantiate + for such a transport operator. Users should instantiate :class:`openmc.deplete.CoupledOperator` or :class:`openmc.deplete.IndependentOperator` rather than this class. @@ -222,10 +222,10 @@ class ReactionRateHelper(ABC): ---------- n_nucs : int Number of burnable nuclides tracked by - :class:`openmc.deplete.abc.DepletionOperator` + :class:`openmc.deplete.abc.TransportOperator` n_react : int Number of reactions tracked by - :class:`openmc.deplete.abc.DepletionOperator` + :class:`openmc.deplete.abc.TransportOperator` Attributes ---------- @@ -294,7 +294,7 @@ class NormalizationHelper(ABC): """Abstract class for obtaining normalization factor on tallies This helper class determines how reaction rates calculated by an instance of - :class:`openmc.deplete.abc.DepletionOperator` should be normalized for the + :class:`openmc.deplete.abc.TransportOperator` should be normalized for the purpose of constructing a burnup matrix. Based on the method chosen, the power or source rate provided by the user, and reaction rates from a :class:`ReactionRateHelper`, this class will scale reaction rates to the @@ -304,7 +304,7 @@ class NormalizationHelper(ABC): ---------- nuclides : list of str All nuclides with desired reaction rates. Ordered to be - consistent with :class:`openmc.deplete.abc.DepletionOperator` + consistent with :class:`openmc.deplete.abc.TransportOperator` """ @@ -319,7 +319,7 @@ class NormalizationHelper(ABC): """Perform work needed to obtain energy produced This method is called prior to calculating the reaction rates - in :meth:`openmc.deplete.abc.DepletionOperator.initial_condition`. Only + in :meth:`openmc.deplete.abc.TransportOperator.initial_condition`. Only used for energy-based normalization. Parameters @@ -433,7 +433,7 @@ class FissionYieldHelper(ABC): def unpack(): """Unpack tally data prior to compute fission yields. - Called after a :meth:`openmc.deplete.abc.DepletionOperator.__call__` + Called after a :meth:`openmc.deplete.abc.TransportOperator.__call__` routine during the normalization of reaction rates. Not necessary for all subclasses to implement, unless tallies @@ -466,13 +466,13 @@ class FissionYieldHelper(ABC): ---------- nuclides : iterable of str Nuclides with non-zero densities from the - :class:`openmc.deplete.abc.DepletionOperator` + :class:`openmc.deplete.abc.TransportOperator` Returns ------- nuclides : list of str Union of nuclides that the - :class:`openmc.deplete.abc.DepletionOperator` says have non-zero + :class:`openmc.deplete.abc.TransportOperator` says have non-zero densities at this stage and those that have yield data. Sorted by nuclide name @@ -488,7 +488,7 @@ class FissionYieldHelper(ABC): Parameters ---------- - operator : openmc.deplete.abc.DepletionOperator + operator : openmc.deplete.abc.TransportOperator Operator with a depletion chain kwargs: optional Additional keyword arguments to be used in constuction @@ -509,8 +509,8 @@ class Integrator(ABC): _params = r""" Parameters ---------- - operator : openmc.deplete.abc.DepletionOperator - Operator that calculates reaction rates + operator : openmc.deplete.abc.TransportOperator + Operator to perform transport simulations timesteps : iterable of float or iterable of tuple Array of timesteps. Note that values are not cumulative. The units are specified by the `timestep_units` argument when `timesteps` is an @@ -552,8 +552,8 @@ class Integrator(ABC): Attributes ---------- - operator : openmc.deplete.abc.DepletionOperator - Operator that calculates reaction rates + operator : openmc.deplete.abc.TransportOperator + Operator to perform transport simulations chain : openmc.deplete.Chain Depletion chain timesteps : iterable of float @@ -847,8 +847,8 @@ class SIIntegrator(Integrator): _params = r""" Parameters ---------- - operator : openmc.deplete.abc.DepletionOperator - Operator that calculates reaction rates + operator : openmc.deplete.abc.TransportOperator + Operator to perform transport simulations timesteps : iterable of float or iterable of tuple Array of timesteps. Note that values are not cumulative. The units are specified by the `timestep_units` argument when `timesteps` is an @@ -893,8 +893,8 @@ class SIIntegrator(Integrator): Attributes ---------- - operator : openmc.deplete.abc.DepletionOperator - Operator that calculates reaction rates + operator : openmc.deplete.abc.TransportOperator + Operator to perform transport simulations chain : openmc.deplete.Chain Depletion chain timesteps : iterable of float diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index 448952b62..d5bb5b4bd 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -1,6 +1,6 @@ -"""Transport-coupled operator for depletion. +"""Transport-coupled transport operator for depletion. -This module implements a depletion operator coupled to OpenMC's transport solver +This module implements a transport operator coupled to OpenMC's transport solver so that it can be used by depletion integrators. The implementation makes use of the Python bindings to OpenMC's C API so that reading tally results and updating material number densities is all done in-memory instead of through the @@ -58,7 +58,7 @@ def _find_cross_sections(model): class CoupledOperator(OpenMCOperator): - """Transport-coupled depletion operator. + """Transport-coupled transport operator. Instances of this class can be used to perform transport-coupled depletion using OpenMC's transport solver. Normally, a user needn't call methods of @@ -199,7 +199,7 @@ class CoupledOperator(OpenMCOperator): "requires an openmc.Model object rather than the " \ "openmc.Geometry and openmc.Settings parameters. Please use " \ "the geometry and settings objects passed here to create a " \ - " model with which to generate the depletion Operator." + " model with which to generate the transport Operator." raise TypeError(msg) # Determine cross sections / depletion chain diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 77f3da201..7b2d370ce 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -557,7 +557,7 @@ class ConstantFissionYieldHelper(FissionYieldHelper): Parameters ---------- - operator : openmc.deplete.abc.DepletionOperator + operator : openmc.deplete.abc.TransportOperator operator with a depletion chain kwargs: Additional keyword arguments to be used in construction diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index cd5a4d454..d2a9f04d0 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -1,6 +1,6 @@ -"""Transport-independent depletion operator. +"""Transport-independent transport operator for depletion. -This module implements a depletion operator that runs independently of any +This module implements a transport operator that runs independently of any transport solver by using user-provided one-group cross sections. """ @@ -23,7 +23,7 @@ from .results import Results from .helpers import ChainFissionHelper, ConstantFissionYieldHelper, SourceRateHelper class IndependentOperator(OpenMCOperator): - """Transport-independent depletion operator that uses one-group cross + """Transport-independent transport operator that uses one-group cross sections to calculate reaction rates. Instances of this class can be used to perform depletion using one-group diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index bcf73a010..6e6f8dd8d 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -1,7 +1,7 @@ """OpenMC transport operator This module implements functions shared by both OpenMC transport-coupled and -transport-independent depletion operators. +transport-independent transport operators. """ @@ -12,7 +12,7 @@ import numpy as np import openmc from openmc.mpi import comm -from .abc import DepletionOperator, OperatorResult +from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .reaction_rates import ReactionRates @@ -42,7 +42,7 @@ def _distribute(items): j += chunk_size -class OpenMCOperator(DepletionOperator): +class OpenMCOperator(TransportOperator): """Abstract class holding OpenMC-specific functions for running depletion calculations. diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index 3082cf304..c54f9edcf 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -462,7 +462,7 @@ class StepResult: Parameters ---------- - op : openmc.deplete.abc.DepletionOperator + op : openmc.deplete.abc.TransportOperator The operator used to generate these results. x : list of list of numpy.array The prior x vectors. Indexed [i][cell] using the above equation. diff --git a/tests/dummy_operator.py b/tests/dummy_operator.py index c54269cc0..1bb00129d 100644 --- a/tests/dummy_operator.py +++ b/tests/dummy_operator.py @@ -6,7 +6,7 @@ import scipy.sparse as sp from uncertainties import ufloat from openmc.deplete.reaction_rates import ReactionRates -from openmc.deplete.abc import DepletionOperator, OperatorResult +from openmc.deplete.abc import TransportOperator, OperatorResult from openmc.deplete import ( CECMIntegrator, PredictorIntegrator, CELIIntegrator, LEQIIntegrator, EPCRK4Integrator, CF4Integrator, SICELIIntegrator, SILEQIIntegrator @@ -117,7 +117,7 @@ class TestChain: return sp.csr_matrix(np.array([[a11, a12], [a21, a22]])) -class DummyOperator(DepletionOperator): +class DummyOperator(TransportOperator): """This is a dummy operator class with no statistical uncertainty. y_1' = sin(y_2) y_1 + cos(y_1) y_2 diff --git a/tests/unit_tests/test_deplete_operator.py b/tests/unit_tests/test_deplete_operator.py index 1910112b8..5fe8715ac 100644 --- a/tests/unit_tests/test_deplete_operator.py +++ b/tests/unit_tests/test_deplete_operator.py @@ -7,7 +7,7 @@ to a custom file with new depletion_chain node from pathlib import Path import pytest -from openmc.deplete.abc import DepletionOperator +from openmc.deplete.abc import TransportOperator from openmc.deplete.chain import Chain, _find_chain_file BARE_XS_FILE = "bare_cross_sections.xml" @@ -32,7 +32,7 @@ def bare_xs(run_in_tmpdir): yield BARE_XS_FILE -class BareDepleteOperator(DepletionOperator): +class BareDepleteOperator(TransportOperator): """Very basic class for testing the initialization.""" @staticmethod From 1c6fb99947ab1c451749e3c9be75398a59af6b6d Mon Sep 17 00:00:00 2001 From: yardasol Date: Mon, 1 Aug 2022 13:36:51 -0500 Subject: [PATCH 0724/2654] fix regression test microxs --- tests/regression_tests/microxs/test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/regression_tests/microxs/test.py b/tests/regression_tests/microxs/test.py index bebe1c302..89fdfcaeb 100644 --- a/tests/regression_tests/microxs/test.py +++ b/tests/regression_tests/microxs/test.py @@ -47,6 +47,4 @@ def test_from_model(model): ref_xs = MicroXS.from_csv('test_reference.csv') test_xs = MicroXS.from_model(model, model.materials[0]) - assert ref_xs._units == test_xs._units np.testing.assert_allclose(test_xs, ref_xs, rtol=1e-11) - From 064426a05fdac019917d613eb2805fb80f5fb5ad Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 13:17:33 +0100 Subject: [PATCH 0725/2654] added specific_activity --- openmc/material.py | 25 +++++++++++++++++++++++++ tests/unit_tests/test_material.py | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/openmc/material.py b/openmc/material.py index 6c2641680..61015f5b0 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -94,6 +94,9 @@ class Material(IDManagerMixin): activity : float Activity of the material in [Bq]. Requires that the :attr:`volume` attribute is set. + specific_activity : float + Activity of the material per unit mass in [Bq/kg]. Requires that the + :attr:`volume` and :attr:`density` attributes are set. """ @@ -155,6 +158,11 @@ class Material(IDManagerMixin): """Returns the total activity of the material in Becquerels.""" return sum(self.get_nuclide_activity().values()) + @property + def specific_activity(self): + """Returns the total specific activity of the material in Becquerels per gram.""" + return sum(self.get_nuclide_specific_activity().values()) + @property def name(self): return self._name @@ -925,6 +933,23 @@ class Material(IDManagerMixin): activity[nuclide] = inv_seconds * atoms return activity + def get_nuclide_specific_activity(self): + """Return specific activity in [Bq/g] for each nuclide in the material + + .. versionadded:: 0.13.1 + + Returns + ------- + dict + Dictionary whose keys are nuclide names and values are specific + activity in [Bq/g]. + """ + activity = {} + for nuclide, atoms in self.get_nuclide_atoms().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = (inv_seconds * atoms) / self.get_mass() + return activity + def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 2c5cc2874..d70161f48 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -496,3 +496,21 @@ def test_activity_of_metastable(): m1.set_density('g/cm3', 1) m1.volume = 98.9 assert pytest.approx(m1.activity, rel=0.001) == 1.93e19 + + +def test_specific_activity_of_tritium(): + """Checks that specific activity stays the same for all volumes and + densities while activity changes proportionally to mass""" + m1 = openmc.Material() + m1.add_nuclide("H3", 1) + m1.set_density('g/cm3', 1) + m1.volume = 1 + # activity and specific_activity are initially the same as we have 1g + assert pytest.approx(m1.specific_activity) == 3.559778e14 + assert pytest.approx(m1.activity) == 3.559778e14 + m1.set_density('g/cm3', 2) + assert pytest.approx(m1.specific_activity) == 3.559778e14 + assert pytest.approx(m1.activity) == 3.559778e14*2 + m1.volume = 3 + assert pytest.approx(m1.specific_activity) == 3.559778e14 + assert pytest.approx(m1.activity) == 3.559778e14*2*3 From 6865264abdca31302384bbd80d8eabfacdd3fe5b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 15:43:21 +0100 Subject: [PATCH 0726/2654] added option for year as time units --- openmc/deplete/results.py | 16 +++++++++------- tests/unit_tests/test_deplete_resultslist.py | 6 ++++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index c238002fe..f56aee3ce 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -16,6 +16,8 @@ __all__ = ["Results", "ResultsList"] def _get_time_as(seconds, units): + if units == "y": + return seconds / (60 * 60 * 24 * 365.25) # 365.25 due to the leap year if units == "d": return seconds / (60 * 60 * 24) elif units == "h": @@ -95,7 +97,7 @@ class Results(list): Units for the returned concentration. Default is ``"atoms"`` .. versionadded:: 0.12 - time_units : {"s", "min", "h", "d"}, optional + time_units : {"s", "min", "h", "d", "y"}, optional Units for the returned time array. Default is ``"s"`` to return the value in seconds. @@ -109,7 +111,7 @@ class Results(list): Concentration of specified nuclide in units of ``nuc_units`` """ - cv.check_value("time_units", time_units, {"s", "d", "min", "h"}) + cv.check_value("time_units", time_units, {"s", "d", "min", "h", "y"}) cv.check_value("nuc_units", nuc_units, {"atoms", "atom/b-cm", "atom/cm3"}) @@ -190,7 +192,7 @@ class Results(list): Parameters ---------- - time_units : {"s", "d", "h", "min"}, optional + time_units : {"s", "d", "min", "h", "y"}, optional Desired units for the times array Returns @@ -203,7 +205,7 @@ class Results(list): 1 contains the associated uncertainty """ - cv.check_value("time_units", time_units, {"s", "d", "min", "h"}) + cv.check_value("time_units", time_units, {"s", "d", "min", "h", "y"}) times = np.empty_like(self, dtype=float) eigenvalues = np.empty((len(self), 2), dtype=float) @@ -257,7 +259,7 @@ class Results(list): Parameters ---------- - time_units : {"s", "d", "h", "min"}, optional + time_units : {"s", "d", "min", "h", "y"}, optional Return the vector in these units. Default is to convert to days @@ -267,7 +269,7 @@ class Results(list): 1-D vector of time points """ - cv.check_value("time_units", time_units, {"s", "d", "min", "h"}) + cv.check_value("time_units", time_units, {"s", "d", "min", "h", "y"}) times = np.fromiter( (r.time[0] for r in self), @@ -296,7 +298,7 @@ class Results(list): ---------- time : float Desired point in time - time_units : {"s", "d", "min", "h"}, optional + time_units : {"s", "d", "min", "h", "y"}, optional Units on ``time``. Default: days atol : float, optional Absolute tolerance (in ``time_units``) if ``time`` is not diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 6ce15601f..86bf4ebc5 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -70,14 +70,16 @@ def test_get_keff(res): np.testing.assert_allclose(k[:, 1], u_ref) -@pytest.mark.parametrize("unit", ("s", "d", "min", "h")) +@pytest.mark.parametrize("unit", ("s", "d", "min", "h", "y")) def test_get_steps(unit): # Make a Results full of near-empty Result instances # Just fill out a time schedule results = openmc.deplete.Results() # Time in units of unit times = np.linspace(0, 100, num=5) - if unit == "d": + if unit == "y": + conversion_to_seconds = 60 * 60 * 24 * 365.25 + elif unit == "d": conversion_to_seconds = 60 * 60 * 24 elif unit == "h": conversion_to_seconds = 60 * 60 From 98c287b83a692beac38eb1617f3f7315a6fa8a20 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 17:24:48 +0100 Subject: [PATCH 0727/2654] volume not needed when finding specific activity --- openmc/material.py | 4 ++-- tests/unit_tests/test_material.py | 21 ++++++++------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 61015f5b0..57f9a6f86 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -945,9 +945,9 @@ class Material(IDManagerMixin): activity in [Bq/g]. """ activity = {} - for nuclide, atoms in self.get_nuclide_atoms().items(): + for nuclide, atoms in self.get_nuclide_atom_densities().items(): inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms) / self.get_mass() + activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density return activity def get_nuclide_atoms(self): diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index d70161f48..c959ba276 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -481,12 +481,16 @@ def test_activity_of_stable(): def test_activity_of_tritium(): - """Checks that 1g of tritium has the correct activity""" + """Checks that 1g of tritium has the correct activity activity scaling""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) m1.volume = 1 assert pytest.approx(m1.activity) == 3.559778e14 + m1.set_density('g/cm3', 2) + assert pytest.approx(m1.activity) == 3.559778e14*2 + m1.volume = 3 + assert pytest.approx(m1.activity) == 3.559778e14*2*3 def test_activity_of_metastable(): @@ -499,18 +503,9 @@ def test_activity_of_metastable(): def test_specific_activity_of_tritium(): - """Checks that specific activity stays the same for all volumes and - densities while activity changes proportionally to mass""" + """Checks that specific activity of tritium is correct""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) - m1.volume = 1 - # activity and specific_activity are initially the same as we have 1g - assert pytest.approx(m1.specific_activity) == 3.559778e14 - assert pytest.approx(m1.activity) == 3.559778e14 - m1.set_density('g/cm3', 2) - assert pytest.approx(m1.specific_activity) == 3.559778e14 - assert pytest.approx(m1.activity) == 3.559778e14*2 - m1.volume = 3 - assert pytest.approx(m1.specific_activity) == 3.559778e14 - assert pytest.approx(m1.activity) == 3.559778e14*2*3 + assert m1.specific_activity == 355978108155965.9 + assert m1.get_nuclide_specific_activity() == {"H3": 355978108155965.9} \ No newline at end of file From 742311fd1bb37b884a633d3464f56504448a6ef5 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 17:37:17 +0100 Subject: [PATCH 0728/2654] [skip ci] fixed typo --- tests/unit_tests/test_material.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index c959ba276..fd9f325f2 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -481,7 +481,7 @@ def test_activity_of_stable(): def test_activity_of_tritium(): - """Checks that 1g of tritium has the correct activity activity scaling""" + """Checks that 1g of tritium has the correct activity scaling""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) From 4a06d14b156b2e0d666f5f5faa293e9bc1356c33 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Tue, 2 Aug 2022 12:28:00 -0500 Subject: [PATCH 0729/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- docs/source/methods/depletion.rst | 3 ++- docs/source/pythonapi/deplete.rst | 5 +++-- docs/source/usersguide/depletion.rst | 13 ++++++++----- openmc/deplete/abc.py | 4 ++-- openmc/deplete/helpers.py | 1 - openmc/deplete/microxs.py | 2 -- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/source/methods/depletion.rst b/docs/source/methods/depletion.rst index 308a62e19..1b131bed5 100644 --- a/docs/source/methods/depletion.rst +++ b/docs/source/methods/depletion.rst @@ -108,7 +108,8 @@ transport-coupled depletion, the expense is driven almost entirely by the time to compute a transport solution, i.e., to evaluate :math:`\mathbf{A}` for a given :math:`\mathbf{n}`. Thus, the cost of a method scales with the number of :math:`\mathbf{A}` evaluations that are performed per timestep. On the other -hand, methods that require more evaluations generally achieve higher accuracy. The predictor method only requires one evaluation and its error converges as +hand, methods that require more evaluations generally achieve higher accuracy. +The predictor method only requires one evaluation and its error converges as :math:`\mathcal{O}(h)`. The CE/CM method requires two evaluations and is thus twice as expensive as the predictor method, but achieves an error of :math:`\mathcal{O}(h^2)`. An exhaustive description of time integration methods diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 020251bd2..0b7faceb7 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -12,10 +12,11 @@ Primary API The two primary requirements to perform depletion with :mod:`openmc.deplete` are: - 1) A transpor operator + 1) A transport operator 2) A time-integration scheme -The former is responsible for calcuating and retaining important information required for depletion. The most common examples are reaction rates and power +The former is responsible for calculating and retaining important information +required for depletion. The most common examples are reaction rates and power normalization data. The latter is responsible for projecting reaction rates and compositions forward in calendar time across some step size :math:`\Delta t`, and obtaining new compositions given a power or power density. The diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index d39ebb83e..29bbcd1ed 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -37,7 +37,8 @@ time:: time, keff = results.get_keff() Note that the coupling between the reaction rate solver and the transmutation -solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of transport operators for obtaining transmutation reaction +solver happens in-memory rather than by reading/writing files on disk. OpenMC +has two categories of transport operators for obtaining transmutation reaction rates. .. _coupled-depletion: @@ -195,7 +196,7 @@ across all material instances. Transport-independent depletion =============================== -.. note:: +.. warning:: This feature is still under heavy development and has yet to be rigorously verified. API changes and feature additions are possible and likely in @@ -218,7 +219,7 @@ and a path to a depletion chain file:: micro_xs = openmc.deplete.MicroXS() ... - op = IndependentOperator(materials, micro_xs, chain_file) + op = openmc.deplete.IndependentOperator(materials, micro_xs, chain_file) .. note:: @@ -270,8 +271,10 @@ Users can generate the one-group microscopic cross sections needed by The :meth:`~openmc.deplete.MicroXS.from_model()` method will produce a :class:`~openmc.deplete.MicroXS` object with microscopic cross section data in -units of ``b``, which is what :class:`~openmc.deplete.IndependentOperator` -expects the units to be. The :class:`~openmc.deplete.MicroXS` class also includes functions to read in cross section data directly from a ``.csv`` file or from data arrays:: +units of barns, which is what :class:`~openmc.deplete.IndependentOperator` +expects the units to be. The :class:`~openmc.deplete.MicroXS` class also +includes functions to read in cross section data directly from a ``.csv`` file +or from data arrays:: micro_xs = MicroXS.from_csv(micro_xs_path) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 8cf0eceb2..e3587f052 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -78,7 +78,7 @@ def change_directory(output_dir): class TransportOperator(ABC): """Abstract class defining a transport operator - Each depletion integrator is written to work with a generic depletion + Each depletion integrator is written to work with a generic transport operator that takes a vector of material compositions and returns an eigenvalue and reaction rates. This abstract class sets the requirements for such a transport operator. Users should instantiate @@ -604,7 +604,7 @@ class Integrator(ABC): else: source_rates = [p*operator.heavy_metal for p in power_density] elif source_rates is None: - raise ValueError("Either power, power_density, source_rates must be set") + raise ValueError("Either power, power_density, or source_rates must be set") if not isinstance(source_rates, Iterable): # Ensure that rate is single value if that is the case diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 7b2d370ce..1e382576e 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -615,7 +615,6 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): Default: 0.0253 [eV] fast_energy : float, optional Energy of yield data corresponding to fast yields. - Default: 500 [KeV] Attributes ---------- diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index aef3c26c2..89ad5e03c 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -89,8 +89,6 @@ class MicroXS(DataFrame): df.rename({'mean': rxn}, axis=1, inplace=True) micro_xs = concat([micro_xs, df], axis=1) - micro_xs._units = 'b' - # Revert to the original tallies model.tallies = original_tallies From aa278ada262e88e6c470d44477c704010ccb9832 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 20:13:14 +0100 Subject: [PATCH 0730/2654] [skip ci] @paulromano review suggestion change "y" to "a" --- openmc/deplete/results.py | 16 ++++++++-------- tests/unit_tests/test_deplete_resultslist.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index f56aee3ce..6feac89b6 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -16,7 +16,7 @@ __all__ = ["Results", "ResultsList"] def _get_time_as(seconds, units): - if units == "y": + if units == "a": return seconds / (60 * 60 * 24 * 365.25) # 365.25 due to the leap year if units == "d": return seconds / (60 * 60 * 24) @@ -97,7 +97,7 @@ class Results(list): Units for the returned concentration. Default is ``"atoms"`` .. versionadded:: 0.12 - time_units : {"s", "min", "h", "d", "y"}, optional + time_units : {"s", "min", "h", "d", "a"}, optional Units for the returned time array. Default is ``"s"`` to return the value in seconds. @@ -111,7 +111,7 @@ class Results(list): Concentration of specified nuclide in units of ``nuc_units`` """ - cv.check_value("time_units", time_units, {"s", "d", "min", "h", "y"}) + cv.check_value("time_units", time_units, {"s", "d", "min", "h", "a"}) cv.check_value("nuc_units", nuc_units, {"atoms", "atom/b-cm", "atom/cm3"}) @@ -192,7 +192,7 @@ class Results(list): Parameters ---------- - time_units : {"s", "d", "min", "h", "y"}, optional + time_units : {"s", "d", "min", "h", "a"}, optional Desired units for the times array Returns @@ -205,7 +205,7 @@ class Results(list): 1 contains the associated uncertainty """ - cv.check_value("time_units", time_units, {"s", "d", "min", "h", "y"}) + cv.check_value("time_units", time_units, {"s", "d", "min", "h", "a"}) times = np.empty_like(self, dtype=float) eigenvalues = np.empty((len(self), 2), dtype=float) @@ -259,7 +259,7 @@ class Results(list): Parameters ---------- - time_units : {"s", "d", "min", "h", "y"}, optional + time_units : {"s", "d", "min", "h", "a"}, optional Return the vector in these units. Default is to convert to days @@ -269,7 +269,7 @@ class Results(list): 1-D vector of time points """ - cv.check_value("time_units", time_units, {"s", "d", "min", "h", "y"}) + cv.check_value("time_units", time_units, {"s", "d", "min", "h", "a"}) times = np.fromiter( (r.time[0] for r in self), @@ -298,7 +298,7 @@ class Results(list): ---------- time : float Desired point in time - time_units : {"s", "d", "min", "h", "y"}, optional + time_units : {"s", "d", "min", "h", "a"}, optional Units on ``time``. Default: days atol : float, optional Absolute tolerance (in ``time_units``) if ``time`` is not diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 86bf4ebc5..175f75b21 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -70,7 +70,7 @@ def test_get_keff(res): np.testing.assert_allclose(k[:, 1], u_ref) -@pytest.mark.parametrize("unit", ("s", "d", "min", "h", "y")) +@pytest.mark.parametrize("unit", ("s", "d", "min", "h", "a")) def test_get_steps(unit): # Make a Results full of near-empty Result instances # Just fill out a time schedule From 3c22a405fee0ebed2600a5ccacb1bd8f73939e7e Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 2 Aug 2022 20:29:19 +0100 Subject: [PATCH 0731/2654] added doc strings for time_units --- openmc/deplete/results.py | 23 ++++++++++++++++---- tests/unit_tests/test_deplete_resultslist.py | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 6feac89b6..017c9c668 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -16,6 +16,17 @@ __all__ = ["Results", "ResultsList"] def _get_time_as(seconds, units): + """Converts the time in seconds to time in different units + + Parameters + ---------- + seconds : float + The time to convert expressed in seconds + units : {"s", "min", "h", "d", "a"} + The units to convert time into. Available options are seconds ``"s"``, + minutes ``"min"``, hours ``"hours"`` days ``"d"``, years ``"a"`` + + """ if units == "a": return seconds / (60 * 60 * 24 * 365.25) # 365.25 due to the leap year if units == "d": @@ -99,7 +110,8 @@ class Results(list): .. versionadded:: 0.12 time_units : {"s", "min", "h", "d", "a"}, optional Units for the returned time array. Default is ``"s"`` to - return the value in seconds. + return the value in seconds. Other options are minutes ``"min"``, + hours ``"hours"``, days ``"d"``, years ``"a"`` .. versionadded:: 0.12 @@ -193,7 +205,8 @@ class Results(list): Parameters ---------- time_units : {"s", "d", "min", "h", "a"}, optional - Desired units for the times array + Desired units for the times array. Options are seconds ``"s"`` + minutes ``"min"``, hours ``"hours"``, days ``"d"``, years ``"a"`` Returns ------- @@ -261,7 +274,8 @@ class Results(list): ---------- time_units : {"s", "d", "min", "h", "a"}, optional Return the vector in these units. Default is to - convert to days + convert to days ``"d"``. Other options are seconds ``"s"``, minutes + ``"min"``, hours ``"hours"``, years ``"a"`` Returns ------- @@ -299,7 +313,8 @@ class Results(list): time : float Desired point in time time_units : {"s", "d", "min", "h", "a"}, optional - Units on ``time``. Default: days + Units on ``time``. Default: days ``"d"``. Other options are seconds + ``"s"``, minutes ``"min"``, hours ``"hours"`` and years ``"a"`` atol : float, optional Absolute tolerance (in ``time_units``) if ``time`` is not found. diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 175f75b21..4d8808c2f 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -77,7 +77,7 @@ def test_get_steps(unit): results = openmc.deplete.Results() # Time in units of unit times = np.linspace(0, 100, num=5) - if unit == "y": + if unit == "a": conversion_to_seconds = 60 * 60 * 24 * 365.25 elif unit == "d": conversion_to_seconds = 60 * 60 * 24 From ea926ef84a2b5c89a661c04f957269aecfc3f6bd Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 2 Aug 2022 20:36:42 +0100 Subject: [PATCH 0732/2654] specified that year is Julian in docstring --- openmc/deplete/results.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 017c9c668..9d4913300 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -111,7 +111,8 @@ class Results(list): time_units : {"s", "min", "h", "d", "a"}, optional Units for the returned time array. Default is ``"s"`` to return the value in seconds. Other options are minutes ``"min"``, - hours ``"hours"``, days ``"d"``, years ``"a"`` + hours ``"hours"``, days ``"d"``, years ``"a"`` (Julian year 365.25 + days). .. versionadded:: 0.12 @@ -207,6 +208,7 @@ class Results(list): time_units : {"s", "d", "min", "h", "a"}, optional Desired units for the times array. Options are seconds ``"s"`` minutes ``"min"``, hours ``"hours"``, days ``"d"``, years ``"a"`` + (Julian year 365.25 days). Returns ------- @@ -275,7 +277,8 @@ class Results(list): time_units : {"s", "d", "min", "h", "a"}, optional Return the vector in these units. Default is to convert to days ``"d"``. Other options are seconds ``"s"``, minutes - ``"min"``, hours ``"hours"``, years ``"a"`` + ``"min"``, hours ``"hours"``, years ``"a"`` (Julian year 365.25 + days). Returns ------- @@ -315,6 +318,7 @@ class Results(list): time_units : {"s", "d", "min", "h", "a"}, optional Units on ``time``. Default: days ``"d"``. Other options are seconds ``"s"``, minutes ``"min"``, hours ``"hours"`` and years ``"a"`` + (Julian year 365.25 days) atol : float, optional Absolute tolerance (in ``time_units``) if ``time`` is not found. From 8965dd1e66f53db42f607e165c504ba354d65c64 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 2 Aug 2022 22:11:37 -0500 Subject: [PATCH 0733/2654] Check for macroscopic data in materials when running Universe.plot --- openmc/universe.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmc/universe.py b/openmc/universe.py index 78f75bbfc..7dee19313 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -334,6 +334,13 @@ class Universe(UniverseBase): if seed is not None: model.settings.seed = seed + # Determine whether any materials contains macroscopic data and if + # so, set energy mode accordingly + for mat in self.get_all_materials().values(): + if mat._macroscopic is not None: + model.settings.energy_mode = 'multi-group' + break + # Create plot object matching passed arguments plot = openmc.Plot() plot.origin = origin From 17482d4fbe6a61aafb5369693549ef86bd04ec93 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 3 Aug 2022 06:45:38 -0500 Subject: [PATCH 0734/2654] Change ordering of halfspaces for RectangularParallelepiped -/+ --- openmc/model/surface_composite.py | 4 ++-- tests/regression_tests/torus/inputs_true.dat | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 6271154fb..51019b0d8 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -451,10 +451,10 @@ class RectangularParallelepiped(CompositeSurface): self.zmax = openmc.ZPlane(z0=zmax, **kwargs) def __neg__(self): - return +self.xmin & -self.xmax & +self.ymin & -self.ymax & +self.zmin & -self.zmax + return -self.xmax & +self.xmin & -self.ymax & +self.ymin & -self.zmax & +self.zmin def __pos__(self): - return -self.xmin | +self.xmax | -self.ymin | +self.ymax | -self.zmin | +self.zmax + return +self.xmax | -self.xmin | +self.ymax | -self.ymin | +self.zmax | -self.zmin class XConeOneSided(CompositeSurface): diff --git a/tests/regression_tests/torus/inputs_true.dat b/tests/regression_tests/torus/inputs_true.dat index 0045d7e46..0ccbda400 100644 --- a/tests/regression_tests/torus/inputs_true.dat +++ b/tests/regression_tests/torus/inputs_true.dat @@ -3,7 +3,7 @@ - + From aa5526aab6e8ea75af389cf63daf9a43f4fff196 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 3 Aug 2022 13:49:30 +0100 Subject: [PATCH 0735/2654] Review suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/deplete/results.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 9d4913300..7e1c6431e 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -24,7 +24,7 @@ def _get_time_as(seconds, units): The time to convert expressed in seconds units : {"s", "min", "h", "d", "a"} The units to convert time into. Available options are seconds ``"s"``, - minutes ``"min"``, hours ``"hours"`` days ``"d"``, years ``"a"`` + minutes ``"min"``, hours ``"h"`` days ``"d"``, Julian years ``"a"`` """ if units == "a": @@ -111,8 +111,7 @@ class Results(list): time_units : {"s", "min", "h", "d", "a"}, optional Units for the returned time array. Default is ``"s"`` to return the value in seconds. Other options are minutes ``"min"``, - hours ``"hours"``, days ``"d"``, years ``"a"`` (Julian year 365.25 - days). + hours ``"h"``, days ``"d"``, and Julian years ``"a"``. .. versionadded:: 0.12 @@ -206,9 +205,9 @@ class Results(list): Parameters ---------- time_units : {"s", "d", "min", "h", "a"}, optional - Desired units for the times array. Options are seconds ``"s"`` - minutes ``"min"``, hours ``"hours"``, days ``"d"``, years ``"a"`` - (Julian year 365.25 days). + Desired units for the times array. Options are seconds ``"s"``, + minutes ``"min"``, hours ``"h"``, days ``"d"``, and Julian years + ``"a"``. Returns ------- @@ -277,8 +276,7 @@ class Results(list): time_units : {"s", "d", "min", "h", "a"}, optional Return the vector in these units. Default is to convert to days ``"d"``. Other options are seconds ``"s"``, minutes - ``"min"``, hours ``"hours"``, years ``"a"`` (Julian year 365.25 - days). + ``"min"``, hours ``"h"``, days ``"d"``, and Julian years ``"a"``. Returns ------- @@ -317,8 +315,7 @@ class Results(list): Desired point in time time_units : {"s", "d", "min", "h", "a"}, optional Units on ``time``. Default: days ``"d"``. Other options are seconds - ``"s"``, minutes ``"min"``, hours ``"hours"`` and years ``"a"`` - (Julian year 365.25 days) + ``"s"``, minutes ``"min"``, hours ``"h"`` and Julian years ``"a"``. atol : float, optional Absolute tolerance (in ``time_units``) if ``time`` is not found. From b32d121e22db8385e4a4dd7258328a4f30792074 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 20 Jul 2022 23:03:40 -0500 Subject: [PATCH 0736/2654] Use add_params decorator to cut down on repeated docstrings for MGXS classes --- openmc/mgxs/mgxs.py | 962 +++----------------------------------------- 1 file changed, 52 insertions(+), 910 deletions(-) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 453c1d099..387a98ea5 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -147,6 +147,11 @@ def _df_column_convert_to_bin(df, current_name, new_name, values_to_bin, df.rename(columns={current_name: new_name}, inplace=True) +def add_params(cls): + cls.__doc__ += cls._params + return cls + +@add_params class MGXS: """An abstract multi-group cross section for some energy group structure within some spatial domain. @@ -157,6 +162,9 @@ class MGXS: .. note:: Users should instantiate the subclasses of this abstract class. + """ + + _params = """ Parameters ---------- domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh @@ -2148,6 +2156,7 @@ class MGXS: return 'cm^-1' if xs_type == 'macro' else 'barns' +@add_params class MatrixMGXS(MGXS): """An abstract multi-group cross section for some energy group structure within some spatial domain. This class is specifically intended for @@ -2161,92 +2170,6 @@ class MatrixMGXS(MGXS): .. note:: Users should instantiate the subclasses of this abstract class. - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ @property def _dont_squeeze(self): @@ -2631,6 +2554,7 @@ class MatrixMGXS(MGXS): print(string) +@add_params class TotalXS(MGXS): r"""A total multi-group cross section. @@ -2657,98 +2581,11 @@ class TotalXS(MGXS): \sigma_t (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`TotalXS.tally_keys` property and values - are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'total' @@ -2887,9 +2724,9 @@ class TransportXS(MGXS): """ - def __init__(self, domain=None, domain_type=None, groups=None, nu=False, + def __init__(self, domain=None, domain_type=None, energy_groups=None, nu=False, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) # Use tracklength estimators for the total MGXS term, and @@ -3128,9 +2965,9 @@ class DiffusionCoefficient(TransportXS): """ - def __init__(self, domain=None, domain_type=None, groups=None, nu=False, + def __init__(self, domain=None, domain_type=None, energy_groups=None, nu=False, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super(DiffusionCoefficient, self).__init__(domain, domain_type, groups, + super(DiffusionCoefficient, self).__init__(domain, domain_type, energy_groups, nu, by_nuclide, name, num_polar, num_azimuthal) if not nu: @@ -3194,6 +3031,7 @@ class DiffusionCoefficient(TransportXS): return self._xs_tally +@add_params class AbsorptionXS(MGXS): r"""An absorption multi-group cross section. @@ -3224,103 +3062,16 @@ class AbsorptionXS(MGXS): \sigma_a (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`AbsorptionXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'absorption' +@add_params class CaptureXS(MGXS): r"""A capture multi-group cross section. @@ -3354,98 +3105,11 @@ class CaptureXS(MGXS): \Omega) \right ]}{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`CaptureXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'capture' @@ -3599,10 +3263,10 @@ class FissionXS(MGXS): """ - def __init__(self, domain=None, domain_type=None, groups=None, nu=False, + def __init__(self, domain=None, domain_type=None, energy_groups=None, nu=False, prompt=False, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._nu = False self._prompt = False @@ -3648,6 +3312,7 @@ class FissionXS(MGXS): self._rxn_type = 'prompt-nu-fission' +@add_params class KappaFissionXS(MGXS): r"""A recoverable fission energy production rate multi-group cross section. @@ -3681,98 +3346,11 @@ class KappaFissionXS(MGXS): \kappa\sigma_f (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`KappaFissionXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'kappa-fission' @@ -3904,10 +3482,10 @@ class ScatterXS(MGXS): """ - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1, nu=False): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self.nu = nu @@ -3932,6 +3510,7 @@ class ScatterXS(MGXS): self._valid_estimators = ['analog'] +@add_params class ArbitraryXS(MGXS): r"""A multi-group cross section for an arbitrary reaction type. @@ -3960,105 +3539,17 @@ class ArbitraryXS(MGXS): where :math:`\sigma_X` is the requested reaction type of interest. - Parameters - ---------- - rxn_type : str - Reaction type (e.g., '(n,2n)', '(n,Xt)', etc.) - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., '(n,2n)', '(n,Xt)', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`TotalXS.tally_keys` property and values - are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ - def __init__(self, rxn_type, domain=None, domain_type=None, groups=None, + def __init__(self, rxn_type, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): cv.check_value("rxn_type", rxn_type, ARBITRARY_VECTOR_TYPES) - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = rxn_type +@add_params class ArbitraryMatrixXS(MatrixMGXS): r"""A multi-group matrix cross section for an arbitrary reaction type. @@ -4094,103 +3585,13 @@ class ArbitraryMatrixXS(MatrixMGXS): where :math:`\sigma_X` is the requested reaction type of interest. - Parameters - ---------- - rxn_type : str - Reaction type (e.g., '(n,2n)', '(n,nta)', etc.). Valid names have - neutrons as a product. - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`NuFissionMatrixXS.tally_keys` - property and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ - def __init__(self, rxn_type, domain=None, domain_type=None, groups=None, + def __init__(self, rxn_type, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): cv.check_value("rxn_type", rxn_type, ARBITRARY_MATRIX_TYPES) - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = rxn_type.split(" ")[0] self._estimator = 'analog' @@ -4391,10 +3792,10 @@ class ScatterMatrixXS(MatrixMGXS): """ - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1, nu=False): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._formulation = 'simple' self._correction = 'P0' @@ -5352,6 +4753,7 @@ class ScatterMatrixXS(MatrixMGXS): print(string) +@add_params class MultiplicityMatrixXS(MatrixMGXS): r"""The scattering multiplicity matrix. @@ -5392,93 +4794,6 @@ class MultiplicityMatrixXS(MatrixMGXS): where :math:`\upsilon_i` is the multiplicity for the :math:`i`-th reaction. - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`MultiplicityMatrixXS.tally_keys` - property and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ # Store whether or not the number density should be removed for microscopic @@ -5487,9 +4802,9 @@ class MultiplicityMatrixXS(MatrixMGXS): # for microscopic data _divide_by_density = False - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'multiplicity matrix' self._estimator = 'analog' @@ -5530,6 +4845,7 @@ class MultiplicityMatrixXS(MatrixMGXS): return self._xs_tally +@add_params class ScatterProbabilityMatrix(MatrixMGXS): r"""The group-to-group scattering probability matrix. @@ -5568,93 +4884,6 @@ class ScatterProbabilityMatrix(MatrixMGXS): \sigma_{s,g'} \phi \rangle} \end{aligned} - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`ScatterProbabilityMatrix.tally_keys` - property and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ # Store whether or not the number density should be removed for microscopic @@ -5662,9 +4891,9 @@ class ScatterProbabilityMatrix(MatrixMGXS): # to 1.0, this density division is not necessary _divide_by_density = False - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'scatter' self._mgxs_type = 'scatter probability matrix' @@ -5833,10 +5062,10 @@ class NuFissionMatrixXS(MatrixMGXS): """ - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1, prompt=False): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) if not prompt: self._rxn_type = 'nu-fission' @@ -5999,10 +5228,10 @@ class Chi(MGXS): # data should not be divided by the number density _divide_by_density = False - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, prompt=False, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._estimator = 'analog' self._valid_estimators = ['analog'] @@ -6401,6 +5630,7 @@ class Chi(MGXS): return '%' +@add_params class InverseVelocity(MGXS): r"""An inverse velocity multi-group cross section. @@ -6430,94 +5660,6 @@ class InverseVelocity(MGXS): \frac{\psi (r, E, \Omega)}{v (r, E)}}{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)} - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`InverseVelocity.tally_keys` property - and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - mgxs_type : str - The name of this MGXS type, to be used when printing and - indexing in an HDF5 data store - - .. versionadded:: 0.13.1 - """ # Store whether or not the number density should be removed for microscopic @@ -6526,9 +5668,9 @@ class InverseVelocity(MGXS): # values _divide_by_density = False - def __init__(self, domain=None, domain_type=None, groups=None, + def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, num_polar, num_azimuthal) self._rxn_type = 'inverse-velocity' @@ -7031,7 +6173,7 @@ class Current(MeshSurfaceMGXS): """ def __init__(self, domain=None, domain_type=None, - groups=None, by_nuclide=False, name=''): + energy_groups=None, by_nuclide=False, name=''): super(Current, self).__init__(domain, domain_type, - groups, by_nuclide, name) + energy_groups, by_nuclide, name) self._rxn_type = 'current' From 54ac2042fbdb1b741447d138b6045a7420149763 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Jul 2022 07:07:25 -0500 Subject: [PATCH 0737/2654] Add ReducedAbsorptionXS class for MGXS (absorption - n2n - 2*n3n - 3*n4n) --- docs/source/pythonapi/mgxs.rst | 1 + openmc/mgxs/mgxs.py | 61 + .../mgxs_library_condense/inputs_true.dat | 358 ++-- .../mgxs_library_condense/results_true.dat | 6 + .../mgxs_library_distribcell/inputs_true.dat | 316 ++-- .../mgxs_library_distribcell/results_true.dat | 2 + .../mgxs_library_hdf5/inputs_true.dat | 358 ++-- .../mgxs_library_hdf5/results_true.dat | 3 + .../mgxs_library_mesh/inputs_true.dat | 316 ++-- .../mgxs_library_mesh/results_true.dat | 6 + .../mgxs_library_no_nuclides/inputs_true.dat | 1632 +++++++++-------- .../mgxs_library_no_nuclides/results_true.dat | 12 + .../mgxs_library_nuclides/inputs_true.dat | 1476 ++++++++------- .../mgxs_library_nuclides/results_true.dat | 2 +- 14 files changed, 2470 insertions(+), 2079 deletions(-) diff --git a/docs/source/pythonapi/mgxs.rst b/docs/source/pythonapi/mgxs.rst index bf5a84599..392914b36 100644 --- a/docs/source/pythonapi/mgxs.rst +++ b/docs/source/pythonapi/mgxs.rst @@ -41,6 +41,7 @@ Multi-group Cross Sections openmc.mgxs.KappaFissionXS openmc.mgxs.MultiplicityMatrixXS openmc.mgxs.NuFissionMatrixXS + openmc.mgxs.ReducedAbsorptionXS openmc.mgxs.ScatterXS openmc.mgxs.ScatterMatrixXS openmc.mgxs.ScatterProbabilityMatrix diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 387a98ea5..75a33eed7 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -20,6 +20,7 @@ MGXS_TYPES = ( 'transport', 'nu-transport', 'absorption', + 'reduced absorption', 'capture', 'fission', 'nu-fission', @@ -772,6 +773,8 @@ class MGXS: mgxs = TransportXS(domain, domain_type, energy_groups, nu=True) elif mgxs_type == 'absorption': mgxs = AbsorptionXS(domain, domain_type, energy_groups) + elif mgxs_type == 'reduced absorption': + mgxs = ReducedAbsorptionXS(domain, domain_type, energy_groups) elif mgxs_type == 'capture': mgxs = CaptureXS(domain, domain_type, energy_groups) elif mgxs_type == 'fission': @@ -824,6 +827,8 @@ class MGXS: elif mgxs_type in ARBITRARY_MATRIX_TYPES: mgxs = ArbitraryMatrixXS(mgxs_type, domain, domain_type, energy_groups) + else: + raise ValueError(f"Unknown MGXS type: {mgxs_type}") mgxs.by_nuclide = by_nuclide mgxs.name = name @@ -3071,6 +3076,62 @@ class AbsorptionXS(MGXS): self._rxn_type = 'absorption' +@add_params +class ReducedAbsorptionXS(MGXS): + r"""A reduced absorpiton multi-group cross section. + + The reduced absorption reaction rate is defined as the difference between + absorption and the produced of neutrons due to (n,xn) reactions. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group capture cross sections for multi-group neutronics calculations. + At a minimum, one needs to set the :attr:`CaptureXS.energy_groups` and + :attr:`CaptureXS.domain` properties. Tallies for the flux and appropriate + reaction rates over the specified domain are generated automatically via the + :attr:`CaptureXS.tallies` property, which can then be appended to a + :class:`openmc.Tallies` instance. + + For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the + necessary data to compute multi-group cross sections from a + :class:`openmc.StatePoint` instance. The derived multi-group cross section + can then be obtained from the :attr:`CaptureXS.xs_tally` property. + + For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the + reduced absorption cross section is calculated as: + + .. math:: + + \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; + \left(\sigma_a (r, E) - \sigma_{n,2n}(r,E) - 2\sigma_{n,3n}(r,E) - + 3\sigma_{n,4n}(r,E) \right) \psi (r, E, \Omega)}{\int_{r \in V} dr + \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. + + """ + + def __init__(self, domain=None, domain_type=None, energy_groups=None, + by_nuclide=False, name='', num_polar=1, num_azimuthal=1): + super().__init__(domain, domain_type, energy_groups, by_nuclide, name, + num_polar, num_azimuthal) + self._rxn_type = 'reduced absorption' + + @property + def scores(self): + return ['flux', 'absorption', '(n,2n)', '(n,3n)', '(n,4n)'] + + @property + def rxn_rate_tally(self): + if self._rxn_rate_tally is None: + self._rxn_rate_tally = ( + self.tallies['absorption'] + - self.tallies['(n,2n)'] + - 2*self.tallies['(n,3n)'] + - 3*self.tallies['(n,4n)'] + ) + self._rxn_rate_tally.sparse = self.sparse + return self._rxn_rate_tally + + @add_params class CaptureXS(MGXS): r"""A capture multi-group cross section. diff --git a/tests/regression_tests/mgxs_library_condense/inputs_true.dat b/tests/regression_tests/mgxs_library_condense/inputs_true.dat index 9661cd46b..cac18ffcd 100644 --- a/tests/regression_tests/mgxs_library_condense/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_condense/inputs_true.dat @@ -67,16 +67,16 @@ 1 - + 3 - + 0.0 20000000.0 - + 1 - + 1 2 3 4 5 6 @@ -166,19 +166,19 @@ 1 2 total - fission + (n,2n) tracklength 1 2 total - flux + (n,3n) tracklength 1 2 total - fission + (n,4n) tracklength @@ -190,207 +190,207 @@ 1 2 total - nu-fission + absorption tracklength 1 2 total - flux + fission tracklength 1 2 total - kappa-fission + flux tracklength 1 2 total - flux + fission tracklength 1 2 total - scatter + flux tracklength 1 2 total - flux - analog + nu-fission + tracklength 1 2 total - nu-scatter - analog + flux + tracklength 1 2 total - flux - analog + kappa-fission + tracklength - 1 2 5 28 + 1 2 total - scatter - analog + flux + tracklength + 1 2 + total + scatter + tracklength + + 1 2 total flux analog - - 1 2 5 28 - total - nu-scatter - analog - - 1 2 5 + 1 2 total nu-scatter analog - 1 2 5 + 1 2 total - scatter + flux analog - 1 2 + 1 2 5 30 total - flux + scatter analog - 1 2 5 + 1 2 total - nu-fission + flux analog - 1 2 5 + 1 2 5 30 total - scatter + nu-scatter analog - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - 1 2 5 total nu-scatter analog - - 1 52 + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 total nu-fission analog - - 1 5 + + 1 2 5 total - nu-fission + scatter analog - - 1 52 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - + 1 2 total flux tracklength + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + 1 54 + total + nu-fission + analog + + + 1 5 + total + nu-fission + analog + + + 1 54 + total + prompt-nu-fission + analog + + + 1 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + 1 2 total inverse-velocity tracklength - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 66 2 - total - current - analog - 1 2 total @@ -400,7 +400,7 @@ 1 2 total - total + prompt-nu-fission tracklength @@ -410,91 +410,121 @@ analog - 1 5 6 + 1 2 5 total - scatter + prompt-nu-fission analog - 1 2 + 68 2 total - flux - tracklength + current + analog 1 2 total - total + flux tracklength + 1 2 + total + total + tracklength + + 1 2 total flux analog - + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + 1 5 6 total nu-scatter analog - + 1 2 total flux tracklength - - 1 77 2 - total - delayed-nu-fission - tracklength - - - 1 77 52 - total - delayed-nu-fission - analog - - - 1 77 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 77 2 - total - delayed-nu-fission - tracklength - - 1 77 + 1 79 2 total delayed-nu-fission tracklength - 1 77 + 1 79 54 + total + delayed-nu-fission + analog + + + 1 79 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 + total + delayed-nu-fission + tracklength + + + 1 79 total decay-rate tracklength - + 1 2 total flux analog - - 1 77 2 5 + + 1 79 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_condense/results_true.dat b/tests/regression_tests/mgxs_library_condense/results_true.dat index 508984e54..e0b47a78b 100644 --- a/tests/regression_tests/mgxs_library_condense/results_true.dat +++ b/tests/regression_tests/mgxs_library_condense/results_true.dat @@ -24,6 +24,12 @@ 3 2 2 1 1 total 0.022046 0.001594 mesh 1 group in nuclide mean std. dev. x y z +0 1 1 1 1 total 0.021489 0.001396 +2 1 2 1 1 total 0.020837 0.001436 +1 2 1 1 1 total 0.021454 0.001983 +3 2 2 1 1 total 0.022036 0.001594 + mesh 1 group in nuclide mean std. dev. + x y z 0 1 1 1 1 total 0.011598 0.001508 2 1 2 1 1 total 0.010856 0.001613 1 2 1 1 1 total 0.011622 0.002259 diff --git a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat index 602e04abe..bd6abbb7c 100644 --- a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat @@ -89,10 +89,10 @@ 1 - + 3 - + 1 2 3 4 5 6 @@ -182,19 +182,19 @@ 1 2 total - fission + (n,2n) tracklength 1 2 total - flux + (n,3n) tracklength 1 2 total - fission + (n,4n) tracklength @@ -206,305 +206,335 @@ 1 2 total - nu-fission + absorption tracklength 1 2 total - flux + fission tracklength 1 2 total - kappa-fission + flux tracklength 1 2 total - flux + fission tracklength 1 2 total - scatter + flux tracklength 1 2 total - flux - analog + nu-fission + tracklength 1 2 total - nu-scatter - analog + flux + tracklength 1 2 total - flux - analog + kappa-fission + tracklength - 1 2 5 28 + 1 2 total - scatter - analog + flux + tracklength + 1 2 + total + scatter + tracklength + + 1 2 total flux analog - - 1 2 5 28 - total - nu-scatter - analog - - 1 2 5 + 1 2 total nu-scatter analog - 1 2 5 + 1 2 total - scatter + flux analog - 1 2 + 1 2 5 30 total - flux + scatter analog - 1 2 5 + 1 2 total - nu-fission + flux analog - 1 2 5 + 1 2 5 30 total - scatter + nu-scatter analog - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - 1 2 5 total nu-scatter analog - + + 1 2 5 + total + scatter + analog + + 1 2 total + flux + analog + + + 1 2 5 + total nu-fission analog - - 1 5 + + 1 2 5 total - nu-fission + scatter analog + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + 1 2 total - prompt-nu-fission - analog + scatter + tracklength - 1 5 + 1 2 5 30 total - prompt-nu-fission + scatter analog - 1 2 + 1 2 5 total - flux - tracklength + nu-scatter + analog 1 2 total - inverse-velocity - tracklength + nu-fission + analog - 1 2 + 1 5 total - flux - tracklength + nu-fission + analog 1 2 total prompt-nu-fission - tracklength - - - 1 2 - total - flux analog - - 1 2 5 + + 1 5 total prompt-nu-fission analog - + 1 2 total flux tracklength + + 1 2 + total + inverse-velocity + tracklength + 1 2 total - total + flux tracklength 1 2 total - flux - analog + prompt-nu-fission + tracklength - 1 5 6 - total - scatter - analog - - 1 2 total flux - tracklength + analog + + + 1 2 5 + total + prompt-nu-fission + analog 1 2 total - total + flux tracklength + 1 2 + total + total + tracklength + + 1 2 total flux analog - + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + 1 5 6 total nu-scatter analog - + 1 2 total flux tracklength - - 1 73 2 - total - delayed-nu-fission - tracklength - - - 1 73 2 - total - delayed-nu-fission - analog - - - 1 73 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 73 2 - total - delayed-nu-fission - tracklength - - 1 73 + 1 75 2 total delayed-nu-fission tracklength - 1 73 + 1 75 2 + total + delayed-nu-fission + analog + + + 1 75 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 75 2 + total + delayed-nu-fission + tracklength + + + 1 75 + total + delayed-nu-fission + tracklength + + + 1 75 total decay-rate tracklength - + 1 2 total flux analog - - 1 73 2 5 + + 1 75 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_distribcell/results_true.dat b/tests/regression_tests/mgxs_library_distribcell/results_true.dat index e6e4b99e4..3d362c1bd 100644 --- a/tests/regression_tests/mgxs_library_distribcell/results_true.dat +++ b/tests/regression_tests/mgxs_library_distribcell/results_true.dat @@ -7,6 +7,8 @@ sum(distribcell) group in nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, ...),) 1 total 0.06484 0.002514 sum(distribcell) group in nuclide mean std. dev. +0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, ...),) 1 total 0.064761 0.002514 + sum(distribcell) group in nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, ...),) 1 total 0.028638 0.002713 sum(distribcell) group in nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, ...),) 1 total 0.036203 0.001449 diff --git a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat index 9661cd46b..cac18ffcd 100644 --- a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat @@ -67,16 +67,16 @@ 1 - + 3 - + 0.0 20000000.0 - + 1 - + 1 2 3 4 5 6 @@ -166,19 +166,19 @@ 1 2 total - fission + (n,2n) tracklength 1 2 total - flux + (n,3n) tracklength 1 2 total - fission + (n,4n) tracklength @@ -190,207 +190,207 @@ 1 2 total - nu-fission + absorption tracklength 1 2 total - flux + fission tracklength 1 2 total - kappa-fission + flux tracklength 1 2 total - flux + fission tracklength 1 2 total - scatter + flux tracklength 1 2 total - flux - analog + nu-fission + tracklength 1 2 total - nu-scatter - analog + flux + tracklength 1 2 total - flux - analog + kappa-fission + tracklength - 1 2 5 28 + 1 2 total - scatter - analog + flux + tracklength + 1 2 + total + scatter + tracklength + + 1 2 total flux analog - - 1 2 5 28 - total - nu-scatter - analog - - 1 2 5 + 1 2 total nu-scatter analog - 1 2 5 + 1 2 total - scatter + flux analog - 1 2 + 1 2 5 30 total - flux + scatter analog - 1 2 5 + 1 2 total - nu-fission + flux analog - 1 2 5 + 1 2 5 30 total - scatter + nu-scatter analog - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - 1 2 5 total nu-scatter analog - - 1 52 + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 total nu-fission analog - - 1 5 + + 1 2 5 total - nu-fission + scatter analog - - 1 52 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - + 1 2 total flux tracklength + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + 1 54 + total + nu-fission + analog + + + 1 5 + total + nu-fission + analog + + + 1 54 + total + prompt-nu-fission + analog + + + 1 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + 1 2 total inverse-velocity tracklength - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 66 2 - total - current - analog - 1 2 total @@ -400,7 +400,7 @@ 1 2 total - total + prompt-nu-fission tracklength @@ -410,91 +410,121 @@ analog - 1 5 6 + 1 2 5 total - scatter + prompt-nu-fission analog - 1 2 + 68 2 total - flux - tracklength + current + analog 1 2 total - total + flux tracklength + 1 2 + total + total + tracklength + + 1 2 total flux analog - + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + 1 5 6 total nu-scatter analog - + 1 2 total flux tracklength - - 1 77 2 - total - delayed-nu-fission - tracklength - - - 1 77 52 - total - delayed-nu-fission - analog - - - 1 77 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 77 2 - total - delayed-nu-fission - tracklength - - 1 77 + 1 79 2 total delayed-nu-fission tracklength - 1 77 + 1 79 54 + total + delayed-nu-fission + analog + + + 1 79 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 + total + delayed-nu-fission + tracklength + + + 1 79 total decay-rate tracklength - + 1 2 total flux analog - - 1 77 2 5 + + 1 79 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_hdf5/results_true.dat b/tests/regression_tests/mgxs_library_hdf5/results_true.dat index 6da73ec9b..b075939f2 100644 --- a/tests/regression_tests/mgxs_library_hdf5/results_true.dat +++ b/tests/regression_tests/mgxs_library_hdf5/results_true.dat @@ -10,6 +10,9 @@ domain=1 type=nu-transport domain=1 type=absorption [9.18204614e-03 9.50890834e-02] [1.02291781e-03 9.51211716e-03] +domain=1 type=reduced absorption +[9.15806809e-03 9.50890834e-02] +[1.02286279e-03 9.51211716e-03] domain=1 type=capture [6.76780024e-03 4.04282690e-02] [1.01848835e-03 8.89313901e-03] diff --git a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat index 5cac8ecf4..ac2ff0c81 100644 --- a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat @@ -50,13 +50,13 @@ 1 - + 3 - + 1 - + 1 2 3 4 5 6 @@ -146,19 +146,19 @@ 1 2 total - fission + (n,2n) tracklength 1 2 total - flux + (n,3n) tracklength 1 2 total - fission + (n,4n) tracklength @@ -170,206 +170,206 @@ 1 2 total - nu-fission + absorption tracklength 1 2 total - flux + fission tracklength 1 2 total - kappa-fission + flux tracklength 1 2 total - flux + fission tracklength 1 2 total - scatter + flux tracklength 1 2 total - flux - analog + nu-fission + tracklength 1 2 total - nu-scatter - analog + flux + tracklength 1 2 total - flux - analog + kappa-fission + tracklength - 1 2 5 28 + 1 2 total - scatter - analog + flux + tracklength + 1 2 + total + scatter + tracklength + + 1 2 total flux analog - - 1 2 5 28 - total - nu-scatter - analog - - 1 2 5 + 1 2 total nu-scatter analog - 1 2 5 + 1 2 total - scatter + flux analog - 1 2 + 1 2 5 30 total - flux + scatter analog - 1 2 5 + 1 2 total - nu-fission + flux analog - 1 2 5 + 1 2 5 30 total - scatter + nu-scatter analog - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - 1 2 5 total nu-scatter analog - + + 1 2 5 + total + scatter + analog + + 1 2 total + flux + analog + + + 1 2 5 + total nu-fission analog - - 1 5 + + 1 2 5 total - nu-fission + scatter analog + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + 1 2 total - prompt-nu-fission - analog + scatter + tracklength - 1 5 + 1 2 5 30 total - prompt-nu-fission + scatter analog - 1 2 + 1 2 5 total - flux - tracklength + nu-scatter + analog 1 2 total - inverse-velocity - tracklength + nu-fission + analog - 1 2 + 1 5 total - flux - tracklength + nu-fission + analog 1 2 total prompt-nu-fission - tracklength - - - 1 2 - total - flux analog - - 1 2 5 + + 1 5 total prompt-nu-fission analog - - 66 2 + + 1 2 total - current - analog + flux + tracklength + + + 1 2 + total + inverse-velocity + tracklength 1 2 @@ -380,7 +380,7 @@ 1 2 total - total + prompt-nu-fission tracklength @@ -390,91 +390,121 @@ analog - 1 5 6 + 1 2 5 total - scatter + prompt-nu-fission analog - 1 2 + 68 2 total - flux - tracklength + current + analog 1 2 total - total + flux tracklength + 1 2 + total + total + tracklength + + 1 2 total flux analog - + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + 1 5 6 total nu-scatter analog - + 1 2 total flux tracklength - - 1 77 2 - total - delayed-nu-fission - tracklength - - - 1 77 2 - total - delayed-nu-fission - analog - - - 1 77 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 77 2 - total - delayed-nu-fission - tracklength - - 1 77 + 1 79 2 total delayed-nu-fission tracklength - 1 77 + 1 79 2 + total + delayed-nu-fission + analog + + + 1 79 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 + total + delayed-nu-fission + tracklength + + + 1 79 total decay-rate tracklength - + 1 2 total flux analog - - 1 77 2 5 + + 1 79 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_mesh/results_true.dat b/tests/regression_tests/mgxs_library_mesh/results_true.dat index 7a6b4abe7..390b5c453 100644 --- a/tests/regression_tests/mgxs_library_mesh/results_true.dat +++ b/tests/regression_tests/mgxs_library_mesh/results_true.dat @@ -24,6 +24,12 @@ 3 2 2 1 1 total 0.013286 0.000621 mesh 1 group in nuclide mean std. dev. x y z +0 1 1 1 1 total 0.012881 0.000835 +2 1 2 1 1 total 0.013282 0.000552 +1 2 1 1 1 total 0.013896 0.000714 +3 2 2 1 1 total 0.013180 0.000621 + mesh 1 group in nuclide mean std. dev. + x y z 0 1 1 1 1 total 0.001231 0.000979 2 1 2 1 1 total 0.001332 0.000691 1 2 1 1 1 total 0.001346 0.000770 diff --git a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat index 0d9dbf821..59cbddec4 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat @@ -62,19 +62,19 @@ 1 - + 3 - + 0.0 20000000.0 - + 1 2 3 4 5 6 - + 2 - + 3 @@ -164,19 +164,19 @@ 1 2 total - fission + (n,2n) tracklength 1 2 total - flux + (n,3n) tracklength 1 2 total - fission + (n,4n) tracklength @@ -188,1673 +188,1763 @@ 1 2 total - nu-fission + absorption tracklength 1 2 total - flux + fission tracklength 1 2 total - kappa-fission + flux tracklength 1 2 total - flux + fission tracklength 1 2 total - scatter + flux tracklength 1 2 total - flux - analog + nu-fission + tracklength 1 2 total - nu-scatter - analog + flux + tracklength 1 2 total - flux - analog + kappa-fission + tracklength - 1 2 5 28 + 1 2 total - scatter - analog + flux + tracklength + 1 2 + total + scatter + tracklength + + 1 2 total flux analog - - 1 2 5 28 - total - nu-scatter - analog - - 1 2 5 + 1 2 total nu-scatter analog - 1 2 5 + 1 2 total - scatter + flux analog - 1 2 + 1 2 5 30 total - flux + scatter analog - 1 2 5 + 1 2 total - nu-fission + flux analog - 1 2 5 + 1 2 5 30 total - scatter + nu-scatter analog - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - 1 2 5 total nu-scatter analog - - 1 52 + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 total nu-fission analog + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 54 + total + nu-fission + analog + + 1 5 total nu-fission analog - - 1 52 + + 1 54 total prompt-nu-fission analog - + 1 5 total prompt-nu-fission analog - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - 1 2 5 + 1 2 total - prompt-nu-fission - analog + flux + tracklength 1 2 total - flux + inverse-velocity tracklength 1 2 total - total + flux tracklength 1 2 total - flux - analog + prompt-nu-fission + tracklength - 1 5 6 - total - scatter - analog - - 1 2 total flux - tracklength + analog + + + 1 2 5 + total + prompt-nu-fission + analog 1 2 total - total + flux tracklength 1 2 total - flux - analog + total + tracklength - 1 5 6 - total - nu-scatter - analog - - 1 2 total flux - tracklength + analog + + + 1 5 6 + total + scatter + analog 1 2 total - (n,elastic) + flux tracklength 1 2 total - flux + total tracklength 1 2 total - (n,level) - tracklength + flux + analog - 1 2 + 1 5 6 total - flux - tracklength + nu-scatter + analog 1 2 total - (n,2n) + flux tracklength 1 2 total - flux + (n,elastic) tracklength 1 2 total - (n,na) + flux tracklength 1 2 total - flux + (n,level) tracklength 1 2 total - (n,nc) + flux tracklength 1 2 total - flux + (n,2n) tracklength 1 2 total - (n,gamma) + flux tracklength 1 2 total - flux + (n,na) tracklength 1 2 total - (n,a) + flux tracklength 1 2 total - flux + (n,nc) tracklength 1 2 total - (n,Xa) + flux tracklength 1 2 total - flux + (n,gamma) tracklength 1 2 total - heating + flux tracklength 1 2 total - flux + (n,a) tracklength 1 2 total - damage-energy + flux tracklength 1 2 total - flux + (n,Xa) tracklength 1 2 total - (n,n1) + flux tracklength 1 2 total - flux + heating tracklength 1 2 total - (n,a0) + flux tracklength + 1 2 + total + damage-energy + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,n1) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,a0) + tracklength + + 1 2 total flux analog - + 1 2 5 total (n,nc) analog - + 1 2 total flux analog - + 1 2 5 total (n,n1) analog - + 1 2 total flux analog - + 1 2 5 total (n,2n) analog - + 1 2 total flux tracklength - - 1 106 2 - total - delayed-nu-fission - tracklength - - - 1 106 52 - total - delayed-nu-fission - analog - - - 1 106 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 106 2 - total - delayed-nu-fission - tracklength - - 1 106 + 1 108 2 total delayed-nu-fission tracklength - 1 106 + 1 108 54 + total + delayed-nu-fission + analog + + + 1 108 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 108 2 + total + delayed-nu-fission + tracklength + + + 1 108 + total + delayed-nu-fission + tracklength + + + 1 108 total decay-rate tracklength - + 1 2 total flux analog - - 1 106 2 5 + + 1 108 2 5 total delayed-nu-fission analog - - 120 2 + + 122 2 total flux tracklength - - 120 2 + + 122 2 total total tracklength - - 120 2 + + 122 2 total flux tracklength - - 120 2 + + 122 2 total total tracklength - - 120 2 + + 122 2 total flux analog - - 120 5 6 + + 122 5 6 total scatter analog - - 120 2 + + 122 2 total flux tracklength - - 120 2 + + 122 2 total total tracklength - - 120 2 + + 122 2 total flux analog - - 120 5 6 + + 122 5 6 total nu-scatter analog - - 120 2 - total - flux - tracklength - - - 120 2 - total - absorption - tracklength - - - 120 2 - total - flux - tracklength - - - 120 2 - total - absorption - tracklength - - - 120 2 - total - fission - tracklength - - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - fission + absorption tracklength - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - nu-fission + absorption tracklength - 120 2 + 122 2 + total + (n,2n) + tracklength + + + 122 2 + total + (n,3n) + tracklength + + + 122 2 + total + (n,4n) + tracklength + + + 122 2 total flux tracklength - - 120 2 + + 122 2 + total + absorption + tracklength + + + 122 2 + total + fission + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + fission + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + nu-fission + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 total kappa-fission tracklength - - 120 2 - total - flux - tracklength - - - 120 2 - total - scatter - tracklength - - - 120 2 - total - flux - analog - - - 120 2 - total - nu-scatter - analog - - - 120 2 - total - flux - analog - - - 120 2 5 28 - total - scatter - analog - - - 120 2 - total - flux - analog - - - 120 2 5 28 - total - nu-scatter - analog - - - 120 2 5 - total - nu-scatter - analog - - - 120 2 5 - total - scatter - analog - - 120 2 + 122 2 total flux - analog + tracklength - 120 2 5 - total - nu-fission - analog - - - 120 2 5 + 122 2 total scatter + tracklength + + + 122 2 + total + flux analog - 120 2 + 122 2 total - flux - tracklength + nu-scatter + analog - 120 2 + 122 2 total - scatter - tracklength + flux + analog - 120 2 5 28 + 122 2 5 30 total scatter analog - 120 2 + 122 2 total flux - tracklength - - - 120 2 - total - scatter - tracklength - - - 120 2 5 28 - total - scatter analog - - 120 2 5 + + 122 2 5 30 total nu-scatter analog - - 120 52 + + 122 2 5 total - nu-fission + nu-scatter + analog + + + 122 2 5 + total + scatter + analog + + + 122 2 + total + flux analog - 120 5 + 122 2 5 total nu-fission analog - 120 52 + 122 2 5 total - prompt-nu-fission + scatter analog - 120 5 - total - prompt-nu-fission - analog - - - 120 2 + 122 2 total flux tracklength - - 120 2 + + 122 2 total - inverse-velocity + scatter tracklength + + 122 2 5 30 + total + scatter + analog + - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - prompt-nu-fission + scatter tracklength - 120 2 - total - flux - analog - - - 120 2 5 - total - prompt-nu-fission - analog - - - 120 2 - total - flux - tracklength - - - 120 2 - total - total - tracklength - - - 120 2 - total - flux - analog - - - 120 5 6 + 122 2 5 30 total scatter analog + + 122 2 5 + total + nu-scatter + analog + + + 122 54 + total + nu-fission + analog + + + 122 5 + total + nu-fission + analog + + + 122 54 + total + prompt-nu-fission + analog + + + 122 5 + total + prompt-nu-fission + analog + - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - total + inverse-velocity tracklength - 120 2 + 122 2 total flux - analog + tracklength - 120 5 6 + 122 2 total - nu-scatter - analog + prompt-nu-fission + tracklength - 120 2 + 122 2 total flux - tracklength + analog - 120 2 + 122 2 5 total - (n,elastic) - tracklength + prompt-nu-fission + analog - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - (n,level) + total tracklength - 120 2 + 122 2 total flux - tracklength + analog - 120 2 + 122 5 6 total - (n,2n) - tracklength + scatter + analog - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - (n,na) + total tracklength - 120 2 + 122 2 total flux - tracklength + analog - 120 2 + 122 5 6 total - (n,nc) - tracklength + nu-scatter + analog - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - (n,gamma) + (n,elastic) tracklength - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - (n,a) + (n,level) tracklength - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - (n,Xa) + (n,2n) tracklength - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - heating + (n,na) tracklength - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - damage-energy + (n,nc) tracklength - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - (n,n1) + (n,gamma) tracklength - 120 2 + 122 2 total flux tracklength - 120 2 + 122 2 total - (n,a0) + (n,a) tracklength - 120 2 + 122 2 total flux - analog + tracklength - 120 2 5 + 122 2 total - (n,nc) - analog + (n,Xa) + tracklength - 120 2 + 122 2 total flux - analog + tracklength - 120 2 5 + 122 2 total - (n,n1) - analog + heating + tracklength - 120 2 + 122 2 total flux - analog + tracklength - 120 2 5 + 122 2 total - (n,2n) - analog + damage-energy + tracklength - 120 2 + 122 2 total flux tracklength - 120 106 2 + 122 2 total - delayed-nu-fission + (n,n1) tracklength - 120 106 52 + 122 2 total - delayed-nu-fission - analog + flux + tracklength - 120 106 5 + 122 2 total - delayed-nu-fission - analog + (n,a0) + tracklength - 120 2 + 122 2 total - nu-fission - tracklength + flux + analog - 120 106 2 + 122 2 5 total - delayed-nu-fission - tracklength + (n,nc) + analog - 120 106 + 122 2 total - delayed-nu-fission - tracklength + flux + analog - 120 106 + 122 2 5 total - decay-rate - tracklength + (n,n1) + analog - 120 2 + 122 2 total flux analog - 120 106 2 5 + 122 2 5 total - delayed-nu-fission + (n,2n) analog - 239 2 + 122 2 total flux tracklength - 239 2 + 122 108 2 total - total + delayed-nu-fission tracklength - 239 2 + 122 108 54 total - flux - tracklength + delayed-nu-fission + analog - 239 2 + 122 108 5 total - total - tracklength + delayed-nu-fission + analog - 239 2 + 122 2 total - flux - analog + nu-fission + tracklength - 239 5 6 + 122 108 2 total - scatter - analog + delayed-nu-fission + tracklength - 239 2 + 122 108 total - flux + delayed-nu-fission tracklength - 239 2 + 122 108 total - total + decay-rate tracklength - 239 2 + 122 2 total flux analog - 239 5 6 + 122 108 2 5 total - nu-scatter + delayed-nu-fission analog - 239 2 + 243 2 total flux tracklength - 239 2 + 243 2 total - absorption + total tracklength - 239 2 + 243 2 total flux tracklength - 239 2 + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + nu-scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 total absorption tracklength - - 239 2 - total - fission - tracklength - - - 239 2 - total - flux - tracklength - - - 239 2 - total - fission - tracklength - - - 239 2 - total - flux - tracklength - - - 239 2 - total - nu-fission - tracklength - - - 239 2 - total - flux - tracklength - - - 239 2 - total - kappa-fission - tracklength - - - 239 2 - total - flux - tracklength - - 239 2 + 243 2 total - scatter + flux tracklength - 239 2 + 243 2 total - flux - analog + absorption + tracklength - 239 2 + 243 2 total - nu-scatter - analog + (n,2n) + tracklength - 239 2 + 243 2 total - flux - analog + (n,3n) + tracklength - 239 2 5 28 + 243 2 total - scatter - analog + (n,4n) + tracklength - 239 2 + 243 2 total flux - analog + tracklength - 239 2 5 28 + 243 2 total - nu-scatter - analog + absorption + tracklength - 239 2 5 + 243 2 total - nu-scatter - analog + fission + tracklength - 239 2 5 - total - scatter - analog - - - 239 2 + 243 2 total flux - analog + tracklength + + + 243 2 + total + fission + tracklength - 239 2 5 + 243 2 total - nu-fission - analog + flux + tracklength - 239 2 5 + 243 2 total - scatter - analog + nu-fission + tracklength - 239 2 + 243 2 total flux tracklength - 239 2 + 243 2 total - scatter + kappa-fission tracklength - 239 2 5 28 - total - scatter - analog - - - 239 2 + 243 2 total flux tracklength - - 239 2 + + 243 2 total scatter tracklength - - 239 2 5 28 + + 243 2 total - scatter + flux analog - - 239 2 5 + + 243 2 total nu-scatter analog - - 239 52 + + 243 2 total - nu-fission + flux + analog + + + 243 2 5 30 + total + scatter analog - 239 5 + 243 2 + total + flux + analog + + + 243 2 5 30 + total + nu-scatter + analog + + + 243 2 5 + total + nu-scatter + analog + + + 243 2 5 + total + scatter + analog + + + 243 2 + total + flux + analog + + + 243 2 5 total nu-fission analog - - 239 52 - total - prompt-nu-fission - analog - - - 239 5 - total - prompt-nu-fission - analog - - - 239 2 - total - flux - tracklength - - - 239 2 - total - inverse-velocity - tracklength - - - 239 2 - total - flux - tracklength - - 239 2 + 243 2 5 total - prompt-nu-fission - tracklength + scatter + analog - 239 2 - total - flux - analog - - - 239 2 5 - total - prompt-nu-fission - analog - - - 239 2 + 243 2 total flux tracklength - - 239 2 + + 243 2 total - total + scatter + tracklength + + + 243 2 5 30 + total + scatter + analog + + + 243 2 + total + flux tracklength - 239 2 + 243 2 total - flux - analog + scatter + tracklength - 239 5 6 + 243 2 5 30 total scatter analog - 239 2 - total - flux - tracklength - - - 239 2 - total - total - tracklength - - - 239 2 - total - flux - analog - - - 239 5 6 + 243 2 5 total nu-scatter analog + + 243 54 + total + nu-fission + analog + + + 243 5 + total + nu-fission + analog + + + 243 54 + total + prompt-nu-fission + analog + - 239 2 + 243 5 + total + prompt-nu-fission + analog + + + 243 2 total flux tracklength - - 239 2 + + 243 2 + total + inverse-velocity + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + prompt-nu-fission + tracklength + + + 243 2 + total + flux + analog + + + 243 2 5 + total + prompt-nu-fission + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + nu-scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 total (n,elastic) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,level) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,2n) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,na) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,nc) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,gamma) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,a) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,Xa) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total heating tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total damage-energy tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,n1) tracklength - - 239 2 + + 243 2 total flux tracklength - - 239 2 + + 243 2 total (n,a0) tracklength - - 239 2 + + 243 2 total flux analog - - 239 2 5 + + 243 2 5 total (n,nc) analog - - 239 2 + + 243 2 total flux analog - - 239 2 5 + + 243 2 5 total (n,n1) analog - - 239 2 + + 243 2 total flux analog - - 239 2 5 + + 243 2 5 total (n,2n) analog - - 239 2 + + 243 2 total flux tracklength - - 239 106 2 + + 243 108 2 total delayed-nu-fission tracklength - - 239 106 52 + + 243 108 54 total delayed-nu-fission analog - - 239 106 5 + + 243 108 5 total delayed-nu-fission analog - - 239 2 + + 243 2 total nu-fission tracklength - - 239 106 2 + + 243 108 2 total delayed-nu-fission tracklength - - 239 106 + + 243 108 total delayed-nu-fission tracklength - - 239 106 + + 243 108 total decay-rate tracklength - - 239 2 + + 243 2 total flux analog - - 239 106 2 5 + + 243 108 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat index 32ae7f4cf..dfbd183d4 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat @@ -14,6 +14,10 @@ absorption material group in nuclide mean std. dev. 1 1 1 total 0.027335 0.002038 0 1 2 total 0.263007 0.029616 +reduced absorption + material group in nuclide mean std. dev. +1 1 1 total 0.027278 0.002038 +0 1 2 total 0.263007 0.029616 capture material group in nuclide mean std. dev. 1 1 1 total 0.019722 0.001980 @@ -316,6 +320,10 @@ absorption material group in nuclide mean std. dev. 1 2 1 total 0.001395 0.000129 0 2 2 total 0.005202 0.000498 +reduced absorption + material group in nuclide mean std. dev. +1 2 1 total 0.001390 0.000129 +0 2 2 total 0.005202 0.000498 capture material group in nuclide mean std. dev. 1 2 1 total 0.001395 0.000129 @@ -618,6 +626,10 @@ absorption material group in nuclide mean std. dev. 1 3 1 total 0.000715 0.000032 0 3 2 total 0.031290 0.001882 +reduced absorption + material group in nuclide mean std. dev. +1 3 1 total 0.000715 0.000032 +0 3 2 total 0.031290 0.001882 capture material group in nuclide mean std. dev. 1 3 1 total 0.000715 0.000032 diff --git a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat index f29a41f3d..e45fe389e 100644 --- a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat @@ -62,16 +62,16 @@ 1 - + 3 - + 0.0 20000000.0 - + 2 - + 3 @@ -161,19 +161,19 @@ 1 2 U234 U235 U238 O16 - fission + (n,2n) tracklength 1 2 - total - flux + U234 U235 U238 O16 + (n,3n) tracklength 1 2 U234 U235 U238 O16 - fission + (n,4n) tracklength @@ -185,1493 +185,1583 @@ 1 2 U234 U235 U238 O16 - nu-fission + absorption tracklength + 1 2 + U234 U235 U238 O16 + fission + tracklength + + 1 2 total flux tracklength - + + 1 2 + U234 U235 U238 O16 + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + 1 2 U234 U235 U238 O16 kappa-fission tracklength - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 - total - flux - analog - - 1 2 5 28 - U234 U235 U238 O16 - scatter - analog + 1 2 + total + flux + tracklength + 1 2 + U234 U235 U238 O16 + scatter + tracklength + + 1 2 total flux analog - - 1 2 5 28 - U234 U235 U238 O16 - nu-scatter - analog - - 1 2 5 + 1 2 U234 U235 U238 O16 nu-scatter analog - 1 2 5 - U234 U235 U238 O16 - scatter + 1 2 + total + flux analog - 1 2 - total - flux + 1 2 5 30 + U234 U235 U238 O16 + scatter analog - 1 2 5 - U234 U235 U238 O16 - nu-fission + 1 2 + total + flux analog - 1 2 5 + 1 2 5 30 U234 U235 U238 O16 - scatter + nu-scatter analog - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 5 28 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 5 28 - U234 U235 U238 O16 - scatter - analog - - 1 2 5 U234 U235 U238 O16 nu-scatter analog - - 1 52 + + 1 2 5 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 U234 U235 U238 O16 nu-fission analog - - 1 5 + + 1 2 5 U234 U235 U238 O16 - nu-fission + scatter analog - - 1 52 - U234 U235 U238 O16 - prompt-nu-fission - analog - - - 1 5 - U234 U235 U238 O16 - prompt-nu-fission - analog - - + 1 2 total flux tracklength + + 1 2 + U234 U235 U238 O16 + scatter + tracklength + + + 1 2 5 30 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + scatter + tracklength + + + 1 2 5 30 + U234 U235 U238 O16 + scatter + analog + + + 1 2 5 + U234 U235 U238 O16 + nu-scatter + analog + + 1 54 + U234 U235 U238 O16 + nu-fission + analog + + + 1 5 + U234 U235 U238 O16 + nu-fission + analog + + + 1 54 + U234 U235 U238 O16 + prompt-nu-fission + analog + + + 1 5 + U234 U235 U238 O16 + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + 1 2 U234 U235 U238 O16 inverse-velocity tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 prompt-nu-fission tracklength - + 1 2 total flux analog - + 1 2 5 U234 U235 U238 O16 prompt-nu-fission analog - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 total tracklength - + 1 2 total flux analog - + 1 5 6 U234 U235 U238 O16 scatter analog - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 total tracklength - + 1 2 total flux analog - + 1 5 6 U234 U235 U238 O16 nu-scatter analog - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,elastic) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,level) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,2n) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,na) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,nc) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,gamma) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,a) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,Xa) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 heating tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 damage-energy tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,n1) tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 (n,a0) tracklength - + 1 2 total flux analog - + 1 2 5 U234 U235 U238 O16 (n,nc) analog - + 1 2 total flux analog - + 1 2 5 U234 U235 U238 O16 (n,n1) analog - + 1 2 total flux analog - + 1 2 5 U234 U235 U238 O16 (n,2n) analog - - 104 2 + + 106 2 total flux tracklength - - 104 2 + + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 total tracklength - - 104 2 + + 106 2 total flux tracklength - - 104 2 + + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 total tracklength - - 104 2 + + 106 2 total flux analog - - 104 5 6 + + 106 5 6 Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog - - 104 2 + + 106 2 total flux tracklength - - 104 2 + + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 total tracklength - - 104 2 + + 106 2 total flux analog - - 104 5 6 + + 106 5 6 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - - 104 2 - total - flux - tracklength - - - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 104 2 - total - flux - tracklength - - - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - fission - tracklength - - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - fission + absorption tracklength - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission + absorption tracklength - 104 2 + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,2n) + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,3n) + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,4n) + tracklength + + + 106 2 total flux tracklength - - 104 2 + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + absorption + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 kappa-fission tracklength - - 104 2 - total - flux - tracklength - - - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 104 2 - total - flux - analog - - - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 104 2 - total - flux - analog - - - 104 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 104 2 - total - flux - analog - - - 104 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 104 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 104 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - 104 2 + 106 2 total flux - analog + tracklength - 104 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 104 2 5 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 scatter + tracklength + + + 106 2 + total + flux analog - 104 2 - total - flux - tracklength + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength + 106 2 + total + flux + analog - 104 2 5 28 + 106 2 5 30 Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog - 104 2 + 106 2 total flux - tracklength - - - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 104 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter analog - - 104 2 5 + + 106 2 5 30 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - - 104 52 + + 106 2 5 Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission + nu-scatter + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 + total + flux analog - 104 5 + 106 2 5 Zr90 Zr91 Zr92 Zr94 Zr96 nu-fission analog - 104 52 + 106 2 5 Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission + scatter analog - 104 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 104 2 + 106 2 total flux tracklength - - 104 2 + + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - inverse-velocity + scatter tracklength + + 106 2 5 30 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission + scatter tracklength - 104 2 - total - flux - analog - - - 104 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 104 2 - total - flux - tracklength - - - 104 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 104 2 - total - flux - analog - - - 104 5 6 + 106 2 5 30 Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 106 54 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog + + + 106 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog + + + 106 54 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog + + + 106 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog + - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - total + inverse-velocity tracklength - 104 2 + 106 2 total flux - analog + tracklength - 104 5 6 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog + prompt-nu-fission + tracklength - 104 2 + 106 2 total flux - tracklength + analog - 104 2 + 106 2 5 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,elastic) - tracklength + prompt-nu-fission + analog - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,level) + total tracklength - 104 2 + 106 2 total flux - tracklength + analog - 104 2 + 106 5 6 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,2n) - tracklength + scatter + analog - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,na) + total tracklength - 104 2 + 106 2 total flux - tracklength + analog - 104 2 + 106 5 6 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,nc) - tracklength + nu-scatter + analog - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,gamma) + (n,elastic) tracklength - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,a) + (n,level) tracklength - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,Xa) + (n,2n) tracklength - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - heating + (n,na) tracklength - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - damage-energy + (n,nc) tracklength - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,n1) + (n,gamma) tracklength - 104 2 + 106 2 total flux tracklength - 104 2 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,a0) + (n,a) tracklength - 104 2 + 106 2 total flux - analog + tracklength - 104 2 5 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,nc) - analog + (n,Xa) + tracklength - 104 2 + 106 2 total flux - analog + tracklength - 104 2 5 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,n1) - analog + heating + tracklength - 104 2 + 106 2 total flux - analog + tracklength - 104 2 5 + 106 2 Zr90 Zr91 Zr92 Zr94 Zr96 - (n,2n) - analog + damage-energy + tracklength - 207 2 + 106 2 total flux tracklength - 207 2 - H1 O16 B10 B11 - total + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,n1) tracklength - 207 2 + 106 2 total flux tracklength - 207 2 - H1 O16 B10 B11 - total + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,a0) tracklength - 207 2 + 106 2 total flux analog - 207 5 6 - H1 O16 B10 B11 - scatter + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,nc) analog - 207 2 + 106 2 total flux - tracklength + analog - 207 2 - H1 O16 B10 B11 - total - tracklength + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,n1) + analog - 207 2 + 106 2 total flux analog - 207 5 6 - H1 O16 B10 B11 - nu-scatter + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,2n) analog - 207 2 + 211 2 total flux tracklength - 207 2 + 211 2 H1 O16 B10 B11 - absorption + total tracklength - 207 2 + 211 2 total flux tracklength - 207 2 + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 H1 O16 B10 B11 absorption tracklength - - 207 2 - H1 O16 B10 B11 - fission - tracklength - - - 207 2 - total - flux - tracklength - - - 207 2 - H1 O16 B10 B11 - fission - tracklength - - - 207 2 - total - flux - tracklength - - - 207 2 - H1 O16 B10 B11 - nu-fission - tracklength - - - 207 2 - total - flux - tracklength - - - 207 2 - H1 O16 B10 B11 - kappa-fission - tracklength - - - 207 2 - total - flux - tracklength - - 207 2 - H1 O16 B10 B11 - scatter + 211 2 + total + flux tracklength - 207 2 - total - flux - analog + 211 2 + H1 O16 B10 B11 + absorption + tracklength - 207 2 + 211 2 H1 O16 B10 B11 - nu-scatter - analog + (n,2n) + tracklength - 207 2 - total - flux - analog + 211 2 + H1 O16 B10 B11 + (n,3n) + tracklength - 207 2 5 28 + 211 2 H1 O16 B10 B11 - scatter - analog + (n,4n) + tracklength - 207 2 + 211 2 total flux - analog + tracklength - 207 2 5 28 + 211 2 H1 O16 B10 B11 - nu-scatter - analog + absorption + tracklength - 207 2 5 + 211 2 H1 O16 B10 B11 - nu-scatter - analog + fission + tracklength - 207 2 5 - H1 O16 B10 B11 - scatter - analog - - - 207 2 + 211 2 total flux - analog + tracklength + + + 211 2 + H1 O16 B10 B11 + fission + tracklength - 207 2 5 - H1 O16 B10 B11 - nu-fission - analog + 211 2 + total + flux + tracklength - 207 2 5 + 211 2 H1 O16 B10 B11 - scatter - analog + nu-fission + tracklength - 207 2 + 211 2 total flux tracklength - 207 2 + 211 2 H1 O16 B10 B11 - scatter + kappa-fission tracklength - 207 2 5 28 - H1 O16 B10 B11 - scatter - analog - - - 207 2 + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 scatter tracklength - - 207 2 5 28 - H1 O16 B10 B11 - scatter + + 211 2 + total + flux analog - - 207 2 5 + + 211 2 H1 O16 B10 B11 nu-scatter analog + + 211 2 + total + flux + analog + - 207 52 + 211 2 5 30 H1 O16 B10 B11 - nu-fission + scatter analog - 207 5 + 211 2 + total + flux + analog + + + 211 2 5 30 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 5 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 5 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + analog + + + 211 2 5 H1 O16 B10 B11 nu-fission analog - - 207 52 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 207 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 207 2 - total - flux - tracklength - - - 207 2 - H1 O16 B10 B11 - inverse-velocity - tracklength - - - 207 2 - total - flux - tracklength - - 207 2 + 211 2 5 H1 O16 B10 B11 - prompt-nu-fission - tracklength + scatter + analog - 207 2 - total - flux - analog - - - 207 2 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 207 2 + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 - total + scatter + tracklength + + + 211 2 5 30 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux tracklength - 207 2 - total - flux - analog + 211 2 + H1 O16 B10 B11 + scatter + tracklength - 207 5 6 + 211 2 5 30 H1 O16 B10 B11 scatter analog - 207 2 - total - flux - tracklength - - - 207 2 - H1 O16 B10 B11 - total - tracklength - - - 207 2 - total - flux - analog - - - 207 5 6 + 211 2 5 H1 O16 B10 B11 nu-scatter analog + + 211 54 + H1 O16 B10 B11 + nu-fission + analog + + + 211 5 + H1 O16 B10 B11 + nu-fission + analog + + + 211 54 + H1 O16 B10 B11 + prompt-nu-fission + analog + - 207 2 + 211 5 + H1 O16 B10 B11 + prompt-nu-fission + analog + + + 211 2 total flux tracklength - - 207 2 + + 211 2 + H1 O16 B10 B11 + inverse-velocity + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + prompt-nu-fission + tracklength + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 O16 B10 B11 + prompt-nu-fission + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 H1 O16 B10 B11 (n,elastic) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,level) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,2n) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,na) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,nc) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,gamma) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,a) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,Xa) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 heating tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 damage-energy tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,n1) tracklength - - 207 2 + + 211 2 total flux tracklength - - 207 2 + + 211 2 H1 O16 B10 B11 (n,a0) tracklength - - 207 2 + + 211 2 total flux analog - - 207 2 5 + + 211 2 5 H1 O16 B10 B11 (n,nc) analog - - 207 2 + + 211 2 total flux analog - - 207 2 5 + + 211 2 5 H1 O16 B10 B11 (n,n1) analog - - 207 2 + + 211 2 total flux analog - - 207 2 5 + + 211 2 5 H1 O16 B10 B11 (n,2n) analog diff --git a/tests/regression_tests/mgxs_library_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_nuclides/results_true.dat index c0084547b..7825aba3f 100644 --- a/tests/regression_tests/mgxs_library_nuclides/results_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/results_true.dat @@ -1 +1 @@ -d36f8abb1131212063470d622dbedeae31602da71006389421bd5dba712c94fe96acbc8ded833cb237687fb1071c1a6c3e0ec67b18ce7cf0f7720451b86d993a \ No newline at end of file +93ad567f1b36461a68d4ead0ff5cfa4a2003b05cf5241a232544545001a94a33fc7b99f21af277ea3a24861d38aac3a9ac36c8b1706c4b3b33caec589df2c90c \ No newline at end of file From 65624df58da7a2cf63cc4dcc6299ef0add974e15 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 3 Aug 2022 12:30:02 -0500 Subject: [PATCH 0738/2654] add chain_file, dilute_initial parameters to MicroXS.from_model --- docs/source/usersguide/depletion.rst | 6 +- openmc/deplete/microxs.py | 84 +++++++++++++++--- tests/micro_xs_simple.csv | 18 ++-- .../test_reference_fission_q.h5 | Bin 35688 -> 36312 bytes .../test_reference_source_rate.h5 | Bin 35688 -> 36312 bytes tests/regression_tests/microxs/test.py | 8 +- .../microxs/test_reference.csv | 20 +++-- 7 files changed, 107 insertions(+), 29 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 29bbcd1ed..821ff338b 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -216,7 +216,7 @@ and a path to a depletion chain file:: materials = openmc.Materials() ... - micro_xs = openmc.deplete.MicroXS() + micro_xs = openmc.deplete.MicroXS ... op = openmc.deplete.IndependentOperator(materials, micro_xs, chain_file) @@ -267,7 +267,9 @@ Users can generate the one-group microscopic cross sections needed by model = openmc.Model.from_xml() - micro_xs = openmc.deplete.MicroXS.from_model(model, model.materials[0]) + micro_xs = openmc.deplete.MicroXS.from_model(model, + model.materials[0], + chain_file) The :meth:`~openmc.deplete.MicroXS.from_model()` method will produce a :class:`~openmc.deplete.MicroXS` object with microscopic cross section data in diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 89ad5e03c..09de090bf 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -8,13 +8,16 @@ import tempfile from pathlib import Path from pandas import DataFrame, read_csv, concat -from numpy import ndarray +import numpy as np from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS -from openmc import Tallies, StatePoint +from openmc.data import DataLibrary +from openmc import Tallies, StatePoint, Materials -from .chain import REACTIONS + +from .chain import Chain, REACTIONS +from .coupled_operator import _find_cross_sections _valid_rxns = list(REACTIONS) _valid_rxns.append('fission') @@ -29,13 +32,8 @@ class MicroXS(DataFrame): def from_model(cls, model, reaction_domain, - reactions=['(n,gamma)', - '(n,2n)', - '(n,p)', - '(n,a)', - '(n,3n)', - '(n,4n)', - 'fission'], + chain_file, + dilute_initial=1.0e3, energy_bounds=(0, 20e6)): """Generate a one-group cross-section dataframe using OpenMC. Note that the ``openmc`` executable must be compiled. @@ -46,6 +44,14 @@ class MicroXS(DataFrame): OpenMC model object. Must contain geometry, materials, and settings. reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh Domain in which to tally reaction rates. + chain_file : str + Path to the depletion chain XML file that will be used in depletion + simulation. Used to determine cross sections for materials not + present in the inital composition. + dilute_initial : float + Initial atom density [atoms/cm^3] to add for nuclides that + are zero in initial condition to ensure they exist in the cross + section data. Only done for nuclides with reaction rates. reactions : list of str, optional Reaction names to tally energy_bound : 2-tuple of float, optional @@ -63,6 +69,12 @@ class MicroXS(DataFrame): original_tallies = model.tallies tallies = Tallies() xs = {} + reactions, diluted_materials = cls._add_dilute_nuclides(chain_file, + model, + dilute_initial) + diluted_materials.export_to_xml('diluted_materials.xml') + model.materials = diluted_materials + for rxn in reactions: if rxn == 'fission': xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) @@ -94,6 +106,56 @@ class MicroXS(DataFrame): return micro_xs + @classmethod + def _add_dilute_nuclides(cls, chain_file, model, dilute_initial): + chain = Chain.from_xml(chain_file) + reactions = chain.reactions + cross_sections = _find_cross_sections(model) + nuclides_with_data = cls._get_nuclides_with_data(cross_sections) + burnable_nucs = [nuc.name for nuc in chain.nuclides + if nuc.name in nuclides_with_data] + diluted_materials = Materials() + for material in model.materials: + if material.depletable: + nuc_densities = material.get_nuclide_atom_densities() + dilute_density = 1.E-24 * dilute_initial + material.set_density('sum') + for nuc, density in nuc_densities.items(): + material.remove_nuclide(nuc) + material.add_nuclide(nuc, density) + for burn_nuc in burnable_nucs: + if burn_nuc not in nuc_densities: + material.add_nuclide(burn_nuc, + dilute_density) + diluted_materials.append(material) + return reactions, diluted_materials + + @staticmethod + def _get_nuclides_with_data(cross_sections): + """Loads cross_sections.xml file to find nuclides with neutron data + + Parameters + ---------- + cross_sections : str + Path to cross_sections.xml file + + Returns + ------- + nuclides : set of str + Set of nuclide names that have cross secton data + + """ + nuclides = set() + data_lib = DataLibrary.from_xml(cross_sections) + for library in data_lib.libraries: + if library['type'] != 'neutron': + continue + for name in library['materials']: + if name not in nuclides: + nuclides.add(name) + + return nuclides + @classmethod def from_array(cls, nuclides, reactions, data): """ @@ -162,6 +224,6 @@ class MicroXS(DataFrame): def _validate_micro_xs_inputs(nuclides, reactions, data): check_iterable_type('nuclides', nuclides, str) check_iterable_type('reactions', reactions, str) - check_type('data', data, ndarray, expected_iter_type=float) + check_type('data', data, np.ndarray, expected_iter_type=float) for reaction in reactions: check_value('reactions', reaction, _valid_rxns) diff --git a/tests/micro_xs_simple.csv b/tests/micro_xs_simple.csv index bc43600ba..787ce74c3 100644 --- a/tests/micro_xs_simple.csv +++ b/tests/micro_xs_simple.csv @@ -1,7 +1,13 @@ nuclide,"(n,gamma)",fission -U234,23.518634203050645,0.49531930067650976 -U235,10.621118186344665,49.10955932965905 -U238,0.8652742788116043,0.10579281644765708 -U236,9.095623870006154,0.32315392339237936 -O16,0.0029535689693132015,0.0 -O17,0.05980775766572907,0.0 +U234,22.231989822002465,0.49620744663749855 +U235,10.479008971197121,48.41787337164604 +U238,0.8673334105437324,0.10467880588762352 +U236,8.65171044607122,0.31948392400019293 +O16,7.497851000107524e-05,0.0 +O17,0.0004079227797153371,0.0 +I135,6.842395323713927,0.0 +Xe135,227463.86426990604,0.0 +Xe136,0.02317896034753588,0.0 +Cs135,2.1721665580713623,0.0 +Gd157,12786.09939237018,0.0 +Gd156,3.4006085445846983,0.0 diff --git a/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 b/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 index 6c1b3de849e1a8792b9ce9398c7e2e41ae410b5e..82bf11567363a56b84f87a204df7ea79d6f7e124 100644 GIT binary patch delta 1568 zcmY+EVN6?96vz860`E2(Ey0yX4du<%wGIXaYoXLa%OkFCuoaDFCMp%TRf&t$;DR_E zq953xjP@khxEK*-VGs@E4XukIG=!y@2`L7(!Kg5^SjkMfFQfayY~Q_Y*Cx&F`Jdl8 z_kZ5Ix3Mu4y@W>fDC+ec7(uK6KU&|MiwrOjFH+(`8ToLqY3~&Iyg(jG*nJ@lcG5&R znW*p=9!Cj_FEl2`3zhkJqlP3MbD?dXER}(y1 zp2kz-qW*H|GrMud5M0~$G}v~@L9T6r2yej7y*Ye>PxY4vHAIc_Qo$haUcU+$i;$ew$hEq|!hZ8B0y3xvXgd&=Vu;rv}qp)-ZKK z`z6SD7Fin1S|x;of}Se!Bh3Y99IW<*J_G}gaYm3H$)b*xPQap$14A;ctS9xHSj%oR z;H={iZxp-h#t;gc;70KYIQ68uuGdJYfQiy%k%j48>D}WrRwnP%UEuRrdA1U+nag+uxon9x4EM`moGss;uiZ=T~3ozc| zK;a?SYB8b6F!XioPx%m?!t8El)EBD9%3*>huUJPt;=CDTsw1Mn<20*;J1sgi6GKN>RisHV*7(eIZxP2X5w< zr8m~hC+^?wx+HX3R~9aJ9cx-L`=|en{kdjrQm}i6{(1kr`TBDwReXLNE?zizuBT_d z`Q6fX)e{X>0$ct2*TI-km_Xat-M8WUz(jOM%D%4`P~V-G zztOD`%&*O~xBWHMX=>ZJ6i5Zx~VS5pn^ydEcM22uIF2!uMFvO2rc*L_xNh zEQ%Yts2y&R(r=zT4~L?yveC1E5PMkZ{$wR(~O*Vcg6s)J+RugZOaN(QCgfHU3OD0d0Y9F>^}40uhz z3ta90ulEpbfCou1VUb!kNTX9yR)lacgt#~?1&^RRaj>5_^yM?DCmENN_F^$kU>7`i z!Hd|0;%#Eo^7AKttip5Dr-hG#R>UXdlc)FY!^y`~6AC5d_-LgDr>M#*tO-XFv;?@I zHprV7a~Q8a1{jc-kndk^Vx7mN3jW;}@A_6ImUd=;==b;aJ$j%CuKDD%j`82_c{(G! zWAfX&X`OU0>{N zX85-El>g?nOVukAYrdz)+jf{=Je{x2t$jT*GVS}-vUBf>bIY%^1)t35;MNsxPri=- E0CJB zS-`}>=(6t7r4c@q7?x!i!?+V=nCN^nK z|IhP#p7Ve1J*S09ls}5bohYA3ZW=?Z0H1fiHk&)Zz)GD7kLbvUgN4vek=Lj6s2EC0 zHXNY|SxGca)J9R!my{;Om0HuC_^OK}!?V&&X2QrKw+jqLo8hX57PZ6W1{;n(L}VNm zY8^0aWSNXu&jt|4^{Ia6YLaAVNrdXSnFKf*Pd8R`GS!7OB+gTgTU*Tqsg7Bb(iFrS zV!+yiAU9ZGnK$DC-Gvxp#vx?hgUc3R*8HT37tI8ZSxEDYD76Ika|w^ zus0cqv~h@U7yH{L5z2VsoBEev_hw7mU^}5wUP_ZiC)2sK-B+kKDR=4*;PtGbQVHk0 z@8S_3sf?=^2DyFed#IGba_65Y(hG}SCt9*3@+d6#cv0>M?CslF@*zfqQ+F}rNvQ*yju2eAVtpNmOO%o6zMK)KY1RbSdmLyw zA+ z{yQjM*zS)$JsSDsd%geX9WR``w0WEVm!Z=i9pCbXe_-b8(}m~i{a3ykXrGf{>~QP; z^z&x}hi)wY_!C5h8*jfgd-T{YVe0&~^TwL9!UwBYUb%EIEA0GX=tFY!@8~eUPbdeJONFoT}zq2 zKKr6u)2^wp?f1Sjx1n6{aWrt{LEmp>J#&FuTtuF-*5-TmKlAVy}SMqDrHdGg(gz6`zneJ!I{A`w+rvFP;N9CXBaXj_RH!C#bL-AP$VR) z?Zzl|@Bz)5Ylxx9K3UBu|7Iv^4(x;YWI1)M3456nPs*xthVHd z$(XcXWi0d&Apu_rT`=9mu?fY@4I;>!vy;W`#90Zf46d2XE(@7!n^}on2Fx~D#UWbz0eGsvB9mvwKWjp+1c^1kY94vN( zASW2-8norvt&p?wc%hSQzN{Z0igxO;rVgTdJK>j|SD`Rq1Y5HcJGwT(d8ZD~>?G=f zQ%_WMagcL`VA{t)!DoWJz~ii&Ahd;$TMuMhM0L1fb=L?;yUE$C?AZh-x?$CPLN0J1 z>{-5)pj}npTD?mWM86=Wr?ftyVlCA{69y zkwtYwFSVoHvic4<44kp9z&_uIc1B(-?Il6H;^VX%(aWPmk7Dc1AjIv}x{rg!Z|lj^ zTT$wzFwMyOH)jk{Tk4n9zd*8KTnmIr;Z3~WPk8z=ru*UTwo|wk1oHzAQ0@R++y5zR zfT2K__BW%T8(PvYETsvSjAO7d)@5ie4e(^xx>rDzFo z&R|uF7fKi}KL%Kllu|a{cXFQlzhy7vPQMt8UtIe0$`6KMI&-u8ZhAO4cI5hxqjz2l z#&?`g9FLlVEf42A$NqqiXFZqB-}!#<@ar3W z{Pyb=(eruR+U3bUG4t6{{Db&&Vzl+*ckLZ(qJOr$ZS-D$_;_@9<@dXn!~d6FqUpzJ X`lt2u#emio+?X}PHy`p_Ds}t|vOiXw diff --git a/tests/regression_tests/microxs/test.py b/tests/regression_tests/microxs/test.py index 89fdfcaeb..dbfe3357b 100644 --- a/tests/regression_tests/microxs/test.py +++ b/tests/regression_tests/microxs/test.py @@ -1,10 +1,14 @@ """Test one-group cross section generation""" +from pathlib import Path + import numpy as np import pytest import openmc from openmc.deplete import MicroXS +CHAIN_FILE = Path(__file__).parents[2] / "chain_simple.xml" + @pytest.fixture(scope="module") def model(): fuel = openmc.Material(name="uo2") @@ -24,8 +28,6 @@ def model(): radii = [0.42, 0.45] fuel.volume = np.pi * radii[0] ** 2 - clad.volume = np.pi * (radii[1]**2 - radii[0]**2) - water.volume = 1.24**2 - (np.pi * radii[1]**2) materials = openmc.Materials([fuel, clad, water]) @@ -45,6 +47,6 @@ def model(): def test_from_model(model): ref_xs = MicroXS.from_csv('test_reference.csv') - test_xs = MicroXS.from_model(model, model.materials[0]) + test_xs = MicroXS.from_model(model, model.materials[0], CHAIN_FILE) np.testing.assert_allclose(test_xs, ref_xs, rtol=1e-11) diff --git a/tests/regression_tests/microxs/test_reference.csv b/tests/regression_tests/microxs/test_reference.csv index 0c47409b0..787ce74c3 100644 --- a/tests/regression_tests/microxs/test_reference.csv +++ b/tests/regression_tests/microxs/test_reference.csv @@ -1,7 +1,13 @@ -nuclide,"(n,gamma)","(n,2n)","(n,p)","(n,a)","(n,3n)","(n,4n)",fission -U234,23.518634203050674,0.0008255330840536984,0.0,0.0,9.404554397521455e-07,0.0,0.49531930067650964 -U235,10.621118186344795,0.004359401013759254,0.0,0.0,7.2974901306692395e-06,0.0,49.10955932965902 -U238,0.8652742788116055,0.005661917442209096,0.0,0.0,4.92273921631416e-05,0.0,0.10579281644765708 -U236,9.095623870006163,0.0024373322002926834,0.0,0.0,1.966889146690413e-05,0.0,0.3231539233923791 -O16,7.511380881289377e-05,0.0,1.3764104470470622e-05,0.002862620940027927,0.0,0.0,0.0 -O17,0.00041221042693945085,1.9826700699084533e-05,7.764409141772239e-06,0.05938517754333328,0.0,0.0,0.0 +nuclide,"(n,gamma)",fission +U234,22.231989822002465,0.49620744663749855 +U235,10.479008971197121,48.41787337164604 +U238,0.8673334105437324,0.10467880588762352 +U236,8.65171044607122,0.31948392400019293 +O16,7.497851000107524e-05,0.0 +O17,0.0004079227797153371,0.0 +I135,6.842395323713927,0.0 +Xe135,227463.86426990604,0.0 +Xe136,0.02317896034753588,0.0 +Cs135,2.1721665580713623,0.0 +Gd157,12786.09939237018,0.0 +Gd156,3.4006085445846983,0.0 From cbb0ee9964b081d8a4686fceaa265a550036d693 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:45:25 -0500 Subject: [PATCH 0739/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- openmc/deplete/microxs.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 09de090bf..75058fce0 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -72,7 +72,6 @@ class MicroXS(DataFrame): reactions, diluted_materials = cls._add_dilute_nuclides(chain_file, model, dilute_initial) - diluted_materials.export_to_xml('diluted_materials.xml') model.materials = diluted_materials for rxn in reactions: @@ -113,12 +112,12 @@ class MicroXS(DataFrame): cross_sections = _find_cross_sections(model) nuclides_with_data = cls._get_nuclides_with_data(cross_sections) burnable_nucs = [nuc.name for nuc in chain.nuclides - if nuc.name in nuclides_with_data] + if nuc.name in nuclides_with_data] diluted_materials = Materials() for material in model.materials: if material.depletable: nuc_densities = material.get_nuclide_atom_densities() - dilute_density = 1.E-24 * dilute_initial + dilute_density = 1.e-24 * dilute_initial material.set_density('sum') for nuc, density in nuc_densities.items(): material.remove_nuclide(nuc) From 98c707ea07736578a7f4080f2bbbbcab3df3b7a6 Mon Sep 17 00:00:00 2001 From: shimwell Date: Wed, 3 Aug 2022 22:46:50 +0100 Subject: [PATCH 0740/2654] refactor activities to single method --- openmc/material.py | 87 ++++++++++++++++--------------- tests/unit_tests/test_material.py | 25 ++++++--- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 57f9a6f86..05b69287d 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -91,13 +91,6 @@ class Material(IDManagerMixin): fissionable_mass : float Mass of fissionable nuclides in the material in [g]. Requires that the :attr:`volume` attribute is set. - activity : float - Activity of the material in [Bq]. Requires that the :attr:`volume` - attribute is set. - specific_activity : float - Activity of the material per unit mass in [Bq/kg]. Requires that the - :attr:`volume` and :attr:`density` attributes are set. - """ next_id = 1 @@ -153,16 +146,6 @@ class Material(IDManagerMixin): return string - @property - def activity(self): - """Returns the total activity of the material in Becquerels.""" - return sum(self.get_nuclide_activity().values()) - - @property - def specific_activity(self): - """Returns the total specific activity of the material in Becquerels per gram.""" - return sum(self.get_nuclide_specific_activity().values()) - @property def name(self): return self._name @@ -916,39 +899,57 @@ class Material(IDManagerMixin): return nuclides - def get_nuclide_activity(self): - """Return activity in [Bq] for each nuclide in the material + def get_activity(self, normalization: str = 'total', by_nuclide: bool = False): + """Returns the activity of the material or for each nuclide in the + material in units of [Bq], [Bq/g] or [Bq/cc]. .. versionadded:: 0.13.1 - Returns - ------- - dict - Dictionary whose keys are nuclide names and values are activity in - [Bq]. - """ - activity = {} - for nuclide, atoms in self.get_nuclide_atoms().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = inv_seconds * atoms - return activity - - def get_nuclide_specific_activity(self): - """Return specific activity in [Bq/g] for each nuclide in the material - - .. versionadded:: 0.13.1 + Parameters + ---------- + normalization : {'total', 'mass', 'volume'} + Specifies the type of activity to return, 'total' will return the + material activity in [Bq], 'mass' returns the materials specific + activity in [Bq/g] and 'volume' returns the activity in [Bq/cc]. + by_nuclide : bool + Specifies if the activity should be returned for the material as a + whole or per nuclide. Returns ------- - dict - Dictionary whose keys are nuclide names and values are specific - activity in [Bq/g]. + + Union[dict, float] + If by_nuclide is True then a dictionary whose keys are nuclide + names and values are activity is returned. Otherwise the activity + of the material is returned as a float. """ - activity = {} - for nuclide, atoms in self.get_nuclide_atom_densities().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density - return activity + + cv.check_value('normalization', normalization, {'total', 'mass', 'volume'}) + cv.check_type('by_nuclide', by_nuclide, bool) + + if normalization=='total': + activity = {} + for nuclide, atoms in self.get_nuclide_atoms().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = inv_seconds * atoms + + elif normalization=='mass': + activity = {} + for nuclide, atoms in self.get_nuclide_atom_densities().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density + # normalization must be volume by this stage so else can be used + else: + activity = {} + for nuclide, atoms in self.get_nuclide_atom_densities().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.volume + + if by_nuclide: + return activity + else: + return sum(activity.values()) + def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index fd9f325f2..763325ac9 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -477,7 +477,7 @@ def test_activity_of_stable(): m1.add_element("Fe", 1) m1.set_density('g/cm3', 1) m1.volume = 1 - assert m1.activity == 0 + assert m1.get_activity() == 0 def test_activity_of_tritium(): @@ -486,11 +486,11 @@ def test_activity_of_tritium(): m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) m1.volume = 1 - assert pytest.approx(m1.activity) == 3.559778e14 + assert pytest.approx(m1.get_activity()) == 3.559778e14 m1.set_density('g/cm3', 2) - assert pytest.approx(m1.activity) == 3.559778e14*2 + assert pytest.approx(m1.get_activity()) == 3.559778e14*2 m1.volume = 3 - assert pytest.approx(m1.activity) == 3.559778e14*2*3 + assert pytest.approx(m1.get_activity()) == 3.559778e14*2*3 def test_activity_of_metastable(): @@ -499,13 +499,22 @@ def test_activity_of_metastable(): m1.add_nuclide("Tc99_m1", 1) m1.set_density('g/cm3', 1) m1.volume = 98.9 - assert pytest.approx(m1.activity, rel=0.001) == 1.93e19 + assert pytest.approx(m1.get_activity(), rel=0.001) == 1.93e19 def test_specific_activity_of_tritium(): - """Checks that specific activity of tritium is correct""" + """Checks that specific and volumetric activity of tritium are correct""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) - assert m1.specific_activity == 355978108155965.9 - assert m1.get_nuclide_specific_activity() == {"H3": 355978108155965.9} \ No newline at end of file + assert m1.get_activity(normalization='mass') == 355978108155965.9 # [Bq/g] + assert m1.get_activity(normalization='mass', by_nuclide=True) == { + "H3": 355978108155965.9 # [Bq/g] + } + # volume is required to calculate total and volumetric activity + m1.volume = 10. + assert m1.get_activity(normalization='total') == 355978108155965.9*10. # [Bq] + assert m1.get_activity(normalization='volume') == 355978108155965.9/10. # [Bq/cc] + assert m1.get_activity(normalization='volume', by_nuclide=True) == { + "H3": 355978108155965.9/10. # [Bq/cc] + } From 15f66ed50af45b140cceb7d20070d8e9968a3a20 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Wed, 3 Aug 2022 17:46:26 -0500 Subject: [PATCH 0741/2654] Minor styling fix in `Material.py` change `E` to `e` for scientific notation. --- openmc/material.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 6c2641680..913d53d9d 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -861,7 +861,7 @@ class Material(IDManagerMixin): elif self.density_units == 'atom/b-cm': density = self.density elif self.density_units == 'atom/cm3' or self.density_units == 'atom/cc': - density = 1.E-24 * self.density + density = 1.e-24 * self.density # For ease of processing split out nuc, nuc_density, # and nuc_density_type into separate arrays @@ -897,7 +897,7 @@ class Material(IDManagerMixin): # Convert the mass density to an atom density if not density_in_atom: - density = -density / self.average_molar_mass * 1.E-24 \ + density = -density / self.average_molar_mass * 1.e-24 \ * openmc.data.AVOGADRO nuc_densities = density * nuc_densities From c900e4784e68b3ea833e3b60fe80d3cc345f33eb Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 07:55:35 +0100 Subject: [PATCH 0742/2654] Corrections to activity calcs Co-authored-by: Ethan Peterson --- openmc/material.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 05b69287d..48684ed67 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -927,23 +927,15 @@ class Material(IDManagerMixin): cv.check_value('normalization', normalization, {'total', 'mass', 'volume'}) cv.check_type('by_nuclide', by_nuclide, bool) - if normalization=='total': - activity = {} - for nuclide, atoms in self.get_nuclide_atoms().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = inv_seconds * atoms - - elif normalization=='mass': - activity = {} - for nuclide, atoms in self.get_nuclide_atom_densities().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density - # normalization must be volume by this stage so else can be used + if normalization == 'total': + multiplier = self.volume else: - activity = {} - for nuclide, atoms in self.get_nuclide_atom_densities().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.volume + multiplier = 1 if normalization == 'volume' else 1.0 / self.get_mass_density() + + activity = {} + for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = inv_seconds * 1e24 * atoms_per_bcm * multiplier if by_nuclide: return activity From e4d54d49a8f92aa5b90bfd2b814b6bcc751c3541 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 09:39:14 +0100 Subject: [PATCH 0743/2654] moved volume lower --- tests/unit_tests/test_material.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 763325ac9..24887d8a6 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -507,14 +507,14 @@ def test_specific_activity_of_tritium(): m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) - assert m1.get_activity(normalization='mass') == 355978108155965.9 # [Bq/g] + assert m1.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] assert m1.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155965.9 # [Bq/g] + "H3": 355978108155966.0 # [Bq/g] } - # volume is required to calculate total and volumetric activity - m1.volume = 10. - assert m1.get_activity(normalization='total') == 355978108155965.9*10. # [Bq] - assert m1.get_activity(normalization='volume') == 355978108155965.9/10. # [Bq/cc] + assert m1.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] assert m1.get_activity(normalization='volume', by_nuclide=True) == { - "H3": 355978108155965.9/10. # [Bq/cc] + "H3": 355978108155965.94 # [Bq/cc] } + # volume is required to calculate total activity + m1.volume = 10. + assert m1.get_activity(normalization='total') == 3559781081559659.5 # [Bq] From 13c83a1c005eab8e2ea38cdce46c2f798cee59d1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 4 Aug 2022 08:54:20 -0500 Subject: [PATCH 0744/2654] Bump up number of samples in test_combine_distributions --- tests/unit_tests/test_stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 1cfcf00c3..b8bb94f37 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -436,5 +436,5 @@ def test_combine_distributions(): # Sample the combined distribution and make sure the sample mean is within # uncertainty of the expected value - samples = combined.sample(10) + samples = combined.sample(1000) assert_sample_mean(samples, 0.25) From c036403c984067946542e97cbdbe488687b6b706 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 14:55:45 +0100 Subject: [PATCH 0745/2654] simpler if else statement for normalization Co-authored-by: Patrick Shriwise --- openmc/material.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 48684ed67..965c9d5c8 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -929,8 +929,10 @@ class Material(IDManagerMixin): if normalization == 'total': multiplier = self.volume - else: - multiplier = 1 if normalization == 'volume' else 1.0 / self.get_mass_density() + elif normalization == 'volume': + multiplier = 1 + elif normalization == 'mass': + multiplier = 1.0 / self.get_mass_density() activity = {} for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): From 8164f309e9d61479fd65759da46c6e8b22715eef Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 15:37:01 +0100 Subject: [PATCH 0746/2654] added pre volume attribute tests for stable nuclide --- tests/unit_tests/test_material.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 24887d8a6..ddb1bfcf2 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -471,16 +471,19 @@ def test_mix_materials(): assert m5.density == pytest.approx(dens5) -def test_activity_of_stable(): +def test_get_activity_of_stable_nuclides(): """Creates a material with stable isotopes to checks the activity is 0""" m1 = openmc.Material() m1.add_element("Fe", 1) - m1.set_density('g/cm3', 1) + m1.set_density('g/cm3', 1.5) + # activity in Bq/cc and Bq/g should not require volume setting + assert m1.get_activity(normalization='volume') == 0 + assert m1.get_activity(normalization='mass') == 0 m1.volume = 1 assert m1.get_activity() == 0 -def test_activity_of_tritium(): +def test_get_activity_of_tritium(): """Checks that 1g of tritium has the correct activity scaling""" m1 = openmc.Material() m1.add_nuclide("H3", 1) @@ -493,7 +496,7 @@ def test_activity_of_tritium(): assert pytest.approx(m1.get_activity()) == 3.559778e14*2*3 -def test_activity_of_metastable(): +def test_get_activity_of_metastable(): """Checks that 1 mol of a Tc99_m1 nuclides has the correct activity""" m1 = openmc.Material() m1.add_nuclide("Tc99_m1", 1) @@ -502,7 +505,7 @@ def test_activity_of_metastable(): assert pytest.approx(m1.get_activity(), rel=0.001) == 1.93e19 -def test_specific_activity_of_tritium(): +def test_get_activity_of_tritium_nuclides(): """Checks that specific and volumetric activity of tritium are correct""" m1 = openmc.Material() m1.add_nuclide("H3", 1) From a30f9b88fd79400c8bbc65de3902d3ddce8e838d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 15:49:11 +0100 Subject: [PATCH 0747/2654] combined activity unit tests as suggested @eepeterson --- tests/unit_tests/test_material.py | 67 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index ddb1bfcf2..432cf3a03 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -471,10 +471,13 @@ def test_mix_materials(): assert m5.density == pytest.approx(dens5) -def test_get_activity_of_stable_nuclides(): - """Creates a material with stable isotopes to checks the activity is 0""" +def test_get_activity(): + """Tests the activity of stable, metastable and active materials""" + + # Creates a material with stable isotopes to checks the activity is 0 m1 = openmc.Material() - m1.add_element("Fe", 1) + m1.add_element("Fe", 0.7) + m1.add_element("Li", 0.3) m1.set_density('g/cm3', 1.5) # activity in Bq/cc and Bq/g should not require volume setting assert m1.get_activity(normalization='volume') == 0 @@ -482,42 +485,36 @@ def test_get_activity_of_stable_nuclides(): m1.volume = 1 assert m1.get_activity() == 0 + # Checks that 1g of tritium has the correct activity scaling + m2 = openmc.Material() + m2.add_nuclide("H3", 1) + m2.set_density('g/cm3', 1) + m2.volume = 1 + assert pytest.approx(m2.get_activity()) == 3.559778e14 + m2.set_density('g/cm3', 2) + assert pytest.approx(m2.get_activity()) == 3.559778e14*2 + m2.volume = 3 + assert pytest.approx(m2.get_activity()) == 3.559778e14*2*3 -def test_get_activity_of_tritium(): - """Checks that 1g of tritium has the correct activity scaling""" - m1 = openmc.Material() - m1.add_nuclide("H3", 1) - m1.set_density('g/cm3', 1) - m1.volume = 1 - assert pytest.approx(m1.get_activity()) == 3.559778e14 - m1.set_density('g/cm3', 2) - assert pytest.approx(m1.get_activity()) == 3.559778e14*2 - m1.volume = 3 - assert pytest.approx(m1.get_activity()) == 3.559778e14*2*3 + # Checks that 1 mol of a metastable nuclides has the correct activity + m3 = openmc.Material() + m3.add_nuclide("Tc99_m1", 1) + m3.set_density('g/cm3', 1) + m3.volume = 98.9 + assert pytest.approx(m3.get_activity(), rel=0.001) == 1.93e19 - -def test_get_activity_of_metastable(): - """Checks that 1 mol of a Tc99_m1 nuclides has the correct activity""" - m1 = openmc.Material() - m1.add_nuclide("Tc99_m1", 1) - m1.set_density('g/cm3', 1) - m1.volume = 98.9 - assert pytest.approx(m1.get_activity(), rel=0.001) == 1.93e19 - - -def test_get_activity_of_tritium_nuclides(): - """Checks that specific and volumetric activity of tritium are correct""" - m1 = openmc.Material() - m1.add_nuclide("H3", 1) - m1.set_density('g/cm3', 1) - assert m1.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] - assert m1.get_activity(normalization='mass', by_nuclide=True) == { + # Checks that specific and volumetric activity of tritium are correct + m4 = openmc.Material() + m4.add_nuclide("H3", 1) + m4.set_density('g/cm3', 1) + assert m4.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] + assert m4.get_activity(normalization='mass', by_nuclide=True) == { "H3": 355978108155966.0 # [Bq/g] } - assert m1.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] - assert m1.get_activity(normalization='volume', by_nuclide=True) == { + assert m4.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] + assert m4.get_activity(normalization='volume', by_nuclide=True) == { "H3": 355978108155965.94 # [Bq/cc] } # volume is required to calculate total activity - m1.volume = 10. - assert m1.get_activity(normalization='total') == 3559781081559659.5 # [Bq] + m4.volume = 10. + assert m4.get_activity(normalization='total') == 3559781081559659.5 # [Bq] From 152a149488ddc9fae4612b828ca49f9cd27cb181 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 16:15:12 +0100 Subject: [PATCH 0748/2654] density set to 1.5 to test different activities scaling Co-authored-by: Ethan Peterson --- tests/unit_tests/test_material.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 432cf3a03..5f567304b 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -474,7 +474,7 @@ def test_mix_materials(): def test_get_activity(): """Tests the activity of stable, metastable and active materials""" - # Creates a material with stable isotopes to checks the activity is 0 + # Creates a material with stable isotopes to check the activity is 0 m1 = openmc.Material() m1.add_element("Fe", 0.7) m1.add_element("Li", 0.3) @@ -506,15 +506,15 @@ def test_get_activity(): # Checks that specific and volumetric activity of tritium are correct m4 = openmc.Material() m4.add_nuclide("H3", 1) - m4.set_density('g/cm3', 1) - assert m4.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] + m4.set_density('g/cm3', 1.5) + assert m4.get_activity(normalization='mass') == 355978108155966.0*2/3 # [Bq/g] assert m4.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155966.0 # [Bq/g] + "H3": 355978108155966.0*2/3 # [Bq/g] } - assert m4.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] + assert m4.get_activity(normalization='volume') == 355978108155965.94*3/2 # [Bq/cc] assert m4.get_activity(normalization='volume', by_nuclide=True) == { - "H3": 355978108155965.94 # [Bq/cc] + "H3": 355978108155965.94*3/2 # [Bq/cc] } # volume is required to calculate total activity m4.volume = 10. - assert m4.get_activity(normalization='total') == 3559781081559659.5 # [Bq] + assert m4.get_activity(normalization='total') == 355978108155965.94*3/2*10 # [Bq] From c3921b735fa7bc4ea4fc923467f542bf472a2427 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 3 Aug 2022 17:43:48 -0500 Subject: [PATCH 0749/2654] Changes from @paulromano's 6th round of comments - add more detail to `MicroXS` example in User's Guide - Cleanup the `from_model` method - Reduce repeated code between `MicroXS` and `CoupledOperator` --- docs/source/usersguide/depletion.rst | 4 +- openmc/deplete/coupled_operator.py | 35 ++++++++++----- openmc/deplete/microxs.py | 67 +++++++++++++++------------- 3 files changed, 62 insertions(+), 44 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 821ff338b..29c8114d9 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -216,9 +216,7 @@ and a path to a depletion chain file:: materials = openmc.Materials() ... - micro_xs = openmc.deplete.MicroXS - ... - + micro_xs = openmc.deplete.MicroXS.from_csv(micro_xs_path) op = openmc.deplete.IndependentOperator(materials, micro_xs, chain_file) .. note:: diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index d5bb5b4bd..eba90f60d 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -56,6 +56,30 @@ def _find_cross_sections(model): ) return cross_sections +def _get_nuclides_with_data(cross_sections): + """Loads cross_sections.xml file to find nuclides with neutron data + + Parameters + ---------- + cross_sections : str + Path to cross_sections.xml file + + Returns + ------- + nuclides : set of str + Set of nuclide names that have cross secton data + + """ + nuclides = set() + data_lib = DataLibrary.from_xml(cross_sections) + for library in data_lib.libraries: + if library['type'] != 'neutron': + continue + for name in library['materials']: + if name not in nuclides: + nuclides.add(name) + + return nuclides class CoupledOperator(OpenMCOperator): """Transport-coupled transport operator. @@ -310,16 +334,7 @@ class CoupledOperator(OpenMCOperator): Set of nuclide names that have cross secton data """ - nuclides = set() - data_lib = DataLibrary.from_xml(cross_sections) - for library in data_lib.libraries: - if library['type'] != 'neutron': - continue - for name in library['materials']: - if name not in nuclides: - nuclides.add(name) - - return nuclides + return _get_nuclides_with_data(cross_sections) def _get_helper_classes(self, helper_kwargs): """Create the ``_rate_helper``, ``_normalization_helper``, and diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 75058fce0..32e0518ff 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -6,6 +6,7 @@ nuclides names as row indices and reaction names as column indices. import tempfile from pathlib import Path +from copy import deepcopy from pandas import DataFrame, read_csv, concat import numpy as np @@ -13,11 +14,11 @@ import numpy as np from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS from openmc.data import DataLibrary -from openmc import Tallies, StatePoint, Materials +from openmc import Tallies, StatePoint, Materials, Material from .chain import Chain, REACTIONS -from .coupled_operator import _find_cross_sections +from .coupled_operator import _find_cross_sections, _get_nuclides_with_data _valid_rxns = list(REACTIONS) _valid_rxns.append('fission') @@ -67,6 +68,7 @@ class MicroXS(DataFrame): # Set up the reaction tallies original_tallies = model.tallies + original_materials = deepcopy(model.materials) tallies = Tallies() xs = {} reactions, diluted_materials = cls._add_dilute_nuclides(chain_file, @@ -100,17 +102,45 @@ class MicroXS(DataFrame): df.rename({'mean': rxn}, axis=1, inplace=True) micro_xs = concat([micro_xs, df], axis=1) - # Revert to the original tallies + # Revert to the original tallies and materials model.tallies = original_tallies + model.materials = original_materials return micro_xs @classmethod def _add_dilute_nuclides(cls, chain_file, model, dilute_initial): + """ + Add nuclides not present in burnable materials that have neutron data + and are present in the depletion chain to those materials. This allows + us to tally those specific nuclides for reactions to create one-group + cross sections. + + Parameters + ---------- + chain_file : str + Path to the depletion chain XML file that will be used in depletion + simulation. Used to determine cross sections for materials not + present in the inital composition. + model : openmc.Model + Model object + dilute_initial : float + Initial atom density [atoms/cm^3] to add for nuclides that + are zero in initial condition to ensure they exist in the cross + section data. Only done for nuclides with reaction rates. + + Returns + ------- + reactions : list of str + List of reaction names + diluted_materials : openmc.Materials + :class:`openmc.Materials` object with nuclides added to burnable + materials. + """ chain = Chain.from_xml(chain_file) reactions = chain.reactions cross_sections = _find_cross_sections(model) - nuclides_with_data = cls._get_nuclides_with_data(cross_sections) + nuclides_with_data = _get_nuclides_with_data(cross_sections) burnable_nucs = [nuc.name for nuc in chain.nuclides if nuc.name in nuclides_with_data] diluted_materials = Materials() @@ -125,36 +155,11 @@ class MicroXS(DataFrame): for burn_nuc in burnable_nucs: if burn_nuc not in nuc_densities: material.add_nuclide(burn_nuc, - dilute_density) + dilute_density) diluted_materials.append(material) + return reactions, diluted_materials - @staticmethod - def _get_nuclides_with_data(cross_sections): - """Loads cross_sections.xml file to find nuclides with neutron data - - Parameters - ---------- - cross_sections : str - Path to cross_sections.xml file - - Returns - ------- - nuclides : set of str - Set of nuclide names that have cross secton data - - """ - nuclides = set() - data_lib = DataLibrary.from_xml(cross_sections) - for library in data_lib.libraries: - if library['type'] != 'neutron': - continue - for name in library['materials']: - if name not in nuclides: - nuclides.add(name) - - return nuclides - @classmethod def from_array(cls, nuclides, reactions, data): """ From d5a8e29b7c526a252bf611dcba6978640554c09d Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 4 Aug 2022 12:12:52 -0500 Subject: [PATCH 0750/2654] fix IndependentOperator._load_prev_results() --- openmc/deplete/independent_operator.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index d2a9f04d0..b7956205a 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -232,7 +232,10 @@ class IndependentOperator(OpenMCOperator): def _load_previous_results(self): """Load results from a previous depletion simulation""" # Reload volumes into geometry - self.prev_res[-1].transfer_volumes(self.materials) + model = openmc.Model(materials=self.materials) + self.prev_res[-1].transfer_volumes(model) + self.materials = model.materials + # Store previous results in operator # Distribute reaction rates according to those tracked From 3ef15da62f4a24cab65c330acabcd34593270cf5 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 4 Aug 2022 12:13:07 -0500 Subject: [PATCH 0751/2654] fix MicroXS.from_model() --- openmc/deplete/microxs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 32e0518ff..29ddc7268 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -106,7 +106,7 @@ class MicroXS(DataFrame): model.tallies = original_tallies model.materials = original_materials - return micro_xs + return cls(micro_xs) @classmethod def _add_dilute_nuclides(cls, chain_file, model, dilute_initial): From fc3d94b781b26e9ad4a885b77f847d329040f856 Mon Sep 17 00:00:00 2001 From: Joffrey Dorville Date: Thu, 4 Aug 2022 11:24:46 -0600 Subject: [PATCH 0752/2654] Apply @paulromano suggestions --- openmc/data/njoy.py | 4 ++-- openmc/data/reaction.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/data/njoy.py b/openmc/data/njoy.py index 70351a772..d8ecaae18 100644 --- a/openmc/data/njoy.py +++ b/openmc/data/njoy.py @@ -127,7 +127,7 @@ acer / %%%%%%%%%%%%%%%%%%%%%%%% Write out in ACE format %%%%%%%%%%%%%%%%%%%%%%%% 1 0 1 .{ext} / '{library}: {zsymam} at {temperature}'/ {mat} {temperature} -1 1 {ismoothing}/ +1 1 {ismooth}/ / """ @@ -383,7 +383,7 @@ def make_ace(filename, temperatures=None, acer=True, xsdir=None, # acer if acer: - ismoothing = int(smoothing) + ismooth = int(smoothing) nacer_in = nlast for i, temperature in enumerate(temperatures): # Extend input with an ACER run for each temperature diff --git a/openmc/data/reaction.py b/openmc/data/reaction.py index 42fc576da..a2431cf1c 100644 --- a/openmc/data/reaction.py +++ b/openmc/data/reaction.py @@ -82,7 +82,7 @@ def _get_products(ev, mt): Raises ------ - IOError: + IOError When the Kalbach-Mann systematics is used, but the product is not defined in the 'center-of-mass' system. The breakup logic is not implemented which can lead to this error being raised while From bce3cc0da42651c01c7a63506f70b784769fff53 Mon Sep 17 00:00:00 2001 From: myerspat Date: Thu, 4 Aug 2022 15:46:10 -0400 Subject: [PATCH 0753/2654] Added rpn back for bounding box --- include/openmc/cell.h | 1 + src/cell.cpp | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index e812fc88f..4d07b2619 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -204,6 +204,7 @@ public: vector region_; //! Revised infix notation with no complements vector region_no_complements_; + vector rpn_; bool simple_; //!< Does the region contain only intersections? //! \brief Neighboring cells in the same universe. diff --git a/src/cell.cpp b/src/cell.cpp index fc19c1c49..c89e437ac 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -138,7 +138,17 @@ std::vector::iterator add_parenthesis( } else if (*start == OP_LEFT_PAREN) { return_iterator = start; - start = std::find(start, infix.end(), OP_RIGHT_PAREN); + int depth = 1; + do { + start++; + if (*start > OP_COMPLEMENT) { + if (*start == OP_RIGHT_PAREN) { + depth--; + } else { + depth++; + } + } + } while (depth > 0); } } @@ -598,6 +608,7 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } else { // Ensure intersections have precedence over unions add_precedence(region_no_complements_); + rpn_ = generate_rpn(id_, region_no_complements_); } region_no_complements_.shrink_to_fit(); @@ -776,9 +787,6 @@ void CSGCell::remove_complement_ops(vector& infix) BoundingBox CSGCell::bounding_box_complex(vector rpn) { - // remove complements by adjusting surface signs and operators - remove_complement_ops(rpn); - vector stack(rpn.size()); int i_stack = -1; @@ -802,7 +810,7 @@ BoundingBox CSGCell::bounding_box_complex(vector rpn) BoundingBox CSGCell::bounding_box() const { return simple_ ? bounding_box_simple() - : bounding_box_complex(region_no_complements_); + : bounding_box_complex(rpn_); } //============================================================================== @@ -867,7 +875,7 @@ bool CSGCell::contains_complex( if (next_token >= OP_UNION && token != next_token) { if (next_token == OP_LEFT_PAREN) { int depth = 1; - while (depth > 0) { + do { it++; if (*it > OP_COMPLEMENT) { if (*it == OP_RIGHT_PAREN) { @@ -876,7 +884,7 @@ bool CSGCell::contains_complex( depth++; } } - } + } while (depth > 0); } else { break; } From 39eaf9d88752f97ad21170c6b393358f24d4961c Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 4 Aug 2022 16:50:18 -0400 Subject: [PATCH 0754/2654] Apply suggestions from code review Co-authored-by: Jonathan Shimwell --- openmc/material.py | 2 +- tests/unit_tests/test_material.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 965c9d5c8..ed1b83977 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -899,7 +899,7 @@ class Material(IDManagerMixin): return nuclides - def get_activity(self, normalization: str = 'total', by_nuclide: bool = False): + def get_activity(self, normalization: str = 'volume', by_nuclide: bool = False): """Returns the activity of the material or for each nuclide in the material in units of [Bq], [Bq/g] or [Bq/cc]. diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 5f567304b..eadad5006 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -483,33 +483,33 @@ def test_get_activity(): assert m1.get_activity(normalization='volume') == 0 assert m1.get_activity(normalization='mass') == 0 m1.volume = 1 - assert m1.get_activity() == 0 + assert m1.get_activity(normalization='total') == 0 # Checks that 1g of tritium has the correct activity scaling m2 = openmc.Material() m2.add_nuclide("H3", 1) m2.set_density('g/cm3', 1) m2.volume = 1 - assert pytest.approx(m2.get_activity()) == 3.559778e14 + assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14 m2.set_density('g/cm3', 2) - assert pytest.approx(m2.get_activity()) == 3.559778e14*2 + assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2 m2.volume = 3 - assert pytest.approx(m2.get_activity()) == 3.559778e14*2*3 + assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2*3 # Checks that 1 mol of a metastable nuclides has the correct activity m3 = openmc.Material() m3.add_nuclide("Tc99_m1", 1) m3.set_density('g/cm3', 1) m3.volume = 98.9 - assert pytest.approx(m3.get_activity(), rel=0.001) == 1.93e19 + assert pytest.approx(m3.get_activity(normalization='total'), rel=0.001) == 1.93e19 # Checks that specific and volumetric activity of tritium are correct m4 = openmc.Material() m4.add_nuclide("H3", 1) m4.set_density('g/cm3', 1.5) - assert m4.get_activity(normalization='mass') == 355978108155966.0*2/3 # [Bq/g] + assert m4.get_activity(normalization='mass') == 355978108155965.94 # [Bq/g] assert m4.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155966.0*2/3 # [Bq/g] + "H3": 355978108155965.94 # [Bq/g] } assert m4.get_activity(normalization='volume') == 355978108155965.94*3/2 # [Bq/cc] assert m4.get_activity(normalization='volume', by_nuclide=True) == { From c75524cfa0288103ec37e1538ff30472f5a83b9d Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Thu, 4 Aug 2022 16:11:11 -0500 Subject: [PATCH 0755/2654] simplify `from_model` Co-authored-by: Paul Romano --- openmc/deplete/microxs.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 29ddc7268..c4094970f 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -94,19 +94,16 @@ class MicroXS(DataFrame): xs[rxn].load_from_statepoint(sp) # Build the DataFrame - micro_xs = cls() - for rxn in xs: - df = xs[rxn].get_pandas_dataframe(xs_type='micro') - df.index = df['nuclide'] - df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) - df.rename({'mean': rxn}, axis=1, inplace=True) - micro_xs = concat([micro_xs, df], axis=1) + series = {} + for rx in xs: + df = xs[rx].get_pandas_dataframe(xs_type='micro') + series[rx] = df.set_index('nuclide')['mean'] # Revert to the original tallies and materials model.tallies = original_tallies model.materials = original_materials - return cls(micro_xs) + return cls(series) @classmethod def _add_dilute_nuclides(cls, chain_file, model, dilute_initial): From 75d82a7df72dc1a1e40d7983d4537f412fca703f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 23:43:42 +0100 Subject: [PATCH 0756/2654] reverting to pytest.approx Co-authored-by: Ethan Peterson --- tests/unit_tests/test_material.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index eadad5006..dbc67fcc2 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -507,14 +507,11 @@ def test_get_activity(): m4 = openmc.Material() m4.add_nuclide("H3", 1) m4.set_density('g/cm3', 1.5) - assert m4.get_activity(normalization='mass') == 355978108155965.94 # [Bq/g] - assert m4.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155965.94 # [Bq/g] - } - assert m4.get_activity(normalization='volume') == 355978108155965.94*3/2 # [Bq/cc] - assert m4.get_activity(normalization='volume', by_nuclide=True) == { - "H3": 355978108155965.94*3/2 # [Bq/cc] + assert pytest.approx(m4.get_activity(normalization='mass')) == 355978108155965.94 # [Bq/g] + assert pytest.approx(m4.get_activity(normalization='mass', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g] + assert pytest.approx(m4.get_activity(normalization='volume')) == 355978108155965.94*3/2 # [Bq/cc] + assert pytest.approx(m4.get_activity(normalization='volume', by_nuclide=True)["H3"]) == 355978108155965.94*3/2 # [Bq/cc] } # volume is required to calculate total activity m4.volume = 10. - assert m4.get_activity(normalization='total') == 355978108155965.94*3/2*10 # [Bq] + assert pytest.approx(m4.get_activity(normalization='total')) == 355978108155965.94*3/2*10 # [Bq] From 496dda717ce055024993053d9a42af47a961c955 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 4 Aug 2022 23:59:51 +0100 Subject: [PATCH 0757/2654] removed missing bracket --- tests/unit_tests/test_material.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index dbc67fcc2..7e9121608 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -511,7 +511,6 @@ def test_get_activity(): assert pytest.approx(m4.get_activity(normalization='mass', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g] assert pytest.approx(m4.get_activity(normalization='volume')) == 355978108155965.94*3/2 # [Bq/cc] assert pytest.approx(m4.get_activity(normalization='volume', by_nuclide=True)["H3"]) == 355978108155965.94*3/2 # [Bq/cc] - } # volume is required to calculate total activity m4.volume = 10. assert pytest.approx(m4.get_activity(normalization='total')) == 355978108155965.94*3/2*10 # [Bq] From a3c15fb07fcf51fec6fdeaa7faa665960b53c796 Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 5 Aug 2022 17:01:09 -0400 Subject: [PATCH 0758/2654] Proper parenthesis handling for De Morgans --- src/cell.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cell.cpp b/src/cell.cpp index c89e437ac..12fb9f674 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -773,7 +773,17 @@ void CSGCell::remove_complement_ops(vector& infix) // Define stop given left parenthesis or not auto stop = it; if (*it == OP_LEFT_PAREN) { - stop = std::find(it, infix.end(), OP_RIGHT_PAREN); + int depth = 1; + do { + stop++; + if (*stop > OP_COMPLEMENT) { + if (*stop == OP_RIGHT_PAREN) { + depth--; + } else { + depth++; + } + } + } while (depth > 0); it++; } From c943128587e846d1e477ba9b37cdfa49d05d18df Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Mar 2022 13:25:55 -0500 Subject: [PATCH 0759/2654] Add pytest request path to location of cleanup files in cpp driver test --- tests/regression_tests/cpp_driver/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/cpp_driver/test.py b/tests/regression_tests/cpp_driver/test.py index 95912b3f7..e8b1c62ac 100644 --- a/tests/regression_tests/cpp_driver/test.py +++ b/tests/regression_tests/cpp_driver/test.py @@ -48,8 +48,8 @@ def cpp_driver(request): finally: # Remove local build directory when test is complete - shutil.rmtree('build') - os.remove('CMakeLists.txt') + shutil.rmtree(request.node.path.parent / 'build') + os.remove(request.node.path.parent / 'CMakeLists.txt') @pytest.fixture From d3535a521e06958f5d9f16c00c5238f60f825300 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 11 Apr 2022 12:23:23 -0500 Subject: [PATCH 0760/2654] Add Python pickle files to ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 88e59895d..3b2a24a4d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.o *.log *.out +*.pkl # Compiler python objects *.pyc From 75548aade800bcab72a865bcc2f1ca4f75fcec37 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 13:34:20 +0100 Subject: [PATCH 0761/2654] added bin_log_width to energyfilter --- openmc/filter.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmc/filter.py b/openmc/filter.py index be3d97679..7fe454865 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1324,6 +1324,13 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) + def bin_log_width(self): + """Returns the base 10 log width of energy bins which is useful when + plotting the normalized flux""" + bin_edges = np.unique(self.bins) + log_width = np.log10(bin_edges[1:]/bin_edges[:-1]) + return log_width + @classmethod def from_group_structure(cls, group_structure): """Construct an EnergyFilter instance from a standard group structure. From 98f5da737f7607cc82d7d8b51fa76ff697c0f579 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 6 Aug 2022 06:20:11 -0500 Subject: [PATCH 0762/2654] rm space --- openmc/universe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 78f75bbfc..4e9cd91f3 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -785,7 +785,7 @@ class DAGMCUniverse(UniverseBase): Universe instance """ - bounding_cell = openmc.Cell(fill=self, cell_id =bounding_cell_id, region=self.bounding_region(**kwargs)) + bounding_cell = openmc.Cell(fill=self, cell_id=bounding_cell_id, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) @classmethod From bb764b960a1a6f745f9eaed7aea2f65fa6eb6b72 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 13:52:50 +0100 Subject: [PATCH 0763/2654] added return type to bin width method --- openmc/filter.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 7fe454865..2e6c22c3a 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1325,8 +1325,14 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v1, 0., equality=True) def bin_log_width(self): - """Returns the base 10 log width of energy bins which is useful when - plotting the normalized flux""" + """Calculates the base 10 log width of energy bins which is useful when + plotting the normalized flux. + + Returns + ------- + numpy.array + Array of bin widths + """ bin_edges = np.unique(self.bins) log_width = np.log10(bin_edges[1:]/bin_edges[:-1]) return log_width From a94fb43418e15fccf522c2ee1f1271e268c5cba9 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 14:00:25 +0100 Subject: [PATCH 0764/2654] review comments from @paulromano --- openmc/material.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index ed1b83977..c194a8229 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -899,18 +899,17 @@ class Material(IDManagerMixin): return nuclides - def get_activity(self, normalization: str = 'volume', by_nuclide: bool = False): + def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False): """Returns the activity of the material or for each nuclide in the - material in units of [Bq], [Bq/g] or [Bq/cc]. + material in units of [Bq], [Bq/g] or [Bq/cm3]. .. versionadded:: 0.13.1 Parameters ---------- - normalization : {'total', 'mass', 'volume'} - Specifies the type of activity to return, 'total' will return the - material activity in [Bq], 'mass' returns the materials specific - activity in [Bq/g] and 'volume' returns the activity in [Bq/cc]. + units : {'Bq', 'Bq/g', 'Bq/cm3'} + Specifies the type of activity to return, options include total + activity [Bq], specific [Bq/g] or volumetric activity [Bq/cm3]. by_nuclide : bool Specifies if the activity should be returned for the material as a whole or per nuclide. @@ -924,16 +923,16 @@ class Material(IDManagerMixin): of the material is returned as a float. """ - cv.check_value('normalization', normalization, {'total', 'mass', 'volume'}) + cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/cm3'}) cv.check_type('by_nuclide', by_nuclide, bool) - - if normalization == 'total': + + if units == 'Bq': multiplier = self.volume - elif normalization == 'volume': + elif units == 'Bq/g': multiplier = 1 - elif normalization == 'mass': + elif units == 'Bq/cm3': multiplier = 1.0 / self.get_mass_density() - + activity = {} for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): inv_seconds = openmc.data.decay_constant(nuclide) @@ -944,7 +943,6 @@ class Material(IDManagerMixin): else: return sum(activity.values()) - def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material From 63b517aebc775fc4c060c18868895960c95100ae Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 14:52:35 +0100 Subject: [PATCH 0765/2654] updated tests to use units args by @eepeterson Co-authored-by: Ethan Peterson --- openmc/material.py | 3 ++- tests/unit_tests/test_material.py | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index c194a8229..724b88ab4 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -910,9 +910,10 @@ class Material(IDManagerMixin): units : {'Bq', 'Bq/g', 'Bq/cm3'} Specifies the type of activity to return, options include total activity [Bq], specific [Bq/g] or volumetric activity [Bq/cm3]. + Default is volumetric activity [Bq/cm3]. by_nuclide : bool Specifies if the activity should be returned for the material as a - whole or per nuclide. + whole or per nuclide. Default is False. Returns ------- diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 7e9121608..451c5308a 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -480,37 +480,37 @@ def test_get_activity(): m1.add_element("Li", 0.3) m1.set_density('g/cm3', 1.5) # activity in Bq/cc and Bq/g should not require volume setting - assert m1.get_activity(normalization='volume') == 0 - assert m1.get_activity(normalization='mass') == 0 + assert m1.get_activity(units='Bq/cm3') == 0 + assert m1.get_activity(units='Bq/g') == 0 m1.volume = 1 - assert m1.get_activity(normalization='total') == 0 + assert m1.get_activity(units='Bq') == 0 # Checks that 1g of tritium has the correct activity scaling m2 = openmc.Material() m2.add_nuclide("H3", 1) m2.set_density('g/cm3', 1) m2.volume = 1 - assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14 m2.set_density('g/cm3', 2) - assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14*2 m2.volume = 3 - assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2*3 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14*2*3 # Checks that 1 mol of a metastable nuclides has the correct activity m3 = openmc.Material() m3.add_nuclide("Tc99_m1", 1) m3.set_density('g/cm3', 1) m3.volume = 98.9 - assert pytest.approx(m3.get_activity(normalization='total'), rel=0.001) == 1.93e19 + assert pytest.approx(m3.get_activity(units='Bq'), rel=0.001) == 1.93e19 # Checks that specific and volumetric activity of tritium are correct m4 = openmc.Material() m4.add_nuclide("H3", 1) m4.set_density('g/cm3', 1.5) - assert pytest.approx(m4.get_activity(normalization='mass')) == 355978108155965.94 # [Bq/g] - assert pytest.approx(m4.get_activity(normalization='mass', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g] - assert pytest.approx(m4.get_activity(normalization='volume')) == 355978108155965.94*3/2 # [Bq/cc] - assert pytest.approx(m4.get_activity(normalization='volume', by_nuclide=True)["H3"]) == 355978108155965.94*3/2 # [Bq/cc] + assert pytest.approx(m4.get_activity(units='Bq/g')) == 355978108155965.94 # [Bq/g] + assert pytest.approx(m4.get_activity(units='Bq/g', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g] + assert pytest.approx(m4.get_activity(units='Bq/cm3')) == 355978108155965.94*3/2 # [Bq/cc] + assert pytest.approx(m4.get_activity(units='Bq/cm3', by_nuclide=True)["H3"]) == 355978108155965.94*3/2 # [Bq/cc] # volume is required to calculate total activity m4.volume = 10. - assert pytest.approx(m4.get_activity(normalization='total')) == 355978108155965.94*3/2*10 # [Bq] + assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq] From 18bf88bab068ed7eae14220cdf494cf4886c0940 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 8 Aug 2022 10:22:46 -0500 Subject: [PATCH 0766/2654] Fix typos in mgxs.py spotted by @mkreher13 --- openmc/mgxs/mgxs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 75a33eed7..f9798c24a 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -3078,10 +3078,10 @@ class AbsorptionXS(MGXS): @add_params class ReducedAbsorptionXS(MGXS): - r"""A reduced absorpiton multi-group cross section. + r"""A reduced absorption multi-group cross section. The reduced absorption reaction rate is defined as the difference between - absorption and the produced of neutrons due to (n,xn) reactions. + absorption and the production of neutrons due to (n,xn) reactions. This class can be used for both OpenMC input generation and tally data post-processing to compute spatially-homogenized and energy-integrated From 3271c08d22d60b21546bbb948cd967a46b2023cd Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 8 Aug 2022 11:34:10 -0400 Subject: [PATCH 0767/2654] Apply suggestions from @paulromano code review Co-authored-by: Paul Romano --- openmc/material.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 724b88ab4..c89109bfa 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -917,7 +917,6 @@ class Material(IDManagerMixin): Returns ------- - Union[dict, float] If by_nuclide is True then a dictionary whose keys are nuclide names and values are activity is returned. Otherwise the activity @@ -939,10 +938,7 @@ class Material(IDManagerMixin): inv_seconds = openmc.data.decay_constant(nuclide) activity[nuclide] = inv_seconds * 1e24 * atoms_per_bcm * multiplier - if by_nuclide: - return activity - else: - return sum(activity.values()) + return activity if by_nuclide else sum(activity.values()) def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material From 77c3c82c7a00b86930db4c690d8c7b78e8b65010 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 17:52:49 +0100 Subject: [PATCH 0768/2654] renamed method to bin_lethargy --- openmc/filter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index 2e6c22c3a..0d68ff8d9 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1324,7 +1324,7 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) - def bin_log_width(self): + def bin_lethargy(self): """Calculates the base 10 log width of energy bins which is useful when plotting the normalized flux. From 0ba14b2cf08297e1cf190aac3f939e43fa286001 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 8 Aug 2022 12:20:11 -0500 Subject: [PATCH 0769/2654] Fix use of energy groups in MicroXS.from_model --- openmc/deplete/microxs.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index c4094970f..982d0a55f 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -76,12 +76,14 @@ class MicroXS(DataFrame): dilute_initial) model.materials = diluted_materials - for rxn in reactions: - if rxn == 'fission': - xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) + for rx in reactions: + if rx == 'fission': + xs[rx] = FissionXS(domain=reaction_domain, + energy_groups=groups, by_nuclide=True) else: - xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) - tallies += xs[rxn].tallies.values() + xs[rx] = ArbitraryXS(rx, domain=reaction_domain, + energy_groups=groups, by_nuclide=True) + tallies += xs[rx].tallies.values() model.tallies = tallies @@ -90,8 +92,8 @@ class MicroXS(DataFrame): statepoint_path = model.run(cwd=temp_dir) with StatePoint(statepoint_path) as sp: - for rxn in xs: - xs[rxn].load_from_statepoint(sp) + for rx in xs: + xs[rx].load_from_statepoint(sp) # Build the DataFrame series = {} From 5d5bc53a15ea3e77744285564d4aac26f0c0c731 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 20:46:57 +0100 Subject: [PATCH 0770/2654] Fixing the activity tests @eepeterson Co-authored-by: Ethan Peterson --- openmc/material.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index c89109bfa..54ff0b512 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -928,9 +928,9 @@ class Material(IDManagerMixin): if units == 'Bq': multiplier = self.volume - elif units == 'Bq/g': - multiplier = 1 elif units == 'Bq/cm3': + multiplier = 1 + elif units == 'Bq/g': multiplier = 1.0 / self.get_mass_density() activity = {} From 7ba45aaa35a839be0dfe1be622d8b499f56a1419 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 22:21:37 +0100 Subject: [PATCH 0771/2654] [skip ci] review comments from @paulromano Co-authored-by: Paul Romano --- openmc/filter.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 0d68ff8d9..d7ab3f27e 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1324,7 +1324,8 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) - def bin_lethargy(self): + @property + def lethargy_bin_width(self): """Calculates the base 10 log width of energy bins which is useful when plotting the normalized flux. @@ -1333,9 +1334,7 @@ class EnergyFilter(RealFilter): numpy.array Array of bin widths """ - bin_edges = np.unique(self.bins) - log_width = np.log10(bin_edges[1:]/bin_edges[:-1]) - return log_width + return np.log10(self.bins[:, 1]/self.bins[:, 0]) @classmethod def from_group_structure(cls, group_structure): From 8c72e4b7b0b8ecbb05ff085e8c859575dd764a00 Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 8 Aug 2022 22:57:32 +0100 Subject: [PATCH 0772/2654] added lethargy_bin_width test --- tests/unit_tests/test_filters.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 6b344b827..f50a57fa5 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -1,3 +1,4 @@ +import math import numpy as np import openmc from pytest import fixture, approx @@ -241,8 +242,14 @@ def test_first_moment(run_in_tmpdir, box_model): assert first_score(sph_flux_tally) == approx(flux) assert first_score(zernike_tally) == approx(scatter) - def test_energy(): f = openmc.EnergyFilter.from_group_structure('CCFE-709') assert f.bins.shape == (709, 2) assert len(f.values) == 710 + +def test_lethargy_bin_width(): + f = openmc.EnergyFilter.from_group_structure('VITAMIN-J-175') + assert len(f.lethargy_bin_width) == 175 + energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] + assert f.lethargy_bin_width[0] == math.log10(energy_bins[1]/energy_bins[0]) + assert f.lethargy_bin_width[-1] == math.log10(energy_bins[-1]/energy_bins[-2]) From 380cfc150b449ef56debb5261caa010a52c42bdd Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 9 Aug 2022 08:12:19 +0200 Subject: [PATCH 0773/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- include/openmc/source.h | 30 +--------- src/settings.cpp | 2 +- src/source.cpp | 128 +++++++++++++++------------------------- 3 files changed, 52 insertions(+), 108 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index 4d7ec104a..5c2dae931 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -96,7 +96,9 @@ class FileSource : public Source { public: // Constructors explicit FileSource(std::string path); - +#ifdef OPENMC_MCPL + explicit FileSource(mcpl_file_t mcpl_file); +#endif // Methods SourceSite sample(uint64_t* seed) const override; @@ -104,32 +106,6 @@ private: vector sites_; //!< Source sites from a file }; -#ifdef OPENMC_MCPL -//============================================================================== -// MCPL-file input source -//============================================================================== -class MCPLFileSource : public Source { -public: - // Constructors, destructors - MCPLFileSource(std::string path); - ~MCPLFileSource(); - - // Methods - //! Sample from the external source distribution - //! \param[inout] seed Pseudorandom seed pointer - //! \return Site read from MCPL-file - SourceSite sample(uint64_t* seed) const; - -private: - SourceSite read_single_particle() const; - void read_source_bank(vector &sites_); - - vector sites_; //!(path)); + model::external_sources.push_back(make_unique(mcpl_open_file(path.c_str()))); #endif } else if (check_for_node(node, "library")) { // Get shared library path and parameters diff --git a/src/source.cpp b/src/source.cpp index 82978f103..49e51c4b1 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -277,6 +277,54 @@ FileSource::FileSource(std::string path) file_close(file_id); } +#ifdef OPENMC_MCPL +FileSource::FileSource(mcpl_file_t mcpl_file) +{ + //do checks on the mcpl_file to see if particles are many enough. + // should model this on the example source shown in the docs. + size_t n_sites=mcpl_hdr_nparticles(mcpl_file); + + sites_.resize(n_sites); + for (int i=0;ipdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { + mcpl_particle=mcpl_read(mcpl_file); + //should check for file exhaustion This could happen if particles are other than + //neutrons or photons + } + + if(mcpl_particle->pdgcode==2112) { + site_.particle=ParticleType::neutron; + } else if (mcpl_particle->pdgcode==22) { + site_.particle=ParticleType::photon; + } + + //particle is good, convert to openmc-formalism + site_.r.x=mcpl_particle->position[0]; + site_.r.y=mcpl_particle->position[1]; + site_.r.z=mcpl_particle->position[2]; + + site_.u.x=mcpl_particle->direction[0]; + site_.u.y=mcpl_particle->direction[1]; + site_.u.z=mcpl_particle->direction[2]; + + //mcpl stores kinetic energy in MeV + site_.E=mcpl_particle->ekin*1e6; + //mcpl stores time in ms + site_.time=mcpl_particle->time*1e-3; + site_.wgt=mcpl_particle->weight; + site_.delayed_group=0; + sites_[i]=site_; + } + mcpl_close_file(mcpl_file); +} +#endif //OPENMC_MCPL + SourceSite FileSource::sample(uint64_t* seed) const { size_t i_site = sites_.size() * prn(seed); @@ -336,86 +384,6 @@ CustomSourceWrapper::~CustomSourceWrapper() #endif } -#ifdef OPENMC_MCPL -//=========================================================================== -// Read particles from an MCPL-file -//=========================================================================== -MCPLFileSource::MCPLFileSource(std::string path) -{ - // Check if source file exists - if (!file_exists(path)) { - fatal_error(fmt::format("Source file '{}' does not exist.", path)); - } - - // Read the source from a binary file instead of sampling from some - // assumed source distribution - write_message(6, "Reading mcpl source file from {}",path); - - // Open the mcpl file - mcpl_file = mcpl_open_file(path.c_str()); - - //do checks on the mcpl_file to see if particles are many enough. - // should model this on the example source shown in the docs. - n_sites=mcpl_hdr_nparticles(mcpl_file); - - read_source_bank(sites_); -} - -MCPLFileSource::~MCPLFileSource(){ - mcpl_close_file(mcpl_file); -} - -SourceSite MCPLFileSource::sample(uint64_t* seed) const -{ - size_t i_site = sites_.size() * prn(seed); - return sites_[i_site]; -} - -void MCPLFileSource::read_source_bank(vector &sites_) -{ - sites_.resize(n_sites); - for (int i=0;ipdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { - mcpl_particle=mcpl_read(mcpl_file); - //should check for file exhaustion This could happen if particles are other than - //neutrons or photons - } - - if(mcpl_particle->pdgcode==2112) { - omc_particle_.particle=ParticleType::neutron; - } else if (mcpl_particle->pdgcode==22) { - omc_particle_.particle=ParticleType::photon; - } - - //particle is good, convert to openmc-formalism - omc_particle_.r.x=mcpl_particle->position[0]; - omc_particle_.r.y=mcpl_particle->position[1]; - omc_particle_.r.z=mcpl_particle->position[2]; - - omc_particle_.u.x=mcpl_particle->direction[0]; - omc_particle_.u.y=mcpl_particle->direction[1]; - omc_particle_.u.z=mcpl_particle->direction[2]; - - //mcpl stores kinetic energy in MeV - omc_particle_.E=mcpl_particle->ekin*1e6; - //mcpl stores time in ms - omc_particle_.time=mcpl_particle->time*1e-3; - omc_particle_.wgt=mcpl_particle->weight; - omc_particle_.delayed_group=0; - return omc_particle_; -} -#endif //OPENMC_MCPL //============================================================================== // Non-member functions From 7004ff5467e48939c73a4fd74569d29b2a77527f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 9 Aug 2022 12:40:45 +0100 Subject: [PATCH 0774/2654] [skip ci] pep8 def spaces --- tests/unit_tests/test_filters.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index f50a57fa5..ec051d9fd 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -242,11 +242,13 @@ def test_first_moment(run_in_tmpdir, box_model): assert first_score(sph_flux_tally) == approx(flux) assert first_score(zernike_tally) == approx(scatter) + def test_energy(): f = openmc.EnergyFilter.from_group_structure('CCFE-709') assert f.bins.shape == (709, 2) assert len(f.values) == 710 + def test_lethargy_bin_width(): f = openmc.EnergyFilter.from_group_structure('VITAMIN-J-175') assert len(f.lethargy_bin_width) == 175 From bdd9468540360e3ca24f1a9e68032517669d61b6 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 9 Aug 2022 17:19:49 -0500 Subject: [PATCH 0775/2654] Fix reaction rate normalization in IndependentOperator The _IndependentNormalizationHelper was unneeded. Additionally, need to have a dilute_inital parameter to get good first-step results. --- openmc/deplete/independent_operator.py | 55 ++++++-------------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index b7956205a..422965fb8 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -55,6 +55,10 @@ class IndependentOperator(OpenMCOperator): Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only applicable if ``"normalization_mode" == "fission-q"``. + dilute_initial : float, optional + Initial atom density [atoms/cm^3] to add for nuclides that are zero + in initial condition to ensure they exist in the decay chain. + Only done for nuclides with reaction rates. reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. @@ -110,6 +114,7 @@ class IndependentOperator(OpenMCOperator): keff=None, normalization_mode='source-rate', fission_q=None, + dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None, @@ -135,6 +140,7 @@ class IndependentOperator(OpenMCOperator): chain_file, prev_results, fission_q=fission_q, + dilute_initial=dilute_initial, helper_kwargs=helper_kwargs, reduce_chain=reduce_chain, reduce_chain_level=reduce_chain_level) @@ -147,6 +153,7 @@ class IndependentOperator(OpenMCOperator): keff=None, normalization_mode='source-rate', fission_q=None, + dilute_initial=1.0e3, prev_results=None, reduce_chain=False, reduce_chain_level=None, @@ -178,6 +185,10 @@ class IndependentOperator(OpenMCOperator): Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only applicable if ``"normalization_mode" == "fission-q"``. + dilute_initial : float + Initial atom density [atoms/cm^3] to add for nuclides that + are zero in initial condition to ensure they exist in the decay + chain. Only done for nuclides with reaction rates. prev_results : Results, optional Results from a previous depletion calculation. reduce_chain : bool, optional @@ -202,6 +213,7 @@ class IndependentOperator(OpenMCOperator): keff=keff, normalization_mode=normalization_mode, fission_q=fission_q, + dilute_initial=dilute_initial, prev_results=prev_results, reduce_chain=reduce_chain, reduce_chain_level=reduce_chain_level, @@ -253,47 +265,6 @@ class IndependentOperator(OpenMCOperator): """Finds nuclides with cross section data""" return set(cross_sections.index) - class _IndependentNormalizationHelper(ChainFissionHelper): - """Class for calculating one-group flux based on a power. - - flux = Power / X, where X = volume * sum_i(Q_i * fission_micro_xs_i * density_i) - - Parameters - ---------- - op : openmc.deplete.IndependentOperator - Reference to the object encapsulating _IndependentNormalizationHelper. - We pass this so we don't have to duplicate :attr:`IndependentOperator.number`. - - """ - - def __init__(self, op): - rates = op.reaction_rates - self.nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} - self._op = op - super().__init__() - - def update(self, fission_rates, mat_index=None): - """Update 'energy' produced with fission rates in a material. What - this actually calculates is the quantity X. - - Parameters - ---------- - fission_rates : numpy.ndarray - fission reaction rate for each isotope in the specified - material. Should be ordered corresponding to initial - ``rate_index`` used in :meth:`prepare` - mat_index : int - Material index - - """ - volume = self._op.number.get_mat_volume(mat_index) - densities = np.empty_like(fission_rates) - for i_nuc, nuc in self.nuc_ind_map.items(): - densities[i_nuc] = self._op.number.get_atom_density(mat_index, nuc) - fission_rates *= volume * densities - - super().update(fission_rates) - class _IndependentRateHelper(ReactionRateHelper): """Class for generating one-group reaction rates with flux and one-group cross sections. @@ -370,7 +341,7 @@ class IndependentOperator(OpenMCOperator): self._rate_helper = self._IndependentRateHelper(self) if normalization_mode == "fission-q": - self._normalization_helper = self._IndependentNormalizationHelper(self) + self._normalization_helper = ChainFissionHelper() else: self._normalization_helper = SourceRateHelper() From b5b0ca5ce01bc3139b1481c48874f898655201f0 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 9 Aug 2022 19:54:40 -0500 Subject: [PATCH 0776/2654] make fission-q default normalization mode --- openmc/deplete/independent_operator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index 422965fb8..d84dcb16f 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -112,7 +112,7 @@ class IndependentOperator(OpenMCOperator): micro_xs, chain_file, keff=None, - normalization_mode='source-rate', + normalization_mode='fission-q', fission_q=None, dilute_initial=1.0e3, prev_results=None, @@ -151,7 +151,7 @@ class IndependentOperator(OpenMCOperator): chain_file, nuc_units='atom/b-cm', keff=None, - normalization_mode='source-rate', + normalization_mode='fission-q', fission_q=None, dilute_initial=1.0e3, prev_results=None, From 6048593ad31e7890eb3882e018a25538483a4db9 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 9 Aug 2022 21:51:33 -0500 Subject: [PATCH 0777/2654] update and expand deplete_no_transport test --- tests/micro_xs_simple.csv | 20 +-- .../deplete_no_transport/test.py | 155 +++++++++++++++--- .../test_reference_coupled_days.h5 | Bin 0 -> 36312 bytes .../test_reference_coupled_hours.h5 | Bin 0 -> 36312 bytes .../test_reference_coupled_minutes.h5 | Bin 0 -> 36312 bytes .../test_reference_coupled_months.h5 | Bin 0 -> 36312 bytes .../test_reference_fission_q.h5 | Bin 36312 -> 36312 bytes .../test_reference_source_rate.h5 | Bin 36312 -> 36312 bytes 8 files changed, 144 insertions(+), 31 deletions(-) create mode 100644 tests/regression_tests/deplete_no_transport/test_reference_coupled_days.h5 create mode 100644 tests/regression_tests/deplete_no_transport/test_reference_coupled_hours.h5 create mode 100644 tests/regression_tests/deplete_no_transport/test_reference_coupled_minutes.h5 create mode 100644 tests/regression_tests/deplete_no_transport/test_reference_coupled_months.h5 diff --git a/tests/micro_xs_simple.csv b/tests/micro_xs_simple.csv index 787ce74c3..71981c718 100644 --- a/tests/micro_xs_simple.csv +++ b/tests/micro_xs_simple.csv @@ -1,13 +1,13 @@ nuclide,"(n,gamma)",fission -U234,22.231989822002465,0.49620744663749855 -U235,10.479008971197121,48.41787337164604 -U238,0.8673334105437324,0.10467880588762352 -U236,8.65171044607122,0.31948392400019293 -O16,7.497851000107524e-05,0.0 -O17,0.0004079227797153371,0.0 -I135,6.842395323713927,0.0 -Xe135,227463.86426990604,0.0 -Xe136,0.02317896034753588,0.0 +U234,22.231989822002454,0.4962074466374984 +U235,10.479008971197121,48.41787337164606 +U238,0.8673334105437321,0.1046788058876236 +U236,8.651710446071224,0.31948392400019293 +O16,7.497851000107522e-05,0.0 +O17,0.0004079227797153372,0.0 +I135,6.842395323713929,0.0 +Xe135,227463.8642699061,0.0 +Xe136,0.023178960347535887,0.0 Cs135,2.1721665580713623,0.0 -Gd157,12786.09939237018,0.0 +Gd157,12786.099392370175,0.0 Gd156,3.4006085445846983,0.0 diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 95b842537..bf4a4b132 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -20,6 +20,17 @@ def fuel(): return fuel +@pytest.fixture(scope="module") +def micro_xs(): + micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' + micro_xs = MicroXS.from_csv(micro_xs_file) + + return micro_xs + +@pytest.fixture(scope="module") +def chain_file(): + return Path(__file__).parents[2] / 'chain_simple.xml' + @pytest.mark.parametrize("multiproc, from_nuclides, normalization_mode, power, flux", [ (True, True,'source-rate', None, 1164719970082145.0), (False, True, 'source-rate', None, 1164719970082145.0), @@ -29,7 +40,15 @@ def fuel(): (False, False, 'source-rate', None, 1164719970082145.0), (True, False, 'fission-q', 174, None), (False, False, 'fission-q', 174, None)]) -def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclides, normalization_mode, power, flux): +def test_against_self(run_in_tmpdir, + fuel, + micro_xs, + chain_file, + multiproc, + from_nuclides, + normalization_mode, + power, + flux): """Transport free system test suite. Runs an OpenMC transport-free depletion calculation and verifies @@ -37,28 +56,22 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide """ # Create operator - micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' - micro_xs = MicroXS.from_csv(micro_xs_file) - chain_file = Path(__file__).parents[2] / 'chain_simple.xml' - - if from_nuclides: - nuclides = {} - for nuc, dens in fuel.get_nuclide_atom_densities().items(): - nuclides[nuc] = dens - - op = IndependentOperator.from_nuclides( - fuel.volume, nuclides, micro_xs, chain_file, normalization_mode=normalization_mode) - - else: - op = IndependentOperator(openmc.Materials([fuel]), micro_xs, chain_file, normalization_mode=normalization_mode) + op = _create_operator(from_nuclides, + fuel, + micro_xs, + chain_file, + normalization_mode) # Power and timesteps - dt = [30] # single step + dt = [360] # single step # Perform simulation using the predictor algorithm openmc.deplete.pool.USE_MULTIPROCESSING = multiproc - openmc.deplete.PredictorIntegrator( - op, dt, power=power, source_rates=flux, timestep_units='d').integrate() + openmc.deplete.PredictorIntegrator(op, + dt, + power=power, + source_rates=flux, + timestep_units='s').integrate() # Get path to test and reference results path_test = op.output_dir / 'depletion_results.h5' @@ -73,9 +86,86 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide res_ref = openmc.deplete.Results(path_reference) # Assert same mats + _assert_same_mats(res_test, res_ref) + + tol = 1.0e-14 + _assert_atoms_equal(res_test, res_ref, tol) + _assert_reaction_rates_equal(res_test, res_ref, tol) + +@pytest.mark.parametrize("multiproc, dt, time_units, time_type, atom_tol, rx_tol ", [ + (True, 360, 's', 'minutes', 2.0e-3, 3.0e-2), + (False, 360, 's', 'minutes', 2.0e-3, 3.0e-2), + (True, 4, 'h', 'hours', 2.0e-3, 6.0e-2), + (False,4, 'h', 'hours', 2.0e-3, 6.0e-2), + (True, 5, 'd', 'days', 2.0e-3, 5.0e-2), + (False,5, 'd', 'days', 2.0e-3, 5.0e-2), + (True, 100, 'd', 'months', 4.0e-3, 9.0e-2), + (False, 100, 'd', 'months', 4.0e-3, 9.0e-2)]) +def test_against_coupled(run_in_tmpdir, + fuel, + micro_xs, + chain_file, + multiproc, + dt, + time_units, + time_type, + atom_tol, + rx_tol): + # Create operator + op = _create_operator(False, fuel, micro_xs, chain_file, 'fission-q') + + # Power and timesteps + dt = [dt] # single step + + # Perform simulation using the predictor algorithm + openmc.deplete.pool.USE_MULTIPROCESSING = multiproc + openmc.deplete.PredictorIntegrator( + op, dt, power=174, timestep_units=time_units).integrate() + + # Get path to test and reference results + path_test = op.output_dir / 'depletion_results.h5' + + ref_path = f'test_reference_coupled_{time_type}.h5' + path_reference = Path(__file__).with_name(ref_path) + + # Load the reference/test results + res_test = openmc.deplete.Results(path_test) + res_ref = openmc.deplete.Results(path_reference) + + # Assert same mats + _assert_same_mats(res_test, res_ref) + + _assert_atoms_equal(res_test, res_ref, atom_tol) + _assert_reaction_rates_equal(res_test, res_ref, rx_tol) + +def _create_operator(from_nuclides, + fuel, + micro_xs, + chain_file, + normalization_mode): + if from_nuclides: + nuclides = {} + for nuc, dens in fuel.get_nuclide_atom_densities().items(): + nuclides[nuc] = dens + + op = IndependentOperator.from_nuclides(fuel.volume, + nuclides, + micro_xs, + chain_file, + normalization_mode=normalization_mode) + + else: + op = IndependentOperator(openmc.Materials([fuel]), + micro_xs, + chain_file, + normalization_mode=normalization_mode) + + return op + +def _assert_same_mats(res_ref, res_test): for mat in res_ref[0].mat_to_ind: - assert mat in res_test[0].mat_to_ind, \ - "Material {} not in new results.".format(mat) + assert mat in res_test[0].mat_to_ind, \ + "Material {} not in new results.".format(mat) for nuc in res_ref[0].nuc_to_ind: assert nuc in res_test[0].nuc_to_ind, \ "Nuclide {} not in new results.".format(nuc) @@ -87,7 +177,7 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide assert nuc in res_ref[0].nuc_to_ind, \ "Nuclide {} not in old results.".format(nuc) - tol = 1.0e-6 +def _assert_atoms_equal(res_ref, res_test, tol): for mat in res_test[0].mat_to_ind: for nuc in res_test[0].nuc_to_ind: _, y_test = res_test.get_atoms(mat, nuc) @@ -104,3 +194,26 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide assert correct, "Discrepancy in mat {} and nuc {}\n{}\n{}".format( mat, nuc, y_old, y_test) + +def _assert_reaction_rates_equal(res_ref, res_test, tol): + for reactions in res_test[0].rates: + for mat in reactions.index_mat: + for nuc in reactions.index_nuc: + for rx in reactions.index_rx: + y_test = res_test.get_reaction_rate(mat, nuc, rx)[1] / \ + res_test.get_atoms(mat, nuc)[1] + y_old = res_ref.get_reaction_rate(mat, nuc, rx)[1] / \ + res_ref.get_atoms(mat, nuc)[1] + + # Test each point + correct = True + for i, ref in enumerate(y_old): + if ref != y_test[i]: + if ref != 0.0: + correct = np.abs(y_test[i] - ref) / ref <= tol + else: + if y_test[i] != 0.0: + correct = False + + assert correct, "Discrepancy in mat {}, nuc {}, and rx {}\n{}\n{}".format( + mat, nuc, rx, y_old, y_test) diff --git a/tests/regression_tests/deplete_no_transport/test_reference_coupled_days.h5 b/tests/regression_tests/deplete_no_transport/test_reference_coupled_days.h5 new file mode 100644 index 0000000000000000000000000000000000000000..d97acffec6923460cacfe609b1122c57e5181ce9 GIT binary patch literal 36312 zcmeHPZ)_aJ6`#BFpCg#&V$xzl8!izg7Xih=A#p)>zQh+|S3sSFKW;_abDRx!QYjxIVFaa-f@G6c)S(|@6^TZmluJ?7P)accnp6~G^-BX^@P{_;%+CAW z-c7Q1=e5t69!cH(pQa?5p32MNlLT0 zyb);Gw4qJ)aE!W%c~%!IZ@-t&d_{ej*EOO=az)6w9TYWkcJH>*1Ks_7A{3M~vYQmQ z&pw}K2GK#zaD9L;kToJs_O6oUgJNfQk2SbAWs$nLRw^!$3Fz;zQc^+I7*1OQLp_57 zP&D|9Y@aNt%7TaJS4ee29`(d8%|o9n5685ppg!ude7f?FWRbA6Q`B;^xdV0;V4TkJ>3dpgG_P_=tS3Qu_fFb@g$+ zT1(VZM>iUcc6hDtaxI7WZ{k%W>S-NPCD%1U(cQPhQa<;hb&UZ`jcBBD)nchEx4XY* zs8_CDmV}#Vtm0zr)ne_m;b%MdZEt<+m47xlD-**oCEeC9rvELrkBHQ2gJH6J_I7>I zLTMJ4Hv;fmh;#5u^)wIM=Gj>+Xx3_cd~&ucpM!M)_OTX9HjIZwIf8eM3(03wNX0t zHJuOs9KJ4JFGK0c>veuu3sHANzFwTt$#0Ot0vCw8CSK0|zt)bs9fSS7;l82X?N&OB z7_7SH7KbUU%CdNlu++AbwmLfXV}g!BE5}kXJ9vr#INki$B#k5cFCfLT5CU%g>mbb| zl!afJEB^)Fnf}M&i#Og?QiB~k-gpN)rSdMhOjpdj!;E2B2mv?V1!*3kY`J)6#&d@+ z-grlkt!EwYV5d~xP0%`nd50OpvJe7pynD=8ua=8<=K6THyhC3dJKo|Q?3Bv8wiUVr z^UgtzuiO!En1l)L+qFm-9jTw2p?J zxvsW5BXu96xDP#Z9S|pbQ`7+HnSQH<^isF#3+N3~dfXUSQlB@0-;d1pIDXQbzx7iO z96R3pE$o>7w%GgJAvI~`QKto;uP_8mKN_a~hv_{hz!B-Y_0f*r-VR!B$nO&d?C%}G zQ}_eu7nA&+Q!#|D?EB`t#6E6Z1H|o}?O55#QzDiZS`Z8G`I_2!!&|lmy zh70s&j!(pHK)_!$ywzz+EtWUxx@W&_9&!w0@+t>^3^zwQ3FEt$Xj@jf=-m z_um(|^!Q;M%<)40%*Q8eH!k3>nB17y(9r5nu!u0Y-ok zU<4QeMxgu%xIIq@m00y*dVT7y(9r5nu!u0Y>19 zN5Jd;VXVY`!???Sf%get{Md5~7y(9r5nu!u0Y-okm&9a5g`J>vBlO&!H)mYd zjnGH=nY5X8839Is5nu!u0Y-okUmr(M>Gygr=&vE>>W0Y-okU<4R} zxk6y?ZAUwHZFxLis(f!(=Zi0`daL>P>rJus|BEJmy{+x!;dg$Pc;j~`7uTe(i=kbA z`~ETO)i55Ygv7WDPTK-_-{piO#Bft66^orO(&5eKj?Da(KiHDCzPmP?5K7XHY-AxV0 zqknGw=(h3x&zp_~{xJM*Z7SOiyL~@gw!xMsthkb+)=1Mw|9SJdM;>ZuerfqH*KdAu zW%K>#MlvV*hnl~4=-&-vA8c)I|NW9j9(eb?jlWtQdgm{#Qyb4rR_^3<04h|ctAKG|f#f2;mZ=e0-v$u~r zI2>qr_B)RcRAq7KdillL+dpoI9qIaTYoP7@=+5ZAEvo`6V@F>2_Px*jJrO(i*VbLn pJbfr!@}fKV%LL{|8&T`&R$} literal 0 HcmV?d00001 diff --git a/tests/regression_tests/deplete_no_transport/test_reference_coupled_hours.h5 b/tests/regression_tests/deplete_no_transport/test_reference_coupled_hours.h5 new file mode 100644 index 0000000000000000000000000000000000000000..6d9bcc91ff7eff734feb83cf96e56f2b2d3e8819 GIT binary patch literal 36312 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 literal 0 HcmV?d00001 diff --git a/tests/regression_tests/deplete_no_transport/test_reference_coupled_months.h5 b/tests/regression_tests/deplete_no_transport/test_reference_coupled_months.h5 new file mode 100644 index 0000000000000000000000000000000000000000..43b45cb370c43d2d05000e6cb2dfa1b764d0d5b7 GIT binary patch literal 36312 zcmeHP4{TdU89&=eQ zMxecIV?y=t2z3+ltRYg_elMr_iuy3GYel={ijZ^LFKXrN-kHh{rU&{(z%OZJH7RPH zJs!;rqJx~_`T$=bYekgoT_?-?#Utt7)X?rsiqyr8QgOLVK))xIkqWZLU^X>4+&eS~ zMT5V{_Q;Z|EO>~11ym>G(M0^xJoGs7@QC&l)JI*G&({tD;9)0q8POs^^9M+*r3=j0 zcHD3&ANbUkxQZpasQlE%nGIRaLaO9S_y^5ZAtosvp}i(Az?;!pT`%;;DShF6I=_XQ zHFXbNEHdE~kEfRDhQhyUKOh|az#{7wH)nwnF#P~{)JgFH%>hrqN94Pe+7GCxtB(sc zTB4o?y3t~^!)<+6YdOS!6R%p)MC*_xa$VyW>HeOS^0}9-YYbp&MGKXy5i4Z5oddnY zeRB1(JlINO6&352iFMP4pY48pTgT~F|JrJ=Obo-6bXvcd{bP5#kGtD%&}LB20ZJdCb_A%F(28Qc1f?_Y z*ZJVjq55LI9Hl2$>inPVU6<8`|2Tw5or<4Dhq;X{b1*BNcgn*O(IzaOX zW#L!m%YT7)rvI_|;*NLK)L`3=JKn)gxx7o>tSe^TVaBkW2>~bG`Dq@ZY^8W-#&er5 z?s!L!t>+x?V5eN(P0%`nd50OpawY_vc(=z`uU3k8=K6T9yhC4YJMQ8g?3By9M58Xj zyt9$xD`y0pcsCU+E>kJqjoqT_nV|Y?zPO8b_<7B?@&r2E0V!;E1$69P`Wn_OL7s#3fg z{jjblNA=B>cX+OC+i@4~V5eN(jjhrBVBQta8%|vr0Vm!iX&#|erFa*-UDpt$`fR?q zi+5NWSNP1FWIt)ro5 zuB)xiNZmaY_n~L51EOSaiW&et({HttUgi#c0lg7Qj~U}i>I)|D`;plm+fTalw_fUj zZO5Izg&ou1mU^E%peC(68noc^HHLucM}yS=Aid`VI70n*JlfUQ*G0<>`F+Bm^}Pdl z3V#6oQj*_uDuvLseczmy*vE~jpjmKW{>@i>*YVPuf6uAKc+Y7U@nVG90l%3e0-!w? zC>>a&-vJarSdmM_OA{}*?-!SfP)_e-?j!s&)Jyg|6&dcU#;B9uX)<^Wp3j%x0bfkN zF21amVMspMBKWv@|BAEQ)Vdy%opOi5}fgVqi&6=w9~rfsaDmiFO&75Q}(_M{l)!K zxIl0A_=Kzm_`FL-?zfv#h>tRjFexu70BK#<=RWz`Xg1x|i|7y(9r5nu!u0Y-ok zU<4QeMxgQtI6Y4Ylv(v5dVT7y(9r5nu!u0Y>1x zN5Jj=;YgYLhB1fz0`C*v`?2R1FanGKBftnS0*nA7FdGD%){Uj!3p+;ZM(8;`Z_YWa z8=;T#vuQKyG6IYMBftnS0*nA7zz8fn0<&E==1Qy=#~s#*ygpp`vE>>W0Y-okU<4R} z`9fg#o!{%)@#!a{<;p+q=zi(t)u&@ekGDoPTnfj(|3Kozq2KR~zy8w`H`He9BWTxe zANpbHwKr<=|CMOV=hv*vZ2x-xzax#Fx&Gwlk^kn?FMjLpUwm@^iG2CkkLtet#F?6W z+CN>rqVdh<$c~%ZZrK`tEBy8&p;vx0-543H{m`#29*;+!`s~s0n}^Sbzq#3S*Q#cD z-SPIFV*~HD-skz{$RFx5`F5!G9s6Q(qt(u1si=~B|MKJ3m)F;HOrKjDi+^p)#h-no zF&18V@H^+$yc&D*wbyTtw0|RZ_gBQ`;r_pUB2+c`kI-kru`fKh`>A(sI~`l~r;C@) zK7UVq)3K+|9RA(j_!D~?UfMCdGT-ivfBwnSr|OsH>wjnUW2c_^=kxh~|LgI;xAp9r z&ZiG|eAV~Z$v5)l&o9evYQD+F;gv(r)qnS7bENe@ThARl|5o_j^p{@jOWYQ@wCwnX x@%{Hk>JmNm=^spn(+@R<1HV2RKK#PL&mBDV@7B!bpFh0+K8*wV4=D<8_#el*|FQr8 literal 0 HcmV?d00001 diff --git a/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 b/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 index 82bf11567363a56b84f87a204df7ea79d6f7e124..826c5f3b012fb4b1fb26be4193ac451bd232e2a1 100644 GIT binary patch delta 499 zcmcaHo9V`ErVS^$>nn9vC1wRSIuJ|W%t~IlPW__u_QUpe=6`Kn)&vI}U2wIi( z>oaS_?HHio#j&PC7cR5g!}yCFtEQR6O|gaXH?i6U{J8Wt0xl3>en?d`?0(3ES5+<&P*^p`|r|UxQ81i*q)a}^6=4er7ihL9<~$Kv;PhB@Zu*w@>_u( s{`<>dl?>3sd^gWHc>p~exwPTDIncxIcc$7g{s(zjOd9527>(p_038;reE=)Ab`?xM&C z8qSOt)V(FQn>#aAeT-cTbW_-dH%EQv+PYj%{r^4vQj3e6i_XteMLR7)=7K<##nCNZ z7gt(Acnl2l&;83O+a_oRSMZ^xFE>U@U!VIc;%#r4Z3tLebJ%iA#UuAeKo76$Sv0HUT&LwCzQBD=W*`rX%D_Afqmexh E0GDu#TmS$7 diff --git a/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 b/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 index 88ed73b1766fb795aee19a1417a151a451c6243e..f5161d37067f6b7ffe333e41270959a75f7ebfda 100644 GIT binary patch delta 439 zcmcaHo9V`ErVS^$>nn9vC1wRSIuJ|W%t~IlPW__u_QUpe=6`Kn)&vI}U2wIf`iXPC8n9r>*gQ;}o;v zI;TpYvs1Ot$(JH6Sx#D$1U!zI*E!wmZ_EYxcER)y;ru|~rtbT(6`OB85x!*u+rMP8 jWv@Krw8@dZ@|rN`M?#(d9EbDogPbn|ayHlqEY1f24GN@? delta 305 zcmcaHo9V`ErVS^$Ctfg+xS5r_a-I4`=beY`?acq$x~vZlIJ)3!i_64=37VT%{C3!U zHrg&CxI19+ZDzaYF>$M}n0nd0soXSmpJe|#6zS}LWc+uJR(kEwwmzFN)7Sx1)yxiilM!@xwv#g^X)G7w|nrxm$)z{}zkurDZ_Q2AP1(`2bQpfkOZQ From 672293a310425f975665ba95b6757b3d32a9fd68 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 9 Aug 2022 23:04:53 -0500 Subject: [PATCH 0778/2654] doc fixes --- docs/source/pythonapi/deplete.rst | 4 ++-- docs/source/usersguide/depletion.rst | 3 ++- openmc/deplete/microxs.py | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 0b7faceb7..4154e35df 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -43,7 +43,7 @@ algorithms `_. SILEQIIntegrator Each of these classes expects a "transport operator" to be passed. OpenMC -provides The following classes implementing transpor operators: +provides The following classes implement transport operators: .. autosummary:: :toctree: generated @@ -55,7 +55,7 @@ provides The following classes implementing transpor operators: The :class:`CoupledOperator` and :class:`IndependentOperator` classes must also have some knowledge of how nuclides transmute and decay. This is handled by the -:class:`Chain`. +:class:`Chain` class. Minimal Example --------------- diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 29c8114d9..6c3117095 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -21,7 +21,8 @@ material compositions over time. Each method appears as a different class. For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation using the CE/CM algorithm (deplete over a timestep using the middle-of-step reaction rates). An instance of :class:`~openmc.deplete.abc.TransportOperator` -is passed to one of these functions along with the timesteps and power level:: +is passed to one of these Integrator classes along with the timesteps and power +level:: power = 1200.0e6 # watts timesteps = [10.0, 10.0, 10.0] # days diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 982d0a55f..71e476c2c 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -1,7 +1,7 @@ """MicroXS module A pandas.DataFrame storing microscopic cross section data with -nuclides names as row indices and reaction names as column indices. +nuclide names as row indices and reaction names as column indices. """ import tempfile @@ -26,7 +26,7 @@ _valid_rxns.append('fission') class MicroXS(DataFrame): """Stores microscopic cross section data for use in - independent depletion. + transport-independent depletion. """ @classmethod From 527d97916d870662664979c855b66b5139637ead Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 9 Aug 2022 12:55:41 -0400 Subject: [PATCH 0779/2654] allow settings properties to be set through constructor --- openmc/settings.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 47c61e6ae..73b690605 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -222,7 +222,7 @@ class Settings: Indicate whether to write the initial source distribution to file """ - def __init__(self): + def __init__(self, **kwargs): self._run_mode = RunMode.EIGENVALUE self._batches = None self._generations_per_batch = None @@ -297,6 +297,9 @@ class Settings: self._max_splits = None self._max_tracks = None + for key, value in kwargs.items(): + setattr(self, key, value) + @property def run_mode(self) -> str: return self._run_mode.value From 1af84f94de57916cf277e7505bea8d9579ebc750 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 10 Aug 2022 08:27:17 -0400 Subject: [PATCH 0780/2654] added docstring info and test --- openmc/settings.py | 172 ++++++++++++++++++++++++++++++ tests/unit_tests/test_settings.py | 5 +- 2 files changed, 173 insertions(+), 4 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 73b690605..4a796c34f 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -29,6 +29,178 @@ _RES_SCAT_METHODS = ['dbrc', 'rvs'] class Settings: """Settings used for an OpenMC simulation. + Parameters + ---------- + batches : int, optional + Number of batches to simulate + confidence_intervals : bool, optional + If True, uncertainties on tally results will be reported as the + half-width of the 95% two-sided confidence interval. If False, + uncertainties on tally results will be reported as the sample standard + deviation. + create_fission_neutrons : bool, optional + Indicate whether fission neutrons should be created or not. + cutoff : dict, optional + Dictionary defining weight cutoff and energy cutoff. The dictionary may + have six keys, 'weight', 'weight_avg', 'energy_neutron', 'energy_photon', + 'energy_electron', and 'energy_positron'. Value for 'weight' + should be a float indicating weight cutoff below which particle undergo + Russian roulette. Value for 'weight_avg' should be a float indicating + weight assigned to particles that are not killed after Russian + roulette. Value of energy should be a float indicating energy in eV + below which particle type will be killed. + delayed_photon_scaling : bool, optional + Indicate whether to scale the fission photon yield by (EGP + EGD)/EGP + where EGP is the energy release of prompt photons and EGD is the energy + release of delayed photons. + electron_treatment : {'led', 'ttb'}, optional + Whether to deposit all energy from electrons locally ('led') or create + secondary bremsstrahlung photons ('ttb'). + energy_mode : {'continuous-energy', 'multi-group'}, optional + Set whether the calculation should be continuous-energy or multi-group. + entropy_mesh : openmc.RegularMesh, optional + Mesh to be used to calculate Shannon entropy. If the mesh dimensions are + not specified, OpenMC assigns a mesh such that 20 source sites per mesh + cell are to be expected on average. + event_based : bool, optional + Indicate whether to use event-based parallelism instead of the default + history-based parallelism. + generations_per_batch : int, optional + Number of generations per batch + max_lost_particles : int, optional + Maximum number of lost particles + rel_max_lost_particles : float, optional + Maximum number of lost particles, relative to the total number of particles + inactive : int, optional + Number of inactive batches + keff_trigger : dict, optional + Dictionary defining a trigger on eigenvalue. The dictionary must have + two keys, 'type' and 'threshold'. Acceptable values corresponding to + type are 'variance', 'std_dev', and 'rel_err'. The threshold value + should be a float indicating the variance, standard deviation, or + relative error used. + log_grid_bins : int, optional + Number of bins for logarithmic energy grid search + material_cell_offsets : bool, optional + Generate an "offset table" for material cells by default. These tables + are necessary when a particular instance of a cell needs to be tallied. + max_particles_in_flight : int, optional + Number of neutrons to run concurrently when using event-based + parallelism. + max_order : None or int, optional + Maximum scattering order to apply globally when in multi-group mode. + max_splits : int, optional + Maximum number of times a particle can split during a history + max_tracks : int, optional + Maximum number of tracks written to a track file (per MPI process). + no_reduce : bool, optional + Indicate that all user-defined and global tallies should not be reduced + across processes in a parallel calculation. + output : dict, optional + Dictionary indicating what files to output. Acceptable keys are: + + :path: String indicating a directory where output files should be + written + :summary: Whether the 'summary.h5' file should be written (bool) + :tallies: Whether the 'tallies.out' file should be written (bool) + particles : int, optional + Number of particles per generation + photon_transport : bool, optional + Whether to use photon transport. + ptables : bool, optional + Determine whether probability tables are used. + resonance_scattering : dict, optional + Settings for resonance elastic scattering. Accepted keys are 'enable' + (bool), 'method' (str), 'energy_min' (float), 'energy_max' (float), and + 'nuclides' (list). The 'method' can be set to 'dbrc' (Doppler broadening + rejection correction) or 'rvs' (relative velocity sampling). If not + specified, 'rvs' is the default method. The 'energy_min' and + 'energy_max' values indicate the minimum and maximum energies above and + below which the resonance elastic scattering method is to be + applied. The 'nuclides' list indicates what nuclides the method should + be applied to. In its absence, the method will be applied to all + nuclides with 0 K elastic scattering data present. + run_mode : {'eigenvalue', 'fixed source', 'plot', 'volume', 'particle restart'}, optional + The type of calculation to perform (default is 'eigenvalue') + seed : int, optional + Seed for the linear congruential pseudorandom number generator + source : Iterable of openmc.Source, optional + Distribution of source sites in space, angle, and energy + sourcepoint : dict, optional + Options for writing source points. Acceptable keys are: + + :batches: list of batches at which to write source + :overwrite: bool indicating whether to overwrite + :separate: bool indicating whether the source should be written as a + separate file + :write: bool indicating whether or not to write the source + statepoint : dict, optional + Options for writing state points. Acceptable keys are: + + :batches: list of batches at which to write source + surf_source_read : dict, optional + Options for reading surface source points. Acceptable keys are: + + :path: Path to surface source file (str). + surf_source_write : dict, optional + Options for writing surface source points. Acceptable keys are: + + :surface_ids: List of surface ids at which crossing particles are to be + banked (int) + :max_particles: Maximum number of particles to be banked on + surfaces per process (int) + survival_biasing : bool, optional + Indicate whether survival biasing is to be used + tabular_legendre : dict, optional + Determines if a multi-group scattering moment kernel expanded via + Legendre polynomials is to be converted to a tabular distribution or + not. Accepted keys are 'enable' and 'num_points'. The value for + 'enable' is a bool stating whether the conversion to tabular is + performed; the value for 'num_points' sets the number of points to use + in the tabular distribution, should 'enable' be True. + temperature : dict, optional + Defines a default temperature and method for treating intermediate + temperatures at which nuclear data doesn't exist. Accepted keys are + 'default', 'method', 'range', 'tolerance', and 'multipole'. The value + for 'default' should be a float representing the default temperature in + Kelvin. The value for 'method' should be 'nearest' or 'interpolation'. + If the method is 'nearest', 'tolerance' indicates a range of temperature + within which cross sections may be used. The value for 'range' should be + a pair a minimum and maximum temperatures which are used to indicate + that cross sections be loaded at all temperatures within the + range. 'multipole' is a boolean indicating whether or not the windowed + multipole method should be used to evaluate resolved resonance cross + sections. + trace : tuple or list, optional + Show detailed information about a single particle, indicated by three + integers: the batch number, generation number, and particle number + track : tuple or list, optional + Specify particles for which track files should be written. Each particle + is identified by a tuple with the batch number, generation number, and + particle number. + trigger_active : bool, optional + Indicate whether tally triggers are used + trigger_batch_interval : int, optional + Number of batches in between convergence checks + trigger_max_batches : int, optional + Maximum number of batches simulated. If this is set, the number of + batches specified via ``batches`` is interpreted as the minimum number + of batches + ufs_mesh : openmc.RegularMesh, optional + Mesh to be used for redistributing source sites via the uniform fission + site (UFS) method. + verbosity : int, optional + Verbosity during simulation between 1 and 10. Verbosity levels are + described in :ref:`verbosity`. + volume_calculations : VolumeCalculation or iterable of VolumeCalculation, optional + Stochastic volume calculation specifications + weight_windows : WeightWindows iterable of WeightWindows, optional + Weight windows to use for variance reduction + weight_windows_on : bool, optional + Whether weight windows are enabled + write_initial_source : bool, optional + Indicate whether to write the initial source distribution to file + Attributes ---------- batches : int diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index b21c036fa..7678711a4 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -3,9 +3,7 @@ import openmc.stats def test_export_to_xml(run_in_tmpdir): - s = openmc.Settings() - s.run_mode = 'fixed source' - s.batches = 1000 + s = openmc.Settings(run_mode='fixed source', batches=1000, seed=17) s.generations_per_batch = 10 s.inactive = 100 s.particles = 1000000 @@ -25,7 +23,6 @@ def test_export_to_xml(run_in_tmpdir): s.surf_source_write = {'surface_ids': [2], 'max_particles': 200} s.confidence_intervals = True s.ptables = True - s.seed = 17 s.survival_biasing = True s.cutoff = {'weight': 0.25, 'weight_avg': 0.5, 'energy_neutron': 1.0e-5, 'energy_photon': 1000.0, 'energy_electron': 1.0e-5, From 36ecaf9bd6a7fa4e51281881921f3506020a5f38 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 10 Aug 2022 09:19:08 -0500 Subject: [PATCH 0781/2654] Adding ability to specify starting ID for surfaces of the DAGMC bounding region --- openmc/universe.py | 45 ++++++++++++------- .../dagmc/universes/inputs_true.dat | 14 +++--- .../regression_tests/dagmc/universes/test.py | 5 ++- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 3ef9e6650..aef4d660b 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Iterable from copy import deepcopy -from numbers import Real +from numbers import Integral, Real from pathlib import Path from tempfile import TemporaryDirectory from xml.etree import ElementTree as ET @@ -723,7 +723,7 @@ class DAGMCUniverse(UniverseBase): dagmc_element.set('filename', self.filename) xml_element.append(dagmc_element) - def bounding_region(self, bounded_type='box', boundary_type='vacuum'): + def bounding_region(self, bounded_type='box', boundary_type='vacuum', starting_id=10000): """Creates a either a spherical or box shaped bounding region around the DAGMC geometry. Parameters @@ -736,6 +736,10 @@ class DAGMCUniverse(UniverseBase): Boundary condition that defines the behavior for particles hitting the surface. Defaults to vacuum boundary condition. Passed into the surface construction. + starting_id : int + Starting ID of the surface(s) used in the region. For bounded_type + 'box', the next 5 IDs will also be used. Defaults to 10000 to reduce + the chance of an overlap of surface IDs with the DAGMC geometry. Returns ------- openmc.Region @@ -744,19 +748,21 @@ class DAGMCUniverse(UniverseBase): check_type('boundary type', boundary_type, str) check_value('boundary type', boundary_type, _BOUNDARY_TYPES) + check_type('starting surface id', starting_id, Integral) check_type('bounded type', bounded_type, str) check_value('bounded type', bounded_type, ('box', 'sphere')) - bounding_box = self.bounding_box + bbox = self.bounding_box if bounded_type == 'sphere': import math - bounding_box_center = (bounding_box[0] + bounding_box[1])/2 - radius = math.dist(bounding_box[0], bounding_box[1]) + bbox_center = (bbox[0] + bbox[1])/2 + radius = math.dist(bbox[0], bbox[1]) bounding_surface = openmc.Sphere( - x0=bounding_box_center[0], - y0=bounding_box_center[1], - z0=bounding_box_center[2], + surface_id=starting_id, + x0=bbox_center[0], + y0=bbox_center[1], + z0=bbox_center[2], boundary_type=boundary_type, r=radius, ) @@ -764,15 +770,21 @@ class DAGMCUniverse(UniverseBase): return -bounding_surface if bounded_type == 'box': + surf_ids = [starting_id+i for i in range(6)] # defines plane surfaces for all six faces of the bounding box - lower_x = openmc.XPlane(bounding_box[0][0], boundary_type=boundary_type) - upper_x = openmc.XPlane(bounding_box[1][0], boundary_type=boundary_type) - lower_y = openmc.YPlane(bounding_box[0][1], boundary_type=boundary_type) - upper_y = openmc.YPlane(bounding_box[1][1], boundary_type=boundary_type) - lower_z = openmc.ZPlane(bounding_box[0][2], boundary_type=boundary_type) - upper_z = openmc.ZPlane(bounding_box[1][2], boundary_type=boundary_type) + lower_x = openmc.XPlane(bbox[0][0], surface_id=surf_ids[0]) + upper_x = openmc.XPlane(bbox[1][0], surface_id=surf_ids[1]) + lower_y = openmc.YPlane(bbox[0][1], surface_id=surf_ids[2]) + upper_y = openmc.YPlane(bbox[1][1], surface_id=surf_ids[3]) + lower_z = openmc.ZPlane(bbox[0][2], surface_id=surf_ids[4]) + upper_z = openmc.ZPlane(bbox[1][2], surface_id=surf_ids[5]) - return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z + region = +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z + + for surface in region.get_surfaces().values(): + surface.boundary_type = boundary_type + + return region def bounded_universe(self, bounding_cell_id=10000, **kwargs): """Returns an openmc.Universe filled with this DAGMCUniverse and bounded @@ -783,7 +795,7 @@ class DAGMCUniverse(UniverseBase): Parameters ---------- bounding_cell_id : int - The cell ID number to use for the bounding cell, defaults to 1000 to reduce + The cell ID number to use for the bounding cell, defaults to 10000 to reduce the chance of overlapping ID numbers with the DAGMC geometry. Returns @@ -791,7 +803,6 @@ class DAGMCUniverse(UniverseBase): openmc.Universe Universe instance """ - bounding_cell = openmc.Cell(fill=self, cell_id=bounding_cell_id, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index 2165a78b6..ea6ad519b 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,6 +1,6 @@ - + 24.0 24.0 @@ -10,12 +10,12 @@ 9 9 9 9 - - - - - - + + + + + + diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index f2eb3882f..67c8f962d 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -62,8 +62,10 @@ class DAGMCUniverseTest(PyAPITestHarness): b_region = pincell_univ.bounding_region(bounded_type='box', boundary_type='vacuum') assert isinstance(b_region, openmc.Region) assert len(b_region.get_surfaces()) == 6 - for surface in list(b_region.get_surfaces().values()): + starting_id = 10000 + for i, surface in enumerate(b_region.get_surfaces().values()): assert surface.boundary_type == 'vacuum' + assert surface.id == 10000 + i # checks that the bounding region is a single surface with a reflective boundary type b_region = pincell_univ.bounding_region(bounded_type='sphere', boundary_type='reflective') @@ -71,6 +73,7 @@ class DAGMCUniverseTest(PyAPITestHarness): assert len(b_region.get_surfaces()) == 1 for surface in list(b_region.get_surfaces().values()): assert surface.boundary_type == 'reflective' + assert surface.id == 10000 # create a 2 x 2 lattice using the DAGMC pincell pitch = np.asarray((24.0, 24.0)) From 5861ba53226e3ae269ee67397307fbf8213f664c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 10 Aug 2022 16:43:34 +0100 Subject: [PATCH 0782/2654] minor typo fix --- src/dagmc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index dc3bc2b2c..0e04869fd 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -745,7 +745,7 @@ namespace openmc { void read_dagmc_universes(pugi::xml_node node) { if (check_for_node(node, "dagmc_universe")) { - fatal_error("DAGMC Universes are present but OpenMC was not configured" + fatal_error("DAGMC Universes are present but OpenMC was not configured " "with DAGMC"); } }; From 6bd4a7134134abd1bbf1078d48147dca29d67694 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 10 Aug 2022 10:56:22 -0500 Subject: [PATCH 0783/2654] add clarifying comment to _IndependentRateHelper --- openmc/deplete/independent_operator.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index d84dcb16f..a2d89e441 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -321,8 +321,10 @@ class IndependentOperator(OpenMCOperator): nuc = self.nuc_ind_map[i_nuc] rxn = self.rxn_ind_map[i_react] density = self._op.number.get_atom_density(mat_id, nuc) - self._results_cache[i_nuc, - i_react] = self._op.cross_sections[rxn][nuc] * density * volume + + # Sigma^j_i * V = sigma^j_i * rho * V + self._results_cache[i_nuc,i_react] = \ + self._op.cross_sections[rxn][nuc] * density * volume return self._results_cache From 2144ec271fa3625c74c90881d9c5e5589fe77db6 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 10 Aug 2022 10:57:23 -0500 Subject: [PATCH 0784/2654] fix flux equation in depletion userguide --- docs/source/usersguide/depletion.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 6c3117095..ee0d09b8d 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -319,7 +319,7 @@ normalizing reaction rates: .. math:: - \phi = \frac{P}{V \cdot \sum_i (Q_i \cdot \Sigma^f_i \cdot \rho_i)} + \phi = \frac{P}{V \cdot \sum_i (Q_i \cdot \sigma^f_i \cdot \rho_i)} where :math:`\sum_i` is the sum over all nuclides :math:`i`. This equation makes the same assumptions and issues as discussed in From d23541f5ed523d0a5a7f268c238435fb7c9c2487 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 10 Aug 2022 13:00:35 -0400 Subject: [PATCH 0785/2654] simplify docstring --- openmc/settings.py | 171 +-------------------------------------------- 1 file changed, 2 insertions(+), 169 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 4a796c34f..4372e679f 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -31,175 +31,8 @@ class Settings: Parameters ---------- - batches : int, optional - Number of batches to simulate - confidence_intervals : bool, optional - If True, uncertainties on tally results will be reported as the - half-width of the 95% two-sided confidence interval. If False, - uncertainties on tally results will be reported as the sample standard - deviation. - create_fission_neutrons : bool, optional - Indicate whether fission neutrons should be created or not. - cutoff : dict, optional - Dictionary defining weight cutoff and energy cutoff. The dictionary may - have six keys, 'weight', 'weight_avg', 'energy_neutron', 'energy_photon', - 'energy_electron', and 'energy_positron'. Value for 'weight' - should be a float indicating weight cutoff below which particle undergo - Russian roulette. Value for 'weight_avg' should be a float indicating - weight assigned to particles that are not killed after Russian - roulette. Value of energy should be a float indicating energy in eV - below which particle type will be killed. - delayed_photon_scaling : bool, optional - Indicate whether to scale the fission photon yield by (EGP + EGD)/EGP - where EGP is the energy release of prompt photons and EGD is the energy - release of delayed photons. - electron_treatment : {'led', 'ttb'}, optional - Whether to deposit all energy from electrons locally ('led') or create - secondary bremsstrahlung photons ('ttb'). - energy_mode : {'continuous-energy', 'multi-group'}, optional - Set whether the calculation should be continuous-energy or multi-group. - entropy_mesh : openmc.RegularMesh, optional - Mesh to be used to calculate Shannon entropy. If the mesh dimensions are - not specified, OpenMC assigns a mesh such that 20 source sites per mesh - cell are to be expected on average. - event_based : bool, optional - Indicate whether to use event-based parallelism instead of the default - history-based parallelism. - generations_per_batch : int, optional - Number of generations per batch - max_lost_particles : int, optional - Maximum number of lost particles - rel_max_lost_particles : float, optional - Maximum number of lost particles, relative to the total number of particles - inactive : int, optional - Number of inactive batches - keff_trigger : dict, optional - Dictionary defining a trigger on eigenvalue. The dictionary must have - two keys, 'type' and 'threshold'. Acceptable values corresponding to - type are 'variance', 'std_dev', and 'rel_err'. The threshold value - should be a float indicating the variance, standard deviation, or - relative error used. - log_grid_bins : int, optional - Number of bins for logarithmic energy grid search - material_cell_offsets : bool, optional - Generate an "offset table" for material cells by default. These tables - are necessary when a particular instance of a cell needs to be tallied. - max_particles_in_flight : int, optional - Number of neutrons to run concurrently when using event-based - parallelism. - max_order : None or int, optional - Maximum scattering order to apply globally when in multi-group mode. - max_splits : int, optional - Maximum number of times a particle can split during a history - max_tracks : int, optional - Maximum number of tracks written to a track file (per MPI process). - no_reduce : bool, optional - Indicate that all user-defined and global tallies should not be reduced - across processes in a parallel calculation. - output : dict, optional - Dictionary indicating what files to output. Acceptable keys are: - - :path: String indicating a directory where output files should be - written - :summary: Whether the 'summary.h5' file should be written (bool) - :tallies: Whether the 'tallies.out' file should be written (bool) - particles : int, optional - Number of particles per generation - photon_transport : bool, optional - Whether to use photon transport. - ptables : bool, optional - Determine whether probability tables are used. - resonance_scattering : dict, optional - Settings for resonance elastic scattering. Accepted keys are 'enable' - (bool), 'method' (str), 'energy_min' (float), 'energy_max' (float), and - 'nuclides' (list). The 'method' can be set to 'dbrc' (Doppler broadening - rejection correction) or 'rvs' (relative velocity sampling). If not - specified, 'rvs' is the default method. The 'energy_min' and - 'energy_max' values indicate the minimum and maximum energies above and - below which the resonance elastic scattering method is to be - applied. The 'nuclides' list indicates what nuclides the method should - be applied to. In its absence, the method will be applied to all - nuclides with 0 K elastic scattering data present. - run_mode : {'eigenvalue', 'fixed source', 'plot', 'volume', 'particle restart'}, optional - The type of calculation to perform (default is 'eigenvalue') - seed : int, optional - Seed for the linear congruential pseudorandom number generator - source : Iterable of openmc.Source, optional - Distribution of source sites in space, angle, and energy - sourcepoint : dict, optional - Options for writing source points. Acceptable keys are: - - :batches: list of batches at which to write source - :overwrite: bool indicating whether to overwrite - :separate: bool indicating whether the source should be written as a - separate file - :write: bool indicating whether or not to write the source - statepoint : dict, optional - Options for writing state points. Acceptable keys are: - - :batches: list of batches at which to write source - surf_source_read : dict, optional - Options for reading surface source points. Acceptable keys are: - - :path: Path to surface source file (str). - surf_source_write : dict, optional - Options for writing surface source points. Acceptable keys are: - - :surface_ids: List of surface ids at which crossing particles are to be - banked (int) - :max_particles: Maximum number of particles to be banked on - surfaces per process (int) - survival_biasing : bool, optional - Indicate whether survival biasing is to be used - tabular_legendre : dict, optional - Determines if a multi-group scattering moment kernel expanded via - Legendre polynomials is to be converted to a tabular distribution or - not. Accepted keys are 'enable' and 'num_points'. The value for - 'enable' is a bool stating whether the conversion to tabular is - performed; the value for 'num_points' sets the number of points to use - in the tabular distribution, should 'enable' be True. - temperature : dict, optional - Defines a default temperature and method for treating intermediate - temperatures at which nuclear data doesn't exist. Accepted keys are - 'default', 'method', 'range', 'tolerance', and 'multipole'. The value - for 'default' should be a float representing the default temperature in - Kelvin. The value for 'method' should be 'nearest' or 'interpolation'. - If the method is 'nearest', 'tolerance' indicates a range of temperature - within which cross sections may be used. The value for 'range' should be - a pair a minimum and maximum temperatures which are used to indicate - that cross sections be loaded at all temperatures within the - range. 'multipole' is a boolean indicating whether or not the windowed - multipole method should be used to evaluate resolved resonance cross - sections. - trace : tuple or list, optional - Show detailed information about a single particle, indicated by three - integers: the batch number, generation number, and particle number - track : tuple or list, optional - Specify particles for which track files should be written. Each particle - is identified by a tuple with the batch number, generation number, and - particle number. - trigger_active : bool, optional - Indicate whether tally triggers are used - trigger_batch_interval : int, optional - Number of batches in between convergence checks - trigger_max_batches : int, optional - Maximum number of batches simulated. If this is set, the number of - batches specified via ``batches`` is interpreted as the minimum number - of batches - ufs_mesh : openmc.RegularMesh, optional - Mesh to be used for redistributing source sites via the uniform fission - site (UFS) method. - verbosity : int, optional - Verbosity during simulation between 1 and 10. Verbosity levels are - described in :ref:`verbosity`. - volume_calculations : VolumeCalculation or iterable of VolumeCalculation, optional - Stochastic volume calculation specifications - weight_windows : WeightWindows iterable of WeightWindows, optional - Weight windows to use for variance reduction - weight_windows_on : bool, optional - Whether weight windows are enabled - write_initial_source : bool, optional - Indicate whether to write the initial source distribution to file + **kwargs : dict, optional + Any keyword arguments are used to set attributes on the instance. Attributes ---------- From dcbaa59cdbd83322881878377901f8f303d60a6b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 10 Aug 2022 13:30:22 -0500 Subject: [PATCH 0786/2654] Using numpy rather than impoting math --- openmc/universe.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index aef4d660b..58b880280 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -755,9 +755,8 @@ class DAGMCUniverse(UniverseBase): bbox = self.bounding_box if bounded_type == 'sphere': - import math bbox_center = (bbox[0] + bbox[1])/2 - radius = math.dist(bbox[0], bbox[1]) + radius = np.linalg.norm(np.asarray(bbox)) bounding_surface = openmc.Sphere( surface_id=starting_id, x0=bbox_center[0], From 8140ff492c5a25b6908f4f1178e2677c436cb592 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 10 Aug 2022 14:23:26 -0500 Subject: [PATCH 0787/2654] added some commenting and the extern remove_tally_from_tallies function --- include/openmc/tallies/tally.h | 4 ++-- src/tallies/tally.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h index 73618a3da..46284dea2 100644 --- a/include/openmc/tallies/tally.h +++ b/include/openmc/tallies/tally.h @@ -47,9 +47,9 @@ public: void set_nuclides(const vector& nuclides); - const vector& filters() const { return filters_; } + const vector& filters() const { return filters_; } // returns vector of inidices corresponding to the tally this is called on - int32_t filters(int i) const { return filters_[i]; } + int32_t filters(int i) const { return filters_[i]; } // i corresponds to the index of the filter for this tally void set_filters(gsl::span filters); diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index c0fedd973..82b526b4e 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -46,6 +46,8 @@ namespace openmc { //============================================================================== namespace model { +// map: key (tally ID) to value (tally index) +// index coresponds to the tally ID's posiition in the tallies vector std::unordered_map tally_map; vector> tallies; vector active_tallies; @@ -1271,4 +1273,13 @@ extern "C" size_t tallies_size() return model::tallies.size(); } +// given a tally ID, remove it from the tallies vector +extern "C" void remove_tally_from_tallies(int32_t id) +{ + // query map for index corersponding to the given id + int index = model::tally_map[id]; + // delete the tally + model::tallies.erase(index); +} + } // namespace openmc From b93642ff74253033cc16693f6a1c61537b207b7b Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Wed, 10 Aug 2022 14:32:42 -0500 Subject: [PATCH 0788/2654] fix density variable --- docs/source/usersguide/depletion.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index ee0d09b8d..229e90a4c 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -319,7 +319,7 @@ normalizing reaction rates: .. math:: - \phi = \frac{P}{V \cdot \sum_i (Q_i \cdot \sigma^f_i \cdot \rho_i)} + \phi = \frac{P}{V \cdot \sum_i (Q_i \cdot \sigma^f_i \cdot \n_i)} where :math:`\sum_i` is the sum over all nuclides :math:`i`. This equation makes the same assumptions and issues as discussed in From 9d146a3e0f657a7d02c231a13cdff65b025b0ded Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 10 Aug 2022 15:44:00 -0500 Subject: [PATCH 0789/2654] added openmc_remove_tally_from_tallies to C++ API in tally.py --- openmc/lib/tally.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index df28cb5dc..d839d6ddc 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -87,6 +87,9 @@ _dll.openmc_tally_set_type.errcheck = _error_handler _dll.openmc_tally_set_writable.argtypes = [c_int32, c_bool] _dll.openmc_tally_set_writable.restype = c_int _dll.openmc_tally_set_writable.errcheck = _error_handler +_dll.openmc_remove_tally_from_tallies.argtypes = [c_int32] +_dll.openmc_remove_tally_from_tallies.restype = None +_dll.openmc_remove_tally_from_tallies.errcheck = _error_handler _dll.tallies_size.restype = c_size_t From 8969b9b4e9fe99ac0926e2e67586b0573f2519c4 Mon Sep 17 00:00:00 2001 From: yardasol Date: Wed, 10 Aug 2022 15:53:40 -0500 Subject: [PATCH 0790/2654] remove unneeded parameter from update --- openmc/deplete/abc.py | 4 +--- openmc/deplete/helpers.py | 4 +--- openmc/deplete/openmc_operator.py | 4 ++-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index e3587f052..3e2c37ece 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -331,7 +331,7 @@ class NormalizationHelper(ABC): `fission_rates` for :meth:`update`. """ - def update(self, fission_rates, mat_index=None): + def update(self, fission_rates): """Update the normalization based on fission rates (only used for energy-based normalization) @@ -341,8 +341,6 @@ class NormalizationHelper(ABC): fission reaction rate for each isotope in the specified material. Should be ordered corresponding to initial ``rate_index`` used in :meth:`prepare` - mat_index : int - Material index """ @property diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 1e382576e..3a7928a52 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -426,7 +426,7 @@ class ChainFissionHelper(EnergyNormalizationHelper): self._fission_q_vector = fission_qs - def update(self, fission_rates, mat_index=None): + def update(self, fission_rates): """Update energy produced with fission rates in a material Parameters @@ -435,8 +435,6 @@ class ChainFissionHelper(EnergyNormalizationHelper): fission reaction rate for each isotope in the specified material. Should be ordered corresponding to initial ``rate_index`` used in :meth:`prepare` - mat_index : int - Unused """ self._energy += dot(fission_rates, self._fission_q_vector) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 6e6f8dd8d..c34065078 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -528,13 +528,13 @@ class OpenMCOperator(TransportOperator): # Accumulate energy from fission if fission_ind is not None: self._normalization_helper.update( - tally_rates[:, fission_ind], - mat_index=mat_index) + tally_rates[:, fission_ind]) # Divide by total number and store rates[i] = self._rate_helper.divide_by_adens(number) # Scale reaction rates to obtain units of reactions/sec + print(f"flux, power, or source rate: {self._normalization_helper.factor(source_rate)}") rates *= self._normalization_helper.factor(source_rate) # Store new fission yields on the chain From e3e2c301afdb7838d14521c4eefc113965a24acd Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 10 Aug 2022 15:59:22 -0500 Subject: [PATCH 0791/2654] forgot to prefix function with openmc. all other extern functions do this,so I changed it to be parallel --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 82b526b4e..4384d62c7 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1274,7 +1274,7 @@ extern "C" size_t tallies_size() } // given a tally ID, remove it from the tallies vector -extern "C" void remove_tally_from_tallies(int32_t id) +extern "C" void openmc_remove_tally_from_tallies(int32_t id) { // query map for index corersponding to the given id int index = model::tally_map[id]; From 6d9d665e53569110894f1d7896304cbed4d8a90e Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 10 Aug 2022 16:29:33 -0500 Subject: [PATCH 0792/2654] added new action to delete a tally as well as an assertion that the length is zero after deletion --- tests/unit_tests/test_tallies.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit_tests/test_tallies.py b/tests/unit_tests/test_tallies.py index bfff741a9..77aef78b4 100644 --- a/tests/unit_tests/test_tallies.py +++ b/tests/unit_tests/test_tallies.py @@ -39,3 +39,6 @@ def test_xml_roundtrip(run_in_tmpdir): assert new_tally.triggers[0].trigger_type == tally.triggers[0].trigger_type assert new_tally.triggers[0].threshold == tally.triggers[0].threshold assert new_tally.triggers[0].scores == tally.triggers[0].scores + # delete tally and check that new_tallies now has length zero + new_tally.openmc_remove_tally_from_tallies(tally.id) + assert len(new_tallies) == 0 \ No newline at end of file From 8887023b22239404c1a5d1e47883ea1231c1db9c Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 10 Aug 2022 16:45:53 -0500 Subject: [PATCH 0793/2654] accidental typo --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 4384d62c7..f5edf75b2 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -47,7 +47,7 @@ namespace openmc { namespace model { // map: key (tally ID) to value (tally index) -// index coresponds to the tally ID's posiition in the tallies vector +// index coresponds to the tally ID's position in the tallies vector std::unordered_map tally_map; vector> tallies; vector active_tallies; From 99027fdd1531d634ca53af83e9e006df331ad9f5 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 10 Aug 2022 17:35:30 -0500 Subject: [PATCH 0794/2654] erase needs an iterator, so feed it model::tallies.begin()+index --- src/tallies/tally.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index f5edf75b2..0df00bbe7 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1277,9 +1277,9 @@ extern "C" size_t tallies_size() extern "C" void openmc_remove_tally_from_tallies(int32_t id) { // query map for index corersponding to the given id - int index = model::tally_map[id]; - // delete the tally - model::tallies.erase(index); + int32_t index = model::tally_map[id]; + // delete the tally via iterator pointing to correct position + model::tallies.erase(model::tallies.begin() + index); } } // namespace openmc From 9abbff92c081ee66fd818e0019893481df30895d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 10 Aug 2022 23:06:47 -0500 Subject: [PATCH 0795/2654] Adding warnings for use of old CMake build options. --- CMakeLists.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85dcd7084..a0e788c13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,32 @@ option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) option(OPENMC_USE_MPI "Enable MPI" OFF) +# Warnings for deprecated options +foreach(OLD_OPT IN ITEMS "openmp" "profile" "coverage" "dagmc" "libmesh") + if(DEFINED ${OLD_OPT}) + string(TOUPPER ${OLD_OPT} OPT_UPPER) + message(WARNING "The OpenMC CMake option '${OLD_OPT}' has been deprecated. " + "Its value will be ignored. " + "Please use '-DOPENMC_USE_${OPT_UPPER}=${${OLD_OPT}}' instead.") + unset(${OLD_OPT} CACHE) + endif() +endforeach() + +foreach(OLD_BLD in ITEMS "debug" "optimize") + if(DEFINED ${OLD_BLD}) + if("${OLD_BLD}" EQUAL "debug") + set(BLD_VAR "Deubg") + else() + set(BLD_VAR "Release") + endif() + message(WARNING "The OpenMC CMake option '${OLD_BLD}' has been deprecated. " + "Its value will be ignored. " + "OpenMC now uses the CMAKE_BUILD_TYPE variable to set the build mode. " + "Please use '-DCMAKE_BUILD_TYPE=${BLD_VAR}' instead.") + unset(${OLD_BLD} CACHE) + endif() +endforeach() + #=============================================================================== # Set a default build configuration if not explicitly specified #=============================================================================== From f9b2c21d59241990ca28fcb604b9ef7ca2c97f7c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 10 Aug 2022 23:12:01 -0500 Subject: [PATCH 0796/2654] Fix potential bug with nuclide densities in Results.export_to_materials --- openmc/deplete/results.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index b89bae088..c2138b55c 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -417,7 +417,16 @@ class Results(list): mat_id = str(mat.id) if mat_id in result.mat_to_ind: mat.volume = result.volume[mat_id] + + # Change density of all nuclides in material to atom/b-cm + atoms_per_barn_cm = mat.get_nuclide_atom_densities() + for nuc, value in atoms_per_barn_cm.items(): + mat.remove_nuclide(nuc) + mat.add_nuclide(nuc, value) mat.set_density('sum') + + # For nuclides in chain that have cross sections, replace + # density in original material with new density from results for nuc in result.nuc_to_ind: if nuc not in available_cross_sections: continue From 84c25272b6a2e465138f1141d4a9539a3594dce1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 11 Aug 2022 06:39:49 -0400 Subject: [PATCH 0797/2654] Apply suggestions from @shimwell Co-authored-by: Jonathan Shimwell --- openmc/universe.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 58b880280..4317a3dd7 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -771,12 +771,12 @@ class DAGMCUniverse(UniverseBase): if bounded_type == 'box': surf_ids = [starting_id+i for i in range(6)] # defines plane surfaces for all six faces of the bounding box - lower_x = openmc.XPlane(bbox[0][0], surface_id=surf_ids[0]) - upper_x = openmc.XPlane(bbox[1][0], surface_id=surf_ids[1]) - lower_y = openmc.YPlane(bbox[0][1], surface_id=surf_ids[2]) - upper_y = openmc.YPlane(bbox[1][1], surface_id=surf_ids[3]) - lower_z = openmc.ZPlane(bbox[0][2], surface_id=surf_ids[4]) - upper_z = openmc.ZPlane(bbox[1][2], surface_id=surf_ids[5]) + lower_x = openmc.XPlane(bbox[0][0], surface_id=starting_id) + upper_x = openmc.XPlane(bbox[1][0], surface_id=starting_id+1) + lower_y = openmc.YPlane(bbox[0][1], surface_id=starting_id+2) + upper_y = openmc.YPlane(bbox[1][1], surface_id=starting_id+3) + lower_z = openmc.ZPlane(bbox[0][2], surface_id=starting_id+4) + upper_z = openmc.ZPlane(bbox[1][2], surface_id=starting_id+5) region = +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z From 4f93f26d8136f4bcb1d28bb9301c6b4c690b4042 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 11 Aug 2022 06:41:23 -0500 Subject: [PATCH 0798/2654] Using valid entries of connectivity only --- openmc/mesh.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index daff4dedc..af830158c 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1476,7 +1476,7 @@ class UnstructuredMesh(MeshBase): Coordinates of the mesh vertices with array shape (n_elements, 3) .. versionadded:: 0.13.1 - connectivity : numpy.ndarray + connectivity : numpy.ndarray Connectivity of the elements with array shape (n_elements, 8) .. versionadded:: 0.13.1 @@ -1562,10 +1562,6 @@ class UnstructuredMesh(MeshBase): def total_volume(self): return np.sum(self.volumes) - @property - def centroids(self): - return self._centroids - @property def vertices(self): return self._vertices @@ -1628,8 +1624,8 @@ class UnstructuredMesh(MeshBase): Parameters ---------- bin : int - Bin ID for the returned centroid - + Bin ID for the returned centroid + Returns ------- numpy.ndarray @@ -1637,6 +1633,8 @@ class UnstructuredMesh(MeshBase): """ conn = self.connectivity[bin] + # remove invalid connectivity values + conn = conn[conn >= 0] coords = self.vertices[conn] return coords.mean(axis=0) From ca99195e8172d761042ac88e17efc28b303b29a5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 11 Aug 2022 07:27:04 -0500 Subject: [PATCH 0799/2654] Fix Mixture.sample to account for intensities of underlying distributions --- openmc/stats/univariate.py | 26 +++++++++++++++++++++++--- tests/unit_tests/test_stats.py | 6 +++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 58b7c6172..0c3052625 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -79,6 +79,18 @@ class Univariate(EqualityMixin, ABC): """ pass + def integral(self): + """Return integral of distribution + + .. versionadded:: 0.13.1 + + Returns + ------- + float + Integral of distribution + """ + return 1.0 + class Discrete(Univariate): """Distribution characterized by a probability mass function. @@ -1168,9 +1180,17 @@ class Mixture(Univariate): def sample(self, n_samples=1, seed=None): np.random.seed(seed) - idx = np.random.choice(range(len(self.distribution)), - n_samples, p=self.probability) + # Get probability of each distribution accounting for its intensity + p = np.array([prob*dist.integral() for prob, dist in + zip(self.probability, self.distribution)]) + p /= p.sum() + + # Sample from the distributions + idx = np.random.choice(range(len(self.distribution)), + n_samples, p=p) + + # Draw samples from the distributions sampled above out = np.empty_like(idx, dtype=float) for i in np.unique(idx): n_dist_samples = np.count_nonzero(idx == i) @@ -1294,7 +1314,7 @@ def combine_distributions(dists, probs): # Combine discrete and continuous if present if len(dist_list) > 1: - probs = [d.integral() for d in dist_list] + probs = [1.0]*len(dist_list) dist_list[:] = [Mixture(probs, dist_list.copy())] return dist_list[0] diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index b8bb94f37..dbf06d0b5 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -61,12 +61,14 @@ def test_merge_discrete(): assert merged.x == pytest.approx([0.0, 0.5, 1.0, 5.0, 10.0]) assert merged.p == pytest.approx( [0.6*0.3, 0.4*0.4, 0.6*0.2 + 0.4*0.5, 0.4*0.1, 0.6*0.5]) + assert merged.integral() == pytest.approx(1.0) # Probabilities add up but are not normalized d1 = openmc.stats.Discrete([3.0], [1.0]) triple = openmc.stats.Discrete.merge([d1, d1, d1], [1.0, 2.0, 3.0]) assert triple.x == pytest.approx([3.0]) assert triple.p == pytest.approx([6.0]) + assert triple.integral() == pytest.approx(6.0) def test_uniform(): @@ -186,6 +188,7 @@ def test_tabular(): # test histogram sampling d = openmc.stats.Tabular(x, p, interpolation='histogram') d.normalize() + assert d.integral() == pytest.approx(1.0) samples = d.sample(n_samples, seed=100) diff = np.abs(samples - d.mean()) @@ -433,8 +436,9 @@ def test_combine_distributions(): t2 = openmc.stats.Tabular([0., 1.], [0.0, 2.0]) d1 = openmc.stats.Discrete([0.0], [1.0]) combined = openmc.stats.combine_distributions([t1, t2, d1], [0.25, 0.25, 0.5]) + assert combined.integral() == pytest.approx(1.0) # Sample the combined distribution and make sure the sample mean is within # uncertainty of the expected value - samples = combined.sample(1000) + samples = combined.sample(10_000) assert_sample_mean(samples, 0.25) From 246a551feaf7eb2b0246a2947fd89d103bbc1d71 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 11 Aug 2022 08:36:46 -0400 Subject: [PATCH 0800/2654] Update openmc/universe.py Co-authored-by: Jonathan Shimwell --- openmc/universe.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 4317a3dd7..727e7a096 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -769,7 +769,6 @@ class DAGMCUniverse(UniverseBase): return -bounding_surface if bounded_type == 'box': - surf_ids = [starting_id+i for i in range(6)] # defines plane surfaces for all six faces of the bounding box lower_x = openmc.XPlane(bbox[0][0], surface_id=starting_id) upper_x = openmc.XPlane(bbox[1][0], surface_id=starting_id+1) From 8791c7212e0bbca9abebf3f786b06ba8e82e151d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 11 Aug 2022 07:48:58 -0500 Subject: [PATCH 0801/2654] Adding check for first vertex and centroid --- .../unstructured_mesh/test.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/regression_tests/unstructured_mesh/test.py b/tests/regression_tests/unstructured_mesh/test.py index 090a47599..6146c1b1e 100644 --- a/tests/regression_tests/unstructured_mesh/test.py +++ b/tests/regression_tests/unstructured_mesh/test.py @@ -37,6 +37,27 @@ class UnstructuredMeshTest(PyAPITestHarness): def _compare_results(self): with openmc.StatePoint(self._sp_name) as sp: + # check some properties of the unstructured mesh + umesh = None + for m in sp.meshes.values(): + if isinstance(m, openmc.UnstructuredMesh): + umesh = m + assert umesh is not None + + # check that the first element centroid is correct + # this will depend on whether the tet mesh or hex mesh + # file is being used in this test + if umesh.element_types[0] == umesh._LINEAR_TET: + exp_vertex = (-10.0, -10.0, -10.0) + exp_centroid = (-8.75, -9.75, -9.25) + else: + exp_vertex = (-10.0, -10.0, 10.0) + exp_centroid = (-9.0, -9.0, 9.0) + + np.testing.assert_array_equal(umesh.vertices[0], exp_vertex) + np.testing.assert_array_equal(umesh.centroid(0), exp_centroid) + + # loop over the tallies and get data for tally in sp.tallies.values(): # find the regular and unstructured meshes From ba72199df02061d2f0aeca00296ad3a474f5576d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 11 Aug 2022 07:58:00 -0500 Subject: [PATCH 0802/2654] rm empty line --- tests/regression_tests/unstructured_mesh/test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/regression_tests/unstructured_mesh/test.py b/tests/regression_tests/unstructured_mesh/test.py index 6146c1b1e..9ed36c69c 100644 --- a/tests/regression_tests/unstructured_mesh/test.py +++ b/tests/regression_tests/unstructured_mesh/test.py @@ -57,7 +57,6 @@ class UnstructuredMeshTest(PyAPITestHarness): np.testing.assert_array_equal(umesh.vertices[0], exp_vertex) np.testing.assert_array_equal(umesh.centroid(0), exp_centroid) - # loop over the tallies and get data for tally in sp.tallies.values(): # find the regular and unstructured meshes From 97236d7c56fde45ca653f3e7f7354206f603badf Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 11 Aug 2022 08:05:33 -0500 Subject: [PATCH 0803/2654] Correcting suggested CMake variable names --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0e788c13..72986ea2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,9 +41,14 @@ option(OPENMC_USE_MPI "Enable MPI" foreach(OLD_OPT IN ITEMS "openmp" "profile" "coverage" "dagmc" "libmesh") if(DEFINED ${OLD_OPT}) string(TOUPPER ${OLD_OPT} OPT_UPPER) + if ("${OLD_OPT}" STREQUAL "profile" OR "${OLD_OPT}" STREQUAL "coverage") + set(NEW_OPT_PREFIX "OPENMC_ENABLE") + else() + set(NEW_OPT_PREFIX "OPENMC_USE") + endif() message(WARNING "The OpenMC CMake option '${OLD_OPT}' has been deprecated. " "Its value will be ignored. " - "Please use '-DOPENMC_USE_${OPT_UPPER}=${${OLD_OPT}}' instead.") + "Please use '-D${NEW_OPT_PREFIX}_${OPT_UPPER}=${${OLD_OPT}}' instead.") unset(${OLD_OPT} CACHE) endif() endforeach() From a753a44d9e10994485a0d8615041789a155a9c75 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 11 Aug 2022 09:06:32 -0400 Subject: [PATCH 0804/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72986ea2c..5e949070c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,8 +55,8 @@ endforeach() foreach(OLD_BLD in ITEMS "debug" "optimize") if(DEFINED ${OLD_BLD}) - if("${OLD_BLD}" EQUAL "debug") - set(BLD_VAR "Deubg") + if("${OLD_BLD}" STREQUAL "debug") + set(BLD_VAR "Debug") else() set(BLD_VAR "Release") endif() From 80dc21be2c62236fb7b654087fd7624f2fc41060 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 11 Aug 2022 11:10:49 -0500 Subject: [PATCH 0805/2654] Add test for TimeFilter when time intervals are effectively zero --- tests/unit_tests/test_time_filter.py | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/unit_tests/test_time_filter.py b/tests/unit_tests/test_time_filter.py index 5b09c6d5f..45fabc544 100644 --- a/tests/unit_tests/test_time_filter.py +++ b/tests/unit_tests/test_time_filter.py @@ -149,3 +149,39 @@ def test_time_filter_surface(model_surf, run_in_tmpdir): # After t0+ε, the current should be zero assert values[2] == 0.0 + + +def test_small_time_interval(run_in_tmpdir): + # Create a model with a photon source at 1.0e8 seconds. Based on the speed + # of the photon, the time intervals are on the order of 1e-9 seconds, which + # are effectively 0 when compared to the starting time of the photon. + mat = openmc.Material() + mat.add_element('N', 1.0) + mat.set_density('g/cm3', 0.001) + sph = openmc.Sphere(r=5.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sph) + model = openmc.Model() + model.geometry = openmc.Geometry([cell]) + model.settings.particles = 100 + model.settings.batches = 10 + model.settings.run_mode = 'fixed source' + model.settings.source = openmc.Source( + time=openmc.stats.Discrete([1.0e8], [1.0]), + particle='photon' + ) + + # Add tallies with and without a time filter that should match all particles + time_filter = openmc.TimeFilter([0.0, 1.0e100]) + tally_with_filter = openmc.Tally() + tally_with_filter.filters = [time_filter] + tally_with_filter.scores = ['flux'] + tally_without_filter = openmc.Tally() + tally_without_filter.scores = ['flux'] + model.tallies.extend([tally_with_filter, tally_without_filter]) + + # Run the model and make sure the two tallies match + sp_filename = model.run() + with openmc.StatePoint(sp_filename) as sp: + flux_with = sp.tallies[tally_with_filter.id].mean.ravel()[0] + flux_without = sp.tallies[tally_without_filter.id].mean.ravel()[0] + assert flux_with == pytest.approx(flux_without) From 23ba62866e8e0dfb836995bfd871f95746399026 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 11 Aug 2022 11:11:29 -0500 Subject: [PATCH 0806/2654] Fix treatment of 0 duration time intervals in TimeFilter::get_all_bins --- src/tallies/filter_time.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tallies/filter_time.cpp b/src/tallies/filter_time.cpp index 3f78d1817..787acc49e 100644 --- a/src/tallies/filter_time.cpp +++ b/src/tallies/filter_time.cpp @@ -55,13 +55,16 @@ void TimeFilter::get_all_bins( // the current track and find where it overlaps with time bins and score // accordingly - // Skip if time interval is zero - if (t_start == t_end) - return; - // Determine first bin containing a portion of time interval auto i_bin = lower_bound_index(bins_.begin(), bins_.end(), t_start); + // If time interval is zero, add a match corresponding to the starting time + if (t_end == t_start) { + match.bins_.push_back(i_bin); + match.weights_.push_back(1.0); + return; + } + // Find matching bins double dt_total = t_end - t_start; for (; i_bin < bins_.size() - 1; ++i_bin) { From 6f433fc429896ca0df716ea7d598c08e5d3edeb0 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 11 Aug 2022 17:29:42 +0100 Subject: [PATCH 0807/2654] unit tests DAGMCUniverse bounding_region bounding_box --- tests/unit_tests/test_dagmc_universe.py | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/unit_tests/test_dagmc_universe.py diff --git a/tests/unit_tests/test_dagmc_universe.py b/tests/unit_tests/test_dagmc_universe.py new file mode 100644 index 000000000..3f5403693 --- /dev/null +++ b/tests/unit_tests/test_dagmc_universe.py @@ -0,0 +1,38 @@ +import openmc +import pytest + + +def test_bounding_box(): + + u = openmc.DAGMCUniverse("tests/regression_tests/dagmc/universes/dagmc.h5m") + + ll, ur = u.bounding_box + assert ll == pytest.approx((-25., -25., -25)) + assert ur == pytest.approx((25., 25., 25)) + + +def test_bounding_region(): + + u = openmc.DAGMCUniverse("tests/regression_tests/dagmc/universes/dagmc.h5m") + + region = u.bounding_region() # should default to bounded_type='box' + assert isinstance(region, openmc.Region) + assert len(region) == 6 + assert region[0].surface.type == 'x-plane' + assert region[1].surface.type == 'x-plane' + assert region[2].surface.type == 'y-plane' + assert region[3].surface.type == 'y-plane' + assert region[4].surface.type == 'z-plane' + assert region[5].surface.type == 'z-plane' + assert region[0].surface.boundary_type == 'vacuum' + assert region[1].surface.boundary_type == 'vacuum' + assert region[2].surface.boundary_type == 'vacuum' + assert region[3].surface.boundary_type == 'vacuum' + assert region[4].surface.boundary_type == 'vacuum' + assert region[5].surface.boundary_type == 'vacuum' + + region = u.bounding_region(bounded_type='sphere', boundary_type='reflective') + assert isinstance(region, openmc.Region) + assert isinstance(region, openmc.Halfspace) + assert region.surface.type == 'sphere' + assert region.surface.boundary_type == 'reflective' From b1ea00b6cb5101b61d521f04cfe4e0c7c7770721 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 11 Aug 2022 18:01:49 +0100 Subject: [PATCH 0808/2654] added test for args passed to bounded_universe --- tests/unit_tests/test_dagmc_universe.py | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/unit_tests/test_dagmc_universe.py b/tests/unit_tests/test_dagmc_universe.py index 3f5403693..945d39d9b 100644 --- a/tests/unit_tests/test_dagmc_universe.py +++ b/tests/unit_tests/test_dagmc_universe.py @@ -36,3 +36,33 @@ def test_bounding_region(): assert isinstance(region, openmc.Halfspace) assert region.surface.type == 'sphere' assert region.surface.boundary_type == 'reflective' + +def test_bounded_universe(): + + u = openmc.DAGMCUniverse("tests/regression_tests/dagmc/universes/dagmc.h5m") + + # bounded with defaults + bu = u.bounded_universe() + + cells = list(bu.get_all_cells().items()) + assert len(cells) == 1 + assert cells[0][0] == 10000 # default bounding_cell_id is 10000 + assert cells[0][1].id == 10000 # default bounding_cell_id is 10000 + surfaces = list(cells[0][1].region.get_surfaces().items()) + assert len(surfaces) == 6 + assert surfaces[0][1].id == 10000 + + # bounded with non defaults + bu = u.bounded_universe( + bounding_cell_id=42, + bounded_type='sphere', + starting_id=43 + ) + + cells = list(bu.get_all_cells().items()) + assert len(cells) == 1 + assert cells[0][0] == 42 # default bounding_cell_id is 10000 + assert cells[0][1].id == 42 # default bounding_cell_id is 10000 + surfaces = list(cells[0][1].region.get_surfaces().items()) + assert surfaces[0][1].type == 'sphere' + assert surfaces[0][1].id == 43 From 3ff11280a11f71385360fd1c04ad5bcaec0ba04b Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:26:12 -0500 Subject: [PATCH 0809/2654] documentation fix tally.h Co-authored-by: Patrick Shriwise --- include/openmc/tallies/tally.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h index 46284dea2..bc7ecaa92 100644 --- a/include/openmc/tallies/tally.h +++ b/include/openmc/tallies/tally.h @@ -47,7 +47,8 @@ public: void set_nuclides(const vector& nuclides); - const vector& filters() const { return filters_; } // returns vector of inidices corresponding to the tally this is called on + //! returns vector of indices corresponding to the tally this is called on + const vector& filters() const { return filters_; } int32_t filters(int i) const { return filters_[i]; } // i corresponds to the index of the filter for this tally From 6ef62fcaf100895defa6cc72904beae76b929d4c Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:26:29 -0500 Subject: [PATCH 0810/2654] documentation fix tally.h Co-authored-by: Patrick Shriwise --- include/openmc/tallies/tally.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h index bc7ecaa92..3cead91dc 100644 --- a/include/openmc/tallies/tally.h +++ b/include/openmc/tallies/tally.h @@ -50,7 +50,8 @@ public: //! returns vector of indices corresponding to the tally this is called on const vector& filters() const { return filters_; } - int32_t filters(int i) const { return filters_[i]; } // i corresponds to the index of the filter for this tally + //! \brief Returns the tally filter at index i + int32_t filters(int i) const { return filters_[i]; } void set_filters(gsl::span filters); From 373049601802b7567bedb719aaeef687aa6aee96 Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:26:50 -0500 Subject: [PATCH 0811/2654] documentation fix tally.cpp Co-authored-by: Patrick Shriwise --- src/tallies/tally.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 0df00bbe7..72c4fa4fe 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -46,8 +46,7 @@ namespace openmc { //============================================================================== namespace model { -// map: key (tally ID) to value (tally index) -// index coresponds to the tally ID's position in the tallies vector +//! a mapping of tally ID to index in the tallies vector std::unordered_map tally_map; vector> tallies; vector active_tallies; From 22e23374dd2433903168dc5c09c9fc603c293527 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:38:45 -0500 Subject: [PATCH 0812/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- docs/source/pythonapi/deplete.rst | 2 +- openmc/deplete/openmc_operator.py | 1 - tests/regression_tests/deplete_no_transport/test.py | 4 +--- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index 4154e35df..dd679a40a 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -43,7 +43,7 @@ algorithms `_. SILEQIIntegrator Each of these classes expects a "transport operator" to be passed. OpenMC -provides The following classes implement transport operators: +provides the following transport operator classes: .. autosummary:: :toctree: generated diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index c34065078..ee569bf71 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -534,7 +534,6 @@ class OpenMCOperator(TransportOperator): rates[i] = self._rate_helper.divide_by_adens(number) # Scale reaction rates to obtain units of reactions/sec - print(f"flux, power, or source rate: {self._normalization_helper.factor(source_rate)}") rates *= self._normalization_helper.factor(source_rate) # Store new fission yields on the chain diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index bf4a4b132..f5ee4bf1d 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -23,9 +23,7 @@ def fuel(): @pytest.fixture(scope="module") def micro_xs(): micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' - micro_xs = MicroXS.from_csv(micro_xs_file) - - return micro_xs + return MicroXS.from_csv(micro_xs_file) @pytest.fixture(scope="module") def chain_file(): From 30b1ae92cb0056cbf6e9084aa3c6f41b30c9898e Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 11 Aug 2022 13:45:28 -0500 Subject: [PATCH 0813/2654] changed name and return type. added signature to capi.h. TODO error handling in tally.cpp --- include/openmc/capi.h | 1 + src/tallies/tally.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/openmc/capi.h b/include/openmc/capi.h index 69d3ff1f6..e04d4898e 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -118,6 +118,7 @@ int openmc_regular_mesh_get_params( int openmc_regular_mesh_set_dimension(int32_t index, int n, const int* dims); int openmc_regular_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, const double* width); +int openmc_remove_tally(int32_t id); int openmc_reset(); int openmc_reset_timers(); int openmc_run(); diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 72c4fa4fe..8d54570ef 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1273,12 +1273,13 @@ extern "C" size_t tallies_size() } // given a tally ID, remove it from the tallies vector -extern "C" void openmc_remove_tally_from_tallies(int32_t id) +extern "C" int openmc_remove_tally(int32_t id) { // query map for index corersponding to the given id int32_t index = model::tally_map[id]; // delete the tally via iterator pointing to correct position model::tallies.erase(model::tallies.begin() + index); + return 0; } } // namespace openmc From 4faaa4062b76069a03956137927b45b1073f9d1e Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 11 Aug 2022 14:03:21 -0500 Subject: [PATCH 0814/2654] moved test out of python API into C++ API. modeled after test that adds a new tally. TODO add a test that tries to delete an invalid ID --- tests/unit_tests/test_lib.py | 14 ++++++++++++++ tests/unit_tests/test_tallies.py | 5 +---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index b57242983..225415e56 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -339,6 +339,20 @@ def test_new_tally(lib_init): new_tally_with_id.scores = ['flux'] assert len(openmc.lib.tallies) == 5 +def test_add_and_delete_tally(lib_init): + with pytest.raises(exc.AllocationError): + openmc.lib.Material(1) + new_tally = openmc.lib.Tally() + new_tally.scores = ['flux'] + new_tally_with_id = openmc.lib.Tally(10) + new_tally_with_id.scores = ['flux'] + assert len(openmc.lib.tallies) == 5 + # delete tally and check length is one less than before + openmc_remove_tally(10) + assert len(openmc.lib.tallies) == 4 + +# def test_delete_wrong_id(): + def test_tally_activate(lib_simulation_init): t = openmc.lib.tallies[1] diff --git a/tests/unit_tests/test_tallies.py b/tests/unit_tests/test_tallies.py index 77aef78b4..14319a0a2 100644 --- a/tests/unit_tests/test_tallies.py +++ b/tests/unit_tests/test_tallies.py @@ -38,7 +38,4 @@ def test_xml_roundtrip(run_in_tmpdir): assert len(new_tally.triggers) == 1 assert new_tally.triggers[0].trigger_type == tally.triggers[0].trigger_type assert new_tally.triggers[0].threshold == tally.triggers[0].threshold - assert new_tally.triggers[0].scores == tally.triggers[0].scores - # delete tally and check that new_tallies now has length zero - new_tally.openmc_remove_tally_from_tallies(tally.id) - assert len(new_tallies) == 0 \ No newline at end of file + assert new_tally.triggers[0].scores == tally.triggers[0].scores \ No newline at end of file From fd2ae7811a30bcc293f488514168dad4ead42ec2 Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Thu, 11 Aug 2022 14:05:23 -0500 Subject: [PATCH 0815/2654] use safer .at(id) Co-authored-by: Patrick Shriwise --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 8d54570ef..e3baaea91 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1276,7 +1276,7 @@ extern "C" size_t tallies_size() extern "C" int openmc_remove_tally(int32_t id) { // query map for index corersponding to the given id - int32_t index = model::tally_map[id]; + int32_t index = model::tally_map.at(id); // delete the tally via iterator pointing to correct position model::tallies.erase(model::tallies.begin() + index); return 0; From bce2c2384a63aba00ab4b999d6c38927ffe2cd43 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 11 Aug 2022 14:14:09 -0500 Subject: [PATCH 0816/2654] added error checking to ensure ID is in map before erasing. also removes the key/value pair from the map after deleting the tally --- src/tallies/tally.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index e3baaea91..1c1b978a1 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1275,11 +1275,17 @@ extern "C" size_t tallies_size() // given a tally ID, remove it from the tallies vector extern "C" int openmc_remove_tally(int32_t id) { + // check that id is in the map + if (!model::tally_map.contains(id)) { + return OPENMC_INVALID_ID; + } // query map for index corersponding to the given id int32_t index = model::tally_map.at(id); // delete the tally via iterator pointing to correct position model::tallies.erase(model::tallies.begin() + index); - return 0; + + // after erasing tally, remove id from map + model::tally_map.remove(id) return 0; } } // namespace openmc From 03806675c9701ba9eeb7eaad65445f1a114dc2cb Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 11 Aug 2022 14:32:58 -0500 Subject: [PATCH 0817/2654] forgot semicolon --- src/tallies/tally.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 1c1b978a1..1613bd318 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1285,7 +1285,8 @@ extern "C" int openmc_remove_tally(int32_t id) model::tallies.erase(model::tallies.begin() + index); // after erasing tally, remove id from map - model::tally_map.remove(id) return 0; + model::tally_map.erase(id); + return 0; } } // namespace openmc From 21f7cda6bc7039975d5c600e0c965850a1c4b181 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 11 Aug 2022 14:50:57 -0500 Subject: [PATCH 0818/2654] changed return type to match signature change --- openmc/lib/tally.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index d839d6ddc..07989d558 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -88,7 +88,7 @@ _dll.openmc_tally_set_writable.argtypes = [c_int32, c_bool] _dll.openmc_tally_set_writable.restype = c_int _dll.openmc_tally_set_writable.errcheck = _error_handler _dll.openmc_remove_tally_from_tallies.argtypes = [c_int32] -_dll.openmc_remove_tally_from_tallies.restype = None +_dll.openmc_remove_tally_from_tallies.restype = c_int _dll.openmc_remove_tally_from_tallies.errcheck = _error_handler _dll.tallies_size.restype = c_size_t From 5af0d291a1fc423d8c0a6aef9762fc344640aa3a Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 11 Aug 2022 15:14:07 -0500 Subject: [PATCH 0819/2654] style fix on constant --- openmc/deplete/microxs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 71e476c2c..96a5e9dbd 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -146,7 +146,7 @@ class MicroXS(DataFrame): for material in model.materials: if material.depletable: nuc_densities = material.get_nuclide_atom_densities() - dilute_density = 1.e-24 * dilute_initial + dilute_density = 1.0e-24 * dilute_initial material.set_density('sum') for nuc, density in nuc_densities.items(): material.remove_nuclide(nuc) From 3c483a7d7df53703381d1bb3ca3b30fc9e5c939c Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 11 Aug 2022 17:25:28 -0500 Subject: [PATCH 0820/2654] add run_kwargs parameter to MicroXS.from_model() --- openmc/deplete/microxs.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 96a5e9dbd..05831fb1a 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -35,7 +35,8 @@ class MicroXS(DataFrame): reaction_domain, chain_file, dilute_initial=1.0e3, - energy_bounds=(0, 20e6)): + energy_bounds=(0, 20e6), + run_kwargs=None): """Generate a one-group cross-section dataframe using OpenMC. Note that the ``openmc`` executable must be compiled. @@ -57,6 +58,8 @@ class MicroXS(DataFrame): Reaction names to tally energy_bound : 2-tuple of float, optional Bounds for the energy group. + run_kwargs : dict, optional + Keyword arguments for :meth:`openmc.model.Model.run()` Returns ------- @@ -89,7 +92,12 @@ class MicroXS(DataFrame): # create temporary run with tempfile.TemporaryDirectory() as temp_dir: - statepoint_path = model.run(cwd=temp_dir) + if run_kwargs is None: + run_kwargs = {} + model.init_lib() + elif 'cwd' in run_kwargs: + run_kwargs.pop('cwd') + statepoint_path = model.run(cwd=temp_dir, **run_kwargs) with StatePoint(statepoint_path) as sp: for rx in xs: From f8d87b1bb30a667d8b2799c18f1e3ac5f4ffae07 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 11 Aug 2022 20:29:02 -0500 Subject: [PATCH 0821/2654] typo in return type --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 1613bd318..3e255302e 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1277,7 +1277,7 @@ extern "C" int openmc_remove_tally(int32_t id) { // check that id is in the map if (!model::tally_map.contains(id)) { - return OPENMC_INVALID_ID; + return OPENMC_E_INVALID_ID; } // query map for index corersponding to the given id int32_t index = model::tally_map.at(id); From 84359e334040b163cd692fe895f616cba5cedd86 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 11 Aug 2022 20:57:23 -0500 Subject: [PATCH 0822/2654] apparently count does not exist in c++11 which the github test system is using, so I will use the older trick of checking whether count equals 0 or 1 to determine if the id exists as a key --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 3e255302e..73d7ae14c 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1276,7 +1276,7 @@ extern "C" size_t tallies_size() extern "C" int openmc_remove_tally(int32_t id) { // check that id is in the map - if (!model::tally_map.contains(id)) { + if (model::tally_map.count(id)!=1) { return OPENMC_E_INVALID_ID; } // query map for index corersponding to the given id From 623b86703391b72712ced5aa9a8ec3cea6513f57 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 12 Aug 2022 10:43:40 +0100 Subject: [PATCH 0823/2654] updated path for dagmc file --- tests/unit_tests/test_dagmc_universe.py | 57 ++++++++++++++----------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/tests/unit_tests/test_dagmc_universe.py b/tests/unit_tests/test_dagmc_universe.py index 945d39d9b..9904fa03b 100644 --- a/tests/unit_tests/test_dagmc_universe.py +++ b/tests/unit_tests/test_dagmc_universe.py @@ -1,50 +1,58 @@ import openmc import pytest +from pathlib import Path def test_bounding_box(): + """Checks that the DAGMCUniverse.bounding_box returns the correct values""" - u = openmc.DAGMCUniverse("tests/regression_tests/dagmc/universes/dagmc.h5m") + u = openmc.DAGMCUniverse(str(Path(__file__).parent.resolve() / "dagmc/dagmc.h5m")) ll, ur = u.bounding_box - assert ll == pytest.approx((-25., -25., -25)) - assert ur == pytest.approx((25., 25., 25)) + assert ll == pytest.approx((-25.0, -25.0, -25)) + assert ur == pytest.approx((25.0, 25.0, 25)) def test_bounding_region(): + """Checks that the DAGMCUniverse.bounding_region() returns a region with + correct surfaces and boundary types""" - u = openmc.DAGMCUniverse("tests/regression_tests/dagmc/universes/dagmc.h5m") + u = openmc.DAGMCUniverse(str(Path(__file__).parent.resolve() / "dagmc/dagmc.h5m")) region = u.bounding_region() # should default to bounded_type='box' assert isinstance(region, openmc.Region) assert len(region) == 6 - assert region[0].surface.type == 'x-plane' - assert region[1].surface.type == 'x-plane' - assert region[2].surface.type == 'y-plane' - assert region[3].surface.type == 'y-plane' - assert region[4].surface.type == 'z-plane' - assert region[5].surface.type == 'z-plane' - assert region[0].surface.boundary_type == 'vacuum' - assert region[1].surface.boundary_type == 'vacuum' - assert region[2].surface.boundary_type == 'vacuum' - assert region[3].surface.boundary_type == 'vacuum' - assert region[4].surface.boundary_type == 'vacuum' - assert region[5].surface.boundary_type == 'vacuum' + assert region[0].surface.type == "x-plane" + assert region[1].surface.type == "x-plane" + assert region[2].surface.type == "y-plane" + assert region[3].surface.type == "y-plane" + assert region[4].surface.type == "z-plane" + assert region[5].surface.type == "z-plane" + assert region[0].surface.boundary_type == "vacuum" + assert region[1].surface.boundary_type == "vacuum" + assert region[2].surface.boundary_type == "vacuum" + assert region[3].surface.boundary_type == "vacuum" + assert region[4].surface.boundary_type == "vacuum" + assert region[5].surface.boundary_type == "vacuum" - region = u.bounding_region(bounded_type='sphere', boundary_type='reflective') + region = u.bounding_region(bounded_type="sphere", boundary_type="reflective") assert isinstance(region, openmc.Region) assert isinstance(region, openmc.Halfspace) - assert region.surface.type == 'sphere' - assert region.surface.boundary_type == 'reflective' + assert region.surface.type == "sphere" + assert region.surface.boundary_type == "reflective" + def test_bounded_universe(): + """Checks that the DAGMCUniverse.bounded_universe() returns a + openmc.Universe with correct surface ids and cell ids""" - u = openmc.DAGMCUniverse("tests/regression_tests/dagmc/universes/dagmc.h5m") + u = openmc.DAGMCUniverse(str(Path(__file__).parent.resolve() / "dagmc/dagmc.h5m")) # bounded with defaults bu = u.bounded_universe() cells = list(bu.get_all_cells().items()) + assert isinstance(bu, openmc.Universe) assert len(cells) == 1 assert cells[0][0] == 10000 # default bounding_cell_id is 10000 assert cells[0][1].id == 10000 # default bounding_cell_id is 10000 @@ -53,16 +61,13 @@ def test_bounded_universe(): assert surfaces[0][1].id == 10000 # bounded with non defaults - bu = u.bounded_universe( - bounding_cell_id=42, - bounded_type='sphere', - starting_id=43 - ) + bu = u.bounded_universe(bounding_cell_id=42, bounded_type="sphere", starting_id=43) cells = list(bu.get_all_cells().items()) + assert isinstance(bu, openmc.Universe) assert len(cells) == 1 assert cells[0][0] == 42 # default bounding_cell_id is 10000 assert cells[0][1].id == 42 # default bounding_cell_id is 10000 surfaces = list(cells[0][1].region.get_surfaces().items()) - assert surfaces[0][1].type == 'sphere' + assert surfaces[0][1].type == "sphere" assert surfaces[0][1].id == 43 From d47f41637f76f5ed81976d5c4c9a1027c8c6e320 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 12 Aug 2022 07:53:36 -0500 Subject: [PATCH 0824/2654] Some updates to DAGMC testing. --- openmc/universe.py | 4 ++-- tests/regression_tests/dagmc/legacy/test.py | 3 ++- .../regression_tests/dagmc/universes/test.py | 22 ------------------- .../test_bounds.py} | 12 +++++----- 4 files changed, 10 insertions(+), 31 deletions(-) rename tests/unit_tests/{test_dagmc_universe.py => dagmc/test_bounds.py} (87%) diff --git a/openmc/universe.py b/openmc/universe.py index 727e7a096..65bcce747 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -678,8 +678,8 @@ class DAGMCUniverse(UniverseBase): @filename.setter def filename(self, val): - cv.check_type('DAGMC filename', val, str) - self._filename = val + cv.check_type('DAGMC filename', val, (Path, str)) + self._filename = str(val) @property def auto_geom_ids(self): diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index e0fccb934..dacbc19ee 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -1,6 +1,7 @@ import openmc import openmc.lib +from pathlib import Path import pytest from tests.testing_harness import PyAPITestHarness @@ -27,7 +28,7 @@ def model(): model.settings.dagmc = True # geometry - dag_univ = openmc.DAGMCUniverse("dagmc.h5m") + dag_univ = openmc.DAGMCUniverse(Path("dagmc.h5m")) model.geometry = openmc.Geometry(dag_univ) # tally diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 67c8f962d..47897ad56 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -53,28 +53,6 @@ class DAGMCUniverseTest(PyAPITestHarness): # assigns the bound_dag_geometry to the model to test the type checks in model.Geometry setter model.Geometry = bound_pincell_geometry - # checks that the bounding box is calculated correctly - bounding_box = pincell_univ.bounding_box - assert bounding_box[0].tolist() == [-25., -25., -25.] - assert bounding_box[1].tolist() == [25., 25., 25.] - - # checks that the bounding region is six surfaces each with a vacuum boundary type - b_region = pincell_univ.bounding_region(bounded_type='box', boundary_type='vacuum') - assert isinstance(b_region, openmc.Region) - assert len(b_region.get_surfaces()) == 6 - starting_id = 10000 - for i, surface in enumerate(b_region.get_surfaces().values()): - assert surface.boundary_type == 'vacuum' - assert surface.id == 10000 + i - - # checks that the bounding region is a single surface with a reflective boundary type - b_region = pincell_univ.bounding_region(bounded_type='sphere', boundary_type='reflective') - assert isinstance(b_region, openmc.Region) - assert len(b_region.get_surfaces()) == 1 - for surface in list(b_region.get_surfaces().values()): - assert surface.boundary_type == 'reflective' - assert surface.id == 10000 - # create a 2 x 2 lattice using the DAGMC pincell pitch = np.asarray((24.0, 24.0)) lattice = openmc.RectLattice() diff --git a/tests/unit_tests/test_dagmc_universe.py b/tests/unit_tests/dagmc/test_bounds.py similarity index 87% rename from tests/unit_tests/test_dagmc_universe.py rename to tests/unit_tests/dagmc/test_bounds.py index 9904fa03b..dbca3ca25 100644 --- a/tests/unit_tests/test_dagmc_universe.py +++ b/tests/unit_tests/dagmc/test_bounds.py @@ -3,21 +3,21 @@ import pytest from pathlib import Path -def test_bounding_box(): +def test_bounding_box(request): """Checks that the DAGMCUniverse.bounding_box returns the correct values""" - u = openmc.DAGMCUniverse(str(Path(__file__).parent.resolve() / "dagmc/dagmc.h5m")) + u = openmc.DAGMCUniverse(Path(request.fspath).parent / "dagmc.h5m") ll, ur = u.bounding_box assert ll == pytest.approx((-25.0, -25.0, -25)) assert ur == pytest.approx((25.0, 25.0, 25)) -def test_bounding_region(): +def test_bounding_region(request): """Checks that the DAGMCUniverse.bounding_region() returns a region with correct surfaces and boundary types""" - u = openmc.DAGMCUniverse(str(Path(__file__).parent.resolve() / "dagmc/dagmc.h5m")) + u = openmc.DAGMCUniverse(Path(request.fspath).parent / "dagmc.h5m") region = u.bounding_region() # should default to bounded_type='box' assert isinstance(region, openmc.Region) @@ -42,11 +42,11 @@ def test_bounding_region(): assert region.surface.boundary_type == "reflective" -def test_bounded_universe(): +def test_bounded_universe(request): """Checks that the DAGMCUniverse.bounded_universe() returns a openmc.Universe with correct surface ids and cell ids""" - u = openmc.DAGMCUniverse(str(Path(__file__).parent.resolve() / "dagmc/dagmc.h5m")) + u = openmc.DAGMCUniverse(Path(request.fspath).parent / "dagmc.h5m") # bounded with defaults bu = u.bounded_universe() From 1124bffb4b6749f6d2ed50f7d1d498c26253ff0a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 12 Aug 2022 07:55:50 -0500 Subject: [PATCH 0825/2654] Leave dagmc filename as Path object until writing the XML file --- openmc/universe.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 65bcce747..4aa1775fb 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -679,7 +679,7 @@ class DAGMCUniverse(UniverseBase): @filename.setter def filename(self, val): cv.check_type('DAGMC filename', val, (Path, str)) - self._filename = str(val) + self._filename = val @property def auto_geom_ids(self): @@ -720,7 +720,7 @@ class DAGMCUniverse(UniverseBase): dagmc_element.set('auto_geom_ids', 'true') if self.auto_mat_ids: dagmc_element.set('auto_mat_ids', 'true') - dagmc_element.set('filename', self.filename) + dagmc_element.set('filename', str(self.filename)) xml_element.append(dagmc_element) def bounding_region(self, bounded_type='box', boundary_type='vacuum', starting_id=10000): From 74e093ae456349798b8b2e7f666aba593a23a811 Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Fri, 12 Aug 2022 10:55:21 -0500 Subject: [PATCH 0826/2654] renamed function and forgot to update these commands Co-authored-by: Paul Romano --- openmc/lib/tally.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index 07989d558..534e6ebaa 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -87,9 +87,9 @@ _dll.openmc_tally_set_type.errcheck = _error_handler _dll.openmc_tally_set_writable.argtypes = [c_int32, c_bool] _dll.openmc_tally_set_writable.restype = c_int _dll.openmc_tally_set_writable.errcheck = _error_handler -_dll.openmc_remove_tally_from_tallies.argtypes = [c_int32] -_dll.openmc_remove_tally_from_tallies.restype = c_int -_dll.openmc_remove_tally_from_tallies.errcheck = _error_handler +_dll.openmc_remove_tally.argtypes = [c_int32] +_dll.openmc_remove_tally.restype = c_int +_dll.openmc_remove_tally.errcheck = _error_handler _dll.tallies_size.restype = c_size_t From 7d429ab45e0092d433c3b3f80da4ec351b9699de Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Fri, 12 Aug 2022 12:58:37 -0500 Subject: [PATCH 0827/2654] pass index instead of ID to remove tally from tallies and tally_map --- src/tallies/tally.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 73d7ae14c..8f0f254e0 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1273,19 +1273,18 @@ extern "C" size_t tallies_size() } // given a tally ID, remove it from the tallies vector -extern "C" int openmc_remove_tally(int32_t id) +extern "C" int openmc_remove_tally(int32_t index) { // check that id is in the map - if (model::tally_map.count(id)!=1) { - return OPENMC_E_INVALID_ID; + if (index <= 0 || index > model::tallies.size()) { + return OPENMC_E_OUT_OF_BOUNDS; } - // query map for index corersponding to the given id - int32_t index = model::tally_map.at(id); + // grab tally so it's ID can be obtained to remove the (ID,index) pair from tally_map + auto& tally = model::tallies[index]; + model::tally_map.erase(tally->id_); // delete the tally via iterator pointing to correct position model::tallies.erase(model::tallies.begin() + index); - // after erasing tally, remove id from map - model::tally_map.erase(id); return 0; } From 88c4f88abd13e929eab48325a8f13b97c86ed7a5 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Fri, 12 Aug 2022 13:02:04 -0500 Subject: [PATCH 0828/2654] accidentally had <= when it should be strictly < --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 8f0f254e0..f45fae994 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1276,7 +1276,7 @@ extern "C" size_t tallies_size() extern "C" int openmc_remove_tally(int32_t index) { // check that id is in the map - if (index <= 0 || index > model::tallies.size()) { + if (index < 0 || index > model::tallies.size()) { return OPENMC_E_OUT_OF_BOUNDS; } // grab tally so it's ID can be obtained to remove the (ID,index) pair from tally_map From 9d82e412da19b83cda05106dceceb0df8fad8c32 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Fri, 12 Aug 2022 13:24:29 -0500 Subject: [PATCH 0829/2654] added test to delete known tally. added test to throw an error if you remove tally that was not added --- tests/unit_tests/test_lib.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index 225415e56..96d54c416 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -339,19 +339,16 @@ def test_new_tally(lib_init): new_tally_with_id.scores = ['flux'] assert len(openmc.lib.tallies) == 5 -def test_add_and_delete_tally(lib_init): - with pytest.raises(exc.AllocationError): - openmc.lib.Material(1) - new_tally = openmc.lib.Tally() - new_tally.scores = ['flux'] - new_tally_with_id = openmc.lib.Tally(10) - new_tally_with_id.scores = ['flux'] - assert len(openmc.lib.tallies) == 5 - # delete tally and check length is one less than before - openmc_remove_tally(10) +def test_delete_tally(lib_init): + # delete tally 10 which was added in the above test + # check length is one less than before + openmc.lib.openmc_remove_tally(openmc.lib.get_tally_index(10)) assert len(openmc.lib.tallies) == 4 -# def test_delete_wrong_id(): +def test_delete_invalid_id(lib_init): + # attempt to delete a tally that is guaranteed not to have a valid index + with pytest.raises(exc.InvalidIDError): + openmc.lib.openmc_remove_tally(np.max(id)+1) def test_tally_activate(lib_simulation_init): From d1775181e905054677d904acb9f4a652d0195325 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Fri, 12 Aug 2022 15:49:08 -0500 Subject: [PATCH 0830/2654] added deletion operator to TallyMapping class. used in tests and changed delete invalid id to access invalid id --- openmc/lib/tally.py | 22 +++++++++++++++------- tests/unit_tests/test_lib.py | 13 ++++++++----- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index 534e6ebaa..c1c8ab094 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -390,13 +390,7 @@ class Tally(_FortranObjectWithID): class _TallyMapping(Mapping): def __getitem__(self, key): - index = c_int32() - try: - _dll.openmc_get_tally_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return Tally(index=index.value) + return Tally(index=self._get_tally_index(key)) def __iter__(self): for i in range(len(self)): @@ -408,4 +402,18 @@ class _TallyMapping(Mapping): def __repr__(self): return repr(dict(self)) + def __delitem__(self,key): + """Delete a tally from tally vector and remove the ID,index pair from tally""" + _dll.openmc_remove_tally(self._get_tally_index(key)) + + def _get_tally_index(self,key): + """Given the ID, return the index""" + index = c_int32() + try: + _dll.openmc_get_tally_index(key, index) + except (AllocationError, InvalidIDError) as e: + # __contains__ expects a KeyError to work correctly + raise KeyError(str(e)) + return index.value + tallies = _TallyMapping() diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index 96d54c416..5063646f7 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -339,16 +339,19 @@ def test_new_tally(lib_init): new_tally_with_id.scores = ['flux'] assert len(openmc.lib.tallies) == 5 + def test_delete_tally(lib_init): # delete tally 10 which was added in the above test # check length is one less than before - openmc.lib.openmc_remove_tally(openmc.lib.get_tally_index(10)) + del openmc.lib.tallies[10] assert len(openmc.lib.tallies) == 4 -def test_delete_invalid_id(lib_init): - # attempt to delete a tally that is guaranteed not to have a valid index - with pytest.raises(exc.InvalidIDError): - openmc.lib.openmc_remove_tally(np.max(id)+1) + +def test_invalid_tally_id(lib_init): + # attempt to access a tally that is guaranteed not to have a valid index + max_id = max(openmc.lib.tallies.keys()) + with pytest.raises(KeyError): + openmc.lib.tallies[max_id+1] def test_tally_activate(lib_simulation_init): From ecd0455b0647fb9a872616fbb43195cee203a957 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 13 Aug 2022 12:32:14 +0100 Subject: [PATCH 0831/2654] added vtk writing to tracks object --- openmc/tracks.py | 49 +++++++++++++++++++++++++++++++++ tests/unit_tests/test_tracks.py | 14 ++++++++++ 2 files changed, 63 insertions(+) diff --git a/openmc/tracks.py b/openmc/tracks.py index e9097e8ee..4b4ecc4f2 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -266,6 +266,55 @@ class Tracks(list): track.plot(ax) return ax + def write_tracks_to_vtk(self, filename): + """Creates a VTK file of the tracks + + Parameters + ---------- + filename : str + Name of the VTK file to write. + + Returns + ------- + vtk.vtkStructuredGrid + the VTK object + """ + + import vtk + + # Initialize data arrays and offset. + points = vtk.vtkPoints() + cells = vtk.vtkCellArray() + + for particle in self: + for state in particle.states: + points.InsertNextPoint(state['r']) + + # Create VTK line and assign points to line. + n = particle.states.size + line = vtk.vtkPolyLine() + line.GetPointIds().SetNumberOfIds(n) + for i in range(n): + line.GetPointIds().SetId(i, point_offset + i) + point_offset += n + + # Add line to cell array + cells.InsertNextCell(line) + + data = vtk.vtkPolyData() + data.SetPoints(points) + data.SetLines(cells) + + writer = vtk.vtkXMLPPolyDataWriter() + if vtk.vtkVersion.GetVTKMajorVersion() > 5: + writer.SetInputData(data) + else: + writer.SetInput(data) + writer.SetFileName(filename) + writer.Write() + + return filename + @staticmethod def combine(track_files, path='tracks.h5'): """Combine multiple track files into a single track file diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index e18015d81..bb1210d2e 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -141,3 +141,17 @@ def test_filter(sphere_model, run_in_tmpdir): assert matches == tracks matches = tracks.filter(particle='bunnytron') assert matches == [] + +def test_write_tracks_to_vtk(): + # Set maximum number of tracks per process to write + sphere_model.settings.max_tracks = 25 + sphere_model.settings.photon_transport = True + + # Run OpenMC to generate tracks.h5 file + generate_track_file(sphere_model, tracks=True) + + tracks = openmc.Tracks('tracks.h5') + filename = tracks.write_tracks_to_vtk('tracks.vtk') + + assert filename == 'tracks.vtk' + assert Path('tracks.vtk').is_file() From d15c051263510e6c81042228c35786921a1ddba0 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 13 Aug 2022 12:34:17 +0100 Subject: [PATCH 0832/2654] added missing arg --- tests/unit_tests/test_tracks.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index bb1210d2e..d2548be64 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -142,7 +142,8 @@ def test_filter(sphere_model, run_in_tmpdir): matches = tracks.filter(particle='bunnytron') assert matches == [] -def test_write_tracks_to_vtk(): + +def test_write_tracks_to_vtk(sphere_model): # Set maximum number of tracks per process to write sphere_model.settings.max_tracks = 25 sphere_model.settings.photon_transport = True From f8101006d821abc109df45092088d5d8ce9794e2 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Sat, 13 Aug 2022 10:20:19 -0500 Subject: [PATCH 0833/2654] remove `init_lib()` call in `MicroXS.from_model()`; use `setdefault` to ensure correct directory is used Co-authored-by: Paul Romano --- openmc/deplete/microxs.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 05831fb1a..ccbfab538 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -94,10 +94,8 @@ class MicroXS(DataFrame): with tempfile.TemporaryDirectory() as temp_dir: if run_kwargs is None: run_kwargs = {} - model.init_lib() - elif 'cwd' in run_kwargs: - run_kwargs.pop('cwd') - statepoint_path = model.run(cwd=temp_dir, **run_kwargs) + run_kwargs.setdefault('cwd', temp_dir) + statepoint_path = model.run(**run_kwargs) with StatePoint(statepoint_path) as sp: for rx in xs: From 2263549b9b59f9b49929c417c3e8ae1111d8bef4 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 15 Aug 2022 13:22:44 +0100 Subject: [PATCH 0834/2654] producing vtp vtk files --- openmc/tracks.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/tracks.py b/openmc/tracks.py index 4b4ecc4f2..076ffc78d 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -266,7 +266,7 @@ class Tracks(list): track.plot(ax) return ax - def write_tracks_to_vtk(self, filename): + def write_tracks_to_vtk(self, filename='tracks.vtk'): """Creates a VTK file of the tracks Parameters @@ -286,12 +286,14 @@ class Tracks(list): points = vtk.vtkPoints() cells = vtk.vtkCellArray() + point_offset = 0 for particle in self: - for state in particle.states: - points.InsertNextPoint(state['r']) + for pt in particle.particle_tracks: + for state in pt.states: + points.InsertNextPoint(state['r']) # Create VTK line and assign points to line. - n = particle.states.size + n = pt.states.size line = vtk.vtkPolyLine() line.GetPointIds().SetNumberOfIds(n) for i in range(n): From 21b874f0be55d61f434397c7ff745e9fb2f97999 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 15 Aug 2022 13:39:47 +0100 Subject: [PATCH 0835/2654] review suggestions from @paulromano --- openmc/tracks.py | 16 +++++++------- scripts/openmc-track-to-vtk | 42 +++++-------------------------------- 2 files changed, 13 insertions(+), 45 deletions(-) diff --git a/openmc/tracks.py b/openmc/tracks.py index 076ffc78d..55a5fb060 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -6,7 +6,7 @@ import h5py from .checkvalue import check_filetype_version from .source import SourceParticle, ParticleType - +from pathlib import Path ParticleTrack = namedtuple('ParticleTrack', ['particle', 'states']) ParticleTrack.__doc__ = """\ Particle track information @@ -266,18 +266,18 @@ class Tracks(list): track.plot(ax) return ax - def write_tracks_to_vtk(self, filename='tracks.vtk'): - """Creates a VTK file of the tracks + def write_tracks_to_vtk(self, filename=Path('tracks.vtk')): + """Creates a VTP file of the tracks Parameters ---------- - filename : str + filename : path-like Name of the VTK file to write. Returns ------- - vtk.vtkStructuredGrid - the VTK object + vtk.vtkPolyData + the VTK vtkPolyData object produced """ import vtk @@ -312,10 +312,10 @@ class Tracks(list): writer.SetInputData(data) else: writer.SetInput(data) - writer.SetFileName(filename) + writer.SetFileName(str(filename)) # SetFileName requires a string writer.Write() - return filename + return data @staticmethod def combine(track_files, path='tracks.h5'): diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index 3b3507974..118e65827 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -14,8 +14,8 @@ def _parse_args(): # Create argument parser. parser = argparse.ArgumentParser( description='Convert particle track file(s) to a .pvtp file.') - parser.add_argument('input', metavar='IN', type=str, nargs='+', - help='Input particle track data filename(s).') + parser.add_argument('input', metavar='IN', type=str, + help='Input particle track data filename.') parser.add_argument('-o', '--out', metavar='OUT', type=str, dest='out', help='Output VTK poly data filename.') @@ -33,41 +33,9 @@ def main(): elif not args.out.endswith('.pvtp'): args.out += '.pvtp' - # Initialize data arrays and offset. - points = vtk.vtkPoints() - cells = vtk.vtkCellArray() - point_offset = 0 - for fname in args.input: - # Write coordinate values to points array. - track_file = openmc.Tracks(fname) - for track in track_file: - for particle in track: - for state in particle.states: - points.InsertNextPoint(state['r']) - - # Create VTK line and assign points to line. - n = particle.states.size - line = vtk.vtkPolyLine() - line.GetPointIds().SetNumberOfIds(n) - for i in range(n): - line.GetPointIds().SetId(i, point_offset + i) - point_offset += n - - # Add line to cell array - cells.InsertNextCell(line) - - data = vtk.vtkPolyData() - data.SetPoints(points) - data.SetLines(cells) - - writer = vtk.vtkXMLPPolyDataWriter() - if vtk.vtkVersion.GetVTKMajorVersion() > 5: - writer.SetInputData(data) - else: - writer.SetInput(data) - writer.SetFileName(args.out) - writer.Write() - + # Write coordinate values to points array. + track_file = openmc.Tracks(args.input) + track_file.write_tracks_to_vtk(args.out) if __name__ == '__main__': main() From 9847d053f35c62c8c5e73d702e938c6a2f9f8db0 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 15 Aug 2022 13:40:56 +0100 Subject: [PATCH 0836/2654] changed vtk file to vtp --- openmc/tracks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/tracks.py b/openmc/tracks.py index 55a5fb060..213a0867e 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -272,7 +272,7 @@ class Tracks(list): Parameters ---------- filename : path-like - Name of the VTK file to write. + Name of the VTP file to write. Returns ------- From 809863c15ca760a708b62b5e844ebcb4aad2d3b7 Mon Sep 17 00:00:00 2001 From: myerspat Date: Mon, 15 Aug 2022 10:18:45 -0400 Subject: [PATCH 0837/2654] Removed second region expression so search finding relys on region_ --- include/openmc/cell.h | 9 ++------- src/cell.cpp | 45 +++++++++++++++++++++---------------------- src/geometry_aux.cpp | 2 +- src/universe.cpp | 4 ++-- 4 files changed, 27 insertions(+), 33 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 4d07b2619..0004a86c6 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -160,14 +160,12 @@ protected: //! \param[in] instance of the cell to find parent cells for //! \param[in] p particle used to do a fast search for parent cells //! \return parent cells - vector find_parent_cells( - int32_t instance, Particle& p) const; + vector find_parent_cells(int32_t instance, Particle& p) const; //! Determine the path to this cell instance in the geometry hierarchy //! \param[in] instance of the cell to find parent cells for //! \return parent cells - vector exhaustive_find_parent_cells( - int32_t instance) const; + vector exhaustive_find_parent_cells(int32_t instance) const; //! Inner function for retrieving contained cells void get_contained_cells_inner( @@ -202,9 +200,6 @@ public: //! Definition of spatial region as Boolean expression of half-spaces vector region_; - //! Revised infix notation with no complements - vector region_no_complements_; - vector rpn_; bool simple_; //!< Does the region contain only intersections? //! \brief Neighboring cells in the same universe. diff --git a/src/cell.cpp b/src/cell.cpp index 12fb9f674..8224ba266 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -108,7 +108,7 @@ vector tokenize(const std::string region_spec) } //============================================================================== -//! Add precedence for infix cell finding so intersections have higher +//! Add precedence for infix regions so intersections have higher //! precedence than unions using parenthesis. //============================================================================== @@ -165,11 +165,17 @@ void add_precedence(std::vector& infix) for (auto it = infix.begin(); it != infix.end(); it++) { int32_t token = *it; + // If the token is a union another operator has not been found set the + // current operator to union + // If the current operator is a union and the token is an intersection + // assert precedence + // If the token is a parenthesis reset the current operator if (token == OP_UNION && current_op == 0) { current_op = OP_UNION; } else if (current_op == OP_UNION && token == OP_INTERSECTION) { it = add_parenthesis(it - 1, infix); + current_op = 0; } else if (token > OP_COMPLEMENT) { current_op = 0; @@ -567,8 +573,10 @@ CSGCell::CSGCell(pugi::xml_node cell_node) region_spec = get_node_value(cell_node, "region"); } - // Get a tokenized representation of the region specification + // Get a tokenized representation of the region specification and apply De + // Morgans law region_ = tokenize(region_spec); + remove_complement_ops(region_); region_.shrink_to_fit(); // Convert user IDs to surface indices. @@ -584,33 +592,26 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } } - // Remove complement operators using De Morgan's law - region_no_complements_ = region_; - remove_complement_ops(region_no_complements_); - // Check if this is a simple cell. simple_ = true; - for (int32_t token : region_no_complements_) { + for (int32_t token : region_) { if (token == OP_UNION) { simple_ = false; + // Ensure intersections have precedence over unions + add_precedence(region_); break; } } // If this cell is simple, remove all the superfluous operator tokens. if (simple_) { - for (auto it = region_no_complements_.begin(); - it != region_no_complements_.end(); it++) { + for (auto it = region_.begin(); it != region_.end(); it++) { if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { - region_no_complements_.erase(it); + region_.erase(it); } } - } else { - // Ensure intersections have precedence over unions - add_precedence(region_no_complements_); - rpn_ = generate_rpn(id_, region_no_complements_); } - region_no_complements_.shrink_to_fit(); + region_.shrink_to_fit(); // Read the translation vector. if (check_for_node(cell_node, "translation")) { @@ -654,7 +655,7 @@ std::pair CSGCell::distance( double min_dist {INFTY}; int32_t i_surf {std::numeric_limits::max()}; - for (int32_t token : region_no_complements_) { + for (int32_t token : region_) { // Ignore this token if it corresponds to an operator rather than a region. if (token >= OP_UNION) continue; @@ -709,7 +710,7 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const BoundingBox CSGCell::bounding_box_simple() const { BoundingBox bbox; - for (int32_t token : region_no_complements_) { + for (int32_t token : region_) { bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); } return bbox; @@ -819,15 +820,14 @@ BoundingBox CSGCell::bounding_box_complex(vector rpn) BoundingBox CSGCell::bounding_box() const { - return simple_ ? bounding_box_simple() - : bounding_box_complex(rpn_); + return simple_ ? bounding_box_simple() : bounding_box_complex(region_); } //============================================================================== bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const { - for (int32_t token : region_no_complements_) { + for (int32_t token : region_) { // Assume that no tokens are operators. Evaluate the sense of particle with // respect to the surface and see if the token matches the sense. If the // particle's surface attribute is set and matches the token, that @@ -854,8 +854,7 @@ bool CSGCell::contains_complex( bool in_cell = true; // For each token - for (auto it = region_no_complements_.begin(); - it != region_no_complements_.end(); it++) { + for (auto it = region_.begin(); it != region_.end(); it++) { int32_t token = *it; // If the token is a surface evaluate the sense @@ -899,7 +898,7 @@ bool CSGCell::contains_complex( break; } } - } while (it < region_no_complements_.end() - 1); + } while (it < region_.end() - 1); } } return in_cell; diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 881af15b7..c3458d469 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -154,7 +154,7 @@ void partition_universes() // Collect the set of surfaces in this universe. std::unordered_set surf_inds; for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->region_no_complements_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) surf_inds.insert(std::abs(token) - 1); } diff --git a/src/universe.cpp b/src/universe.cpp index dc6f751c2..873d03bb7 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -98,7 +98,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find all of the z-planes in this universe. A set is used here for the // O(log(n)) insertions that will ensure entries are not repeated. for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->region_no_complements_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) { auto i_surf = std::abs(token) - 1; const auto* surf = model::surfaces[i_surf].get(); @@ -125,7 +125,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find the tokens for bounding z-planes. int32_t lower_token = 0, upper_token = 0; double min_z, max_z; - for (auto token : model::cells[i_cell]->region_no_complements_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) { const auto* surf = model::surfaces[std::abs(token) - 1].get(); if (const auto* zplane = dynamic_cast(surf)) { From 3a2d4a9138f95ec8c47f705de7d782c50137459e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 15 Aug 2022 16:05:02 +0100 Subject: [PATCH 0838/2654] suggestions from code review by @paulromano Co-authored-by: Paul Romano --- openmc/tracks.py | 3 ++- tests/unit_tests/test_tracks.py | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/tracks.py b/openmc/tracks.py index 213a0867e..671aa65cf 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -7,6 +7,7 @@ from .checkvalue import check_filetype_version from .source import SourceParticle, ParticleType from pathlib import Path + ParticleTrack = namedtuple('ParticleTrack', ['particle', 'states']) ParticleTrack.__doc__ = """\ Particle track information @@ -266,7 +267,7 @@ class Tracks(list): track.plot(ax) return ax - def write_tracks_to_vtk(self, filename=Path('tracks.vtk')): + def write_tracks_to_vtk(self, filename=Path('tracks.vtp')): """Creates a VTP file of the tracks Parameters diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index d2548be64..5f3940fad 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -144,6 +144,7 @@ def test_filter(sphere_model, run_in_tmpdir): def test_write_tracks_to_vtk(sphere_model): + vtk = pytest.importorskip('vtk') # Set maximum number of tracks per process to write sphere_model.settings.max_tracks = 25 sphere_model.settings.photon_transport = True @@ -152,7 +153,7 @@ def test_write_tracks_to_vtk(sphere_model): generate_track_file(sphere_model, tracks=True) tracks = openmc.Tracks('tracks.h5') - filename = tracks.write_tracks_to_vtk('tracks.vtk') + polydata = tracks.write_tracks_to_vtk('tracks.vtp') - assert filename == 'tracks.vtk' - assert Path('tracks.vtk').is_file() + assert isinstance(polydata, vtk.vtkPolyData) + assert Path('tracks.vtp').is_file() From 02f18152991d2d1992a71ff5feaa7f43e92d24ce Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 29 Jul 2022 10:08:33 -0500 Subject: [PATCH 0839/2654] Add missing versionadded directives --- openmc/data/kalbach_mann.py | 5 +++++ openmc/deplete/coupled_operator.py | 6 ++++++ openmc/deplete/independent_operator.py | 5 +++-- openmc/deplete/microxs.py | 8 +++++--- openmc/filter.py | 2 ++ openmc/material.py | 4 +++- openmc/region.py | 2 ++ openmc/stats/univariate.py | 2 ++ openmc/universe.py | 6 ++++++ openmc/weight_windows.py | 4 +++- 10 files changed, 37 insertions(+), 7 deletions(-) diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index a036da694..f98bb4186 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -178,6 +178,8 @@ def kalbach_slope(energy_projectile, energy_emitted, za_projectile, energies are not calculated with the AWR number, but approximated with the number of mass instead. + .. versionadded:: 0.13.1 + Parameters ---------- energy_projectile : float @@ -593,6 +595,9 @@ class KalbachMann(AngleEnergy): If the projectile is a neutron, the slope is calculated when it is not given explicitly. + .. versionchanged:: 0.13.1 + Arguments changed to accommodate slope calculation + Parameters ---------- file_obj : file-like object diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index eba90f60d..dd14f282f 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -56,6 +56,7 @@ def _find_cross_sections(model): ) return cross_sections + def _get_nuclides_with_data(cross_sections): """Loads cross_sections.xml file to find nuclides with neutron data @@ -81,6 +82,7 @@ def _get_nuclides_with_data(cross_sections): return nuclides + class CoupledOperator(OpenMCOperator): """Transport-coupled transport operator. @@ -93,6 +95,9 @@ class CoupledOperator(OpenMCOperator): The geometry and settings parameters have been replaced with a model parameter that takes a :class:`~openmc.model.Model` object + .. versionchanged:: 0.13.1 + Name changed from ``Operator`` to ``CoupledOperator`` + Parameters ---------- model : openmc.model.Model @@ -534,6 +539,7 @@ class CoupledOperator(OpenMCOperator): if self.cleanup_when_done: openmc.lib.finalize() + # Retain deprecated name for the time being def Operator(*args, **kwargs): # warn of name change diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index a2d89e441..20267f948 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -6,8 +6,6 @@ transport solver by using user-provided one-group cross sections. """ import copy -from collections import OrderedDict -from warnings import warn from itertools import product import numpy as np @@ -22,6 +20,7 @@ from .microxs import MicroXS from .results import Results from .helpers import ChainFissionHelper, ConstantFissionYieldHelper, SourceRateHelper + class IndependentOperator(OpenMCOperator): """Transport-independent transport operator that uses one-group cross sections to calculate reaction rates. @@ -32,6 +31,8 @@ class IndependentOperator(OpenMCOperator): passed to an integrator class, such as :class:`openmc.deplete.CECMIntegrator`. + .. versionadded:: 0.13.1 + Parameters ---------- materials : openmc.Materials diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index ccbfab538..72d87d3b7 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -25,8 +25,10 @@ _valid_rxns.append('fission') class MicroXS(DataFrame): - """Stores microscopic cross section data for use in - transport-independent depletion. + """Microscopic cross section data for use in transport-independent depletion. + + .. versionadded:: 0.13.1 + """ @classmethod @@ -59,7 +61,7 @@ class MicroXS(DataFrame): energy_bound : 2-tuple of float, optional Bounds for the energy group. run_kwargs : dict, optional - Keyword arguments for :meth:`openmc.model.Model.run()` + Keyword arguments passed to :meth:`openmc.model.Model.run` Returns ------- diff --git a/openmc/filter.py b/openmc/filter.py index d7ab3f27e..7874a775b 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1340,6 +1340,8 @@ class EnergyFilter(RealFilter): def from_group_structure(cls, group_structure): """Construct an EnergyFilter instance from a standard group structure. + .. versionadded:: 0.13.1 + Parameters ---------- group_structure : str diff --git a/openmc/material.py b/openmc/material.py index 6c23d3319..167eaba84 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -463,6 +463,8 @@ class Material(IDManagerMixin): def remove_element(self, element): """Remove an element from the material + .. versionadded:: 0.13.1 + Parameters ---------- element : str @@ -918,7 +920,7 @@ class Material(IDManagerMixin): Returns ------- Union[dict, float] - If by_nuclide is True then a dictionary whose keys are nuclide + If by_nuclide is True then a dictionary whose keys are nuclide names and values are activity is returned. Otherwise the activity of the material is returned as a float. """ diff --git a/openmc/region.py b/openmc/region.py index 4e74a08ad..5d0e68020 100644 --- a/openmc/region.py +++ b/openmc/region.py @@ -269,6 +269,8 @@ class Region(ABC): inplace : bool Whether or not to return a region based on new surfaces or one based on the original surfaces that have been modified. + + .. versionadded:: 0.13.1 memo : dict or None Dictionary used for memoization. This parameter is used internally and should not be specified by the user. diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 0c3052625..d6b8a7573 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -205,6 +205,8 @@ class Discrete(Univariate): def merge(cls, dists, probs): """Merge multiple discrete distributions into a single distribution + .. versionadded:: 0.13.1 + Parameters ---------- dists : iterable of openmc.stats.Discrete diff --git a/openmc/universe.py b/openmc/universe.py index 4aa1775fb..081fff4ff 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -644,6 +644,8 @@ class DAGMCUniverse(UniverseBase): bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box of the universe. + + .. versionadded:: 0.13.1 """ def __init__(self, @@ -726,6 +728,9 @@ class DAGMCUniverse(UniverseBase): def bounding_region(self, bounded_type='box', boundary_type='vacuum', starting_id=10000): """Creates a either a spherical or box shaped bounding region around the DAGMC geometry. + + .. versionadded:: 0.13.1 + Parameters ---------- bounded_type : str @@ -740,6 +745,7 @@ class DAGMCUniverse(UniverseBase): Starting ID of the surface(s) used in the region. For bounded_type 'box', the next 5 IDs will also be used. Defaults to 10000 to reduce the chance of an overlap of surface IDs with the DAGMC geometry. + Returns ------- openmc.Region diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index c5b7a00b6..9183bb08b 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -409,7 +409,9 @@ class WeightWindows(IDManagerMixin): def wwinp_to_wws(path): - """Creates WeightWindows classes from a wwinp file + """Create WeightWindows instances from a wwinp file + + .. versionadded:: 0.13.1 Parameters ---------- From 70598087cd8d735c7fd8d122893dcd74b10a7d43 Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:33:49 -0500 Subject: [PATCH 0840/2654] forgot to change name of arrgument from id to index in header Co-authored-by: Paul Romano --- include/openmc/capi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/capi.h b/include/openmc/capi.h index e04d4898e..29e900965 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -118,7 +118,7 @@ int openmc_regular_mesh_get_params( int openmc_regular_mesh_set_dimension(int32_t index, int n, const int* dims); int openmc_regular_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, const double* width); -int openmc_remove_tally(int32_t id); +int openmc_remove_tally(int32_t index); int openmc_reset(); int openmc_reset_timers(); int openmc_run(); From c772972808674b94f602af5fe854adcf4da3d3e3 Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:34:19 -0500 Subject: [PATCH 0841/2654] add space for compliant formatting Co-authored-by: Paul Romano --- openmc/lib/tally.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index c1c8ab094..0be2f9ed5 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -402,7 +402,7 @@ class _TallyMapping(Mapping): def __repr__(self): return repr(dict(self)) - def __delitem__(self,key): + def __delitem__(self, key): """Delete a tally from tally vector and remove the ID,index pair from tally""" _dll.openmc_remove_tally(self._get_tally_index(key)) From 7b0189125906fbc8e351cae1e54933e6369bc6f4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 29 Jul 2022 10:08:47 -0500 Subject: [PATCH 0842/2654] Start release notes for 0.13.1 --- docs/source/pythonapi/stats.rst | 7 ++ docs/source/releasenotes/0.13.1.rst | 179 ++++++++++++++++++++++++++++ docs/source/releasenotes/index.rst | 1 + 3 files changed, 187 insertions(+) create mode 100644 docs/source/releasenotes/0.13.1.rst diff --git a/docs/source/pythonapi/stats.rst b/docs/source/pythonapi/stats.rst index 1d4ef0302..b4f115854 100644 --- a/docs/source/pythonapi/stats.rst +++ b/docs/source/pythonapi/stats.rst @@ -51,3 +51,10 @@ Spatial Distributions openmc.stats.SphericalIndependent openmc.stats.Box openmc.stats.Point + +.. autosummary:: + :toctree: generated + :nosignatures: + :template: myfunction.rst + + openmc.stats.spherical_uniform diff --git a/docs/source/releasenotes/0.13.1.rst b/docs/source/releasenotes/0.13.1.rst new file mode 100644 index 000000000..501d54090 --- /dev/null +++ b/docs/source/releasenotes/0.13.1.rst @@ -0,0 +1,179 @@ +==================== +What's New in 0.13.1 +==================== + +.. currentmodule:: openmc + +------- +Summary +------- + +This release of OpenMC includes many bug fixes as well as improvements in +geometry modeling, mesh functionality, source specification, depletion +capabilities, and other general enhancements. The depletion module features a +new transport operator, :class:`openmc.deplete.IndependentOperator`, that allows +a depletion calculation to be performed using arbitrary one-group cross sections +(e.g., generated by an external solver). The track file generation capability +has been significantly overhauled and a new :class:`openmc.Tracks` class was +introduced to allow access to information in track files from the Python API. +Support has been added for new ENDF thermal scattering evaluations that use +mixed coherent/incoherent elastic scattering. + +------------------------------------ +Compatibility Notes and Deprecations +------------------------------------ + +- The ``openmc.deplete.Operator`` class has been renamed + :class:`openmc.deplete.CoupledOperator`. +- The ``openmc.deplete.ResultsList`` class has been renamed to + :class:`openmc.deplete.Results` and no longer requires you to call the + ``from_hdf5()`` method in order to create it; instead, you can directly + instantiate it. +- A few methods that represent k-effective have been renamed for the sake of + consistency: + + - ``openmc.StatePoint.k_combined`` is now :attr:`openmc.StatePoint.keff` + - ``openmc.deplete.ResultsList.get_eigenvalue`` is now + :meth:`openmc.deplete.Results.get_keff` + +- The :class:`openmc.stats.SphericalIndependent` class, which used to + accept a distribution for ``theta`` now accepts a distribution for ``cos_theta`` + instead in order to more easily handle the common case of specifying a uniform + spatial distribution over a sphere (also see the new + :func:`openmc.stats.spherical_uniform` function). + +- If you are building OpenMC from source, note that several of our CMake options + have been changed: + + ========== ====================== + Old option New option + ========== ====================== + debug --- + optimize --- + profile OPENMC_ENABLE_PROFILE + coverage OPENMC_ENABLE_COVERAGE + openmp OPENMC_USE_OPENMP + --- OPENMC_USE_MPI + dagmc OPENMC_USE_DAGMC + libmesh OPENMC_USE_LIBMESH + ========== ====================== + + The ``debug`` and ``optimize`` options have been removed; instead, use the + standard `CMAKE_BUILD_TYPE + `_ + variable. + +------------ +New Features +------------ + +- An :class:`openmc.model.IsogonalOctagon` composite surface. +- The :class:`~openmc.DAGMCUniverse` class now has a + :attr:`~openmc.DAGMCUniverse.bounding_box` attribute and a + :meth:`~openmc.DAGMCUniverse.bounding_region` method. +- When translating a :class:`~openmc.Region` using the + :meth:`~openmc.Region.translate` method, there is now an ``inplace`` argument. +- The :class:`~openmc.Material` class has several new methods and attributes: + + - The :meth:`~openmc.Material.add_components` methods allows you to add + multiple nuclides/elements to a material with a single call by passing a + dictionary. + - The :meth:`~openmc.Material.get_activity` method returns the activity of a + material in Bq, Bq/g, or Bq/cm³. + - The :meth:`~openmc.Material.remove_element` method removes an element from a + material + - The :meth:`~openmc.Material.get_nuclide_atoms` method gives the number of + atoms of each nuclide in a material + +- All mesh classes now have a ``volumes`` property that provides the volume of + each mesh element as well as ``write_data_to_vtk`` methods. +- Support for externally managed MOAB meshes or libMesh meshes. +- Multiple discrete distributions can be merged with the new + :meth:`~openmc.stats.Discrete.merge` method. +- The :func:`openmc.stats.spherical_uniform` function creates a uniform + distribution over a sphere using the + :class:`~openmc.stats.SphericalIndependent` class. +- Univariate distributions in the :mod:`openmc.stats` module now have + ``sample()`` methods. +- An ``openmc_sample_external_source`` function has been added to the C API with + a corresponding Python binding :func:`openmc.lib.sample_external_source`. +- The track file generation capability has been completely overhauled. Track + files now include much more information, and a new :class:`~openmc.TrackFile` + class allows access to track file information from the Python API. Multiple + tracks are now written to a single file (one per MPI rank). +- A new :func:`openmc.wwinp_to_wws` function that converts weight windows from a + ``wwinp`` file to a list of :class:`~openmc.WeightWindows` objects. +- The new :meth:`openmc.EnergyFilter.from_group_structure` method provides a + way of creating an energy filter with a group structure identified by name. +- The :class:`openmc.data.Decay` class now has a + :attr:`~openmc.data.Decay.sources` property that provides radioactive decay + source distributions. +- A :class:`openmc.mgxs.ReducedAbsorptionXS` class produces a multigroup cross + section representing "reduced" absorption (absorption less neutron production + from (n,xn) reactions). +- Added support in the Python API and HDF5 nuclear data format for new ENDF + thermal neutron scattering evaluations with mixed coherent elastic and + incoherent elastic. +- CMake now relies on ``find_package(MPI)`` for a more standard means of + identifying an MPI compiler configuration. + +--------- +Bug Fixes +--------- + +- `Fix bug when a rotation matrix is passed to Halfspace.rotate `_ +- `Fix bug for spherical mesh string repr `_ +- `Fix package_data specification to include pyx files `_ +- `Allow meshes with same ID to appear in multiple files `_ +- `Fix overwritten variable in get_libraries_from_xsdata `_ +- `Write output files to correct directory `_ +- `Allow CMake to properly find third-party packages `_ +- `Fix Region.from_expression when ")(" appears in specification `_ +- `Move lost particle reset from finalize() to reset() `_ +- `Minor typo fixes in test_lattice.py `_ +- `Fix color assignment in Universe.plot `_ +- `Several depletion-related fixes `_ +- `Allow control of C++ standard used by compiler `_ +- `Fix IO format documentation for surface source read/write `_ +- `Make sure basis gets set in Plot.from_geometry `_ +- `Improve robustness of torus distance calculation `_ +- `Allow use of redundant fission when adjusting KERMA in from_njoy `_ +- `Disable GNU extensions for CMake target `_ +- `Two from_xml fixes `_ +- `Fix for rare infinite loop when finding cell `_ +- `Allow photon heating to be tallied by nuclide `_ +- `Use UTF-8 encoding when reading dose coefficients `_ +- `Fix a corner case in Region.from_expression `_ +- `Fix bug in spherical and cylindrical meshes `_ +- `Ensure weight window bounds are flattened when writing to XML `_ +- `Fix for std::cout sync bug in output.cpp `_ +- `Allow compiling against fmt v9 `_ +- `Fix TimeFilter for small time intervals `_ + +------------ +Contributors +------------ + +- `David Andrs `_ +- `Hunter Belanger `_ +- `Helen Brooks `_ +- `Rémi Delaporte-Mathurin `_ +- `Joffrey Dorville `_ +- `Christopher Fichtlscherer `_ +- `Lewis Gross `_ +- `Andrew Johnson `_ +- `Kalin Kiesling `_ +- `Amanda Lund `_ +- `Richard Morrison `_ +- `Patrick Myers `_ +- `Adam Nelson `_ +- `April Novak `_ +- `Ethan Peterson `_ +- `Gavin Ridley `_ +- `Paul Romano `_ +- `Jonathan Shimwell `_ +- `Patrick Shriwise `_ +- `Amelia Trainer `_ +- `John Tramm `_ +- `Bob Urberger `_ +- `Olek Yardas `_ diff --git a/docs/source/releasenotes/index.rst b/docs/source/releasenotes/index.rst index 75db7ebc9..34ddb285a 100644 --- a/docs/source/releasenotes/index.rst +++ b/docs/source/releasenotes/index.rst @@ -7,6 +7,7 @@ Release Notes .. toctree:: :maxdepth: 1 + 0.13.1 0.13.0 0.12.2 0.12.1 From 28b8f9ecc565c1fcfe5716dd31fc126a0c911044 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 12 Aug 2022 14:37:39 -0500 Subject: [PATCH 0843/2654] Change Operator --> CoupledOperator in a few places --- examples/pincell_depletion/restart_depletion.py | 2 +- examples/pincell_depletion/run_depletion.py | 2 +- openmc/model/model.py | 6 +++--- tests/regression_tests/deplete_with_transport/test.py | 2 +- tests/unit_tests/test_deplete_activation.py | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/pincell_depletion/restart_depletion.py b/examples/pincell_depletion/restart_depletion.py index 95bbb9954..6bb715f3b 100644 --- a/examples/pincell_depletion/restart_depletion.py +++ b/examples/pincell_depletion/restart_depletion.py @@ -43,7 +43,7 @@ model = openmc.Model(geometry=geometry, settings=settings) # Create depletion "operator" chain_file = 'chain_simple.xml' -op = openmc.deplete.Operator(model, chain_file, previous_results) +op = openmc.deplete.CoupledOperator(model, chain_file, previous_results) # Perform simulation using the predictor algorithm time_steps = [1.0, 1.0, 1.0, 1.0, 1.0] # days diff --git a/examples/pincell_depletion/run_depletion.py b/examples/pincell_depletion/run_depletion.py index ae069334e..6a6c25f59 100644 --- a/examples/pincell_depletion/run_depletion.py +++ b/examples/pincell_depletion/run_depletion.py @@ -88,7 +88,7 @@ model = openmc.Model(geometry=geometry, settings=settings) # Create depletion "operator" chain_file = 'chain_simple.xml' -op = openmc.deplete.Operator(model, chain_file) +op = openmc.deplete.CoupledOperator(model, chain_file) # Perform simulation using the predictor algorithm time_steps = [1.0, 1.0, 1.0, 1.0, 1.0] # days diff --git a/openmc/model/model.py b/openmc/model/model.py index 52c52154e..ab99ac978 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -331,7 +331,7 @@ class Model: Indicate whether or not a transport solve should be run at the end of the last timestep. Defaults to running this transport solve. operator_kwargs : dict - Keyword arguments passed to the depletion Operator initializer + Keyword arguments passed to the depletion operator initializer (e.g., :func:`openmc.deplete.Operator`) directory : str, optional Directory to write XML files to. If it doesn't exist already, it @@ -360,8 +360,8 @@ class Model: with _change_directory(Path(directory)): with openmc.lib.quiet_dll(output): - depletion_operator = \ - dep.Operator(self, **op_kwargs) + # TODO: Support use of IndependentOperator too + depletion_operator = dep.CoupledOperator(self, **op_kwargs) # Tell depletion_operator.finalize NOT to clear C API memory when # it is done diff --git a/tests/regression_tests/deplete_with_transport/test.py b/tests/regression_tests/deplete_with_transport/test.py index 0c2a4cd97..58065035f 100644 --- a/tests/regression_tests/deplete_with_transport/test.py +++ b/tests/regression_tests/deplete_with_transport/test.py @@ -53,7 +53,7 @@ def test_full(run_in_tmpdir, problem, multiproc): # Create operator chain_file = Path(__file__).parents[2] / 'chain_simple.xml' - op = openmc.deplete.Operator(model, chain_file) + op = openmc.deplete.CoupledOperator(model, chain_file) op.round_number = True # Power and timesteps diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index cb3b86b9c..1842ad8ac 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -64,7 +64,7 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts chain.export_to_xml('test_chain.xml') # Create transport operator - op = openmc.deplete.Operator( + op = openmc.deplete.CoupledOperator( model, 'test_chain.xml', normalization_mode="source-rate", reaction_rate_mode=reaction_rate_mode, @@ -144,7 +144,7 @@ def test_decay(run_in_tmpdir): model = openmc.Model(geometry=geometry, settings=settings) # Create transport operator - op = openmc.deplete.Operator( + op = openmc.deplete.CoupledOperator( model, 'test_chain.xml', normalization_mode="source-rate" ) From c252930c4990fa71e3f00ec7d3e90dd4df7116d1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 15 Aug 2022 12:33:24 -0500 Subject: [PATCH 0844/2654] Support passing Path objects to Summary() --- openmc/summary.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openmc/summary.py b/openmc/summary.py index 41bae7f26..43224334d 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -14,6 +14,11 @@ _VERSION_SUMMARY = 6 class Summary: """Summary of model used in a simulation. + Parameters + ---------- + filename : str or path-like + Path to file to load + Attributes ---------- date_and_time : str @@ -33,8 +38,9 @@ class Summary: """ def __init__(self, filename): + filename = str(filename) if not filename.endswith(('.h5', '.hdf5')): - msg = 'Unable to open "{0}" which is not an HDF5 summary file' + msg = f'Unable to open "{filename}" which is not an HDF5 summary file' raise ValueError(msg) self._f = h5py.File(filename, 'r') From d69a6ec647d7f78eac7cf25586df9ab2ae2dec41 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Mon, 15 Aug 2022 13:43:53 -0500 Subject: [PATCH 0845/2654] [skip ci] erasing the tally from the tallies vector calls the destructor, which already handles removing this tally from the map --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index f45fae994..59adce455 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -1281,8 +1281,8 @@ extern "C" int openmc_remove_tally(int32_t index) } // grab tally so it's ID can be obtained to remove the (ID,index) pair from tally_map auto& tally = model::tallies[index]; - model::tally_map.erase(tally->id_); // delete the tally via iterator pointing to correct position + // this calls the Tally destructor, removing the tally from the map as well model::tallies.erase(model::tallies.begin() + index); return 0; From 7fdd96a5734d2accedabcd1b6c0397230b3a04c3 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Mon, 15 Aug 2022 13:46:26 -0500 Subject: [PATCH 0846/2654] forgot a space for formatting requirements --- openmc/lib/tally.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index 0be2f9ed5..79f1193e6 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -406,7 +406,7 @@ class _TallyMapping(Mapping): """Delete a tally from tally vector and remove the ID,index pair from tally""" _dll.openmc_remove_tally(self._get_tally_index(key)) - def _get_tally_index(self,key): + def _get_tally_index(self, key): """Given the ID, return the index""" index = c_int32() try: From 82bbf7141352cac21295bac96d6e691692a170de Mon Sep 17 00:00:00 2001 From: myerspat Date: Mon, 15 Aug 2022 15:04:03 -0400 Subject: [PATCH 0847/2654] Reduced contains_complex to one while loop --- include/openmc/cell.h | 4 +- src/cell.cpp | 125 ++++++++++++++++++++++-------------------- src/geometry_aux.cpp | 2 +- src/universe.cpp | 4 +- 4 files changed, 72 insertions(+), 63 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 0004a86c6..23cd0130a 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -199,7 +199,9 @@ public: vector sqrtkT_; //! Definition of spatial region as Boolean expression of half-spaces - vector region_; + vector region_; + //! Region in infix that may be modified depending on simplicity + vector region_infix_; bool simple_; //!< Does the region contain only intersections? //! \brief Neighboring cells in the same universe. diff --git a/src/cell.cpp b/src/cell.cpp index 8224ba266..a663d1144 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -115,46 +115,62 @@ vector tokenize(const std::string region_spec) std::vector::iterator add_parenthesis( std::vector::iterator start, std::vector& infix) { + int32_t start_token = *start; // Add left parenthesis - start = infix.insert(start, OP_LEFT_PAREN); - start = start + 2; + if (start_token == OP_INTERSECTION) { + start = infix.insert(start - 1, OP_LEFT_PAREN); + } else { + start = infix.insert(start + 1, OP_LEFT_PAREN); + } + start++; // Initialize return iterator - std::vector::iterator return_iterator = infix.end() - 1; + std::vector::iterator return_iterator = infix.begin(); // Add right parenthesis // While the start iterator is within the bounds of infix while (start < infix.end()) { start++; - // If we find a union or right parenthesis not wrapped by - // left and right parenthesis then place a right parenthesis, - // If we find a wrapped region return an iterator pointing to - // that wrapped region and continue looking to place a - // right parenthesis - if (*start == OP_UNION || *start == OP_RIGHT_PAREN) { - start = infix.insert(start, OP_RIGHT_PAREN); - return start - 1; - - } else if (*start == OP_LEFT_PAREN) { - return_iterator = start; - int depth = 1; - do { - start++; - if (*start > OP_COMPLEMENT) { - if (*start == OP_RIGHT_PAREN) { - depth--; - } else { - depth++; + // If the current token is an operator and is different than the start token + if (*start >= OP_UNION && *start != start_token) { + // Skip wraped regions but save iterator position to check precedence and + // add right parenthesis depending on the precedence of the original token + // when a right parenthesis is encountered of the opposite token + if (*start == OP_LEFT_PAREN) { + return_iterator = start; + int depth = 1; + do { + start++; + if (*start > OP_COMPLEMENT) { + if (*start == OP_RIGHT_PAREN) { + depth--; + } else { + depth++; + } } + } while (depth > 0); + } else if (start_token == OP_UNION) { + start = infix.insert(start - 1, OP_RIGHT_PAREN); + if (return_iterator == infix.begin()) { + return_iterator = start - 1; } - } while (depth > 0); + return return_iterator; + } else { + start = infix.insert(start, OP_RIGHT_PAREN); + if (return_iterator == infix.begin()) { + return_iterator = start - 1; + } + return return_iterator; + } } } - // If we get here a right parenthesis hasn't been placed, // return iterator infix.push_back(OP_RIGHT_PAREN); + if (return_iterator == infix.begin()) { + return_iterator = start - 1; + } return return_iterator; } @@ -168,15 +184,15 @@ void add_precedence(std::vector& infix) // If the token is a union another operator has not been found set the // current operator to union // If the current operator is a union and the token is an intersection - // assert precedence + // assert precedence // If the token is a parenthesis reset the current operator - if (token == OP_UNION && current_op == 0) { - current_op = OP_UNION; - - } else if (current_op == OP_UNION && token == OP_INTERSECTION) { - it = add_parenthesis(it - 1, infix); - current_op = 0; - + if (token == OP_UNION || token == OP_INTERSECTION) { + if (current_op == 0) { + current_op = token; + } else if (token != current_op) { + it = add_parenthesis(it, infix); + current_op = 0; + } } else if (token > OP_COMPLEMENT) { current_op = 0; } @@ -577,7 +593,6 @@ CSGCell::CSGCell(pugi::xml_node cell_node) // Morgans law region_ = tokenize(region_spec); remove_complement_ops(region_); - region_.shrink_to_fit(); // Convert user IDs to surface indices. for (auto& r : region_) { @@ -602,16 +617,18 @@ CSGCell::CSGCell(pugi::xml_node cell_node) break; } } + region_.shrink_to_fit(); + region_infix_ = region_; // If this cell is simple, remove all the superfluous operator tokens. if (simple_) { - for (auto it = region_.begin(); it != region_.end(); it++) { + for (auto it = region_infix_.begin(); it != region_infix_.end(); it++) { if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { - region_.erase(it); + region_infix_.erase(it); } } + region_infix_.shrink_to_fit(); } - region_.shrink_to_fit(); // Read the translation vector. if (check_for_node(cell_node, "translation")) { @@ -655,7 +672,7 @@ std::pair CSGCell::distance( double min_dist {INFTY}; int32_t i_surf {std::numeric_limits::max()}; - for (int32_t token : region_) { + for (int32_t token : region_infix_) { // Ignore this token if it corresponds to an operator rather than a region. if (token >= OP_UNION) continue; @@ -710,7 +727,7 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const BoundingBox CSGCell::bounding_box_simple() const { BoundingBox bbox; - for (int32_t token : region_) { + for (int32_t token : region_infix_) { bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); } return bbox; @@ -820,14 +837,14 @@ BoundingBox CSGCell::bounding_box_complex(vector rpn) BoundingBox CSGCell::bounding_box() const { - return simple_ ? bounding_box_simple() : bounding_box_complex(region_); + return simple_ ? bounding_box_simple() : bounding_box_complex(region_infix_); } //============================================================================== bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const { - for (int32_t token : region_) { + for (int32_t token : region_infix_) { // Assume that no tokens are operators. Evaluate the sense of particle with // respect to the surface and see if the token matches the sense. If the // particle's surface attribute is set and matches the token, that @@ -854,7 +871,7 @@ bool CSGCell::contains_complex( bool in_cell = true; // For each token - for (auto it = region_.begin(); it != region_.end(); it++) { + for (auto it = region_infix_.begin(); it != region_infix_.end(); it++) { int32_t token = *it; // If the token is a surface evaluate the sense @@ -873,32 +890,22 @@ bool CSGCell::contains_complex( } else if ((token == OP_UNION && in_cell == true) || (token == OP_INTERSECTION && in_cell == false)) { // While the iterator is within the bounds of the vector + int depth = 1; do { // Get next token it++; int32_t next_token = *it; - // If the next token is an operator and is not the same as the one that - // started the short circuiting, check if it is a left parenthesis to - // skip a section or break - if (next_token >= OP_UNION && token != next_token) { - if (next_token == OP_LEFT_PAREN) { - int depth = 1; - do { - it++; - if (*it > OP_COMPLEMENT) { - if (*it == OP_RIGHT_PAREN) { - depth--; - } else { - depth++; - } - } - } while (depth > 0); + // If the token is an a parenthesis + if (next_token > OP_COMPLEMENT) { + // Adjust depth accordingly + if (next_token == OP_RIGHT_PAREN) { + depth--; } else { - break; + depth++; } } - } while (it < region_.end() - 1); + } while (depth > 0 && it < region_infix_.end() - 1); } } return in_cell; diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index c3458d469..7648d270a 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -154,7 +154,7 @@ void partition_universes() // Collect the set of surfaces in this universe. std::unordered_set surf_inds; for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_infix_) { if (token < OP_UNION) surf_inds.insert(std::abs(token) - 1); } diff --git a/src/universe.cpp b/src/universe.cpp index 873d03bb7..723400ec0 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -98,7 +98,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find all of the z-planes in this universe. A set is used here for the // O(log(n)) insertions that will ensure entries are not repeated. for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_infix_) { if (token < OP_UNION) { auto i_surf = std::abs(token) - 1; const auto* surf = model::surfaces[i_surf].get(); @@ -125,7 +125,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find the tokens for bounding z-planes. int32_t lower_token = 0, upper_token = 0; double min_z, max_z; - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_infix_) { if (token < OP_UNION) { const auto* surf = model::surfaces[std::abs(token) - 1].get(); if (const auto* zplane = dynamic_cast(surf)) { From 15a863e6457766ae792ca44e4b706060318e85f4 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Mon, 15 Aug 2022 14:49:36 -0500 Subject: [PATCH 0848/2654] suggestion by Paul Romano. removed need for _get_tally_index_ funciton by using python's fancy self[key] and self[key]._index capabilities --- openmc/lib/tally.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index 79f1193e6..90983d171 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -390,7 +390,7 @@ class Tally(_FortranObjectWithID): class _TallyMapping(Mapping): def __getitem__(self, key): - return Tally(index=self._get_tally_index(key)) + return Tally(index=self[key]) def __iter__(self): for i in range(len(self)): @@ -404,16 +404,6 @@ class _TallyMapping(Mapping): def __delitem__(self, key): """Delete a tally from tally vector and remove the ID,index pair from tally""" - _dll.openmc_remove_tally(self._get_tally_index(key)) - - def _get_tally_index(self, key): - """Given the ID, return the index""" - index = c_int32() - try: - _dll.openmc_get_tally_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return index.value + _dll.openmc_remove_tally(self[key]._index) tallies = _TallyMapping() From ab6b8f9acfecfb9f33e40b974635a378f58eef6d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 15 Aug 2022 15:05:36 -0500 Subject: [PATCH 0849/2654] CMake cmd fixes for libmesh and dagmc --- docs/source/usersguide/install.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index d05c00bb3..3d48828fb 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -269,7 +269,7 @@ Prerequisites In addition to turning this option on, the path to the DAGMC installation should be specified as part of the ``CMAKE_PREFIX_PATH`` variable:: - cmake -DOPENMC_USE_DAGMC=on -DCMAKE_PREFIX_PATH=/path/to/dagmc/installation + cmake -DOPENMC_USE_DAGMC=on -DCMAKE_PREFIX_PATH=/path/to/dagmc/installation .. * libMesh_ mesh library framework for numerical simulations of partial differential equations @@ -280,7 +280,7 @@ Prerequisites installation should be specified as part of the ``CMAKE_PREFIX_PATH`` variable.:: - cmake -DOPENMC_USE_LIBMESH=on -DOPENMC_USE_MPI=on -DCMAKE_PREFIX_PATH=/path/to/libmesh/installation + cmake -DOPENMC_USE_LIBMESH=on -DOPENMC_USE_MPI=on -DCMAKE_PREFIX_PATH=/path/to/libmesh/installation .. Note that libMesh is most commonly compiled with MPI support. If that is the case, then OpenMC should be compiled with MPI support as well. From 762993fb8b5c47599d512a6bb1bf5ba2047abe3e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 16 Aug 2022 16:47:08 +0100 Subject: [PATCH 0850/2654] added "ecco-2000" with 1968 bins --- openmc/mgxs/__init__.py | 329 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index 938dd8c7a..a3603f23d 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -14,6 +14,9 @@ GROUP_STRUCTURES = {} - "SHEM-361_" designed for LWR analysis to eliminate self-shielding calculations of thermal resonances ([HFA2005]_, [SAN2007]_, [HEB2008]_) - "SCALE-44" designed for criticality analysis ([ZAL1999]_) +- "ECCO-2000" is a 1968-group neutron structure aimed at fine group reactor + cell calculations for fast, intermediate and thermal reactor applications. + ([SAR1990]_) - activation_ energy group structures "VITAMIN-J-42", "VITAMIN-J-175", "TRIPOLI-315", "CCFE-709_" and "UKAEA-1102_" @@ -639,3 +642,329 @@ GROUP_STRUCTURES['UKAEA-1102'] = np.array([ 5.7544e8, 6.0256e8, 6.3096e8, 6.6069e8, 6.9183e8, 7.2444e8, 7.5858e8, 7.9433e8, 8.3176e8, 8.7096e8, 9.1201e8, 9.5499e8, 1.e9]) +GROUP_STRUCTURES['ECCO-2000'] = np.array([ + 1.00001e-5, 3.00000e-3, 5.00000e-3, 6.90000e-3, 1.00000e-2, 1.50000e-2, + 2.00000e-2, 2.50000e-2, 3.00000e-2, 3.50000e-2, 4.20000e-2, 5.00000e-2, + 5.80000e-2, 6.70000e-2, 7.70000e-2, 8.00000e-2, 9.50000e-2, 1.00000e-1, + 1.15000e-1, 1.34000e-1, 1.40000e-1, 1.46370e-1, 1.53030e-1, 1.60000e-1, + 1.69710e-1, 1.80000e-1, 1.89000e-1, 1.98810e-1, 2.09140e-1, 2.20000e-1, + 2.33580e-1, 2.48000e-1, 2.63510e-1, 2.80000e-1, 3.00000e-1, 3.14500e-1, + 3.20000e-1, 3.34660e-1, 3.50000e-1, 3.69930e-1, 3.91000e-1, 4.00000e-1, + 4.13990e-1, 4.33000e-1, 4.49680e-1, 4.67010e-1, 4.85000e-1, 5.00000e-1, + 5.19620e-1, 5.31580e-1, 5.40000e-1, 5.66960e-1, 5.95280e-1, 6.25000e-1, + 6.53150e-1, 6.82560e-1, 7.05000e-1, 7.41550e-1, 7.80000e-1, 7.90000e-1, + 8.19450e-1, 8.50000e-1, 8.60000e-1, 8.76425e-1, 9.10000e-1, 9.30000e-1, + 9.50000e-1, 9.72000e-1, 9.86000e-1, 9.96000e-1, + 1.020000, 1.035000, 1.045000, 1.071000, 1.080000, 1.097000, 1.110000, + 1.123000, 1.150000, 1.170000, 1.202060, 1.235000, 1.267080, 1.300000, + 1.337500, 1.370000, 1.404560, 1.440000, 1.475000, 1.500000, 1.544340, + 1.590000, 1.629510, 1.670000, 1.711970, 1.755000, 1.797000, 1.840000, + 1.855390, 1.884460, 1.930000, 1.974490, 2.020000, 2.059610, 2.100000, + 2.130000, 2.185310, 2.242050, 2.300270, 2.360000, 2.382370, 2.421710, + 2.485030, 2.550000, 2.600000, 2.659320, 2.720000, 2.767920, 2.837990, + 2.909830, 2.983490, 3.059020, 3.137330, 3.217630, 3.300000, 3.380750, + 3.466330, 3.554080, 3.644050, 3.736300, 3.830880, 3.927860, 4.000000, + 4.129250, 4.233782, 4.340961, 4.450853, 4.563526, 4.679053, 4.797503, + 4.918953, 5.043477, 5.085681, 5.128239, 5.171153, 5.214426, 5.258061, + 5.302061, 5.346430, 5.391169, 5.436284, 5.481775, 5.527647, 5.573904, + 5.620547, 5.667581, 5.715008, 5.762832, 5.811056, 5.859684, 5.908719, + 5.958164, 6.008022, 6.058298, 6.108995, 6.160116, 6.211665, 6.263645, + 6.316060, 6.368914, 6.422210, 6.475952, 6.530144, 6.584789, 6.639892, + 6.695455, 6.751484, 6.807981, 6.864952, 6.922399, 6.980326, 7.038739, + 7.097640, 7.157034, 7.216925, 7.277317, 7.338215, 7.399622, 7.461544, + 7.523983, 7.586945, 7.650434, 7.714454, 7.779009, 7.844105, 7.909746, + 7.975936, 8.042680, 8.109982, 8.177848, 8.246281, 8.315287, 8.384871, + 8.455037, 8.525790, 8.597135, 8.669077, 8.741621, 8.814772, 8.888536, + 8.962916, 9.037919, 9.113550, 9.189814, 9.266715, 9.344261, 9.422455, + 9.501303, 9.580812, 9.660985, 9.741830, 9.823351, 9.905554, 9.988446, + 1.007203e1, 1.015631e1, 1.024130e1, 1.032701e1, 1.041342e1, 1.050056e1, + 1.058843e1, 1.067704e1, 1.076639e1, 1.085648e1, 1.094733e1, 1.103894e1, + 1.113132e1, 1.122446e1, 1.131839e1, 1.141311e1, 1.150861e1, 1.160492e1, + 1.170203e1, 1.179995e1, 1.189870e1, 1.199827e1, 1.209867e1, 1.219991e1, + 1.230201e1, 1.240495e1, 1.250876e1, 1.261343e1, 1.271898e1, 1.282542e1, + 1.293274e1, 1.304097e1, 1.315010e1, 1.326014e1, 1.337110e1, 1.348299e1, + 1.359582e1, 1.370959e1, 1.382431e1, 1.394000e1, 1.405665e1, 1.417428e1, + 1.429289e1, 1.441250e1, 1.453310e1, 1.465472e1, 1.477735e1, 1.490101e1, + 1.502570e1, 1.515144e1, 1.527823e1, 1.540608e1, 1.553500e1, 1.566500e1, + 1.579609e1, 1.592827e1, 1.606156e1, 1.619597e1, 1.633150e1, 1.646816e1, + 1.660597e1, 1.674493e1, 1.688506e1, 1.702635e1, 1.716883e1, 1.731250e1, + 1.745738e1, 1.760346e1, 1.775077e1, 1.789931e1, 1.804910e1, 1.820013e1, + 1.835244e1, 1.850601e1, 1.866087e1, 1.881703e1, 1.897449e1, 1.913328e1, + 1.929339e1, 1.945484e1, 1.961764e1, 1.978180e1, 1.994734e1, 2.011426e1, + 2.028258e1, 2.045231e1, 2.062345e1, 2.079603e1, 2.097006e1, 2.114554e1, + 2.132249e1, 2.150092e1, 2.168084e1, 2.186227e1, 2.204522e1, 2.222969e1, + 2.241572e1, 2.260329e1, 2.279244e1, 2.298317e1, 2.317550e1, 2.336944e1, + 2.356499e1, 2.376219e1, 2.396104e1, 2.416154e1, 2.436373e1, 2.456761e1, + 2.477320e1, 2.498050e1, 2.518954e1, 2.540033e1, 2.561289e1, 2.582722e1, + 2.604335e1, 2.626128e1, 2.648104e1, 2.670264e1, 2.692609e1, 2.715141e1, + 2.737862e1, 2.760773e1, 2.783875e1, 2.807171e1, 2.830662e1, 2.854349e1, + 2.878235e1, 2.902320e1, 2.926607e1, 2.951098e1, 2.975793e1, 3.000695e1, + 3.025805e1, 3.051126e1, 3.076658e1, 3.102404e1, 3.128365e1, 3.154544e1, + 3.180942e1, 3.207560e1, 3.234401e1, 3.261467e1, 3.288760e1, 3.316281e1, + 3.344032e1, 3.372015e1, 3.400233e1, 3.428686e1, 3.457378e1, 3.486310e1, + 3.515484e1, 3.544902e1, 3.574566e1, 3.604479e1, 3.634642e1, 3.665057e1, + 3.695727e1, 3.726653e1, 3.757838e1, 3.789285e1, 3.820994e1, 3.852969e1, + 3.885211e1, 3.917723e1, 3.950507e1, 3.983565e1, 4.016900e1, 4.050514e1, + 4.084410e1, 4.118589e1, 4.153054e1, 4.187807e1, 4.222851e1, 4.258189e1, + 4.293822e1, 4.329753e1, 4.365985e1, 4.402521e1, 4.439361e1, 4.476511e1, + 4.513971e1, 4.551744e1, 4.589834e1, 4.628243e1, 4.666972e1, 4.706026e1, + 4.745407e1, 4.785117e1, 4.825160e1, 4.865538e1, 4.906253e1, 4.947309e1, + 4.988709e1, 5.030456e1, 5.072551e1, 5.114999e1, 5.157802e1, 5.200963e1, + 5.244486e1, 5.288373e1, 5.332626e1, 5.377251e1, 5.422248e1, 5.467623e1, + 5.513376e1, 5.559513e1, 5.606036e1, 5.652948e1, 5.700253e1, 5.747954e1, + 5.796053e1, 5.844556e1, 5.893464e1, 5.942781e1, 5.992511e1, 6.042657e1, + 6.093223e1, 6.144212e1, 6.195628e1, 6.247474e1, 6.299754e1, 6.352471e1, + 6.405630e1, 6.459233e1, 6.513285e1, 6.567789e1, 6.622749e1, 6.678169e1, + 6.734053e1, 6.790405e1, 6.847228e1, 6.904527e1, 6.962305e1, 7.020566e1, + 7.079316e1, 7.138556e1, 7.198293e1, 7.258529e1, 7.319270e1, 7.380518e1, + 7.442280e1, 7.504558e1, 7.567357e1, 7.630682e1, 7.694537e1, 7.758926e1, + 7.823854e1, 7.889325e1, 7.955344e1, 8.021915e1, 8.089044e1, 8.156734e1, + 8.224991e1, 8.293819e1, 8.363223e1, 8.433208e1, 8.503778e1, 8.574939e1, + 8.646695e1, 8.719052e1, 8.792015e1, 8.865588e1, 8.939776e1, 9.014586e1, + 9.090021e1, 9.166088e1, 9.242791e1, 9.320136e1, 9.398128e1, 9.476773e1, + 9.556076e1, 9.636043e1, 9.716679e1, 9.797990e1, 9.879981e1, 9.962658e1, + 1.004603e2, 1.013009e2, 1.021486e2, 1.030034e2, 1.038654e2, 1.047345e2, + 1.056110e2, 1.064947e2, 1.073859e2, 1.082845e2, 1.091907e2, 1.101044e2, + 1.110258e2, 1.119548e2, 1.128917e2, 1.138364e2, 1.147890e2, 1.157496e2, + 1.167182e2, 1.176949e2, 1.186798e2, 1.196729e2, 1.206744e2, 1.216842e2, + 1.227024e2, 1.237292e2, 1.247646e2, 1.258087e2, 1.268615e2, 1.279231e2, + 1.289935e2, 1.300730e2, 1.311615e2, 1.322590e2, 1.333658e2, 1.344818e2, + 1.356072e2, 1.367420e2, 1.378862e2, 1.390401e2, 1.402036e2, 1.413768e2, + 1.425599e2, 1.437529e2, 1.449558e2, 1.461688e2, 1.473920e2, 1.486254e2, + 1.498691e2, 1.511232e2, 1.523879e2, 1.536631e2, 1.549489e2, 1.562456e2, + 1.575531e2, 1.588715e2, 1.602010e2, 1.615415e2, 1.628933e2, 1.642565e2, + 1.656310e2, 1.670170e2, 1.684146e2, 1.698239e2, 1.712451e2, 1.726781e2, + 1.741231e2, 1.755802e2, 1.770494e2, 1.785310e2, 1.800250e2, 1.815315e2, + 1.830505e2, 1.845823e2, 1.861269e2, 1.876845e2, 1.892551e2, 1.908388e2, + 1.924358e2, 1.940461e2, 1.956699e2, 1.973073e2, 1.989584e2, 2.006233e2, + 2.023021e2, 2.039950e2, 2.057021e2, 2.074234e2, 2.091592e2, 2.109095e2, + 2.126744e2, 2.144541e2, 2.162487e2, 2.180583e2, 2.198830e2, 2.217230e2, + 2.235784e2, 2.254494e2, 2.273360e2, 2.292384e2, 2.311567e2, 2.330910e2, + 2.350416e2, 2.370084e2, 2.389917e2, 2.409917e2, 2.430083e2, 2.450418e2, + 2.470924e2, 2.491601e2, 2.512451e2, 2.533476e2, 2.554676e2, 2.576054e2, + 2.597611e2, 2.619348e2, 2.641267e2, 2.663370e2, 2.685657e2, 2.708131e2, + 2.730793e2, 2.753645e2, 2.776688e2, 2.799924e2, 2.823354e2, 2.846980e2, + 2.870804e2, 2.894827e2, 2.919052e2, 2.943479e2, 2.968110e2, 2.992948e2, + 3.017993e2, 3.043248e2, 3.068715e2, 3.094394e2, 3.120288e2, 3.146399e2, + 3.172729e2, 3.199279e2, 3.226051e2, 3.253047e2, 3.280269e2, 3.307719e2, + 3.335398e2, 3.363309e2, 3.391454e2, 3.419834e2, 3.448452e2, 3.477309e2, + 3.506408e2, 3.535750e2, 3.565338e2, 3.595173e2, 3.625258e2, 3.655595e2, + 3.686185e2, 3.717032e2, 3.748137e2, 3.779502e2, 3.811129e2, 3.843021e2, + 3.875180e2, 3.907608e2, 3.940308e2, 3.973281e2, 4.006530e2, 4.040057e2, + 4.073865e2, 4.107955e2, 4.142332e2, 4.176995e2, 4.211949e2, 4.247195e2, + 4.282736e2, 4.318575e2, 4.354713e2, 4.391154e2, 4.427900e2, 4.464953e2, + 4.502317e2, 4.539993e2, 4.577984e2, 4.616294e2, 4.654923e2, 4.693877e2, + 4.733156e2, 4.772763e2, 4.812703e2, 4.852976e2, 4.893587e2, 4.934537e2, + 4.975830e2, 5.017468e2, 5.059455e2, 5.101793e2, 5.144486e2, 5.187536e2, + 5.230946e2, 5.274719e2, 5.318859e2, 5.363368e2, 5.408249e2, 5.453506e2, + 5.499142e2, 5.545160e2, 5.591563e2, 5.638354e2, 5.685536e2, 5.733114e2, + 5.781089e2, 5.829466e2, 5.878248e2, 5.927438e2, 5.977040e2, 6.027057e2, + 6.077492e2, 6.128350e2, 6.179633e2, 6.231345e2, 6.283489e2, 6.336071e2, + 6.389092e2, 6.442557e2, 6.496469e2, 6.550832e2, 6.605651e2, 6.660928e2, + 6.716668e2, 6.772874e2, 6.829550e2, 6.886701e2, 6.944330e2, 7.002441e2, + 7.061038e2, 7.120126e2, 7.179709e2, 7.239790e2, 7.300373e2, 7.361464e2, + 7.423066e2, 7.485183e2, 7.547820e2, 7.610981e2, 7.674671e2, 7.738894e2, + 7.803654e2, 7.868957e2, 7.934805e2, 8.001205e2, 8.068160e2, 8.135676e2, + 8.203756e2, 8.272407e2, 8.341631e2, 8.411435e2, 8.481824e2, 8.552801e2, + 8.624372e2, 8.696542e2, 8.769316e2, 8.842699e2, 8.916696e2, 8.991312e2, + 9.066553e2, 9.142423e2, 9.218928e2, 9.296074e2, 9.373865e2, 9.452307e2, + 9.531405e2, 9.611165e2, 9.691593e2, 9.772694e2, 9.854473e2, 9.936937e2, + 1.002009e3, 1.010394e3, 1.018849e3, 1.027375e3, 1.035972e3, 1.044641e3, + 1.053383e3, 1.062198e3, 1.071087e3, 1.080050e3, 1.089088e3, 1.098201e3, + 1.107391e3, 1.116658e3, 1.126002e3, 1.135425e3, 1.144926e3, 1.154507e3, + 1.164168e3, 1.173910e3, 1.183734e3, 1.193639e3, 1.203628e3, 1.213700e3, + 1.223857e3, 1.234098e3, 1.244425e3, 1.254839e3, 1.265339e3, 1.275928e3, + 1.286605e3, 1.297372e3, 1.308228e3, 1.319176e3, 1.330215e3, 1.341346e3, + 1.352571e3, 1.363889e3, 1.375303e3, 1.386811e3, 1.398416e3, 1.410118e3, + 1.421919e3, 1.433817e3, 1.445816e3, 1.457915e3, 1.470115e3, 1.482417e3, + 1.494822e3, 1.507331e3, 1.519944e3, 1.532663e3, 1.545489e3, 1.558422e3, + 1.571463e3, 1.584613e3, 1.597874e3, 1.611245e3, 1.624728e3, 1.638324e3, + 1.652034e3, 1.665858e3, 1.679798e3, 1.693855e3, 1.708030e3, 1.722323e3, + 1.736735e3, 1.751268e3, 1.765923e3, 1.780701e3, 1.795602e3, 1.810628e3, + 1.825780e3, 1.841058e3, 1.856464e3, 1.871999e3, 1.887665e3, 1.903461e3, + 1.919389e3, 1.935451e3, 1.951647e3, 1.967979e3, 1.984447e3, 2.001053e3, + 2.017798e3, 2.034684e3, 2.051710e3, 2.068879e3, 2.086192e3, 2.103650e3, + 2.121253e3, 2.139004e3, 2.156904e3, 2.174953e3, 2.193153e3, 2.211506e3, + 2.230012e3, 2.248673e3, 2.267490e3, 2.286465e3, 2.305599e3, 2.324892e3, + 2.344347e3, 2.363965e3, 2.383747e3, 2.403695e3, 2.423809e3, 2.444092e3, + 2.464545e3, 2.485168e3, 2.505965e3, 2.526935e3, 2.548081e3, 2.569403e3, + 2.590904e3, 2.612586e3, 2.634448e3, 2.656494e3, 2.678723e3, 2.701139e3, + 2.723743e3, 2.746536e3, 2.769519e3, 2.792695e3, 2.816065e3, 2.839630e3, + 2.863392e3, 2.887354e3, 2.911515e3, 2.935879e3, 2.960447e3, 2.985221e3, + 3.010202e3, 3.035391e3, 3.060792e3, 3.086405e3, 3.112233e3, 3.138276e3, + 3.164538e3, 3.191019e3, 3.217722e3, 3.244649e3, 3.271800e3, 3.299179e3, + 3.326787e3, 3.354626e3, 3.382698e3, 3.411005e3, 3.439549e3, 3.468332e3, + 3.497355e3, 3.526622e3, 3.556133e3, 3.585891e3, 3.615898e3, 3.646157e3, + 3.676668e3, 3.707435e3, 3.738460e3, 3.769744e3, 3.801290e3, 3.833099e3, + 3.865175e3, 3.897520e3, 3.930135e3, 3.963023e3, 3.996186e3, 4.029627e3, + 4.063347e3, 4.097350e3, 4.131637e3, 4.166211e3, 4.201075e3, 4.236230e3, + 4.271679e3, 4.307425e3, 4.343471e3, 4.379817e3, 4.416468e3, 4.453426e3, + 4.490693e3, 4.528272e3, 4.566165e3, 4.604375e3, 4.642906e3, 4.681758e3, + 4.720936e3, 4.760441e3, 4.800277e3, 4.840447e3, 4.880952e3, 4.921797e3, + 4.962983e3, 5.004514e3, 5.046393e3, 5.088622e3, 5.131204e3, 5.174143e3, + 5.217441e3, 5.261101e3, 5.305127e3, 5.349521e3, 5.394287e3, 5.439427e3, + 5.484945e3, 5.530844e3, 5.577127e3, 5.623797e3, 5.670858e3, 5.718312e3, + 5.766164e3, 5.814416e3, 5.863072e3, 5.912135e3, 5.961609e3, 6.011496e3, + 6.061802e3, 6.112528e3, 6.163678e3, 6.215257e3, 6.267267e3, 6.319712e3, + 6.372597e3, 6.425924e3, 6.479697e3, 6.533920e3, 6.588597e3, 6.643731e3, + 6.699327e3, 6.755388e3, 6.811918e3, 6.868921e3, 6.926401e3, 6.984362e3, + 7.042809e3, 7.101744e3, 7.161172e3, 7.221098e3, 7.281525e3, 7.342458e3, + 7.403901e3, 7.465858e3, 7.528334e3, 7.591332e3, 7.654857e3, 7.718914e3, + 7.783507e3, 7.848641e3, 7.914319e3, 7.980548e3, 8.047330e3, 8.114671e3, + 8.182576e3, 8.251049e3, 8.320095e3, 8.389719e3, 8.459926e3, 8.530719e3, + 8.602106e3, 8.674090e3, 8.746676e3, 8.819869e3, 8.893675e3, 8.968099e3, + 9.043145e3, 9.118820e3, 9.195127e3, 9.272074e3, 9.349664e3, 9.427903e3, + 9.506797e3, 9.586352e3, 9.666572e3, 9.747463e3, 9.829031e3, 9.911282e3, + 9.994221e3, 1.007785e4, 1.016219e4, 1.024723e4, 1.033298e4, 1.041944e4, + 1.050664e4, 1.059456e4, 1.068321e4, 1.077261e4, 1.086276e4, 1.095366e4, + 1.104532e4, 1.113775e4, 1.123095e4, 1.132494e4, 1.141970e4, 1.151527e4, + 1.161163e4, 1.170880e4, 1.180678e4, 1.190558e4, 1.200521e4, 1.210567e4, + 1.220697e4, 1.230912e4, 1.241212e4, 1.251599e4, 1.262073e4, 1.272634e4, + 1.283283e4, 1.294022e4, 1.304851e4, 1.315770e4, 1.326780e4, 1.337883e4, + 1.349079e4, 1.360368e4, 1.371752e4, 1.383231e4, 1.394806e4, 1.406478e4, + 1.418247e4, 1.430116e4, 1.442083e4, 1.454151e4, 1.466319e4, 1.478590e4, + 1.490963e4, 1.503439e4, 1.516020e4, 1.528706e4, 1.541499e4, 1.554398e4, + 1.567406e4, 1.580522e4, 1.593748e4, 1.607085e4, 1.620533e4, 1.634094e4, + 1.647768e4, 1.661557e4, 1.675461e4, 1.689482e4, 1.703620e4, 1.717876e4, + 1.732251e4, 1.746747e4, 1.761364e4, 1.776104e4, 1.790966e4, 1.805953e4, + 1.821066e4, 1.836305e4, 1.851671e4, 1.867166e4, 1.882791e4, 1.898547e4, + 1.914434e4, 1.930454e4, 1.946608e4, 1.962898e4, 1.979324e4, 1.995887e4, + 2.012589e4, 2.029431e4, 2.046413e4, 2.063538e4, 2.080806e4, 2.098218e4, + 2.115777e4, 2.133482e4, 2.151335e4, 2.169338e4, 2.187491e4, 2.205796e4, + 2.224255e4, 2.242868e4, 2.261636e4, 2.280562e4, 2.299646e4, 2.318890e4, + 2.338295e4, 2.357862e4, 2.377593e4, 2.397489e4, 2.417552e4, 2.437782e4, + 2.458182e4, 2.478752e4, 2.499495e4, 2.520411e4, 2.541502e4, 2.562770e4, + 2.584215e4, 2.605841e4, 2.627647e4, 2.649635e4, 2.671808e4, 2.694166e4, + 2.700000e4, 2.716711e4, 2.739445e4, 2.762369e4, 2.785485e4, 2.808794e4, + 2.832299e4, 2.850000e4, 2.856000e4, 2.879899e4, 2.903999e4, 2.928300e4, + 2.952804e4, 2.977514e4, 3.002430e4, 3.027555e4, 3.052890e4, 3.078437e4, + 3.104198e4, 3.130174e4, 3.156368e4, 3.182781e4, 3.209415e4, 3.236272e4, + 3.263353e4, 3.290662e4, 3.318198e4, 3.345965e4, 3.373965e4, 3.402199e4, + 3.430669e4, 3.459377e4, 3.488326e4, 3.517517e4, 3.546952e4, 3.576633e4, + 3.606563e4, 3.636743e4, 3.667176e4, 3.697864e4, 3.728808e4, 3.760011e4, + 3.791476e4, 3.823203e4, 3.855196e4, 3.887457e4, 3.919988e4, 3.952791e4, + 3.985869e4, 4.019223e4, 4.052857e4, 4.086771e4, 4.120970e4, 4.155455e4, + 4.190229e4, 4.225293e4, 4.260651e4, 4.296305e4, 4.332257e4, 4.368510e4, + 4.405066e4, 4.441928e4, 4.479099e4, 4.516581e4, 4.554376e4, 4.592488e4, + 4.630919e4, 4.669671e4, 4.708747e4, 4.748151e4, 4.787884e4, 4.827950e4, + 4.868351e4, 4.909090e4, 4.950170e4, 4.991594e4, 5.033364e4, 5.075484e4, + 5.117957e4, 5.160785e4, 5.203971e4, 5.247518e4, 5.291430e4, 5.335710e4, + 5.380360e4, 5.425384e4, 5.470784e4, 5.516564e4, 5.562728e4, 5.609278e4, + 5.656217e4, 5.703549e4, 5.751277e4, 5.799405e4, 5.847935e4, 5.896871e4, + 5.946217e4, 5.995976e4, 6.046151e4, 6.096747e4, 6.147765e4, 6.199211e4, + 6.251086e4, 6.303396e4, 6.356144e4, 6.409333e4, 6.462968e4, 6.517051e4, + 6.571586e4, 6.626579e4, 6.682031e4, 6.737947e4, 6.794331e4, 6.851187e4, + 6.908519e4, 6.966330e4, 7.024626e4, 7.083409e4, 7.142684e4, 7.202455e4, + 7.262726e4, 7.323502e4, 7.384786e4, 7.446583e4, 7.508897e4, 7.571733e4, + 7.635094e4, 7.698986e4, 7.763412e4, 7.828378e4, 7.893887e4, 7.950000e4, + 7.959944e4, 8.026554e4, 8.093721e4, 8.161451e4, 8.229747e4, 8.250000e4, + 8.298615e4, 8.368059e4, 8.438084e4, 8.508695e4, 8.579897e4, 8.651695e4, + 8.724094e4, 8.797098e4, 8.870714e4, 8.944945e4, 9.019798e4, 9.095277e4, + 9.171388e4, 9.248135e4, 9.325525e4, 9.403563e4, 9.482253e4, 9.561602e4, + 9.641615e4, 9.722297e4, 9.803655e4, 9.885694e4, 9.968419e4, 1.005184e5, + 1.013595e5, 1.022077e5, 1.030630e5, 1.039254e5, 1.047951e5, 1.056720e5, + 1.065563e5, 1.074480e5, 1.083471e5, 1.092538e5, 1.101681e5, 1.110900e5, + 1.120196e5, 1.129570e5, 1.139022e5, 1.148554e5, 1.158165e5, 1.167857e5, + 1.177629e5, 1.187484e5, 1.197421e5, 1.207441e5, 1.217545e5, 1.227734e5, + 1.238008e5, 1.248368e5, 1.258814e5, 1.269348e5, 1.279970e5, 1.290681e5, + 1.301482e5, 1.312373e5, 1.323355e5, 1.334429e5, 1.345596e5, 1.356856e5, + 1.368210e5, 1.379660e5, 1.391205e5, 1.402847e5, 1.414586e5, 1.426423e5, + 1.438360e5, 1.450396e5, 1.462533e5, 1.474772e5, 1.487113e5, 1.499558e5, + 1.512106e5, 1.524760e5, 1.537519e5, 1.550385e5, 1.563359e5, 1.576442e5, + 1.589634e5, 1.602936e5, 1.616349e5, 1.629875e5, 1.643514e5, 1.657268e5, + 1.671136e5, 1.685120e5, 1.699221e5, 1.713441e5, 1.727779e5, 1.742237e5, + 1.756817e5, 1.771518e5, 1.786342e5, 1.801291e5, 1.816364e5, 1.831564e5, + 1.846891e5, 1.862346e5, 1.877930e5, 1.893645e5, 1.909491e5, 1.925470e5, + 1.941583e5, 1.957830e5, 1.974214e5, 1.990734e5, 2.007393e5, 2.024191e5, + 2.041130e5, 2.058210e5, 2.075434e5, 2.092801e5, 2.110314e5, 2.127974e5, + 2.145781e5, 2.163737e5, 2.181844e5, 2.200102e5, 2.218512e5, 2.237077e5, + 2.255797e5, 2.274674e5, 2.293709e5, 2.312903e5, 2.332258e5, 2.351775e5, + 2.371455e5, 2.391299e5, 2.411310e5, 2.431488e5, 2.451835e5, 2.472353e5, + 2.493042e5, 2.513904e5, 2.534941e5, 2.556153e5, 2.577544e5, 2.599113e5, + 2.620863e5, 2.642794e5, 2.664910e5, 2.687210e5, 2.709697e5, 2.732372e5, + 2.755237e5, 2.778293e5, 2.801543e5, 2.824986e5, 2.848626e5, 2.872464e5, + 2.896501e5, 2.920740e5, 2.945181e5, 2.969826e5, 2.972000e5, 2.985000e5, + 2.994678e5, 3.019738e5, 3.045008e5, 3.070489e5, 3.096183e5, 3.122093e5, + 3.148219e5, 3.174564e5, 3.201129e5, 3.227916e5, 3.254928e5, 3.282166e5, + 3.309631e5, 3.337327e5, 3.365254e5, 3.393415e5, 3.421812e5, 3.450446e5, + 3.479320e5, 3.508435e5, 3.537795e5, 3.567399e5, 3.597252e5, 3.627354e5, + 3.657708e5, 3.688317e5, 3.719181e5, 3.750304e5, 3.781687e5, 3.813333e5, + 3.845243e5, 3.877421e5, 3.909868e5, 3.942586e5, 3.975578e5, 4.008846e5, + 4.042393e5, 4.076220e5, 4.110331e5, 4.144727e5, 4.179410e5, 4.214384e5, + 4.249651e5, 4.285213e5, 4.321072e5, 4.357231e5, 4.393693e5, 4.430460e5, + 4.467535e5, 4.504920e5, 4.542618e5, 4.580631e5, 4.618963e5, 4.657615e5, + 4.696591e5, 4.735892e5, 4.775523e5, 4.815485e5, 4.855782e5, 4.896416e5, + 4.937390e5, 4.978707e5, 5.020369e5, 5.062381e5, 5.104743e5, 5.147461e5, + 5.190535e5, 5.233971e5, 5.277769e5, 5.321934e5, 5.366469e5, 5.411377e5, + 5.456660e5, 5.502322e5, 5.548366e5, 5.594796e5, 5.641614e5, 5.688824e5, + 5.736429e5, 5.784432e5, 5.832837e5, 5.881647e5, 5.930866e5, 5.980496e5, + 6.030542e5, 6.081006e5, 6.131893e5, 6.183206e5, 6.234948e5, 6.287123e5, + 6.339734e5, 6.392786e5, 6.446282e5, 6.500225e5, 6.554620e5, 6.609470e5, + 6.664779e5, 6.720551e5, 6.776790e5, 6.833499e5, 6.890683e5, 6.948345e5, + 7.006490e5, 7.065121e5, 7.124243e5, 7.183860e5, 7.243976e5, 7.304594e5, + 7.365720e5, 7.427358e5, 7.489511e5, 7.552184e5, 7.615382e5, 7.679109e5, + 7.743369e5, 7.808167e5, 7.873507e5, 7.939393e5, 8.005831e5, 8.072825e5, + 8.140380e5, 8.208500e5, 8.277190e5, 8.346455e5, 8.416299e5, 8.486728e5, + 8.557746e5, 8.629359e5, 8.701570e5, 8.774387e5, 8.847812e5, 8.921852e5, + 8.996511e5, 9.071795e5, 9.147709e5, 9.224259e5, 9.301449e5, 9.379285e5, + 9.457772e5, 9.536916e5, 9.616723e5, 9.697197e5, 9.778344e5, 9.860171e5, + 9.942682e5, 1.002588e6, 1.010978e6, 1.019438e6, 1.027969e6, 1.036571e6, + 1.045245e6, 1.053992e6, 1.062812e6, 1.071706e6, 1.080674e6, 1.089717e6, + 1.098836e6, 1.108032e6, 1.117304e6, 1.126654e6, 1.136082e6, 1.145588e6, + 1.155175e6, 1.164842e6, 1.174589e6, 1.184418e6, 1.194330e6, 1.204324e6, + 1.214402e6, 1.224564e6, 1.234812e6, 1.245145e6, 1.255564e6, 1.266071e6, + 1.276666e6, 1.287349e6, 1.298122e6, 1.308985e6, 1.319938e6, 1.330984e6, + 1.342122e6, 1.353353e6, 1.364678e6, 1.376098e6, 1.387613e6, 1.399225e6, + 1.410934e6, 1.422741e6, 1.434646e6, 1.446652e6, 1.458758e6, 1.470965e6, + 1.483274e6, 1.495686e6, 1.508202e6, 1.520823e6, 1.533550e6, 1.546383e6, + 1.559323e6, 1.572372e6, 1.585530e6, 1.598797e6, 1.612176e6, 1.625667e6, + 1.639271e6, 1.652989e6, 1.666821e6, 1.680770e6, 1.694834e6, 1.709017e6, + 1.723318e6, 1.737739e6, 1.752281e6, 1.766944e6, 1.781731e6, 1.796640e6, + 1.811675e6, 1.826835e6, 1.842122e6, 1.857538e6, 1.873082e6, 1.888756e6, + 1.904561e6, 1.920499e6, 1.936570e6, 1.952776e6, 1.969117e6, 1.985595e6, + 2.002210e6, 2.018965e6, 2.035860e6, 2.052897e6, 2.070076e6, 2.087398e6, + 2.104866e6, 2.122480e6, 2.140241e6, 2.158151e6, 2.176211e6, 2.194421e6, + 2.212785e6, 2.231302e6, 2.249973e6, 2.268802e6, 2.287787e6, 2.306932e6, + 2.326237e6, 2.345703e6, 2.365332e6, 2.385126e6, 2.405085e6, 2.425211e6, + 2.445505e6, 2.465970e6, 2.486605e6, 2.507414e6, 2.528396e6, 2.549554e6, + 2.570889e6, 2.592403e6, 2.614096e6, 2.635971e6, 2.658030e6, 2.680272e6, + 2.702701e6, 2.725318e6, 2.748124e6, 2.771121e6, 2.794310e6, 2.817693e6, + 2.841272e6, 2.865048e6, 2.889023e6, 2.913199e6, 2.937577e6, 2.962159e6, + 2.986947e6, 3.011942e6, 3.037147e6, 3.062562e6, 3.088190e6, 3.114032e6, + 3.140091e6, 3.166368e6, 3.192864e6, 3.219583e6, 3.246525e6, 3.273692e6, + 3.301087e6, 3.328711e6, 3.356566e6, 3.384654e6, 3.412978e6, 3.441538e6, + 3.470337e6, 3.499377e6, 3.528661e6, 3.558189e6, 3.587965e6, 3.617989e6, + 3.648265e6, 3.678794e6, 3.709579e6, 3.740621e6, 3.771924e6, 3.803488e6, + 3.835316e6, 3.867410e6, 3.899773e6, 3.932407e6, 3.965314e6, 3.998497e6, + 4.031957e6, 4.065697e6, 4.099719e6, 4.134026e6, 4.168620e6, 4.203504e6, + 4.238679e6, 4.274149e6, 4.309916e6, 4.345982e6, 4.382350e6, 4.419022e6, + 4.456001e6, 4.493290e6, 4.530890e6, 4.568805e6, 4.607038e6, 4.645590e6, + 4.684465e6, 4.723666e6, 4.763194e6, 4.803053e6, 4.843246e6, 4.883775e6, + 4.924643e6, 4.965853e6, 5.007408e6, 5.049311e6, 5.091564e6, 5.134171e6, + 5.177135e6, 5.220458e6, 5.264143e6, 5.308195e6, 5.352614e6, 5.397406e6, + 5.442572e6, 5.488116e6, 5.534042e6, 5.580351e6, 5.627049e6, 5.674137e6, + 5.721619e6, 5.769498e6, 5.817778e6, 5.866462e6, 5.915554e6, 5.965056e6, + 6.014972e6, 6.065307e6, 6.116062e6, 6.167242e6, 6.218851e6, 6.270891e6, + 6.323367e6, 6.376282e6, 6.429639e6, 6.483443e6, 6.537698e6, 6.592406e6, + 6.647573e6, 6.703200e6, 6.759294e6, 6.815857e6, 6.872893e6, 6.930406e6, + 6.988401e6, 7.046881e6, 7.105850e6, 7.165313e6, 7.225274e6, 7.285736e6, + 7.346704e6, 7.408182e6, 7.470175e6, 7.532687e6, 7.595721e6, 7.659283e6, + 7.723377e6, 7.788008e6, 7.853179e6, 7.918896e6, 7.985162e6, 8.051983e6, + 8.119363e6, 8.187308e6, 8.255820e6, 8.324906e6, 8.394570e6, 8.464817e6, + 8.535652e6, 8.607080e6, 8.679105e6, 8.751733e6, 8.824969e6, 8.898818e6, + 8.973284e6, 9.048374e6, 9.124092e6, 9.200444e6, 9.277435e6, 9.355070e6, + 9.433354e6, 9.512294e6, 9.591895e6, 9.672161e6, 9.753099e6, 9.834715e6, + 9.917013e6, 1.000000e7, 1.008368e7, 1.016806e7, 1.025315e7, 1.033895e7, + 1.042547e7, 1.051271e7, 1.060068e7, 1.068939e7, 1.077884e7, 1.086904e7, + 1.095999e7, 1.105171e7, 1.114419e7, 1.123745e7, 1.133148e7, 1.142631e7, + 1.152193e7, 1.161834e7, 1.171557e7, 1.181360e7, 1.191246e7, 1.201215e7, + 1.211267e7, 1.221403e7, 1.231624e7, 1.241930e7, 1.252323e7, 1.262802e7, + 1.273370e7, 1.284025e7, 1.294770e7, 1.305605e7, 1.316531e7, 1.327548e7, + 1.338657e7, 1.349859e7, 1.361155e7, 1.372545e7, 1.384031e7, 1.395612e7, + 1.407291e7, 1.419068e7, 1.430943e7, 1.442917e7, 1.454991e7, 1.467167e7, + 1.479444e7, 1.491825e7, 1.504309e7, 1.516897e7, 1.529590e7, 1.542390e7, + 1.555297e7, 1.568312e7, 1.581436e7, 1.594670e7, 1.608014e7, 1.621470e7, + 1.635039e7, 1.648721e7, 1.662518e7, 1.676430e7, 1.690459e7, 1.704605e7, + 1.718869e7, 1.733253e7, 1.747757e7, 1.762383e7, 1.777131e7, 1.792002e7, + 1.806998e7, 1.822119e7, 1.837367e7, 1.852742e7, 1.868246e7, 1.883880e7, + 1.899644e7, 1.915541e7, 1.931570e7, 1.947734e7, 1.964033e7]) From d0963a0a8a6707cb87863be675470071d88cb78e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 16 Aug 2022 16:52:23 +0100 Subject: [PATCH 0851/2654] renamed group name to match serpent reference --- openmc/mgxs/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index a3603f23d..14a0588a8 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -14,9 +14,8 @@ GROUP_STRUCTURES = {} - "SHEM-361_" designed for LWR analysis to eliminate self-shielding calculations of thermal resonances ([HFA2005]_, [SAN2007]_, [HEB2008]_) - "SCALE-44" designed for criticality analysis ([ZAL1999]_) -- "ECCO-2000" is a 1968-group neutron structure aimed at fine group reactor - cell calculations for fast, intermediate and thermal reactor applications. - ([SAR1990]_) +- "ECCO-1968" designed for fine group reactor cell calculations for fast, + intermediate and thermal reactor applications ([SAR1990]_) - activation_ energy group structures "VITAMIN-J-42", "VITAMIN-J-175", "TRIPOLI-315", "CCFE-709_" and "UKAEA-1102_" @@ -28,6 +27,7 @@ GROUP_STRUCTURES = {} .. _VITAMIN-J-42: https://www.oecd-nea.org/dbdata/nds_jefreports/jefreport-10.pdf .. _CCFE-709: https://fispact.ukaea.uk/wiki/CCFE-709_group_structure .. _UKAEA-1102: https://fispact.ukaea.uk/wiki/UKAEA-1102_group_structure +.. _ECCO-1968: http://serpent.vtt.fi/mediawiki/index.php/ECCO_1968-group_structure .. [SAR1990] Sartori, E., OECD/NEA Data Bank: Standard Energy Group Structures of Cross Section Libraries for Reactor Shielding, Reactor Cell and Fusion Neutronics Applications: VITAMIN-J, ECCO-33, ECCO-2000 and XMAS JEF/DOC-315 From 6c592fa1a054463d7a83e01adb2142076c504c95 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 16 Aug 2022 16:59:12 +0100 Subject: [PATCH 0852/2654] renamed 2000 to 1968 --- openmc/mgxs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index 14a0588a8..47a6af89b 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -642,7 +642,7 @@ GROUP_STRUCTURES['UKAEA-1102'] = np.array([ 5.7544e8, 6.0256e8, 6.3096e8, 6.6069e8, 6.9183e8, 7.2444e8, 7.5858e8, 7.9433e8, 8.3176e8, 8.7096e8, 9.1201e8, 9.5499e8, 1.e9]) -GROUP_STRUCTURES['ECCO-2000'] = np.array([ +GROUP_STRUCTURES['ECCO-1968'] = np.array([ 1.00001e-5, 3.00000e-3, 5.00000e-3, 6.90000e-3, 1.00000e-2, 1.50000e-2, 2.00000e-2, 2.50000e-2, 3.00000e-2, 3.50000e-2, 4.20000e-2, 5.00000e-2, 5.80000e-2, 6.70000e-2, 7.70000e-2, 8.00000e-2, 9.50000e-2, 1.00000e-1, From 209954ee2fb652db70b84596b5accd35afbb87bb Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Tue, 16 Aug 2022 13:08:35 -0500 Subject: [PATCH 0853/2654] change back to prevent accidental infinite recursion Co-authored-by: Patrick Shriwise --- openmc/lib/tally.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index 90983d171..dc782539b 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -390,7 +390,12 @@ class Tally(_FortranObjectWithID): class _TallyMapping(Mapping): def __getitem__(self, key): - return Tally(index=self[key]) + index = c_int32() + try: + _dll.openmc_get_tally_index(key, index) + except (AllocationError, InvalidIDError) as e: + # __contains__ expects a KeyError to work correctly + raise KeyError(str(e)) def __iter__(self): for i in range(len(self)): From 5b6c6667cbc082d438ea38708fd4da34b89b1a18 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 16 Aug 2022 13:43:15 -0500 Subject: [PATCH 0854/2654] put _get_tally_index(self,key) back and forgot return in __getitem__ --- openmc/lib/tally.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index dc782539b..5ddee90e4 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -396,6 +396,7 @@ class _TallyMapping(Mapping): except (AllocationError, InvalidIDError) as e: # __contains__ expects a KeyError to work correctly raise KeyError(str(e)) + return Tally(index=index.value) def __iter__(self): for i in range(len(self)): @@ -411,4 +412,14 @@ class _TallyMapping(Mapping): """Delete a tally from tally vector and remove the ID,index pair from tally""" _dll.openmc_remove_tally(self[key]._index) + def _get_tally_index(self,key): + """Given the ID, return the index""" + index = c_int32() + try: + _dll.openmc_get_tally_index(key, index) + except (AllocationError, InvalidIDError) as e: + # __contains__ expects a KeyError to work correctly + raise KeyError(str(e)) + return index.value + tallies = _TallyMapping() From a8b0f1714af39b2803055c6dc8288f22739bd8f2 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 16 Aug 2022 14:09:05 -0500 Subject: [PATCH 0855/2654] mistaken, dont need _get_tally_index, we call the openmc C++ api one instead --- openmc/lib/tally.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index 5ddee90e4..85af8ffff 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -412,14 +412,4 @@ class _TallyMapping(Mapping): """Delete a tally from tally vector and remove the ID,index pair from tally""" _dll.openmc_remove_tally(self[key]._index) - def _get_tally_index(self,key): - """Given the ID, return the index""" - index = c_int32() - try: - _dll.openmc_get_tally_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return index.value - tallies = _TallyMapping() From 37b17b61cf55cba9158528d968ab1332ec602548 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 16 Aug 2022 14:26:48 -0500 Subject: [PATCH 0856/2654] added openmc_remove_tally to documentation --- docs/source/capi/index.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index 222f81c4b..623c9fa5c 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -460,6 +460,14 @@ Functions :return: Return status (negative if an error occurs) :rtype: int +.. c:function:: int openmc_remove_tally(int32_t index); + + Given an index of a tally, remove it from the tallies vector + :param int index: Index in tallies vector + :return: Return status (negative if an error occurs) + :rtype: int + + .. c:function:: int openmc_run() Run a simulation From 5003cf482361061d35b0195166f6c87580571eba Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 16 Aug 2022 15:42:45 -0500 Subject: [PATCH 0857/2654] changed vector to array to match other entries, removed extra trailing space --- docs/source/capi/index.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index 623c9fa5c..52c0b2406 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -462,12 +462,11 @@ Functions .. c:function:: int openmc_remove_tally(int32_t index); - Given an index of a tally, remove it from the tallies vector - :param int index: Index in tallies vector + Given an index of a tally, remove it from the tallies array + :param int index: Index in tallies array :return: Return status (negative if an error occurs) :rtype: int - .. c:function:: int openmc_run() Run a simulation From d31b083685f7109348a817a12d9bb7e0ff079cba Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 16 Aug 2022 16:19:55 -0500 Subject: [PATCH 0858/2654] Address @yardasol review comments --- docs/source/releasenotes/0.13.1.rst | 16 +++++++++------- openmc/deplete/results.py | 3 +++ openmc/deplete/stepresult.py | 3 +++ openmc/mgxs/mgxs.py | 2 ++ openmc/model/surface_composite.py | 4 ++++ openmc/stats/multivariate.py | 7 +++++-- openmc/stats/univariate.py | 2 +- openmc/tracks.py | 6 +++++- 8 files changed, 32 insertions(+), 11 deletions(-) diff --git a/docs/source/releasenotes/0.13.1.rst b/docs/source/releasenotes/0.13.1.rst index 501d54090..4df31e456 100644 --- a/docs/source/releasenotes/0.13.1.rst +++ b/docs/source/releasenotes/0.13.1.rst @@ -13,11 +13,12 @@ geometry modeling, mesh functionality, source specification, depletion capabilities, and other general enhancements. The depletion module features a new transport operator, :class:`openmc.deplete.IndependentOperator`, that allows a depletion calculation to be performed using arbitrary one-group cross sections -(e.g., generated by an external solver). The track file generation capability -has been significantly overhauled and a new :class:`openmc.Tracks` class was -introduced to allow access to information in track files from the Python API. -Support has been added for new ENDF thermal scattering evaluations that use -mixed coherent/incoherent elastic scattering. +(e.g., generated by an external solver) along with a +:class:`openmc.deplete.MicroXS` class for managing one-group cross sections. The +track file generation capability has been significantly overhauled and a new +:class:`openmc.Tracks` class was introduced to allow access to information in +track files from the Python API. Support has been added for new ENDF thermal +scattering evaluations that use mixed coherent/incoherent elastic scattering. ------------------------------------ Compatibility Notes and Deprecations @@ -67,7 +68,8 @@ Compatibility Notes and Deprecations New Features ------------ -- An :class:`openmc.model.IsogonalOctagon` composite surface. +- Two new composite surfaces: :class:`openmc.model.IsogonalOctagon` and + :class:`openmc.model.CylinderSector`. - The :class:`~openmc.DAGMCUniverse` class now has a :attr:`~openmc.DAGMCUniverse.bounding_box` attribute and a :meth:`~openmc.DAGMCUniverse.bounding_region` method. @@ -98,7 +100,7 @@ New Features - An ``openmc_sample_external_source`` function has been added to the C API with a corresponding Python binding :func:`openmc.lib.sample_external_source`. - The track file generation capability has been completely overhauled. Track - files now include much more information, and a new :class:`~openmc.TrackFile` + files now include much more information, and a new :class:`~openmc.Tracks` class allows access to track file information from the Python API. Multiple tracks are now written to a single file (one per MPI rank). - A new :func:`openmc.wwinp_to_wws` function that converts weight windows from a diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index c2138b55c..b38dcf058 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -46,6 +46,9 @@ class Results(list): each depletion step and provides extra methods for interrogating these results. + .. versionchanged:: 0.13.1 + Name changed from ``ResultsList`` to ``Results`` + Parameters ---------- filename : str diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index c54f9edcf..db5260c80 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -23,6 +23,9 @@ __all__ = ["StepResult"] class StepResult: """Result of a single depletion timestep + .. versionchanged:: 0.13.1 + Name changed from ``Results`` to ``StepResult`` + Attributes ---------- k : list of (float, float) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index f9798c24a..46a6ed35c 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -3107,6 +3107,8 @@ class ReducedAbsorptionXS(MGXS): 3\sigma_{n,4n}(r,E) \right) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. + .. versionadded:: 0.13.1 + """ def __init__(self, domain=None, domain_type=None, energy_groups=None, diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 51019b0d8..4c76c7786 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -64,6 +64,8 @@ class CylinderSector(CompositeSurface): operators applied to it will produce a half-space. The negative side is defined to be the region inside of the cylinder sector. + .. versionadded:: 0.13.1 + Parameters ---------- r1 : float @@ -225,6 +227,8 @@ class IsogonalOctagon(CompositeSurface): operators applied to it will produce a half-space. The negative side is defined to be the region inside of the octogonal prism. + .. versionadded:: 0.13.1 + Parameters ---------- center : iterable of float diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 98c76ea67..f34bf0d1f 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -377,7 +377,10 @@ class SphericalIndependent(Spatial): :math:`\theta`, and :math:`\phi` components are sampled independently from one another and centered on the coordinates (x0, y0, z0). - .. versionadded: 0.12 + .. versionadded:: 0.12 + + .. versionchanged:: 0.13.1 + Accepts ``cos_theta`` instead of ``theta`` Parameters ---------- @@ -787,7 +790,7 @@ def spherical_uniform(r_outer, r_inner=0.0, thetas=(0., pi), phis=(0., 2*pi), shell between `r_inner` and `r_outer`. Optionally, the range of angles can be restricted by the `thetas` and `phis` arguments. - .. versionadded: 0.13.1 + .. versionadded:: 0.13.1 Parameters ---------- diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index d6b8a7573..5298499ce 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -1059,7 +1059,7 @@ class Tabular(Univariate): def integral(self): """Return integral of distribution - .. versionadded: 0.13.1 + .. versionadded:: 0.13.1 Returns ------- diff --git a/openmc/tracks.py b/openmc/tracks.py index 671aa65cf..15bd29727 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -47,6 +47,8 @@ class Track(Sequence): primary/secondary particle is stored in the :attr:`particle_tracks` attribute. + .. versionadded:: 0.13.1 + Parameters ---------- dset : h5py.Dataset @@ -201,6 +203,8 @@ class Tracks(list): This class behaves like a list and can be indexed using the normal subscript notation. Each element in the list is a :class:`openmc.Track` object. + .. versionadded:: 0.13.1 + Parameters ---------- filepath : str or pathlib.Path @@ -286,7 +290,7 @@ class Tracks(list): # Initialize data arrays and offset. points = vtk.vtkPoints() cells = vtk.vtkCellArray() - + point_offset = 0 for particle in self: for pt in particle.particle_tracks: From 282c8115dfd436e51e2ee5704917156d5b61ce43 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 16 Aug 2022 16:38:21 -0500 Subject: [PATCH 0859/2654] Fix error in equation in depletion user docs --- docs/source/usersguide/depletion.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 229e90a4c..e8dc21bca 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -14,7 +14,7 @@ are requested. The depletion module is designed such that the reaction rate solution (the transport "operator") is completely isolated from the solution of the -transmutation equations and the method used for advancing time. +transmutation equations and the method used for advancing time. :mod:`openmc.deplete` supports multiple time-integration methods for determining material compositions over time. Each method appears as a different class. @@ -40,7 +40,7 @@ time:: Note that the coupling between the reaction rate solver and the transmutation solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of transport operators for obtaining transmutation reaction -rates. +rates. .. _coupled-depletion: @@ -65,7 +65,7 @@ Any material that contains a fissionable nuclide is depleted by default, but this can behavior can be changed with the :attr:`Material.depletable` attribute. .. important:: - + The volume must be specified for each material that is depleted by setting the :attr:`Material.volume` attribute. This is necessary in order to calculate the proper normalization of tally results based on the source rate. @@ -198,8 +198,8 @@ Transport-independent depletion =============================== .. warning:: - - This feature is still under heavy development and has yet to be rigorously + + This feature is still under heavy development and has yet to be rigorously verified. API changes and feature additions are possible and likely in the near future. @@ -237,7 +237,7 @@ object:: 'U236': 4.57e18, 'O16': 4.64e22, 'O17': 1.76e19} - volume = 0.5 + volume = 0.5 op = openmc.deplete.IndependentOperator.from_nuclides(volume, nuclides, micro_xs, @@ -250,8 +250,8 @@ transport-depletion calculation and follow the same steps from there. .. note:: Ideally, one-group cross section data should be available for every - reaction in the depletion chain. If a nuclide that has a reaction - associated with it in the depletion chain is present in the `nuclides` + reaction in the depletion chain. If a nuclide that has a reaction + associated with it in the depletion chain is present in the `nuclides` parameter but not the cross section data, that reaction will not be simulated. @@ -289,7 +289,7 @@ or from data arrays:: .. important:: Both :meth:`~openmc.deplete.MicroXS.from_csv()` and - :meth:`~openmc.deplete.MicroXS.from_array()` assume the cross section values + :meth:`~openmc.deplete.MicroXS.from_array()` assume the cross section values provided are in barns by defualt, but have no way of verifying this. Make sure your cross sections are in the correct units before passing to a :class:`~openmc.deplete.IndependentOperator` object. @@ -315,11 +315,11 @@ normalizing reaction rates: the cross-sections by the ``source-rate``. 2. ``fission-q`` normalization, which uses the ``power`` or ``power_density`` provided by the time integrator to obtain reaction rates by computing a value - for the flux based on this power. The general equation for the flux is + for the flux based on this power. The general equation for the flux is .. math:: - \phi = \frac{P}{V \cdot \sum_i (Q_i \cdot \sigma^f_i \cdot \n_i)} + \phi = \frac{P}{V \cdot \sum\limits_i (Q_i \cdot \sigma^f_i \cdot n_i)} where :math:`\sum_i` is the sum over all nuclides :math:`i`. This equation makes the same assumptions and issues as discussed in @@ -328,13 +328,13 @@ normalizing reaction rates: However, there is a method to converge to a more accurate value for flux by using substeps during time integration. `This paper `_ provides a - good discussion of this method. + good discussion of this method. .. warning:: The accuracy of results when using ``fission-q`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the - dynamics of your particular scenario. + dynamics of your particular scenario. Multiple Materials ~~~~~~~~~~~~~~~~~~ From bee89f2c1ac10f728af0fec1e26093b0baf8c4a4 Mon Sep 17 00:00:00 2001 From: yardasol Date: Tue, 16 Aug 2022 18:10:05 -0500 Subject: [PATCH 0860/2654] cleanup rxn rate calculation in _IndependentRateHelper --- openmc/deplete/independent_operator.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index 20267f948..200bc195e 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -272,15 +272,15 @@ class IndependentOperator(OpenMCOperator): This class does not generate tallies, and instead stores cross sections for each nuclide and transmutation reaction relevant for a depletion - calculation. The reaction rate is calculated by multiplying the flux by the - cross sections. + calculation. The reaction rate is calculated by multiplying the flux by + the cross sections. Parameters ---------- op : openmc.deplete.IndependentOperator Reference to the object encapsulate _IndependentRateHelper. - We pass this so we don't have to duplicate the :attr:`IndependentOperator.number` object. - + We pass this so we don't have to duplicate the + :attr:`IndependentOperator.number` object. Attributes ---------- @@ -317,15 +317,14 @@ class IndependentOperator(OpenMCOperator): """ self._results_cache.fill(0.0) - volume = self._op.number.get_mat_volume(mat_id) for i_nuc, i_react in product(nuc_index, react_index): nuc = self.nuc_ind_map[i_nuc] rxn = self.rxn_ind_map[i_react] - density = self._op.number.get_atom_density(mat_id, nuc) - # Sigma^j_i * V = sigma^j_i * rho * V + # Sigma^j_i * V = sigma^j_i * n_i * V = sigma^j_i * N_i self._results_cache[i_nuc,i_react] = \ - self._op.cross_sections[rxn][nuc] * density * volume + self._op.cross_sections[rxn][nuc] * \ + self._op.number[mat_id, nuc] return self._results_cache From aec246be729c1e91f73b081fcbdfc0a2230c17cb Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 16 Aug 2022 22:09:58 -0500 Subject: [PATCH 0861/2654] Rename Tracks.write_tracks_to_vtk --> Tracks.write_to_vtk --- docs/source/releasenotes/0.13.1.rst | 3 ++- openmc/tracks.py | 2 +- scripts/openmc-track-to-vtk | 2 +- tests/unit_tests/test_tracks.py | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/releasenotes/0.13.1.rst b/docs/source/releasenotes/0.13.1.rst index 4df31e456..70c8609ac 100644 --- a/docs/source/releasenotes/0.13.1.rst +++ b/docs/source/releasenotes/0.13.1.rst @@ -101,7 +101,8 @@ New Features a corresponding Python binding :func:`openmc.lib.sample_external_source`. - The track file generation capability has been completely overhauled. Track files now include much more information, and a new :class:`~openmc.Tracks` - class allows access to track file information from the Python API. Multiple + class allows access to track file information from the Python API and has a + :meth:`~openmc.Tracks.write_to_vtk` method for writing a VTK file. Multiple tracks are now written to a single file (one per MPI rank). - A new :func:`openmc.wwinp_to_wws` function that converts weight windows from a ``wwinp`` file to a list of :class:`~openmc.WeightWindows` objects. diff --git a/openmc/tracks.py b/openmc/tracks.py index 15bd29727..9b4b55247 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -271,7 +271,7 @@ class Tracks(list): track.plot(ax) return ax - def write_tracks_to_vtk(self, filename=Path('tracks.vtp')): + def write_to_vtk(self, filename=Path('tracks.vtp')): """Creates a VTP file of the tracks Parameters diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index 118e65827..82439bea7 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -35,7 +35,7 @@ def main(): # Write coordinate values to points array. track_file = openmc.Tracks(args.input) - track_file.write_tracks_to_vtk(args.out) + track_file.write_to_vtk(args.out) if __name__ == '__main__': main() diff --git a/tests/unit_tests/test_tracks.py b/tests/unit_tests/test_tracks.py index 5f3940fad..be75c6f88 100644 --- a/tests/unit_tests/test_tracks.py +++ b/tests/unit_tests/test_tracks.py @@ -143,7 +143,7 @@ def test_filter(sphere_model, run_in_tmpdir): assert matches == [] -def test_write_tracks_to_vtk(sphere_model): +def test_write_to_vtk(sphere_model): vtk = pytest.importorskip('vtk') # Set maximum number of tracks per process to write sphere_model.settings.max_tracks = 25 @@ -153,7 +153,7 @@ def test_write_tracks_to_vtk(sphere_model): generate_track_file(sphere_model, tracks=True) tracks = openmc.Tracks('tracks.h5') - polydata = tracks.write_tracks_to_vtk('tracks.vtp') + polydata = tracks.write_to_vtk('tracks.vtp') assert isinstance(polydata, vtk.vtkPolyData) assert Path('tracks.vtp').is_file() From 6e1e18ab36fbaaec882d6f62010d3fbd98e81347 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 16 Aug 2022 22:18:55 -0500 Subject: [PATCH 0862/2654] Define terms in flux equation for depletion docs --- docs/source/usersguide/depletion.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index e8dc21bca..2d03e167b 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -319,16 +319,18 @@ normalizing reaction rates: .. math:: - \phi = \frac{P}{V \cdot \sum\limits_i (Q_i \cdot \sigma^f_i \cdot n_i)} + \phi = \frac{P}{\sum\limits_i (Q_i \sigma^f_i n_i)} - where :math:`\sum_i` is the sum over all nuclides :math:`i`. This equation - makes the same assumptions and issues as discussed in - :ref:`energy-deposition`. Unfortunately, the proposed solution in that + where :math:`P` is the power, :math:`Q_i` is the fission Q value for nuclide + :math:`i`, :math:`\sigma_i^f` is the microscopic fission cross section for + nuclide :math:`i`, and :math:`N_i` is the number of atoms of nuclide + :math:`i`. This equation makes the same assumptions and issues as discussed + in :ref:`energy-deposition`. Unfortunately, the proposed solution in that section does not apply here since we are decoupled from transport code. However, there is a method to converge to a more accurate value for flux by - using substeps during time integration. - `This paper `_ provides a - good discussion of this method. + using substeps during time integration. `This paper + `_ provides a good discussion + of this method. .. warning:: From 9b458c102a22a2bbad947abafdb44de9d7f32770 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 17 Aug 2022 07:28:50 +0100 Subject: [PATCH 0863/2654] Review suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/mgxs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index 47a6af89b..459b6a874 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -14,7 +14,7 @@ GROUP_STRUCTURES = {} - "SHEM-361_" designed for LWR analysis to eliminate self-shielding calculations of thermal resonances ([HFA2005]_, [SAN2007]_, [HEB2008]_) - "SCALE-44" designed for criticality analysis ([ZAL1999]_) -- "ECCO-1968" designed for fine group reactor cell calculations for fast, +- "ECCO-1968_" designed for fine group reactor cell calculations for fast, intermediate and thermal reactor applications ([SAR1990]_) - activation_ energy group structures "VITAMIN-J-42", "VITAMIN-J-175", "TRIPOLI-315", "CCFE-709_" and "UKAEA-1102_" From 630117aab50172dd6659d36084b094dcf2148945 Mon Sep 17 00:00:00 2001 From: myerspat Date: Wed, 17 Aug 2022 08:19:22 -0400 Subject: [PATCH 0864/2654] Added return for a parenthesis depth of 0 --- src/cell.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/cell.cpp b/src/cell.cpp index a663d1144..6b4fcafda 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -869,6 +869,7 @@ bool CSGCell::contains_complex( Position r, Direction u, int32_t on_surface) const { bool in_cell = true; + int total_depth = 0; // For each token for (auto it = region_infix_.begin(); it != region_infix_.end(); it++) { @@ -889,6 +890,13 @@ bool CSGCell::contains_complex( } } else if ((token == OP_UNION && in_cell == true) || (token == OP_INTERSECTION && in_cell == false)) { + // If the total depth is zero return + if (total_depth == 0) { + return in_cell; + } + + total_depth--; + // While the iterator is within the bounds of the vector int depth = 1; do { @@ -905,7 +913,11 @@ bool CSGCell::contains_complex( depth++; } } - } while (depth > 0 && it < region_infix_.end() - 1); + } while (depth > 0); + } else if (token == OP_LEFT_PAREN) { + total_depth++; + } else if (token == OP_RIGHT_PAREN) { + total_depth--; } } return in_cell; From 2a7a6b171ed59dd8c6d2ed599be4151549c50015 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 17 Aug 2022 09:26:46 -0500 Subject: [PATCH 0865/2654] Fix flux equation per @yardasol suggestion Co-authored-by: Olek <45364492+yardasol@users.noreply.github.com> --- docs/source/usersguide/depletion.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 2d03e167b..be9406182 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -319,7 +319,7 @@ normalizing reaction rates: .. math:: - \phi = \frac{P}{\sum\limits_i (Q_i \sigma^f_i n_i)} + \phi = \frac{P}{\sum\limits_i (Q_i \sigma^f_i N_i)} where :math:`P` is the power, :math:`Q_i` is the fission Q value for nuclide :math:`i`, :math:`\sigma_i^f` is the microscopic fission cross section for From 9897fe372797d72fd14d285bad3f8ef2c91b451c Mon Sep 17 00:00:00 2001 From: James Logan Date: Wed, 17 Aug 2022 13:45:50 -0400 Subject: [PATCH 0866/2654] add pass-through to allow plotting geometry on existing axes --- openmc/universe.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 4aa1775fb..c95a80f06 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -360,12 +360,15 @@ class Universe(UniverseBase): # Create a figure sized such that the size of the axes within # exactly matches the number of pixels specified - px = 1/plt.rcParams['figure.dpi'] - fig, ax = plt.subplots() - params = fig.subplotpars - width = pixels[0]*px/(params.right - params.left) - height = pixels[0]*px/(params.top - params.bottom) - fig.set_size_inches(width, height) + if kwargs.get("ax") is None: + px = 1/plt.rcParams['figure.dpi'] + fig, ax = plt.subplots() + params = fig.subplotpars + width = pixels[0]*px/(params.right - params.left) + height = pixels[0]*px/(params.top - params.bottom) + fig.set_size_inches(width, height) + else: + ax = kwargs.pop("ax") # Plot image and return the axes return ax.imshow(img, extent=(x_min, x_max, y_min, y_max), **kwargs) From 3bdf2ddfc88fad57024163eca70999c18f89f278 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 18 Aug 2022 09:35:04 -0500 Subject: [PATCH 0867/2654] Remove -dev tag from version number (0.13.1) --- docs/source/conf.py | 2 +- include/openmc/version.h.in | 2 +- openmc/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index a7a3c803a..4f88314f6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -71,7 +71,7 @@ copyright = '2011-2022, Massachusetts Institute of Technology, UChicago Argonne # The short X.Y version. version = "0.13" # The full version, including alpha/beta/rc tags. -release = "0.13.1-dev" +release = "0.13.1" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index e1c2b0541..a518e0d63 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -10,7 +10,7 @@ namespace openmc { constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {true}; +constexpr bool VERSION_DEV {false}; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/openmc/__init__.py b/openmc/__init__.py index e63e9e4d1..7ed9009a2 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -37,4 +37,4 @@ from . import examples from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.13.1-dev' +__version__ = '0.13.1' From 0ef945cc06aac18517d5ca1825bf1c876e843633 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 18 Aug 2022 14:55:56 -0500 Subject: [PATCH 0868/2654] removing set_strides() from tally.cpp causes issues, but it should be fine to add in openmc_simulation_init() and in there should occur before init_results. this is because init_results use n_filter_bins_ which is modified by set_strides() --- src/simulation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/simulation.cpp b/src/simulation.cpp index b70535c33..d7292cb9d 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -97,6 +97,7 @@ int openmc_simulation_init() // Allocate tally results arrays if they're not allocated yet for (auto& t : model::tallies) { + t->set_strides(); t->init_results(); } From 53b85e0c9628945609a5965b38b188dbcf258b28 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 19 Aug 2022 07:16:31 -0500 Subject: [PATCH 0869/2654] Change version number to 0.14.0-dev --- CMakeLists.txt | 4 ++-- docs/source/conf.py | 4 ++-- include/openmc/version.h.in | 2 +- openmc/__init__.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e949070c..995480372 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ project(openmc C CXX) # Set version numbers set(OPENMC_VERSION_MAJOR 0) -set(OPENMC_VERSION_MINOR 13) -set(OPENMC_VERSION_RELEASE 1) +set(OPENMC_VERSION_MINOR 14) +set(OPENMC_VERSION_RELEASE 0) set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4f88314f6..98ccdee44 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -69,9 +69,9 @@ copyright = '2011-2022, Massachusetts Institute of Technology, UChicago Argonne # built documents. # # The short X.Y version. -version = "0.13" +version = "0.14" # The full version, including alpha/beta/rc tags. -release = "0.13.1" +release = "0.14.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index a518e0d63..e1c2b0541 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -10,7 +10,7 @@ namespace openmc { constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {false}; +constexpr bool VERSION_DEV {true}; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/openmc/__init__.py b/openmc/__init__.py index 7ed9009a2..abcac899f 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -37,4 +37,4 @@ from . import examples from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.13.1' +__version__ = '0.14.0-dev' From 085125ef866f62cb4f0486385d5c299fde550219 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 23 Aug 2022 16:30:53 +0100 Subject: [PATCH 0870/2654] added optional nuclide to atom densities --- openmc/material.py | 21 ++++++++++++++------- tests/unit_tests/test_material.py | 7 +++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 167eaba84..16b5923d7 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -825,9 +825,15 @@ class Material(IDManagerMixin): return nuclides - def get_nuclide_atom_densities(self): - """Returns all nuclides in the material and their atomic densities in - units of atom/b-cm + def get_nuclide_atom_densities(self, nuclide: Optional[str] = None): + """Returns one or all nuclides in the material and their atomic + densities in units of atom/b-cm + + Parameters + ---------- + nuclides : str, optional + Nuclide for which atom density is desired. If not specified, the + atom density for the all the material is given. .. versionchanged:: 0.13.1 The values in the dictionary were changed from a tuple containing @@ -862,10 +868,11 @@ class Material(IDManagerMixin): nuc_densities = [] nuc_density_types = [] - for nuclide in self.nuclides: - nucs.append(nuclide.name) - nuc_densities.append(nuclide.percent) - nuc_density_types.append(nuclide.percent_type) + for loop_nuclide in self.nuclides: + if nuclide is None or nuclide == loop_nuclide.name: + nucs.append(loop_nuclide.name) + nuc_densities.append(loop_nuclide.percent) + nuc_density_types.append(loop_nuclide.percent_type) nucs = np.array(nucs) nuc_densities = np.array(nuc_densities) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 451c5308a..1e5b8a797 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -339,6 +339,13 @@ def test_get_nuclide_atom_densities(uo2): assert density > 0 +def test_get_specific_nuclide_atom_densities(uo2): + print(uo2) + nuc = uo2.get_nuclide_atom_densities(nuclide='O16') + assert list(nuc.keys()) == ['O16'] + assert list(nuc.values())[0] > 0 + + def test_get_nuclide_atoms(): mat = openmc.Material() mat.add_nuclide('Li6', 1.0) From 6171e09ed3c65d822623815fb62ffc8d83812a3a Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 23 Aug 2022 16:42:22 +0100 Subject: [PATCH 0871/2654] improved test fixed sum bug --- openmc/material.py | 10 +++++----- tests/unit_tests/test_material.py | 10 +++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 16b5923d7..f83c63c14 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -869,10 +869,9 @@ class Material(IDManagerMixin): nuc_density_types = [] for loop_nuclide in self.nuclides: - if nuclide is None or nuclide == loop_nuclide.name: - nucs.append(loop_nuclide.name) - nuc_densities.append(loop_nuclide.percent) - nuc_density_types.append(loop_nuclide.percent_type) + nucs.append(loop_nuclide.name) + nuc_densities.append(loop_nuclide.percent) + nuc_density_types.append(loop_nuclide.percent_type) nucs = np.array(nucs) nuc_densities = np.array(nuc_densities) @@ -904,7 +903,8 @@ class Material(IDManagerMixin): nuclides = OrderedDict() for n, nuc in enumerate(nucs): - nuclides[nuc] = nuc_densities[n] + if nuclide is None or nuclide == nuc: + nuclides[nuc] = nuc_densities[n] return nuclides diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 1e5b8a797..f841c805b 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -341,9 +341,13 @@ def test_get_nuclide_atom_densities(uo2): def test_get_specific_nuclide_atom_densities(uo2): print(uo2) - nuc = uo2.get_nuclide_atom_densities(nuclide='O16') - assert list(nuc.keys()) == ['O16'] - assert list(nuc.values())[0] > 0 + one_nuc = uo2.get_nuclide_atom_densities(nuclide='O16') + assert list(one_nuc.keys()) == ['O16'] + assert list(one_nuc.values())[0] > 0 + + all_nuc = uo2.get_nuclide_atom_densities() + assert all_nuc['O16'] == one_nuc['O16'] + def test_get_nuclide_atoms(): From 2a71a244d983a645dc8e3ade5972cec494d4b930 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 23 Aug 2022 16:44:56 +0100 Subject: [PATCH 0872/2654] if statement no longer needed --- openmc/material.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index f83c63c14..957e0ba2d 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -984,11 +984,10 @@ class Material(IDManagerMixin): """ mass_density = 0.0 - for nuc, atoms_per_bcm in self.get_nuclide_atom_densities().items(): - if nuclide is None or nuclide == nuc: - density_i = 1e24 * atoms_per_bcm * openmc.data.atomic_mass(nuc) \ - / openmc.data.AVOGADRO - mass_density += density_i + for nuc, atoms_per_bcm in self.get_nuclide_atom_densities(nuclide=nuclide).items(): + density_i = 1e24 * atoms_per_bcm * openmc.data.atomic_mass(nuc) \ + / openmc.data.AVOGADRO + mass_density += density_i return mass_density def get_mass(self, nuclide: Optional[str] = None): From dc6e2266fb5a57265fa7f46751aee80f0bd0139c Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Tue, 23 Aug 2022 16:57:34 -0500 Subject: [PATCH 0873/2654] removed set_strides() from set_filters(). determined my tests were weird locally and this was not causing them to fail --- src/tallies/tally.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 59adce455..11d5b245f 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -374,9 +374,6 @@ void Tally::set_filters(gsl::span filters) delayedgroup_filter_ = i; } } - - // Set the strides. - set_strides(); } void Tally::set_strides() From 1e55089e9d67cbf4a11c0b0487521958c1d9fde2 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 23 Aug 2022 23:20:18 +0100 Subject: [PATCH 0874/2654] [skip ci] removed print statement --- tests/unit_tests/test_material.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index f841c805b..ce9bc2122 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -340,7 +340,6 @@ def test_get_nuclide_atom_densities(uo2): def test_get_specific_nuclide_atom_densities(uo2): - print(uo2) one_nuc = uo2.get_nuclide_atom_densities(nuclide='O16') assert list(one_nuc.keys()) == ['O16'] assert list(one_nuc.values())[0] > 0 From 08f026496b88e427abdbe3bfab77ed7825a6dbc3 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 23 Aug 2022 23:20:59 +0100 Subject: [PATCH 0875/2654] [skip ci] removed blank line pep8 --- tests/unit_tests/test_material.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index ce9bc2122..9425da44f 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -348,7 +348,6 @@ def test_get_specific_nuclide_atom_densities(uo2): assert all_nuc['O16'] == one_nuc['O16'] - def test_get_nuclide_atoms(): mat = openmc.Material() mat.add_nuclide('Li6', 1.0) From fb8b4e0690f0d8b304e5bc4ed6600a608780f596 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 24 Aug 2022 10:50:40 +0100 Subject: [PATCH 0876/2654] added main method to voxel script --- scripts/openmc-voxel-to-vtk | 64 ++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/scripts/openmc-voxel-to-vtk b/scripts/openmc-voxel-to-vtk index 33251144f..01b4808d2 100755 --- a/scripts/openmc-voxel-to-vtk +++ b/scripts/openmc-voxel-to-vtk @@ -1,54 +1,46 @@ #!/usr/bin/env python3 -import struct -import sys from argparse import ArgumentParser -import numpy as np import h5py import vtk _min_version = (2, 0) -def main(): - # Process command line arguments - parser = ArgumentParser() - parser.add_argument('voxel_file', help='Path to voxel file') - parser.add_argument('-o', '--output', action='store', - default='plot', help='Path to output VTK file.') - args = parser.parse_args() +def voxel_to_vtk(voxel_file: str, output: str): # Read data from voxel file - fh = h5py.File(args.voxel_file, 'r') + fh = h5py.File(voxel_file, "r") # check version - version = tuple(fh.attrs['version']) + version = tuple(fh.attrs["version"]) if version < _min_version: - old_version = ".".join(map(str,version)) - min_version = ".".join(map(str,_min_version)) - err_msg = "This voxel file's version is {}. This script " \ - "only supports voxel files with version {} or " \ - "higher. Please generate a new voxel file using " \ - "a newer version of OpenMC.".format(old_version, min_version) + old_version = ".".join(map(str, version)) + min_version = ".".join(map(str, _min_version)) + err_msg = ( + "This voxel file's version is {}. This script " + "only supports voxel files with version {} or " + "higher. Please generate a new voxel file using " + "a newer version of OpenMC.".format(old_version, min_version) + ) raise ValueError(err_msg) - dimension = fh.attrs['num_voxels'] - width = fh.attrs['voxel_width'] - lower_left = fh.attrs['lower_left'] + dimension = fh.attrs["num_voxels"] + width = fh.attrs["voxel_width"] + lower_left = fh.attrs["lower_left"] nx, ny, nz = dimension - upper_right = lower_left + width*dimension grid = vtk.vtkImageData() - grid.SetDimensions(nx+1, ny+1, nz+1) + grid.SetDimensions(nx + 1, ny + 1, nz + 1) grid.SetOrigin(*lower_left) grid.SetSpacing(*width) # transpose data from OpenMC ordering (zyx) to VTK ordering (xyz) # and flatten to 1-D array print("Reading and translating data...") - h5data = fh['data'][...] + h5data = fh["data"][...] data = vtk.vtkIntArray() data.SetName("id") @@ -62,11 +54,23 @@ def main(): writer.SetInputData(grid) else: writer.SetInput(grid) - if not args.output.endswith(".vti"): - args.output += ".vti" - writer.SetFileName(args.output) - print("Writing VTK file {}...".format(args.output)) + if not output.endswith(".vti"): + output += ".vti" + writer.SetFileName(output) + print("Writing VTK file {}...".format(output)) writer.Write() -if __name__ == '__main__': - main() + +if __name__ == "__main__": + # Process command line arguments + parser = ArgumentParser('Converts a voxel HDF5 file to a VTK file') + parser.add_argument("voxel_file", help="Path to voxel h5 file") + parser.add_argument( + "-o", + "--output", + action="store", + default="plot", + help="Path to output VTK file.", + ) + args = parser.parse_args() + voxel_to_vtk(args.voxel_file, args.output) From 8aa7b40c412a999227281f51824fb6d684433398 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 24 Aug 2022 12:20:10 +0100 Subject: [PATCH 0877/2654] added main to ace-to-hdf5 --- scripts/openmc-ace-to-hdf5 | 194 +++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 85 deletions(-) diff --git a/scripts/openmc-ace-to-hdf5 b/scripts/openmc-ace-to-hdf5 index 7c391fd6f..d7eb488f7 100755 --- a/scripts/openmc-ace-to-hdf5 +++ b/scripts/openmc-ace-to-hdf5 @@ -28,102 +28,126 @@ import openmc.data from openmc.data.ace import TableType -class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, - argparse.RawDescriptionHelpFormatter): - pass +def ace_to_hdf5(destination, xsdir, xsdata, libraries, metastable, libver): + if not destination.is_dir(): + destination.mkdir(parents=True, exist_ok=True) -parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=CustomFormatter -) -parser.add_argument('libraries', nargs='*', - help='ACE libraries to convert to HDF5') -parser.add_argument('-d', '--destination', type=Path, default=Path.cwd(), - help='Directory to create new library in') -parser.add_argument('-m', '--metastable', choices=['mcnp', 'nndc'], - default='nndc', - help='How to interpret ZAIDs for metastable nuclides') -parser.add_argument('--xsdir', help='MCNP xsdir file that lists ' - 'ACE libraries') -parser.add_argument('--xsdata', help='Serpent xsdata file that lists ' - 'ACE libraries') -parser.add_argument('--libver', choices=['earliest', 'latest'], - default='earliest', help="Output HDF5 versioning. Use " - "'earliest' for backwards compatibility or 'latest' for " - "performance") -args = parser.parse_args() + ace_libraries = [] + if xsdir is not None: + ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdir(xsdir)) + elif xsdata is not None: + ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdata(xsdata)) + else: + ace_libraries = [Path(lib) for lib in libraries] -if not args.destination.is_dir(): - args.destination.mkdir(parents=True, exist_ok=True) + converted = {} + library = openmc.data.DataLibrary() -ace_libraries = [] -if args.xsdir is not None: - ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdir(args.xsdir)) -elif args.xsdata is not None: - ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdata(args.xsdata)) -else: - ace_libraries = [Path(lib) for lib in args.libraries] - -converted = {} -library = openmc.data.DataLibrary() - -for path in ace_libraries: - # Check that ACE library exists - if not os.path.exists(path): - warnings.warn("ACE library '{}' does not exist.".format(path)) - continue - - lib = openmc.data.ace.Library(path) - for table in lib.tables: - # Check type of the ACE table and determine appropriate class / - # conversion function - if table.data_type == TableType.NEUTRON_CONTINUOUS: - name = table.zaid - cls = openmc.data.IncidentNeutron - converter = partial(cls.from_ace, metastable_scheme=args.metastable) - elif table.data_type == TableType.THERMAL_SCATTERING: - # Adjust name to be the new thermal scattering name - name = openmc.data.get_thermal_name(table.zaid) - cls = openmc.data.ThermalScattering - converter = cls.from_ace - else: - print("Can't convert ACE table {}".format(table.name)) + for path in ace_libraries: + # Check that ACE library exists + if not os.path.exists(path): + warnings.warn(f"ACE library '{path}' does not exist.") continue - if name not in converted: - try: - data = converter(table) - except Exception as e: - print('Failed to convert {}: {}'.format(table.name, e)) + lib = openmc.data.ace.Library(path) + for table in lib.tables: + # Check type of the ACE table and determine appropriate class / + # conversion function + if table.data_type == TableType.NEUTRON_CONTINUOUS: + name = table.zaid + cls = openmc.data.IncidentNeutron + converter = partial(cls.from_ace, metastable_scheme=metastable) + elif table.data_type == TableType.THERMAL_SCATTERING: + # Adjust name to be the new thermal scattering name + name = openmc.data.get_thermal_name(table.zaid) + cls = openmc.data.ThermalScattering + converter = cls.from_ace + else: + print(f"Can't convert ACE table {table.name}") continue - print('Converting {} (ACE) to {} (HDF5)'.format(table.name, data.name)) + if name not in converted: + try: + data = converter(table) + except Exception as e: + print(f"Failed to convert {table.name}: {e}") + continue - # Determine output filename - outfile = args.destination / (data.name.replace('.', '_') + '.h5') - data.export_to_hdf5(outfile, 'w', libver=args.libver) + print(f"Converting {table.name} (ACE) to {data.name} (HDF5)") - # Register with library - library.register_file(outfile) + # Determine output filename + outfile = destination / (data.name.replace(".", "_") + ".h5") + data.export_to_hdf5(outfile, "w", libver=libver) - # Add nuclide to list - converted[name] = outfile - else: - # Read existing HDF5 file - data = cls.from_hdf5(converted[name]) + # Register with library + library.register_file(outfile) - # Add data for new temperature - try: - print('Converting {} (ACE) to {} (HDF5)' - .format(table.name, data.name)) - data.add_temperature_from_ace(table, args.metastable) - except Exception as e: - print('Failed to convert {}: {}'.format(table.name, e)) - continue + # Add nuclide to list + converted[name] = outfile + else: + # Read existing HDF5 file + data = cls.from_hdf5(converted[name]) - # Re-export - data.export_to_hdf5(converted[name], 'w', libver=args.libver) + # Add data for new temperature + try: + print(f"Converting {table.name} (ACE) to {data.name} (HDF5)") + data.add_temperature_from_ace(table, metastable) + except Exception as e: + print(f"Failed to convert {table.name}: {e}") + continue -# Write cross_sections.xml -library.export_to_xml(args.destination / 'cross_sections.xml') + # Re-export + data.export_to_hdf5(converted[name], "w", libver=libver) + + # Write cross_sections.xml + library.export_to_xml(destination / "cross_sections.xml") + + +if __name__ == "__main__": + + class CustomFormatter( + argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter + ): + pass + + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=CustomFormatter + ) + parser.add_argument("libraries", nargs="*", help="ACE libraries to convert to HDF5") + parser.add_argument( + "-d", + "--destination", + type=Path, + default=Path.cwd(), + help="Directory to create new library in", + ) + parser.add_argument( + "-m", + "--metastable", + choices=["mcnp", "nndc"], + default="nndc", + help="How to interpret ZAIDs for metastable nuclides", + ) + parser.add_argument("--xsdir", help="MCNP xsdir file that lists " "ACE libraries") + parser.add_argument( + "--xsdata", help="Serpent xsdata file that lists " "ACE libraries" + ) + parser.add_argument( + "--libver", + choices=["earliest", "latest"], + default="earliest", + help="Output HDF5 versioning. Use " + "'earliest' for backwards compatibility or 'latest' " + "for performance", + ) + args = parser.parse_args() + + ace_to_hdf5( + destination=args.destination, + xsdir=args.xsdir, + xsdata=args.xsdata, + libraries=args.libraries, + metastable=args.metastable, + libver=args.libver, + ) From cb3dfe62adbe646bb4fd4888ed436d9b063e6c07 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 24 Aug 2022 12:37:43 +0100 Subject: [PATCH 0878/2654] added main method to validate xml --- scripts/openmc-validate-xml | 163 ++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 80 deletions(-) diff --git a/scripts/openmc-validate-xml b/scripts/openmc-validate-xml index f36ba2b5d..e3aeb1039 100755 --- a/scripts/openmc-validate-xml +++ b/scripts/openmc-validate-xml @@ -4,96 +4,99 @@ import os import sys import glob import lxml.etree as etree -from subprocess import call from optparse import OptionParser -# Command line parsing -parser = OptionParser() -parser.add_option('-r', '--relaxng-path', dest='relaxng', - help="Path to RelaxNG files.") -parser.add_option('-i', '--input-path', dest='inputs', default=os.getcwd(), - help="Path to OpenMC input files." ) -(options, args) = parser.parse_args() +def validate_xml(inputs, relaxng): -# Colored output -if sys.stdout.isatty(): - OK = '\033[92m' - FAIL = '\033[91m' - NOT_FOUND = '\033[93m' - ENDC = '\033[0m' - BOLD = '\033[1m' -else: - OK = '' - FAIL = '' - ENDC = '' - BOLD = '' - NOT_FOUND = '' - -# Get absolute paths -if options.relaxng is not None: - relaxng_path = os.path.abspath(options.relaxng) -if options.inputs is not None: - inputs_path = os.path.abspath(options.inputs) - -# Search for relaxng path if not set -if options.relaxng is None: - xml_validate_path = os.path.abspath(os.path.dirname(sys.argv[0])) - if "bin" in xml_validate_path: - relaxng_path = os.path.join(xml_validate_path, "..", "share", "relaxng") - elif os.path.join("src", "utils") in xml_validate_path: - relaxng_path = os.path.join(xml_validate_path, "..", "relaxng") + # Colored output + if sys.stdout.isatty(): + OK = '\033[92m' + FAIL = '\033[91m' + NOT_FOUND = '\033[93m' + ENDC = '\033[0m' + BOLD = '\033[1m' else: - raise Exception("Set RelaxNG path with -r command line option.") -if not os.path.exists(relaxng_path): - raise Exception("RelaxNG path: {0} does not exist, set with -r " - "command line option.".format(relaxng_path)) + OK = '' + FAIL = '' + ENDC = '' + BOLD = '' + NOT_FOUND = '' -# Make sure there are .rng files in RelaxNG path -rng_files = glob.glob(os.path.join(relaxng_path, "*.rng")) -if len(rng_files) == 0: - raise Exception("No .rng files found in RelaxNG " - "path: {0}.".format(relaxng_path)) + # Get absolute paths + if relaxng is not None: + relaxng_path = os.path.abspath(relaxng) + if inputs is not None: + inputs_path = os.path.abspath(inputs) -# Get list of xml input files -xml_files = glob.glob(os.path.join(inputs_path, "*.xml")) -if len(xml_files) == 0: - raise Exception("No .xml files found at input path: {0}" - ".".format(inputs_path)) + # Search for relaxng path if not set + if relaxng is None: + xml_validate_path = os.path.abspath(os.path.dirname(sys.argv[0])) + if "bin" in xml_validate_path: + relaxng_path = os.path.join(xml_validate_path, "..", "share", "relaxng") + elif os.path.join("src", "utils") in xml_validate_path: + relaxng_path = os.path.join(xml_validate_path, "..", "relaxng") + else: + raise Exception("Set RelaxNG path with -r command line option.") + if not os.path.exists(relaxng_path): + raise Exception(f"RelaxNG path: {relaxng_path} does not exist, set " + "with -r command line option.") -# Begin loop around input files -for xml_file in xml_files: + # Make sure there are .rng files in RelaxNG path + rng_files = glob.glob(os.path.join(relaxng_path, "*.rng")) + if len(rng_files) == 0: + raise Exception(f"No .rng files found in RelaxNG path: {relaxng_path}.") - text = "Validating {0}".format(os.path.basename(xml_file)) - print(text + '.'*(30 - len(text)), end="") + # Get list of xml input files + xml_files = glob.glob(os.path.join(inputs_path, "*.xml")) + if len(xml_files) == 0: + raise Exception(f"No .xml files found at input path: {inputs_path}.") - # Validate the XML file - try: - xml_tree = etree.parse(xml_file) - except etree.XMLSyntaxError as e: - print(BOLD + FAIL + '[XML ERROR]' + ENDC) - print(" {0}".format(e)) - continue + # Begin loop around input files + for xml_file in xml_files: - # Get xml_filename prefix - xml_prefix = os.path.basename(xml_file) - xml_prefix = xml_prefix.split(".")[0] + text = f"Validating {os.path.basename(xml_file)}" + print(text + '.'*(30 - len(text)), end="") - # Search for rng file - rng_file = os.path.join(relaxng_path, xml_prefix + ".rng") - if rng_file in rng_files: - - # read in RelaxNG - relaxng_doc = etree.parse(rng_file) - relaxng = etree.RelaxNG(relaxng_doc) - - # validate xml file again RelaxNG + # Validate the XML file try: - relaxng.assertValid(xml_tree) - print(BOLD + OK + '[VALID]' + ENDC) - except (etree.DocumentInvalid, TypeError) as e: - print(BOLD + FAIL + '[NOT VALID]' + ENDC) - print(" {0}".format(e)) + xml_tree = etree.parse(xml_file) + except etree.XMLSyntaxError as e: + print(BOLD + FAIL + '[XML ERROR]' + ENDC) + print(f" {e}") + continue - # RNG file does not exist - else: - print(BOLD + NOT_FOUND + '[NO RELAXNG FOUND]' + ENDC) + # Get xml_filename prefix + xml_prefix = os.path.basename(xml_file) + xml_prefix = xml_prefix.split(".")[0] + + # Search for rng file + rng_file = os.path.join(relaxng_path, xml_prefix + ".rng") + if rng_file in rng_files: + + # read in RelaxNG + relaxng_doc = etree.parse(rng_file) + relaxng = etree.RelaxNG(relaxng_doc) + + # validate xml file again RelaxNG + try: + relaxng.assertValid(xml_tree) + print(BOLD + OK + '[VALID]' + ENDC) + except (etree.DocumentInvalid, TypeError) as e: + print(BOLD + FAIL + '[NOT VALID]' + ENDC) + print(f" {e}") + + # RNG file does not exist + else: + print(BOLD + NOT_FOUND + '[NO RELAXNG FOUND]' + ENDC) + + +if __name__ == "__main__": + # Command line parsing + parser = OptionParser() + parser.add_option('-r', '--relaxng-path', dest='relaxng', + help="Path to RelaxNG files.") + parser.add_option('-i', '--input-path', dest='inputs', default=os.getcwd(), + help="Path to OpenMC input files." ) + (options, args) = parser.parse_args() + + validate_xml(inputs=options.inputs, relaxng=options.relaxng) From 4169cabc5d1923f2d88cf7ad4edc193adf43761e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 24 Aug 2022 12:50:53 +0100 Subject: [PATCH 0879/2654] removed script that is now in data repo --- scripts/openmc-make-test-data | 164 ---------------------------------- 1 file changed, 164 deletions(-) delete mode 100755 scripts/openmc-make-test-data diff --git a/scripts/openmc-make-test-data b/scripts/openmc-make-test-data deleted file mode 100755 index 4d26db7fb..000000000 --- a/scripts/openmc-make-test-data +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python3 - -""" -Download ENDF/B-VII.1 ENDF and ACE files from NNDC and WMP files from GitHub and -generate a full HDF5 library with incident neutron, incident photon, thermal -scattering data, and windowed multipole data. This data is used for OpenMC's -regression test suite. -""" - -import glob -import os -from pathlib import Path -import tarfile -import tempfile -from urllib.parse import urljoin -import zipfile - -import openmc.data -from openmc._utils import download - -base_ace = 'https://www.nndc.bnl.gov/endf/b7.1/aceFiles/' -base_endf = 'https://www.nndc.bnl.gov/endf/b7.1/zips/' -base_wmp = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/' -files = [ - (base_ace, 'ENDF-B-VII.1-neutron-293.6K.tar.gz', '9729a17eb62b75f285d8a7628ace1449'), - (base_ace, 'ENDF-B-VII.1-tsl.tar.gz', 'e17d827c92940a30f22f096d910ea186'), - (base_endf, 'ENDF-B-VII.1-neutrons.zip', 'e5d7f441fc4c92893322c24d1725e29c'), - (base_endf, 'ENDF-B-VII.1-photoat.zip', '5192f94e61f0b385cf536f448ffab4a4'), - (base_endf, 'ENDF-B-VII.1-atomic_relax.zip', 'fddb6035e7f2b6931e51a58fc754bd10'), - (base_wmp, 'WMP_Library_v1.1.tar.gz', '8523895928dd6ba63fba803e3a45d4f3') -] - - -def fix_zaid(table, old, new): - filename = os.path.join('tsl', table) - with open(filename, 'r') as fh: - text = fh.read() - text = text.replace(old, new, 1) - with open(filename, 'w') as fh: - fh.write(text) - -pwd = Path.cwd() -output_dir = pwd / 'nndc_hdf5' -os.makedirs('nndc_hdf5/photon', exist_ok=True) - -with tempfile.TemporaryDirectory() as tmpdir: - # Temporarily change dir - os.chdir(tmpdir) - - # ========================================================================= - # Download files from NNDC server - for base, fname, checksum in files: - download(urljoin(base, fname), checksum) - - # ========================================================================= - # EXTRACT FILES FROM TGZ - - for _, f, _ in files: - print('Extracting {}...'.format(f)) - path = Path(f) - if path.suffix == '.gz': - with tarfile.open(f, 'r') as tgz: - if 'tsl' in f: - tgz.extractall(path='tsl') - else: - tgz.extractall() - elif path.suffix == '.zip': - zipfile.ZipFile(f).extractall() - - # ========================================================================= - # FIX ZAID ASSIGNMENTS FOR VARIOUS S(A,B) TABLES - - print('Fixing ZAIDs for S(a,b) tables') - fix_zaid('bebeo.acer', '8016', ' 0') - fix_zaid('obeo.acer', '4009', ' 0') - - library = openmc.data.DataLibrary() - - # ========================================================================= - # INCIDENT NEUTRON DATA - - neutron_files = sorted(glob.glob('ENDF-B-VII.1-neutron-293.6K/*.ace')) - for f in neutron_files: - print('Converting {}...'.format(os.path.basename(f))) - data = openmc.data.IncidentNeutron.from_ace(f) - - # Check for fission energy release data on MF=1, MT=458 - endf_filename = 'neutrons/n-{:03}_{}_{:03}{}.endf'.format( - data.atomic_number, - data.atomic_symbol, - data.mass_number, - 'm{}'.format(data.metastable) if data.metastable else '' - ) - ev = openmc.data.endf.Evaluation(endf_filename) - if (1, 458) in ev.section: - endf_data = openmc.data.IncidentNeutron.from_endf(ev) - data.fission_energy = endf_data.fission_energy - - # Add 0K elastic scattering data for select nuclides - if data.name in ('U235', 'U238', 'Pu239'): - data.add_elastic_0K_from_endf(endf_filename) - - # Determine filename - outfile = output_dir / (data.name + '.h5') - data.export_to_hdf5(outfile, 'w', 'earliest') - - # Register with library - library.register_file(outfile) - - # ========================================================================= - # THERMAL SCATTERING DATA - - thermal_files = sorted(glob.glob('tsl/*.acer')) - for f in thermal_files: - print('Converting {}...'.format(os.path.basename(f))) - data = openmc.data.ThermalScattering.from_ace(f) - - # Determine filename - outfile = output_dir / (data.name + '.h5') - data.export_to_hdf5(outfile, 'w', 'earliest') - - # Register with library - library.register_file(outfile) - - # ========================================================================= - # INCIDENT PHOTON DATA - - for z in range(1, 101): - element = openmc.data.ATOMIC_SYMBOL[z] - print('Generating HDF5 file for Z={} ({})...'.format(z, element)) - - # Generate instance of IncidentPhoton - photo_file = Path('photoat') / 'photoat-{:03}_{}_000.endf'.format(z, element) - atom_file = Path('atomic_relax') / 'atom-{:03}_{}_000.endf'.format(z, element) - data = openmc.data.IncidentPhoton.from_endf(photo_file, atom_file) - - # Write HDF5 file and register it - outfile = output_dir / 'photon' / (element + '.h5') - data.export_to_hdf5(outfile, 'w', 'earliest') - library.register_file(outfile) - - # ========================================================================= - # WINDOWED MULTIPOLE DATA - - # Move data into output directory - os.rename('WMP_Library', str(output_dir / 'wmp')) - - # Add multipole data to library - for f in sorted(glob.glob('{}/wmp/*.h5'.format(output_dir))): - print('Registering WMP file {}...'.format(f)) - library.register_file(f) - - library.export_to_xml(output_dir / 'cross_sections.xml') - - # ========================================================================= - # CREATE TARBALL AND MOVE BACK - - print('Creating compressed archive...') - test_tar = pwd / 'nndc_hdf5_test.tar.xz' - with tarfile.open(str(test_tar), 'w:xz') as txz: - txz.add(output_dir) - - # Change back to original directory - os.chdir(str(pwd)) From 00f05719069cfdfe4848487eb4583baca629d705 Mon Sep 17 00:00:00 2001 From: James Logan Date: Wed, 24 Aug 2022 09:43:13 -0400 Subject: [PATCH 0880/2654] add Axes as an argument to Universe.plot instead of popping it from kwargs --- openmc/universe.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index c95a80f06..768c2ba29 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -272,7 +272,7 @@ class Universe(UniverseBase): def plot(self, origin=(0., 0., 0.), width=(1., 1.), pixels=(200, 200), basis='xy', color_by='cell', colors=None, seed=None, - openmc_exec='openmc', **kwargs): + openmc_exec='openmc', axes=None, **kwargs): """Display a slice plot of the universe. Parameters @@ -302,6 +302,7 @@ class Universe(UniverseBase): Seed for the random number generator openmc_exec : str Path to OpenMC executable. + axes : matplotlib.Axes to draw to .. versionadded:: 0.13.1 **kwargs @@ -360,18 +361,18 @@ class Universe(UniverseBase): # Create a figure sized such that the size of the axes within # exactly matches the number of pixels specified - if kwargs.get("ax") is None: + if axes is None: px = 1/plt.rcParams['figure.dpi'] - fig, ax = plt.subplots() + fig, axes = plt.subplots() params = fig.subplotpars width = pixels[0]*px/(params.right - params.left) height = pixels[0]*px/(params.top - params.bottom) fig.set_size_inches(width, height) else: - ax = kwargs.pop("ax") + pass # Plot image and return the axes - return ax.imshow(img, extent=(x_min, x_max, y_min, y_max), **kwargs) + return axes.imshow(img, extent=(x_min, x_max, y_min, y_max), **kwargs) def add_cell(self, cell): """Add a cell to the universe. From 519bd75f3e8f6e126e6e130cf1c7de028846b696 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Wed, 24 Aug 2022 13:51:51 -0500 Subject: [PATCH 0881/2654] switched math.log10 to numpy.log10 so the assert passes --- tests/unit_tests/test_filters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index ec051d9fd..4e741e60f 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -252,6 +252,6 @@ def test_energy(): def test_lethargy_bin_width(): f = openmc.EnergyFilter.from_group_structure('VITAMIN-J-175') assert len(f.lethargy_bin_width) == 175 - energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] - assert f.lethargy_bin_width[0] == math.log10(energy_bins[1]/energy_bins[0]) - assert f.lethargy_bin_width[-1] == math.log10(energy_bins[-1]/energy_bins[-2]) + energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] + assert f.lethargy_bin_width[0] == np.log10(energy_bins[1]/energy_bins[0]) + assert f.lethargy_bin_width[-1] == np.log10(energy_bins[-1]/energy_bins[-2]) From fb6984e0a75a759badd50db0eb169f3de2970a8f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 25 Aug 2022 12:50:56 +0100 Subject: [PATCH 0882/2654] added numbers for size --- openmc/mesh.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index af830158c..54d7ba950 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -217,7 +217,7 @@ class StructuredMesh(MeshBase): Raises ------ RuntimeError - When the size of a dataset doesn't match the number of cells + When the size of a dataset doesn't match the number of mesh cells Returns ------- @@ -229,13 +229,14 @@ class StructuredMesh(MeshBase): from vtk.util import numpy_support as nps # check that the data sets are appropriately sized - errmsg = "The size of the dataset {} should be equal to the number of cells" + errmsg = "The size of the dataset {} ({}) should be equal to the number of mesh cells ({})" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): - if not dataset.size == self.dimension[0] * self.dimension[1]* self.dimension[2]: - raise RuntimeError(errmsg.format(label)) + num_cells = self.dimension[0] * self.dimension[1] * self.dimension[2] + if not dataset.size == num_cells: + raise RuntimeError(errmsg.format(label, dataset.size, num_cells)) else: - if len(dataset) == self.dimension[0] * self.dimension[1]* self.dimension[2]: + if len(dataset) == self.dimension[0] * self.dimension[1] * self.dimension[2]: raise RuntimeError(errmsg.format(label)) cv.check_type('label', label, str) From 19574d08ccd6b3fea9baba839248c604d8b7eb19 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 25 Aug 2022 14:25:48 +0100 Subject: [PATCH 0883/2654] [skip ci] review suggestion from @pshriwise Co-authored-by: Patrick Shriwise --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 54d7ba950..d58986285 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -229,7 +229,7 @@ class StructuredMesh(MeshBase): from vtk.util import numpy_support as nps # check that the data sets are appropriately sized - errmsg = "The size of the dataset {} ({}) should be equal to the number of mesh cells ({})" + errmsg = "The size of the dataset '{}' ({}) should be equal to the number of mesh cells ({})" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): num_cells = self.dimension[0] * self.dimension[1] * self.dimension[2] From 2a903f8eb559c2e8b982712ffa867d46cc792484 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 25 Aug 2022 14:27:45 +0100 Subject: [PATCH 0884/2654] moving errmsg var closer to usage line --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d58986285..0950d8dba 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -229,11 +229,11 @@ class StructuredMesh(MeshBase): from vtk.util import numpy_support as nps # check that the data sets are appropriately sized - errmsg = "The size of the dataset '{}' ({}) should be equal to the number of mesh cells ({})" for label, dataset in datasets.items(): if isinstance(dataset, np.ndarray): num_cells = self.dimension[0] * self.dimension[1] * self.dimension[2] if not dataset.size == num_cells: + errmsg = "The size of the dataset '{}' ({}) should be equal to the number of mesh cells ({})" raise RuntimeError(errmsg.format(label, dataset.size, num_cells)) else: if len(dataset) == self.dimension[0] * self.dimension[1] * self.dimension[2]: From 474f0742ba535f25266c0707542ecd75a8f0994d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 25 Aug 2022 15:10:45 +0100 Subject: [PATCH 0885/2654] [skip ci] suggestion from review by @Paulromano Co-authored-by: Paul Romano --- openmc/material.py | 10 +++++----- tests/unit_tests/test_material.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 957e0ba2d..f4c978798 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -833,7 +833,7 @@ class Material(IDManagerMixin): ---------- nuclides : str, optional Nuclide for which atom density is desired. If not specified, the - atom density for the all the material is given. + atom density for each nuclide in the material is given. .. versionchanged:: 0.13.1 The values in the dictionary were changed from a tuple containing @@ -868,10 +868,10 @@ class Material(IDManagerMixin): nuc_densities = [] nuc_density_types = [] - for loop_nuclide in self.nuclides: - nucs.append(loop_nuclide.name) - nuc_densities.append(loop_nuclide.percent) - nuc_density_types.append(loop_nuclide.percent_type) + for nuc in self.nuclides: + nucs.append(nuc.name) + nuc_densities.append(nuc.percent) + nuc_density_types.append(nuc.percent_type) nucs = np.array(nucs) nuc_densities = np.array(nuc_densities) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 9425da44f..8bb881795 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -339,7 +339,7 @@ def test_get_nuclide_atom_densities(uo2): assert density > 0 -def test_get_specific_nuclide_atom_densities(uo2): +def test_get_nuclide_atom_densities_specific(uo2): one_nuc = uo2.get_nuclide_atom_densities(nuclide='O16') assert list(one_nuc.keys()) == ['O16'] assert list(one_nuc.values())[0] > 0 From cacf279fc8aa667776b8a31f97bd2562d5267b29 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 25 Aug 2022 15:13:24 +0100 Subject: [PATCH 0886/2654] moved parameters below 0.13.1 directive --- openmc/material.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index f4c978798..d9d4f241d 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -829,16 +829,16 @@ class Material(IDManagerMixin): """Returns one or all nuclides in the material and their atomic densities in units of atom/b-cm + .. versionchanged:: 0.13.1 + The values in the dictionary were changed from a tuple containing + the nuclide name and the density to just the density. + Parameters ---------- nuclides : str, optional Nuclide for which atom density is desired. If not specified, the atom density for each nuclide in the material is given. - .. versionchanged:: 0.13.1 - The values in the dictionary were changed from a tuple containing - the nuclide name and the density to just the density. - Returns ------- nuclides : dict From 14e81ab94acb5acd37bc4ffb857875d832fe1153 Mon Sep 17 00:00:00 2001 From: lewisgross1296 Date: Thu, 25 Aug 2022 09:44:57 -0500 Subject: [PATCH 0887/2654] removed unused import --- tests/unit_tests/test_filters.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 4e741e60f..a20b129e9 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -1,4 +1,3 @@ -import math import numpy as np import openmc from pytest import fixture, approx From 80c86925372bed9a59192b4e66b35d6917996550 Mon Sep 17 00:00:00 2001 From: myerspat Date: Thu, 25 Aug 2022 11:47:14 -0400 Subject: [PATCH 0888/2654] Removed one of the region vectors and changed HDF5 output for geometry --- include/openmc/cell.h | 2 -- src/cell.cpp | 49 +++++++++++++++++++++++-------------------- src/geometry_aux.cpp | 2 +- src/universe.cpp | 4 ++-- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 23cd0130a..fd1883ce5 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -200,8 +200,6 @@ public: //! Definition of spatial region as Boolean expression of half-spaces vector region_; - //! Region in infix that may be modified depending on simplicity - vector region_infix_; bool simple_; //!< Does the region contain only intersections? //! \brief Neighboring cells in the same universe. diff --git a/src/cell.cpp b/src/cell.cpp index 6b4fcafda..4a61eb60e 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -205,7 +205,7 @@ void add_precedence(std::vector& infix) //! This function uses the shunting-yard algorithm. //============================================================================== -vector generate_rpn(int32_t cell_id, vector infix) +vector generate_postfix(int32_t cell_id, vector infix) { vector rpn; vector stack; @@ -619,15 +619,14 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } region_.shrink_to_fit(); - region_infix_ = region_; // If this cell is simple, remove all the superfluous operator tokens. if (simple_) { - for (auto it = region_infix_.begin(); it != region_infix_.end(); it++) { + for (auto it = region_.begin(); it != region_.end(); it++) { if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { - region_infix_.erase(it); + region_.erase(it); } } - region_infix_.shrink_to_fit(); + region_.shrink_to_fit(); } // Read the translation vector. @@ -672,7 +671,7 @@ std::pair CSGCell::distance( double min_dist {INFTY}; int32_t i_surf {std::numeric_limits::max()}; - for (int32_t token : region_infix_) { + for (int32_t token : region_) { // Ignore this token if it corresponds to an operator rather than a region. if (token >= OP_UNION) continue; @@ -705,19 +704,18 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const if (!region_.empty()) { std::stringstream region_spec {}; for (int32_t token : region_) { - if (token == OP_LEFT_PAREN) { - region_spec << " ("; - } else if (token == OP_RIGHT_PAREN) { - region_spec << " )"; - } else if (token == OP_COMPLEMENT) { - region_spec << " ~"; - } else if (token == OP_INTERSECTION) { - } else if (token == OP_UNION) { - region_spec << " |"; - } else { + if (token < OP_UNION) { // Note the off-by-one indexing auto surf_id = model::surfaces[abs(token) - 1]->id_; region_spec << " " << ((token > 0) ? surf_id : -surf_id); + } else if (token > OP_COMPLEMENT) { + if (token == OP_LEFT_PAREN) { + region_spec << " ("; + } else { + region_spec << " )"; + } + } else if (token == OP_UNION) { + region_spec << " |"; } } write_string(group_id, "region", region_spec.str(), false); @@ -727,7 +725,7 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const BoundingBox CSGCell::bounding_box_simple() const { BoundingBox bbox; - for (int32_t token : region_infix_) { + for (int32_t token : region_) { bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); } return bbox; @@ -813,12 +811,12 @@ void CSGCell::remove_complement_ops(vector& infix) } } -BoundingBox CSGCell::bounding_box_complex(vector rpn) +BoundingBox CSGCell::bounding_box_complex(vector postfix) { - vector stack(rpn.size()); + vector stack(postfix.size()); int i_stack = -1; - for (auto& token : rpn) { + for (auto& token : postfix) { if (token == OP_UNION) { stack[i_stack - 1] = stack[i_stack - 1] | stack[i_stack]; i_stack--; @@ -837,14 +835,19 @@ BoundingBox CSGCell::bounding_box_complex(vector rpn) BoundingBox CSGCell::bounding_box() const { - return simple_ ? bounding_box_simple() : bounding_box_complex(region_infix_); + if (simple_) { + return bounding_box_simple(); + } else { + auto postfix = generate_postfix(this->id_, this->region_); + return bounding_box_complex(postfix); + } } //============================================================================== bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const { - for (int32_t token : region_infix_) { + for (int32_t token : region_) { // Assume that no tokens are operators. Evaluate the sense of particle with // respect to the surface and see if the token matches the sense. If the // particle's surface attribute is set and matches the token, that @@ -872,7 +875,7 @@ bool CSGCell::contains_complex( int total_depth = 0; // For each token - for (auto it = region_infix_.begin(); it != region_infix_.end(); it++) { + for (auto it = region_.begin(); it != region_.end(); it++) { int32_t token = *it; // If the token is a surface evaluate the sense diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 7648d270a..c3458d469 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -154,7 +154,7 @@ void partition_universes() // Collect the set of surfaces in this universe. std::unordered_set surf_inds; for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->region_infix_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) surf_inds.insert(std::abs(token) - 1); } diff --git a/src/universe.cpp b/src/universe.cpp index 723400ec0..873d03bb7 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -98,7 +98,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find all of the z-planes in this universe. A set is used here for the // O(log(n)) insertions that will ensure entries are not repeated. for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->region_infix_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) { auto i_surf = std::abs(token) - 1; const auto* surf = model::surfaces[i_surf].get(); @@ -125,7 +125,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find the tokens for bounding z-planes. int32_t lower_token = 0, upper_token = 0; double min_z, max_z; - for (auto token : model::cells[i_cell]->region_infix_) { + for (auto token : model::cells[i_cell]->region_) { if (token < OP_UNION) { const auto* surf = model::surfaces[std::abs(token) - 1].get(); if (const auto* zplane = dynamic_cast(surf)) { From bd2bab3f568b7cb70e9556974218dd11d80e93d4 Mon Sep 17 00:00:00 2001 From: James Logan Date: Thu, 25 Aug 2022 11:57:36 -0400 Subject: [PATCH 0889/2654] remove explicit else-pass --- openmc/universe.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 768c2ba29..2994540ae 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -368,8 +368,6 @@ class Universe(UniverseBase): width = pixels[0]*px/(params.right - params.left) height = pixels[0]*px/(params.top - params.bottom) fig.set_size_inches(width, height) - else: - pass # Plot image and return the axes return axes.imshow(img, extent=(x_min, x_max, y_min, y_max), **kwargs) From cc667cc11a52157bc3228f1753d77111358e8bf6 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 25 Aug 2022 17:18:45 +0100 Subject: [PATCH 0890/2654] updated error message check --- openmc/mesh.py | 14 ++++++++------ tests/unit_tests/test_mesh_to_vtk.py | 7 +++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 0950d8dba..288d1527c 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -230,14 +230,16 @@ class StructuredMesh(MeshBase): # check that the data sets are appropriately sized for label, dataset in datasets.items(): + errmsg = ( + f"The size of the dataset '{label}' ({dataset.size}) " + f"should be equal to the number of mesh cells ({self.num_mesh_cells})" + ) if isinstance(dataset, np.ndarray): - num_cells = self.dimension[0] * self.dimension[1] * self.dimension[2] - if not dataset.size == num_cells: - errmsg = "The size of the dataset '{}' ({}) should be equal to the number of mesh cells ({})" - raise RuntimeError(errmsg.format(label, dataset.size, num_cells)) + if not dataset.size == self.num_mesh_cells: + raise RuntimeError(errmsg) else: - if len(dataset) == self.dimension[0] * self.dimension[1] * self.dimension[2]: - raise RuntimeError(errmsg.format(label)) + if len(dataset) == self.num_mesh_cells: + raise RuntimeError(errmsg) cv.check_type('label', label, str) vtk_grid = vtk.vtkStructuredGrid() diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 26a393b41..a6bed7035 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -71,6 +71,9 @@ def test_write_data_to_vtk_size_mismatch(mesh): right_size = mesh.num_mesh_cells data = np.random.random(right_size + 1) - expected_error_msg = "The size of the dataset label should be equal to the number of cells" + expected_error_msg = ( + f"The size of the dataset 'label' ({len(data)}) should be equal to " + f"the number of mesh cells ({mesh.num_mesh_cells})" + ) with pytest.raises(RuntimeError, match=expected_error_msg): - mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) \ No newline at end of file + mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) From 922a5fcf5a4d41b12b2b001cb1100225b8687d73 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 26 Aug 2022 10:19:39 +0100 Subject: [PATCH 0891/2654] used escape chars to match regex --- openmc/mesh.py | 4 ++-- tests/unit_tests/test_mesh_to_vtk.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 288d1527c..1b37a4272 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -231,8 +231,8 @@ class StructuredMesh(MeshBase): # check that the data sets are appropriately sized for label, dataset in datasets.items(): errmsg = ( - f"The size of the dataset '{label}' ({dataset.size}) " - f"should be equal to the number of mesh cells ({self.num_mesh_cells})" + f"The size of the dataset '{label}' ({dataset.size}) should be" + f" equal to the number of mesh cells ({self.num_mesh_cells})" ) if isinstance(dataset, np.ndarray): if not dataset.size == self.num_mesh_cells: diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index a6bed7035..2c23a5298 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -28,6 +28,7 @@ spherical_mesh.r_grid = np.linspace(1, 2, num=30) spherical_mesh.phi_grid = np.linspace(0, np.pi, num=50) spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, num=30) + @pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) def test_write_data_to_vtk(mesh, tmpdir): # BUILD @@ -43,7 +44,7 @@ def test_write_data_to_vtk(mesh, tmpdir): # read file reader = vtk.vtkStructuredGridReader() - reader.SetFileName(filename) + reader.SetFileName(str(filename)) reader.Update() # check name of datasets @@ -58,6 +59,7 @@ def test_write_data_to_vtk(mesh, tmpdir): assert nps.vtk_to_numpy(array1).size == data.size assert nps.vtk_to_numpy(array2).size == data.size + @pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) def test_write_data_to_vtk_size_mismatch(mesh): """Checks that an error is raised when the size of the dataset @@ -71,9 +73,12 @@ def test_write_data_to_vtk_size_mismatch(mesh): right_size = mesh.num_mesh_cells data = np.random.random(right_size + 1) + # Error message has \ in to escape characters that are otherwise recognized + # by regex. These are needed to make the test string match the error message + # string when using the match argument as that uses regular expression expected_error_msg = ( - f"The size of the dataset 'label' ({len(data)}) should be equal to " - f"the number of mesh cells ({mesh.num_mesh_cells})" + f"The size of the dataset 'label' \({len(data)}\) should be equal to " + f"the number of mesh cells \({mesh.num_mesh_cells}\)" ) with pytest.raises(RuntimeError, match=expected_error_msg): mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) From a3a28d094ac821fd5df9927b194087e9b223f061 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 26 Aug 2022 16:22:08 +0100 Subject: [PATCH 0892/2654] changing RunTimeError to ValueError --- openmc/mesh.py | 6 +++--- tests/unit_tests/test_mesh_to_vtk.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 1b37a4272..8ac4b1594 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -216,7 +216,7 @@ class StructuredMesh(MeshBase): Raises ------ - RuntimeError + ValueError When the size of a dataset doesn't match the number of mesh cells Returns @@ -236,10 +236,10 @@ class StructuredMesh(MeshBase): ) if isinstance(dataset, np.ndarray): if not dataset.size == self.num_mesh_cells: - raise RuntimeError(errmsg) + raise ValueError(errmsg) else: if len(dataset) == self.num_mesh_cells: - raise RuntimeError(errmsg) + raise ValueError(errmsg) cv.check_type('label', label, str) vtk_grid = vtk.vtkStructuredGrid() diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 2c23a5298..d7d5907a2 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -80,5 +80,5 @@ def test_write_data_to_vtk_size_mismatch(mesh): f"The size of the dataset 'label' \({len(data)}\) should be equal to " f"the number of mesh cells \({mesh.num_mesh_cells}\)" ) - with pytest.raises(RuntimeError, match=expected_error_msg): + with pytest.raises(ValueError, match=expected_error_msg): mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) From 5cdef2e964d6823faf7ebae0f977d86df4506998 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 26 Aug 2022 16:30:24 +0100 Subject: [PATCH 0893/2654] added Julian years to Integrator --- openmc/deplete/abc.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 3e2c37ece..45432218a 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -12,7 +12,6 @@ from numbers import Real, Integral from contextlib import contextmanager import os from pathlib import Path -import sys import time from warnings import warn @@ -36,6 +35,7 @@ __all__ = [ _SECONDS_PER_MINUTE = 60 _SECONDS_PER_HOUR = 60*60 _SECONDS_PER_DAY = 24*60*60 +_SECONDS_PER_JULIAN_YEAR = 365.25*24*60*60 OperatorResult = namedtuple('OperatorResult', ['k', 'rates']) OperatorResult.__doc__ = """\ @@ -531,11 +531,11 @@ class Integrator(ABC): each interval in :attr:`timesteps` .. versionadded:: 0.12.1 - timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} + timestep_units : {'s', 'min', 'h', 'd', 'a', 'MWd/kg'} Units for values specified in the `timesteps` argument. 's' means - seconds, 'min' means minutes, 'h' means hours, and 'MWd/kg' indicates - that the values are given in burnup (MW-d of energy deposited per - kilogram of initial heavy metal). + seconds, 'min' means minutes, 'h' means hours, 'a' means Julian years + and 'MWd/kg' indicates that the values are given in burnup (MW-d of + energy deposited per kilogram of initial heavy metal). solver : str or callable, optional If a string, must be the name of the solver responsible for solving the Bateman equations. Current options are: @@ -638,6 +638,8 @@ class Integrator(ABC): seconds.append(timestep*_SECONDS_PER_HOUR) elif unit in ('d', 'day'): seconds.append(timestep*_SECONDS_PER_DAY) + elif unit in ('a', 'year'): + seconds.append(timestep*_SECONDS_PER_JULIAN_YEAR) elif unit.lower() == 'mwd/kg': watt_days_per_kg = 1e6*timestep kilograms = 1e-3*operator.heavy_metal From 090363b6372b32983fa2d4b23c84c3e4d2c83723 Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 26 Aug 2022 12:47:08 -0400 Subject: [PATCH 0894/2654] Fixed error due to applying de morgans laws --- include/openmc/cell.h | 2 +- src/cell.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index fd1883ce5..817196727 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -244,7 +244,7 @@ protected: bool contains_simple(Position r, Direction u, int32_t on_surface) const; bool contains_complex(Position r, Direction u, int32_t on_surface) const; BoundingBox bounding_box_simple() const; - static BoundingBox bounding_box_complex(vector rpn); + static BoundingBox bounding_box_complex(vector postfix); //! Applies DeMorgan's laws to a section of the RPN //! \param start Starting point for token modification diff --git a/src/cell.cpp b/src/cell.cpp index 4a61eb60e..5c3e06eef 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -624,6 +624,7 @@ CSGCell::CSGCell(pugi::xml_node cell_node) for (auto it = region_.begin(); it != region_.end(); it++) { if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { region_.erase(it); + it--; } } region_.shrink_to_fit(); @@ -807,7 +808,7 @@ void CSGCell::remove_complement_ops(vector& infix) // positions in the RPN apply_demorgan(it, stop); // update iterator position - it = std::find(it, infix.end(), OP_COMPLEMENT); + it = std::find(infix.begin(), infix.end(), OP_COMPLEMENT); } } From c0982eb6224a536dde1da175d9b3395443731649 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 27 Aug 2022 00:12:25 +0100 Subject: [PATCH 0895/2654] format to f strings --- openmc/data/data.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 71b93293e..0c4495ede 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -228,7 +228,7 @@ def atomic_mass(isotope): with open(mass_file, 'r') as ame: # Read lines in file starting at line 40 for line in itertools.islice(ame, 39, None): - name = '{}{}'.format(line[20:22].strip(), int(line[16:19])) + name = f'{line[20:22].strip()}{int(line[16:19])}' mass = float(line[96:99]) + 1e-6*float( line[100:106] + '.' + line[107:112]) _ATOMIC_MASS[name.lower()] = mass @@ -273,8 +273,7 @@ def atomic_weight(element): if weight > 0.: return weight else: - raise ValueError("No naturally-occurring isotopes for element '{}'." - .format(element)) + raise ValueError(f"No naturally-occurring isotopes for element '{element}'.") def half_life(isotope): @@ -456,9 +455,8 @@ def gnd_name(Z, A, m=0): """ if m > 0: - return '{}{}_m{}'.format(ATOMIC_SYMBOL[Z], A, m) - else: - return '{}{}'.format(ATOMIC_SYMBOL[Z], A) + return f'{ATOMIC_SYMBOL[Z]}{A}_m{m}' + return f'{ATOMIC_SYMBOL[Z]}{A}' def isotopes(element): @@ -486,7 +484,7 @@ def isotopes(element): if len(element) > 2: symbol = ELEMENT_SYMBOL.get(element.lower()) if symbol is None: - raise ValueError('Element name "{}" not recognised'.format(element)) + raise ValueError(f'Element name "{element}" not recognised') element = symbol # Get the nuclides present in nature @@ -515,12 +513,11 @@ def zam(name): try: symbol, A, state = _GND_NAME_RE.match(name).groups() except AttributeError: - raise ValueError("'{}' does not appear to be a nuclide name in GND " - "format".format(name)) + raise ValueError(f"'{name}' does not appear to be a nuclide name in " + "GND format") if symbol not in ATOMIC_NUMBER: - raise ValueError("'{}' is not a recognized element symbol" - .format(symbol)) + raise ValueError(f"'{symbol}' is not a recognized element symbol") metastable = int(state[2:]) if state else 0 return (ATOMIC_NUMBER[symbol], int(A), metastable) From 985b2d26960f4a9765b189ba3832baf1f0f33b3b Mon Sep 17 00:00:00 2001 From: Miriam Kreher Date: Fri, 26 Aug 2022 21:07:15 -0400 Subject: [PATCH 0896/2654] Removed the option to condense transport cross sections instead of diffusion coefficients. --- openmc/mgxs/mgxs.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 6502a5ef2..8760dfc36 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -3154,6 +3154,8 @@ class DiffusionCoefficient(TransportXS): raise ValueError(msg) # Switch EnergyoutFilter to EnergyFilter + # If 'scatter-1' is not in tallies, it is because the transport correction has + # already occurred on this MGXS in another function or in a previous call to this function. if 'scatter-1' in self.tallies: p1_tally = self.tallies['scatter-1'] old_filt = p1_tally.filters[-2] @@ -3176,7 +3178,7 @@ class DiffusionCoefficient(TransportXS): return self._xs_tally - def get_condensed_xs(self, coarse_groups, condense_diff_coef=True): + def get_condensed_xs(self, coarse_groups): """Construct an energy-condensed version of this cross section. Parameters @@ -3202,7 +3204,9 @@ class DiffusionCoefficient(TransportXS): # Clone this MGXS to initialize the condensed version condensed_xs = copy.deepcopy(self) - if condense_diff_coef: + # If 'scatter-1' is not in tallies, it is because the transport correction has + # already occurred on this MGXS in another function or in a previous call to this function. + if 'scatter-1' in self.tallies: p1_tally = self.tallies['scatter-1'] old_filt = p1_tally.filters[-2] new_filt = openmc.EnergyFilter(old_filt.values) From 5f1b05f5faea4d00f0d5d359b2fc868a4f0a3c10 Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 29 Aug 2022 17:01:34 +0100 Subject: [PATCH 0897/2654] added element filter to get_nuclide --- openmc/material.py | 22 ++++++++++++++++++---- tests/unit_tests/test_material.py | 17 +++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index d9d4f241d..ac8e73afe 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -795,16 +795,30 @@ class Material(IDManagerMixin): return sorted({re.split(r'(\d+)', i)[0] for i in self.get_nuclides()}) - def get_nuclides(self): - """Returns all nuclides in the material + def get_nuclides(self, element: Optional[str] = None): + """Returns a list of all nuclides in the material, if the element + argument is specified then just nuclides of that element are returned. + + Parameters + ---------- + element : str + Specifies the element to match when searching through the nuclides Returns ------- nuclides : list of str List of nuclide names - """ - return [x.name for x in self._nuclides] + + if element: + matching_nuclides = [] + for nuclide in self._nuclides: + if re.split(r'(\d+)', nuclide.name)[0] == element: + matching_nuclides.append(nuclide.name) + return list(set(matching_nuclides)) + + else: + return list(set([x.name for x in self._nuclides])) def get_nuclide_densities(self): """Returns all nuclides in the material and their densities diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 8bb881795..8879119a1 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -299,6 +299,23 @@ def test_isotropic(): assert m2.isotropic == ['H1'] +def test_get_nuclides(): + mat = openmc.Material() + + mat.add_nuclide('Li6', 1.0) + assert mat.get_nuclides() == ['Li6'] + assert mat.get_nuclides(element='Li') == ['Li6'] + assert mat.get_nuclides(element='Be') == [] + + mat.add_element('Li', 1.0) + assert mat.get_nuclides() == ['Li7', 'Li6'] + assert mat.get_nuclides(element='Be') == [] + + mat.add_element('Be', 1.0) + assert mat.get_nuclides() == ['Li7', 'Li6', 'Be9'] + assert mat.get_nuclides(element='Be') == ['Be9'] + + def test_get_elements(): # test that zero elements exist on creation m = openmc.Material() From e42dfac373d3a8a548fa42619a8e10928a990c6f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 29 Aug 2022 11:22:00 -0500 Subject: [PATCH 0898/2654] Update libmesh version in Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d408b9de5..ae59ec089 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,7 +53,7 @@ ENV DAGMC_REPO='https://github.com/svalinn/DAGMC' ENV DAGMC_INSTALL_DIR=$HOME/DAGMC/ # LIBMESH variables -ENV LIBMESH_TAG='v1.6.0' +ENV LIBMESH_TAG='v1.7.1' ENV LIBMESH_REPO='https://github.com/libMesh/libmesh' ENV LIBMESH_INSTALL_DIR=$HOME/LIBMESH From 3b5910057da5370dfbf2e53fdc31a28eecb391f3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 29 Aug 2022 11:54:23 -0500 Subject: [PATCH 0899/2654] Update libmesh to 1.7.1 in gha-install-libmesh.sh for consistency --- tools/ci/gha-install-libmesh.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/gha-install-libmesh.sh b/tools/ci/gha-install-libmesh.sh index d592616ed..cb808ae5b 100755 --- a/tools/ci/gha-install-libmesh.sh +++ b/tools/ci/gha-install-libmesh.sh @@ -5,7 +5,7 @@ set -ex # libMESH install pushd $HOME mkdir LIBMESH && cd LIBMESH -git clone https://github.com/libmesh/libmesh -b v1.7.0 --recurse-submodules +git clone https://github.com/libmesh/libmesh -b v1.7.1 --recurse-submodules mkdir build && cd build export METHODS="opt" From b857fbd261f4f04136afee6d80b35d740cbe818c Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 29 Aug 2022 18:10:52 +0100 Subject: [PATCH 0900/2654] appending to list if not in list --- openmc/material.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index ac8e73afe..f137ec0cd 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -810,15 +810,18 @@ class Material(IDManagerMixin): List of nuclide names """ + matching_nuclides = [] if element: - matching_nuclides = [] for nuclide in self._nuclides: if re.split(r'(\d+)', nuclide.name)[0] == element: - matching_nuclides.append(nuclide.name) - return list(set(matching_nuclides)) - + if nuclide.name not in matching_nuclides: + matching_nuclides.append(nuclide.name) else: - return list(set([x.name for x in self._nuclides])) + for nuclide in self._nuclides: + if nuclide.name not in matching_nuclides: + matching_nuclides.append(nuclide.name) + + return matching_nuclides def get_nuclide_densities(self): """Returns all nuclides in the material and their densities From 5a0884e9de34cfcaf5cd16dccfb3f28303d962d5 Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 29 Aug 2022 22:41:07 +0100 Subject: [PATCH 0901/2654] corrected get nuclide tests --- tests/unit_tests/test_material.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 8879119a1..26ccbc9fe 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -308,11 +308,11 @@ def test_get_nuclides(): assert mat.get_nuclides(element='Be') == [] mat.add_element('Li', 1.0) - assert mat.get_nuclides() == ['Li7', 'Li6'] + assert mat.get_nuclides() == ['Li6', 'Li7'] assert mat.get_nuclides(element='Be') == [] mat.add_element('Be', 1.0) - assert mat.get_nuclides() == ['Li7', 'Li6', 'Be9'] + assert mat.get_nuclides() == ['Li6', 'Li7', 'Be9'] assert mat.get_nuclides(element='Be') == ['Be9'] From 9e80a73369b31c32c8a81791b2853ca2476ba883 Mon Sep 17 00:00:00 2001 From: James Logan Date: Tue, 30 Aug 2022 10:20:35 -0400 Subject: [PATCH 0902/2654] Update openmc/universe.py Co-authored-by: Paul Romano --- openmc/universe.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 2994540ae..cdb72bf6e 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -302,7 +302,8 @@ class Universe(UniverseBase): Seed for the random number generator openmc_exec : str Path to OpenMC executable. - axes : matplotlib.Axes to draw to + axes : matplotlib.Axes + Axes to draw to .. versionadded:: 0.13.1 **kwargs From bff8700c8b52dfbcf94f0aa65dc12cb53e56808d Mon Sep 17 00:00:00 2001 From: Patrick Myers <90068356+myerspat@users.noreply.github.com> Date: Tue, 30 Aug 2022 15:45:31 -0500 Subject: [PATCH 0903/2654] Simple wording and comment changes Co-authored-by: Paul Romano --- src/cell.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index 5c3e06eef..9076b1136 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -109,10 +109,10 @@ vector tokenize(const std::string region_spec) //============================================================================== //! Add precedence for infix regions so intersections have higher -//! precedence than unions using parenthesis. +//! precedence than unions using parentheses. //============================================================================== -std::vector::iterator add_parenthesis( +std::vector::iterator add_parentheses( std::vector::iterator start, std::vector& infix) { int32_t start_token = *start; @@ -125,7 +125,7 @@ std::vector::iterator add_parenthesis( start++; // Initialize return iterator - std::vector::iterator return_iterator = infix.begin(); + auto return_iterator = infix.begin(); // Add right parenthesis // While the start iterator is within the bounds of infix @@ -134,7 +134,7 @@ std::vector::iterator add_parenthesis( // If the current token is an operator and is different than the start token if (*start >= OP_UNION && *start != start_token) { - // Skip wraped regions but save iterator position to check precedence and + // Skip wrapped regions but save iterator position to check precedence and // add right parenthesis depending on the precedence of the original token // when a right parenthesis is encountered of the opposite token if (*start == OP_LEFT_PAREN) { @@ -190,7 +190,7 @@ void add_precedence(std::vector& infix) if (current_op == 0) { current_op = token; } else if (token != current_op) { - it = add_parenthesis(it, infix); + it = add_parentheses(it, infix); current_op = 0; } } else if (token > OP_COMPLEMENT) { From 02254cc78787c3e21e3498c937a8fbdb2e7bc045 Mon Sep 17 00:00:00 2001 From: myerspat Date: Tue, 30 Aug 2022 17:00:59 -0400 Subject: [PATCH 0904/2654] Changed wording and rearranging --- src/cell.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index 9076b1136..bb524f0b3 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -135,8 +135,10 @@ std::vector::iterator add_parentheses( // If the current token is an operator and is different than the start token if (*start >= OP_UNION && *start != start_token) { // Skip wrapped regions but save iterator position to check precedence and - // add right parenthesis depending on the precedence of the original token - // when a right parenthesis is encountered of the opposite token + // add right parenthesis, right parenthesis position depends on the + // operator, when the operator is a union then do not include the operator + // in the region, when the operator is an intersection then include the + // operato and next surface if (*start == OP_LEFT_PAREN) { return_iterator = start; int depth = 1; @@ -150,14 +152,9 @@ std::vector::iterator add_parentheses( } } } while (depth > 0); - } else if (start_token == OP_UNION) { - start = infix.insert(start - 1, OP_RIGHT_PAREN); - if (return_iterator == infix.begin()) { - return_iterator = start - 1; - } - return return_iterator; } else { - start = infix.insert(start, OP_RIGHT_PAREN); + start = infix.insert( + start_token == OP_UNION ? start - 1 : start, OP_RIGHT_PAREN); if (return_iterator == infix.begin()) { return_iterator = start - 1; } @@ -181,19 +178,17 @@ void add_precedence(std::vector& infix) for (auto it = infix.begin(); it != infix.end(); it++) { int32_t token = *it; - // If the token is a union another operator has not been found set the - // current operator to union - // If the current operator is a union and the token is an intersection - // assert precedence - // If the token is a parenthesis reset the current operator if (token == OP_UNION || token == OP_INTERSECTION) { if (current_op == 0) { + // Set the current operator if is hasn't been set current_op = token; } else if (token != current_op) { + // If the current operator doesn't match the token, add parenthesis to assert precedence it = add_parentheses(it, infix); current_op = 0; } } else if (token > OP_COMPLEMENT) { + // If the token is a parenthesis reset the current operator current_op = 0; } } @@ -898,7 +893,7 @@ bool CSGCell::contains_complex( if (total_depth == 0) { return in_cell; } - + total_depth--; // While the iterator is within the bounds of the vector From 588e7bbab0d1f5fcb07aa6aea63e75ebd671f209 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 12:37:06 -0500 Subject: [PATCH 0905/2654] Add XML roundtrip test for openmc.Source --- tests/unit_tests/test_source.py | 43 ++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_source.py b/tests/unit_tests/test_source.py index dbcf49efc..76dcbcdc8 100644 --- a/tests/unit_tests/test_source.py +++ b/tests/unit_tests/test_source.py @@ -1,6 +1,10 @@ +from math import pi + import openmc import openmc.stats -from math import pi +import numpy as np +from pytest import approx + def test_source(): space = openmc.stats.Point() @@ -39,8 +43,8 @@ def test_spherical_uniform(): phis, origin) - assert isinstance(sph_indep_function, openmc.stats.SphericalIndependent) - + assert isinstance(sph_indep_function, openmc.stats.SphericalIndependent) + def test_source_file(): filename = 'source.h5' @@ -59,3 +63,36 @@ def test_source_dlopen(): elem = src.to_xml_element() assert 'library' in elem.attrib + + +def test_source_xml_roundtrip(): + # Create a source and write to an XML element + space = openmc.stats.Box([-5., -5., -5.], [5., 5., 5.]) + energy = openmc.stats.Discrete([1.0e6, 2.0e6, 5.0e6], [0.3, 0.5, 0.2]) + angle = openmc.stats.PolarAzimuthal( + mu=openmc.stats.Uniform(0., 1.), + phi=openmc.stats.Uniform(0., 2*pi), + reference_uvw=(0., 1., 0.) + ) + src = openmc.Source( + space=space, angle=angle, energy=energy, + particle='photon', strength=100.0 + ) + elem = src.to_xml_element() + + # Read from XML element and make sure data is preserved + new_src = openmc.Source.from_xml_element(elem) + assert isinstance(new_src.space, openmc.stats.Box) + np.testing.assert_allclose(new_src.space.lower_left, src.space.lower_left) + np.testing.assert_allclose(new_src.space.upper_right, src.space.upper_right) + assert isinstance(new_src.energy, openmc.stats.Discrete) + np.testing.assert_allclose(new_src.energy.x, src.energy.x) + np.testing.assert_allclose(new_src.energy.p, src.energy.p) + assert isinstance(new_src.angle, openmc.stats.PolarAzimuthal) + assert new_src.angle.mu.a == src.angle.mu.a + assert new_src.angle.mu.b == src.angle.mu.b + assert new_src.angle.phi.a == src.angle.phi.a + assert new_src.angle.phi.b == src.angle.phi.b + np.testing.assert_allclose(new_src.angle.reference_uvw, src.angle.reference_uvw) + assert new_src.particle == src.particle + assert new_src.strength == approx(src.strength) From eb1dc015e5026f3083e7e0ad1e313a26cccd1a19 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 30 Aug 2022 21:15:58 -0500 Subject: [PATCH 0906/2654] Fix reading of reference_uvw during from_xml --- openmc/stats/multivariate.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index f34bf0d1f..8bb319aa4 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -148,9 +148,9 @@ class PolarAzimuthal(UnitSphere): """ mu_phi = cls() - params = get_text(elem, 'parameters') - if params is not None: - mu_phi.reference_uvw = [float(x) for x in params.split()] + uvw = get_text(elem, 'reference_uvw') + if uvw is not None: + mu_phi.reference_uvw = [float(x) for x in uvw.split()] mu_phi.mu = Univariate.from_xml_element(elem.find('mu')) mu_phi.phi = Univariate.from_xml_element(elem.find('phi')) return mu_phi @@ -242,9 +242,9 @@ class Monodirectional(UnitSphere): """ monodirectional = cls() - params = get_text(elem, 'parameters') - if params is not None: - monodirectional.reference_uvw = [float(x) for x in params.split()] + uvw = get_text(elem, 'reference_uvw') + if uvw is not None: + monodirectional.reference_uvw = [float(x) for x in uvw.split()] return monodirectional From 0214b220367a6c58fc950ec2d241e40797b27f8a Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 1 Sep 2022 11:52:21 -0500 Subject: [PATCH 0907/2654] fix errorneous behavior when adding metastable nuclides via add_components --- openmc/material.py | 3 ++- tests/unit_tests/test_material.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index d9d4f241d..4a988c597 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -438,7 +438,8 @@ class Material(IDManagerMixin): params['percent_type'] = percent_type ## check if nuclide - if str.isdigit(component[-1]): + if str.isdigit(component[-1]) or (component[-1] == 'm' + and str.isdigit(component[-2])): self.add_nuclide(component, **params) else: # is element kwargs = params diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 8bb881795..dde755231 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -32,6 +32,7 @@ def test_add_components(): 'O16': 1.0, 'Zr': 1.0, 'O': 1.0, + 'Ag110m': 1.0, 'U': {'percent': 1.0, 'enrichment': 4.5}, 'Li': {'percent': 1.0, From 85c5c791d6db687bd0deb9813a15d98808b931bd Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Thu, 1 Sep 2022 14:33:24 -0500 Subject: [PATCH 0908/2654] Cleanup flow control for detecting nuclides Co-authored-by: Paul Romano --- tests/unit_tests/test_material.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index dde755231..8e04ca192 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -32,7 +32,7 @@ def test_add_components(): 'O16': 1.0, 'Zr': 1.0, 'O': 1.0, - 'Ag110m': 1.0, + 'Ag110_m1': 1.0, 'U': {'percent': 1.0, 'enrichment': 4.5}, 'Li': {'percent': 1.0, From 2d01241b533b961ac2c9c4951855b6c2dbeed26a Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Thu, 1 Sep 2022 14:33:44 -0500 Subject: [PATCH 0909/2654] Cleanup flow control for detecting nuclides Co-authored-by: Paul Romano --- openmc/material.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 4a988c597..de4940a47 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -438,8 +438,7 @@ class Material(IDManagerMixin): params['percent_type'] = percent_type ## check if nuclide - if str.isdigit(component[-1]) or (component[-1] == 'm' - and str.isdigit(component[-2])): + if not str.isalpha(): self.add_nuclide(component, **params) else: # is element kwargs = params From 8650621f797f42d5482a4de4694273f907f344cf Mon Sep 17 00:00:00 2001 From: myerspat Date: Thu, 1 Sep 2022 17:01:01 -0400 Subject: [PATCH 0910/2654] Revereted hdf5 function back to original --- src/cell.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index bb524f0b3..4ff35498c 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -700,18 +700,19 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const if (!region_.empty()) { std::stringstream region_spec {}; for (int32_t token : region_) { - if (token < OP_UNION) { + if (token == OP_LEFT_PAREN) { + region_spec << " ("; + } else if (token == OP_RIGHT_PAREN) { + region_spec << " )"; + } else if (token == OP_COMPLEMENT) { + region_spec << " ~"; + } else if (token == OP_INTERSECTION) { + } else if (token == OP_UNION) { + region_spec << " |"; + } else { // Note the off-by-one indexing auto surf_id = model::surfaces[abs(token) - 1]->id_; region_spec << " " << ((token > 0) ? surf_id : -surf_id); - } else if (token > OP_COMPLEMENT) { - if (token == OP_LEFT_PAREN) { - region_spec << " ("; - } else { - region_spec << " )"; - } - } else if (token == OP_UNION) { - region_spec << " |"; } } write_string(group_id, "region", region_spec.str(), false); From 026d172255e64e45fc7e6ca37d23557ac455f469 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 10:04:23 -0500 Subject: [PATCH 0911/2654] Adding interpolation property to EnergyFunctionFilter. --- openmc/filter.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 7874a775b..0d8458be5 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1884,6 +1884,9 @@ class EnergyFunctionFilter(Filter): A grid of energy values in [eV] y : iterable of Real A grid of interpolant values in [eV] + interpolation : str + Used to indicate the type of interpolation used. + One of ('linear-linear', 'log-log') id : int Unique identifier for the filter num_bins : Integral @@ -1895,6 +1898,7 @@ class EnergyFunctionFilter(Filter): self.energy = energy self.y = y self.id = filter_id + self.interpolation = 'linear-linear' def __eq__(self, other): if type(self) is not type(other): @@ -1949,10 +1953,14 @@ class EnergyFunctionFilter(Filter): + group['type'][()].decode() + " instead") energy = group['energy'][()] - y = group['y'][()] + y = group['y'][()] filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - return cls(energy, y, filter_id=filter_id) + out = cls(energy, y, filter_id=filter_id) + if 'interpolation' in group: + out.interpolation = group['interpolation'][()] + + return out @classmethod def from_tabulated1d(cls, tab1d): @@ -1974,10 +1982,13 @@ class EnergyFunctionFilter(Filter): if tab1d.n_regions > 1: raise ValueError('Only Tabulated1Ds with a single interpolation ' 'region are supported') - if tab1d.interpolation[0] != 2: - raise ValueError('Only linear-linear Tabulated1Ds are supported') + if tab1d.interpolation[0] not in (2, 5): + raise ValueError('Only linear-linear or log-log Tabulated1Ds are supported') + out = cls(tab1d.x, tab1d.y) + if tab1d.interpolation[0] == 5: + out.interpolation = 'log-log' - return cls(tab1d.x, tab1d.y) + return out @property def energy(self): @@ -1987,6 +1998,10 @@ class EnergyFunctionFilter(Filter): def y(self): return self._y + @property + def interpolation(self): + return self._interpolation + @property def bins(self): raise AttributeError('EnergyFunctionFilters have no bins.') @@ -2021,6 +2036,12 @@ class EnergyFunctionFilter(Filter): def bins(self, bins): raise RuntimeError('EnergyFunctionFilters have no bins.') + @interpolation.setter + def interpolation(self, val): + cv.check_type('interpolation', val, str) + cv.check_value('interpolation', val, ('linear-linear', 'log-log')) + self._interpolation = val + def to_xml_element(self): """Return XML Element representing the Filter. @@ -2040,14 +2061,20 @@ class EnergyFunctionFilter(Filter): subelement = ET.SubElement(element, 'y') subelement.text = ' '.join(str(y) for y in self.y) + subelement = ET.SubElement(element, 'interpolation') + subelement.text = self.interpolation + return element @classmethod def from_xml_element(cls, elem, **kwargs): filter_id = int(elem.get('id')) energy = [float(x) for x in get_text(elem, 'energy').split()] - y = [float(x) for x in get_text(elem, 'y').split()] - return cls(energy, y, filter_id=filter_id) + y = [float(x) for x in get_text(elem, 'y').split()] + out = cls(energy, y, filter_id=filter_id) + if elem.find('interpolation') is not None: + out.interpolation = elem.find('interpolation') + return out def can_merge(self, other): return False From 8f26df7f5a91545903331916981c9d51a45880e4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 10:04:57 -0500 Subject: [PATCH 0912/2654] Adding interpolation value check and updating test inputs --- tests/regression_tests/filter_energyfun/inputs_true.dat | 1 + tests/regression_tests/filter_energyfun/test.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat index 0f506f3f5..15de0f027 100644 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ b/tests/regression_tests/filter_energyfun/inputs_true.dat @@ -22,6 +22,7 @@ 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + linear-linear Am241 diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index f61f05d78..c76b525d7 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -28,6 +28,8 @@ def model(): # Make an EnergyFunctionFilter directly from the x and y lists. filt1 = openmc.EnergyFunctionFilter(x, y) + assert filt1.interpolation == 'linear-linear' + # Also make a filter with the .from_tabulated1d constructor. Make sure # the filters are identical. tab1d = openmc.data.Tabulated1D(x, y) From 0d551cbb21f76894ea70f9e712f81d09f4b3c7f2 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 11:14:30 -0500 Subject: [PATCH 0913/2654] Adding support for log-log interpolation on the C++ side --- include/openmc/tallies/filter_energyfunc.h | 2 ++ openmc/filter.py | 5 +++-- src/tallies/filter_energyfunc.cpp | 26 ++++++++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/openmc/tallies/filter_energyfunc.h b/include/openmc/tallies/filter_energyfunc.h index c066dfa17..f650976ef 100644 --- a/include/openmc/tallies/filter_energyfunc.h +++ b/include/openmc/tallies/filter_energyfunc.h @@ -1,6 +1,7 @@ #ifndef OPENMC_TALLIES_FILTER_ENERGYFUNC_H #define OPENMC_TALLIES_FILTER_ENERGYFUNC_H +#include "openmc/constants.h" #include "openmc/tallies/filter.h" #include "openmc/vector.h" @@ -39,6 +40,7 @@ public: const vector& energy() const { return energy_; } const vector& y() const { return y_; } + Interpolation interpolation_; void set_data(gsl::span energy, gsl::span y); private: diff --git a/openmc/filter.py b/openmc/filter.py index 0d8458be5..f44ac99f8 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1957,8 +1957,9 @@ class EnergyFunctionFilter(Filter): filter_id = int(group.name.split('/')[-1].lstrip('filter ')) out = cls(energy, y, filter_id=filter_id) - if 'interpolation' in group: - out.interpolation = group['interpolation'][()] + if 'interpolation' in group.attrs: + out.interpolation = \ + openmc.data.INTERPOLATION_SCHEME[group.attrs['interpolation']] return out diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index fd595e332..2fcca7110 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -22,9 +22,15 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) if (!check_for_node(node, "y")) fatal_error("y values not specified for EnergyFunction filter."); - + auto y = get_node_array(node, "y"); + // use linear-linear interpolation by default + interpolation_ = Interpolation::lin_lin; + if (check_for_node(node, "interpolation")) { + std::string interpolation = get_node_value(node, "interpolation"); + } + this->set_data(energy, y); } @@ -58,12 +64,23 @@ void EnergyFunctionFilter::get_all_bins( // Search for the incoming energy bin. auto i = lower_bound_index(energy_.begin(), energy_.end(), p.E_last()); - // Compute the interpolation factor between the nearest bins. - double f = (p.E_last() - energy_[i]) / (energy_[i + 1] - energy_[i]); + double f, w; + switch (interpolation_) { + case Interpolation::lin_lin: + f = (p.E_last() - energy_[i]) / (energy_[i + 1] - energy_[i]); + w = (1 - f) * y_[i] + f * y_[i + 1]; + break; + case Interpolation::log_log: + f = log(p.E_last() / energy_[i]) / log(energy_[i + 1] / energy_[i]); + w = y_[i] * exp(f * log(y_[i + 1] / y_[i])); + break; + default: + fatal_error(fmt::format("Invalid interpolation scheme found on EnergyFunctionFilter {}", id())); + } // Interpolate on the lin-lin grid. match.bins_.push_back(0); - match.weights_.push_back((1 - f) * y_[i] + f * y_[i + 1]); + match.weights_.push_back(w); } } @@ -72,6 +89,7 @@ void EnergyFunctionFilter::to_statepoint(hid_t filter_group) const Filter::to_statepoint(filter_group); write_dataset(filter_group, "energy", energy_); write_dataset(filter_group, "y", y_); + write_attr_int(filter_group, "interpolation", interpolation_); } std::string EnergyFunctionFilter::text_label(int bin) const From 0c1b1875b7df89f4bb9ae8eee53d116b11816d3b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 11:31:12 -0500 Subject: [PATCH 0914/2654] Adding a quick test for the interpolation value checking --- src/tallies/filter_energyfunc.cpp | 23 ++++++++++--------- .../regression_tests/filter_energyfun/test.py | 3 +++ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index 2fcca7110..d783366bc 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -22,7 +22,7 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) if (!check_for_node(node, "y")) fatal_error("y values not specified for EnergyFunction filter."); - + auto y = get_node_array(node, "y"); // use linear-linear interpolation by default @@ -66,16 +66,17 @@ void EnergyFunctionFilter::get_all_bins( double f, w; switch (interpolation_) { - case Interpolation::lin_lin: - f = (p.E_last() - energy_[i]) / (energy_[i + 1] - energy_[i]); - w = (1 - f) * y_[i] + f * y_[i + 1]; - break; - case Interpolation::log_log: - f = log(p.E_last() / energy_[i]) / log(energy_[i + 1] / energy_[i]); - w = y_[i] * exp(f * log(y_[i + 1] / y_[i])); - break; - default: - fatal_error(fmt::format("Invalid interpolation scheme found on EnergyFunctionFilter {}", id())); + case Interpolation::lin_lin: + f = (p.E_last() - energy_[i]) / (energy_[i + 1] - energy_[i]); + w = (1 - f) * y_[i] + f * y_[i + 1]; + break; + case Interpolation::log_log: + f = log(p.E_last() / energy_[i]) / log(energy_[i + 1] / energy_[i]); + w = y_[i] * exp(f * log(y_[i + 1] / y_[i])); + break; + default: + fatal_error(fmt::format( + "Invalid interpolation scheme found on EnergyFunctionFilter {}", id())); } // Interpolate on the lin-lin grid. diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index c76b525d7..ba5a9b16f 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -30,6 +30,9 @@ def model(): assert filt1.interpolation == 'linear-linear' + with pytest.raises(ValueError): + filt1.interpolation = '5th order polynomial' + # Also make a filter with the .from_tabulated1d constructor. Make sure # the filters are identical. tab1d = openmc.data.Tabulated1D(x, y) From a0de07bf707957f615cd163ce1ea96de433e052b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 28 Jul 2022 18:23:51 -0500 Subject: [PATCH 0915/2654] Correcting hdf5 function signature --- src/tallies/filter_energyfunc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index d783366bc..37c1c3178 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -90,7 +90,7 @@ void EnergyFunctionFilter::to_statepoint(hid_t filter_group) const Filter::to_statepoint(filter_group); write_dataset(filter_group, "energy", energy_); write_dataset(filter_group, "y", y_); - write_attr_int(filter_group, "interpolation", interpolation_); + write_attribute(filter_group, "interpolation", static_cast(interpolation_)); } std::string EnergyFunctionFilter::text_label(int bin) const From b4cf42b092eb456a7ad7b6480939a4c0bcb21b94 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 23:37:34 -0500 Subject: [PATCH 0916/2654] Adding entry to statepoint documentation. --- docs/source/io_formats/statepoint.rst | 3 +++ src/tallies/filter_energyfunc.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index c1598f2c3..2332ebf21 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -108,6 +108,9 @@ The current version of the statepoint file format is 17.0. interpolation. Only used for 'energyfunction' filters. - **y** (*double[]*) -- Interpolant values for energyfunction interpolation. Only used for 'energyfunction' filters. + - **interpolation** (*int*) -- Interpolation type. One of + (1 - linear-linear or 2 - log-log). Only used for 'energyfunction' + filters. **/tallies/derivatives/derivative /** diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index 37c1c3178..819b5d13e 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -90,7 +90,8 @@ void EnergyFunctionFilter::to_statepoint(hid_t filter_group) const Filter::to_statepoint(filter_group); write_dataset(filter_group, "energy", energy_); write_dataset(filter_group, "y", y_); - write_attribute(filter_group, "interpolation", static_cast(interpolation_)); + write_attribute( + filter_group, "interpolation", static_cast(interpolation_)); } std::string EnergyFunctionFilter::text_label(int bin) const From d88648634e0d9f84ab2642fc77ee20053ef33f65 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 29 Jul 2022 23:49:58 -0500 Subject: [PATCH 0917/2654] Adding check for round-trip of spec for eff --- .../regression_tests/filter_energyfun/test.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index ba5a9b16f..b5ab1387c 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -61,6 +61,24 @@ class FilterEnergyFunHarness(PyAPITestHarness): # Output the tally in a Pandas DataFrame. return br_tally.get_pandas_dataframe().to_string() + '\n' + def _compare_results(self): + super()._compare_results() + + # Read the statepoint file. + sp = openmc.StatePoint(self._sp_name) + + # check that values are round-tripped correctly from + # the statepoint file + sp_tally = sp.get_tally(id=2) + sp_filt = sp_tally.find_filter(openmc.EnergyFunctionFilter) + + model_tally = self._model.tallies[1] + model_filt = model_tally.find_filter(openmc.EnergyFunctionFilter) + + assert sp_filt.interpolation == model_filt.interpolation + assert all(sp_filt.energy == model_filt.energy) + assert all(sp_filt.y == model_filt.y) + def test_filter_energyfun(model): harness = FilterEnergyFunHarness('statepoint.5.h5', model) From 2ef49a9c9b66736cc69eb4a7a7ff31d7cd9b4407 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 30 Jul 2022 00:18:10 -0500 Subject: [PATCH 0918/2654] Updating tests for eff --- openmc/filter.py | 6 ++++-- .../regression_tests/filter_energyfun/inputs_true.dat | 10 ++++++++++ .../filter_energyfun/results_true.dat | 2 +- tests/regression_tests/filter_energyfun/test.py | 11 +++++++++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index f44ac99f8..f5268ad81 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1894,11 +1894,11 @@ class EnergyFunctionFilter(Filter): """ - def __init__(self, energy, y, filter_id=None): + def __init__(self, energy, y, interpolation='linear-linear', filter_id=None): self.energy = energy self.y = y self.id = filter_id - self.interpolation = 'linear-linear' + self.interpolation = interpolation def __eq__(self, other): if type(self) is not type(other): @@ -1936,12 +1936,14 @@ class EnergyFunctionFilter(Filter): string = type(self).__name__ + '\n' string += '{: <16}=\t{}\n'.format('\tEnergy', self.energy) string += '{: <16}=\t{}\n'.format('\tInterpolant', self.y) + string += '{: <16}=\t{}\n'.format('\tInterpolation', self.interpolation) return hash(string) def __repr__(self): string = type(self).__name__ + '\n' string += '{: <16}=\t{}\n'.format('\tEnergy', self.energy) string += '{: <16}=\t{}\n'.format('\tInterpolant', self.y) + string += '{: <16}=\t{}\n'.format('\tInterpolation', self.interpolation) string += '{: <16}=\t{}\n'.format('\tID', self.id) return string diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat index 15de0f027..35d15d61c 100644 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ b/tests/regression_tests/filter_energyfun/inputs_true.dat @@ -24,6 +24,11 @@ 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 linear-linear + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + log-log + Am241 (n,gamma) @@ -33,4 +38,9 @@ Am241 (n,gamma) + + 3 + Am241 + (n,gamma) + diff --git a/tests/regression_tests/filter_energyfun/results_true.dat b/tests/regression_tests/filter_energyfun/results_true.dat index a1fda93a8..a75b3fd4f 100644 --- a/tests/regression_tests/filter_energyfun/results_true.dat +++ b/tests/regression_tests/filter_energyfun/results_true.dat @@ -1,2 +1,2 @@ energyfunction nuclide score mean std. dev. -0 d2effa26cb3cf2 Am241 ((n,gamma) / (n,gamma)) 1.74e-01 6.83e-03 +0 448ee8dfd19c4f Am241 ((n,gamma) / (n,gamma)) 1.74e-01 6.83e-03 diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index b5ab1387c..cb658b902 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -39,14 +39,21 @@ def model(): filt2 = openmc.EnergyFunctionFilter.from_tabulated1d(tab1d) assert filt1 == filt2, 'Error with the .from_tabulated1d constructor' + filt3 = openmc.EnergyFunctionFilter(x, y) + filt3.interpolation = 'log-log' + print(filt3) + # Make tallies - tallies = [openmc.Tally(), openmc.Tally()] + tallies = [openmc.Tally(), openmc.Tally(), openmc.Tally()] for t in tallies: t.scores = ['(n,gamma)'] t.nuclides = ['Am241'] tallies[1].filters = [filt1] + tallies[2].filters = [filt3] model.tallies.extend(tallies) + + return model @@ -75,7 +82,7 @@ class FilterEnergyFunHarness(PyAPITestHarness): model_tally = self._model.tallies[1] model_filt = model_tally.find_filter(openmc.EnergyFunctionFilter) - assert sp_filt.interpolation == model_filt.interpolation + assert sp_filt.interpolation == 'linear-linear' assert all(sp_filt.energy == model_filt.energy) assert all(sp_filt.y == model_filt.y) From c09f539cd5bd87ab3201c495a9c96552a0e5fe68 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 30 Jul 2022 00:34:37 -0500 Subject: [PATCH 0919/2654] Updating check to log-log --- openmc/filter.py | 4 ++-- src/tallies/filter_energyfunc.cpp | 12 +++++++++++- tests/regression_tests/filter_energyfun/test.py | 10 ++++------ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index f5268ad81..432ea1599 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1959,9 +1959,9 @@ class EnergyFunctionFilter(Filter): filter_id = int(group.name.split('/')[-1].lstrip('filter ')) out = cls(energy, y, filter_id=filter_id) - if 'interpolation' in group.attrs: + if 'interpolation' in group: out.interpolation = \ - openmc.data.INTERPOLATION_SCHEME[group.attrs['interpolation']] + openmc.data.INTERPOLATION_SCHEME[group['interpolation'][()]] return out diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index 819b5d13e..fb76fb215 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -29,6 +29,16 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) interpolation_ = Interpolation::lin_lin; if (check_for_node(node, "interpolation")) { std::string interpolation = get_node_value(node, "interpolation"); + if (interpolation == "linear-linear") { + interpolation_ = Interpolation::lin_lin; + } else if (interpolation == "log-log") { + interpolation_ = Interpolation::log_log; + } else { + fatal_error(fmt::format( + "Invalid interpolation type '{}' specified on EnergyFunctionFilter {}. " + "Must be 'linear-linear' or 'log-log'.", + interpolation, id())); + } } this->set_data(energy, y); @@ -90,7 +100,7 @@ void EnergyFunctionFilter::to_statepoint(hid_t filter_group) const Filter::to_statepoint(filter_group); write_dataset(filter_group, "energy", energy_); write_dataset(filter_group, "y", y_); - write_attribute( + write_dataset( filter_group, "interpolation", static_cast(interpolation_)); } diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index cb658b902..e0a191ce8 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -52,8 +52,6 @@ def model(): tallies[2].filters = [filt3] model.tallies.extend(tallies) - - return model @@ -74,15 +72,15 @@ class FilterEnergyFunHarness(PyAPITestHarness): # Read the statepoint file. sp = openmc.StatePoint(self._sp_name) - # check that values are round-tripped correctly from + # check that information is round-tripped correctly from # the statepoint file - sp_tally = sp.get_tally(id=2) + sp_tally = sp.get_tally(id=3) sp_filt = sp_tally.find_filter(openmc.EnergyFunctionFilter) - model_tally = self._model.tallies[1] + model_tally = self._model.tallies[2] model_filt = model_tally.find_filter(openmc.EnergyFunctionFilter) - assert sp_filt.interpolation == 'linear-linear' + assert sp_filt.interpolation == 'log-log' assert all(sp_filt.energy == model_filt.energy) assert all(sp_filt.y == model_filt.y) From aeca1173e7f9b4a51c774ecfbd52f13050f41983 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 30 Jul 2022 00:43:20 -0500 Subject: [PATCH 0920/2654] Expanding on eff checks for log-log case. --- .../regression_tests/filter_energyfun/test.py | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index e0a191ce8..9e8189f21 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -72,17 +72,34 @@ class FilterEnergyFunHarness(PyAPITestHarness): # Read the statepoint file. sp = openmc.StatePoint(self._sp_name) - # check that information is round-tripped correctly from - # the statepoint file - sp_tally = sp.get_tally(id=3) - sp_filt = sp_tally.find_filter(openmc.EnergyFunctionFilter) + # statepoint file round-trip checks + + # linear-linear interpolation tally + sp_lin_lin_tally = sp.get_tally(id=2) + sp_lin_lin_filt = sp_lin_lin_tally.find_filter(openmc.EnergyFunctionFilter) - model_tally = self._model.tallies[2] - model_filt = model_tally.find_filter(openmc.EnergyFunctionFilter) + model_lin_lin_tally = self._model.tallies[1] + model_lin_lin_filt = model_lin_lin_tally.find_filter(openmc.EnergyFunctionFilter) - assert sp_filt.interpolation == 'log-log' - assert all(sp_filt.energy == model_filt.energy) - assert all(sp_filt.y == model_filt.y) + assert sp_lin_lin_filt.interpolation == 'linear-linear' + assert all(sp_lin_lin_filt.energy == model_lin_lin_filt.energy) + assert all(sp_lin_lin_filt.y == model_lin_lin_filt.y) + + # log-log interpolation tally + sp_log_log_tally = sp.get_tally(id=3) + sp_log_log_filt = sp_log_log_tally.find_filter(openmc.EnergyFunctionFilter) + + model_log_log_tally = self._model.tallies[2] + model_log_log_filt = model_log_log_tally.find_filter(openmc.EnergyFunctionFilter) + + assert sp_log_log_filt.interpolation == 'log-log' + assert all(sp_log_log_filt.energy == model_log_log_filt.energy) + assert all(sp_log_log_filt.y == model_log_log_filt.y) + + + # because the values of y are monotonically increasing, + # we expect the log-log tally to have a higher value + assert all(sp_lin_lin_tally.mean < sp_log_log_tally.mean) def test_filter_energyfun(model): From 7ea116c89fce2a63c853b82021483f14cdb228e4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 30 Jul 2022 00:51:52 -0500 Subject: [PATCH 0921/2654] Adding log-lg tally output and updating results. --- tests/regression_tests/filter_energyfun/results_true.dat | 2 ++ tests/regression_tests/filter_energyfun/test.py | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/filter_energyfun/results_true.dat b/tests/regression_tests/filter_energyfun/results_true.dat index a75b3fd4f..4fedf2a0d 100644 --- a/tests/regression_tests/filter_energyfun/results_true.dat +++ b/tests/regression_tests/filter_energyfun/results_true.dat @@ -1,2 +1,4 @@ energyfunction nuclide score mean std. dev. 0 448ee8dfd19c4f Am241 ((n,gamma) / (n,gamma)) 1.74e-01 6.83e-03 + energyfunction nuclide score mean std. dev. +0 37e006ae6b2e74 Am241 (n,gamma) 8.16e-02 2.24e-03 diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index 9e8189f21..93eed3327 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -60,11 +60,17 @@ class FilterEnergyFunHarness(PyAPITestHarness): # Read the statepoint file. sp = openmc.StatePoint(self._sp_name) + dataframes_string = "" # Use tally arithmetic to compute the branching ratio. br_tally = sp.tallies[2] / sp.tallies[1] + dataframes_string += br_tally.get_pandas_dataframe().to_string() + '\n' + + # Write out the log-log interpolation as well + log_tally = sp.tallies[3] + dataframes_string += log_tally.get_pandas_dataframe().to_string() + '\n' # Output the tally in a Pandas DataFrame. - return br_tally.get_pandas_dataframe().to_string() + '\n' + return dataframes_string def _compare_results(self): super()._compare_results() @@ -96,7 +102,6 @@ class FilterEnergyFunHarness(PyAPITestHarness): assert all(sp_log_log_filt.energy == model_log_log_filt.energy) assert all(sp_log_log_filt.y == model_log_log_filt.y) - # because the values of y are monotonically increasing, # we expect the log-log tally to have a higher value assert all(sp_lin_lin_tally.mean < sp_log_log_tally.mean) From 66ff5b873de7095ef9d9704aca0f46dd8ad7d823 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 31 Jul 2022 00:51:34 -0500 Subject: [PATCH 0922/2654] Adding missing docstring --- openmc/filter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index 432ea1599..989f5d762 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1875,6 +1875,9 @@ class EnergyFunctionFilter(Filter): A grid of energy values in [eV] y : iterable of Real A grid of interpolant values in [eV] + interpolation : str + The type of interpolation to be used. + One of ('linear-linear', 'log-log') filter_id : int Unique identifier for the filter @@ -1885,7 +1888,7 @@ class EnergyFunctionFilter(Filter): y : iterable of Real A grid of interpolant values in [eV] interpolation : str - Used to indicate the type of interpolation used. + The type of interpolation to be used. One of ('linear-linear', 'log-log') id : int Unique identifier for the filter From bdf73abb06fc211ee10d5fc49946f7502f47ddb0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 31 Jul 2022 01:05:42 -0500 Subject: [PATCH 0923/2654] Some cleanup --- docs/source/io_formats/statepoint.rst | 4 ++-- src/tallies/filter_energyfunc.cpp | 2 +- tests/regression_tests/filter_energyfun/test.py | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 2332ebf21..71025d1e6 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -108,8 +108,8 @@ The current version of the statepoint file format is 17.0. interpolation. Only used for 'energyfunction' filters. - **y** (*double[]*) -- Interpolant values for energyfunction interpolation. Only used for 'energyfunction' filters. - - **interpolation** (*int*) -- Interpolation type. One of - (1 - linear-linear or 2 - log-log). Only used for 'energyfunction' + - **interpolation** (*int*) -- Interpolation type. Either + 1 (linear-linear) or 2 (log-log). Only used for 'energyfunction' filters. **/tallies/derivatives/derivative /** diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index fb76fb215..b0a42d099 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -25,7 +25,7 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) auto y = get_node_array(node, "y"); - // use linear-linear interpolation by default + // default to linear-linear interpolation interpolation_ = Interpolation::lin_lin; if (check_for_node(node, "interpolation")) { std::string interpolation = get_node_value(node, "interpolation"); diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index 93eed3327..b09f0e5ec 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -41,7 +41,6 @@ def model(): filt3 = openmc.EnergyFunctionFilter(x, y) filt3.interpolation = 'log-log' - print(filt3) # Make tallies tallies = [openmc.Tally(), openmc.Tally(), openmc.Tally()] From d78a9b188594a262bb84cb758fd8f13f75887966 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 1 Aug 2022 17:34:39 -0500 Subject: [PATCH 0924/2654] Adding new interpolation entry. --- include/openmc/constants.h | 3 ++- openmc/data/function.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index a7362ea9e..9c9a5f9b3 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -318,7 +318,8 @@ enum class Interpolation { lin_lin = 2, lin_log = 3, log_lin = 4, - log_log = 5 + log_log = 5, + cubic = 6 }; enum class RunMode { diff --git a/openmc/data/function.py b/openmc/data/function.py index b0390d19c..f03319eed 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -13,7 +13,7 @@ from openmc.mixin import EqualityMixin from .data import EV_PER_MEV INTERPOLATION_SCHEME = {1: 'histogram', 2: 'linear-linear', 3: 'linear-log', - 4: 'log-linear', 5: 'log-log'} + 4: 'log-linear', 5: 'log-log', 6 : 'cubic'} def sum_functions(funcs): From 4ba9acd459391a1d9806d112480ce47489b49fab Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 1 Aug 2022 18:50:49 -0500 Subject: [PATCH 0925/2654] Adding test results for additional interpolation types --- docs/source/io_formats/statepoint.rst | 7 +- include/openmc/interpolate.h | 65 +++++++++++++++++++ openmc/filter.py | 11 ++-- src/material.cpp | 4 +- src/physics.cpp | 13 ++-- src/tallies/filter_energyfunc.cpp | 24 +++++-- .../filter_energyfun/inputs_true.dat | 20 ++++++ .../filter_energyfun/results_true.dat | 4 ++ .../regression_tests/filter_energyfun/test.py | 35 +++++++--- 9 files changed, 148 insertions(+), 35 deletions(-) create mode 100644 include/openmc/interpolate.h diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 71025d1e6..09a531ecd 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -80,7 +80,7 @@ The current version of the statepoint file format is 17.0. dimension. - **Unstructured Mesh Only:** - **filename** (*char[]*) -- Name of the mesh file. - - **library** (*char[]*) -- Mesh library used to represent the + - **library** (*char[]*) -- Mesh library used to represent the mesh ("moab" or "libmesh"). - **length_multiplier** (*double*) Scaling factor applied to the mesh. - **volumes** (*double[]*) -- Volume of each mesh cell. @@ -108,9 +108,8 @@ The current version of the statepoint file format is 17.0. interpolation. Only used for 'energyfunction' filters. - **y** (*double[]*) -- Interpolant values for energyfunction interpolation. Only used for 'energyfunction' filters. - - **interpolation** (*int*) -- Interpolation type. Either - 1 (linear-linear) or 2 (log-log). Only used for 'energyfunction' - filters. + - **interpolation** (*int*) -- Interpolation type. Only used for + 'energyfunction' filters. **/tallies/derivatives/derivative /** diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h new file mode 100644 index 000000000..b88ab2f2e --- /dev/null +++ b/include/openmc/interpolate.h @@ -0,0 +1,65 @@ + +#ifndef OPENMC_INTERPOLATE_H +#define OPENMC_INTERPOLATE_H + +#include +#include + +#include "openmc/search.h" + +namespace openmc { + +inline double interpolate_lin_lin( + double x0, double x1, double y0, double y1, double x) +{ + return y0 + (x - x0) / (x1 - x0) * (y1 - y0); +} + +inline double interpolate_lin_log( + double x0, double x1, double y0, double y1, double x) +{ + return y0 + log(x / x0) / log(x1 / x0) * (y1 - y0); +} + +inline double interpolate_log_lin( + double x0, double x1, double y0, double y1, double x) +{ + return y0 * exp((x - x0) / (x1 - x0) * log(y1 / y0)); +} + +inline double interpolate_log_log( + double x0, double x1, double y0, double y1, double x) +{ + double f = log(x / x0) / log(x1 / x0); + return y0 * exp(f * log(y1 / y0)); +} + +inline double interpolate(const std::vector& xs, + const std::vector& ys, int idx, double x, + Interpolation i = Interpolation::lin_lin) +{ + switch (i) { + case Interpolation::lin_lin: + return interpolate_lin_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + case Interpolation::log_log: + return interpolate_log_log(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + case Interpolation::lin_log: + return interpolate_lin_log(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + case Interpolation::log_lin: + return interpolate_log_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + default: + fatal_error("Unsupported interpolation"); + } +} + +inline double interpolate(const std::vector& xs, + const std::vector& ys, double x, + Interpolation i = Interpolation::lin_lin) +{ + int idx = lower_bound_index(xs.begin(), xs.end(), x); + return interpolate(xs, ys, idx, x, i); +} + +} // namespace openmc + +#endif \ No newline at end of file diff --git a/openmc/filter.py b/openmc/filter.py index 989f5d762..858238bcf 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -12,6 +12,7 @@ import pandas as pd import openmc import openmc.checkvalue as cv from .cell import Cell +from .data.function import INTERPOLATION_SCHEME from .material import Material from .mixin import IDManagerMixin from .surface import Surface @@ -1877,7 +1878,6 @@ class EnergyFunctionFilter(Filter): A grid of interpolant values in [eV] interpolation : str The type of interpolation to be used. - One of ('linear-linear', 'log-log') filter_id : int Unique identifier for the filter @@ -1889,7 +1889,6 @@ class EnergyFunctionFilter(Filter): A grid of interpolant values in [eV] interpolation : str The type of interpolation to be used. - One of ('linear-linear', 'log-log') id : int Unique identifier for the filter num_bins : Integral @@ -1958,7 +1957,7 @@ class EnergyFunctionFilter(Filter): + group['type'][()].decode() + " instead") energy = group['energy'][()] - y = group['y'][()] + y = group['y'][()] filter_id = int(group.name.split('/')[-1].lstrip('filter ')) out = cls(energy, y, filter_id=filter_id) @@ -2045,7 +2044,7 @@ class EnergyFunctionFilter(Filter): @interpolation.setter def interpolation(self, val): cv.check_type('interpolation', val, str) - cv.check_value('interpolation', val, ('linear-linear', 'log-log')) + cv.check_value('interpolation', val, INTERPOLATION_SCHEME.values()) self._interpolation = val def to_xml_element(self): @@ -2076,11 +2075,11 @@ class EnergyFunctionFilter(Filter): def from_xml_element(cls, elem, **kwargs): filter_id = int(elem.get('id')) energy = [float(x) for x in get_text(elem, 'energy').split()] - y = [float(x) for x in get_text(elem, 'y').split()] + y = [float(x) for x in get_text(elem, 'y').split()] out = cls(energy, y, filter_id=filter_id) if elem.find('interpolation') is not None: out.interpolation = elem.find('interpolation') - return out + return out def can_merge(self, other): return False diff --git a/src/material.cpp b/src/material.cpp index 30dfa5ed5..8c75b079d 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -734,8 +734,8 @@ void Material::init_bremsstrahlung() // Loop over photon energies double c = 0.0; for (int i = 0; i < j; ++i) { - // Integrate the CDF from the PDF using the trapezoidal rule in log-log - // space + // Integra te the CDF from the PDF using the trapezoidal rule in + // log-log space double w_l = std::log(data::ttb_e_grid(i)); double w_r = std::log(data::ttb_e_grid(i + 1)); double x_l = std::log(ttb->pdf(j, i)); diff --git a/src/physics.cpp b/src/physics.cpp index bcdcf7ecf..5e9afa090 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -7,6 +7,7 @@ #include "openmc/eigenvalue.h" #include "openmc/endf.h" #include "openmc/error.h" +#include "openmc/interpolate.h" #include "openmc/material.h" #include "openmc/math_functions.h" #include "openmc/message_passing.h" @@ -883,15 +884,9 @@ Direction sample_target_velocity(const Nuclide& nuc, double E, Direction u, if (sampling_method == ResScatMethod::dbrc) { // interpolate xs since we're not exactly at the energy indices - double xs_low = nuc.elastic_0K_[i_E_low]; - double m = (nuc.elastic_0K_[i_E_low + 1] - xs_low) / - (nuc.energy_0K_[i_E_low + 1] - nuc.energy_0K_[i_E_low]); - xs_low += m * (E_low - nuc.energy_0K_[i_E_low]); - double xs_up = nuc.elastic_0K_[i_E_up]; - m = (nuc.elastic_0K_[i_E_up + 1] - xs_up) / - (nuc.energy_0K_[i_E_up + 1] - nuc.energy_0K_[i_E_up]); - xs_up += m * (E_up - nuc.energy_0K_[i_E_up]); - + double xs_low = + interpolate(nuc.energy_0K_, nuc.elastic_0K_, i_E_low, E_low); + double xs_up = interpolate(nuc.energy_0K_, nuc.elastic_0K_, i_E_up, E_up); // get max 0K xs value over range of practical relative energies double xs_max = *std::max_element( &nuc.elastic_0K_[i_E_low + 1], &nuc.elastic_0K_[i_E_up + 1]); diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index b0a42d099..f883975a3 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -3,6 +3,7 @@ #include #include "openmc/error.h" +#include "openmc/interpolate.h" #include "openmc/search.h" #include "openmc/settings.h" #include "openmc/xml_interface.h" @@ -31,12 +32,15 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) std::string interpolation = get_node_value(node, "interpolation"); if (interpolation == "linear-linear") { interpolation_ = Interpolation::lin_lin; + } else if (interpolation == "linear-log") { + interpolation_ = Interpolation::lin_log; + } else if (interpolation == "log-linear") { + interpolation_ = Interpolation::log_lin; } else if (interpolation == "log-log") { interpolation_ = Interpolation::log_log; } else { fatal_error(fmt::format( - "Invalid interpolation type '{}' specified on EnergyFunctionFilter {}. " - "Must be 'linear-linear' or 'log-log'.", + "Found invalid interpolation type '{}' on EnergyFunctionFilter {}.", interpolation, id())); } } @@ -77,12 +81,20 @@ void EnergyFunctionFilter::get_all_bins( double f, w; switch (interpolation_) { case Interpolation::lin_lin: - f = (p.E_last() - energy_[i]) / (energy_[i + 1] - energy_[i]); - w = (1 - f) * y_[i] + f * y_[i + 1]; + w = interpolate_lin_lin( + energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); + break; + case Interpolation::lin_log: + w = interpolate_lin_log( + energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); + break; + case Interpolation::log_lin: + w = interpolate_log_lin( + energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); break; case Interpolation::log_log: - f = log(p.E_last() / energy_[i]) / log(energy_[i + 1] / energy_[i]); - w = y_[i] * exp(f * log(y_[i + 1] / y_[i])); + w = interpolate_log_log( + energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); break; default: fatal_error(fmt::format( diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat index 35d15d61c..8c3db3518 100644 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ b/tests/regression_tests/filter_energyfun/inputs_true.dat @@ -29,6 +29,16 @@ 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 log-log + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + linear-log + + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + log-linear + Am241 (n,gamma) @@ -43,4 +53,14 @@ Am241 (n,gamma) + + 4 + Am241 + (n,gamma) + + + 5 + Am241 + (n,gamma) + diff --git a/tests/regression_tests/filter_energyfun/results_true.dat b/tests/regression_tests/filter_energyfun/results_true.dat index 4fedf2a0d..c0b59680e 100644 --- a/tests/regression_tests/filter_energyfun/results_true.dat +++ b/tests/regression_tests/filter_energyfun/results_true.dat @@ -2,3 +2,7 @@ 0 448ee8dfd19c4f Am241 ((n,gamma) / (n,gamma)) 1.74e-01 6.83e-03 energyfunction nuclide score mean std. dev. 0 37e006ae6b2e74 Am241 (n,gamma) 8.16e-02 2.24e-03 + energyfunction nuclide score mean std. dev. +0 b4e2ac84068d2d Am241 (n,gamma) 8.19e-02 2.25e-03 + energyfunction nuclide score mean std. dev. +0 dacf88242512ea Am241 (n,gamma) 7.95e-02 2.19e-03 diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index b09f0e5ec..c297c094a 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -32,7 +32,7 @@ def model(): with pytest.raises(ValueError): filt1.interpolation = '5th order polynomial' - + # Also make a filter with the .from_tabulated1d constructor. Make sure # the filters are identical. tab1d = openmc.data.Tabulated1D(x, y) @@ -42,13 +42,22 @@ def model(): filt3 = openmc.EnergyFunctionFilter(x, y) filt3.interpolation = 'log-log' + filt4 = openmc.EnergyFunctionFilter(x , y) + filt4.interpolation = 'linear-log' + + filt5 = openmc.EnergyFunctionFilter(x, y) + filt5.interpolation = 'log-linear' + + filters = [filt1, filt3, filt4, filt5] # Make tallies - tallies = [openmc.Tally(), openmc.Tally(), openmc.Tally()] + tallies = [openmc.Tally() for i in range(5)] for t in tallies: t.scores = ['(n,gamma)'] t.nuclides = ['Am241'] - tallies[1].filters = [filt1] - tallies[2].filters = [filt3] + + for t, f in zip(tallies[1:], filters): + t.filters = [f] + model.tallies.extend(tallies) return model @@ -64,9 +73,11 @@ class FilterEnergyFunHarness(PyAPITestHarness): br_tally = sp.tallies[2] / sp.tallies[1] dataframes_string += br_tally.get_pandas_dataframe().to_string() + '\n' - # Write out the log-log interpolation as well - log_tally = sp.tallies[3] - dataframes_string += log_tally.get_pandas_dataframe().to_string() + '\n' + + for t_id in (3, 4, 5): + # Write out the log-log interpolation as well + ef_tally = sp.tallies[t_id] + dataframes_string += ef_tally.get_pandas_dataframe().to_string() + '\n' # Output the tally in a Pandas DataFrame. return dataframes_string @@ -78,7 +89,7 @@ class FilterEnergyFunHarness(PyAPITestHarness): sp = openmc.StatePoint(self._sp_name) # statepoint file round-trip checks - + # linear-linear interpolation tally sp_lin_lin_tally = sp.get_tally(id=2) sp_lin_lin_filt = sp_lin_lin_tally.find_filter(openmc.EnergyFunctionFilter) @@ -105,6 +116,14 @@ class FilterEnergyFunHarness(PyAPITestHarness): # we expect the log-log tally to have a higher value assert all(sp_lin_lin_tally.mean < sp_log_log_tally.mean) + sp_lin_log_tally = self._model.tallies[3] + sp_lin_log_filt = sp_lin_log_tally.find_filter(openmc.EnergyFunctionFilter) + assert sp_lin_log_filt.interpolation == 'linear-log' + + sp_log_lin_tally = self._model.tallies[4] + sp_log_lin_filt = sp_log_lin_tally.find_filter(openmc.EnergyFunctionFilter) + assert sp_log_lin_filt.interpolation == 'log-linear' + def test_filter_energyfun(model): harness = FilterEnergyFunHarness('statepoint.5.h5', model) From 48a9ac9a2cb9df43d391f3a0dbe6948f26536afb Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 6 Aug 2022 06:48:47 -0500 Subject: [PATCH 0926/2654] Adding initial lagrangian interpolation. --- include/openmc/interpolate.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index b88ab2f2e..068314033 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -60,6 +60,31 @@ inline double interpolate(const std::vector& xs, return interpolate(xs, ys, idx, x, i); } +inline double interpolate_lagrangian( + const std::vector& xs, const std::vector& ys, double x) +{ + int idx = lower_bound_index(xs.begin(), xs.end(), x); + + std::vector coeffs; + + int order = 3; + + for (int i = 0; i < order + 1; i++) { + double numerator {1.0}; + double denominator {1.0}; + for (int j = 0; j < order; j++) { + if (i == j) + continue; + numerator *= (x - xs[idx + j]); + denominator *= (xs[idx + i] - xs[idx + j]); + } + coeffs.push_back(numerator / denominator); + } + + return std::inner_product( + coeffs.begin(), coeffs.end(), ys.begin() + idx, 0.0); +} + } // namespace openmc #endif \ No newline at end of file From 445fb0af3627b728a35de8fffa33f17501b85ead Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 8 Aug 2022 07:38:37 -0500 Subject: [PATCH 0927/2654] Adjusting interpolation enumeration values. --- include/openmc/constants.h | 3 ++- openmc/data/function.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index 9c9a5f9b3..32cd8186a 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -319,7 +319,8 @@ enum class Interpolation { lin_log = 3, log_lin = 4, log_log = 5, - cubic = 6 + quadratic = 6, + cubic = 7 }; enum class RunMode { diff --git a/openmc/data/function.py b/openmc/data/function.py index f03319eed..59f549d6f 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -13,7 +13,7 @@ from openmc.mixin import EqualityMixin from .data import EV_PER_MEV INTERPOLATION_SCHEME = {1: 'histogram', 2: 'linear-linear', 3: 'linear-log', - 4: 'log-linear', 5: 'log-log', 6 : 'cubic'} + 4: 'log-linear', 5: 'log-log', 6 : 'quadratic', 7 : 'cubic'} def sum_functions(funcs): From aa571c2c33b421e2524e249ca00f9584e891dd0a Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 0928/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- include/openmc/state_point.h | 9 +++ src/state_point.cpp | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 5ada2bf88..2d92c935a 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -9,6 +9,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { void load_state_point(); @@ -21,5 +25,10 @@ void write_tally_results_nr(hid_t file_id); void restart_set_keff(); void write_unstructured_mesh_results(); +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename_, bool surf_source_bank = false); +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); +#endif + } // namespace openmc #endif // OPENMC_STATE_POINT_H diff --git a/src/state_point.cpp b/src/state_point.cpp index 9ea045915..babd670a2 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -28,6 +28,10 @@ #include "openmc/timer.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) @@ -598,6 +602,45 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } +void write_mcpl_point(const char *filename, bool surf_source_bank) +{ + std::string filename_; + if (filename) { + filename_ = filename; + } else { + // Determine width for zero padding + int w = std::to_string(settings::n_max_batches).size(); + + filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, + simulation::current_batch, w); + } + + mcpl_outfile_t file_id; + + std::string line; + if (mpi::master) { + // this must be rewritten: file_open is h5-specific + file_id = mcpl_create_outfile(filename_.c_str()); + //write_attribute(file_id, "filetype", "source"); + //write header stuff (oopy in xml-files as binary blobs for instance)) + if (VERSION_DEV){ + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}-development"); + } else { + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}"); + } + mcpl_hdr_set_srcname(file_id,line.c_str()); + } + + write_mcpl_source_bank(file_id, surf_source_bank); + + if (mpi::master) { + //change this - this is h5 specific + mcpl_closeandgzip_outfile(file_id); + } + +} + + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); @@ -714,6 +757,88 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) +{ + int64_t dims_size = settings::n_particles; + int64_t count_size = simulation::work_per_rank; + + // Set vectors for source bank and starting bank index of each process + vector* bank_index = &simulation::work_index; + vector* source_bank = &simulation::source_bank; + vector surf_source_index_vector; + vector surf_source_bank_vector; + + if(surf_source_bank) { + surf_source_index_vector = calculate_surf_source_size(); + dims_size = surf_source_index_vector[mpi::n_procs]; + count_size = simulation::surf_source_bank.size(); + + bank_index = &surf_source_index_vector; + + // Copy data in a SharedArray into a vector. + surf_source_bank_vector.resize(count_size); + surf_source_bank_vector.assign(simulation::surf_source_bank.data(), + simulation::surf_source_bank.data() + count_size); + source_bank = &surf_source_bank_vector; + } + + if (mpi::master) { + //write particles from the master node + //loop over the other nodes and receive data - then write those. + for (int i = 0; i < mpi::n_procs; ++i) { +#ifdef OPENMC_MPI + if (i>0) + MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + mpi::intracomm, MPI_STATUS_IGNORE); +#endif + //now write the source_banke data again. + for (vector::iterator _site=source_bank->begin(); _site!=source_bank->end();_site++){ + //particle is now at the iterator + //write it to the mcpl-file + mcpl_particle_t p; + p.position[0]=_site->r.x; + p.position[1]=_site->r.y; + p.position[2]=_site->r.z; + + p.direction[0]=_site->u.x; + p.direction[1]=_site->u.y; + p.direction[2]=_site->u.x; + + //mcpl stores kinetic energy in MeV + p.ekin=_site->E*1e-6; + + p.time=_site->time*1e3; + + p.weight=_site->wgt; + + switch(_site->particle){ + case ParticleType::neutron: + p.pdgcode=2112; + break; + case ParticleType::photon: + p.pdgcode=22; + break; + case ParticleType::electron: + p.pdgcode=11; + break; + case ParticleType::positron: + p.pdgcode=-11; + break; + } + + mcpl_add_particle(file_id,&p); + } + } + } else { +#ifdef OPENMC_MPI + MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + mpi::intracomm); +#endif + } + +} + + // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) { From be09b442fbfc41d029ed0eccef87ea25477f40aa Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 09:11:41 +0200 Subject: [PATCH 0929/2654] allow electrons and positrons as well --- src/source.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 82978f103..e7c944cb5 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -383,19 +383,30 @@ SourceSite MCPLFileSource::read_single_particle() const { SourceSite omc_particle_; const mcpl_particle_t *mcpl_particle; - //extract particle from mcpl-file + // extract particle from mcpl-file mcpl_particle=mcpl_read(mcpl_file); - // check if it is a neutron or a photon. otherwise skip - while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { + // check if it is a neutron, photon, electron, or positron. Otherwise skip. + int pdg=mcpl_particle->pdgcode; + while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { mcpl_particle=mcpl_read(mcpl_file); - //should check for file exhaustion This could happen if particles are other than - //neutrons or photons + pdg=mcpl_particle->pdgcode; + //should check for file exhaustion. This could happen if particles are other than + //neutrons, photons, electrons, or positrons. } - if(mcpl_particle->pdgcode==2112) { - omc_particle_.particle=ParticleType::neutron; - } else if (mcpl_particle->pdgcode==22) { - omc_particle_.particle=ParticleType::photon; + switch(pdg){ + case 2112: + omc_particle_.particle=ParticleType::neutron; + break; + case 22: + omc_particle_.particle=ParticleType::photon; + break; + case 11: + omc_particle_.particle=ParticleType::electron; + break; + case -11: + omc_particle_.particle=ParticleType::positron; + break; } //particle is good, convert to openmc-formalism From 4e5ba4b4601209f389c394cd3747891e76b43f1c Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 09:12:01 +0200 Subject: [PATCH 0930/2654] expose a python function to check for mcpl --- openmc/lib/__init__.py | 3 +++ src/source.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/openmc/lib/__init__.py b/openmc/lib/__init__.py index c14b0d9c2..1e337fc07 100644 --- a/openmc/lib/__init__.py +++ b/openmc/lib/__init__.py @@ -48,6 +48,9 @@ def _coord_levels(): def _libmesh_enabled(): return c_bool.in_dll(_dll, "LIBMESH_ENABLED").value +def _mcpl_enabled(): + return c_bool.in_dll(_dll, "MCPL_ENABLED").value + from .error import * from .core import * from .nuclide import * diff --git a/src/source.cpp b/src/source.cpp index e7c944cb5..9b426c3cf 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -41,6 +41,12 @@ namespace openmc { // Global variables //============================================================================== +#ifdef OPENMC_MCPL +const bool MCPL_ENABLED = true; +#else +const bool MCPL_ENABLED = false; +#endif + namespace model { vector> external_sources; From 1c917201aee18000b9a9ccf98f6f422c3f2ac121 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 6 Sep 2022 13:59:09 +0100 Subject: [PATCH 0931/2654] type hints added to openmc.deplete.Results --- openmc/deplete/results.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index b38dcf058..aea54ba8c 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -1,6 +1,7 @@ import numbers import bisect import math +from typing import Iterable, Optional, Tuple from warnings import warn import h5py @@ -15,7 +16,7 @@ from openmc.exceptions import DataError __all__ = ["Results", "ResultsList"] -def _get_time_as(seconds, units): +def _get_time_as(seconds: float, units: str) -> float: """Converts the time in seconds to time in different units Parameters @@ -70,7 +71,7 @@ class Results(list): @classmethod - def from_hdf5(cls, filename): + def from_hdf5(cls, filename: str): """Load in depletion results from a previous file Parameters @@ -91,7 +92,13 @@ class Results(list): ) return cls(filename) - def get_atoms(self, mat, nuc, nuc_units="atoms", time_units="s"): + def get_atoms( + self, + mat: Material, + nuc: str, + nuc_units: str = "atoms", + time_units: str = "s" + ) -> Tuple[np.ndarray, np.ndarray]: """Get number of nuclides over time from a single material .. note:: @@ -155,7 +162,12 @@ class Results(list): return times, concentrations - def get_reaction_rate(self, mat, nuc, rx): + def get_reaction_rate( + self, + mat: Material, + nuc: str, + rx: str + ) -> Tuple[np.ndarray, np.ndarray]: """Get reaction rate in a single material/nuclide over time .. note:: @@ -200,7 +212,7 @@ class Results(list): return times, rates - def get_keff(self, time_units='s'): + def get_keff(self, time_units: str = 's') -> Tuple[np.ndarray, np.ndarray]: """Evaluates the eigenvalue from a results list. .. versionadded:: 0.13.1 @@ -236,12 +248,12 @@ class Results(list): times = _get_time_as(times, time_units) return times, eigenvalues - def get_eigenvalue(self, time_units='s'): + def get_eigenvalue(self, time_units: str = 's') -> Tuple[np.ndarray, np.ndarray]: warn("The get_eigenvalue(...) function has been renamed get_keff and " "will be removed in a future version of OpenMC.", FutureWarning) return self.get_keff(time_units) - def get_depletion_time(self): + def get_depletion_time(self) -> np.ndarray: """Return an array of the average time to deplete a material .. note:: @@ -269,7 +281,7 @@ class Results(list): times[ix] = res.proc_time return times - def get_times(self, time_units="d") -> np.ndarray: + def get_times(self, time_units: str = "d") -> np.ndarray: """Return the points in time that define the depletion schedule .. versionadded:: 0.12.1 @@ -298,7 +310,7 @@ class Results(list): return _get_time_as(times, time_units) def get_step_where( - self, time, time_units="d", atol=1e-6, rtol=1e-3 + self, time, time_units: str = "d", atol: float = 1e-6, rtol: float = 1e-3 ) -> int: """Return the index closest to a given point in time @@ -358,7 +370,11 @@ class Results(list): time, time_units, atol, rtol) ) - def export_to_materials(self, burnup_index, nuc_with_data=None) -> Materials: + def export_to_materials( + self, + burnup_index: int, + nuc_with_data: Optional[Iterable[str]] = None + ) -> Materials: """Return openmc.Materials object based on results at a given step .. versionadded:: 0.12.1 From 225dc5c43cece1deea1049fcd703e06541ad4e46 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 6 Sep 2022 17:22:31 +0100 Subject: [PATCH 0932/2654] create PathLike type for hints --- openmc/checkvalue.py | 5 +++++ openmc/deplete/results.py | 7 ++++--- openmc/material.py | 6 +++--- openmc/settings.py | 5 +++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/openmc/checkvalue.py b/openmc/checkvalue.py index d50b3fcae..c5d80b2fc 100644 --- a/openmc/checkvalue.py +++ b/openmc/checkvalue.py @@ -1,8 +1,13 @@ import copy +import os +from typing import Union from collections.abc import Iterable import numpy as np +# Type for arguments that accept file paths +PathLike = Union[str, os.PathLike] + def check_type(name, value, expected_type, expected_iter_type=None, *, none_ok=False): """Ensure that an object is of an expected type. Optionally, if the object is diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index aea54ba8c..ab2123220 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -1,7 +1,7 @@ import numbers import bisect import math -from typing import Iterable, Optional, Tuple +from typing import Iterable, Optional, Tuple, Union from warnings import warn import h5py @@ -12,6 +12,7 @@ import openmc.checkvalue as cv from openmc.data.library import DataLibrary from openmc.material import Material, Materials from openmc.exceptions import DataError +from openmc.checkvalue import PathLike __all__ = ["Results", "ResultsList"] @@ -71,7 +72,7 @@ class Results(list): @classmethod - def from_hdf5(cls, filename: str): + def from_hdf5(cls, filename: PathLike): """Load in depletion results from a previous file Parameters @@ -164,7 +165,7 @@ class Results(list): def get_reaction_rate( self, - mat: Material, + mat: Union[Material, str], nuc: str, rx: str ) -> Tuple[np.ndarray, np.ndarray]: diff --git a/openmc/material.py b/openmc/material.py index f137ec0cd..15a5933a6 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -3,7 +3,6 @@ from collections.abc import Iterable from copy import deepcopy from numbers import Real from pathlib import Path -import os import re import typing # imported separately as py3.8 requires typing.Iterable import warnings @@ -18,6 +17,7 @@ import openmc.data import openmc.checkvalue as cv from ._xml import clean_indentation, reorder_attributes from .mixin import IDManagerMixin +from openmc.checkvalue import PathLike # Units for density supported by OpenMC @@ -1382,7 +1382,7 @@ class Materials(cv.CheckedList): for material in self: material.make_isotropic_in_lab() - def export_to_xml(self, path: Union[str, os.PathLike] = 'materials.xml'): + def export_to_xml(self, path: PathLike = 'materials.xml'): """Export material collection to an XML file. Parameters @@ -1429,7 +1429,7 @@ class Materials(cv.CheckedList): fh.write('\n') @classmethod - def from_xml(cls, path: Union[str, os.PathLike] = 'materials.xml'): + def from_xml(cls, path: PathLike = 'materials.xml'): """Generate materials collection from XML file Parameters diff --git a/openmc/settings.py b/openmc/settings.py index 4372e679f..ad5a9b28a 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -13,6 +13,7 @@ import openmc.checkvalue as cv from . import RegularMesh, Source, VolumeCalculation, WeightWindows from ._xml import clean_indentation, get_text, reorder_attributes +from openmc.checkvalue import PathLike class RunMode(Enum): @@ -1535,7 +1536,7 @@ class Settings: if text is not None: self.max_tracks = int(text) - def export_to_xml(self, path: Union[str, os.PathLike] = 'settings.xml'): + def export_to_xml(self, path: PathLike = 'settings.xml'): """Export simulation settings to an XML file. Parameters @@ -1607,7 +1608,7 @@ class Settings: tree.write(str(p), xml_declaration=True, encoding='utf-8') @classmethod - def from_xml(cls, path: Union[str, os.PathLike] = 'settings.xml'): + def from_xml(cls, path: PathLike = 'settings.xml'): """Generate settings from XML file .. versionadded:: 0.13.0 From 32e71395b3ad44ecc7080ba39d4b920adfb88702 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 23:06:19 +0200 Subject: [PATCH 0933/2654] add a trigger to simulation control --- src/simulation.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/simulation.cpp b/src/simulation.cpp index b70535c33..05c8c0450 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -406,6 +406,13 @@ void finalize_batch() auto filename = settings::path_output + "surface_source.h5"; write_source_point(filename.c_str(), true); } + + if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + auto filename = settings::path_output + ".mcpl"; + write_mcplt_source_point(filename.c_str(), true); + } + + } void initialize_generation() From d300bac7340f473dc8d4cf6b586ea92a69ecac55 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Sep 2022 20:30:43 -0500 Subject: [PATCH 0934/2654] Reverting some changes outside of the EFF. --- src/material.cpp | 4 ++-- src/physics.cpp | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/material.cpp b/src/material.cpp index 8c75b079d..30dfa5ed5 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -734,8 +734,8 @@ void Material::init_bremsstrahlung() // Loop over photon energies double c = 0.0; for (int i = 0; i < j; ++i) { - // Integra te the CDF from the PDF using the trapezoidal rule in - // log-log space + // Integrate the CDF from the PDF using the trapezoidal rule in log-log + // space double w_l = std::log(data::ttb_e_grid(i)); double w_r = std::log(data::ttb_e_grid(i + 1)); double x_l = std::log(ttb->pdf(j, i)); diff --git a/src/physics.cpp b/src/physics.cpp index 5e9afa090..bcdcf7ecf 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -7,7 +7,6 @@ #include "openmc/eigenvalue.h" #include "openmc/endf.h" #include "openmc/error.h" -#include "openmc/interpolate.h" #include "openmc/material.h" #include "openmc/math_functions.h" #include "openmc/message_passing.h" @@ -884,9 +883,15 @@ Direction sample_target_velocity(const Nuclide& nuc, double E, Direction u, if (sampling_method == ResScatMethod::dbrc) { // interpolate xs since we're not exactly at the energy indices - double xs_low = - interpolate(nuc.energy_0K_, nuc.elastic_0K_, i_E_low, E_low); - double xs_up = interpolate(nuc.energy_0K_, nuc.elastic_0K_, i_E_up, E_up); + double xs_low = nuc.elastic_0K_[i_E_low]; + double m = (nuc.elastic_0K_[i_E_low + 1] - xs_low) / + (nuc.energy_0K_[i_E_low + 1] - nuc.energy_0K_[i_E_low]); + xs_low += m * (E_low - nuc.energy_0K_[i_E_low]); + double xs_up = nuc.elastic_0K_[i_E_up]; + m = (nuc.elastic_0K_[i_E_up + 1] - xs_up) / + (nuc.energy_0K_[i_E_up + 1] - nuc.energy_0K_[i_E_up]); + xs_up += m * (E_up - nuc.energy_0K_[i_E_up]); + // get max 0K xs value over range of practical relative energies double xs_max = *std::max_element( &nuc.elastic_0K_[i_E_low + 1], &nuc.elastic_0K_[i_E_up + 1]); From 5168b3392a2a5b4e3aa54531dc1ba0a7bedf0487 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Sep 2022 20:31:00 -0500 Subject: [PATCH 0935/2654] Accepting other interpolation types for converted Tabulated1D distributions --- openmc/filter.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 858238bcf..9815572a3 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1987,10 +1987,18 @@ class EnergyFunctionFilter(Filter): if tab1d.n_regions > 1: raise ValueError('Only Tabulated1Ds with a single interpolation ' 'region are supported') - if tab1d.interpolation[0] not in (2, 5): - raise ValueError('Only linear-linear or log-log Tabulated1Ds are supported') + if tab1d.interpolation[0] not in (2, 3, 4, 5): + raise ValueError('Only linear-linear, linear-log, log-linear, and ' + 'log-log Tabulated1Ds are supported') out = cls(tab1d.x, tab1d.y) - if tab1d.interpolation[0] == 5: + + if tab1d.interpolation[0] == 2: + out.interpolation = 'linear-lienar' + elif tab1d.interpolation[0] == 3: + out.interpolation = 'linear-log' + elif tab1d.interpolation[0] == 4: + out.interpolation = 'log-linear' + elif tab1d.interpolation[0] == 5: out.interpolation = 'log-log' return out From 35aa433b9a460c6cf5093d3864fb50e8c56d140c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Sep 2022 22:49:00 -0500 Subject: [PATCH 0936/2654] Updating interpolation function signature. --- include/openmc/interpolate.h | 63 ++++++++++++++++--------------- src/tallies/filter_energyfunc.cpp | 25 +----------- 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index 068314033..2764b7ffc 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -34,41 +34,11 @@ inline double interpolate_log_log( return y0 * exp(f * log(y1 / y0)); } -inline double interpolate(const std::vector& xs, - const std::vector& ys, int idx, double x, - Interpolation i = Interpolation::lin_lin) -{ - switch (i) { - case Interpolation::lin_lin: - return interpolate_lin_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); - case Interpolation::log_log: - return interpolate_log_log(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); - case Interpolation::lin_log: - return interpolate_lin_log(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); - case Interpolation::log_lin: - return interpolate_log_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); - default: - fatal_error("Unsupported interpolation"); - } -} - -inline double interpolate(const std::vector& xs, - const std::vector& ys, double x, - Interpolation i = Interpolation::lin_lin) -{ - int idx = lower_bound_index(xs.begin(), xs.end(), x); - return interpolate(xs, ys, idx, x, i); -} - inline double interpolate_lagrangian( - const std::vector& xs, const std::vector& ys, double x) + const std::vector& xs, const std::vector& ys, int idx, double x, int order) { - int idx = lower_bound_index(xs.begin(), xs.end(), x); - std::vector coeffs; - int order = 3; - for (int i = 0; i < order + 1; i++) { double numerator {1.0}; double denominator {1.0}; @@ -85,6 +55,37 @@ inline double interpolate_lagrangian( coeffs.begin(), coeffs.end(), ys.begin() + idx, 0.0); } +inline double interpolate(const std::vector& xs, + const std::vector& ys, double x, + Interpolation i = Interpolation::lin_lin) +{ + int idx = lower_bound_index(xs.begin(), xs.end(), x); + + switch (i) { + case Interpolation::lin_lin: + return interpolate_lin_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + case Interpolation::log_log: + return interpolate_log_log(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + case Interpolation::lin_log: + return interpolate_lin_log(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + case Interpolation::log_lin: + return interpolate_log_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); + case Interpolation::quadratic: + // move back one point if x is in the last interval of the x-grid + if (idx == xs.size() - 2 && idx > 0) idx--; + return interpolate_lagrangian(xs, ys, x, idx, 2); + case Interpolation::cubic: + // if x is not in the first interval of the x-grid, move back one + if (idx > 0) idx--; + // if the index was the last interval of the x-grid, move it back one more + if (idx == xs.size() - 3) idx--; + return interpolate_lagrangian(xs, ys, x, idx, 3); + default: + fatal_error("Unsupported interpolation"); + } +} + + } // namespace openmc #endif \ No newline at end of file diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index f883975a3..a09854e84 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -75,31 +75,8 @@ void EnergyFunctionFilter::get_all_bins( const Particle& p, TallyEstimator estimator, FilterMatch& match) const { if (p.E_last() >= energy_.front() && p.E_last() <= energy_.back()) { - // Search for the incoming energy bin. - auto i = lower_bound_index(energy_.begin(), energy_.end(), p.E_last()); - double f, w; - switch (interpolation_) { - case Interpolation::lin_lin: - w = interpolate_lin_lin( - energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); - break; - case Interpolation::lin_log: - w = interpolate_lin_log( - energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); - break; - case Interpolation::log_lin: - w = interpolate_log_lin( - energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); - break; - case Interpolation::log_log: - w = interpolate_log_log( - energy_[i], energy_[i + 1], y_[i], y_[i + 1], p.E_last()); - break; - default: - fatal_error(fmt::format( - "Invalid interpolation scheme found on EnergyFunctionFilter {}", id())); - } + double w = interpolate(energy_, y_, p.E_last(), interpolation_); // Interpolate on the lin-lin grid. match.bins_.push_back(0); From fd7683fe31db6791670c6d512a0739445d9397e6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Sep 2022 22:50:27 -0500 Subject: [PATCH 0937/2654] Correction to str literal 'linear-linear' --- openmc/filter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index 9815572a3..8b0c84c7e 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1992,8 +1992,9 @@ class EnergyFunctionFilter(Filter): 'log-log Tabulated1Ds are supported') out = cls(tab1d.x, tab1d.y) + # set interpolation type if tab1d.interpolation[0] == 2: - out.interpolation = 'linear-lienar' + out.interpolation = 'linear-linear' elif tab1d.interpolation[0] == 3: out.interpolation = 'linear-log' elif tab1d.interpolation[0] == 4: From e34f786c6f6c5cf3c236aa9d8cb15cf39876aaa8 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Wed, 7 Sep 2022 11:52:06 -0500 Subject: [PATCH 0938/2654] str->component in flow control Co-authored-by: Paul Romano --- openmc/material.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index de4940a47..67615d74c 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -438,7 +438,7 @@ class Material(IDManagerMixin): params['percent_type'] = percent_type ## check if nuclide - if not str.isalpha(): + if not component.isalpha(): self.add_nuclide(component, **params) else: # is element kwargs = params From 494e357a6422d929be050a08677a54c76808641d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 7 Sep 2022 18:55:03 +0100 Subject: [PATCH 0939/2654] Fixed the type of mat Co-authored-by: Paul Romano --- openmc/deplete/results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index ab2123220..15a65e98a 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -95,7 +95,7 @@ class Results(list): def get_atoms( self, - mat: Material, + mat: Union[Material, str], nuc: str, nuc_units: str = "atoms", time_units: str = "s" From c29fb407d5794089da62b7bf53049097fc74c725 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 16:20:42 -0500 Subject: [PATCH 0940/2654] Add global configuration via openmc.config --- openmc/__init__.py | 1 + openmc/config.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 openmc/config.py diff --git a/openmc/__init__.py b/openmc/__init__.py index abcac899f..214695e67 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -32,6 +32,7 @@ from openmc.search import * from openmc.polynomial import * from openmc.tracks import * from . import examples +from .config import * # Import a few names from the model module from openmc.model import rectangular_prism, hexagonal_prism, Model diff --git a/openmc/config.py b/openmc/config.py new file mode 100644 index 000000000..a883c74cc --- /dev/null +++ b/openmc/config.py @@ -0,0 +1,54 @@ +from collections.abc import MutableMapping +import os +from pathlib import Path + +from openmc.data import DataLibrary + + +class _Config(MutableMapping): + def __init__(self, data=()): + self._mapping = {} + self.update(data) + + def __getitem__(self, key): + return self._mapping[key] + + def __delitem__(self, key): + del self._mapping[key] + + def __setitem__(self, key, value): + if key == 'cross_sections': + # Force environment variable to match + self._mapping[key] = Path(value) + os.environ['OPENMC_CROSS_SECTIONS'] = str(value) + elif key == 'chain_file': + self._mapping[key] = Path(value) + else: + raise KeyError(f'Unrecognized config key: {key}') + + def __iter__(self): + return iter(self._mapping) + + def __len__(self): + return len(self._mapping) + + def __repr__(self): + return repr(self._mapping) + + +# Create default configuration +config = _Config() + +# Set cross sections using environment variable +config['cross_sections'] = os.environ.get("OPENMC_CROSS_SECTIONS") + +# Check for depletion chain in cross_sections.xml +# Set depletion chain +chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") +if chain_file is None and config['cross_sections'] is not None: + data = DataLibrary.from_xml(config['cross_sections']) + for lib in reversed(data.libraries): + if lib['type'] == 'depletion_chain': + chain_file = lib['path'] + break +config['chain_file'] = chain_file From a074e0a5cf985ce3a2763133aaa04e73c38d482b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 22:13:54 -0500 Subject: [PATCH 0941/2654] Use openmc.config['cross_sections'] instead of OPENMC_CROSS_SECTIONS --- openmc/data/library.py | 17 ++++++++------- openmc/deplete/chain.py | 23 ++------------------- openmc/deplete/coupled_operator.py | 15 +++++--------- openmc/deplete/openmc_operator.py | 16 +++++++++++---- openmc/deplete/results.py | 4 ++-- openmc/element.py | 33 +++++++++++++++--------------- openmc/material.py | 10 ++++----- openmc/mgxs_library.py | 2 +- 8 files changed, 51 insertions(+), 69 deletions(-) diff --git a/openmc/data/library.py b/openmc/data/library.py index bf937e57a..ad6c65fb6 100644 --- a/openmc/data/library.py +++ b/openmc/data/library.py @@ -4,6 +4,7 @@ import pathlib import h5py +import openmc from openmc.mixin import EqualityMixin from openmc._xml import clean_indentation, reorder_attributes @@ -124,8 +125,8 @@ class DataLibrary(EqualityMixin): Parameters ---------- path : str, optional - Path to XML file to read. If not provided, the - :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used. + Path to XML file to read. If not provided, + openmc.config['cross_sections'] will be used. Returns ------- @@ -136,15 +137,14 @@ class DataLibrary(EqualityMixin): data = cls() - # If path is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable + # If path is None, get the cross sections from the global configuration if path is None: - path = os.environ.get('OPENMC_CROSS_SECTIONS') + path = openmc.config.get('cross_sections') - # Check to make sure there was an environmental variable. + # Check to make sure we picked up cross sections if path is None: - raise ValueError("Either path or OPENMC_CROSS_SECTIONS " - "environmental variable must be set") + raise ValueError("Either path or openmc.config['cross_sections'] " + "must be set") tree = ET.parse(path) root = tree.getroot() @@ -162,7 +162,6 @@ class DataLibrary(EqualityMixin): data.libraries.append(library) # get depletion chain data - dep_node = root.find("depletion_chain") if dep_node is not None: filename = os.path.join(directory, dep_node.attrib['path']) diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index d63bc6bfb..217c9cac0 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -239,24 +239,6 @@ def replace_missing_fpy(actinide, fpy_data, decay_data): return 'U235' -def _find_chain_file(cross_sections=None): - # First check deprecated OPENMC_DEPLETE_CHAIN environment variable - chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") - if chain_file is not None: - warn("Use of OPENMC_DEPLETE_CHAIN is deprecated in favor of adding " - "depletion_chain to OPENMC_CROSS_SECTIONS", FutureWarning) - return chain_file - - # Check for depletion chain in cross_sections.xml - data = DataLibrary.from_xml(cross_sections) - for lib in reversed(data.libraries): - if lib['type'] == 'depletion_chain': - return lib['path'] - - raise DataError("No depletion chain specified and could not find depletion " - f"chain in {cross_sections}") - - class Chain: """Full representation of a depletion chain. @@ -265,9 +247,8 @@ class Chain: yield sublibrary files. The depletion chain used during a depletion simulation is indicated by either an argument to :class:`openmc.deplete.CoupledOperator` or - :class:`openmc.deplete.IndependentOperator`, or through the - ``depletion_chain`` item in the :envvar:`OPENMC_CROSS_SECTIONS` - environment variable. + :class:`openmc.deplete.IndependentOperator`, or through + openmc.config['chain_file']. Attributes ---------- diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index dd14f282f..4a7c5c56f 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -9,7 +9,6 @@ filesystem. """ import copy -import os from warnings import warn import numpy as np @@ -22,7 +21,6 @@ from openmc.exceptions import DataError import openmc.lib from openmc.mpi import comm from .abc import OperatorResult -from .chain import _find_chain_file from .openmc_operator import OpenMCOperator, _distribute from .results import Results from .helpers import ( @@ -48,11 +46,11 @@ def _find_cross_sections(model): return model.materials.cross_sections # otherwise fallback to environment variable - cross_sections = os.environ.get("OPENMC_CROSS_SECTIONS") + cross_sections = openmc.config.get("cross_sections") if cross_sections is None: raise DataError( "Cross sections were not specified in Model.materials and " - "the OPENMC_CROSS_SECTIONS environment variable is not set." + "openmc.config['cross_sections'] is not set." ) return cross_sections @@ -103,9 +101,8 @@ class CoupledOperator(OpenMCOperator): model : openmc.model.Model OpenMC model object chain_file : str, optional - Path to the depletion chain XML file. Defaults to the file - listed under ``depletion_chain`` in - :envvar:`OPENMC_CROSS_SECTIONS` environment variable. + Path to the depletion chain XML file. Defaults to + ``openmc.config['chain_file']``. prev_results : Results, optional Results from a previous depletion calculation. If this argument is specified, the depletion calculation will start from the latest state @@ -231,10 +228,8 @@ class CoupledOperator(OpenMCOperator): " model with which to generate the transport Operator." raise TypeError(msg) - # Determine cross sections / depletion chain + # Determine cross sections cross_sections = _find_cross_sections(model) - if chain_file is None: - chain_file = _find_chain_file(cross_sections) check_value('fission yield mode', fission_yield_mode, self._fission_helpers.keys()) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index ee569bf71..91dc49b54 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -11,6 +11,7 @@ from collections import OrderedDict import numpy as np import openmc +from openmc.exceptions import DataError from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber @@ -57,9 +58,8 @@ class OpenMCOperator(TransportOperator): Path to continuous energy cross section library, or object containing one-group cross-sections. chain_file : str, optional - Path to the depletion chain XML file. Defaults to the file - listed under ``depletion_chain`` in - :envvar:`OPENMC_CROSS_SECTIONS` environment variable. + Path to the depletion chain XML file. Defaults to + openmc.config['chain_file']. prev_results : Results, optional Results from a previous depletion calculation. If this argument is specified, the depletion calculation will start from the latest state @@ -83,7 +83,6 @@ class OpenMCOperator(TransportOperator): if ``reduce_chain`` evaluates to true. The default value of ``None`` implies no limit on the depth. - Attributes ---------- materials : openmc.Materials @@ -133,6 +132,15 @@ class OpenMCOperator(TransportOperator): reduce_chain=False, reduce_chain_level=None): + # If chain file was not specified, try to get it from global config + if chain_file is None: + chain_file = openmc.config.get('chain_file') + if chain_file is None: + raise DataError( + "No depletion chain specified and could not find depletion " + "chain in openmc.config['chain_file']" + ) + super().__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False self.materials = materials diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 15a65e98a..b2c8e7733 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -392,7 +392,7 @@ class Results(list): as such cannot be used in subsequent transport calculations. If not provided, nuclides from the cross_sections element of materials.xml will be used. If that element is not present, - nuclides from OPENMC_CROSS_SECTIONS will be used. + nuclides from openmc.config['cross_sections'] will be used. Returns ------- @@ -412,7 +412,7 @@ class Results(list): # the new materials XML file. The precedence of nuclides to select # is first ones provided as a kwarg here, then ones specified # in the materials.xml file if provided, then finally from - # the environment variable OPENMC_CROSS_SECTIONS. + # openmc.config['cross_sections']. if nuc_with_data: cv.check_iterable_type('nuclide names', nuc_with_data, str) available_cross_sections = nuc_with_data diff --git a/openmc/element.py b/openmc/element.py index 1473bd63e..49aeaf464 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -1,9 +1,9 @@ from collections import OrderedDict -import os import re from xml.etree import ElementTree as ET import openmc.checkvalue as cv +import openmc from openmc.data import NATURAL_ABUNDANCE, atomic_mass, \ isotopes as natural_isotopes @@ -40,10 +40,10 @@ class Element(str): cross_sections=None): """Expand natural element into its naturally-occurring isotopes. - An optional cross_sections argument or the :envvar:`OPENMC_CROSS_SECTIONS` - environment variable is used to specify a cross_sections.xml file. - If the cross_sections.xml file is found, the element is expanded only - into the isotopes/nuclides present in cross_sections.xml. If no + An optional cross_sections argument or the ``cross_sections`` + configuration value is used to specify a cross_sections.xml file. If the + cross_sections.xml file is found, the element is expanded only into the + isotopes/nuclides present in cross_sections.xml. If no cross_sections.xml file is found, the element is expanded based on its naturally occurring isotopes. @@ -54,12 +54,13 @@ class Element(str): percent_type : {'ao', 'wo'} 'ao' for atom percent and 'wo' for weight percent enrichment : float, optional - Enrichment of an enrichment_target nuclide in percent (ao or wo). - If enrichment_target is not supplied then it is enrichment for U235 - in weight percent. For example, input 4.95 for 4.95 weight percent + Enrichment of an enrichment_target nuclide in percent (ao or wo). If + enrichment_target is not supplied then it is enrichment for U235 in + weight percent. For example, input 4.95 for 4.95 weight percent enriched U. Default is None (natural composition). enrichment_target: str, optional - Single nuclide name to enrich from a natural composition (e.g., 'O16') + Single nuclide name to enrich from a natural composition (e.g., + 'O16') .. versionadded:: 0.12 enrichment_type: {'ao', 'wo'}, optional @@ -82,8 +83,8 @@ class Element(str): ValueError No data is available for any of natural isotopes of the element ValueError - If only some natural isotopes are available in the cross-section data - library and the element is not O, W, or Ta + If only some natural isotopes are available in the cross-section + data library and the element is not O, W, or Ta ValueError If a non-naturally-occurring isotope is requested ValueError @@ -101,8 +102,8 @@ class Element(str): `ORNL/CSD/TM-244 `_ is used to calculate the weight fractions of U234, U235, U236, and U238. Namely, the weight fraction of U234 and U236 are taken to be 0.89% and 0.46%, - respectively, of the U235 weight fraction. The remainder of the - isotopic weight is assigned to U238. + respectively, of the U235 weight fraction. The remainder of the isotopic + weight is assigned to U238. When the `enrichment` argument is specified with `enrichment_target`, a general enrichment procedure is used for elements composed of exactly @@ -125,10 +126,10 @@ class Element(str): # Create dict to store the expanded nuclides and abundances abundances = OrderedDict() - # If cross_sections is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable + # If cross_sections is None, get the cross sections from the global + # configuration if cross_sections is None: - cross_sections = os.environ.get('OPENMC_CROSS_SECTIONS') + cross_sections = openmc.config.get('cross_sections') # If a cross_sections library is present, check natural nuclides # against the nuclides in the library diff --git a/openmc/material.py b/openmc/material.py index ece70df88..96a660b8b 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1310,9 +1310,8 @@ class Materials(cv.CheckedList): """Collection of Materials used for an OpenMC simulation. This class corresponds directly to the materials.xml input file. It can be - thought of as a normal Python list where each member is a - :class:`Material`. It behaves like a list as the following example - demonstrates: + thought of as a normal Python list where each member is a :class:`Material`. + It behaves like a list as the following example demonstrates: >>> fuel = openmc.Material() >>> clad = openmc.Material() @@ -1330,9 +1329,8 @@ class Materials(cv.CheckedList): ---------- cross_sections : str or path-like Indicates the path to an XML cross section listing file (usually named - cross_sections.xml). If it is not set, the - :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used for - continuous-energy calculations and + cross_sections.xml). If it is not set, openmc.config['cross_sections'] + will be used for continuous-energy calculations and :envvar:`OPENMC_MG_CROSS_SECTIONS` will be used for multi-group calculations to find the path to the HDF5 cross section file. diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index 67ad151cc..8d6e4bec9 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -2546,7 +2546,7 @@ class MGXSLibrary: """ # If filename is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable + # OPENMC_MG_CROSS_SECTIONS environment variable if filename is None: filename = os.environ.get('OPENMC_MG_CROSS_SECTIONS') From 225e40db0c5da659b2e040fa5fe455e569ee25aa Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 22:23:29 -0500 Subject: [PATCH 0942/2654] Add mg_cross_sections to openmc.config --- openmc/config.py | 11 +++++++++-- openmc/material.py | 9 +++++---- openmc/mgxs_library.py | 13 +++++-------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/openmc/config.py b/openmc/config.py index a883c74cc..65b7e0863 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -21,6 +21,9 @@ class _Config(MutableMapping): # Force environment variable to match self._mapping[key] = Path(value) os.environ['OPENMC_CROSS_SECTIONS'] = str(value) + elif key == 'mg_cross_sections': + self._mapping[key] = Path(value) + os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value) elif key == 'chain_file': self._mapping[key] = Path(value) else: @@ -40,7 +43,10 @@ class _Config(MutableMapping): config = _Config() # Set cross sections using environment variable -config['cross_sections'] = os.environ.get("OPENMC_CROSS_SECTIONS") +if "OPENMC_CROSS_SECTIONS" in os.environ: + config['cross_sections'] = os.environ["OPENMC_CROSS_SECTIONS"] +if "OPENMC_MG_CROSS_SECTIONS" in os.environ: + config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] # Check for depletion chain in cross_sections.xml # Set depletion chain @@ -51,4 +57,5 @@ if chain_file is None and config['cross_sections'] is not None: if lib['type'] == 'depletion_chain': chain_file = lib['path'] break -config['chain_file'] = chain_file +if chain_file is not None: + config['chain_file'] = chain_file diff --git a/openmc/material.py b/openmc/material.py index 96a660b8b..1b2b46a73 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1329,10 +1329,11 @@ class Materials(cv.CheckedList): ---------- cross_sections : str or path-like Indicates the path to an XML cross section listing file (usually named - cross_sections.xml). If it is not set, openmc.config['cross_sections'] - will be used for continuous-energy calculations and - :envvar:`OPENMC_MG_CROSS_SECTIONS` will be used for multi-group - calculations to find the path to the HDF5 cross section file. + cross_sections.xml). If it is not set, the + :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used for + continuous-energy calculations and :envvar:`OPENMC_MG_CROSS_SECTIONS` + will be used for multi-group calculations to find the path to the HDF5 + cross section file. """ diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index 8d6e4bec9..98a99196e 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -1,6 +1,5 @@ import copy from numbers import Real, Integral -import os import h5py import numpy as np @@ -2536,8 +2535,7 @@ class MGXSLibrary: ---------- filename : str, optional Name of HDF5 file containing MGXS data. Default is None. - If not provided, the value of the OPENMC_MG_CROSS_SECTIONS - environmental variable will be used + If not provided, openmc.config['mg_cross_sections'] will be used. Returns ------- @@ -2545,15 +2543,14 @@ class MGXSLibrary: Multi-group cross section data object. """ - # If filename is None, get the cross sections from the - # OPENMC_MG_CROSS_SECTIONS environment variable + # If filename is None, get the cross sections from openmc.config if filename is None: - filename = os.environ.get('OPENMC_MG_CROSS_SECTIONS') + filename = openmc.config.get('mg_cross_sections') # Check to make sure there was an environmental variable. if filename is None: - raise ValueError("Either path or OPENMC_MG_CROSS_SECTIONS " - "environmental variable must be set") + raise ValueError("Either path or openmc.config['mg_cross_sections']" + "must be set") check_type('filename', filename, str) file = h5py.File(filename, 'r') From fb1e92b614adfbafd0567a6bafc3e1adbb4f7990 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 1 Sep 2022 09:37:05 -0500 Subject: [PATCH 0943/2654] Cleanup config namespace --- openmc/config.py | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/openmc/config.py b/openmc/config.py index 65b7e0863..23a355467 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -4,6 +4,8 @@ from pathlib import Path from openmc.data import DataLibrary +__all__ = ["config"] + class _Config(MutableMapping): def __init__(self, data=()): @@ -39,23 +41,29 @@ class _Config(MutableMapping): return repr(self._mapping) -# Create default configuration -config = _Config() +def _default_config(): + """Return default configuration""" + config = _Config() -# Set cross sections using environment variable -if "OPENMC_CROSS_SECTIONS" in os.environ: - config['cross_sections'] = os.environ["OPENMC_CROSS_SECTIONS"] -if "OPENMC_MG_CROSS_SECTIONS" in os.environ: - config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] + # Set cross sections using environment variable + if "OPENMC_CROSS_SECTIONS" in os.environ: + config['cross_sections'] = os.environ["OPENMC_CROSS_SECTIONS"] + if "OPENMC_MG_CROSS_SECTIONS" in os.environ: + config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] -# Check for depletion chain in cross_sections.xml -# Set depletion chain -chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") -if chain_file is None and config['cross_sections'] is not None: - data = DataLibrary.from_xml(config['cross_sections']) - for lib in reversed(data.libraries): - if lib['type'] == 'depletion_chain': - chain_file = lib['path'] - break -if chain_file is not None: - config['chain_file'] = chain_file + # Check for depletion chain in cross_sections.xml + # Set depletion chain + chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") + if chain_file is None and config['cross_sections'] is not None: + data = DataLibrary.from_xml(config['cross_sections']) + for lib in reversed(data.libraries): + if lib['type'] == 'depletion_chain': + chain_file = lib['path'] + break + if chain_file is not None: + config['chain_file'] = chain_file + + return config + + +config = _default_config() From c5012996df45eb1130ee8e7f03f4e1bede4ec1af Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 6 Sep 2022 16:00:51 -0500 Subject: [PATCH 0944/2654] Handle missing files in openmc.config --- openmc/config.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/openmc/config.py b/openmc/config.py index 23a355467..08b8c3cb6 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -1,6 +1,7 @@ from collections.abc import MutableMapping import os from pathlib import Path +import warnings from openmc.data import DataLibrary @@ -17,17 +18,21 @@ class _Config(MutableMapping): def __delitem__(self, key): del self._mapping[key] + if key == 'cross_sections': + del os.environ['OPENMC_CROSS_SECTIONS'] + elif key == 'mg_cross_sections': + del os.environ['OPENMC_MG_CROSS_SECTIONS'] def __setitem__(self, key, value): if key == 'cross_sections': # Force environment variable to match - self._mapping[key] = Path(value) + self._set_path(key, value) os.environ['OPENMC_CROSS_SECTIONS'] = str(value) elif key == 'mg_cross_sections': - self._mapping[key] = Path(value) + self._set_path(key, value) os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value) elif key == 'chain_file': - self._mapping[key] = Path(value) + self._set_path(key, value) else: raise KeyError(f'Unrecognized config key: {key}') @@ -40,6 +45,11 @@ class _Config(MutableMapping): def __repr__(self): return repr(self._mapping) + def _set_path(self, key, value): + self._mapping[key] = p = Path(value) + if not p.exists(): + warnings.warn(f"'{value}' does not exist.") + def _default_config(): """Return default configuration""" @@ -51,10 +61,13 @@ def _default_config(): if "OPENMC_MG_CROSS_SECTIONS" in os.environ: config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] - # Check for depletion chain in cross_sections.xml # Set depletion chain chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") - if chain_file is None and config['cross_sections'] is not None: + if (chain_file is None and + config['cross_sections'] is not None and + config['cross_sections'].exists() + ): + # Check for depletion chain in cross_sections.xml data = DataLibrary.from_xml(config['cross_sections']) for lib in reversed(data.libraries): if lib['type'] == 'depletion_chain': From 8f20c20af045267ee6729eeedd0b3c75243472f4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 6 Sep 2022 16:01:46 -0500 Subject: [PATCH 0945/2654] Move cross_sections.rst to data.rst and rename section header --- docs/source/usersguide/{cross_sections.rst => data.rst} | 8 ++++---- docs/source/usersguide/index.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename docs/source/usersguide/{cross_sections.rst => data.rst} (99%) diff --git a/docs/source/usersguide/cross_sections.rst b/docs/source/usersguide/data.rst similarity index 99% rename from docs/source/usersguide/cross_sections.rst rename to docs/source/usersguide/data.rst index 0cbb581bd..6a135df76 100644 --- a/docs/source/usersguide/cross_sections.rst +++ b/docs/source/usersguide/data.rst @@ -1,8 +1,8 @@ -.. _usersguide_cross_sections: +.. _usersguide_data: -=========================== -Cross Section Configuration -=========================== +================== +Data Configuration +================== In order to run a simulation with OpenMC, you will need cross section data for each nuclide or material in your problem. OpenMC can be run in continuous-energy diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst index fab353c77..511bdc6ce 100644 --- a/docs/source/usersguide/index.rst +++ b/docs/source/usersguide/index.rst @@ -13,7 +13,7 @@ essential aspects of using OpenMC to perform simulations. beginners install - cross_sections + data basics materials geometry From 683910aba4fb0ad106752e0ea94f79522be38b40 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Sep 2022 16:09:21 -0500 Subject: [PATCH 0946/2654] Discuss openmc.config in user's guide --- docs/source/usersguide/data.rst | 154 ++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 45 deletions(-) diff --git a/docs/source/usersguide/data.rst b/docs/source/usersguide/data.rst index 6a135df76..fccc93940 100644 --- a/docs/source/usersguide/data.rst +++ b/docs/source/usersguide/data.rst @@ -4,49 +4,93 @@ Data Configuration ================== -In order to run a simulation with OpenMC, you will need cross section data for -each nuclide or material in your problem. OpenMC can be run in continuous-energy -or multi-group mode. +OpenMC relies on a variety of physical data in order to carry out transport +simulations, depletion simulations, and other common tasks. As a user, you are +responsible for specifying one or more of the following: -In continuous-energy mode, OpenMC uses a native `HDF5 -`_ format (see :ref:`io_nuclear_data`) to -store all nuclear data. Pregenerated HDF5 libraries can be found at -https://openmc.org; unless you have specific data needs, it is highly -recommended to use one of the pregenerated libraries. Alternatively, if you have -ACE format data that was produced with NJOY_, such as that distributed with -MCNP_ or Serpent_, it can be converted to the HDF5 format using the :ref:`using -the Python API `. Several sources provide openly available -ACE data including the `ENDF/B`_, JEFF_, and TENDL_ libraries as well as the -`LANL Nuclear Data Team `_. In addition to -tabulated cross sections in the HDF5 files, OpenMC relies on :ref:`windowed -multipole ` data to perform on-the-fly Doppler broadening. +- **Cross sections (XML)** -- A :ref:`cross sections XML ` + file (commonly named ``cross_sections.xml``) contains a listing of other data + files, in particular neutron cross sections, photon cross sections, and + windowed multipole data. Each of those files, in turn, uses a `HDF5 + `_ format (see :ref:`io_nuclear_data`). In + order to run transport simulations with continuous-energy cross sections, you + need to specify this file. -In multi-group mode, OpenMC utilizes an HDF5-based library format which can be -used to describe nuclide- or material-specific quantities. +- **Depletion chain (XML)** -- A :ref:`depletion chain XML ` + file contains decay data, fission product yields, and information on what + neutron reactions can result in transmutation. This file is needed for + depletion/activation calculations as well as some basic functions in the + :mod:`openmc.data` module. + +- **Multigroup cross sections (HDF5)** -- OpenMC can also perform transport + simulations using multigroup data. In this case, multigroup cross sections are + stored in a single :ref:`HDF5 file `. Thus, in order to run a + multigroup transport simulation, this file needs to be specified. + +Each of the above files can specified in several ways. In the Python API, a +:ref:`runtime configuration variable ` +:data:`openmc.config` can be used to specify any of the above. Alternatively, +you can specify these files using a set of :ref:`environment variables +`. + +.. _usersguide_data_runtime: + +--------------------- +Runtime Configuration +--------------------- + +Data sources for OpenMC can be specified at runtime in Python using the +:data:`openmc.config` variable. This variable acts like a dictionary and stores +key-values pairs, where the values are file paths (strings or path-like objects) +and the key can be one of the following: + +``"cross_sections"`` + Indicates the path to the :ref:`cross sections XML ` file + that lists HDF5 format neutron cross sections, photon cross sections, and + windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` + attribute will override this, if specified. + +``"chain_file"`` + Indicates the path to the :ref:`depletion chain XML ` file + that contains decay data, fission product yields, and what neutron reactions + may result in transmutation of a target nuclide. + +``"mg_cross_sections"`` + Indicates the path to an :ref:`HDF5 file ` that contains + multigroup cross sections. Note that the + :attr:`openmc.Materials.cross_sections` attribute will override this if + specified. + +At the time the :mod:`openmc` Python module is imported, the +:data:`openmc.config` dictionary will be initialized using a set of +:ref:`environment variable `. + +.. _usersguide_data_envvar: --------------------- Environment Variables --------------------- -When :ref:`scripts_openmc` is run, it will look for several environment -variables that indicate where cross sections can be found. While the location of -cross sections can also be indicated through the -:attr:`openmc.Materials.cross_sections` attribute (or in the :ref:`materials.xml -` file), if you always use the same set of cross section data, it -is often easier to just set an environment variable that will be picked up by -default every time OpenMC is run. The following environment variables are used: +In addition to the :ref:`runtime configuration `, data +sources can be specified using a set of environment variables. The following +environment variables are recognized by OpenMC: :envvar:`OPENMC_CROSS_SECTIONS` - Indicates the path to the :ref:`cross_sections.xml ` - summary file that is used to locate HDF5 format cross section libraries if the - user has not specified :attr:`openmc.Materials.cross_sections` (equivalently, - the :ref:`cross_sections` in :ref:`materials.xml `). + Indicates the path to the :ref:`cross sections XML ` file + that lists HDF5 format neutron cross sections, photon cross sections, and + windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` + attribute will override this if specified. + +:envvar:`OPENMC_CHAIN_FILE` + Indicates the path to the :ref:`depletion chain XML ` file + that contains decay data, fission product yields, and what neutron reactions + may result in transmutation of a target nuclide. :envvar:`OPENMC_MG_CROSS_SECTIONS` Indicates the path to an :ref:`HDF5 file ` that contains - multi-group cross sections if the user has not specified - :attr:`openmc.Materials.cross_sections` (equivalently, the - :ref:`cross_sections` in :ref:`materials.xml `). + multigroup cross sections. Note that the + :attr:`openmc.Materials.cross_sections` attribute will override this if + specified. To set these environment variables persistently, export them from your shell profile (``.profile`` or ``.bashrc`` in bash_). @@ -61,12 +105,13 @@ Using Pregenerated Libraries ---------------------------- Various evaluated nuclear data libraries have been processed into the HDF5 -format required by OpenMC and can be found at https://openmc.org. You -can find both libraries generated by the OpenMC development team as well as -libraries based on ACE files distributed elsewhere. To use these libraries, -download the archive file, unpack it, and then set your -:envvar:`OPENMC_CROSS_SECTIONS` environment variable to the absolute path of -the ``cross_sections.xml`` file contained in the unpacked directory. +format required by OpenMC and can be found at https://openmc.org. Unless you +have specific data needs, it is highly recommended to use one of the +pregenerated libraries. You can find both libraries generated by the OpenMC +development team as well as libraries based on ACE files distributed elsewhere. +To use these libraries, download the archive file, unpack it, and then specify +the path of the ``cross_sections.xml`` file contained in the unpacked directory +as described in :ref:`usersguide_data_runtime`. .. _create_xs_library: @@ -75,6 +120,12 @@ Manually Creating a Library from ACE files .. currentmodule:: openmc.data +If you have ACE format data that was produced with NJOY_, such as that +distributed with MCNP_ or Serpent_, it can be converted to the HDF5 format using +the using the Python API. Several sources provide openly available ACE data +including the `ENDF/B`_, JEFF_, and TENDL_ libraries as well as the `LANL +Nuclear Data Team `_. + The :mod:`openmc.data` module in the Python API enables users to directly convert ACE data to OpenMC's HDF5 format and create a corresponding :ref:`cross_sections.xml ` file. For those who prefer to use @@ -224,6 +275,19 @@ relaxation sublibrary files are required: Once the HDF5 files have been generated, a library can be created using the :class:`DataLibrary` class as described in :ref:`create_xs_library`. +----------- +Chain Files +----------- + +Pregenerated depletion chain XML files can be found at https://openmc.org. +Additionally, depletion chains can be generated using the +:class:`openmc.deplete.Chain` class. In particular, the +:meth:`~openmc.deplete.Chain.from_endf` method allows a chain to be generated +starting from a set of ENDF incident neutron, decay, and fission product yield +sublibrary files. Once you've downloaded or generated a depletion chain XML +file, make sure to specify its path as described in +:ref:`usersguide_data_runtime`. + ----------------------- Windowed Multipole Data ----------------------- @@ -241,16 +305,16 @@ The `official ENDF/B-VII.1 HDF5 library multipole library, so if you are using this library, the windowed multipole data will already be available to you. --------------------------- -Multi-Group Cross Sections --------------------------- +------------------------- +Multigroup Cross Sections +------------------------- -Multi-group cross section libraries are generally tailored to the specific +Multigroup cross section libraries are generally tailored to the specific calculation to be performed. Therefore, at this point in time, OpenMC is not -distributed with any pre-existing multi-group cross section libraries. -However, if obtained or generated their own library, the user -should set the :envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable -to the absolute path of the file library expected to used most frequently. +distributed with any pre-existing multi-group cross section libraries. However, +if obtained or generated their own library, the user should set the +:envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable to the absolute path of +the file library expected to used most frequently. For an example of how to create a multi-group library, see the `example notebook <../examples/mg-mode-part-i.ipynb>`__. From ab6f9247cafc4689399f41bd9c07a71289c1b396 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Sep 2022 16:14:35 -0500 Subject: [PATCH 0947/2654] Remove specific section on environment variables --- docs/source/usersguide/data.rst | 64 ++++++++++----------------------- 1 file changed, 18 insertions(+), 46 deletions(-) diff --git a/docs/source/usersguide/data.rst b/docs/source/usersguide/data.rst index fccc93940..48003ecb7 100644 --- a/docs/source/usersguide/data.rst +++ b/docs/source/usersguide/data.rst @@ -29,9 +29,8 @@ responsible for specifying one or more of the following: Each of the above files can specified in several ways. In the Python API, a :ref:`runtime configuration variable ` -:data:`openmc.config` can be used to specify any of the above. Alternatively, -you can specify these files using a set of :ref:`environment variables -`. +:data:`openmc.config` can be used to specify any of the above and is initialized +using a set of environment variables. .. _usersguide_data_runtime: @@ -47,53 +46,28 @@ and the key can be one of the following: ``"cross_sections"`` Indicates the path to the :ref:`cross sections XML ` file that lists HDF5 format neutron cross sections, photon cross sections, and - windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` - attribute will override this, if specified. + windowed multipole data. At startup, this is initialized with the value of the + :envvar:`OPENMC_CROSS_SECTIONS` environment variable. Note that the + :attr:`openmc.Materials.cross_sections` attribute will override this, if + specified. ``"chain_file"`` Indicates the path to the :ref:`depletion chain XML ` file that contains decay data, fission product yields, and what neutron reactions - may result in transmutation of a target nuclide. + may result in transmutation of a target nuclide. At startup, this is + initialized with the value of the :envvar:`OPENMC_CHAIN_FILE` environment + variable. ``"mg_cross_sections"`` Indicates the path to an :ref:`HDF5 file ` that contains - multigroup cross sections. Note that the + multigroup cross sections. At startup, this is initialized with the value of + the :envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable. Note that the :attr:`openmc.Materials.cross_sections` attribute will override this if specified. -At the time the :mod:`openmc` Python module is imported, the -:data:`openmc.config` dictionary will be initialized using a set of -:ref:`environment variable `. - -.. _usersguide_data_envvar: - ---------------------- -Environment Variables ---------------------- - -In addition to the :ref:`runtime configuration `, data -sources can be specified using a set of environment variables. The following -environment variables are recognized by OpenMC: - -:envvar:`OPENMC_CROSS_SECTIONS` - Indicates the path to the :ref:`cross sections XML ` file - that lists HDF5 format neutron cross sections, photon cross sections, and - windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` - attribute will override this if specified. - -:envvar:`OPENMC_CHAIN_FILE` - Indicates the path to the :ref:`depletion chain XML ` file - that contains decay data, fission product yields, and what neutron reactions - may result in transmutation of a target nuclide. - -:envvar:`OPENMC_MG_CROSS_SECTIONS` - Indicates the path to an :ref:`HDF5 file ` that contains - multigroup cross sections. Note that the - :attr:`openmc.Materials.cross_sections` attribute will override this if - specified. - -To set these environment variables persistently, export them from your shell -profile (``.profile`` or ``.bashrc`` in bash_). +If you want to persistently set the environment variables used to initialized +the configuration, export them from your shell profile (``.profile`` or +``.bashrc`` in bash_). .. _bash: http://www.linuxfromscratch.org/blfs/view/6.3/postlfs/profile.html @@ -311,12 +285,10 @@ Multigroup Cross Sections Multigroup cross section libraries are generally tailored to the specific calculation to be performed. Therefore, at this point in time, OpenMC is not -distributed with any pre-existing multi-group cross section libraries. However, -if obtained or generated their own library, the user should set the -:envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable to the absolute path of -the file library expected to used most frequently. - -For an example of how to create a multi-group library, see the `example notebook +distributed with any pre-existing multigroup cross section libraries. However, +if a multigroup library file is downloaded or generated, the path to the file +needs to be specified as described in :ref:`usersguide_data_runtime`. For an +example of how to create a multigroup library, see the `example notebook <../examples/mg-mode-part-i.ipynb>`__. .. _NJOY: http://www.njoy21.io/ From 35930e0422426ee972b8ddfc6a9147288afb7d37 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Sep 2022 16:36:33 -0500 Subject: [PATCH 0948/2654] Add tests for openmc.config --- openmc/config.py | 3 ++- tests/unit_tests/test_config.py | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/test_config.py diff --git a/openmc/config.py b/openmc/config.py index 08b8c3cb6..fe7c5aa06 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -33,6 +33,7 @@ class _Config(MutableMapping): os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value) elif key == 'chain_file': self._set_path(key, value) + os.environ['OPENMC_CHAIN_FILE'] = str(value) else: raise KeyError(f'Unrecognized config key: {key}') @@ -62,7 +63,7 @@ def _default_config(): config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] # Set depletion chain - chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") + chain_file = os.environ.get("OPENMC_CHAIN_FILE") if (chain_file is None and config['cross_sections'] is not None and config['cross_sections'].exists() diff --git a/tests/unit_tests/test_config.py b/tests/unit_tests/test_config.py new file mode 100644 index 000000000..1d3c0f173 --- /dev/null +++ b/tests/unit_tests/test_config.py @@ -0,0 +1,43 @@ +from collections.abc import Mapping +import os + +import openmc +import pytest + + +@pytest.fixture(autouse=True, scope='module') +def reset_config(): + config = dict(openmc.config) + try: + yield + finally: + openmc.config.clear() + openmc.config.update(config) + + +def test_config_basics(): + assert isinstance(openmc.config, Mapping) + for key, value in openmc.config.items(): + assert isinstance(key, str) + assert isinstance(value, os.PathLike) + + # Set and delete + openmc.config['cross_sections'] = '/path/to/cross_sections.xml' + del openmc.config['cross_sections'] + assert 'cross_sections' not in openmc.config + assert 'OPENMC_CROSS_SECTIONS' not in os.environ + + # Can't use any key + with pytest.raises(KeyError): + openmc.config['🐖'] = '/like/to/eat/bacon' + + +def test_config_set_envvar(): + openmc.config['cross_sections'] = '/path/to/cross_sections.xml' + assert os.environ['OPENMC_CROSS_SECTIONS'] == '/path/to/cross_sections.xml' + + openmc.config['mg_cross_sections'] = '/path/to/mg_cross_sections.h5' + assert os.environ['OPENMC_MG_CROSS_SECTIONS'] == '/path/to/mg_cross_sections.h5' + + openmc.config['chain_file'] = '/path/to/chain_file.xml' + assert os.environ['OPENMC_CHAIN_FILE'] == '/path/to/chain_file.xml' From 2afefba206769cee22acab1abfd860030c8834f5 Mon Sep 17 00:00:00 2001 From: josh Date: Thu, 8 Sep 2022 00:04:05 +0000 Subject: [PATCH 0949/2654] deepcopy method for FissionYield class --- openmc/deplete/nuclide.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py index 7b6ddd788..962e3e6d6 100644 --- a/openmc/deplete/nuclide.py +++ b/openmc/deplete/nuclide.py @@ -13,7 +13,7 @@ try: except ImportError: import xml.etree.ElementTree as ET -from numpy import empty, searchsorted +import numpy as np from openmc.checkvalue import check_type @@ -470,7 +470,7 @@ class FissionYieldDistribution(Mapping): shared_prod = set.union(*(set(x) for x in fission_yields.values())) ordered_prod = sorted(shared_prod) - yield_matrix = empty((len(energies), len(shared_prod))) + yield_matrix = np.empty((len(energies), len(shared_prod))) for g_index, energy in enumerate(energies): prod_map = fission_yields[energy] @@ -560,7 +560,7 @@ class FissionYieldDistribution(Mapping): return None products = sorted(overlap) - indices = searchsorted(self.products, products) + indices = np.searchsorted(self.products, products) # coerce back to dictionary to pass back to __init__ new_yields = {} @@ -681,6 +681,11 @@ class FissionYield(Mapping): return "<{} containing {} products and yields>".format( self.__class__.__name__, len(self)) + def __deepcopy__(self, memo): + result = FissionYield(self.products, np.copy(self.yields)) + memo[id(self)] = result + return result + # Avoid greedy numpy operations like np.float64 * fission_yield # converting this to an array on the fly. Force __rmul__ and # __radd__. See issue #1492 From 3c7483becbadeb5fc4323137ea30500f66f9e8c0 Mon Sep 17 00:00:00 2001 From: josh Date: Thu, 8 Sep 2022 02:08:18 +0000 Subject: [PATCH 0950/2654] Add a simple unittest for the FissionYield deepcopy --- tests/unit_tests/test_deplete_nuclide.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_deplete_nuclide.py b/tests/unit_tests/test_deplete_nuclide.py index 705beb32a..e73af6955 100644 --- a/tests/unit_tests/test_deplete_nuclide.py +++ b/tests/unit_tests/test_deplete_nuclide.py @@ -1,7 +1,7 @@ """Tests for the openmc.deplete.Nuclide class.""" import xml.etree.ElementTree as ET - +import copy import numpy as np import pytest from openmc.deplete import nuclide @@ -335,3 +335,14 @@ def test_validate(): assert "decay mode" in record[0].message.args[0] assert "0 reaction" in record[1].message.args[0] assert "1.0" in record[2].message.args[0] + + +def test_deepcopy(): + """Test deepcopying a FissionYield object""" + nuc = nuclide.FissionYield(products=("I129", "Sm149", "Xe135"), yields=np.array((0.001, 0.0003, 0.002))) + copied_nuc = copy.deepcopy(nuc) + # Check the deepcopy equals the original + assert copied_nuc == nuc + # Mutate the original and verify the copy remains intact + nuc *= 2 + assert copied_nuc != nuc \ No newline at end of file From fbce363784e2b9d4b95c246317bccc2230f18703 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 7 Sep 2022 23:05:15 -0500 Subject: [PATCH 0951/2654] Using a separate dictionary for interpolation values --- include/openmc/interpolate.h | 3 +++ openmc/data/function.py | 2 +- openmc/filter.py | 10 +++++++--- tests/regression_tests/filter_energyfun/test.py | 2 -- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index 2764b7ffc..d02d87ff2 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -61,6 +61,9 @@ inline double interpolate(const std::vector& xs, { int idx = lower_bound_index(xs.begin(), xs.end(), x); + if (idx == xs.size()) + idx--; + switch (i) { case Interpolation::lin_lin: return interpolate_lin_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); diff --git a/openmc/data/function.py b/openmc/data/function.py index 59f549d6f..b0390d19c 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -13,7 +13,7 @@ from openmc.mixin import EqualityMixin from .data import EV_PER_MEV INTERPOLATION_SCHEME = {1: 'histogram', 2: 'linear-linear', 3: 'linear-log', - 4: 'log-linear', 5: 'log-log', 6 : 'quadratic', 7 : 'cubic'} + 4: 'log-linear', 5: 'log-log'} def sum_functions(funcs): diff --git a/openmc/filter.py b/openmc/filter.py index 8b0c84c7e..c1ce573c9 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -12,7 +12,6 @@ import pandas as pd import openmc import openmc.checkvalue as cv from .cell import Cell -from .data.function import INTERPOLATION_SCHEME from .material import Material from .mixin import IDManagerMixin from .surface import Surface @@ -1896,6 +1895,11 @@ class EnergyFunctionFilter(Filter): """ + # keys selected to match those in function.py where possible + INTERPOLATION_SCHEMES = {2: 'linear-linear', 3: 'linear-log', + 4: 'log-linear', 5: 'log-log', + 6 : 'quadratic', 7 : 'cubic'} + def __init__(self, energy, y, interpolation='linear-linear', filter_id=None): self.energy = energy self.y = y @@ -1963,7 +1967,7 @@ class EnergyFunctionFilter(Filter): out = cls(energy, y, filter_id=filter_id) if 'interpolation' in group: out.interpolation = \ - openmc.data.INTERPOLATION_SCHEME[group['interpolation'][()]] + cls.INTERPOLATION_SCHEMES[group['interpolation'][()]] return out @@ -2053,7 +2057,7 @@ class EnergyFunctionFilter(Filter): @interpolation.setter def interpolation(self, val): cv.check_type('interpolation', val, str) - cv.check_value('interpolation', val, INTERPOLATION_SCHEME.values()) + cv.check_value('interpolation', val, self.INTERPOLATION_SCHEMES.values()) self._interpolation = val def to_xml_element(self): diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index c297c094a..9c2be7be3 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -73,9 +73,7 @@ class FilterEnergyFunHarness(PyAPITestHarness): br_tally = sp.tallies[2] / sp.tallies[1] dataframes_string += br_tally.get_pandas_dataframe().to_string() + '\n' - for t_id in (3, 4, 5): - # Write out the log-log interpolation as well ef_tally = sp.tallies[t_id] dataframes_string += ef_tally.get_pandas_dataframe().to_string() + '\n' From a7abe84b380450bc5e40e9199c026292a5b9de3b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 09:35:03 -0500 Subject: [PATCH 0952/2654] Fix openmc.config when OPENMC_CROSS_SECTIONS is not set --- openmc/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/config.py b/openmc/config.py index fe7c5aa06..628df7edc 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -65,7 +65,7 @@ def _default_config(): # Set depletion chain chain_file = os.environ.get("OPENMC_CHAIN_FILE") if (chain_file is None and - config['cross_sections'] is not None and + config.get('cross_sections') is not None and config['cross_sections'].exists() ): # Check for depletion chain in cross_sections.xml From a95f4cc0d73bbb4b4c025d92caa66d9e5fddd632 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 10:50:09 -0500 Subject: [PATCH 0953/2654] Remove use of _find_chain_file in test_deplete_operator.py --- tests/unit_tests/test_deplete_operator.py | 31 +++-------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/tests/unit_tests/test_deplete_operator.py b/tests/unit_tests/test_deplete_operator.py index 5fe8715ac..6ea89fc4a 100644 --- a/tests/unit_tests/test_deplete_operator.py +++ b/tests/unit_tests/test_deplete_operator.py @@ -1,37 +1,15 @@ """Basic unit tests for openmc.deplete.Operator instantiation -Modifies and resets environment variable OPENMC_CROSS_SECTIONS -to a custom file with new depletion_chain node """ from pathlib import Path -import pytest from openmc.deplete.abc import TransportOperator -from openmc.deplete.chain import Chain, _find_chain_file +from openmc.deplete.chain import Chain -BARE_XS_FILE = "bare_cross_sections.xml" CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" -@pytest.fixture() -def bare_xs(run_in_tmpdir): - """Create a very basic cross_sections file, return simple Chain. - - """ - - bare_xs_contents = """ - - - -""".format(CHAIN_PATH) - - with open(BARE_XS_FILE, "w") as out: - out.write(bare_xs_contents) - - yield BARE_XS_FILE - - class BareDepleteOperator(TransportOperator): """Very basic class for testing the initialization.""" @@ -52,10 +30,10 @@ class BareDepleteOperator(TransportOperator): pass -def test_operator_init(bare_xs): +def test_operator_init(): """The test uses a temporary dummy chain. This file will be removed at the end of the test, and only contains a depletion_chain node.""" - bare_op = BareDepleteOperator(_find_chain_file(bare_xs)) + bare_op = BareDepleteOperator(CHAIN_PATH) act_chain = bare_op.chain ref_chain = Chain.from_xml(CHAIN_PATH) assert len(act_chain) == len(ref_chain) @@ -73,8 +51,7 @@ def test_operator_init(bare_xs): def test_operator_fiss_q(): """Make sure fission q values can be set""" new_q = {"U235": 2.0E8, "U238": 2.0E8, "U234": 5.0E7} - chain_file = Path(__file__).parents[1] / "chain_simple.xml" - operator = BareDepleteOperator(chain_file=chain_file, fission_q=new_q) + operator = BareDepleteOperator(chain_file=CHAIN_PATH, fission_q=new_q) mod_chain = operator.chain for name, q in new_q.items(): chain_nuc = mod_chain[name] From 9127ff4f5ecacd46692784f1a75e490490d1b3f2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 11:24:08 -0500 Subject: [PATCH 0954/2654] [WIP] started region refactor --- include/openmc/cell.h | 40 ++++++++++++++++++++++++++++++++++++++-- src/cell.cpp | 7 +++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 817196727..fcce520fe 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -52,8 +52,41 @@ extern vector> cells; } // namespace model //============================================================================== + +// TODO: Maybe not, just move this inline to Region::bounding_box() for complex +// case +class RegionPostfix { +public: + BoundingBox bounding_box() const; +}; + +class Region { +public: + Region() {} + explicit Region(std::string region_expression); + + void add_precedence(); + std::string str() const; + BoundingBox bounding_box() const; + bool contains(Position r, Direction u, int32_t on_surface) const; + + RegionPostfix to_postfix() const; + +private: + void add_parentheses(); + void apply_demorgan( + vector::iterator start, vector::iterator stop); + + //! Definition of spatial region as Boolean expression of half-spaces + // TODO: Should this be a vector of some other type + vector tokens_; + bool simple_; //!< Does the region contain only intersections? +}; + //============================================================================== +// TODO: Think about what data members really need to live in this class versus +// putting them in the Region class class Cell { public: //---------------------------------------------------------------------------- @@ -198,9 +231,9 @@ public: //! T. The units are sqrt(eV). vector sqrtkT_; + // TODO: Probably move this guy to CSGCell //! Definition of spatial region as Boolean expression of half-spaces - vector region_; - bool simple_; //!< Does the region contain only intersections? + Region region_; //! \brief Neighboring cells in the same universe. NeighborList neighbors_; @@ -263,6 +296,9 @@ protected: //! \param rpn The rpn being searched static vector::iterator find_left_parenthesis( vector::iterator start, const vector& rpn); + +private: + Region region_; }; //============================================================================== diff --git a/src/cell.cpp b/src/cell.cpp index 4ff35498c..4eb0fa0b9 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -43,6 +43,7 @@ vector> cells; //! operators. //============================================================================== +// TODO: Move this to be Region::Region(...) vector tokenize(const std::string region_spec) { // Check for an empty region_spec first. @@ -183,7 +184,8 @@ void add_precedence(std::vector& infix) // Set the current operator if is hasn't been set current_op = token; } else if (token != current_op) { - // If the current operator doesn't match the token, add parenthesis to assert precedence + // If the current operator doesn't match the token, add parenthesis to + // assert precedence it = add_parentheses(it, infix); current_op = 0; } @@ -586,7 +588,7 @@ CSGCell::CSGCell(pugi::xml_node cell_node) // Get a tokenized representation of the region specification and apply De // Morgans law - region_ = tokenize(region_spec); + region_ = Region(region_spec); remove_complement_ops(region_); // Convert user IDs to surface indices. @@ -696,6 +698,7 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const write_string(group_id, "geom_type", "csg", false); + // TODO: Move to Region::str() // Write the region specification. if (!region_.empty()) { std::stringstream region_spec {}; From 37cfd2049886215aefef90498b4baa044768ec7a Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 8 Sep 2022 11:42:37 -0500 Subject: [PATCH 0955/2654] add paragraph on using env variable w from_model --- docs/source/usersguide/depletion.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index be9406182..46403ff91 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -294,6 +294,14 @@ or from data arrays:: sure your cross sections are in the correct units before passing to a :class:`~openmc.deplete.IndependentOperator` object. +If you are runnnig :meth:`~openmc.deplete.MicroXS.from_model()` on a cluster +that does not share local filesystems across nodes, you'll need to set an +environment variable so that each MPI process knows where to store output files +used to calculate the microscopic cross sections. In order of priority, they +are `TMPDIR`. `TEMP`, and `TMP`. Users interested in further details can read +the `relevant docpage on the tempfile pacakge `_ + + Caveats ------- From a414f5a32ad82272c449d0157f6aeee72a95ce4b Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Thu, 8 Sep 2022 12:49:54 -0500 Subject: [PATCH 0956/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- docs/source/usersguide/depletion.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index b0d8ff454..245070237 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -296,12 +296,12 @@ units of barns:: model.materials[0], chain_file) -If you are runnnig :meth:`~openmc.deplete.MicroXS.from_model()` on a cluster -that does not share local filesystems across nodes, you'll need to set an +If you are running :meth:`~openmc.deplete.MicroXS.from_model()` on a cluster +where temporary files are created on a local filesystem that is not shared across nodes, you'll need to set an environment variable so that each MPI process knows where to store output files used to calculate the microscopic cross sections. In order of priority, they -are `TMPDIR`. `TEMP`, and `TMP`. Users interested in further details can read -the `relevant docpage on the tempfile pacakge `_ +are :envvar:`TMPDIR`. :envvar:`TEMP`, and :envvar:`TMP`. Users interested in further details can read +the documentation for the `tempfile `_ module. Caveats From 8cdce03828b160f53b6604d21dc0d20cc2836e24 Mon Sep 17 00:00:00 2001 From: yardasol Date: Thu, 8 Sep 2022 12:52:14 -0500 Subject: [PATCH 0957/2654] cleanup awkward sentences --- docs/source/usersguide/depletion.rst | 96 ++++++++++++++-------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 46403ff91..b0d8ff454 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -203,21 +203,25 @@ Transport-independent depletion verified. API changes and feature additions are possible and likely in the near future. -This category of operator uses pre-calculated one-group microscopic cross -sections to obtain transmutation reaction rates. OpenMC provides the -:class:`~openmc.deplete.IndependentOperator` for this method of calculation. -While the one-group microscopic cross sections can be calculated using a -transport solver, :class:`~openmc.deplete.IndependentOperator` is not directly -coupled to any transport solver. The -:class:`~openmc.deplete.IndependentOperator` class requires a -:class:`openmc.Materials` object, a :class:`~openmc.deplete.MicroXS` object, -and a path to a depletion chain file:: +This category of operator uses one-group microscopic cross sections to obtain +transmutation reaction rates. The cross sections are pre-calculated, so there is +no need for direct coupling between a transport-independent operator and a +transport solver. The :mod:`openmc.deplete` module offers a single +transport-independent operator, :class:`~openmc.deplete.IndependentOperator`, +and only one operator is needed since, in theory, any transport code could +calcuate the one-group microscopic cross sections. + +The :class:`~openmc.deplete.IndependentOperator` class has two constructors. +The default constructor requires a :class:`openmc.Materials` instance, a +:class:`~openmc.deplete.MicroXS` instance containing one-group microscoic cross +sections in units of barns, and a path to a depletion chain file:: - # load in the microscopic cross sections materials = openmc.Materials() ... + # load in the microscopic cross sections micro_xs = openmc.deplete.MicroXS.from_csv(micro_xs_path) + op = openmc.deplete.IndependentOperator(materials, micro_xs, chain_file) .. note:: @@ -229,7 +233,7 @@ and a path to a depletion chain file:: An alternate constructor, :meth:`~openmc.deplete.IndependentOperator.from_nuclides`, accepts a volume and dictionary of nuclide concentrations in place of the :class:`openmc.Materials` -object:: +instance:: nuclides = {'U234': 8.92e18, 'U235': 9.98e20, @@ -250,32 +254,17 @@ transport-depletion calculation and follow the same steps from there. .. note:: Ideally, one-group cross section data should be available for every - reaction in the depletion chain. If a nuclide that has a reaction - associated with it in the depletion chain is present in the `nuclides` - parameter but not the cross section data, that reaction will not be - simulated. + reaction in the depletion chain. If cross section data is not present for + a nuclide in the depletion chain with at least one reaction, that reaction + will not be simulated. -Generating Microscopic Cross Sections +Loading and Generating Microscopic Cross Sections ------------------------------------- -Users can generate the one-group microscopic cross sections needed by -:class:`~openmc.deplete.IndependentOperator` using the -:class:`~openmc.deplete.MicroXS` class:: - - import openmc - - model = openmc.Model.from_xml() - - micro_xs = openmc.deplete.MicroXS.from_model(model, - model.materials[0], - chain_file) - -The :meth:`~openmc.deplete.MicroXS.from_model()` method will produce a -:class:`~openmc.deplete.MicroXS` object with microscopic cross section data in -units of barns, which is what :class:`~openmc.deplete.IndependentOperator` -expects the units to be. The :class:`~openmc.deplete.MicroXS` class also -includes functions to read in cross section data directly from a ``.csv`` file -or from data arrays:: +As mentioned earlier, any transport code could be used to calculate one-group +microscopic cross sections. The :mod:`openmc.deplete` module provides the +:class:`~openmc.deplete.MicroXS` class, which contains methods to read in +pre-caluclated cross sections from a ``.csv`` file or from data arrays:: micro_xs = MicroXS.from_csv(micro_xs_path) @@ -294,6 +283,19 @@ or from data arrays:: sure your cross sections are in the correct units before passing to a :class:`~openmc.deplete.IndependentOperator` object. +The :class:`~openmc.deplete.MicroXS` class also contains a method to generate one-group microscopic cross sections using OpenMC's transport solver. The +:meth:`~openmc.deplete.MicroXS.from_model()` method will produce a +:class:`~openmc.deplete.MicroXS` instance with microscopic cross section data in +units of barns:: + + import openmc + + model = openmc.Model.from_xml() + + micro_xs = openmc.deplete.MicroXS.from_model(model, + model.materials[0], + chain_file) + If you are runnnig :meth:`~openmc.deplete.MicroXS.from_model()` on a cluster that does not share local filesystems across nodes, you'll need to set an environment variable so that each MPI process knows where to store output files @@ -320,12 +322,13 @@ normalizing reaction rates: 1. ``source-rate`` normalization, which assumes the ``source_rate`` provided by the time integrator is a flux, and obtains the reaction rates by multiplying - the cross-sections by the ``source-rate``. + the cross sections by the ``source-rate``. 2. ``fission-q`` normalization, which uses the ``power`` or ``power_density`` provided by the time integrator to obtain reaction rates by computing a value for the flux based on this power. The general equation for the flux is .. math:: + :label: fission-q \phi = \frac{P}{\sum\limits_i (Q_i \sigma^f_i N_i)} @@ -349,19 +352,18 @@ normalizing reaction rates: Multiple Materials ~~~~~~~~~~~~~~~~~~ -Running a depletion simulation with multiple materials using the -``source-rate`` normalization method treats each material as completely -separate with respect to reaction rates. This can be useful for running many -different cases of a particular scenario. However, running a depletion -simulation with multiple materials using the ``fission-q`` normalization method -treats each material as part of the same "reactor" due to how ``fission-q`` -normalization accumulates energy values from each material to a single value. -This behavior may change in the future. +A transport-independent depletion simulation using ``source-race`` normalization +will calculate reaction rates for each material independently. This can be +useful for running many different cases of a particular scenario. A depletion +simulation using ``fission-q`` normalization will sum the energy values from +each material into :math:`Q` in Equation :math:numref:`fission-q`, which is +used to normalize the reaction rates for all materials. This behavior may +change in the future. Time integration ~~~~~~~~~~~~~~~~ -The one-group microscopic cross sections passed to -:class:`openmc.deplete.IndependentOperator` are fixed values for the entire -depletion simulation. This implicit assumption may produce inaccurate results -for certain scenarios. +The values of the one-group microscopic cross sections passed to +:class:`openmc.deplete.IndependentOperator` are fixed for the entire depletion +simulation. This implicit assumption may produce inaccurate results for certain +scenarios. From d590aa7ad745e862d4a372f072d3d48ec48613e3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 13:01:42 -0500 Subject: [PATCH 0958/2654] Remove RELAX NG schema and openmc-validate-xml script --- CMakeLists.txt | 1 - docs/source/devguide/user-input.rst | 11 - docs/source/usersguide/basics.rst | 5 +- docs/source/usersguide/install.rst | 29 +- docs/source/usersguide/scripts.rst | 28 - schemas.xml | 9 - scripts/openmc-validate-xml | 102 --- src/relaxng/cross_sections.rnc | 12 - src/relaxng/cross_sections.rng | 42 -- src/relaxng/geometry.rnc | 55 -- src/relaxng/geometry.rng | 447 -------------- src/relaxng/materials.rnc | 41 -- src/relaxng/materials.rng | 165 ----- src/relaxng/mg_cross_sections.rnc | 61 -- src/relaxng/mg_cross_sections.rng | 314 ---------- src/relaxng/plots.rnc | 41 -- src/relaxng/plots.rng | 293 --------- src/relaxng/readme.rst | 19 - src/relaxng/settings.rnc | 204 ------ src/relaxng/settings.rng | 921 ---------------------------- src/relaxng/tallies.rnc | 114 ---- src/relaxng/tallies.rng | 480 --------------- 22 files changed, 2 insertions(+), 3392 deletions(-) delete mode 100644 schemas.xml delete mode 100755 scripts/openmc-validate-xml delete mode 100644 src/relaxng/cross_sections.rnc delete mode 100644 src/relaxng/cross_sections.rng delete mode 100644 src/relaxng/geometry.rnc delete mode 100644 src/relaxng/geometry.rng delete mode 100644 src/relaxng/materials.rnc delete mode 100644 src/relaxng/materials.rng delete mode 100644 src/relaxng/mg_cross_sections.rnc delete mode 100644 src/relaxng/mg_cross_sections.rng delete mode 100644 src/relaxng/plots.rnc delete mode 100644 src/relaxng/plots.rng delete mode 100644 src/relaxng/readme.rst delete mode 100644 src/relaxng/settings.rnc delete mode 100644 src/relaxng/settings.rng delete mode 100644 src/relaxng/tallies.rnc delete mode 100644 src/relaxng/tallies.rng diff --git a/CMakeLists.txt b/CMakeLists.txt index 995480372..521b46cfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -525,7 +525,6 @@ install(EXPORT openmc-targets NAMESPACE OpenMC:: DESTINATION ${INSTALL_CONFIGDIR}) -install(DIRECTORY src/relaxng DESTINATION ${CMAKE_INSTALL_DATADIR}/openmc) install(FILES "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/OpenMCConfig.cmake" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/OpenMCConfigVersion.cmake" diff --git a/docs/source/devguide/user-input.rst b/docs/source/devguide/user-input.rst index 0bde0fb05..a26f98b19 100644 --- a/docs/source/devguide/user-input.rst +++ b/docs/source/devguide/user-input.rst @@ -49,14 +49,6 @@ following steps should be followed to make changes to user input: written out to the statepoint or summary files and that the :class:`openmc.StatePoint` and :class:`openmc.Summary` classes read them in. -7. Finally, a set of `RELAX NG`_ schemas exists that enables validation of input - files. You should modify the RELAX NG schema for the file you changed. The - easiest way to do this is to change the `compact syntax`_ file - (e.g. ``src/relaxng/geometry.rnc``) and then convert it to regular XML syntax - using trang_:: - - trang geometry.rnc geometry.rng - For most user input additions and changes, it is simple enough to follow a "monkey see, monkey do" approach. When in doubt, contact your nearest OpenMC developer or send a message to the `developers mailing list`_. @@ -65,7 +57,4 @@ developer or send a message to the `developers mailing list`_. .. _property attribute: https://docs.python.org/3.6/library/functions.html#property .. _XML Schema Part 2: http://www.w3.org/TR/xmlschema-2/ .. _boolean: http://www.w3.org/TR/xmlschema-2/#boolean -.. _RELAX NG: https://relaxng.org/ -.. _compact syntax: https://relaxng.org/compact-tutorial-20030326.html -.. _trang: https://relaxng.org/jclark/trang.html .. _developers mailing list: https://groups.google.com/forum/?fromgroups=#!forum/openmc-dev diff --git a/docs/source/usersguide/basics.rst b/docs/source/usersguide/basics.rst index 250255f45..3394c17a6 100644 --- a/docs/source/usersguide/basics.rst +++ b/docs/source/usersguide/basics.rst @@ -75,10 +75,7 @@ person. The nested tags *firstname*, *lastname*, *age*, and *occupation* indicate characteristics about the person being described. In much the same way, OpenMC input uses XML tags to describe the geometry, the -materials, and settings for a Monte Carlo simulation. Note that because the XML -files have a well-defined structure, they can be validated using the -:ref:`scripts_validate` script or using :ref:`Emacs nXML mode -`. +materials, and settings for a Monte Carlo simulation. Creating Input Files -------------------- diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 3d48828fb..b57958814 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -545,8 +545,7 @@ distributions. Uncertainties are used for decay data in the :mod:`openmc.data` module. `lxml `_ - lxml is used for the :ref:`scripts_validate` script and various other - parts of the Python API. + lxml is used for various parts of the Python API. .. admonition:: Optional :class: note @@ -590,31 +589,5 @@ wrapper is used when installing h5py: CC= HDF5_MPI=ON HDF5_DIR= pip install --no-binary=h5py h5py -.. _usersguide_nxml: - ------------------------------------------------------ -Configuring Input Validation with GNU Emacs nXML mode ------------------------------------------------------ - -The `GNU Emacs`_ text editor has a built-in mode that extends functionality for -editing XML files. One of the features in nXML mode is the ability to perform -real-time `validation`_ of XML files against a `RELAX NG`_ schema. The OpenMC -source contains RELAX NG schemas for each type of user input file. In order for -nXML mode to know about these schemas, you need to tell emacs where to find a -"locating files" description. Adding the following lines to your ``~/.emacs`` -file will enable real-time validation of XML input files: - -.. code-block:: common-lisp - - (require 'rng-loc) - (add-to-list 'rng-schema-locating-files "~/openmc/schemas.xml") - -Make sure to replace the last string on the second line with the path to the -schemas.xml file in your own OpenMC source directory. - -.. _GNU Emacs: http://www.gnu.org/software/emacs/ -.. _validation: https://en.wikipedia.org/wiki/XML_validation -.. _RELAX NG: https://relaxng.org/ -.. _ctest: https://cmake.org/cmake/help/latest/manual/ctest.1.html .. _Conda: https://conda.io/en/latest/ .. _pip: https://pip.pypa.io/en/stable/ diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst index f2ba81605..c433ffe2c 100644 --- a/docs/source/usersguide/scripts.rst +++ b/docs/source/usersguide/scripts.rst @@ -171,34 +171,6 @@ the latest HDF5-based format. -i IN, --input IN Input XML file -o OUT, --output OUT Output file in HDF5 format -.. _scripts_validate: - ------------------------ -``openmc-validate-xml`` ------------------------ - -Input files can be checked before executing OpenMC using the -``openmc-validate-xml`` script which is installed alongside the Python API. Two -command line arguments can be set when running ``openmc-validate-xml``: - --i, --input-path Location of OpenMC input files. --r, --relaxng-path Location of OpenMC RelaxNG files - -If the RelaxNG path is not set, the script will search for these files because -it expects that the user is either running the script located in the install -directory ``bin`` folder or in ``src/utils``. Once executed, it will match -OpenMC XML files with their RelaxNG schema and check if they are valid. Below -is a table of the messages that will be printed after each file is checked. - -======================== =================================== -Message Description -======================== =================================== -[XML ERROR] Cannot parse XML file. -[NO RELAXNG FOUND] No RelaxNG file found for XML file. -[NOT VALID] XML file does not match RelaxNG. -[VALID] XML file matches RelaxNG. -======================== =================================== - .. _scripts_voxel: --------------------------- diff --git a/schemas.xml b/schemas.xml deleted file mode 100644 index 3e586ec6a..000000000 --- a/schemas.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/scripts/openmc-validate-xml b/scripts/openmc-validate-xml deleted file mode 100755 index e3aeb1039..000000000 --- a/scripts/openmc-validate-xml +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import glob -import lxml.etree as etree -from optparse import OptionParser - -def validate_xml(inputs, relaxng): - - # Colored output - if sys.stdout.isatty(): - OK = '\033[92m' - FAIL = '\033[91m' - NOT_FOUND = '\033[93m' - ENDC = '\033[0m' - BOLD = '\033[1m' - else: - OK = '' - FAIL = '' - ENDC = '' - BOLD = '' - NOT_FOUND = '' - - # Get absolute paths - if relaxng is not None: - relaxng_path = os.path.abspath(relaxng) - if inputs is not None: - inputs_path = os.path.abspath(inputs) - - # Search for relaxng path if not set - if relaxng is None: - xml_validate_path = os.path.abspath(os.path.dirname(sys.argv[0])) - if "bin" in xml_validate_path: - relaxng_path = os.path.join(xml_validate_path, "..", "share", "relaxng") - elif os.path.join("src", "utils") in xml_validate_path: - relaxng_path = os.path.join(xml_validate_path, "..", "relaxng") - else: - raise Exception("Set RelaxNG path with -r command line option.") - if not os.path.exists(relaxng_path): - raise Exception(f"RelaxNG path: {relaxng_path} does not exist, set " - "with -r command line option.") - - # Make sure there are .rng files in RelaxNG path - rng_files = glob.glob(os.path.join(relaxng_path, "*.rng")) - if len(rng_files) == 0: - raise Exception(f"No .rng files found in RelaxNG path: {relaxng_path}.") - - # Get list of xml input files - xml_files = glob.glob(os.path.join(inputs_path, "*.xml")) - if len(xml_files) == 0: - raise Exception(f"No .xml files found at input path: {inputs_path}.") - - # Begin loop around input files - for xml_file in xml_files: - - text = f"Validating {os.path.basename(xml_file)}" - print(text + '.'*(30 - len(text)), end="") - - # Validate the XML file - try: - xml_tree = etree.parse(xml_file) - except etree.XMLSyntaxError as e: - print(BOLD + FAIL + '[XML ERROR]' + ENDC) - print(f" {e}") - continue - - # Get xml_filename prefix - xml_prefix = os.path.basename(xml_file) - xml_prefix = xml_prefix.split(".")[0] - - # Search for rng file - rng_file = os.path.join(relaxng_path, xml_prefix + ".rng") - if rng_file in rng_files: - - # read in RelaxNG - relaxng_doc = etree.parse(rng_file) - relaxng = etree.RelaxNG(relaxng_doc) - - # validate xml file again RelaxNG - try: - relaxng.assertValid(xml_tree) - print(BOLD + OK + '[VALID]' + ENDC) - except (etree.DocumentInvalid, TypeError) as e: - print(BOLD + FAIL + '[NOT VALID]' + ENDC) - print(f" {e}") - - # RNG file does not exist - else: - print(BOLD + NOT_FOUND + '[NO RELAXNG FOUND]' + ENDC) - - -if __name__ == "__main__": - # Command line parsing - parser = OptionParser() - parser.add_option('-r', '--relaxng-path', dest='relaxng', - help="Path to RelaxNG files.") - parser.add_option('-i', '--input-path', dest='inputs', default=os.getcwd(), - help="Path to OpenMC input files." ) - (options, args) = parser.parse_args() - - validate_xml(inputs=options.inputs, relaxng=options.relaxng) diff --git a/src/relaxng/cross_sections.rnc b/src/relaxng/cross_sections.rnc deleted file mode 100644 index 7fbc610a2..000000000 --- a/src/relaxng/cross_sections.rnc +++ /dev/null @@ -1,12 +0,0 @@ -element cross_sections { - element library { - (element materials { xsd:string } | - attribute materials { xsd:string }) & - (element type { xsd:string } | - attribute type { xsd:string }) & - (element path { xsd:string } | - attribute path { xsd:string }) - }* & - - element directory { xsd:string { maxLength = "255" } }? -} \ No newline at end of file diff --git a/src/relaxng/cross_sections.rng b/src/relaxng/cross_sections.rng deleted file mode 100644 index 435f7fa84..000000000 --- a/src/relaxng/cross_sections.rng +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 255 - - - - - diff --git a/src/relaxng/geometry.rnc b/src/relaxng/geometry.rnc deleted file mode 100644 index e3c88c445..000000000 --- a/src/relaxng/geometry.rnc +++ /dev/null @@ -1,55 +0,0 @@ -element geometry { - element cell { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element universe { xsd:int } | attribute universe { xsd:int })? & - ( - (element fill { xsd:int } | attribute fill { xsd:int }) | - (element material { list { ( xsd:int | "void" )+ } } | - attribute material { list { ( xsd:int | "void" )+ } }) - ) & - (element temperature { list { xsd:double+ } } | - attribute temperature { list { xsd:double+ } } )? & - (element region { xsd:string } | attribute region { xsd:string })? & - (element rotation { list { xsd:double+ } } | attribute rotation { list { xsd:double+ } })? & - (element translation { list { xsd:double+ } } | attribute translation { list { xsd:double+ } })? - }* - - & element surface { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element type { xsd:string { maxLength = "15" } } | - attribute type { xsd:string { maxLength = "15" } }) & - (element coeffs { list { xsd:double+ } } | attribute coeffs { list { xsd:double+ } }) & - (element boundary { ( "transmit" | "reflective" | "vacuum" | "periodic" ) } | - attribute boundary { ( "transmit" | "reflective" | "vacuum" | "periodic" ) })? & - (element periodic_surface_id { xsd:int } | attribute periodic_surface_id { xsd:int })? - }* - - & element lattice { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element dimension { list { xsd:positiveInteger+ } } | - attribute dimension { list { xsd:positiveInteger+ } }) & - (element lower_left { list { xsd:double+ } } | attribute lower_left { list { xsd:double+ } }) & - (element pitch { list { xsd:double+ } } | attribute pitch { list { xsd:double+ } }) & - (element universes { list { xsd:int+ } } | attribute universes { list { xsd:int+ } }) & - (element outer { xsd:int } | attribute outer { xsd:int })? - }* - - & element hex_lattice { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element n_rings { xsd:int } | attribute n_rings { xsd:int }) & - (element n_axial { xsd:int } | attribute n_axial { xsd:int })? & - (element center { list { xsd:double+ } } | attribute center { list { xsd:double+ } }) & - (element pitch { list { xsd:double+ } } | attribute pitch { list { xsd:double+ } }) & - (element orientation { ( "x" | "y" ) } | attribute orientation { ( "x" | "y" ) })? & - (element universes { list { xsd:int+ } } | attribute universes { list { xsd:int+ } }) & - (element outer { xsd:int } | attribute outer { xsd:int })? - }* -} diff --git a/src/relaxng/geometry.rng b/src/relaxng/geometry.rng deleted file mode 100644 index 56bf38580..000000000 --- a/src/relaxng/geometry.rng +++ /dev/null @@ -1,447 +0,0 @@ - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void - - - - - - - - - - void - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - 15 - - - - - 15 - - - - - - - - - - - - - - - - - - - - - - - - transmit - reflective - vacuum - periodic - - - - - transmit - reflective - vacuum - periodic - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x - y - - - - - x - y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/materials.rnc b/src/relaxng/materials.rnc deleted file mode 100644 index c82ecfeaa..000000000 --- a/src/relaxng/materials.rnc +++ /dev/null @@ -1,41 +0,0 @@ -element materials { - element material { - (element id { xsd:int } | attribute id { xsd:int }) & - - (element name { xsd:string } | attribute name { xsd:string })? & - - (element depletable { xsd:boolean } | attribute depletable { xsd:boolean })? & - - (element volume { xsd:double } | attribute volume { xsd:double })? & - - (element temperature { xsd:double } | attribute temperature { xsd:double })? & - - element density { - (element value { xsd:double } | attribute value { xsd:double })? & - (element units { xsd:string { maxLength = "10" } } | - attribute units { xsd:string { maxLength = "10" } }) - } & - - element nuclide { - (element name { xsd:string } | attribute name { xsd:string }) & - ( - (element ao { xsd:double } | attribute ao { xsd:double }) | - (element wo { xsd:double } | attribute wo { xsd:double }) - ) - }* & - - element isotropic { xsd:string }? & - - element macroscopic { - (element name { xsd:string } | - attribute name { xsd:string }) - }* & - - element sab { - (element name { xsd:string } | attribute name { xsd:string }) & - (element fraction { xsd:double } | attribute fraction { xsd:double })? - }* - }+ & - - element cross_sections { xsd:string { maxLength = "255" } }? -} diff --git a/src/relaxng/materials.rng b/src/relaxng/materials.rng deleted file mode 100644 index e99fb7adf..000000000 --- a/src/relaxng/materials.rng +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10 - - - - - 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 255 - - - - - diff --git a/src/relaxng/mg_cross_sections.rnc b/src/relaxng/mg_cross_sections.rnc deleted file mode 100644 index b2aaec4d4..000000000 --- a/src/relaxng/mg_cross_sections.rnc +++ /dev/null @@ -1,61 +0,0 @@ -element cross_sections { - - element groups { xsd:int } & - - element group_structure { list { xsd:double+ } } & - - element inverse_velocities { list { xsd:double+ } }? & - - element xsdata { - (element name { xsd:string { maxLength = "15" } } | - attribute name { xsd:string { maxLength = "15" } }) & - (element alias { xsd:string { maxLength = "15" } } | - attribute alias { xsd:string { maxLength = "15" } })? & - (element kT { xsd:double } | attribute kT { xsd:double })? & - (element fissionable { ( "true" | "false" ) } | - attribute fissionable { ( "true" | "false" ) }) & - (element representation { ( "isotropic" | "angle" ) } | - attribute representation { ( "isotropic" | "angle" ) })? & - (element num_azimuthal { xsd:positiveInteger } | - attribute num_azimuthal { xsd:positiveInteger })? & - (element num_polar { xsd:positiveInteger } | - attribute num_polar { xsd:positiveInteger })? & - (element scatt_type { ( "legendre" | "histogram" | "tabular" ) } | - attribute scatt_type { ( "legendre" | "histogram" | "tabular" ) })? & - (element order { xsd:positiveInteger } | - attribute order { xsd:positiveInteger }) & - element tabular_legendre { - (element enable { ( "true" | "false" ) } | - attribute enable { ( "true" | "false" ) })? & - (element num_points { xsd:positiveInteger } | - attribute num_points { xsd:positiveInteger })? - }? & - - (element total { list { xsd:double+ } } | - attribute total { list { xsd:double+ } })? & - - (element absorption { list { xsd:double+ } } | - attribute absorption { list { xsd:double+ } }) & - - (element scatter { list { xsd:double+ } } | - attribute scatter { list { xsd:double+ } }) & - - (element fission { list { xsd:double+ } } | - attribute fission { list { xsd:double+ } })? & - - (element fission { list { xsd:double+ } } | - attribute fission { list { xsd:double+ } })? & - - (element k_fission { list { xsd:double+ } } | - attribute k_fission { list { xsd:double+ } })? & - - (element chi { list { xsd:double+ } } | - attribute chi { list { xsd:double+ } })? & - - (element nu_fission { list { xsd:double+ } } | - attribute nu_fission { list { xsd:double+ } })? - - }* - - -} \ No newline at end of file diff --git a/src/relaxng/mg_cross_sections.rng b/src/relaxng/mg_cross_sections.rng deleted file mode 100644 index b293cddbe..000000000 --- a/src/relaxng/mg_cross_sections.rng +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 - - - - - 15 - - - - - - - - 15 - - - - - 15 - - - - - - - - - - - - - - - - - - true - false - - - - - true - false - - - - - - - - isotropic - angle - - - - - isotropic - angle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - legendre - histogram - tabular - - - - - legendre - histogram - tabular - - - - - - - - - - - - - - - - - - - - true - false - - - - - true - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/plots.rnc b/src/relaxng/plots.rnc deleted file mode 100644 index e53cc15f7..000000000 --- a/src/relaxng/plots.rnc +++ /dev/null @@ -1,41 +0,0 @@ -element plots { - element plot { - (element id { xsd:int } | attribute id { xsd:int })? & - (element filename { xsd:string { maxLength = "50" } } | - attribute filename { xsd:string { maxLength = "50" } })? & - (element type { "slice" | "voxel" } | - attribute type { "slice" | "voxel" })? & - (element color_by { ( "cell" | "material" ) } | - attribute color_by { ( "cell" | "material" ) })? & - (element level { xsd:int } | attribute level { xsd:int })? & - (element origin { list { xsd:double+ } } | - attribute origin { list { xsd:double+ } })? & - (element width { list { xsd:double+ } } | - attribute width { list { xsd:double+ } })? & - (element basis { ( "xy" | "yz" | "xz" ) } | - attribute basis { ( "xy" | "yz" | "xz" ) })? & - (element pixels { list { xsd:int+ } } | - attribute pixels { list { xsd:int+ } })? & - (element background { list { xsd:int+ } } | - attribute background { list { xsd:int+ } })? & - element color { - (element id { xsd:int } | attribute id { xsd:int }) & - (element rgb { list { xsd:int+ } } | - attribute rgb { list { xsd:int+ } }) - }* & - element mask { - (element components { list { xsd:int+ } } | - attribute components { list { xsd:int+ } }) & - (element background { list { xsd:int+ } } | - attribute background { list { xsd:int+ } }) - }* & - element meshlines { - (element meshtype { ( "tally" | "entropy" | "ufs" | "cmfd" ) } | - attribute meshtype { ( "tally" | "entropy" | "ufs" | "cmfd" ) }) & - (element id { xsd:int } | attribute id { xsd:int })? & - (element linewidth { xsd:int } | attribute linewidth { xsd:int }) & - (element color { list { xsd:int+ } } | - attribute color { list { xsd:int+ } })? - }* - }* -} diff --git a/src/relaxng/plots.rng b/src/relaxng/plots.rng deleted file mode 100644 index 55d69008e..000000000 --- a/src/relaxng/plots.rng +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - - - - - - - - - - - - - - 50 - - - - - 50 - - - - - - - - - slice - voxel - - - - - slice - voxel - - - - - - - - - cell - material - - - - - cell - material - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - xy - yz - xz - - - - - xy - yz - xz - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tally - entropy - ufs - cmfd - - - - - tally - entropy - ufs - cmfd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/readme.rst b/src/relaxng/readme.rst deleted file mode 100644 index 9660e3f8c..000000000 --- a/src/relaxng/readme.rst +++ /dev/null @@ -1,19 +0,0 @@ -===================== -Editing RelaxNG files -===================== - -All direct edits to RelaxNG files should be in the .rnc files. The program -TRANG_ should be used to generate a correcsponding .rng file. For Ubuntu, you -can install with: - -.. code-block:: bash - - sudo apt-get install trang - -To convert the .rnc file to .rng, use the following syntax: - -.. code-block:: bash - - trang {filename}.rnc {filename}.rng - -.. _TRANG: http://www.thaiopensource.com/relaxng/trang.html diff --git a/src/relaxng/settings.rnc b/src/relaxng/settings.rnc deleted file mode 100644 index f9877a3f9..000000000 --- a/src/relaxng/settings.rnc +++ /dev/null @@ -1,204 +0,0 @@ -element settings { - element batches { xsd:positiveInteger }? & - - element confidence_intervals { xsd:boolean }? & - - element create_fission_neutrons { xsd:boolean }? & - - element cutoff { - (element weight { xsd:double } | attribute weight { xsd:double })? & - (element weight_avg { xsd:double } | attribute weight_avg { xsd:double })? & - (element energy_neutron { xsd:double } | attribute energy_neutron { xsd:double })? & - (element energy_photon { xsd:double } | attribute energy_photon { xsd:double })? & - (element energy_electron { xsd:double } | attribute energy_electron { xsd:double })? & - (element energy_positron { xsd:double } | attribute energy_positron { xsd:double })? - }? & - - element delayed_photon_scaling { xsd:boolean }? & - - element electron_treatment { ( "led" | "ttb" ) }? & - - element energy_grid { ( "nuclide" | "log" | "logarithm" | "logarithmic" | "material-union" | "union" ) }? & - - element energy_mode { ( "continuous-energy" | "ce" | "CE" | "multi-group" | "mg" | "MG" ) }? & - - element entropy_mesh { xsd:positiveInteger }? & - - element event_based { xsd:boolean }? & - - element generations_per_batch { xsd:positiveInteger }? & - - element inactive { xsd:nonNegativeInteger }? & - - element keff_trigger { - (element type { xsd:string } | attribute type { xsd:string }) & - (element threshold { xsd:double} | attribute threshold { xsd:double }) - }? & - - element log_grid_bins { xsd:positiveInteger }? & - - element material_cell_offsets { xsd:boolean }? & - - element max_particles_in_flight { xsd:positiveInteger }? & - - element max_order { xsd:nonNegativeInteger }? & - - element mesh { - (element id { xsd:int } | attribute id { xsd:int }) & - (element type { ( "regular" ) } | - attribute type { ( "regular" ) })? & - (element dimension { list { xsd:positiveInteger+ } } | - attribute dimension { list { xsd:positiveInteger+ } }) & - (element lower_left { list { xsd:double+ } } | - attribute lower_left { list { xsd:double+ } }) & - ( - (element upper_right { list { xsd:double+ } } | - attribute upper_right { list { xsd:double+ } }) | - (element width { list { xsd:double+ } } | - attribute width { list { xsd:double+ } }) - ) - }* & - - element no_reduce { xsd:boolean }? & - - element output { - (element summary { xsd:boolean } | attribute summary { xsd:boolean })? & - (element tallies { xsd:boolean } | attribute tallies { xsd:boolean })? & - (element path { xsd:string } | attribute path { xsd:string })? - }? & - - element particles { xsd:positiveInteger }? & - - element photon_transport { xsd:boolean }? & - - element ptables { xsd:boolean }? & - - element dagmc { xsd:boolean }? & - - element run_mode { xsd:string }? & - - element seed { xsd:positiveInteger }? & - - element source { - grammar { - start = - (element particle { xsd:string } | attribute particle { xsd:string })? & - (element strength { xsd:double } | attribute strength { xsd:double })? & - (element file { xsd:string } | attribute file { xsd:string })? & - element space { - (element type { xsd:string } | attribute type { xsd:string }) & - (element parameters { list { xsd:double+ } } | - attribute parameters { list { xsd:double+ } })? & - element x { distribution }? & - element y { distribution }? & - element z { distribution }? & - element r { distribution }? & - element theta { distribution }? & - element phi { distribution }? & - element origin { list { xsd:double, xsd:double, xsd:double } }? - }? & - element angle { - (element type { xsd:string } | attribute type { xsd:string }) & - (element reference_uvw { list { xsd:double, xsd:double, xsd:double } } | - attribute reference_uvw { list { xsd:double, xsd:double, xsd:double } })? & - element mu { distribution }? & - element phi { distribution }? - }? & - element energy { distribution }? - distribution = - (element type { xsd:string { maxLength = "16" } } | - attribute type { xsd:string { maxLength = "16" } }) & - (element interpolation { xsd:string } | - attribute interpolation { xsd:string })? & - (element parameters { list { xsd:double+ } } | - attribute parameters { list { xsd:double+ } })? - } - }* & - - element state_point { - ( - (element batches { list { xsd:positiveInteger+ } } | - attribute batches { list { xsd:positiveInteger+ } }) | - (element interval { xsd:positiveInteger } | - attribute interval { xsd:positiveInteger }) - ) - }? & - - element source_point { - ( - (element batches { list { xsd:positiveInteger+ } } | - attribute batches { list { xsd:positiveInteger+ } }) | - (element interval { xsd:positiveInteger } | - attribute interval { xsd:positiveInteger }) - )? & - (element separate { xsd:boolean } | - attribute separate { xsd:boolean })? & - (element write { xsd:boolean } | - attribute write { xsd:boolean })? & - (element overwrite_latest { xsd:boolean} | - attribute overwrite_latest {xsd:boolean})? - }? & - - element surf_source_read { - (element path { xsd:string } | attribute path { xsd:string }) - }? & - - element surf_source_write { - (element surface_ids { list { xsd:positiveInteger+ } } | - attribute surface_ids { list { xsd:positiveInteger+ } }) & - (element max_particles { xsd:positiveInteger } | - attribute max_particles { xsd:positiveInteger }) - }? & - - element survival_biasing { xsd:boolean }? & - - element temperature_default { xsd:double }? & - - element temperature_method { xsd:string }? & - - element temperature_multipole { xsd:boolean }? & - - element temperature_range { list { xsd:double, xsd:double } }? & - - element temperature_tolerance { xsd:double }? & - - element threads { xsd:positiveInteger }? & - - element trace { list { xsd:positiveInteger+ } }? & - - element track { list { xsd:positiveInteger+ } }? & - - element trigger { - (element active { xsd:boolean } | attribute active { xsd:boolean }) & - (element max_batches { xsd:positiveInteger } | attribute max_batches { xsd:positiveInteger }) & - (element batch_interval { xsd:positiveInteger } | attribute batch_interval { xsd:positiveInteger })? - }? & - - element ufs_mesh { xsd:positiveInteger }? & - - element verbosity { xsd:positiveInteger }? & - - element volume_calc { - (element domain_type { xsd:string } | - attribute domain_type { xsd:string }) & - (element domain_ids { list { xsd:integer+ } } | - attribute domain_ids { list { xsd:integer+ } }) & - (element samples { xsd:positiveInteger } | - attribute samples { xsd:positiveInteger }) & - (element lower_left { list { xsd:double+ } } | - attribute lower_left { list { xsd:double+ } }) & - (element upper_right { list { xsd:double+ } } | - attribute upper_right { list { xsd:double+ } }) - }* & - - element write_initial_source { xsd:boolean }? & - - element resonance_scattering { - (element enable { xsd:boolean } | attribute enable { xsd:boolean })? & - (element method { xsd:string } | attribute method { xsd:string })? & - (element energy_min { xsd:double } | attribute energy_min { xsd:double })? & - (element energy_max { xsd:double } | attribute energy_max { xsd:double })? & - (element nuclides { list { xsd:string+ } } | - attribute nuclides { list { xsd:string+ } })? - }? -} diff --git a/src/relaxng/settings.rng b/src/relaxng/settings.rng deleted file mode 100644 index 07b8a6d1d..000000000 --- a/src/relaxng/settings.rng +++ /dev/null @@ -1,921 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - led - ttb - - - - - - - nuclide - log - logarithm - logarithmic - material-union - union - - - - - - - continuous-energy - ce - CE - multi-group - mg - MG - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - regular - - - regular - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 - - - - - 16 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc deleted file mode 100644 index 4e46c45a1..000000000 --- a/src/relaxng/tallies.rnc +++ /dev/null @@ -1,114 +0,0 @@ -element tallies { - element mesh { - (element id { xsd:int } | attribute id { xsd:int }) & - ( - ( - (element type { ( "regular" ) } | - attribute type { ( "regular" ) }) & - (element dimension { list { xsd:positiveInteger+ } } | - attribute dimension { list { xsd:positiveInteger+ } }) & - (element lower_left { list { xsd:double+ } } | - attribute lower_left { list { xsd:double+ } }) & - ( - (element upper_right { list { xsd:double+ } } | - attribute upper_right { list { xsd:double+ } }) | - (element width { list { xsd:double+ } } | - attribute width { list { xsd:double+ } }) - ) - ) | ( - (element type { ( "rectilinear" ) } | - attribute type { ( "rectilinear" ) }) & - (element x_grid { list { xsd:double+ } } | - attribute x_grid { list { xsd:double+ } }) & - (element y_grid { list { xsd:double+ } } | - attribute y_grid { list { xsd:double+ } }) & - (element z_grid { list { xsd:double+ } } | - attribute z_grid { list { xsd:double+ } }) - ) | ( - (element type { ( "cylindrical" ) } | - attribute type { ( "cylindrical" ) }) & - (element r_grid { list { xsd:double+ } } | - attribute r_grid { list { xsd:double+ } }) & - (element phi_grid { list { xsd:double+ } } | - attribute phi_grid { list { xsd:double+ } }) & - (element z_grid { list { xsd:double+ } } | - attribute z_grid { list { xsd:double+ } }) - ) | ( - (element type { ( "spherical" ) } | - attribute type { ( "spherical" ) }) & - (element r_grid { list { xsd:double+ } } | - attribute r_grid { list { xsd:double+ } }) & - (element theta_grid { list { xsd:double+ } } | - attribute theta_grid { list { xsd:double+ } }) & - (element phi_grid { list { xsd:double+ } } | - attribute phi_grid { list { xsd:double+ } }) - ) - ) - }* & - - element derivative { - (element id { xsd:int } | attribute id { xsd:int }) & - (element material { xsd:int } | attribute material { xsd:int }) & - ( (element variable { ( "density") } - | attribute variable { ( "density" ) } ) | - ( - (element variable { ( "nuclide_density" ) } - | attribute variable { ( "nuclide_density" ) } ) - & - (element nuclide { xsd:string { maxLength = "12" } } - | attribute nuclide { xsd:string { maxLength = "12" } } ) - ) | - (element variable { ( "temperature") } - | attribute variable { ( "temperature" ) } ) - ) - }* & - - element filter { - (element id { xsd:int } | attribute id { xsd:int }) & - ( - ( (element type { ( "cell" | "cellfrom" | "cellborn" | "material" | - "universe" | "surface" | "distribcell" | "mesh" | "energy" | - "energyout" | "mu" | "polar" | "azimuthal" | "delayedgroup" | - "energyfunction" | "meshsurface" | "cellinstance") } | - attribute type { ( "cell" | "cellfrom" | "cellborn" | "material" | - "universe" | "surface" | "distribcell" | "mesh" | "energy" | - "energyout" | "mu" | "polar" | "azimuthal" | "delayedgroup" | - "energyfunction" | "meshsurface" | "cellinstance") }) & - (element bins { list { xsd:double+ } } | - attribute bins { list { xsd:double+ } }) - ) | - ( - (element type { ("energyfunction") } | - attribute type { ("energyfunction") }) & - (element energy { list { xsd:double+ } } | - attribute energy { list { xsd:double+ } }) & - (element y { list { xsd:double+ } } | - attribute y { list { xsd:double+ } }) - ) - ) - }* & - - element tally { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element estimator { ( "analog" | "tracklength" | "collision" ) } | - attribute estimator { ( "analog" | "tracklength" | "collision" ) })? & - (element filters { list { xsd:int+ } } | - attribute filters { list { xsd:int+ } })? & - element nuclides { - list { xsd:string { maxLength = "12" }+ } - }? & - element scores { - list { xsd:string { maxLength = "20" }+ } - } & - element trigger { - (element type { xsd:string } | attribute type { xsd:string }) & - (element threshold { xsd:double} | attribute threshold { xsd:double }) & - (element scores { list { xsd:string { maxLength = "20" }+ } } | attribute scores { list { xsd:string { maxLength = "20"}+ } } )? - }* & - (element derivative { xsd:int } | attribute derivative { xsd:int } )? - }* & - - element assume_separate { xsd:boolean }? -} diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng deleted file mode 100644 index 350c3cb4a..000000000 --- a/src/relaxng/tallies.rng +++ /dev/null @@ -1,480 +0,0 @@ - - - - - - - - - - - - - - - - - - - regular - - - regular - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - rectilinear - - - rectilinear - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - density - - - density - - - - - - nuclide_density - - - nuclide_density - - - - - - 12 - - - - - 12 - - - - - - - temperature - - - temperature - - - - - - - - - - - - - - - - - - - - - - - cell - cellfrom - cellborn - material - universe - surface - distribcell - mesh - energy - energyout - mu - polar - azimuthal - delayedgroup - energyfunction - meshsurface - cellinstance - - - - - cell - cellfrom - cellborn - material - universe - surface - distribcell - mesh - energy - energyout - mu - polar - azimuthal - delayedgroup - energyfunction - meshsurface - cellinstance - - - - - - - - - - - - - - - - - - - - - - - - energyfunction - - - energyfunction - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - analog - tracklength - collision - - - - - analog - tracklength - collision - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 - - - - - - - - - - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 20 - - - - - - - - - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 50067898ff1180d87e57d47c590e472d3e9ca947 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 13:42:22 -0500 Subject: [PATCH 0959/2654] Replace Muir classes with single muir() Python function --- docs/source/pythonapi/stats.rst | 2 +- include/openmc/distribution.h | 36 +-------- include/openmc/random_dist.h | 17 ---- openmc/stats/univariate.py | 134 ++++++++------------------------ src/distribution.cpp | 29 +------ src/random_dist.cpp | 7 -- tests/unit_tests/test_stats.py | 12 ++- 7 files changed, 45 insertions(+), 192 deletions(-) diff --git a/docs/source/pythonapi/stats.rst b/docs/source/pythonapi/stats.rst index b4f115854..10be9454f 100644 --- a/docs/source/pythonapi/stats.rst +++ b/docs/source/pythonapi/stats.rst @@ -22,7 +22,7 @@ Univariate Probability Distributions openmc.stats.Legendre openmc.stats.Mixture openmc.stats.Normal - openmc.stats.Muir + openmc.stats.muir Angular Distributions --------------------- diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 8403f2c67..d3fe958ca 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -31,7 +31,6 @@ using UPtrDist = unique_ptr; //! \return Unique pointer to distribution UPtrDist distribution_from_xml(pugi::xml_node node); - //============================================================================== //! A discrete distribution (probability mass function) //============================================================================== @@ -99,11 +98,12 @@ public: double a() const { return std::pow(offset_, ninv_); } double b() const { return std::pow(offset_ + span_, ninv_); } double n() const { return 1 / ninv_ - 1; } + private: //! Store processed values in object to allow for faster sampling double offset_; //!< a^(n+1) - double span_; //!< b^(n+1) - a^(n+1) - double ninv_; //!< 1/(n+1) + double span_; //!< b^(n+1) - a^(n+1) + double ninv_; //!< 1/(n+1) }; //============================================================================== @@ -172,35 +172,6 @@ private: double std_dev_; //!< standard deviation [eV] }; -//============================================================================== -//! Muir (fusion) spectrum derived from Normal with extra params e0 is mean -//! std dev is sqrt(4*e0*kt/m) -//============================================================================== - -class Muir : public Distribution { -public: - explicit Muir(pugi::xml_node node); - Muir(double e0, double m_rat, double kt) - : e0_ {e0}, m_rat_ {m_rat}, kt_ {kt} {}; - - //! Sample a value from the distribution - //! \param seed Pseudorandom number seed pointer - //! \return Sampled value - double sample(uint64_t* seed) const; - - double e0() const { return e0_; } - double m_rat() const { return m_rat_; } - double kt() const { return kt_; } - -private: - // example DT fusion m_rat = 5 (D = 2 + T = 3) - // ion temp = 20000 eV - // mean neutron energy 14.08e6 eV - double e0_; //!< mean neutron energy [eV] - double m_rat_; //!< ratio of reactant masses relative to atomic mass unit - double kt_; //!< ion temperature [eV] -}; - //============================================================================== //! Histogram or linear-linear interpolated tabular distribution //============================================================================== @@ -277,7 +248,6 @@ private: distribution_; //!< sub-distributions + cummulative probabilities }; - } // namespace openmc #endif // OPENMC_DISTRIBUTION_H diff --git a/include/openmc/random_dist.h b/include/openmc/random_dist.h index 9bf55aa93..4c9ab3c67 100644 --- a/include/openmc/random_dist.h +++ b/include/openmc/random_dist.h @@ -64,23 +64,6 @@ extern "C" double watt_spectrum(double a, double b, uint64_t* seed); extern "C" double normal_variate(double mean, double std_dev, uint64_t* seed); -//============================================================================== -//! Samples an energy from the Muir (Gaussian) energy-dependent distribution. -//! -//! This is another form of the Gaussian distribution but with more easily -//! modifiable parameters -//! https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS -//! -//! \param e0 peak neutron energy [eV] -//! \param m_rat ratio of the fusion reactants to AMU -//! \param kt the ion temperature of the reactants [eV] -//! \param seed A pointer to the pseudorandom seed -//! \result The sampled outgoing energy -//============================================================================== - -extern "C" double muir_spectrum( - double e0, double m_rat, double kt, uint64_t* seed); - } // namespace openmc #endif // OPENMC_RANDOM_DIST_H diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 5298499ce..28f60de6d 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -2,7 +2,9 @@ from abc import ABC, abstractmethod from collections import defaultdict from collections.abc import Iterable from copy import deepcopy +import math from numbers import Real +from warnings import warn from xml.etree import ElementTree as ET import numpy as np @@ -53,7 +55,9 @@ class Univariate(EqualityMixin, ABC): elif distribution == 'normal': return Normal.from_xml_element(elem) elif distribution == 'muir': - return Muir.from_xml_element(elem) + # Support older files where Muir had its own class + params = [float(x) for x in get_text(elem, 'parameters').split()] + return muir(*params) elif distribution == 'tabular': return Tabular.from_xml_element(elem) elif distribution == 'legendre': @@ -717,119 +721,45 @@ class Normal(Univariate): return cls(*map(float, params)) -class Muir(Univariate): - """Muir energy spectrum. +def muir(e0, m_rat, kt): + """Generate a Muir energy spectrum - The Muir energy spectrum is a Gaussian spectrum, but for - convenience reasons allows the user 3 parameters to define - the distribution, e0 the mean energy of particles, the mass - of reactants m_rat, and the ion temperature kt. + The Muir energy spectrum is a normal distribution, but for convenience + reasons allows the user to specify three parameters to define the + distribution: the mean energy of particles ``e0``, the mass of reactants + ``m_rat``, and the ion temperature ``kt``. + + .. versionadded:: 0.14.0 Parameters ---------- e0 : float - Mean of the Muir distribution in units of eV + Mean of the Muir distribution in [eV] m_rat : float - Ratio of the sum of the masses of the reaction inputs to an - AMU + Ratio of the sum of the masses of the reaction inputs to 1 amu kt : float - Ion temperature for the Muir distribution in units of eV + Ion temperature for the Muir distribution in [eV] - Attributes - ---------- - e0 : float - Mean of the Muir distribution in units of eV - m_rat : float - Ratio of the sum of the masses of the reaction inputs to an - AMU - kt : float - Ion temperature for the Muir distribution in units of eV + Returns + ------- + openmc.stats.Normal + Corresponding normal distribution """ + # https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS + std_dev = math.sqrt(4 * e0 * kt / m_rat) + return Normal(e0, std_dev) - def __init__(self, e0=14.08e6, m_rat = 5., kt = 20000.): - self.e0 = e0 - self.m_rat = m_rat - self.kt = kt - def __len__(self): - return 3 - - @property - def e0(self): - return self._e0 - - @property - def m_rat(self): - return self._m_rat - - @property - def kt(self): - return self._kt - - @e0.setter - def e0(self, e0): - cv.check_type('Muir e0', e0, Real) - cv.check_greater_than('Muir e0', e0, 0.0) - self._e0 = e0 - - @m_rat.setter - def m_rat(self, m_rat): - cv.check_type('Muir m_rat', m_rat, Real) - cv.check_greater_than('Muir m_rat', m_rat, 0.0) - self._m_rat = m_rat - - @kt.setter - def kt(self, kt): - cv.check_type('Muir kt', kt, Real) - cv.check_greater_than('Muir kt', kt, 0.0) - self._kt = kt - - @property - def std_dev(self): - return np.sqrt(4.*self.e0*self.kt/self.m_rat) - - def sample(self, n_samples=1, seed=None): - # Based on LANL report LA-05411-MS - np.random.seed(seed) - return np.random.normal(self.e0, self.std_dev, n_samples) - - def to_xml_element(self, element_name): - """Return XML representation of the Watt distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Watt distribution data - - """ - element = ET.Element(element_name) - element.set("type", "muir") - element.set("parameters", '{} {} {}'.format(self._e0, self._m_rat, self._kt)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate Muir distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Muir - Muir distribution generated from XML element - - """ - params = get_text(elem, 'parameters').split() - return cls(*map(float, params)) +# Retain deprecated name for the time being +def Muir(*args, **kwargs): + # warn of name change + warn( + "The Muir(...) class has been replaced by the muir(...) function and " + "will be removed in a future version of OpenMC. Use muir(...) instead.", + FutureWarning + ) + return muir(*args, **kwargs) class Tabular(Univariate): diff --git a/src/distribution.cpp b/src/distribution.cpp index 901852e0f..c3e1cc1b3 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -165,27 +165,6 @@ double Normal::sample(uint64_t* seed) const return normal_variate(mean_value_, std_dev_, seed); } -//============================================================================== -// Muir implementation -//============================================================================== -Muir::Muir(pugi::xml_node node) -{ - auto params = get_node_array(node, "parameters"); - if (params.size() != 3) { - openmc::fatal_error("Muir energy distribution must have three " - "parameters specified."); - } - - e0_ = params.at(0); - m_rat_ = params.at(1); - kt_ = params.at(2); -} - -double Muir::sample(uint64_t* seed) const -{ - return muir_spectrum(e0_, m_rat_, kt_, seed); -} - //============================================================================== // Tabular implementation //============================================================================== @@ -324,8 +303,10 @@ Mixture::Mixture(pugi::xml_node node) double cumsum = 0.0; for (pugi::xml_node pair : node.children("pair")) { // Check that required data exists - if (!pair.attribute("probability")) fatal_error("Mixture pair element does not have probability."); - if (!pair.child("dist")) fatal_error("Mixture pair element does not have a distribution."); + if (!pair.attribute("probability")) + fatal_error("Mixture pair element does not have probability."); + if (!pair.child("dist")) + fatal_error("Mixture pair element does not have a distribution."); // cummulative sum of probybilities cumsum += std::stod(pair.attribute("probability").value()); @@ -381,8 +362,6 @@ UPtrDist distribution_from_xml(pugi::xml_node node) dist = UPtrDist {new Watt(node)}; } else if (type == "normal") { dist = UPtrDist {new Normal(node)}; - } else if (type == "muir") { - dist = UPtrDist {new Muir(node)}; } else if (type == "discrete") { dist = UPtrDist {new Discrete(node)}; } else if (type == "tabular") { diff --git a/src/random_dist.cpp b/src/random_dist.cpp index c8d2380c3..1aa35a689 100644 --- a/src/random_dist.cpp +++ b/src/random_dist.cpp @@ -46,11 +46,4 @@ double normal_variate(double mean, double standard_deviation, uint64_t* seed) return mean + standard_deviation * z * x; } -double muir_spectrum(double e0, double m_rat, double kt, uint64_t* seed) -{ - // https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS - double sigma = std::sqrt(4. * e0 * kt / m_rat); - return normal_variate(e0, sigma, seed); -} - } // namespace openmc diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index dbf06d0b5..e752c004f 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -376,16 +376,14 @@ def test_muir(): mean = 10.0 mass = 5.0 temp = 20000. - d = openmc.stats.Muir(mean,mass,temp) + d = openmc.stats.muir(mean, mass, temp) + assert isinstance(d, openmc.stats.Normal) elem = d.to_xml_element('energy') - assert elem.attrib['type'] == 'muir' + assert elem.attrib['type'] == 'normal' - d = openmc.stats.Muir.from_xml_element(elem) - assert d.e0 == pytest.approx(mean) - assert d.m_rat == pytest.approx(mass) - assert d.kt == pytest.approx(temp) - assert len(d) == 3 + d = openmc.stats.Univariate.from_xml_element(elem) + assert isinstance(d, openmc.stats.Normal) # sample muir distribution n_samples = 10000 From ca12e3656ee94147bbc8409a452acc6a204c5f97 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Thu, 8 Sep 2022 14:02:47 -0500 Subject: [PATCH 0960/2654] Typo and syntax fixes Co-authored-by: Paul Romano --- docs/source/usersguide/depletion.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index 245070237..c1f9bf94a 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -259,12 +259,12 @@ transport-depletion calculation and follow the same steps from there. will not be simulated. Loading and Generating Microscopic Cross Sections -------------------------------------- +------------------------------------------------- As mentioned earlier, any transport code could be used to calculate one-group microscopic cross sections. The :mod:`openmc.deplete` module provides the :class:`~openmc.deplete.MicroXS` class, which contains methods to read in -pre-caluclated cross sections from a ``.csv`` file or from data arrays:: +pre-calculated cross sections from a ``.csv`` file or from data arrays:: micro_xs = MicroXS.from_csv(micro_xs_path) @@ -352,7 +352,7 @@ normalizing reaction rates: Multiple Materials ~~~~~~~~~~~~~~~~~~ -A transport-independent depletion simulation using ``source-race`` normalization +A transport-independent depletion simulation using ``source-rate`` normalization will calculate reaction rates for each material independently. This can be useful for running many different cases of a particular scenario. A depletion simulation using ``fission-q`` normalization will sum the energy values from From 09de637b3a3795a5188b7ebec4d8095ec5ceba2d Mon Sep 17 00:00:00 2001 From: Josh May <85899979+joshmay1@users.noreply.github.com> Date: Thu, 8 Sep 2022 14:42:28 -0700 Subject: [PATCH 0961/2654] Change copy to match convention Co-authored-by: Paul Romano --- openmc/deplete/nuclide.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py index 962e3e6d6..04e0c26c5 100644 --- a/openmc/deplete/nuclide.py +++ b/openmc/deplete/nuclide.py @@ -682,7 +682,7 @@ class FissionYield(Mapping): self.__class__.__name__, len(self)) def __deepcopy__(self, memo): - result = FissionYield(self.products, np.copy(self.yields)) + result = FissionYield(self.products, self.yields.copy()) memo[id(self)] = result return result From 3c3ce6e2e7bafd0dc8e6b28cc3dd10a852d150c8 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Sep 2022 22:28:54 -0500 Subject: [PATCH 0962/2654] A couple of corrections to the lagrangian interpolation function --- include/openmc/interpolate.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index d02d87ff2..3f5d2d361 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -42,7 +42,7 @@ inline double interpolate_lagrangian( for (int i = 0; i < order + 1; i++) { double numerator {1.0}; double denominator {1.0}; - for (int j = 0; j < order; j++) { + for (int j = 0; j < order + 1; j++) { if (i == j) continue; numerator *= (x - xs[idx + j]); @@ -55,7 +55,7 @@ inline double interpolate_lagrangian( coeffs.begin(), coeffs.end(), ys.begin() + idx, 0.0); } -inline double interpolate(const std::vector& xs, +double interpolate(const std::vector& xs, const std::vector& ys, double x, Interpolation i = Interpolation::lin_lin) { @@ -76,13 +76,13 @@ inline double interpolate(const std::vector& xs, case Interpolation::quadratic: // move back one point if x is in the last interval of the x-grid if (idx == xs.size() - 2 && idx > 0) idx--; - return interpolate_lagrangian(xs, ys, x, idx, 2); + return interpolate_lagrangian(xs, ys, idx, x, 2); case Interpolation::cubic: // if x is not in the first interval of the x-grid, move back one if (idx > 0) idx--; // if the index was the last interval of the x-grid, move it back one more if (idx == xs.size() - 3) idx--; - return interpolate_lagrangian(xs, ys, x, idx, 3); + return interpolate_lagrangian(xs, ys, idx, x, 3); default: fatal_error("Unsupported interpolation"); } From 84276c54bfc1b076591f274f64cd9890acac36d7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Sep 2022 22:29:25 -0500 Subject: [PATCH 0963/2654] Adding additional interpolation types to the constructor --- src/tallies/filter_energyfunc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index a09854e84..0abebf885 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -38,6 +38,10 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) interpolation_ = Interpolation::log_lin; } else if (interpolation == "log-log") { interpolation_ = Interpolation::log_log; + } else if (interpolation == "quadratic") { + interpolation_ = Interpolation::quadratic; + } else if (interpolation == "cubic") { + interpolation_ = Interpolation::cubic; } else { fatal_error(fmt::format( "Found invalid interpolation type '{}' on EnergyFunctionFilter {}.", From ac043cb67a3da93d16761d44d23451f15588b7ba Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Sep 2022 22:37:03 -0500 Subject: [PATCH 0964/2654] Adding checks for minimum number of data points for quadratic/cubic interpolation --- src/tallies/filter_energyfunc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index 0abebf885..170c05262 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -39,8 +39,12 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) } else if (interpolation == "log-log") { interpolation_ = Interpolation::log_log; } else if (interpolation == "quadratic") { + if (energy.size() < 3) + fatal_error(fmt::format("Quadratic interpolation on EnergyFunctionFilter {} requires at least 3 data points.", id())); interpolation_ = Interpolation::quadratic; } else if (interpolation == "cubic") { + if (energy.size() < 4) + fatal_error(fmt::format("Cubic interpolation on EnergyFunctionFilter {} requires at least 4 data points.", id())); interpolation_ = Interpolation::cubic; } else { fatal_error(fmt::format( From 3b00ed3864d2fabff601f31d67994f4828c0af28 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Sep 2022 22:37:57 -0500 Subject: [PATCH 0965/2654] Adding checks for data size based on interpolation type --- openmc/filter.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmc/filter.py b/openmc/filter.py index c1ce573c9..7a85e2d45 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -2058,6 +2058,13 @@ class EnergyFunctionFilter(Filter): def interpolation(self, val): cv.check_type('interpolation', val, str) cv.check_value('interpolation', val, self.INTERPOLATION_SCHEMES.values()) + + if val == 'quadratic' and len(self.energy) < 3: + raise ValueError('Quadratic interpolation requires 3 or more values.') + + if val == 'cubic' and len(self.energy) < 4: + raise ValueError('Cubic interpolation requires 3 or more values.') + self._interpolation = val def to_xml_element(self): From b68e6e96e614546d2cad91e8b023f994bdbd5d74 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Sep 2022 22:38:22 -0500 Subject: [PATCH 0966/2654] Updating tests to include checks for quadratic/cubic interpolation --- .../filter_energyfun/inputs_true.dat | 30 +++++++++++++++++++ .../filter_energyfun/results_true.dat | 2 ++ .../regression_tests/filter_energyfun/test.py | 29 +++++++++++++++--- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat index 8c3db3518..133b3167f 100644 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ b/tests/regression_tests/filter_energyfun/inputs_true.dat @@ -39,6 +39,21 @@ 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 log-linear + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + linear-linear + + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + quadratic + + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + cubic + Am241 (n,gamma) @@ -63,4 +78,19 @@ Am241 (n,gamma) + + 6 + Am241 + (n,gamma) + + + 7 + Am241 + (n,gamma) + + + 8 + Am241 + (n,gamma) + diff --git a/tests/regression_tests/filter_energyfun/results_true.dat b/tests/regression_tests/filter_energyfun/results_true.dat index c0b59680e..0aadac82e 100644 --- a/tests/regression_tests/filter_energyfun/results_true.dat +++ b/tests/regression_tests/filter_energyfun/results_true.dat @@ -6,3 +6,5 @@ 0 b4e2ac84068d2d Am241 (n,gamma) 8.19e-02 2.25e-03 energyfunction nuclide score mean std. dev. 0 dacf88242512ea Am241 (n,gamma) 7.95e-02 2.19e-03 + energyfunction nuclide score mean std. dev. +0 fe168c70d9e078 Am241 (n,gamma) 1.06e-01 2.96e-03 diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index 9c2be7be3..12144c1fd 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -48,9 +48,21 @@ def model(): filt5 = openmc.EnergyFunctionFilter(x, y) filt5.interpolation = 'log-linear' - filters = [filt1, filt3, filt4, filt5] + # define a trapezoidal function for comparison + x = [0.0, 5e6, 1e7, 1.5e7] + y = [0.2, 0.7, 0.7, 0.2] + + filt6 = openmc.EnergyFunctionFilter(x, y) + + filt7 = openmc.EnergyFunctionFilter(x, y) + filt7.interpolation = 'quadratic' + + filt8 = openmc.EnergyFunctionFilter(x, y) + filt8.interpolation = 'cubic' + + filters = [filt1, filt3, filt4, filt5, filt6, filt7, filt8] # Make tallies - tallies = [openmc.Tally() for i in range(5)] + tallies = [openmc.Tally() for _ in range(len(filters) + 1)] for t in tallies: t.scores = ['(n,gamma)'] t.nuclides = ['Am241'] @@ -73,7 +85,7 @@ class FilterEnergyFunHarness(PyAPITestHarness): br_tally = sp.tallies[2] / sp.tallies[1] dataframes_string += br_tally.get_pandas_dataframe().to_string() + '\n' - for t_id in (3, 4, 5): + for t_id in (3, 4, 5, 6): ef_tally = sp.tallies[t_id] dataframes_string += ef_tally.get_pandas_dataframe().to_string() + '\n' @@ -122,7 +134,16 @@ class FilterEnergyFunHarness(PyAPITestHarness): sp_log_lin_filt = sp_log_lin_tally.find_filter(openmc.EnergyFunctionFilter) assert sp_log_lin_filt.interpolation == 'log-linear' + # check that the cubic interpolation provides a higher value + # than linear-linear + contrived_lin_lin_tally = sp.get_tally(id=6) + contrived_quadratic_tally = sp.get_tally(id=7) + contrived_cubic_tally = sp.get_tally(id=8) + + assert all(contrived_lin_lin_tally.mean < contrived_quadratic_tally.mean) + assert all(contrived_lin_lin_tally.mean < contrived_cubic_tally.mean) + def test_filter_energyfun(model): harness = FilterEnergyFunHarness('statepoint.5.h5', model) - harness.main() + harness.main() \ No newline at end of file From 2fa63f33020da122e52460f64f4f4963ebc89209 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Sep 2022 22:41:54 -0500 Subject: [PATCH 0967/2654] Applying clang format --- include/openmc/interpolate.h | 19 ++++++++++--------- src/tallies/filter_energyfunc.cpp | 9 +++++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index 3f5d2d361..8ccdc5bd7 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -34,8 +34,8 @@ inline double interpolate_log_log( return y0 * exp(f * log(y1 / y0)); } -inline double interpolate_lagrangian( - const std::vector& xs, const std::vector& ys, int idx, double x, int order) +inline double interpolate_lagrangian(const std::vector& xs, + const std::vector& ys, int idx, double x, int order) { std::vector coeffs; @@ -55,9 +55,8 @@ inline double interpolate_lagrangian( coeffs.begin(), coeffs.end(), ys.begin() + idx, 0.0); } -double interpolate(const std::vector& xs, - const std::vector& ys, double x, - Interpolation i = Interpolation::lin_lin) +double interpolate(const std::vector& xs, const std::vector& ys, + double x, Interpolation i = Interpolation::lin_lin) { int idx = lower_bound_index(xs.begin(), xs.end(), x); @@ -75,20 +74,22 @@ double interpolate(const std::vector& xs, return interpolate_log_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); case Interpolation::quadratic: // move back one point if x is in the last interval of the x-grid - if (idx == xs.size() - 2 && idx > 0) idx--; + if (idx == xs.size() - 2 && idx > 0) + idx--; return interpolate_lagrangian(xs, ys, idx, x, 2); case Interpolation::cubic: // if x is not in the first interval of the x-grid, move back one - if (idx > 0) idx--; + if (idx > 0) + idx--; // if the index was the last interval of the x-grid, move it back one more - if (idx == xs.size() - 3) idx--; + if (idx == xs.size() - 3) + idx--; return interpolate_lagrangian(xs, ys, idx, x, 3); default: fatal_error("Unsupported interpolation"); } } - } // namespace openmc #endif \ No newline at end of file diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index 170c05262..bf2b2e6cb 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -40,11 +40,16 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) interpolation_ = Interpolation::log_log; } else if (interpolation == "quadratic") { if (energy.size() < 3) - fatal_error(fmt::format("Quadratic interpolation on EnergyFunctionFilter {} requires at least 3 data points.", id())); + fatal_error( + fmt::format("Quadratic interpolation on EnergyFunctionFilter {} " + "requires at least 3 data points.", + id())); interpolation_ = Interpolation::quadratic; } else if (interpolation == "cubic") { if (energy.size() < 4) - fatal_error(fmt::format("Cubic interpolation on EnergyFunctionFilter {} requires at least 4 data points.", id())); + fatal_error(fmt::format("Cubic interpolation on EnergyFunctionFilter " + "{} requires at least 4 data points.", + id())); interpolation_ = Interpolation::cubic; } else { fatal_error(fmt::format( From 476feab519f357bbff1089364540c5f502befd9c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 9 Sep 2022 11:40:15 +0100 Subject: [PATCH 0968/2654] changing the description of tracks arg --- openmc/executor.py | 8 ++++++-- openmc/mesh.py | 30 ++++++++++++++++++++++++++++++ openmc/model/model.py | 8 ++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index 357fa64d5..a73d896ff 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -31,7 +31,9 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, to the number of hardware threads available (or a value set by the :envvar:`OMP_NUM_THREADS` environment variable). tracks : bool, optional - Write tracks for all particles. Defaults to False. + Enables the writing of particles tracks. The number of particle + tracks written to tracks.h5 is limited to 1000 unless + Settings.max_tracks is set. Defaults to False. event_based : None or bool, optional Turns on event-based parallelism if True. If None, the value in the Settings will be used. @@ -245,7 +247,9 @@ def run(particles=None, threads=None, geometry_debug=False, restart_file : str, optional Path to restart file to use tracks : bool, optional - Write tracks for all particles. Defaults to False. + Enables the writing of particles tracks. The number of particle + tracks written to tracks.h5 is limited to 1000 unless + Settings.max_tracks is set. Defaults to False. output : bool Capture OpenMC output from standard out cwd : str, optional diff --git a/openmc/mesh.py b/openmc/mesh.py index 8ac4b1594..9f191e879 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -458,6 +458,36 @@ class RegularMesh(StructuredMesh): string += '{0: <16}{1}{2}\n'.format('\tWidth', '=\t', self._width) return string + @classmethod + def from_universe(cls, universe, dimension=[10, 10, 10], mesh_id=None, name=''): + """Create mesh from an existing openmc universe + + Parameters + ---------- + universe : openmc.Universe + Open used as a template for this mesh + dimension : Iterable of int + The number of mesh cells in each direction. + mesh_id : int + Unique identifier for the mesh + name : str + Name of the mesh + + Returns + ------- + openmc.RegularMesh + RegularMesh instance + + """ + cv.check_type('rectangular lattice', universe, openmc.Universe) + + mesh = cls(mesh_id, name) + mesh.lower_left = universe.bounding_box[0] + mesh.upper_right = universe.bounding_box[1] + mesh.dimension = dimension + + return mesh + @classmethod def from_hdf5(cls, group): mesh_id = int(group.name.split('/')[-1].lstrip('mesh ')) diff --git a/openmc/model/model.py b/openmc/model/model.py index ab99ac978..625094cce 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -256,7 +256,9 @@ class Model: restart_file : str, optional Path to restart file to use tracks : bool, optional - Write tracks for all particles. Defaults to False. + Enables the writing of particles tracks. The number of particle + tracks written to tracks.h5 is limited to 1000 unless + Settings.max_tracks is set. Defaults to False. output : bool Capture OpenMC output from standard out event_based : None or bool, optional @@ -517,7 +519,9 @@ class Model: restart_file : str, optional Path to restart file to use tracks : bool, optional - Write tracks for all particles. Defaults to False. + Enables the writing of particles tracks. The number of particle + tracks written to tracks.h5 is limited to 1000 unless + Settings.max_tracks is set. Defaults to False. output : bool, optional Capture OpenMC output from standard out cwd : str, optional From a17ef0403ab9e64ad5f4d4427c7caad0efa52e9f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 9 Sep 2022 11:42:44 +0100 Subject: [PATCH 0969/2654] removed unrelated code --- openmc/mesh.py | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 9f191e879..8ac4b1594 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -458,36 +458,6 @@ class RegularMesh(StructuredMesh): string += '{0: <16}{1}{2}\n'.format('\tWidth', '=\t', self._width) return string - @classmethod - def from_universe(cls, universe, dimension=[10, 10, 10], mesh_id=None, name=''): - """Create mesh from an existing openmc universe - - Parameters - ---------- - universe : openmc.Universe - Open used as a template for this mesh - dimension : Iterable of int - The number of mesh cells in each direction. - mesh_id : int - Unique identifier for the mesh - name : str - Name of the mesh - - Returns - ------- - openmc.RegularMesh - RegularMesh instance - - """ - cv.check_type('rectangular lattice', universe, openmc.Universe) - - mesh = cls(mesh_id, name) - mesh.lower_left = universe.bounding_box[0] - mesh.upper_right = universe.bounding_box[1] - mesh.dimension = dimension - - return mesh - @classmethod def from_hdf5(cls, group): mesh_id = int(group.name.split('/')[-1].lstrip('mesh ')) From 1cfbd67659292978265468db35a33110585f2b8b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 9 Sep 2022 14:47:11 +0100 Subject: [PATCH 0970/2654] added bbox class method to regular mesh --- openmc/mesh.py | 44 +++++++++++++ .../unit_tests/test_mesh_from_bounding_box.py | 63 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 tests/unit_tests/test_mesh_from_bounding_box.py diff --git a/openmc/mesh.py b/openmc/mesh.py index 8ac4b1594..cdbd4f1be 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -279,6 +279,7 @@ class StructuredMesh(MeshBase): return vtk_grid + class RegularMesh(StructuredMesh): """A regular Cartesian mesh in one, two, or three dimensions @@ -509,6 +510,49 @@ class RegularMesh(StructuredMesh): return mesh + @classmethod + def from_bounding_box( + cls, + bounding_box, + dimension=[100, 100, 100], + mesh_id=None, + name='' + ): + """Create mesh from an existing openmc cell, region, universe or + geometry by making use of the objects bounding box property. + + Parameters + ---------- + bounding_box : {openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry} + The object passed in will be used as a template for this mesh. The + bounding_box of the property of the object passed will be used to + set the lower_left and upper_right of the mesh instance + dimension : Iterable of int + The number of mesh cells in each direction. + mesh_id : int + Unique identifier for the mesh + name : str + Name of the mesh + + Returns + ------- + openmc.RegularMesh + RegularMesh instance + + """ + cv.check_type( + "bounding_box", + bounding_box, + (openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry), + ) + + mesh = cls(mesh_id, name) + mesh.lower_left = bounding_box.bounding_box[0] + mesh.upper_right = bounding_box.bounding_box[1] + mesh.dimension = dimension + + return mesh + def to_xml_element(self): """Return XML representation of the mesh diff --git a/tests/unit_tests/test_mesh_from_bounding_box.py b/tests/unit_tests/test_mesh_from_bounding_box.py new file mode 100644 index 000000000..4f3d99128 --- /dev/null +++ b/tests/unit_tests/test_mesh_from_bounding_box.py @@ -0,0 +1,63 @@ +import numpy as np +import openmc +import pytest + + +def test_mesh_from_cell(): + """Tests a RegularMesh can be made from a Cell and the specified dimensions + are propagated through. Cell is not centralized""" + surface = openmc.Sphere(r=10, x0=2, y0=3, z0=5) + cell = openmc.Cell(region=-surface) + + mesh = openmc.RegularMesh.from_bounding_box(cell, dimension=[7, 11, 13]) + assert isinstance(mesh, openmc.RegularMesh) + assert np.array_equal(mesh.dimension, (7, 11, 13)) + assert np.array_equal(mesh.lower_left, cell.bounding_box[0]) + assert np.array_equal(mesh.upper_right, cell.bounding_box[1]) + + +def test_mesh_from_region(): + """Tests a RegularMesh can be made from a Region and the default dimensions + are propagated through. Region is not centralized""" + surface = openmc.Sphere(r=1, x0=-5, y0=-3, z0=-2) + region = -surface + + mesh = openmc.RegularMesh.from_bounding_box(region) + assert isinstance(mesh, openmc.RegularMesh) + assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values + assert np.array_equal(mesh.lower_left, region.bounding_box[0]) + assert np.array_equal(mesh.upper_right, region.bounding_box[1]) + + +def test_mesh_from_universe(): + """Tests a RegularMesh can be made from a Universe and the default dimensions + are propagated through. Universe is centralized""" + surface = openmc.Sphere(r=42) + cell = openmc.Cell(region=-surface) + universe = openmc.Universe(cells=[cell]) + + mesh = openmc.RegularMesh.from_bounding_box(universe) + assert isinstance(mesh, openmc.RegularMesh) + assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values + assert np.array_equal(mesh.lower_left, universe.bounding_box[0]) + assert np.array_equal(mesh.upper_right, universe.bounding_box[1]) + + +def test_mesh_from_geometry(): + """Tests a RegularMesh can be made from a Geometry and the default dimensions + are propagated through. Geometry is centralized""" + surface = openmc.Sphere(r=42) + cell = openmc.Cell(region=-surface) + universe = openmc.Universe(cells=[cell]) + geometry = openmc.Geometry(universe) + + mesh = openmc.RegularMesh.from_bounding_box(geometry) + assert isinstance(mesh, openmc.RegularMesh) + assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values + assert np.array_equal(mesh.lower_left, geometry.bounding_box[0]) + assert np.array_equal(mesh.upper_right, geometry.bounding_box[1]) + + +def test_error_from_unsupported_object(): + with pytest.raises(TypeError): + openmc.RegularMesh.from_bounding_box("vacuum energy") From abc2c7cd7a00615f87245765193eabefb0c7d8cb Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 9 Sep 2022 16:45:49 +0100 Subject: [PATCH 0971/2654] renamed dounding_box to domain, review suggestion --- openmc/mesh.py | 16 ++++++++-------- ..._bounding_box.py => test_mesh_from_domain.py} | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) rename tests/unit_tests/{test_mesh_from_bounding_box.py => test_mesh_from_domain.py} (87%) diff --git a/openmc/mesh.py b/openmc/mesh.py index cdbd4f1be..6fefb7b4c 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -511,9 +511,9 @@ class RegularMesh(StructuredMesh): return mesh @classmethod - def from_bounding_box( + def from_domain( cls, - bounding_box, + domain, dimension=[100, 100, 100], mesh_id=None, name='' @@ -523,9 +523,9 @@ class RegularMesh(StructuredMesh): Parameters ---------- - bounding_box : {openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry} + domain : {openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry} The object passed in will be used as a template for this mesh. The - bounding_box of the property of the object passed will be used to + domain of the property of the object passed will be used to set the lower_left and upper_right of the mesh instance dimension : Iterable of int The number of mesh cells in each direction. @@ -541,14 +541,14 @@ class RegularMesh(StructuredMesh): """ cv.check_type( - "bounding_box", - bounding_box, + "domain", + domain, (openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry), ) mesh = cls(mesh_id, name) - mesh.lower_left = bounding_box.bounding_box[0] - mesh.upper_right = bounding_box.bounding_box[1] + mesh.lower_left = domain.bounding_box[0] + mesh.upper_right = domain.bounding_box[1] mesh.dimension = dimension return mesh diff --git a/tests/unit_tests/test_mesh_from_bounding_box.py b/tests/unit_tests/test_mesh_from_domain.py similarity index 87% rename from tests/unit_tests/test_mesh_from_bounding_box.py rename to tests/unit_tests/test_mesh_from_domain.py index 4f3d99128..2140d5625 100644 --- a/tests/unit_tests/test_mesh_from_bounding_box.py +++ b/tests/unit_tests/test_mesh_from_domain.py @@ -9,7 +9,7 @@ def test_mesh_from_cell(): surface = openmc.Sphere(r=10, x0=2, y0=3, z0=5) cell = openmc.Cell(region=-surface) - mesh = openmc.RegularMesh.from_bounding_box(cell, dimension=[7, 11, 13]) + mesh = openmc.RegularMesh.from_domain(cell, dimension=[7, 11, 13]) assert isinstance(mesh, openmc.RegularMesh) assert np.array_equal(mesh.dimension, (7, 11, 13)) assert np.array_equal(mesh.lower_left, cell.bounding_box[0]) @@ -22,7 +22,7 @@ def test_mesh_from_region(): surface = openmc.Sphere(r=1, x0=-5, y0=-3, z0=-2) region = -surface - mesh = openmc.RegularMesh.from_bounding_box(region) + mesh = openmc.RegularMesh.from_domain(region) assert isinstance(mesh, openmc.RegularMesh) assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values assert np.array_equal(mesh.lower_left, region.bounding_box[0]) @@ -36,7 +36,7 @@ def test_mesh_from_universe(): cell = openmc.Cell(region=-surface) universe = openmc.Universe(cells=[cell]) - mesh = openmc.RegularMesh.from_bounding_box(universe) + mesh = openmc.RegularMesh.from_domain(universe) assert isinstance(mesh, openmc.RegularMesh) assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values assert np.array_equal(mesh.lower_left, universe.bounding_box[0]) @@ -51,7 +51,7 @@ def test_mesh_from_geometry(): universe = openmc.Universe(cells=[cell]) geometry = openmc.Geometry(universe) - mesh = openmc.RegularMesh.from_bounding_box(geometry) + mesh = openmc.RegularMesh.from_domain(geometry) assert isinstance(mesh, openmc.RegularMesh) assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values assert np.array_equal(mesh.lower_left, geometry.bounding_box[0]) @@ -60,4 +60,4 @@ def test_mesh_from_geometry(): def test_error_from_unsupported_object(): with pytest.raises(TypeError): - openmc.RegularMesh.from_bounding_box("vacuum energy") + openmc.RegularMesh.from_domain("vacuum energy") From 88c2ff9198b1ba2671ad614278170f433dd7480f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 9 Sep 2022 16:48:05 +0100 Subject: [PATCH 0972/2654] [skip ci] one too many domains --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 6fefb7b4c..a4c50a608 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -525,7 +525,7 @@ class RegularMesh(StructuredMesh): ---------- domain : {openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry} The object passed in will be used as a template for this mesh. The - domain of the property of the object passed will be used to + bounding box of the property of the object passed will be used to set the lower_left and upper_right of the mesh instance dimension : Iterable of int The number of mesh cells in each direction. From 21f1d5142bfc9a9ebbb452a347af7b289779d932 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 9 Sep 2022 17:08:40 +0100 Subject: [PATCH 0973/2654] renamed tests to reg_mesh prefix --- tests/unit_tests/test_mesh_from_domain.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit_tests/test_mesh_from_domain.py b/tests/unit_tests/test_mesh_from_domain.py index 2140d5625..ce27288ad 100644 --- a/tests/unit_tests/test_mesh_from_domain.py +++ b/tests/unit_tests/test_mesh_from_domain.py @@ -3,7 +3,7 @@ import openmc import pytest -def test_mesh_from_cell(): +def test_reg_mesh_from_cell(): """Tests a RegularMesh can be made from a Cell and the specified dimensions are propagated through. Cell is not centralized""" surface = openmc.Sphere(r=10, x0=2, y0=3, z0=5) @@ -16,7 +16,7 @@ def test_mesh_from_cell(): assert np.array_equal(mesh.upper_right, cell.bounding_box[1]) -def test_mesh_from_region(): +def test_reg_mesh_from_region(): """Tests a RegularMesh can be made from a Region and the default dimensions are propagated through. Region is not centralized""" surface = openmc.Sphere(r=1, x0=-5, y0=-3, z0=-2) @@ -29,7 +29,7 @@ def test_mesh_from_region(): assert np.array_equal(mesh.upper_right, region.bounding_box[1]) -def test_mesh_from_universe(): +def test_reg_mesh_from_universe(): """Tests a RegularMesh can be made from a Universe and the default dimensions are propagated through. Universe is centralized""" surface = openmc.Sphere(r=42) @@ -43,7 +43,7 @@ def test_mesh_from_universe(): assert np.array_equal(mesh.upper_right, universe.bounding_box[1]) -def test_mesh_from_geometry(): +def test_reg_mesh_from_geometry(): """Tests a RegularMesh can be made from a Geometry and the default dimensions are propagated through. Geometry is centralized""" surface = openmc.Sphere(r=42) From b8ffbe000ba8cc002f752a09f192bcb18183d857 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 10 Sep 2022 00:07:31 +0000 Subject: [PATCH 0974/2654] Add a basic cache system for the burnable material reaction rates tallies --- openmc/deplete/helpers.py | 43 ++++++++++++++++++++++++++++--- openmc/deplete/openmc_operator.py | 3 +++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 3a7928a52..b21e58e21 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -147,6 +147,7 @@ class DirectReactionRateHelper(ReactionRateHelper): def __init__(self, n_nuc, n_react): super().__init__(n_nuc, n_react) self._rate_tally = None + self._rate_tally_means = None # Automatically pre-calculate reaction rates for depletion openmc.lib.settings.need_depletion_rx = True @@ -176,6 +177,18 @@ class DirectReactionRateHelper(ReactionRateHelper): self._rate_tally.scores = scores self._rate_tally.filters = [MaterialFilter(materials)] + @property + def rate_tally_means(self): + # If the mean cache is empty, fill it once with this transport cycle's results + if self._rate_tally_means is None: + self._rate_tally_means = self._rate_tally.mean + return self._rate_tally_means + + def reset_tally_means(self): + """Reset the cached mean rate tallies. This step must be performed after each transport cycle + """ + self._rate_tally_means = None + def get_material_rates(self, mat_id, nuc_index, react_index): """Return an array of reaction rates for a material @@ -196,7 +209,7 @@ class DirectReactionRateHelper(ReactionRateHelper): reaction rates in this material """ self._results_cache.fill(0.0) - full_tally_res = self._rate_tally.mean[mat_id] + full_tally_res = self.rate_tally_means[mat_id] for i_tally, (i_nuc, i_react) in enumerate( product(nuc_index, react_index)): self._results_cache[i_nuc, i_react] = full_tally_res[i_tally] @@ -278,6 +291,7 @@ class FluxCollapseHelper(ReactionRateHelper): EnergyFilter(self._energies) ] self._flux_tally.scores = ['flux'] + self._flux_tally_means_cache = None # Create reaction rate tally if self._reactions_direct: @@ -285,9 +299,32 @@ class FluxCollapseHelper(ReactionRateHelper): self._rate_tally.writable = False self._rate_tally.scores = self._reactions_direct self._rate_tally.filters = [MaterialFilter(materials)] + self._rate_tally_means_cache = None if self._nuclides_direct is not None: self._rate_tally.nuclides = self._nuclides_direct + @property + def rate_tally_means(self): + # If the mean cache is empty, fill it once with this transport cycle's results + if self._rate_tally_means_cache is None: + self._rate_tally_means_cache = self._rate_tally.mean + return self._rate_tally_means_cache + + @property + def flux_tally_means(self): + # If the mean cache is empty, fill it once for this transport cycle's results + if self._flux_tally_means_cache is None: + self._flux_tally_means_cache = self._flux_tally.mean + return self._flux_tally_means_cache + + def reset_tally_means(self): + """Reset the cached mean rate and flux tallies. This step must be performed after each transport cycle + """ + self._flux_tally_means_cache = None + if self._reactions_direct: + self._rate_tally_means_cache = None + + def get_material_rates(self, mat_index, nuc_index, react_index): """Return an array of reaction rates for a material @@ -312,14 +349,14 @@ class FluxCollapseHelper(ReactionRateHelper): # Get flux for specified material shape = (len(self._materials), len(self._energies) - 1) - mean_value = self._flux_tally.mean.reshape(shape) + mean_value = self.flux_tally_means.reshape(shape) flux = mean_value[mat_index] # Get direct reaction rates if self._reactions_direct: nuclides_direct = self._rate_tally.nuclides shape = (len(nuclides_direct), len(self._reactions_direct)) - rx_rates = self._rate_tally.mean[mat_index].reshape(shape) + rx_rates = self.rate_tally_means[mat_index].reshape(shape) mat = self._materials[mat_index] diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index ee569bf71..76f8e964e 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -507,6 +507,9 @@ class OpenMCOperator(TransportOperator): fission_ind = rates.index_rx.get("fission") + # Reset the cached material reaction rates tallies + self._rate_helper.reset_tally_means() + # Extract results for i, mat in enumerate(self.local_mats): # Get tally index From 9ec20b507a1ae691ebd0666e9214ffb4b85fbfa2 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 10 Sep 2022 00:35:37 +0000 Subject: [PATCH 0975/2654] Rename cache variable --- openmc/deplete/helpers.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index b21e58e21..fd1207280 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -147,7 +147,6 @@ class DirectReactionRateHelper(ReactionRateHelper): def __init__(self, n_nuc, n_react): super().__init__(n_nuc, n_react) self._rate_tally = None - self._rate_tally_means = None # Automatically pre-calculate reaction rates for depletion openmc.lib.settings.need_depletion_rx = True @@ -176,18 +175,20 @@ class DirectReactionRateHelper(ReactionRateHelper): self._rate_tally.writable = False self._rate_tally.scores = scores self._rate_tally.filters = [MaterialFilter(materials)] + self._rate_tally_means_cache = None @property def rate_tally_means(self): # If the mean cache is empty, fill it once with this transport cycle's results - if self._rate_tally_means is None: - self._rate_tally_means = self._rate_tally.mean - return self._rate_tally_means + if self._rate_tally_means_cache is None: + self._rate_tally_means_cache = self._rate_tally.mean + return self._rate_tally_means_cache def reset_tally_means(self): - """Reset the cached mean rate tallies. This step must be performed after each transport cycle + """Reset the cached mean rate tallies. + This step must be performed after each transport cycle """ - self._rate_tally_means = None + self._rate_tally_means_cache = None def get_material_rates(self, mat_id, nuc_index, react_index): """Return an array of reaction rates for a material @@ -318,7 +319,8 @@ class FluxCollapseHelper(ReactionRateHelper): return self._flux_tally_means_cache def reset_tally_means(self): - """Reset the cached mean rate and flux tallies. This step must be performed after each transport cycle + """Reset the cached mean rate and flux tallies. + This step must be performed after each transport cycle """ self._flux_tally_means_cache = None if self._reactions_direct: From c4b5f067cdab8f0177e69135da6d58bc7d1808fc Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 10 Sep 2022 00:56:29 +0000 Subject: [PATCH 0976/2654] Add blank reset function to IndependentRateHelper --- openmc/deplete/independent_operator.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index 200bc195e..7f0bf5fb2 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -303,6 +303,10 @@ class IndependentOperator(OpenMCOperator): """Unused in this case""" pass + def reset_tally_means(self): + """Unused in this case""" + pass + def get_material_rates(self, mat_id, nuc_index, react_index): """Return 2D array of [nuclide, reaction] reaction rates From 15a75284f4c50d6543055b7621d5151f240f5bfa Mon Sep 17 00:00:00 2001 From: yardasol Date: Sun, 11 Sep 2022 14:03:23 -0500 Subject: [PATCH 0977/2654] make statements about multiple materials and env vars more precise --- docs/source/usersguide/depletion.rst | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index b0d8ff454..ca4228efa 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -298,10 +298,10 @@ units of barns:: If you are runnnig :meth:`~openmc.deplete.MicroXS.from_model()` on a cluster that does not share local filesystems across nodes, you'll need to set an -environment variable so that each MPI process knows where to store output files -used to calculate the microscopic cross sections. In order of priority, they -are `TMPDIR`. `TEMP`, and `TMP`. Users interested in further details can read -the `relevant docpage on the tempfile pacakge `_ +environment variable pointing to a directory accessible by MPI so that each +MPI process knows where to store output files used to calculate the microscopic +cross sections. In order of priority, they are `TMPDIR`. `TEMP`, and `TMP`. +Users interested in further details can read the `relevant docpage on the tempfile pacakge `_ Caveats @@ -325,7 +325,7 @@ normalizing reaction rates: the cross sections by the ``source-rate``. 2. ``fission-q`` normalization, which uses the ``power`` or ``power_density`` provided by the time integrator to obtain reaction rates by computing a value - for the flux based on this power. The general equation for the flux is + for the flux based on this power. The equation we use for this calculation is .. math:: :label: fission-q @@ -354,11 +354,13 @@ Multiple Materials A transport-independent depletion simulation using ``source-race`` normalization will calculate reaction rates for each material independently. This can be -useful for running many different cases of a particular scenario. A depletion -simulation using ``fission-q`` normalization will sum the energy values from -each material into :math:`Q` in Equation :math:numref:`fission-q`, which is -used to normalize the reaction rates for all materials. This behavior may -change in the future. +useful for running many different cases of a particular scenario. A +transport-independent depletion simulation using ``fission-q`` normalization +will sum the fission energy values across all materials into :math:`Q_i` in +Equation :math:numref:`fission-q`, and Equation :math:numref:`fission-q` +provides the flux we use to calculate the reaction rates in each material. +This can be useful for running a scenario with multiple depletable materials +that are part of the same reactor. This behavior may change in the future. Time integration ~~~~~~~~~~~~~~~~ From f5625c922990614f27d01ff3a141b4bcfcda37f6 Mon Sep 17 00:00:00 2001 From: josh Date: Mon, 12 Sep 2022 17:08:41 +0000 Subject: [PATCH 0978/2654] Update documentation and formatting --- openmc/deplete/helpers.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index fd1207280..e51106544 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -179,6 +179,8 @@ class DirectReactionRateHelper(ReactionRateHelper): @property def rate_tally_means(self): + """The mean results of the tally of every material's reaction rates for this cycle + """ # If the mean cache is empty, fill it once with this transport cycle's results if self._rate_tally_means_cache is None: self._rate_tally_means_cache = self._rate_tally.mean @@ -186,7 +188,9 @@ class DirectReactionRateHelper(ReactionRateHelper): def reset_tally_means(self): """Reset the cached mean rate tallies. - This step must be performed after each transport cycle + .. note:: + + This step must be performed after each transport cycle """ self._rate_tally_means_cache = None @@ -306,6 +310,8 @@ class FluxCollapseHelper(ReactionRateHelper): @property def rate_tally_means(self): + """The mean results of the tally of every material's reaction rates for this cycle + """ # If the mean cache is empty, fill it once with this transport cycle's results if self._rate_tally_means_cache is None: self._rate_tally_means_cache = self._rate_tally.mean @@ -320,13 +326,14 @@ class FluxCollapseHelper(ReactionRateHelper): def reset_tally_means(self): """Reset the cached mean rate and flux tallies. - This step must be performed after each transport cycle + .. note:: + + This step must be performed after each transport cycle """ self._flux_tally_means_cache = None if self._reactions_direct: self._rate_tally_means_cache = None - def get_material_rates(self, mat_index, nuc_index, react_index): """Return an array of reaction rates for a material From ab665fb4563be28b6cfd365634049c90f133f485 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 15 Jul 2022 21:35:59 +0200 Subject: [PATCH 0979/2654] fix typo Co-authored-by: Paul Romano --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6af9643cd..be56f1c12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) option(OPENMC_USE_MPI "Enable MPI" OFF) -option(OPENMC_USE_MCPL "Enable MPCPL" OFF) +option(OPENMC_USE_MCPL "Enable MCPL" OFF) #=============================================================================== # Set a default build configuration if not explicitly specified From 71568d4f4bffa21a2a9c26725619cd180a9a59ff Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 9 Aug 2022 08:12:19 +0200 Subject: [PATCH 0980/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- include/openmc/source.h | 30 ++--------- src/settings.cpp | 2 +- src/source.cpp | 116 +++++++++++++++++----------------------- 3 files changed, 53 insertions(+), 95 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index 4d7ec104a..5c2dae931 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -96,7 +96,9 @@ class FileSource : public Source { public: // Constructors explicit FileSource(std::string path); - +#ifdef OPENMC_MCPL + explicit FileSource(mcpl_file_t mcpl_file); +#endif // Methods SourceSite sample(uint64_t* seed) const override; @@ -104,32 +106,6 @@ private: vector sites_; //!< Source sites from a file }; -#ifdef OPENMC_MCPL -//============================================================================== -// MCPL-file input source -//============================================================================== -class MCPLFileSource : public Source { -public: - // Constructors, destructors - MCPLFileSource(std::string path); - ~MCPLFileSource(); - - // Methods - //! Sample from the external source distribution - //! \param[inout] seed Pseudorandom seed pointer - //! \return Site read from MCPL-file - SourceSite sample(uint64_t* seed) const; - -private: - SourceSite read_single_particle() const; - void read_source_bank(vector &sites_); - - vector sites_; //!(path)); + model::external_sources.push_back(make_unique(mcpl_open_file(path.c_str()))); #endif } else if (check_for_node(node, "library")) { // Get shared library path and parameters diff --git a/src/source.cpp b/src/source.cpp index 9b426c3cf..9cdf1632b 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -283,6 +283,54 @@ FileSource::FileSource(std::string path) file_close(file_id); } +#ifdef OPENMC_MCPL +FileSource::FileSource(mcpl_file_t mcpl_file) +{ + //do checks on the mcpl_file to see if particles are many enough. + // should model this on the example source shown in the docs. + size_t n_sites=mcpl_hdr_nparticles(mcpl_file); + + sites_.resize(n_sites); + for (int i=0;ipdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { + mcpl_particle=mcpl_read(mcpl_file); + //should check for file exhaustion This could happen if particles are other than + //neutrons or photons + } + + if(mcpl_particle->pdgcode==2112) { + site_.particle=ParticleType::neutron; + } else if (mcpl_particle->pdgcode==22) { + site_.particle=ParticleType::photon; + } + + //particle is good, convert to openmc-formalism + site_.r.x=mcpl_particle->position[0]; + site_.r.y=mcpl_particle->position[1]; + site_.r.z=mcpl_particle->position[2]; + + site_.u.x=mcpl_particle->direction[0]; + site_.u.y=mcpl_particle->direction[1]; + site_.u.z=mcpl_particle->direction[2]; + + //mcpl stores kinetic energy in MeV + site_.E=mcpl_particle->ekin*1e6; + //mcpl stores time in ms + site_.time=mcpl_particle->time*1e-3; + site_.wgt=mcpl_particle->weight; + site_.delayed_group=0; + sites_[i]=site_; + } + mcpl_close_file(mcpl_file); +} +#endif //OPENMC_MCPL + SourceSite FileSource::sample(uint64_t* seed) const { size_t i_site = sites_.size() * prn(seed); @@ -366,73 +414,7 @@ MCPLFileSource::MCPLFileSource(std::string path) read_source_bank(sites_); } - -MCPLFileSource::~MCPLFileSource(){ - mcpl_close_file(mcpl_file); -} - -SourceSite MCPLFileSource::sample(uint64_t* seed) const -{ - size_t i_site = sites_.size() * prn(seed); - return sites_[i_site]; -} - -void MCPLFileSource::read_source_bank(vector &sites_) -{ - sites_.resize(n_sites); - for (int i=0;ipdgcode; - while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { - mcpl_particle=mcpl_read(mcpl_file); - pdg=mcpl_particle->pdgcode; - //should check for file exhaustion. This could happen if particles are other than - //neutrons, photons, electrons, or positrons. - } - - switch(pdg){ - case 2112: - omc_particle_.particle=ParticleType::neutron; - break; - case 22: - omc_particle_.particle=ParticleType::photon; - break; - case 11: - omc_particle_.particle=ParticleType::electron; - break; - case -11: - omc_particle_.particle=ParticleType::positron; - break; - } - - //particle is good, convert to openmc-formalism - omc_particle_.r.x=mcpl_particle->position[0]; - omc_particle_.r.y=mcpl_particle->position[1]; - omc_particle_.r.z=mcpl_particle->position[2]; - - omc_particle_.u.x=mcpl_particle->direction[0]; - omc_particle_.u.y=mcpl_particle->direction[1]; - omc_particle_.u.z=mcpl_particle->direction[2]; - - //mcpl stores kinetic energy in MeV - omc_particle_.E=mcpl_particle->ekin*1e6; - //mcpl stores time in ms - omc_particle_.time=mcpl_particle->time*1e-3; - omc_particle_.wgt=mcpl_particle->weight; - omc_particle_.delayed_group=0; - return omc_particle_; -} -#endif //OPENMC_MCPL +#endif //============================================================================== // Non-member functions From 73a391daef86e3a93c0c7180d9ff7f670afff240 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 0981/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- include/openmc/state_point.h | 9 +++ src/state_point.cpp | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 5ada2bf88..2d92c935a 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -9,6 +9,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { void load_state_point(); @@ -21,5 +25,10 @@ void write_tally_results_nr(hid_t file_id); void restart_set_keff(); void write_unstructured_mesh_results(); +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename_, bool surf_source_bank = false); +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); +#endif + } // namespace openmc #endif // OPENMC_STATE_POINT_H diff --git a/src/state_point.cpp b/src/state_point.cpp index 9ea045915..babd670a2 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -28,6 +28,10 @@ #include "openmc/timer.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) @@ -598,6 +602,45 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } +void write_mcpl_point(const char *filename, bool surf_source_bank) +{ + std::string filename_; + if (filename) { + filename_ = filename; + } else { + // Determine width for zero padding + int w = std::to_string(settings::n_max_batches).size(); + + filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, + simulation::current_batch, w); + } + + mcpl_outfile_t file_id; + + std::string line; + if (mpi::master) { + // this must be rewritten: file_open is h5-specific + file_id = mcpl_create_outfile(filename_.c_str()); + //write_attribute(file_id, "filetype", "source"); + //write header stuff (oopy in xml-files as binary blobs for instance)) + if (VERSION_DEV){ + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}-development"); + } else { + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}"); + } + mcpl_hdr_set_srcname(file_id,line.c_str()); + } + + write_mcpl_source_bank(file_id, surf_source_bank); + + if (mpi::master) { + //change this - this is h5 specific + mcpl_closeandgzip_outfile(file_id); + } + +} + + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); @@ -714,6 +757,88 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) +{ + int64_t dims_size = settings::n_particles; + int64_t count_size = simulation::work_per_rank; + + // Set vectors for source bank and starting bank index of each process + vector* bank_index = &simulation::work_index; + vector* source_bank = &simulation::source_bank; + vector surf_source_index_vector; + vector surf_source_bank_vector; + + if(surf_source_bank) { + surf_source_index_vector = calculate_surf_source_size(); + dims_size = surf_source_index_vector[mpi::n_procs]; + count_size = simulation::surf_source_bank.size(); + + bank_index = &surf_source_index_vector; + + // Copy data in a SharedArray into a vector. + surf_source_bank_vector.resize(count_size); + surf_source_bank_vector.assign(simulation::surf_source_bank.data(), + simulation::surf_source_bank.data() + count_size); + source_bank = &surf_source_bank_vector; + } + + if (mpi::master) { + //write particles from the master node + //loop over the other nodes and receive data - then write those. + for (int i = 0; i < mpi::n_procs; ++i) { +#ifdef OPENMC_MPI + if (i>0) + MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + mpi::intracomm, MPI_STATUS_IGNORE); +#endif + //now write the source_banke data again. + for (vector::iterator _site=source_bank->begin(); _site!=source_bank->end();_site++){ + //particle is now at the iterator + //write it to the mcpl-file + mcpl_particle_t p; + p.position[0]=_site->r.x; + p.position[1]=_site->r.y; + p.position[2]=_site->r.z; + + p.direction[0]=_site->u.x; + p.direction[1]=_site->u.y; + p.direction[2]=_site->u.x; + + //mcpl stores kinetic energy in MeV + p.ekin=_site->E*1e-6; + + p.time=_site->time*1e3; + + p.weight=_site->wgt; + + switch(_site->particle){ + case ParticleType::neutron: + p.pdgcode=2112; + break; + case ParticleType::photon: + p.pdgcode=22; + break; + case ParticleType::electron: + p.pdgcode=11; + break; + case ParticleType::positron: + p.pdgcode=-11; + break; + } + + mcpl_add_particle(file_id,&p); + } + } + } else { +#ifdef OPENMC_MPI + MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + mpi::intracomm); +#endif + } + +} + + // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) { From d07223bf681e5d6e1d7cbde0dac6f97059a12767 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 23:06:19 +0200 Subject: [PATCH 0982/2654] add a trigger to simulation control --- src/simulation.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/simulation.cpp b/src/simulation.cpp index b70535c33..05c8c0450 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -406,6 +406,13 @@ void finalize_batch() auto filename = settings::path_output + "surface_source.h5"; write_source_point(filename.c_str(), true); } + + if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + auto filename = settings::path_output + ".mcpl"; + write_mcplt_source_point(filename.c_str(), true); + } + + } void initialize_generation() From 55f2be19e6c0ef51d7a7946ac15a9f2df51da6da Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 16 Sep 2022 16:07:22 +0200 Subject: [PATCH 0983/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- src/source.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/source.cpp b/src/source.cpp index 626d02f9d..21522438c 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -426,6 +426,7 @@ MCPLFileSource::MCPLFileSource(std::string path) read_source_bank(sites_); } +<<<<<<< HEAD MCPLFileSource::~MCPLFileSource(){ mcpl_close_file(mcpl_file); @@ -495,6 +496,9 @@ SourceSite MCPLFileSource::read_single_particle() const #endif //OPENMC_MCPL ======= >>>>>>> 380cfc150b449ef56debb5261caa010a52c42bdd +======= +#endif +>>>>>>> 71568d4f4 (refactor MCPL file read part of FileSource) //============================================================================== // Non-member functions From f0af56b181555f52d05f245240846f4ce8eadcaa Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 0984/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- include/openmc/state_point.h | 9 +++ src/state_point.cpp | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 5ada2bf88..2d92c935a 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -9,6 +9,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { void load_state_point(); @@ -21,5 +25,10 @@ void write_tally_results_nr(hid_t file_id); void restart_set_keff(); void write_unstructured_mesh_results(); +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename_, bool surf_source_bank = false); +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); +#endif + } // namespace openmc #endif // OPENMC_STATE_POINT_H diff --git a/src/state_point.cpp b/src/state_point.cpp index 9ea045915..babd670a2 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -28,6 +28,10 @@ #include "openmc/timer.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) @@ -598,6 +602,45 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } +void write_mcpl_point(const char *filename, bool surf_source_bank) +{ + std::string filename_; + if (filename) { + filename_ = filename; + } else { + // Determine width for zero padding + int w = std::to_string(settings::n_max_batches).size(); + + filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, + simulation::current_batch, w); + } + + mcpl_outfile_t file_id; + + std::string line; + if (mpi::master) { + // this must be rewritten: file_open is h5-specific + file_id = mcpl_create_outfile(filename_.c_str()); + //write_attribute(file_id, "filetype", "source"); + //write header stuff (oopy in xml-files as binary blobs for instance)) + if (VERSION_DEV){ + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}-development"); + } else { + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}"); + } + mcpl_hdr_set_srcname(file_id,line.c_str()); + } + + write_mcpl_source_bank(file_id, surf_source_bank); + + if (mpi::master) { + //change this - this is h5 specific + mcpl_closeandgzip_outfile(file_id); + } + +} + + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); @@ -714,6 +757,88 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) +{ + int64_t dims_size = settings::n_particles; + int64_t count_size = simulation::work_per_rank; + + // Set vectors for source bank and starting bank index of each process + vector* bank_index = &simulation::work_index; + vector* source_bank = &simulation::source_bank; + vector surf_source_index_vector; + vector surf_source_bank_vector; + + if(surf_source_bank) { + surf_source_index_vector = calculate_surf_source_size(); + dims_size = surf_source_index_vector[mpi::n_procs]; + count_size = simulation::surf_source_bank.size(); + + bank_index = &surf_source_index_vector; + + // Copy data in a SharedArray into a vector. + surf_source_bank_vector.resize(count_size); + surf_source_bank_vector.assign(simulation::surf_source_bank.data(), + simulation::surf_source_bank.data() + count_size); + source_bank = &surf_source_bank_vector; + } + + if (mpi::master) { + //write particles from the master node + //loop over the other nodes and receive data - then write those. + for (int i = 0; i < mpi::n_procs; ++i) { +#ifdef OPENMC_MPI + if (i>0) + MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + mpi::intracomm, MPI_STATUS_IGNORE); +#endif + //now write the source_banke data again. + for (vector::iterator _site=source_bank->begin(); _site!=source_bank->end();_site++){ + //particle is now at the iterator + //write it to the mcpl-file + mcpl_particle_t p; + p.position[0]=_site->r.x; + p.position[1]=_site->r.y; + p.position[2]=_site->r.z; + + p.direction[0]=_site->u.x; + p.direction[1]=_site->u.y; + p.direction[2]=_site->u.x; + + //mcpl stores kinetic energy in MeV + p.ekin=_site->E*1e-6; + + p.time=_site->time*1e3; + + p.weight=_site->wgt; + + switch(_site->particle){ + case ParticleType::neutron: + p.pdgcode=2112; + break; + case ParticleType::photon: + p.pdgcode=22; + break; + case ParticleType::electron: + p.pdgcode=11; + break; + case ParticleType::positron: + p.pdgcode=-11; + break; + } + + mcpl_add_particle(file_id,&p); + } + } + } else { +#ifdef OPENMC_MPI + MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + mpi::intracomm); +#endif + } + +} + + // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) { From 04c8ffc81c7ed7ced0c3525b5ec13f15f8fc079c Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 23:06:19 +0200 Subject: [PATCH 0985/2654] add a trigger to simulation control --- src/simulation.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/simulation.cpp b/src/simulation.cpp index b70535c33..05c8c0450 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -406,6 +406,13 @@ void finalize_batch() auto filename = settings::path_output + "surface_source.h5"; write_source_point(filename.c_str(), true); } + + if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + auto filename = settings::path_output + ".mcpl"; + write_mcplt_source_point(filename.c_str(), true); + } + + } void initialize_generation() From 53d3cd005f2267793b9489f0f39a5b8843468f67 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 09:46:33 -0500 Subject: [PATCH 0986/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- include/openmc/interpolate.h | 9 ++++----- tests/regression_tests/filter_energyfun/test.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index 8ccdc5bd7..fd95e96a8 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -1,4 +1,3 @@ - #ifndef OPENMC_INTERPOLATE_H #define OPENMC_INTERPOLATE_H @@ -18,20 +17,20 @@ inline double interpolate_lin_lin( inline double interpolate_lin_log( double x0, double x1, double y0, double y1, double x) { - return y0 + log(x / x0) / log(x1 / x0) * (y1 - y0); + return y0 + std::log(x / x0) / std::log(x1 / x0) * (y1 - y0); } inline double interpolate_log_lin( double x0, double x1, double y0, double y1, double x) { - return y0 * exp((x - x0) / (x1 - x0) * log(y1 / y0)); + return y0 * std::exp((x - x0) / (x1 - x0) * std::log(y1 / y0)); } inline double interpolate_log_log( double x0, double x1, double y0, double y1, double x) { - double f = log(x / x0) / log(x1 / x0); - return y0 * exp(f * log(y1 / y0)); + double f = std::log(x / x0) / std::log(x1 / x0); + return y0 * std::exp(f * std::log(y1 / y0)); } inline double interpolate_lagrangian(const std::vector& xs, diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index 12144c1fd..44a2c44b0 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -42,7 +42,7 @@ def model(): filt3 = openmc.EnergyFunctionFilter(x, y) filt3.interpolation = 'log-log' - filt4 = openmc.EnergyFunctionFilter(x , y) + filt4 = openmc.EnergyFunctionFilter(x, y) filt4.interpolation = 'linear-log' filt5 = openmc.EnergyFunctionFilter(x, y) From 3c9e359a575741d98278dfd0e5a2c6e12741c870 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 09:46:00 -0500 Subject: [PATCH 0987/2654] Addressing some comments from @paulromano --- include/openmc/constants.h | 6 ++-- include/openmc/interpolate.h | 14 +++++--- openmc/filter.py | 32 ++++++++----------- src/tallies/filter_energyfunc.cpp | 4 ++- .../regression_tests/filter_energyfun/test.py | 2 +- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index 32cd8186a..fa2251b84 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -319,8 +319,10 @@ enum class Interpolation { lin_log = 3, log_lin = 4, log_log = 5, - quadratic = 6, - cubic = 7 + // skip 6 b/c ENDF-6 reserves this value for + // "special one-dimensional interpolation law" + quadratic = 7, + cubic = 8 }; enum class RunMode { diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index fd95e96a8..33167fa2a 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -33,10 +33,12 @@ inline double interpolate_log_log( return y0 * std::exp(f * std::log(y1 / y0)); } -inline double interpolate_lagrangian(const std::vector& xs, - const std::vector& ys, int idx, double x, int order) +inline double interpolate_lagrangian(gsl::span xs, + gsl::span ys, int idx, double x, int order) { - std::vector coeffs; + Expects(order <= 3); + std::array coeffs; + coeffs.fill(0.0); for (int i = 0; i < order + 1; i++) { double numerator {1.0}; @@ -47,14 +49,14 @@ inline double interpolate_lagrangian(const std::vector& xs, numerator *= (x - xs[idx + j]); denominator *= (xs[idx + i] - xs[idx + j]); } - coeffs.push_back(numerator / denominator); + coeffs[i] = numerator / denominator; } return std::inner_product( coeffs.begin(), coeffs.end(), ys.begin() + idx, 0.0); } -double interpolate(const std::vector& xs, const std::vector& ys, +double interpolate(gsl::span xs, gsl::span ys, double x, Interpolation i = Interpolation::lin_lin) { int idx = lower_bound_index(xs.begin(), xs.end(), x); @@ -63,6 +65,8 @@ double interpolate(const std::vector& xs, const std::vector& ys, idx--; switch (i) { + case Interpolation::histogram: + return ys[idx]; case Interpolation::lin_lin: return interpolate_lin_lin(xs[idx], xs[idx + 1], ys[idx], ys[idx + 1], x); case Interpolation::log_log: diff --git a/openmc/filter.py b/openmc/filter.py index 7a85e2d45..254bf5245 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1887,7 +1887,9 @@ class EnergyFunctionFilter(Filter): y : iterable of Real A grid of interpolant values in [eV] interpolation : str - The type of interpolation to be used. + The type of interpolation to be used. One of + ('histogram', 'linear-linear', 'linear-log', 'log-linear', + 'log-log', 'quadratic', 'cubic') id : int Unique identifier for the filter num_bins : Integral @@ -1896,9 +1898,12 @@ class EnergyFunctionFilter(Filter): """ # keys selected to match those in function.py where possible - INTERPOLATION_SCHEMES = {2: 'linear-linear', 3: 'linear-log', - 4: 'log-linear', 5: 'log-log', - 6 : 'quadratic', 7 : 'cubic'} + # skip 6 b/c ENDF-6 reserves this value for + # "special one-dimensional interpolation law" + INTERPOLATION_SCHEMES = {1: 'histogram', 2: 'linear-linear', + 3: 'linear-log', 4: 'log-linear', + 5: 'log-log', 7: 'quadratic', + 8: 'cubic'} def __init__(self, energy, y, interpolation='linear-linear', filter_id=None): self.energy = energy @@ -1991,22 +1996,11 @@ class EnergyFunctionFilter(Filter): if tab1d.n_regions > 1: raise ValueError('Only Tabulated1Ds with a single interpolation ' 'region are supported') - if tab1d.interpolation[0] not in (2, 3, 4, 5): - raise ValueError('Only linear-linear, linear-log, log-linear, and ' + interpolation = tab1d.interpolation[0] + if interpolation not in cls.INTERPOLATION_SCHEMES.keys(): + raise ValueError('Only histogram, linear-linear, linear-log, log-linear, and ' 'log-log Tabulated1Ds are supported') - out = cls(tab1d.x, tab1d.y) - - # set interpolation type - if tab1d.interpolation[0] == 2: - out.interpolation = 'linear-linear' - elif tab1d.interpolation[0] == 3: - out.interpolation = 'linear-log' - elif tab1d.interpolation[0] == 4: - out.interpolation = 'log-linear' - elif tab1d.interpolation[0] == 5: - out.interpolation = 'log-log' - - return out + return cls(tab1d.x, tab1d.y, interpolation) @property def energy(self): diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index bf2b2e6cb..e5a6bc9b7 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -30,7 +30,9 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) interpolation_ = Interpolation::lin_lin; if (check_for_node(node, "interpolation")) { std::string interpolation = get_node_value(node, "interpolation"); - if (interpolation == "linear-linear") { + if (interpolation == "histogram") { + interpolation_ = Interpolation::histogram; + } else if (interpolation == "linear-linear") { interpolation_ = Interpolation::lin_lin; } else if (interpolation == "linear-log") { interpolation_ = Interpolation::lin_log; diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index 44a2c44b0..4a42ce0cb 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -31,7 +31,7 @@ def model(): assert filt1.interpolation == 'linear-linear' with pytest.raises(ValueError): - filt1.interpolation = '5th order polynomial' + filt1.interpolation = '🥏' # Also make a filter with the .from_tabulated1d constructor. Make sure # the filters are identical. From 848c0f3e0b408e01f14287be2a70283debb76a67 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 09:50:31 -0500 Subject: [PATCH 0988/2654] Update to eff docstring --- openmc/filter.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 254bf5245..326572c4a 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1887,9 +1887,8 @@ class EnergyFunctionFilter(Filter): y : iterable of Real A grid of interpolant values in [eV] interpolation : str - The type of interpolation to be used. One of - ('histogram', 'linear-linear', 'linear-log', 'log-linear', - 'log-log', 'quadratic', 'cubic') + Interpolation scheme: {'histogram', 'linear-linear', 'linear-log', + 'log-linear', 'log-log', 'quadratic', 'cubic'} id : int Unique identifier for the filter num_bins : Integral From f33ea966b21802e206bb46c04c7aa8e45943e01b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 11:10:27 -0500 Subject: [PATCH 0989/2654] Compute interpolation value in loop. Correction to from_tab1D. --- include/openmc/interpolate.h | 9 +++------ openmc/filter.py | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/include/openmc/interpolate.h b/include/openmc/interpolate.h index 33167fa2a..05353f130 100644 --- a/include/openmc/interpolate.h +++ b/include/openmc/interpolate.h @@ -36,9 +36,7 @@ inline double interpolate_log_log( inline double interpolate_lagrangian(gsl::span xs, gsl::span ys, int idx, double x, int order) { - Expects(order <= 3); - std::array coeffs; - coeffs.fill(0.0); + double output {0.0}; for (int i = 0; i < order + 1; i++) { double numerator {1.0}; @@ -49,11 +47,10 @@ inline double interpolate_lagrangian(gsl::span xs, numerator *= (x - xs[idx + j]); denominator *= (xs[idx + i] - xs[idx + j]); } - coeffs[i] = numerator / denominator; + output += (numerator / denominator) * ys[i]; } - return std::inner_product( - coeffs.begin(), coeffs.end(), ys.begin() + idx, 0.0); + return output; } double interpolate(gsl::span xs, gsl::span ys, diff --git a/openmc/filter.py b/openmc/filter.py index 326572c4a..2af5fe5b7 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1995,11 +1995,11 @@ class EnergyFunctionFilter(Filter): if tab1d.n_regions > 1: raise ValueError('Only Tabulated1Ds with a single interpolation ' 'region are supported') - interpolation = tab1d.interpolation[0] - if interpolation not in cls.INTERPOLATION_SCHEMES.keys(): + interpolation_val = tab1d.interpolation[0] + if interpolation_val not in cls.INTERPOLATION_SCHEMES.keys(): raise ValueError('Only histogram, linear-linear, linear-log, log-linear, and ' 'log-log Tabulated1Ds are supported') - return cls(tab1d.x, tab1d.y, interpolation) + return cls(tab1d.x, tab1d.y, cls.INTERPOLATION_SCHEMES[interpolation_val]) @property def energy(self): From 834450066e9926d0441ca027dda8c23eb2798174 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 11:31:46 -0500 Subject: [PATCH 0990/2654] Adding check of interpolation parameter in eff __eq__ --- openmc/filter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/filter.py b/openmc/filter.py index 2af5fe5b7..35a65f4fe 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1913,6 +1913,8 @@ class EnergyFunctionFilter(Filter): def __eq__(self, other): if type(self) is not type(other): return False + elif not self.interpolation == other.interpolation: + return False elif not all(self.energy == other.energy): return False else: From 3351918394cad106ce6ca35fa3fc4b53a2389e87 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 11:32:24 -0500 Subject: [PATCH 0991/2654] Adding a histogram filter test. Testing conversion from Tabulated1D for many interpolation types --- .../filter_energyfun/inputs_true.dat | 10 ++++++++++ .../regression_tests/filter_energyfun/test.py | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat index 133b3167f..db7f91ed0 100644 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ b/tests/regression_tests/filter_energyfun/inputs_true.dat @@ -54,6 +54,11 @@ 0.2 0.7 0.7 0.2 cubic + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + histogram + Am241 (n,gamma) @@ -93,4 +98,9 @@ Am241 (n,gamma) + + 9 + Am241 + (n,gamma) + diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index 4a42ce0cb..489eec8c0 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -28,6 +28,7 @@ def model(): # Make an EnergyFunctionFilter directly from the x and y lists. filt1 = openmc.EnergyFunctionFilter(x, y) + # check interpolatoin property setter assert filt1.interpolation == 'linear-linear' with pytest.raises(ValueError): @@ -60,7 +61,10 @@ def model(): filt8 = openmc.EnergyFunctionFilter(x, y) filt8.interpolation = 'cubic' - filters = [filt1, filt3, filt4, filt5, filt6, filt7, filt8] + filt9 = openmc.EnergyFunctionFilter(x, y) + filt9.interpolation = 'histogram' + + filters = [filt1, filt3, filt4, filt5, filt6, filt7, filt8, filt9] # Make tallies tallies = [openmc.Tally() for _ in range(len(filters) + 1)] for t in tallies: @@ -72,6 +76,14 @@ def model(): model.tallies.extend(tallies) + interpolation_vals = \ + list(openmc.EnergyFunctionFilter.INTERPOLATION_SCHEMES.keys()) + for i_val in interpolation_vals: + # breakpoint here is fake and unused + t1d = openmc.data.Tabulated1D(x, y, breakpoints=[1], interpolation=[i_val]) + f = openmc.EnergyFunctionFilter.from_tabulated1d(t1d) + assert f.interpolation == openmc.EnergyFunctionFilter.INTERPOLATION_SCHEMES[i_val] + return model @@ -143,6 +155,10 @@ class FilterEnergyFunHarness(PyAPITestHarness): assert all(contrived_lin_lin_tally.mean < contrived_quadratic_tally.mean) assert all(contrived_lin_lin_tally.mean < contrived_cubic_tally.mean) + # check that the histogram tally is less than the quadratic/cubic interpolations + histogram_tally = sp.get_tally(id=9) + assert all(histogram_tally.mean < contrived_quadratic_tally.mean) + assert all(histogram_tally.mean < contrived_cubic_tally.mean) def test_filter_energyfun(model): harness = FilterEnergyFunHarness('statepoint.5.h5', model) From 8228db6d47d22367eaafbad7ba32e417341c320f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 12:05:48 -0500 Subject: [PATCH 0992/2654] Writing interpolation attribute as an attribute of the 'y' dataset. --- docs/source/io_formats/statepoint.rst | 5 +++-- openmc/filter.py | 7 ++++--- src/tallies/filter_energyfunc.cpp | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 09a531ecd..a05034a2d 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -108,8 +108,9 @@ The current version of the statepoint file format is 17.0. interpolation. Only used for 'energyfunction' filters. - **y** (*double[]*) -- Interpolant values for energyfunction interpolation. Only used for 'energyfunction' filters. - - **interpolation** (*int*) -- Interpolation type. Only used for - 'energyfunction' filters. + + :Attributes: - **interpolation** (*int*) -- Interpolation type. Only used for + 'energyfunction' filters. **/tallies/derivatives/derivative /** diff --git a/openmc/filter.py b/openmc/filter.py index 35a65f4fe..1928f5ddb 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1967,13 +1967,14 @@ class EnergyFunctionFilter(Filter): + group['type'][()].decode() + " instead") energy = group['energy'][()] - y = group['y'][()] + y_grp = group['y'] + y = y_grp[()] filter_id = int(group.name.split('/')[-1].lstrip('filter ')) out = cls(energy, y, filter_id=filter_id) - if 'interpolation' in group: + if 'interpolation' in y_grp.attrs: out.interpolation = \ - cls.INTERPOLATION_SCHEMES[group['interpolation'][()]] + cls.INTERPOLATION_SCHEMES[y_grp.attrs['interpolation'][()]] return out diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index e5a6bc9b7..b961105a2 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -104,8 +104,9 @@ void EnergyFunctionFilter::to_statepoint(hid_t filter_group) const Filter::to_statepoint(filter_group); write_dataset(filter_group, "energy", energy_); write_dataset(filter_group, "y", y_); - write_dataset( - filter_group, "interpolation", static_cast(interpolation_)); + hid_t y_dataset = open_dataset(filter_group, "y"); + write_attribute(y_dataset, "interpolation", static_cast(interpolation_)); + close_dataset(y_dataset); } std::string EnergyFunctionFilter::text_label(int bin) const From a6c5dd4d8acccb21c5b5eaafc0a25279f1c7c890 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 17 Sep 2022 12:06:12 -0500 Subject: [PATCH 0993/2654] Formatting --- tests/regression_tests/filter_energyfun/test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py index 489eec8c0..295b8ebd8 100644 --- a/tests/regression_tests/filter_energyfun/test.py +++ b/tests/regression_tests/filter_energyfun/test.py @@ -80,9 +80,13 @@ def model(): list(openmc.EnergyFunctionFilter.INTERPOLATION_SCHEMES.keys()) for i_val in interpolation_vals: # breakpoint here is fake and unused - t1d = openmc.data.Tabulated1D(x, y, breakpoints=[1], interpolation=[i_val]) + t1d = openmc.data.Tabulated1D(x, + y, + breakpoints=[1], + interpolation=[i_val]) f = openmc.EnergyFunctionFilter.from_tabulated1d(t1d) - assert f.interpolation == openmc.EnergyFunctionFilter.INTERPOLATION_SCHEMES[i_val] + assert f.interpolation == \ + openmc.EnergyFunctionFilter.INTERPOLATION_SCHEMES[i_val] return model From 46ad8df16508972a599655e12d1f9e7b12a74a42 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 21 Sep 2022 07:06:38 -0500 Subject: [PATCH 0994/2654] Add error message for 'muir' distribution found in XML --- src/distribution.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/distribution.cpp b/src/distribution.cpp index c3e1cc1b3..97dce37c6 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -368,6 +368,10 @@ UPtrDist distribution_from_xml(pugi::xml_node node) dist = UPtrDist {new Tabular(node)}; } else if (type == "mixture") { dist = UPtrDist {new Mixture(node)}; + } else if (type == "muir") { + openmc::fatal_error( + "'muir' distribution type is no longer supported. Please regenerate your " + "XML files using the Python API."); } else { openmc::fatal_error("Invalid distribution type: " + type); } From 3645a418615c454a4ee5c7c67f8f5f7cc65ac5fc Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 21 Sep 2022 07:26:27 -0500 Subject: [PATCH 0995/2654] Address @shimwell comments on #2211 --- openmc/deplete/coupled_operator.py | 2 +- openmc/deplete/independent_operator.py | 5 +++-- openmc/deplete/microxs.py | 26 ++++++++++++++++---------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index 4a7c5c56f..a8c1fa156 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -101,7 +101,7 @@ class CoupledOperator(OpenMCOperator): model : openmc.model.Model OpenMC model object chain_file : str, optional - Path to the depletion chain XML file. Defaults to + Path to the depletion chain XML file. Defaults to ``openmc.config['chain_file']``. prev_results : Results, optional Results from a previous depletion calculation. If this argument is diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index 200bc195e..2dcdff343 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -40,7 +40,8 @@ class IndependentOperator(OpenMCOperator): micro_xs : MicroXS One-group microscopic cross sections in [b] . chain_file : str - Path to the depletion chain XML file. + Path to the depletion chain XML file. Defaults to + ``openmc.config['chain_file']``. keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. Default is None. @@ -111,7 +112,7 @@ class IndependentOperator(OpenMCOperator): def __init__(self, materials, micro_xs, - chain_file, + chain_file=None, keff=None, normalization_mode='fission-q', fission_q=None, diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 72d87d3b7..7f3a84bf6 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -5,18 +5,16 @@ nuclide names as row indices and reaction names as column indices. """ import tempfile -from pathlib import Path from copy import deepcopy -from pandas import DataFrame, read_csv, concat +from pandas import DataFrame, read_csv import numpy as np from openmc.checkvalue import check_type, check_value, check_iterable_type +from openmc.exceptions import DataError from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS -from openmc.data import DataLibrary -from openmc import Tallies, StatePoint, Materials, Material - - +from openmc import Tallies, StatePoint, Materials +import openmc from .chain import Chain, REACTIONS from .coupled_operator import _find_cross_sections, _get_nuclides_with_data @@ -35,7 +33,7 @@ class MicroXS(DataFrame): def from_model(cls, model, reaction_domain, - chain_file, + chain_file=None, dilute_initial=1.0e3, energy_bounds=(0, 20e6), run_kwargs=None): @@ -48,11 +46,12 @@ class MicroXS(DataFrame): OpenMC model object. Must contain geometry, materials, and settings. reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh Domain in which to tally reaction rates. - chain_file : str + chain_file : str, optional Path to the depletion chain XML file that will be used in depletion simulation. Used to determine cross sections for materials not - present in the inital composition. - dilute_initial : float + present in the inital composition. Defaults to + ``openmc.config['chain_file']``. + dilute_initial : float, optional Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the cross section data. Only done for nuclides with reaction rates. @@ -144,6 +143,13 @@ class MicroXS(DataFrame): :class:`openmc.Materials` object with nuclides added to burnable materials. """ + if chain_file is None: + chain_file = openmc.config.get('chain_file') + if chain_file is None: + raise DataError( + "No depletion chain specified and could not find depletion " + "chain in openmc.config['chain_file']" + ) chain = Chain.from_xml(chain_file) reactions = chain.reactions cross_sections = _find_cross_sections(model) From cf278af2810a0c99053ab4cb38c3370ba3fc9297 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Wed, 21 Sep 2022 12:07:42 -0400 Subject: [PATCH 0996/2654] helpful error message for excessive energy spectrum rejection rate --- src/source.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 3716720df..efc9e4598 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -201,14 +201,12 @@ SourceSite IndependentSource::sample(uint64_t* seed) const if (n_reject >= EXTSRC_REJECT_THRESHOLD && static_cast(n_accept) / n_reject <= EXTSRC_REJECT_FRACTION) { fatal_error("More than 95% of external source sites sampled were " - "rejected. Please check your external source definition."); + "rejected. Please check your external source's spatial " + "definition."); } } } - // Increment number of accepted samples - ++n_accept; - // Sample angle site.u = angle_->sample(seed); @@ -233,11 +231,22 @@ SourceSite IndependentSource::sample(uint64_t* seed) const // Resample if energy falls outside minimum or maximum particle energy if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break; + + n_reject++; + if (n_reject >= EXTSRC_REJECT_THRESHOLD && + static_cast(n_accept) / n_reject <= EXTSRC_REJECT_FRACTION) { + fatal_error("More than 95% of external source sites sampled were " + "rejected. Please check your external source energy spectrum " + "definition."); + } } // Sample particle creation time site.time = time_->sample(seed); + // Increment number of accepted samples + ++n_accept; + return site; } From 43ff0a28218138dce71a5c5eb307bdbc84658df2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 21 Sep 2022 11:54:25 -0500 Subject: [PATCH 0997/2654] Update error message for 'muir' distributions in C++ --- src/distribution.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index 97dce37c6..6bf51df6a 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -370,8 +370,8 @@ UPtrDist distribution_from_xml(pugi::xml_node node) dist = UPtrDist {new Mixture(node)}; } else if (type == "muir") { openmc::fatal_error( - "'muir' distribution type is no longer supported. Please regenerate your " - "XML files using the Python API."); + "'muir' distributions are now specified using the openmc.stats.muir() " + "function in Python. Please regenerate your XML files."); } else { openmc::fatal_error("Invalid distribution type: " + type); } From 61a0458d4c27d7e9bdb54abb012c6c0fb54c51a9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 22 Sep 2022 10:46:55 -0500 Subject: [PATCH 0998/2654] Include interpolation types in params docstr --- openmc/filter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index 1928f5ddb..d83b9f6ba 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1876,7 +1876,8 @@ class EnergyFunctionFilter(Filter): y : iterable of Real A grid of interpolant values in [eV] interpolation : str - The type of interpolation to be used. + Interpolation scheme: {'histogram', 'linear-linear', 'linear-log', + 'log-linear', 'log-log', 'quadratic', 'cubic'} filter_id : int Unique identifier for the filter From 607be496bce599032ca74bb15b8c2adb312de7b6 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Thu, 22 Sep 2022 14:58:52 -0300 Subject: [PATCH 0999/2654] Fix elastic distribution Elastic distributions were created but not used --- openmc/data/thermal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index 3d5f2df64..7e66b6319 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -730,10 +730,10 @@ class ThermalScattering(EqualityMixin): if ace.nxs[5] == 3: xs = incoherent_xs - dist = incoherent_dist + distribution = incoherent_dist elif ace.nxs[5] == 4: xs = coherent_xs - dist = coherent_dist + distribution = coherent_dist else: # Create mixed cross section -- note that coherent must come # first due to assumption on C++ side From 96753f9af0101d94aa4c3b2e9de9c86d639bf5dd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Sep 2022 23:31:43 -0500 Subject: [PATCH 1000/2654] Fix reading source file with time attribute. Closes #2223 --- src/state_point.cpp | 1 + tests/unit_tests/test_source_file.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/state_point.cpp b/src/state_point.cpp index 648d1a249..470dd7718 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -527,6 +527,7 @@ hid_t h5banktype() H5Tinsert(banktype, "r", HOFFSET(SourceSite, r), postype); H5Tinsert(banktype, "u", HOFFSET(SourceSite, u), postype); H5Tinsert(banktype, "E", HOFFSET(SourceSite, E), H5T_NATIVE_DOUBLE); + H5Tinsert(banktype, "time", HOFFSET(SourceSite, time), H5T_NATIVE_DOUBLE); H5Tinsert(banktype, "wgt", HOFFSET(SourceSite, wgt), H5T_NATIVE_DOUBLE); H5Tinsert(banktype, "delayed_group", HOFFSET(SourceSite, delayed_group), H5T_NATIVE_INT); diff --git a/tests/unit_tests/test_source_file.py b/tests/unit_tests/test_source_file.py index 1398088e5..78115a1f6 100644 --- a/tests/unit_tests/test_source_file.py +++ b/tests/unit_tests/test_source_file.py @@ -75,3 +75,25 @@ def test_wrong_source_attributes(run_in_tmpdir): with pytest.raises(RuntimeError) as excinfo: openmc.run() assert 'platypus, axolotl, narwhal' in str(excinfo.value) + + +def test_source_file_transport(run_in_tmpdir): + # Create a source file with a single particle + particle = openmc.SourceParticle() + openmc.write_source_file([particle], 'source.h5') + + # Created simple model to use source file + model = openmc.Model() + al = openmc.Material() + al.add_element('Al', 1.0) + al.set_density('g/cm3', 2.7) + sph = openmc.Sphere(r=10.0, boundary_type='vacuum') + cell = openmc.Cell(fill=al, region=-sph) + model.geometry = openmc.Geometry([cell]) + model.settings.source = openmc.Source(filename='source.h5') + model.settings.particles = 10 + model.settings.batches = 3 + model.settings.run_mode = 'fixed source' + + # Try running OpenMC + model.run() From b2270d4aefdaea4f3a2b564742a1a76f2e2e7812 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 23 Sep 2022 08:43:48 -0500 Subject: [PATCH 1001/2654] Update reference surface source for regression test --- .../surface_source/surface_source_true.h5 | Bin 106088 -> 106144 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/regression_tests/surface_source/surface_source_true.h5 b/tests/regression_tests/surface_source/surface_source_true.h5 index 2ea48b2ac16fa4acb1275d48ab3ef28c2136af37..c26afee8671dba0b729d6959614a6856166bd37a 100644 GIT binary patch delta 11162 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 delta 11163 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 j$?zyz#`bI Date: Sat, 24 Sep 2022 20:09:01 +0100 Subject: [PATCH 1002/2654] added ability to find material names in DAG --- openmc/universe.py | 30 +++++++++++++++++++++++++++ tests/unit_tests/dagmc/test_bounds.py | 9 ++++++++ 2 files changed, 39 insertions(+) diff --git a/openmc/universe.py b/openmc/universe.py index 0e60974c0..16a251dee 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -699,6 +699,36 @@ class DAGMCUniverse(UniverseBase): def auto_mat_ids(self): return self._auto_mat_ids + @property + def material_names(self): + """Return the names of the materials that are contained within the + DAGMC h5m file. This is useful when naming openmc.Material() objects + as each material name present in the DAGMC h5m file must have a + matching openmc.Material() with the same name. + + Returns + ------- + materials : List[str] + Sorted list of material names present in the DAGMC h5m file + + """ + + dagmc_file_contents = h5py.File(self.filename) + material_tags_hex=dagmc_file_contents['/tstt/tags/NAME'].get('values') + material_tags_ascii=[] + for tag in material_tags_hex: + raw_tag= np.array2string(tag) + tag_in_hex=raw_tag.replace("\\x00", '').replace("\\x", '') + tag_in_hex =tag_in_hex.lstrip("b'").rstrip("'") + candidate_tag = bytes.fromhex(tag_in_hex).decode() + # tags might be for temperature or reflective surfaces + if candidate_tag.startswith('mat:'): + # removes first 4 characters as openmc.Material name should be + # set without the 'mat:' part of the tag + material_tags_ascii.append(candidate_tag[4:]) + + return sorted(set(material_tags_ascii)) + @auto_mat_ids.setter def auto_mat_ids(self, val): cv.check_type('DAGMC automatic material ids', val, bool) diff --git a/tests/unit_tests/dagmc/test_bounds.py b/tests/unit_tests/dagmc/test_bounds.py index dbca3ca25..d2458195a 100644 --- a/tests/unit_tests/dagmc/test_bounds.py +++ b/tests/unit_tests/dagmc/test_bounds.py @@ -71,3 +71,12 @@ def test_bounded_universe(request): surfaces = list(cells[0][1].region.get_surfaces().items()) assert surfaces[0][1].type == "sphere" assert surfaces[0][1].id == 43 + + +def test_material_names(request): + """Checks that the DAGMCUniverse.material_names() returns a list of the + name present in the dagmc.h5m file in the expected order""" + + u = openmc.DAGMCUniverse(Path(request.fspath).parent / "dagmc.h5m") + + assert u.material_names == ['41', 'Graveyard', 'no-void fuel'] From 67e983218dbd040f8d9cbfd6d11188e56f504dda Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Sat, 24 Sep 2022 17:07:08 -0500 Subject: [PATCH 1003/2654] let thermal table name be None as default --- scripts/openmc-ace-to-hdf5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/openmc-ace-to-hdf5 b/scripts/openmc-ace-to-hdf5 index d7eb488f7..75948e012 100755 --- a/scripts/openmc-ace-to-hdf5 +++ b/scripts/openmc-ace-to-hdf5 @@ -92,7 +92,7 @@ def ace_to_hdf5(destination, xsdir, xsdata, libraries, metastable, libver): # Add data for new temperature try: print(f"Converting {table.name} (ACE) to {data.name} (HDF5)") - data.add_temperature_from_ace(table, metastable) + data.add_temperature_from_ace(table) except Exception as e: print(f"Failed to convert {table.name}: {e}") continue From 06312b0535bbc0d46464a77039aa0ad483c9db21 Mon Sep 17 00:00:00 2001 From: myerspat Date: Sun, 25 Sep 2022 22:05:22 -0400 Subject: [PATCH 1004/2654] Refactored CSGCell to use Region --- include/openmc/cell.h | 90 +++-- src/cell.cpp | 872 ++++++++++++++++++++++-------------------- src/geometry.cpp | 2 +- src/geometry_aux.cpp | 5 +- src/universe.cpp | 36 +- 5 files changed, 523 insertions(+), 482 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index fcce520fe..0891c062f 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -53,33 +53,46 @@ extern vector> cells; //============================================================================== -// TODO: Maybe not, just move this inline to Region::bounding_box() for complex -// case -class RegionPostfix { -public: - BoundingBox bounding_box() const; -}; - class Region { public: + //---------------------------------------------------------------------------- + // Constructors Region() {} - explicit Region(std::string region_expression); + explicit Region(std::string region_expressioni, int32_t cell_id); - void add_precedence(); - std::string str() const; - BoundingBox bounding_box() const; + //---------------------------------------------------------------------------- + // Methods + std::pair distance( + Position r, Direction u, int32_t on_surface, Particle* p) const; bool contains(Position r, Direction u, int32_t on_surface) const; + BoundingBox bounding_box(int32_t cell_id) const; + std::string str() const; + vector surfaces() const; - RegionPostfix to_postfix() const; + //---------------------------------------------------------------------------- + // Accessors + bool is_simple() const { return simple_; } private: - void add_parentheses(); + //---------------------------------------------------------------------------- + // Private Methods + vector generate_postfix(int32_t cell_id) const; + bool contains_simple(Position r, Direction u, int32_t on_surface) const; + bool contains_complex(Position r, Direction u, int32_t on_surface) const; + BoundingBox bounding_box_simple() const; + BoundingBox bounding_box_complex(vector postfix) const; + void add_precedence(); + std::vector::iterator add_parentheses( + std::vector::iterator start); + void remove_complement_ops(); void apply_demorgan( vector::iterator start, vector::iterator stop); + //---------------------------------------------------------------------------- + // Private Data //! Definition of spatial region as Boolean expression of half-spaces // TODO: Should this be a vector of some other type - vector tokens_; + vector expression_; bool simple_; //!< Does the region contain only intersections? }; @@ -141,6 +154,12 @@ public: //! Get the BoundingBox for this cell. virtual BoundingBox bounding_box() const = 0; + //! Get a vector of surfaces in the cell + virtual vector surfaces() const = 0; + + //! Check if the cell region expression is simple + virtual bool is_simple() const = 0; + //---------------------------------------------------------------------------- // Accessors @@ -231,10 +250,6 @@ public: //! T. The units are sqrt(eV). vector sqrtkT_; - // TODO: Probably move this guy to CSGCell - //! Definition of spatial region as Boolean expression of half-spaces - Region region_; - //! \brief Neighboring cells in the same universe. NeighborList neighbors_; @@ -260,35 +275,36 @@ struct CellInstanceItem { class CSGCell : public Cell { public: + //---------------------------------------------------------------------------- + // Constructors CSGCell(); - explicit CSGCell(pugi::xml_node cell_node); - bool contains(Position r, Direction u, int32_t on_surface) const override; + //---------------------------------------------------------------------------- + // Methods + vector surfaces() const override { return region_.surfaces(); } std::pair distance( - Position r, Direction u, int32_t on_surface, Particle* p) const override; + Position r, Direction u, int32_t on_surface, Particle* p) const override + { + return region_.distance(r, u, on_surface, p); + } + + bool contains(Position r, Direction u, int32_t on_surface) const override + { + return region_.contains(r, u, on_surface); + } + + BoundingBox bounding_box() const override + { + return region_.bounding_box(id_); + } void to_hdf5_inner(hid_t group_id) const override; - BoundingBox bounding_box() const override; + bool is_simple() const override { return region_.is_simple(); } protected: - bool contains_simple(Position r, Direction u, int32_t on_surface) const; - bool contains_complex(Position r, Direction u, int32_t on_surface) const; - BoundingBox bounding_box_simple() const; - static BoundingBox bounding_box_complex(vector postfix); - - //! Applies DeMorgan's laws to a section of the RPN - //! \param start Starting point for token modification - //! \param stop Stopping point for token modification - static void apply_demorgan( - vector::iterator start, vector::iterator stop); - - //! Removes complement operators from the RPN - //! \param rpn The rpn to remove complement operators from. - static void remove_complement_ops(vector& rpn); - //! Returns the beginning position of a parenthesis block (immediately before //! two surface tokens) in the RPN given a starting position at the end of //! that block (immediately after two surface tokens) diff --git a/src/cell.cpp b/src/cell.cpp index 4eb0fa0b9..dc38a567e 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -36,243 +36,6 @@ vector> cells; } // namespace model -//============================================================================== -//! Convert region specification string to integer tokens. -//! -//! The characters (, ), |, and ~ count as separate tokens since they represent -//! operators. -//============================================================================== - -// TODO: Move this to be Region::Region(...) -vector tokenize(const std::string region_spec) -{ - // Check for an empty region_spec first. - vector tokens; - if (region_spec.empty()) { - return tokens; - } - - // Parse all halfspaces and operators except for intersection (whitespace). - for (int i = 0; i < region_spec.size();) { - if (region_spec[i] == '(') { - tokens.push_back(OP_LEFT_PAREN); - i++; - - } else if (region_spec[i] == ')') { - tokens.push_back(OP_RIGHT_PAREN); - i++; - - } else if (region_spec[i] == '|') { - tokens.push_back(OP_UNION); - i++; - - } else if (region_spec[i] == '~') { - tokens.push_back(OP_COMPLEMENT); - i++; - - } else if (region_spec[i] == '-' || region_spec[i] == '+' || - std::isdigit(region_spec[i])) { - // This is the start of a halfspace specification. Iterate j until we - // find the end, then push-back everything between i and j. - int j = i + 1; - while (j < region_spec.size() && std::isdigit(region_spec[j])) { - j++; - } - tokens.push_back(std::stoi(region_spec.substr(i, j - i))); - i = j; - - } else if (std::isspace(region_spec[i])) { - i++; - - } else { - auto err_msg = - fmt::format("Region specification contains invalid character, \"{}\"", - region_spec[i]); - fatal_error(err_msg); - } - } - - // Add in intersection operators where a missing operator is needed. - int i = 0; - while (i < tokens.size() - 1) { - bool left_compat {(tokens[i] < OP_UNION) || (tokens[i] == OP_RIGHT_PAREN)}; - bool right_compat {(tokens[i + 1] < OP_UNION) || - (tokens[i + 1] == OP_LEFT_PAREN) || - (tokens[i + 1] == OP_COMPLEMENT)}; - if (left_compat && right_compat) { - tokens.insert(tokens.begin() + i + 1, OP_INTERSECTION); - } - i++; - } - - return tokens; -} - -//============================================================================== -//! Add precedence for infix regions so intersections have higher -//! precedence than unions using parentheses. -//============================================================================== - -std::vector::iterator add_parentheses( - std::vector::iterator start, std::vector& infix) -{ - int32_t start_token = *start; - // Add left parenthesis - if (start_token == OP_INTERSECTION) { - start = infix.insert(start - 1, OP_LEFT_PAREN); - } else { - start = infix.insert(start + 1, OP_LEFT_PAREN); - } - start++; - - // Initialize return iterator - auto return_iterator = infix.begin(); - - // Add right parenthesis - // While the start iterator is within the bounds of infix - while (start < infix.end()) { - start++; - - // If the current token is an operator and is different than the start token - if (*start >= OP_UNION && *start != start_token) { - // Skip wrapped regions but save iterator position to check precedence and - // add right parenthesis, right parenthesis position depends on the - // operator, when the operator is a union then do not include the operator - // in the region, when the operator is an intersection then include the - // operato and next surface - if (*start == OP_LEFT_PAREN) { - return_iterator = start; - int depth = 1; - do { - start++; - if (*start > OP_COMPLEMENT) { - if (*start == OP_RIGHT_PAREN) { - depth--; - } else { - depth++; - } - } - } while (depth > 0); - } else { - start = infix.insert( - start_token == OP_UNION ? start - 1 : start, OP_RIGHT_PAREN); - if (return_iterator == infix.begin()) { - return_iterator = start - 1; - } - return return_iterator; - } - } - } - // If we get here a right parenthesis hasn't been placed, - // return iterator - infix.push_back(OP_RIGHT_PAREN); - if (return_iterator == infix.begin()) { - return_iterator = start - 1; - } - return return_iterator; -} - -void add_precedence(std::vector& infix) -{ - int32_t current_op = 0; - - for (auto it = infix.begin(); it != infix.end(); it++) { - int32_t token = *it; - - if (token == OP_UNION || token == OP_INTERSECTION) { - if (current_op == 0) { - // Set the current operator if is hasn't been set - current_op = token; - } else if (token != current_op) { - // If the current operator doesn't match the token, add parenthesis to - // assert precedence - it = add_parentheses(it, infix); - current_op = 0; - } - } else if (token > OP_COMPLEMENT) { - // If the token is a parenthesis reset the current operator - current_op = 0; - } - } -} - -//============================================================================== -//! Convert infix region specification to Reverse Polish Notation (RPN) -//! -//! This function uses the shunting-yard algorithm. -//============================================================================== - -vector generate_postfix(int32_t cell_id, vector infix) -{ - vector rpn; - vector stack; - - for (int32_t token : infix) { - if (token < OP_UNION) { - // If token is not an operator, add it to output - rpn.push_back(token); - } else if (token < OP_RIGHT_PAREN) { - // Regular operators union, intersection, complement - while (stack.size() > 0) { - int32_t op = stack.back(); - - if (op < OP_RIGHT_PAREN && ((token == OP_COMPLEMENT && token < op) || - (token != OP_COMPLEMENT && token <= op))) { - // While there is an operator, op, on top of the stack, if the token - // is left-associative and its precedence is less than or equal to - // that of op or if the token is right-associative and its precedence - // is less than that of op, move op to the output queue and push the - // token on to the stack. Note that only complement is - // right-associative. - rpn.push_back(op); - stack.pop_back(); - } else { - break; - } - } - - stack.push_back(token); - - } else if (token == OP_LEFT_PAREN) { - // If the token is a left parenthesis, push it onto the stack - stack.push_back(token); - - } else { - // If the token is a right parenthesis, move operators from the stack to - // the output queue until reaching the left parenthesis. - for (auto it = stack.rbegin(); *it != OP_LEFT_PAREN; it++) { - // If we run out of operators without finding a left parenthesis, it - // means there are mismatched parentheses. - if (it == stack.rend()) { - fatal_error(fmt::format( - "Mismatched parentheses in region specification for cell {}", - cell_id)); - } - rpn.push_back(stack.back()); - stack.pop_back(); - } - - // Pop the left parenthesis. - stack.pop_back(); - } - } - - while (stack.size() > 0) { - int32_t op = stack.back(); - - // If the operator is a parenthesis it is mismatched. - if (op >= OP_RIGHT_PAREN) { - fatal_error(fmt::format( - "Mismatched parentheses in region specification for cell {}", cell_id)); - } - - rpn.push_back(stack.back()); - stack.pop_back(); - } - - return rpn; -} - //============================================================================== // Cell implementation //============================================================================== @@ -588,44 +351,8 @@ CSGCell::CSGCell(pugi::xml_node cell_node) // Get a tokenized representation of the region specification and apply De // Morgans law - region_ = Region(region_spec); - remove_complement_ops(region_); - - // Convert user IDs to surface indices. - for (auto& r : region_) { - if (r < OP_UNION) { - const auto& it {model::surface_map.find(abs(r))}; - if (it == model::surface_map.end()) { - throw std::runtime_error { - "Invalid surface ID " + std::to_string(abs(r)) + - " specified in region for cell " + std::to_string(id_) + "."}; - } - r = (r > 0) ? it->second + 1 : -(it->second + 1); - } - } - - // Check if this is a simple cell. - simple_ = true; - for (int32_t token : region_) { - if (token == OP_UNION) { - simple_ = false; - // Ensure intersections have precedence over unions - add_precedence(region_); - break; - } - } - region_.shrink_to_fit(); - - // If this cell is simple, remove all the superfluous operator tokens. - if (simple_) { - for (auto it = region_.begin(); it != region_.end(); it++) { - if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { - region_.erase(it); - it--; - } - } - region_.shrink_to_fit(); - } + Region region(region_spec, id_); + region_ = region; // Read the translation vector. if (check_for_node(cell_node, "translation")) { @@ -652,99 +379,13 @@ CSGCell::CSGCell(pugi::xml_node cell_node) //============================================================================== -bool CSGCell::contains(Position r, Direction u, int32_t on_surface) const -{ - if (simple_) { - return contains_simple(r, u, on_surface); - } else { - return contains_complex(r, u, on_surface); - } -} - -//============================================================================== - -std::pair CSGCell::distance( - Position r, Direction u, int32_t on_surface, Particle* p) const -{ - double min_dist {INFTY}; - int32_t i_surf {std::numeric_limits::max()}; - - for (int32_t token : region_) { - // Ignore this token if it corresponds to an operator rather than a region. - if (token >= OP_UNION) - continue; - - // Calculate the distance to this surface. - // Note the off-by-one indexing - bool coincident {std::abs(token) == std::abs(on_surface)}; - double d {model::surfaces[abs(token) - 1]->distance(r, u, coincident)}; - - // Check if this distance is the new minimum. - if (d < min_dist) { - if (min_dist - d >= FP_PRECISION * min_dist) { - min_dist = d; - i_surf = -token; - } - } - } - - return {min_dist, i_surf}; -} - -//============================================================================== - void CSGCell::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "geom_type", "csg", false); - - // TODO: Move to Region::str() - // Write the region specification. - if (!region_.empty()) { - std::stringstream region_spec {}; - for (int32_t token : region_) { - if (token == OP_LEFT_PAREN) { - region_spec << " ("; - } else if (token == OP_RIGHT_PAREN) { - region_spec << " )"; - } else if (token == OP_COMPLEMENT) { - region_spec << " ~"; - } else if (token == OP_INTERSECTION) { - } else if (token == OP_UNION) { - region_spec << " |"; - } else { - // Note the off-by-one indexing - auto surf_id = model::surfaces[abs(token) - 1]->id_; - region_spec << " " << ((token > 0) ? surf_id : -surf_id); - } - } - write_string(group_id, "region", region_spec.str(), false); - } + write_string(group_id, "region", region_.str(), false); } -BoundingBox CSGCell::bounding_box_simple() const -{ - BoundingBox bbox; - for (int32_t token : region_) { - bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); - } - return bbox; -} - -void CSGCell::apply_demorgan( - vector::iterator start, vector::iterator stop) -{ - do { - if (*start < OP_UNION) { - *start *= -1; - } else if (*start == OP_UNION) { - *start = OP_INTERSECTION; - } else if (*start == OP_INTERSECTION) { - *start = OP_UNION; - } - start++; - } while (start < stop); -} +//============================================================================== vector::iterator CSGCell::find_left_parenthesis( vector::iterator start, const vector& infix) @@ -779,75 +420,395 @@ vector::iterator CSGCell::find_left_parenthesis( return it; } -void CSGCell::remove_complement_ops(vector& infix) -{ - auto it = std::find(infix.begin(), infix.end(), OP_COMPLEMENT); - while (it != infix.end()) { - // Erase complement - infix.erase(it); +//============================================================================== +// Region implementation +//============================================================================== - // Define stop given left parenthesis or not - auto stop = it; - if (*it == OP_LEFT_PAREN) { - int depth = 1; - do { - stop++; - if (*stop > OP_COMPLEMENT) { - if (*stop == OP_RIGHT_PAREN) { - depth--; - } else { - depth++; - } +Region::Region(std::string region_spec, int32_t cell_id) +{ + // Check if region_spec is not empty. + if (!region_spec.empty()) { + // Parse all halfspaces and operators except for intersection (whitespace). + for (int i = 0; i < region_spec.size();) { + if (region_spec[i] == '(') { + expression_.push_back(OP_LEFT_PAREN); + i++; + + } else if (region_spec[i] == ')') { + expression_.push_back(OP_RIGHT_PAREN); + i++; + + } else if (region_spec[i] == '|') { + expression_.push_back(OP_UNION); + i++; + + } else if (region_spec[i] == '~') { + expression_.push_back(OP_COMPLEMENT); + i++; + + } else if (region_spec[i] == '-' || region_spec[i] == '+' || + std::isdigit(region_spec[i])) { + // This is the start of a halfspace specification. Iterate j until we + // find the end, then push-back everything between i and j. + int j = i + 1; + while (j < region_spec.size() && std::isdigit(region_spec[j])) { + j++; } - } while (depth > 0); - it++; + expression_.push_back(std::stoi(region_spec.substr(i, j - i))); + i = j; + + } else if (std::isspace(region_spec[i])) { + i++; + + } else { + auto err_msg = + fmt::format("Region specification contains invalid character, \"{}\"", + region_spec[i]); + fatal_error(err_msg); + } } - // apply DeMorgan's law to any surfaces/operators between these - // positions in the RPN - apply_demorgan(it, stop); - // update iterator position - it = std::find(infix.begin(), infix.end(), OP_COMPLEMENT); - } -} - -BoundingBox CSGCell::bounding_box_complex(vector postfix) -{ - vector stack(postfix.size()); - int i_stack = -1; - - for (auto& token : postfix) { - if (token == OP_UNION) { - stack[i_stack - 1] = stack[i_stack - 1] | stack[i_stack]; - i_stack--; - } else if (token == OP_INTERSECTION) { - stack[i_stack - 1] = stack[i_stack - 1] & stack[i_stack]; - i_stack--; - } else { - i_stack++; - stack[i_stack] = model::surfaces[abs(token) - 1]->bounding_box(token > 0); + // Add in intersection operators where a missing operator is needed. + int i = 0; + while (i < expression_.size() - 1) { + bool left_compat { + (expression_[i] < OP_UNION) || (expression_[i] == OP_RIGHT_PAREN)}; + bool right_compat {(expression_[i + 1] < OP_UNION) || + (expression_[i + 1] == OP_LEFT_PAREN) || + (expression_[i + 1] == OP_COMPLEMENT)}; + if (left_compat && right_compat) { + expression_.insert(expression_.begin() + i + 1, OP_INTERSECTION); + } + i++; } - } - Ensures(i_stack == 0); - return stack.front(); -} + // Remove complement operators using DeMorgan's laws + auto it = std::find(expression_.begin(), expression_.end(), OP_COMPLEMENT); + while (it != expression_.end()) { + // Erase complement + expression_.erase(it); + + // Define stop given left parenthesis or not + auto stop = it; + if (*it == OP_LEFT_PAREN) { + int depth = 1; + do { + stop++; + if (*stop > OP_COMPLEMENT) { + if (*stop == OP_RIGHT_PAREN) { + depth--; + } else { + depth++; + } + } + } while (depth > 0); + it++; + } + + // apply DeMorgan's law to any surfaces/operators between these + // positions in the RPN + apply_demorgan(it, stop); + // update iterator position + it = std::find(expression_.begin(), expression_.end(), OP_COMPLEMENT); + } + + // Convert user IDs to surface indices. + for (auto& r : expression_) { + if (r < OP_UNION) { + const auto& it {model::surface_map.find(abs(r))}; + if (it == model::surface_map.end()) { + throw std::runtime_error { + "Invalid surface ID " + std::to_string(abs(r)) + + " specified in region for cell " + std::to_string(cell_id) + "."}; + } + r = (r > 0) ? it->second + 1 : -(it->second + 1); + } + } + + // Check if this is a simple cell. + simple_ = true; + for (int32_t token : expression_) { + if (token == OP_UNION) { + simple_ = false; + // Ensure intersections have precedence over unions + add_precedence(); + break; + } + } + + // If this cell is simple, remove all the superfluous operator tokens. + if (simple_) { + for (auto it = expression_.begin(); it != expression_.end(); it++) { + if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { + expression_.erase(it); + it--; + } + } + } + expression_.shrink_to_fit(); -BoundingBox CSGCell::bounding_box() const -{ - if (simple_) { - return bounding_box_simple(); } else { - auto postfix = generate_postfix(this->id_, this->region_); - return bounding_box_complex(postfix); + simple_ = true; } } //============================================================================== -bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const +void Region::apply_demorgan( + vector::iterator start, vector::iterator stop) { - for (int32_t token : region_) { + do { + if (*start < OP_UNION) { + *start *= -1; + } else if (*start == OP_UNION) { + *start = OP_INTERSECTION; + } else if (*start == OP_INTERSECTION) { + *start = OP_UNION; + } + start++; + } while (start < stop); +} + +//============================================================================== +//! Add precedence for infix regions so intersections have higher +//! precedence than unions using parentheses. +//============================================================================== + +std::vector::iterator Region::add_parentheses( + std::vector::iterator start) +{ + int32_t start_token = *start; + // Add left parenthesis + if (start_token == OP_INTERSECTION) { + start = expression_.insert(start - 1, OP_LEFT_PAREN); + } else { + start = expression_.insert(start + 1, OP_LEFT_PAREN); + } + start++; + + // Initialize return iterator + auto return_iterator = expression_.begin(); + + // Add right parenthesis + // While the start iterator is within the bounds of infix + while (start < expression_.end()) { + start++; + + // If the current token is an operator and is different than the start token + if (*start >= OP_UNION && *start != start_token) { + // Skip wrapped regions but save iterator position to check precedence and + // add right parenthesis, right parenthesis position depends on the + // operator, when the operator is a union then do not include the operator + // in the region, when the operator is an intersection then include the + // operato and next surface + if (*start == OP_LEFT_PAREN) { + return_iterator = start; + int depth = 1; + do { + start++; + if (*start > OP_COMPLEMENT) { + if (*start == OP_RIGHT_PAREN) { + depth--; + } else { + depth++; + } + } + } while (depth > 0); + } else { + start = expression_.insert( + start_token == OP_UNION ? start - 1 : start, OP_RIGHT_PAREN); + if (return_iterator == expression_.begin()) { + return_iterator = start - 1; + } + return return_iterator; + } + } + } + // If we get here a right parenthesis hasn't been placed, + // return iterator + expression_.push_back(OP_RIGHT_PAREN); + if (return_iterator == expression_.begin()) { + return_iterator = start - 1; + } + return return_iterator; +} + +//============================================================================== + +void Region::add_precedence() +{ + int32_t current_op = 0; + + for (auto it = expression_.begin(); it != expression_.end(); it++) { + int32_t token = *it; + + if (token == OP_UNION || token == OP_INTERSECTION) { + if (current_op == 0) { + // Set the current operator if is hasn't been set + current_op = token; + } else if (token != current_op) { + // If the current operator doesn't match the token, add parenthesis to + // assert precedence + it = add_parentheses(it); + current_op = 0; + } + } else if (token > OP_COMPLEMENT) { + // If the token is a parenthesis reset the current operator + current_op = 0; + } + } +} + +//============================================================================== +//! Convert infix region specification to Reverse Polish Notation (RPN) +//! +//! This function uses the shunting-yard algorithm. +//============================================================================== + +vector Region::generate_postfix(int32_t cell_id) const +{ + vector rpn; + vector stack; + + for (int32_t token : expression_) { + if (token < OP_UNION) { + // If token is not an operator, add it to output + rpn.push_back(token); + } else if (token < OP_RIGHT_PAREN) { + // Regular operators union, intersection, complement + while (stack.size() > 0) { + int32_t op = stack.back(); + + if (op < OP_RIGHT_PAREN && ((token == OP_COMPLEMENT && token < op) || + (token != OP_COMPLEMENT && token <= op))) { + // While there is an operator, op, on top of the stack, if the token + // is left-associative and its precedence is less than or equal to + // that of op or if the token is right-associative and its precedence + // is less than that of op, move op to the output queue and push the + // token on to the stack. Note that only complement is + // right-associative. + rpn.push_back(op); + stack.pop_back(); + } else { + break; + } + } + + stack.push_back(token); + + } else if (token == OP_LEFT_PAREN) { + // If the token is a left parenthesis, push it onto the stack + stack.push_back(token); + + } else { + // If the token is a right parenthesis, move operators from the stack to + // the output queue until reaching the left parenthesis. + for (auto it = stack.rbegin(); *it != OP_LEFT_PAREN; it++) { + // If we run out of operators without finding a left parenthesis, it + // means there are mismatched parentheses. + if (it == stack.rend()) { + fatal_error(fmt::format( + "Mismatched parentheses in region specification for cell {}", + cell_id)); + } + rpn.push_back(stack.back()); + stack.pop_back(); + } + + // Pop the left parenthesis. + stack.pop_back(); + } + } + + while (stack.size() > 0) { + int32_t op = stack.back(); + + // If the operator is a parenthesis it is mismatched. + if (op >= OP_RIGHT_PAREN) { + fatal_error(fmt::format( + "Mismatched parentheses in region specification for cell {}", cell_id)); + } + + rpn.push_back(stack.back()); + stack.pop_back(); + } + + return rpn; +} + +//============================================================================== + +std::string Region::str() const +{ + std::stringstream region_spec {}; + if (!expression_.empty()) { + for (int32_t token : expression_) { + if (token == OP_LEFT_PAREN) { + region_spec << " ("; + } else if (token == OP_RIGHT_PAREN) { + region_spec << " )"; + } else if (token == OP_COMPLEMENT) { + region_spec << " ~"; + } else if (token == OP_INTERSECTION) { + } else if (token == OP_UNION) { + region_spec << " |"; + } else { + // Note the off-by-one indexing + auto surf_id = model::surfaces[abs(token) - 1]->id_; + region_spec << " " << ((token > 0) ? surf_id : -surf_id); + } + } + } + return region_spec.str(); +} + +//============================================================================== + +std::pair Region::distance( + Position r, Direction u, int32_t on_surface, Particle* p) const +{ + double min_dist {INFTY}; + int32_t i_surf {std::numeric_limits::max()}; + + + for (int32_t token : expression_) { + // Ignore this token if it corresponds to an operator rather than a region. + if (token >= OP_UNION) + continue; + + // Calculate the distance to this surface. + // Note the off-by-one indexing + bool coincident {std::abs(token) == std::abs(on_surface)}; + double d {model::surfaces[abs(token) - 1]->distance(r, u, coincident)}; + + // Check if this distance is the new minimum. + if (d < min_dist) { + if (min_dist - d >= FP_PRECISION * min_dist) { + min_dist = d; + i_surf = -token; + } + } + } + + return {min_dist, i_surf}; +} + +//============================================================================== + +bool Region::contains(Position r, Direction u, int32_t on_surface) const +{ + if (simple_) { + return contains_simple(r, u, on_surface); + } else { + return contains_complex(r, u, on_surface); + } +} + +//============================================================================== + +bool Region::contains_simple(Position r, Direction u, int32_t on_surface) const +{ + for (int32_t token : expression_) { // Assume that no tokens are operators. Evaluate the sense of particle with // respect to the surface and see if the token matches the sense. If the // particle's surface attribute is set and matches the token, that @@ -868,14 +829,13 @@ bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const //============================================================================== -bool CSGCell::contains_complex( - Position r, Direction u, int32_t on_surface) const +bool Region::contains_complex(Position r, Direction u, int32_t on_surface) const { bool in_cell = true; int total_depth = 0; // For each token - for (auto it = region_.begin(); it != region_.end(); it++) { + for (auto it = expression_.begin(); it != expression_.end(); it++) { int32_t token = *it; // If the token is a surface evaluate the sense @@ -926,6 +886,76 @@ bool CSGCell::contains_complex( return in_cell; } +//============================================================================== + +BoundingBox Region::bounding_box(int32_t cell_id) const +{ + if (simple_) { + return bounding_box_simple(); + } else { + auto postfix = generate_postfix(cell_id); + return bounding_box_complex(postfix); + } +} + +//============================================================================== + +BoundingBox Region::bounding_box_simple() const +{ + BoundingBox bbox; + for (int32_t token : expression_) { + bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); + } + return bbox; +} + +//============================================================================== + +BoundingBox Region::bounding_box_complex(vector postfix) const +{ + vector stack(postfix.size()); + int i_stack = -1; + + for (auto& token : postfix) { + if (token == OP_UNION) { + stack[i_stack - 1] = stack[i_stack - 1] | stack[i_stack]; + i_stack--; + } else if (token == OP_INTERSECTION) { + stack[i_stack - 1] = stack[i_stack - 1] & stack[i_stack]; + i_stack--; + } else { + i_stack++; + stack[i_stack] = model::surfaces[abs(token) - 1]->bounding_box(token > 0); + } + } + + Ensures(i_stack == 0); + return stack.front(); +} + +//============================================================================== + +vector Region::surfaces() const +{ + if (simple_) { + return expression_; + } + + vector surfaces = expression_; + + auto it = std::find_if(surfaces.begin(), surfaces.end(), + [&](const auto& value) { return value >= OP_UNION; }); + + while (it != surfaces.end()) { + surfaces.erase(it); + + it = std::find_if(surfaces.begin(), surfaces.end(), + [&](const auto& value) { return value >= OP_UNION; }); + } + + return surfaces; +} + //============================================================================== // Non-method functions //============================================================================== diff --git a/src/geometry.cpp b/src/geometry.cpp index 216650ff1..29ca8b1bf 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -425,7 +425,7 @@ BoundaryInfo distance_to_boundary(Particle& p) // positive half-space were given in the region specification. Thus, we // have to explicitly check which half-space the particle would be // traveling into if the surface is crossed - if (c.simple_) { + if (c.is_simple()) { info.surface_index = level_surf_cross; } else { Position r_hit = r + d_surf * u; diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index c3458d469..261471984 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -154,9 +154,8 @@ void partition_universes() // Collect the set of surfaces in this universe. std::unordered_set surf_inds; for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->region_) { - if (token < OP_UNION) - surf_inds.insert(std::abs(token) - 1); + for (auto token : model::cells[i_cell]->surfaces()) { + surf_inds.insert(std::abs(token) - 1); } } diff --git a/src/universe.cpp b/src/universe.cpp index 873d03bb7..f8f9a82d8 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -98,13 +98,11 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find all of the z-planes in this universe. A set is used here for the // O(log(n)) insertions that will ensure entries are not repeated. for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->region_) { - if (token < OP_UNION) { - auto i_surf = std::abs(token) - 1; - const auto* surf = model::surfaces[i_surf].get(); - if (const auto* zplane = dynamic_cast(surf)) - surf_set.insert(i_surf); - } + for (auto token : model::cells[i_cell]->surfaces()) { + auto i_surf = std::abs(token) - 1; + const auto* surf = model::surfaces[i_surf].get(); + if (const auto* zplane = dynamic_cast(surf)) + surf_set.insert(i_surf); } } @@ -116,7 +114,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) for (auto i_cell : univ.cells_) { // It is difficult to determine the bounds of a complex cell, so add complex // cells to all partitions. - if (!model::cells[i_cell]->simple_) { + if (!model::cells[i_cell]->is_simple()) { for (auto& p : partitions_) p.push_back(i_cell); continue; @@ -125,18 +123,16 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find the tokens for bounding z-planes. int32_t lower_token = 0, upper_token = 0; double min_z, max_z; - for (auto token : model::cells[i_cell]->region_) { - if (token < OP_UNION) { - const auto* surf = model::surfaces[std::abs(token) - 1].get(); - if (const auto* zplane = dynamic_cast(surf)) { - if (lower_token == 0 || zplane->z0_ < min_z) { - lower_token = token; - min_z = zplane->z0_; - } - if (upper_token == 0 || zplane->z0_ > max_z) { - upper_token = token; - max_z = zplane->z0_; - } + for (auto token : model::cells[i_cell]->surfaces()) { + const auto* surf = model::surfaces[std::abs(token) - 1].get(); + if (const auto* zplane = dynamic_cast(surf)) { + if (lower_token == 0 || zplane->z0_ < min_z) { + lower_token = token; + min_z = zplane->z0_; + } + if (upper_token == 0 || zplane->z0_ > max_z) { + upper_token = token; + max_z = zplane->z0_; } } } From 27f2cb1b5ea4f5ada5a77de3e3d9312f4bfb421d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 26 Sep 2022 08:45:44 +0100 Subject: [PATCH 1005/2654] @pshriwise review suggestions Co-authored-by: Patrick Shriwise --- openmc/universe.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 16a251dee..34618a70a 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -708,7 +708,7 @@ class DAGMCUniverse(UniverseBase): Returns ------- - materials : List[str] + materials : list of str Sorted list of material names present in the DAGMC h5m file """ @@ -717,10 +717,7 @@ class DAGMCUniverse(UniverseBase): material_tags_hex=dagmc_file_contents['/tstt/tags/NAME'].get('values') material_tags_ascii=[] for tag in material_tags_hex: - raw_tag= np.array2string(tag) - tag_in_hex=raw_tag.replace("\\x00", '').replace("\\x", '') - tag_in_hex =tag_in_hex.lstrip("b'").rstrip("'") - candidate_tag = bytes.fromhex(tag_in_hex).decode() + candidate_tag = tag.tobytes().decode().replace('\x00', '') # tags might be for temperature or reflective surfaces if candidate_tag.startswith('mat:'): # removes first 4 characters as openmc.Material name should be From e63b4376628e978610c08081721974cd0b4ae90a Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 26 Sep 2022 16:11:53 +0100 Subject: [PATCH 1006/2654] added from domain to CylindricalMesh --- openmc/mesh.py | 60 +++++++++++++++++++++++ tests/unit_tests/test_mesh_from_domain.py | 40 +++++++++++++-- 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index a4c50a608..a64a2f8dd 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1137,6 +1137,66 @@ class CylindricalMesh(StructuredMesh): return mesh + @classmethod + def from_domain( + cls, + domain, + dimension=[100, 100, 100], + mesh_id=None, + name='' + ): + """Create mesh from an existing openmc cell, region, universe or + geometry by making use of the objects bounding box property. phi_grid + is set to have a range of 0 to 2π by default. + + Parameters + ---------- + domain : {openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry} + The object passed in will be used as a template for this mesh. The + bounding box of the property of the object passed will be used to + set the The r_grid, z_grid ranges. + dimension : Iterable of int + The number of equally spaced mesh cells in each direction (r_grid, + phi_grid, z_grid) + mesh_id : int + Unique identifier for the mesh + name : str + Name of the mesh + + Returns + ------- + openmc.RegularMesh + RegularMesh instance + + """ + cv.check_type( + "domain", + domain, + (openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry), + ) + + mesh = cls(mesh_id, name) + + # loaded once to avoid reading h5m file repeatedly + cached_bb = domain.bounding_box + max_bounding_box_radius = max( + [ + cached_bb[0][0], + cached_bb[0][1], + cached_bb[1][0], + cached_bb[1][1], + ] + ) + mesh.r_grid = np.linspace(0, max_bounding_box_radius, num=dimension[0]+1) + mesh.phi_grid = np.linspace(0, 2*np.pi, num=dimension[1]+1) + mesh.z_grid = np.linspace( + cached_bb[0][2], + cached_bb[1][2], + num=dimension[2]+1 + ) + + return mesh + def to_xml_element(self): """Return XML representation of the mesh diff --git a/tests/unit_tests/test_mesh_from_domain.py b/tests/unit_tests/test_mesh_from_domain.py index ce27288ad..64b9424b9 100644 --- a/tests/unit_tests/test_mesh_from_domain.py +++ b/tests/unit_tests/test_mesh_from_domain.py @@ -16,6 +16,22 @@ def test_reg_mesh_from_cell(): assert np.array_equal(mesh.upper_right, cell.bounding_box[1]) +def test_cylindrical_mesh_from_cell(): + """Tests a CylindricalMesh can be made from a Cell and the specified + dimensions are propagated through. Cell is not centralized""" + cy_surface = openmc. openmc.ZCylinder(r=50) + z_surface_1 = openmc. openmc.ZPlane(z0=30) + z_surface_2 = openmc. openmc.ZPlane(z0=0) + cell = openmc.Cell(region=-cy_surface & -z_surface_1 & +z_surface_2) + mesh = openmc.CylindricalMesh.from_domain(cell, dimension=[2, 4, 3]) + + assert isinstance(mesh, openmc.CylindricalMesh) + assert np.array_equal(mesh.dimension, (2, 4, 3)) + assert np.array_equal(mesh.r_grid, [0., 25., 50.]) + assert np.array_equal(mesh.phi_grid, [0., 0.5*np.pi, np.pi, 1.5*np.pi, 2.*np.pi]) + assert np.array_equal(mesh.z_grid, [0., 10., 20., 30.]) + + def test_reg_mesh_from_region(): """Tests a RegularMesh can be made from a Region and the default dimensions are propagated through. Region is not centralized""" @@ -29,9 +45,25 @@ def test_reg_mesh_from_region(): assert np.array_equal(mesh.upper_right, region.bounding_box[1]) +def test_cylindrical_mesh_from_region(): + """Tests a CylindricalMesh can be made from a Region and the specified + dimensions are propagated through. Cell is centralized""" + cy_surface = openmc. openmc.ZCylinder(r=6) + z_surface_1 = openmc. openmc.ZPlane(z0=30) + z_surface_2 = openmc. openmc.ZPlane(z0=-30) + cell = openmc.Cell(region=-cy_surface & -z_surface_1 & +z_surface_2) + mesh = openmc.CylindricalMesh.from_domain(cell, dimension=[6, 2, 3]) + + assert isinstance(mesh, openmc.CylindricalMesh) + assert np.array_equal(mesh.dimension, (6, 2, 3)) + assert np.array_equal(mesh.r_grid, [0., 1., 2., 3., 4., 5., 6.]) + assert np.array_equal(mesh.phi_grid, [0., np.pi, 2.*np.pi]) + assert np.array_equal(mesh.z_grid, [-30., -10., 10., 30.]) + + def test_reg_mesh_from_universe(): - """Tests a RegularMesh can be made from a Universe and the default dimensions - are propagated through. Universe is centralized""" + """Tests a RegularMesh can be made from a Universe and the default + dimensions are propagated through. Universe is centralized""" surface = openmc.Sphere(r=42) cell = openmc.Cell(region=-surface) universe = openmc.Universe(cells=[cell]) @@ -44,8 +76,8 @@ def test_reg_mesh_from_universe(): def test_reg_mesh_from_geometry(): - """Tests a RegularMesh can be made from a Geometry and the default dimensions - are propagated through. Geometry is centralized""" + """Tests a RegularMesh can be made from a Geometry and the default + dimensions are propagated through. Geometry is centralized""" surface = openmc.Sphere(r=42) cell = openmc.Cell(region=-surface) universe = openmc.Universe(cells=[cell]) From 4e5d9bf5963fb8a857057fdacb16af7a5e0ecce1 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 26 Sep 2022 16:17:48 +0100 Subject: [PATCH 1007/2654] fixed typo --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index a64a2f8dd..0dc390ebe 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1154,7 +1154,7 @@ class CylindricalMesh(StructuredMesh): domain : {openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry} The object passed in will be used as a template for this mesh. The bounding box of the property of the object passed will be used to - set the The r_grid, z_grid ranges. + set the r_grid, z_grid ranges. dimension : Iterable of int The number of equally spaced mesh cells in each direction (r_grid, phi_grid, z_grid) From 1395b50d49099b8b011c9cb097e51e237c4699e3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 14:52:51 -0500 Subject: [PATCH 1008/2654] Store decay sources on openmc.deplete.Nuclide --- openmc/deplete/chain.py | 2 ++ openmc/deplete/nuclide.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index 217c9cac0..ce376a181 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -420,6 +420,8 @@ class Chain: # Append decay mode nuclide.add_decay_mode(type_, target, br) + nuclide.sources = data.sources + fissionable = False if parent in reactions: reactions_available = set(reactions[parent].keys()) diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py index 04e0c26c5..250861985 100644 --- a/openmc/deplete/nuclide.py +++ b/openmc/deplete/nuclide.py @@ -16,6 +16,7 @@ except ImportError: import numpy as np from openmc.checkvalue import check_type +from openmc.stats import Univariate __all__ = [ "DecayTuple", "ReactionTuple", "Nuclide", "FissionYield", @@ -101,6 +102,9 @@ class Nuclide: reactions : list of openmc.deplete.ReactionTuple Reaction information. Each element of the list is a named tuple with attribute 'type', 'target', 'Q', and 'branching_ratio'. + sources : dict + Dictionary mapping particle type as string to energy distribution of + decay source represented as :class:`openmc.stats.Univariate` yield_data : FissionYieldDistribution or None Fission product yields at tabulated energies for this nuclide. Can be treated as a nested dictionary ``{energy: {product: yield}}`` @@ -120,6 +124,9 @@ class Nuclide: # Reaction paths self.reactions = [] + # Decay sources + self.sources = {} + # Neutron fission yields, if present self._yield_data = None @@ -237,6 +244,12 @@ class Nuclide: branching_ratio = float(decay_elem.get('branching_ratio')) nuc.decay_modes.append(DecayTuple(d_type, target, branching_ratio)) + # Check for sources + for src_elem in element.iter('source'): + particle = src_elem.get('particle') + distribution = Univariate.from_xml_element(src_elem) + nuc.sources[particle] = distribution + # Check for reaction paths for reaction_elem in element.iter('reaction'): r_type = reaction_elem.get('type') @@ -302,6 +315,19 @@ class Nuclide: mode_elem.set('target', daughter) mode_elem.set('branching_ratio', str(br)) + # Write decay sources + if self.sources: + for particle, source in self.sources.items(): + # TODO: Ugly hack to deal with the fact that + # 'source.to_xml_element' will return an xml.etree object + # whereas here lxml is being used preferentially. We should just + # switch to use lxml everywhere, + import xml.etree.ElementTree as etree + src_elem_xmletree = source.to_xml_element('source') + src_elem = ET.fromstring(etree.tostring(src_elem_xmletree)) + src_elem.set('particle', particle) + elem.append(src_elem) + elem.set('reactions', str(len(self.reactions))) for rx, daughter, Q, br in self.reactions: rx_elem = ET.SubElement(elem, 'reaction') From a917fd94c15bde5fddff8a72f74e5f2ada17f882 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 18 Jul 2022 14:47:37 -0500 Subject: [PATCH 1009/2654] Add decay_photon_source property on Material --- openmc/data/decay.py | 43 ++++++++++++++++++++++++++++++++++++++++++- openmc/material.py | 12 ++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 2c2505bf5..c372b72e4 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -1,15 +1,19 @@ from collections.abc import Iterable from io import StringIO from math import log +from pathlib import Path import re from warnings import warn +from xml.etree import ElementTree as ET import numpy as np from uncertainties import ufloat, UFloat +import openmc import openmc.checkvalue as cv +from openmc.exceptions import DataError from openmc.mixin import EqualityMixin -from openmc.stats import Discrete, Tabular, combine_distributions +from openmc.stats import Discrete, Tabular, Univariate, combine_distributions from .data import ATOMIC_SYMBOL, ATOMIC_NUMBER from .function import INTERPOLATION_SCHEME from .endf import Evaluation, get_head_record, get_list_record, get_tab1_record @@ -570,3 +574,40 @@ class Decay(EqualityMixin): self._sources = merged_sources return self._sources + + +_DECAY_PHOTON_SOURCE = {} + + +def decay_photon_source(nuclide): + """Get photon source from the decay of a nuclide + + This function relies on data stored in a depletion chain. Before calling it + for the first time, you need to ensure that a depletion chain has been + specified in openmc.config['chain_file']. + + Parameters + ---------- + nuclide : str + Name of nuclide, e.g., 'Co58' + + Returns + ------- + openmc.stats.Univariate + Distribution of energies in [eV] of photons emitted from decay + """ + if not _DECAY_PHOTON_SOURCE: + chain_file = openmc.config.get('chain_file') + if chain_file is None: + raise DataError( + "A depletion chain file must be specified with " + "openmc.config['chain_file'] in order to load decay data." + ) + + from openmc.deplete import Chain + chain = Chain.from_xml(chain_file) + for nuc in chain.nuclides: + if 'photon' in nuc.sources: + _DECAY_PHOTON_SOURCE[nuc.name] = nuc.sources['photon'] + + return _DECAY_PHOTON_SOURCE.get(nuclide) diff --git a/openmc/material.py b/openmc/material.py index 1b2b46a73..b5c9d70f9 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -255,6 +255,18 @@ class Material(IDManagerMixin): / openmc.data.AVOGADRO return density*self.volume + @property + def decay_photon_source(self): + atoms = self.get_nuclide_atoms() + dists = [] + probs = [] + for nuc, num_atoms in atoms.items(): + source_per_atom = openmc.data.decay_photon_source(nuc) + if source_per_atom is not None: + dists.append(source_per_atom) + probs.append(num_atoms) + return openmc.data.combine_distributions(dists, probs) + @classmethod def from_hdf5(cls, group: h5py.Group): """Create material from HDF5 group From ed6fbe37f55a38ade7fd442054c408d95a431f0d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 30 Aug 2022 21:16:58 -0500 Subject: [PATCH 1010/2654] Rename mat_to_ind -> index_mat, nuc_to_ind -> index_nuc in StepResult --- openmc/deplete/stepresult.py | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index db5260c80..b26dfb44c 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -42,9 +42,9 @@ class StepResult: The reaction rates for each substep. volume : OrderedDict of str to float Dictionary mapping mat id to volume. - mat_to_ind : OrderedDict of str to int + index_mat : OrderedDict of str to int A dictionary mapping mat ID as string to index. - nuc_to_ind : OrderedDict of str to int + index_nuc : OrderedDict of str to int A dictionary mapping nuclide name as string to index. mat_to_hdf5_ind : OrderedDict of str to int A dictionary mapping mat ID as string to global index. @@ -67,8 +67,8 @@ class StepResult: self.volume = None self.proc_time = None - self.mat_to_ind = None - self.nuc_to_ind = None + self.index_mat = None + self.index_nuc = None self.mat_to_hdf5_ind = None self.data = None @@ -98,9 +98,9 @@ class StepResult: if isinstance(mat, openmc.Material): mat = str(mat.id) if isinstance(mat, str): - mat = self.mat_to_ind[mat] + mat = self.index_mat[mat] if isinstance(nuc, str): - nuc = self.nuc_to_ind[nuc] + nuc = self.index_nuc[nuc] return self.data[stage, mat, nuc] @@ -120,19 +120,19 @@ class StepResult: """ stage, mat, nuc = pos if isinstance(mat, str): - mat = self.mat_to_ind[mat] + mat = self.index_mat[mat] if isinstance(nuc, str): - nuc = self.nuc_to_ind[nuc] + nuc = self.index_nuc[nuc] self.data[stage, mat, nuc] = val @property def n_mat(self): - return len(self.mat_to_ind) + return len(self.index_mat) @property def n_nuc(self): - return len(self.nuc_to_ind) + return len(self.index_nuc) @property def n_hdf5_mats(self): @@ -160,8 +160,8 @@ class StepResult: """ self.volume = copy.deepcopy(volume) - self.nuc_to_ind = {nuc: i for i, nuc in enumerate(nuc_list)} - self.mat_to_ind = {mat: i for i, mat in enumerate(burn_list)} + self.index_nuc = {nuc: i for i, nuc in enumerate(nuc_list)} + self.index_mat = {mat: i for i, mat in enumerate(burn_list)} self.mat_to_hdf5_ind = {mat: i for i, mat in enumerate(full_burn_list)} # Create storage array @@ -186,10 +186,10 @@ class StepResult: """ new = StepResult() new.volume = {lm: self.volume[lm] for lm in local_materials} - new.mat_to_ind = {mat: idx for (idx, mat) in enumerate(local_materials)} + new.index_mat = {mat: idx for (idx, mat) in enumerate(local_materials)} # Direct transfer - direct_attrs = ("time", "k", "source_rate", "nuc_to_ind", + direct_attrs = ("time", "k", "source_rate", "index_nuc", "mat_to_hdf5_ind", "proc_time") for attr in direct_attrs: setattr(new, attr, getattr(self, attr)) @@ -239,11 +239,11 @@ class StepResult: """ # Create and save the 5 dictionaries: # quantities - # self.mat_to_ind -> self.volume (TODO: support for changing volumes) - # self.nuc_to_ind + # self.index_mat -> self.volume (TODO: support for changing volumes) + # self.index_nuc # reactions - # self.rates[0].nuc_to_ind (can be different from above, above is superset) - # self.rates[0].react_to_ind + # self.rates[0].index_nuc (can be different from above, above is superset) + # self.rates[0].index_rx # these are shared by every step of the simulation, and should be deduplicated. # Store concentration mat and nuclide dictionaries (along with volumes) @@ -252,7 +252,7 @@ class StepResult: handle.attrs['filetype'] = np.string_('depletion results') mat_list = sorted(self.mat_to_hdf5_ind, key=int) - nuc_list = sorted(self.nuc_to_ind) + nuc_list = sorted(self.index_nuc) rxn_list = sorted(self.rates[0].index_rx) n_mats = self.n_hdf5_mats @@ -272,7 +272,7 @@ class StepResult: for nuc in nuc_list: nuc_single_group = nuc_group.create_group(nuc) - nuc_single_group.attrs["atom number index"] = self.nuc_to_ind[nuc] + nuc_single_group.attrs["atom number index"] = self.index_nuc[nuc] if nuc in self.rates[0].index_nuc: nuc_single_group.attrs["reaction rate index"] = self.rates[0].index_nuc[nuc] @@ -367,13 +367,13 @@ class StepResult: proc_time_dset.resize(proc_shape) # If nothing to write, just return - if len(self.mat_to_ind) == 0: + if len(self.index_mat) == 0: return # Add data # Note, for the last step, self.n_stages = 1, even if n_stages != 1. n_stages = self.n_stages - inds = [self.mat_to_hdf5_ind[mat] for mat in self.mat_to_ind] + inds = [self.mat_to_hdf5_ind[mat] for mat in self.index_mat] low = min(inds) high = max(inds) for i in range(n_stages): @@ -427,8 +427,8 @@ class StepResult: # Reconstruct dictionaries results.volume = OrderedDict() - results.mat_to_ind = OrderedDict() - results.nuc_to_ind = OrderedDict() + results.index_mat = OrderedDict() + results.index_nuc = OrderedDict() rxn_nuc_to_ind = OrderedDict() rxn_to_ind = OrderedDict() @@ -437,11 +437,11 @@ class StepResult: ind = mat_handle.attrs["index"] results.volume[mat] = vol - results.mat_to_ind[mat] = ind + results.index_mat[mat] = ind for nuc, nuc_handle in handle["/nuclides"].items(): ind_atom = nuc_handle.attrs["atom number index"] - results.nuc_to_ind[nuc] = ind_atom + results.index_nuc[nuc] = ind_atom if "reaction rate index" in nuc_handle.attrs: rxn_nuc_to_ind[nuc] = nuc_handle.attrs["reaction rate index"] @@ -452,7 +452,7 @@ class StepResult: results.rates = [] # Reconstruct reactions for i in range(results.n_stages): - rate = ReactionRates(results.mat_to_ind, rxn_nuc_to_ind, rxn_to_ind, True) + rate = ReactionRates(results.index_mat, rxn_nuc_to_ind, rxn_to_ind, True) rate[:] = handle["/reaction rates"][step, i, :, :, :] results.rates.append(rate) From 7af56d8db22e552596989d691e44f6084081876f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 30 Aug 2022 21:17:50 -0500 Subject: [PATCH 1011/2654] Add get_material method on StepResult --- openmc/deplete/stepresult.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index b26dfb44c..41086baf3 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -6,6 +6,7 @@ timestep. from collections import OrderedDict import copy +import warnings import h5py import numpy as np @@ -198,6 +199,32 @@ class StepResult: new.rates = [r[ranges] for r in self.rates] return new + def get_material(self, mat_id): + """Return material object for given depleted composition + + Parameters + ---------- + mat_id : str + Material ID as a string + + Returns + ------- + openmc.Material + Equivalent material + """ + with warnings.catch_warnings(): + warnings.simplefilter('ignore', openmc.IDWarning) + material = openmc.Material(material_id=int(mat_id)) + vol = self.volume[mat_id] + for nuc, _ in sorted(self.index_nuc.items(), key=lambda x: x[1]): + atoms = self[0, mat_id, nuc] + if atoms < 0.0: + continue + atom_per_bcm = atoms / vol * 1e-24 + material.add_nuclide(nuc, atom_per_bcm) + material.volume = vol + return material + def export_to_hdf5(self, filename, step): """Export results to an HDF5 file From ce1abc5350e9e9612bb5e3876b52ff843388160c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Sep 2022 22:21:48 -0500 Subject: [PATCH 1012/2654] Documentation updates --- docs/source/pythonapi/data.rst | 1 + openmc/data/decay.py | 4 +++- openmc/deplete/stepresult.py | 2 ++ openmc/material.py | 20 ++++++++++++++------ 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index c7c65e14a..2ee08c7f5 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -63,6 +63,7 @@ Core Functions atomic_weight combine_distributions decay_constant + decay_photon_source dose_coefficients gnd_name half_life diff --git a/openmc/data/decay.py b/openmc/data/decay.py index c372b72e4..eafa84f66 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -579,13 +579,15 @@ class Decay(EqualityMixin): _DECAY_PHOTON_SOURCE = {} -def decay_photon_source(nuclide): +def decay_photon_source(nuclide: str) -> Univariate: """Get photon source from the decay of a nuclide This function relies on data stored in a depletion chain. Before calling it for the first time, you need to ensure that a depletion chain has been specified in openmc.config['chain_file']. + .. versionadded:: 0.14.0 + Parameters ---------- nuclide : str diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index 41086baf3..e462f1754 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -202,6 +202,8 @@ class StepResult: def get_material(self, mat_id): """Return material object for given depleted composition + .. versionadded:: 0.14.0 + Parameters ---------- mat_id : str diff --git a/openmc/material.py b/openmc/material.py index b5c9d70f9..53bf676d5 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -18,6 +18,7 @@ import openmc.checkvalue as cv from ._xml import clean_indentation, reorder_attributes from .mixin import IDManagerMixin from openmc.checkvalue import PathLike +from openmc.stats import Univariate # Units for density supported by OpenMC @@ -34,10 +35,10 @@ class Material(IDManagerMixin): To create a material, one should create an instance of this class, add nuclides or elements with :meth:`Material.add_nuclide` or :meth:`Material.add_element`, respectively, and set the total material - density with :meth:`Material.set_density()`. Alternatively, you can - use :meth:`Material.add_components()` to pass a dictionary - containing all the component information. The material can then be - assigned to a cell using the :attr:`Cell.fill` attribute. + density with :meth:`Material.set_density()`. Alternatively, you can use + :meth:`Material.add_components()` to pass a dictionary containing all the + component information. The material can then be assigned to a cell using the + :attr:`Cell.fill` attribute. Parameters ---------- @@ -91,6 +92,13 @@ class Material(IDManagerMixin): fissionable_mass : float Mass of fissionable nuclides in the material in [g]. Requires that the :attr:`volume` attribute is set. + decay_photon_source : openmc.stats.Univariate + Energy distribution of photons emitted from decay of unstable nuclides + within the material. The integral of this distribution is the total + intensity of the photon source. + + .. versionadded:: 0.14.0 + """ next_id = 1 @@ -256,7 +264,7 @@ class Material(IDManagerMixin): return density*self.volume @property - def decay_photon_source(self): + def decay_photon_source(self) -> Univariate: atoms = self.get_nuclide_atoms() dists = [] probs = [] @@ -832,7 +840,7 @@ class Material(IDManagerMixin): for nuclide in self._nuclides: if nuclide.name not in matching_nuclides: matching_nuclides.append(nuclide.name) - + return matching_nuclides def get_nuclide_densities(self): From 52eef1adf5a764fe3d8e88898282cf29d7024eb1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 26 Sep 2022 12:23:40 -0500 Subject: [PATCH 1013/2654] Reset decay source if config['chain_file'] changes --- openmc/config.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmc/config.py b/openmc/config.py index 628df7edc..3c031ee7d 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -4,6 +4,7 @@ from pathlib import Path import warnings from openmc.data import DataLibrary +from openmc.data.decay import _DECAY_PHOTON_SOURCE __all__ = ["config"] @@ -22,6 +23,10 @@ class _Config(MutableMapping): del os.environ['OPENMC_CROSS_SECTIONS'] elif key == 'mg_cross_sections': del os.environ['OPENMC_MG_CROSS_SECTIONS'] + elif key == 'chain_file': + del os.environ['OPENMC_CHAIN_FILE'] + # Reset photon source data since it relies on chain file + _DECAY_PHOTON_SOURCE.clear() def __setitem__(self, key, value): if key == 'cross_sections': @@ -34,6 +39,8 @@ class _Config(MutableMapping): elif key == 'chain_file': self._set_path(key, value) os.environ['OPENMC_CHAIN_FILE'] = str(value) + # Reset photon source data since it relies on chain file + _DECAY_PHOTON_SOURCE.clear() else: raise KeyError(f'Unrecognized config key: {key}') From 95d182b73f6ef68e6e1ca3c2d75ae74183721a7c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 26 Sep 2022 12:24:13 -0500 Subject: [PATCH 1014/2654] Add tests for decay photon source --- tests/chain_simple.xml | 12 ++++++++++++ tests/unit_tests/test_data_decay.py | 20 ++++++++++++++++++- tests/unit_tests/test_deplete_chain.py | 10 ++++++++++ tests/unit_tests/test_material.py | 27 ++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/tests/chain_simple.xml b/tests/chain_simple.xml index c2e50a370..ba42b5542 100644 --- a/tests/chain_simple.xml +++ b/tests/chain_simple.xml @@ -3,10 +3,16 @@ + + 3696.125 4095.822 4477.27 5097.122 29452.1 29781.3 33566.5 33629.4 33865.1 33878.5 34395.3 34408.0 34486.2 34488.2 112780.0 113150.0 162650.0 165740.0 184490.0 197190.0 220502.0 229720.0 247500.0 254740.0 264260.0 288451.0 290270.0 304910.0 305830.0 326000.0 333600.0 342520.0 361850.0 403030.0 414830.0 417633.0 429930.0 433741.0 451630.0 530800.0 546557.0 575970.0 588280.0 616900.0 649850.0 656090.0 679220.0 684600.0 690130.0 707920.0 785480.0 795500.0 797710.0 807200.0 836804.0 960290.0 961430.0 971960.0 972620.0 995090.0 1038760.0 1096860.0 1101580.0 1124000.0 1131511.0 1151510.0 1159900.0 1169040.0 1225600.0 1240470.0 1254800.0 1260409.0 1315770.0 1334800.0 1343660.0 1367890.0 1441800.0 1448350.0 1457560.0 1502790.0 1521990.0 1543700.0 1566410.0 1678027.0 1706459.0 1791196.0 1830690.0 1845300.0 1927300.0 1948490.0 2045880.0 2112400.0 2151500.0 2189400.0 2255457.0 2408650.0 2466070.0 2477100.0 9.714352819815078e-10 7.460941651551526e-09 6.047882056201745e-09 8.510389107205747e-10 3.7979729633684727e-08 7.033747061198817e-08 6.602815946851458e-09 1.2800909198245071e-08 6.513060244589454e-11 8.894667887850525e-11 1.3843783302275766e-09 2.700005498135763e-09 1.2141115256573815e-11 1.654893875618862e-11 3.7007705885806645e-09 2.0186021392258173e-09 2.859686363903241e-09 9.16781804898392e-09 6.896890642354875e-09 9.588360161322631e-09 5.130613770532286e-07 7.06510748729036e-08 8.410842246774237e-09 6.7286737974193905e-09 5.3829390379355124e-08 9.083709626516178e-07 8.915492781580693e-08 9.251926471451662e-09 2.783988783682273e-08 6.728673797419391e-10 1.093409492080651e-08 2.5232526740322717e-10 5.467047460403255e-08 6.812782219887132e-08 8.83138435911295e-08 1.0345335963532313e-06 8.915492781580693e-08 1.623292553627428e-07 9.251926471451663e-08 9.251926471451662e-09 2.0942997194467853e-06 3.784879011048407e-08 1.513951604419363e-08 1.093409492080651e-08 1.337323917237104e-07 2.186818984161302e-08 1.5980600268871052e-08 6.7286737974193905e-09 3.784879011048407e-08 1.9344937167580748e-07 4.457746390790346e-08 6.7286737974193905e-09 5.0465053480645434e-08 1.3457347594838781e-08 1.9597262434983976e-06 1.0093010696129087e-08 4.289529545854862e-08 2.607361096500014e-07 3.53255374364518e-07 4.541854813258089e-08 2.329803302356464e-06 2.607361096500014e-08 4.7100716581935733e-07 1.059766123093554e-06 6.6193328482113254e-06 4.205421123387119e-10 3.027903208838726e-08 2.565306885266143e-07 1.2616263370161358e-08 2.649415307733885e-07 3.3643368987096953e-09 8.410842246774237e-06 1.934493716758075e-08 9.251926471451662e-09 2.2709274066290446e-08 1.7830985563161385e-07 5.046505348064544e-09 9.251926471451663e-08 2.5400743585258203e-06 3.154065842540339e-07 1.093409492080651e-08 7.569758022096815e-09 3.784879011048407e-07 2.8008104681758214e-06 1.2027504412887161e-06 2.26251656438227e-06 1.6989901338483962e-07 1.6821684493548476e-09 8.663167514177466e-08 1.8503852942903323e-08 2.5568960430193683e-07 2.0186021392258175e-08 6.560456952483906e-09 3.784879011048407e-09 1.7999202408096872e-07 2.800810468175822e-07 2.1027105616935597e-08 4.205421123387119e-10 + + + 3860.681 4271.629 4683.641 5336.674 30621.8 30978.9 34925.5 34994.3 35237.3 35252.0 35803.0 35817.2 35899.4 35901.8 158197.0 200190.0 249794.0 358390.0 373130.0 407990.0 454200.0 573320.0 608185.0 654432.0 731520.0 812630.0 1062410.0 7.994251137825248e-09 6.327910906791491e-08 5.1272731446173495e-08 7.363690277270275e-09 3.054968676386751e-07 5.64321319541835e-07 5.347473347583344e-08 1.0365225698627538e-07 5.533995748532528e-10 7.536429363113684e-10 1.1251670022820477e-08 2.1931143930358873e-08 1.0789862609689208e-10 1.4667031416354672e-10 6.085892914653786e-08 2.4646918345949914e-09 1.895916795842301e-05 4.644996149813638e-08 3.223058552931912e-09 7.545748847452359e-08 7.583667183369205e-10 1.0048359017964195e-09 6.10485208261221e-07 9.479583979211505e-09 1.1565092454638037e-08 1.478815100756995e-08 8.531625581290355e-10 + @@ -28,6 +34,9 @@ + + 3065.349 12960.11 13197.49 16125.43 19185.05 19590.0 31600.0 34700.0 41400.0 41960.0 51220.0 54100.0 54250.0 64350.0 72700.0 75020.0 76198.0 90330.0 93795.0 96090.0 105278.0 106074.0 106608.0 106771.0 108948.0 109154.0 109160.0 109395.0 109433.0 115450.0 120350.0 136550.0 140760.0 142400.0 143760.0 150930.0 163330.0 173300.0 182610.0 185715.0 194940.0 198900.0 202110.0 205311.0 215280.0 221380.0 228780.0 233500.0 240870.0 246840.0 266450.0 275129.0 275430.0 281420.0 282920.0 289560.0 291650.0 301700.0 317100.0 343500.0 345900.0 356030.0 387820.0 410290.0 428710.0 448400.0 1.4211820389290126e-18 3.695705148646686e-18 4.752472005970374e-19 4.0825252294602915e-18 8.998127221991115e-19 1.9035285506819052e-21 5.305446177665699e-21 1.1547147563154756e-20 9.362552078233586e-21 1.86835843588509e-20 1.0610892355331398e-20 2.736290732002608e-22 4.776811520523089e-21 3.977552295559136e-21 3.432935762018982e-20 1.872510415646717e-20 2.4966805541956234e-21 1.0265454754703584e-18 1.7575878976520235e-18 2.839974130397521e-20 2.1057468800839102e-19 4.1342252420362975e-19 7.098565272539688e-21 8.20050332279016e-21 5.276915360632628e-20 1.0602918581811435e-19 4.806110066826575e-19 2.0521431485853304e-21 2.375669880669523e-21 9.362552078233586e-21 8.267152210184412e-21 3.745020831293435e-21 6.865871524037964e-20 1.5604253463722645e-21 3.420452359248004e-18 2.4966805541956232e-20 1.5853921519142206e-18 1.8725104156467174e-21 1.0610892355331397e-19 1.7851265962498703e-17 1.966135936429053e-19 1.3107572909527022e-20 3.370518748164091e-19 1.5635461970650089e-18 9.050467008959134e-21 3.745020831293434e-20 2.18459548492117e-21 9.050467008959134e-21 2.3406380195583967e-20 1.6540508671546e-20 1.8725104156467174e-21 1.622842360227155e-20 2.18459548492117e-21 1.8725104156467174e-21 1.8725104156467174e-21 2.18459548492117e-21 1.2483402770978116e-20 1.5604253463722645e-21 3.120850692744529e-22 9.362552078233587e-22 1.2483402770978116e-20 1.5604253463722645e-21 1.2483402770978116e-20 9.362552078233587e-22 3.120850692744529e-22 3.120850692744529e-22 + 2.53000e-02 @@ -38,6 +47,9 @@ + + 3061.32 12959.8 13440.07 16150.05 19148.83 49550.0 90330.0 93795.0 105278.0 106074.0 106608.0 106771.0 108948.0 109154.0 109395.0 109433.0 113500.0 5.3130501476983077e-20 1.4936931167066328e-19 1.943509007980312e-20 1.8224649880365157e-19 4.0452400597373603e-20 3.146222282132249e-21 3.300026341588747e-23 5.444173877278485e-23 6.3486292118621375e-24 1.2400176384733938e-23 2.124537722121886e-25 2.4542156071495764e-25 1.5792541400719878e-24 3.1731991718126067e-24 6.141568457919309e-26 7.109808533300877e-26 5.014291762148272e-22 + 2.53000e-02 diff --git a/tests/unit_tests/test_data_decay.py b/tests/unit_tests/test_data_decay.py index f0bda1bd9..e658c16d3 100644 --- a/tests/unit_tests/test_data_decay.py +++ b/tests/unit_tests/test_data_decay.py @@ -1,13 +1,14 @@ #!/usr/bin/env python -from collections.abc import Mapping import os from math import log +from pathlib import Path import numpy as np import pytest from uncertainties import ufloat import openmc.data +from openmc.exceptions import DataError def ufloat_close(a, b): @@ -126,3 +127,20 @@ def test_sources(ba137m, nb90): # Nb90 decays by β+ and should emit positrons, electrons, and photons sources = nb90.sources assert len(set(sources.keys()) ^ {'positron', 'electron', 'photon'}) == 0 + + +def test_decay_photon_source(): + # If chain file is not set, we should get a data error + if 'chain_file' in openmc.config: + del openmc.config['chain_file'] + with pytest.raises(DataError): + openmc.data.decay_photon_source('135') + + # Set chain file to simple chain + openmc.config['chain_file'] = Path(__file__).parents[1] / "chain_simple.xml" + + # Check strength of I135 source and presence of specific spectral line + src = openmc.data.decay_photon_source('I135') + assert isinstance(src, openmc.stats.Discrete) + assert src.integral() == pytest.approx(3.920996223799345e-05) + assert 1260409. in src.x diff --git a/tests/unit_tests/test_deplete_chain.py b/tests/unit_tests/test_deplete_chain.py index 4bfdaa63e..32c3e2809 100644 --- a/tests/unit_tests/test_deplete_chain.py +++ b/tests/unit_tests/test_deplete_chain.py @@ -9,6 +9,7 @@ from pathlib import Path import numpy as np from openmc.mpi import comm from openmc.deplete import Chain, reaction_rates, nuclide, cram, pool +from openmc.stats import Discrete import pytest from tests import cdtemp @@ -476,6 +477,15 @@ def gnd_simple_chain(): return Chain.from_xml(chainfile) +def test_chain_sources(gnd_simple_chain): + i135 = gnd_simple_chain['I135'] + assert isinstance(i135.sources, dict) + assert list(i135.sources.keys()) == ['photon'] + photon_src = i135.sources['photon'] + assert isinstance(photon_src, Discrete) + assert photon_src.integral() == pytest.approx(3.920996223799345e-05) + + def test_reduce(gnd_simple_chain, endf_chain): ref_U5 = gnd_simple_chain["U235"] ref_iodine = gnd_simple_chain["I135"] diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 7b8a60629..352017c8d 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -1,8 +1,10 @@ from collections import defaultdict +from pathlib import Path import pytest import openmc +from openmc.data import decay_photon_source import openmc.examples import openmc.model import openmc.stats @@ -541,3 +543,28 @@ def test_get_activity(): # volume is required to calculate total activity m4.volume = 10. assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq] + + +def test_decay_photon_source(): + # Set chain file for testing + openmc.config['chain_file'] = Path(__file__).parents[1] / 'chain_simple.xml' + + # Material representing single atom of I135, Xe135, and Cs135 + m = openmc.Material() + m.add_nuclide('I135', 1.0e-24) + m.add_nuclide('Xe135', 1.0e-24) + m.add_nuclide('Cs135', 1.0e-24) + m.volume = 1.0 + + # Get decay photon source and make sure it's the right type + src = m.decay_photon_source + assert isinstance(src, openmc.stats.Discrete) + + # With a single atom of each, the intensity of the photon source should be + # equal to sum(I*λ) + def intensity(src): + return src.integral() if src is not None else 0.0 + + assert src.integral() == pytest.approx(sum( + intensity(decay_photon_source(nuc)) for nuc in m.get_nuclides() + )) From 89c33923c1a46a35a5a1c0ad2115671b72d15228 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 26 Sep 2022 12:33:26 -0500 Subject: [PATCH 1015/2654] Add test for StepResult.get_material --- tests/unit_tests/test_deplete_resultslist.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 63073cf57..e13944e03 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -133,3 +133,17 @@ def test_get_steps(unit): actual = results.get_step_where( times[-1] * 100, time_units=unit, atol=inf, rtol=inf) assert actual == times.size - 1 + + +def test_stepresult_get_material(res): + # Get material at first timestep + step_result = res[0] + mat1 = step_result.get_material("1") + assert mat1.id == 1 + assert mat1.volume == step_result.volume["1"] + + # Spot check number densities + densities = mat1.get_nuclide_atom_densities() + assert densities['Xe135'] == pytest.approx(1e-14) + assert densities['I135'] == pytest.approx(1e-21) + assert densities['U234'] == pytest.approx(1.00506e-05) From aff6316642ccb3ba11b5c474c191f85ecb1ce436 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 5 Aug 2022 11:39:48 -0500 Subject: [PATCH 1016/2654] Simple rejection based on a vector of cell IDs --- include/openmc/source.h | 9 +++++++-- openmc/source.py | 29 +++++++++++++++++++++++++++- src/source.cpp | 42 +++++++++++++++++++++++++++++------------ 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index 18fddc689..d48b4e4ae 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -4,6 +4,8 @@ #ifndef OPENMC_SOURCE_H #define OPENMC_SOURCE_H +#include + #include "pugixml.hpp" #include "openmc/distribution_multi.h" @@ -51,13 +53,15 @@ public: }; //============================================================================== -//! Source composed of independent spatial, angle, energy, and time distributions +//! Source composed of independent spatial, angle, energy, and time +//! distributions //============================================================================== class IndependentSource : public Source { public: // Constructors - IndependentSource(UPtrSpace space, UPtrAngle angle, UPtrDist energy, UPtrDist time); + IndependentSource( + UPtrSpace space, UPtrAngle angle, UPtrDist energy, UPtrDist time); explicit IndependentSource(pugi::xml_node node); //! Sample from the external source distribution @@ -82,6 +86,7 @@ private: UPtrAngle angle_; //!< Angular distribution UPtrDist energy_; //!< Energy distribution UPtrDist time_; //!< Time distribution + std::unordered_set cells_; //!< Cells to reject from }; //============================================================================== diff --git a/openmc/source.py b/openmc/source.py index bd4c28ba4..6ec1338a3 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -5,6 +5,7 @@ from xml.etree import ElementTree as ET import numpy as np import h5py +import openmc import openmc.checkvalue as cv from openmc.stats.multivariate import UnitSphere, Spatial from openmc.stats.univariate import Univariate @@ -36,6 +37,8 @@ class Source: Strength of the source particle : {'neutron', 'photon'} Source particle type + cells : iterable of int or openmc.Cell + Cells to reject based on Attributes ---------- @@ -57,11 +60,14 @@ class Source: Strength of the source particle : {'neutron', 'photon'} Source particle type + cells : iterable of int or openmc.Cell + Cells to reject based on """ def __init__(self, space=None, angle=None, energy=None, time=None, filename=None, - library=None, parameters=None, strength=1.0, particle='neutron'): + library=None, parameters=None, strength=1.0, particle='neutron', + cells=None): self._space = None self._angle = None self._energy = None @@ -69,6 +75,7 @@ class Source: self._file = None self._library = None self._parameters = None + self._cells = [] if space is not None: self.space = space @@ -86,6 +93,8 @@ class Source: self.parameters = parameters self.strength = strength self.particle = particle + if cells is not None: + self.cells = cells @property def file(self): @@ -123,6 +132,10 @@ class Source: def particle(self): return self._particle + @property + def cells(self): + return self._cells + @file.setter def file(self, filename): cv.check_type('source file', filename, str) @@ -169,6 +182,13 @@ class Source: cv.check_value('source particle', particle, ['neutron', 'photon']) self._particle = particle + @cells.setter + def cells(self, cells): + self._cells = [ + cell.id if isinstance(cell, openmc.Cell) else cell + for cell in cells + ] + def to_xml_element(self): """Return XML representation of the source @@ -196,6 +216,9 @@ class Source: element.append(self.energy.to_xml_element('energy')) if self.time is not None: element.append(self.time.to_xml_element('time')) + if self.cells: + cells_elem = ET.SubElement(element, "cells") + cells_elem.text = ' '.join(str(x) for x in self.cells) return element @classmethod @@ -251,6 +274,10 @@ class Source: if time is not None: source.time = Univariate.from_xml_element(time) + cells = elem.find('cells') + if cells is not None: + source.cells = [int(x) for x in cells.text.split()] + return source diff --git a/src/source.cpp b/src/source.cpp index efc9e4598..17bef4377 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -16,8 +16,10 @@ #include "openmc/bank.h" #include "openmc/capi.h" #include "openmc/cell.h" +#include "openmc/container_util.h" #include "openmc/error.h" #include "openmc/file_utils.h" +#include "openmc/geometry.h" #include "openmc/hdf5_interface.h" #include "openmc/material.h" #include "openmc/memory.h" @@ -151,29 +153,36 @@ IndependentSource::IndependentSource(pugi::xml_node node) double p[] {1.0}; time_ = UPtrDist {new Discrete {T, p, 1}}; } + + // Check for cells to reject from + if (check_for_node(node, "cells")) { + auto cells = get_node_array(node, "cells"); + cells_.insert(cells.cbegin(), cells.cend()); + } } } SourceSite IndependentSource::sample(uint64_t* seed) const { SourceSite site; + site.particle = particle_; // Repeat sampling source location until a good site has been found bool found = false; int n_reject = 0; static int n_accept = 0; + while (!found) { // Set particle type - site.particle = particle_; + Particle p; + p.type() = particle_; + p.u() = {0.0, 0.0, 1.0}; // Sample spatial distribution - site.r = space_->sample(seed); + p.r() = space_->sample(seed); // Now search to see if location exists in geometry - int32_t cell_index, instance; - double xyz[] {site.r.x, site.r.y, site.r.z}; - int err = openmc_find_cell(xyz, &cell_index, &instance); - found = (err != OPENMC_E_GEOMETRY); + found = exhaustive_find_cell(p); // Check if spatial site is in fissionable material if (found) { @@ -181,15 +190,22 @@ SourceSite IndependentSource::sample(uint64_t* seed) const if (space_box) { if (space_box->only_fissionable()) { // Determine material - const auto& c = model::cells[cell_index]; - auto mat_index = - c->material_.size() == 1 ? c->material_[0] : c->material_[instance]; - + auto mat_index = p.material(); if (mat_index == MATERIAL_VOID) { found = false; } else { - if (!model::materials[mat_index]->fissionable_) - found = false; + found = model::materials[mat_index]->fissionable_; + } + } + } + + // Rejection based on cells + if (!cells_.empty()) { + found = false; + for (const auto& coord : p.coord()) { + if (contains(cells_, model::cells[coord.cell]->id_)) { + found = true; + break; } } } @@ -205,6 +221,8 @@ SourceSite IndependentSource::sample(uint64_t* seed) const "definition."); } } + + site.r = p.r(); } // Sample angle From 3e5c9d83c509754be32f40fba6c3f73427b2fd92 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 1 Sep 2022 16:13:26 -0500 Subject: [PATCH 1017/2654] Expand source rejection to cells, materials, and universes --- include/openmc/source.h | 7 +++- openmc/source.py | 85 +++++++++++++++++++++++++++++------------ src/source.cpp | 44 ++++++++++++++++----- 3 files changed, 100 insertions(+), 36 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index d48b4e4ae..04b9ff856 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -80,13 +80,18 @@ public: Distribution* time() const { return time_.get(); } private: + // Domain types + enum class DomainType { UNIVERSE, MATERIAL, CELL }; + + // Data members ParticleType particle_ {ParticleType::neutron}; //!< Type of particle emitted double strength_ {1.0}; //!< Source strength UPtrSpace space_; //!< Spatial distribution UPtrAngle angle_; //!< Angular distribution UPtrDist energy_; //!< Energy distribution UPtrDist time_; //!< Time distribution - std::unordered_set cells_; //!< Cells to reject from + DomainType domain_type_; //!< Domain type for rejection + std::unordered_set domain_ids_; //!< Domains to reject from }; //============================================================================== diff --git a/openmc/source.py b/openmc/source.py index 6ec1338a3..48e14f6f7 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -1,5 +1,7 @@ +from collections.abc import Iterable from enum import Enum from numbers import Real +import warnings from xml.etree import ElementTree as ET import numpy as np @@ -37,8 +39,9 @@ class Source: Strength of the source particle : {'neutron', 'photon'} Source particle type - cells : iterable of int or openmc.Cell - Cells to reject based on + domains : iterable of openmc.Cell, openmc.Material, or openmc.Universe + Domains to reject based on, i.e., if a sampled spatial location is not + within one of these domains, it will be rejected. Attributes ---------- @@ -60,14 +63,16 @@ class Source: Strength of the source particle : {'neutron', 'photon'} Source particle type - cells : iterable of int or openmc.Cell - Cells to reject based on + ids : Iterable of int + IDs of domains to use for rejection + domain_type : {'cell', 'material', 'universe'} + Type of domain to use for rejection """ def __init__(self, space=None, angle=None, energy=None, time=None, filename=None, library=None, parameters=None, strength=1.0, particle='neutron', - cells=None): + domains=None): self._space = None self._angle = None self._energy = None @@ -75,7 +80,6 @@ class Source: self._file = None self._library = None self._parameters = None - self._cells = [] if space is not None: self.space = space @@ -93,8 +97,17 @@ class Source: self.parameters = parameters self.strength = strength self.particle = particle - if cells is not None: - self.cells = cells + + self._domain_ids = [] + self._domain_type = None + if domains is not None: + if isinstance(domains[0], openmc.Cell): + self.domain_type = 'cell' + elif isinstance(domains[0], openmc.Material): + self.domain_type = 'material' + elif isinstance(domains[0], openmc.Universe): + self.domain_type = 'universe' + self.domain_ids = [d.id for d in domains] @property def file(self): @@ -133,8 +146,22 @@ class Source: return self._particle @property - def cells(self): - return self._cells + def domain_ids(self): + return self._domain_ids + + @property + def domain_type(self): + return self._domain_type + + @domain_ids.setter + def domain_ids(self, ids): + cv.check_type('domain IDs', ids, Iterable, Real) + self._domain_ids = ids + + @domain_type.setter + def domain_type(self, domain_type): + cv.check_value('domain type', domain_type, ('cell', 'material', 'universe')) + self._domain_type = domain_type @file.setter def file(self, filename): @@ -182,13 +209,6 @@ class Source: cv.check_value('source particle', particle, ['neutron', 'photon']) self._particle = particle - @cells.setter - def cells(self, cells): - self._cells = [ - cell.id if isinstance(cell, openmc.Cell) else cell - for cell in cells - ] - def to_xml_element(self): """Return XML representation of the source @@ -216,9 +236,11 @@ class Source: element.append(self.energy.to_xml_element('energy')) if self.time is not None: element.append(self.time.to_xml_element('time')) - if self.cells: - cells_elem = ET.SubElement(element, "cells") - cells_elem.text = ' '.join(str(x) for x in self.cells) + if self.domain_ids: + dt_elem = ET.SubElement(element, "domain_type") + dt_elem.text = self.domain_type + id_elem = ET.SubElement(element, "domain_ids") + id_elem.text = ' '.join(str(uid) for uid in self.domain_ids) return element @classmethod @@ -236,7 +258,24 @@ class Source: Source generated from XML element """ - source = cls() + domain_type = get_text(elem, "domain_type") + if domain_type is not None: + domain_ids = [int(x) for x in get_text(elem, "domain_ids").split()] + + # Instantiate some throw-away domains that are used by the + # constructor to assign IDs + with warnings.catch_warnings(): + warnings.simplefilter('ignore', openmc.IDWarning) + if domain_type == 'cell': + domains = [openmc.Cell(uid) for uid in domain_ids] + elif domain_type == 'material': + domains = [openmc.Material(uid) for uid in domain_ids] + elif domain_type == 'universe': + domains = [openmc.Universe(uid) for uid in domain_ids] + else: + domains = None + + source = cls(domains=domains) strength = get_text(elem, 'strength') if strength is not None: @@ -274,10 +313,6 @@ class Source: if time is not None: source.time = Univariate.from_xml_element(time) - cells = elem.find('cells') - if cells is not None: - source.cells = [int(x) for x in cells.text.split()] - return source diff --git a/src/source.cpp b/src/source.cpp index 17bef4377..e443c49e6 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -154,10 +154,22 @@ IndependentSource::IndependentSource(pugi::xml_node node) time_ = UPtrDist {new Discrete {T, p, 1}}; } - // Check for cells to reject from - if (check_for_node(node, "cells")) { - auto cells = get_node_array(node, "cells"); - cells_.insert(cells.cbegin(), cells.cend()); + // Check for domains to reject from + if (check_for_node(node, "domain_type")) { + std::string domain_type = get_node_value(node, "domain_type"); + if (domain_type == "cell") { + domain_type_ = DomainType::CELL; + } else if (domain_type == "material") { + domain_type_ = DomainType::MATERIAL; + } else if (domain_type == "universe") { + domain_type_ = DomainType::UNIVERSE; + } else { + fatal_error(std::string( + "Unrecognized domain type for source rejection: " + domain_type)); + } + + auto ids = get_node_array(node, "domain_ids"); + domain_ids_.insert(ids.begin(), ids.end()); } } } @@ -199,13 +211,25 @@ SourceSite IndependentSource::sample(uint64_t* seed) const } } - // Rejection based on cells - if (!cells_.empty()) { + // Rejection based on cells/materials/universes + if (!domain_ids_.empty()) { found = false; - for (const auto& coord : p.coord()) { - if (contains(cells_, model::cells[coord.cell]->id_)) { - found = true; - break; + if (domain_type_ == DomainType::MATERIAL) { + auto mat_index = p.material(); + if (mat_index != MATERIAL_VOID) { + if (contains(domain_ids_, model::materials[mat_index]->id())) { + found = true; + } + } + } else { + for (const auto& coord : p.coord()) { + auto id = (domain_type_ == DomainType::CELL) + ? model::cells[coord.cell]->id_ + : model::universes[coord.universe]->id_; + if (contains(domain_ids_, id)) { + found = true; + break; + } } } } From dd7a25c570ba1741f683d4add9a2ce96e7b88959 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 26 Sep 2022 14:20:34 -0500 Subject: [PATCH 1018/2654] Add test for source rejection by domain --- tests/unit_tests/test_source.py | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/unit_tests/test_source.py b/tests/unit_tests/test_source.py index 76dcbcdc8..7558d8238 100644 --- a/tests/unit_tests/test_source.py +++ b/tests/unit_tests/test_source.py @@ -1,6 +1,7 @@ from math import pi import openmc +import openmc.lib import openmc.stats import numpy as np from pytest import approx @@ -96,3 +97,38 @@ def test_source_xml_roundtrip(): np.testing.assert_allclose(new_src.angle.reference_uvw, src.angle.reference_uvw) assert new_src.particle == src.particle assert new_src.strength == approx(src.strength) + + +def test_rejection(run_in_tmpdir): + # Model with two spheres inside a box + mat = openmc.Material() + mat.add_nuclide('H1', 1.0) + sph1 = openmc.Sphere(x0=3, r=1.0) + sph2 = openmc.Sphere(x0=-3, r=1.0) + cube = openmc.model.RectangularParallelepiped( + -5., 5., -5., 5., -5., 5., boundary_type='reflective' + ) + cell1 = openmc.Cell(fill=mat, region=-sph1) + cell2 = openmc.Cell(fill=mat, region=-sph2) + cell3 = openmc.Cell(region=+sph1 & +sph2 & -cube) + model = openmc.Model() + model.geometry = openmc.Geometry([cell1, cell2, cell3]) + model.settings.particles = 100 + model.settings.batches = 10 + model.settings.run_mode = 'fixed source' + + # Set up a box source with rejection on the spherical cell + space = openmc.stats.Box(*cell3.bounding_box) + model.settings.source = openmc.Source(space=space, domains=[cell1, cell2]) + + # Load up model via openmc.lib and sample source + model.export_to_xml() + openmc.lib.init() + particles = openmc.lib.sample_external_source(1000) + + # Make sure that all sampled sources are within one of the spheres + joint_region = cell1.region | cell2.region + for p in particles: + assert p.r in joint_region + + openmc.lib.finalize() From 18337073f4d9e235cd443dca7d017fef34365bd6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 26 Sep 2022 14:26:05 -0500 Subject: [PATCH 1019/2654] Fix name change on mat_to_ind, nuc_to_ind --- openmc/deplete/openmc_operator.py | 2 +- openmc/deplete/results.py | 4 ++-- .../deplete_no_transport/test.py | 20 +++++++++---------- .../deplete_with_transport/test.py | 20 +++++++++---------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index ca1516803..fd9e66524 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -334,7 +334,7 @@ class OpenMCOperator(TransportOperator): mat_id = str(mat.id) # Get nuclide lists from geometry and depletion results - depl_nuc = prev_res[-1].nuc_to_ind + depl_nuc = prev_res[-1].index_nuc geom_nuc_densities = mat.get_nuclide_atom_densities() # Merge lists of nuclides, with the same order for every calculation diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index b2c8e7733..d9aa52b79 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -435,7 +435,7 @@ class Results(list): # results, and save them to the new depleted xml file. for mat in mat_file: mat_id = str(mat.id) - if mat_id in result.mat_to_ind: + if mat_id in result.index_mat: mat.volume = result.volume[mat_id] # Change density of all nuclides in material to atom/b-cm @@ -447,7 +447,7 @@ class Results(list): # For nuclides in chain that have cross sections, replace # density in original material with new density from results - for nuc in result.nuc_to_ind: + for nuc in result.index_nuc: if nuc not in available_cross_sections: continue atoms = result[0, mat_id, nuc] diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index f5ee4bf1d..384653ff7 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -161,23 +161,23 @@ def _create_operator(from_nuclides, return op def _assert_same_mats(res_ref, res_test): - for mat in res_ref[0].mat_to_ind: - assert mat in res_test[0].mat_to_ind, \ + for mat in res_ref[0].index_mat: + assert mat in res_test[0].index_mat, \ "Material {} not in new results.".format(mat) - for nuc in res_ref[0].nuc_to_ind: - assert nuc in res_test[0].nuc_to_ind, \ + for nuc in res_ref[0].index_nuc: + assert nuc in res_test[0].index_nuc, \ "Nuclide {} not in new results.".format(nuc) - for mat in res_test[0].mat_to_ind: - assert mat in res_ref[0].mat_to_ind, \ + for mat in res_test[0].index_mat: + assert mat in res_ref[0].index_mat, \ "Material {} not in old results.".format(mat) - for nuc in res_test[0].nuc_to_ind: - assert nuc in res_ref[0].nuc_to_ind, \ + for nuc in res_test[0].index_nuc: + assert nuc in res_ref[0].index_nuc, \ "Nuclide {} not in old results.".format(nuc) def _assert_atoms_equal(res_ref, res_test, tol): - for mat in res_test[0].mat_to_ind: - for nuc in res_test[0].nuc_to_ind: + for mat in res_test[0].index_mat: + for nuc in res_test[0].index_nuc: _, y_test = res_test.get_atoms(mat, nuc) _, y_old = res_ref.get_atoms(mat, nuc) diff --git a/tests/regression_tests/deplete_with_transport/test.py b/tests/regression_tests/deplete_with_transport/test.py index 58065035f..9b37e4351 100644 --- a/tests/regression_tests/deplete_with_transport/test.py +++ b/tests/regression_tests/deplete_with_transport/test.py @@ -81,23 +81,23 @@ def test_full(run_in_tmpdir, problem, multiproc): res_ref = openmc.deplete.Results(path_reference) # Assert same mats - for mat in res_ref[0].mat_to_ind: - assert mat in res_test[0].mat_to_ind, \ + for mat in res_ref[0].index_mat: + assert mat in res_test[0].index_mat, \ "Material {} not in new results.".format(mat) - for nuc in res_ref[0].nuc_to_ind: - assert nuc in res_test[0].nuc_to_ind, \ + for nuc in res_ref[0].index_nuc: + assert nuc in res_test[0].index_nuc, \ "Nuclide {} not in new results.".format(nuc) - for mat in res_test[0].mat_to_ind: - assert mat in res_ref[0].mat_to_ind, \ + for mat in res_test[0].index_mat: + assert mat in res_ref[0].index_mat, \ "Material {} not in old results.".format(mat) - for nuc in res_test[0].nuc_to_ind: - assert nuc in res_ref[0].nuc_to_ind, \ + for nuc in res_test[0].index_nuc: + assert nuc in res_ref[0].index_nuc, \ "Nuclide {} not in old results.".format(nuc) tol = 1.0e-6 - for mat in res_test[0].mat_to_ind: - for nuc in res_test[0].nuc_to_ind: + for mat in res_test[0].index_mat: + for nuc in res_test[0].index_nuc: _, y_test = res_test.get_atoms(mat, nuc) _, y_old = res_ref.get_atoms(mat, nuc) From e31576fc097f2d8c7b08790794eae6709a7e6e0f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 27 Sep 2022 13:46:33 +0100 Subject: [PATCH 1020/2654] moved doc string to class attributes --- openmc/universe.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 34618a70a..2ca4ad388 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -647,6 +647,11 @@ class DAGMCUniverse(UniverseBase): bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box of the universe. + material_name : list of str + Return a sorted list of materials names that are contained within the + DAGMC h5m file. This is useful when naming openmc.Material() objects + as each material name present in the DAGMC h5m file must have a + matching openmc.Material() with the same name. .. versionadded:: 0.13.1 """ @@ -701,18 +706,6 @@ class DAGMCUniverse(UniverseBase): @property def material_names(self): - """Return the names of the materials that are contained within the - DAGMC h5m file. This is useful when naming openmc.Material() objects - as each material name present in the DAGMC h5m file must have a - matching openmc.Material() with the same name. - - Returns - ------- - materials : list of str - Sorted list of material names present in the DAGMC h5m file - - """ - dagmc_file_contents = h5py.File(self.filename) material_tags_hex=dagmc_file_contents['/tstt/tags/NAME'].get('values') material_tags_ascii=[] From 663deb2761dddb11378407f3d2355ec8c42c57c0 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Tue, 27 Sep 2022 11:26:41 -0500 Subject: [PATCH 1021/2654] Add flow control to differentiate indident neutron from thermal scattering data Co-authored-by: Paul Romano --- scripts/openmc-ace-to-hdf5 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/openmc-ace-to-hdf5 b/scripts/openmc-ace-to-hdf5 index 75948e012..66ae7e2a9 100755 --- a/scripts/openmc-ace-to-hdf5 +++ b/scripts/openmc-ace-to-hdf5 @@ -92,7 +92,10 @@ def ace_to_hdf5(destination, xsdir, xsdata, libraries, metastable, libver): # Add data for new temperature try: print(f"Converting {table.name} (ACE) to {data.name} (HDF5)") - data.add_temperature_from_ace(table) + if table.data_type == TableType.NEUTRON_CONTINUOUS: + data.add_temperature_from_ace(table, metastable) + else: + data.add_temperature_from_ace(table) except Exception as e: print(f"Failed to convert {table.name}: {e}") continue From 7815a5e02d9baa1a076b926242aa6a02b5ba4834 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 28 Sep 2022 09:31:12 -0500 Subject: [PATCH 1022/2654] Address @shimwell comments on #2234 --- docs/source/pythonapi/data.rst | 2 +- openmc/config.py | 6 +++--- openmc/data/decay.py | 17 +++++++++++------ openmc/material.py | 6 +++--- tests/chain_simple.xml | 4 ++-- tests/unit_tests/test_data_decay.py | 11 ++++++++--- tests/unit_tests/test_material.py | 19 ++++++++++++------- 7 files changed, 40 insertions(+), 25 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 2ee08c7f5..55289864f 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -63,7 +63,7 @@ Core Functions atomic_weight combine_distributions decay_constant - decay_photon_source + decay_photon_energy dose_coefficients gnd_name half_life diff --git a/openmc/config.py b/openmc/config.py index 3c031ee7d..087a8c27e 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -4,7 +4,7 @@ from pathlib import Path import warnings from openmc.data import DataLibrary -from openmc.data.decay import _DECAY_PHOTON_SOURCE +from openmc.data.decay import _DECAY_PHOTON_ENERGY __all__ = ["config"] @@ -26,7 +26,7 @@ class _Config(MutableMapping): elif key == 'chain_file': del os.environ['OPENMC_CHAIN_FILE'] # Reset photon source data since it relies on chain file - _DECAY_PHOTON_SOURCE.clear() + _DECAY_PHOTON_ENERGY.clear() def __setitem__(self, key, value): if key == 'cross_sections': @@ -40,7 +40,7 @@ class _Config(MutableMapping): self._set_path(key, value) os.environ['OPENMC_CHAIN_FILE'] = str(value) # Reset photon source data since it relies on chain file - _DECAY_PHOTON_SOURCE.clear() + _DECAY_PHOTON_ENERGY.clear() else: raise KeyError(f'Unrecognized config key: {key}') diff --git a/openmc/data/decay.py b/openmc/data/decay.py index eafa84f66..6672add3b 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -576,11 +576,11 @@ class Decay(EqualityMixin): return self._sources -_DECAY_PHOTON_SOURCE = {} +_DECAY_PHOTON_ENERGY = {} -def decay_photon_source(nuclide: str) -> Univariate: - """Get photon source from the decay of a nuclide +def decay_photon_energy(nuclide: str) -> Univariate: + """Get photon energy distribution resulting from the decay of a nuclide This function relies on data stored in a depletion chain. Before calling it for the first time, you need to ensure that a depletion chain has been @@ -598,7 +598,7 @@ def decay_photon_source(nuclide: str) -> Univariate: openmc.stats.Univariate Distribution of energies in [eV] of photons emitted from decay """ - if not _DECAY_PHOTON_SOURCE: + if not _DECAY_PHOTON_ENERGY: chain_file = openmc.config.get('chain_file') if chain_file is None: raise DataError( @@ -610,6 +610,11 @@ def decay_photon_source(nuclide: str) -> Univariate: chain = Chain.from_xml(chain_file) for nuc in chain.nuclides: if 'photon' in nuc.sources: - _DECAY_PHOTON_SOURCE[nuc.name] = nuc.sources['photon'] + _DECAY_PHOTON_ENERGY[nuc.name] = nuc.sources['photon'] - return _DECAY_PHOTON_SOURCE.get(nuclide) + # If the chain file contained no sources at all, warn the user + if not _DECAY_PHOTON_ENERGY: + warn(f"Chain file '{chain_file}' does not have any decay photon " + "sources listed.") + + return _DECAY_PHOTON_ENERGY.get(nuclide) diff --git a/openmc/material.py b/openmc/material.py index 53bf676d5..52978dbbe 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -92,7 +92,7 @@ class Material(IDManagerMixin): fissionable_mass : float Mass of fissionable nuclides in the material in [g]. Requires that the :attr:`volume` attribute is set. - decay_photon_source : openmc.stats.Univariate + decay_photon_energy : openmc.stats.Univariate Energy distribution of photons emitted from decay of unstable nuclides within the material. The integral of this distribution is the total intensity of the photon source. @@ -264,12 +264,12 @@ class Material(IDManagerMixin): return density*self.volume @property - def decay_photon_source(self) -> Univariate: + def decay_photon_energy(self) -> Univariate: atoms = self.get_nuclide_atoms() dists = [] probs = [] for nuc, num_atoms in atoms.items(): - source_per_atom = openmc.data.decay_photon_source(nuc) + source_per_atom = openmc.data.decay_photon_energy(nuc) if source_per_atom is not None: dists.append(source_per_atom) probs.append(num_atoms) diff --git a/tests/chain_simple.xml b/tests/chain_simple.xml index ba42b5542..28c5739c9 100644 --- a/tests/chain_simple.xml +++ b/tests/chain_simple.xml @@ -10,8 +10,8 @@ - - 3860.681 4271.629 4683.641 5336.674 30621.8 30978.9 34925.5 34994.3 35237.3 35252.0 35803.0 35817.2 35899.4 35901.8 158197.0 200190.0 249794.0 358390.0 373130.0 407990.0 454200.0 573320.0 608185.0 654432.0 731520.0 812630.0 1062410.0 7.994251137825248e-09 6.327910906791491e-08 5.1272731446173495e-08 7.363690277270275e-09 3.054968676386751e-07 5.64321319541835e-07 5.347473347583344e-08 1.0365225698627538e-07 5.533995748532528e-10 7.536429363113684e-10 1.1251670022820477e-08 2.1931143930358873e-08 1.0789862609689208e-10 1.4667031416354672e-10 6.085892914653786e-08 2.4646918345949914e-09 1.895916795842301e-05 4.644996149813638e-08 3.223058552931912e-09 7.545748847452359e-08 7.583667183369205e-10 1.0048359017964195e-09 6.10485208261221e-07 9.479583979211505e-09 1.1565092454638037e-08 1.478815100756995e-08 8.531625581290355e-10 + + 0.0 10000.0 20000.0 50000.0 100000.0 200000.0 300000.0 400000.0 600000.0 800000.0 1000000.0 1220000.0 1.1612176249914943e-11 0.0 3.1976524142990123e-11 0.0 6.418466676129901e-13 1.894551923065874e-10 5.099949011192198e-13 3.170644340540729e-13 2.756798470867507e-12 6.67627508515641e-14 3.711746246444946e-15 0.0 diff --git a/tests/unit_tests/test_data_decay.py b/tests/unit_tests/test_data_decay.py index e658c16d3..8900e7eac 100644 --- a/tests/unit_tests/test_data_decay.py +++ b/tests/unit_tests/test_data_decay.py @@ -129,18 +129,23 @@ def test_sources(ba137m, nb90): assert len(set(sources.keys()) ^ {'positron', 'electron', 'photon'}) == 0 -def test_decay_photon_source(): +def test_decay_photon_energy(): # If chain file is not set, we should get a data error if 'chain_file' in openmc.config: del openmc.config['chain_file'] with pytest.raises(DataError): - openmc.data.decay_photon_source('135') + openmc.data.decay_photon_energy('I135') # Set chain file to simple chain openmc.config['chain_file'] = Path(__file__).parents[1] / "chain_simple.xml" # Check strength of I135 source and presence of specific spectral line - src = openmc.data.decay_photon_source('I135') + src = openmc.data.decay_photon_energy('I135') assert isinstance(src, openmc.stats.Discrete) assert src.integral() == pytest.approx(3.920996223799345e-05) assert 1260409. in src.x + + # Check Xe135 source, which should be tabular + src = openmc.data.decay_photon_energy('Xe135') + assert isinstance(src, openmc.stats.Tabular) + assert src.integral() == pytest.approx(2.076506258964966e-05) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 352017c8d..58df246dd 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -4,7 +4,7 @@ from pathlib import Path import pytest import openmc -from openmc.data import decay_photon_source +from openmc.data import decay_photon_energy import openmc.examples import openmc.model import openmc.stats @@ -545,26 +545,31 @@ def test_get_activity(): assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq] -def test_decay_photon_source(): +def test_decay_photon_energy(): # Set chain file for testing openmc.config['chain_file'] = Path(__file__).parents[1] / 'chain_simple.xml' - # Material representing single atom of I135, Xe135, and Cs135 + # Material representing single atom of I135 and Cs135 m = openmc.Material() m.add_nuclide('I135', 1.0e-24) - m.add_nuclide('Xe135', 1.0e-24) m.add_nuclide('Cs135', 1.0e-24) m.volume = 1.0 # Get decay photon source and make sure it's the right type - src = m.decay_photon_source + src = m.decay_photon_energy assert isinstance(src, openmc.stats.Discrete) + # If we add Xe135 (which has a tabular distribution), the photon source + # should be a mixture distribution + m.add_nuclide('Xe135', 1.0e-24) + src = m.decay_photon_energy + assert isinstance(src, openmc.stats.Mixture) + # With a single atom of each, the intensity of the photon source should be - # equal to sum(I*λ) + # equal to the sum of the intensities for each nuclide def intensity(src): return src.integral() if src is not None else 0.0 assert src.integral() == pytest.approx(sum( - intensity(decay_photon_source(nuc)) for nuc in m.get_nuclides() + intensity(decay_photon_energy(nuc)) for nuc in m.get_nuclides() )) From e0be9de08625b00fe0f764a505612a5268c1ecec Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 28 Sep 2022 09:33:48 -0500 Subject: [PATCH 1023/2654] Apply @shimwell suggestions from code review Co-authored-by: Jonathan Shimwell --- tests/unit_tests/test_source.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_source.py b/tests/unit_tests/test_source.py index 7558d8238..ca3ee7f55 100644 --- a/tests/unit_tests/test_source.py +++ b/tests/unit_tests/test_source.py @@ -110,7 +110,8 @@ def test_rejection(run_in_tmpdir): ) cell1 = openmc.Cell(fill=mat, region=-sph1) cell2 = openmc.Cell(fill=mat, region=-sph2) - cell3 = openmc.Cell(region=+sph1 & +sph2 & -cube) + non_source_region = +sph1 & +sph2 & -cube + cell3 = openmc.Cell(region=non_source_region) model = openmc.Model() model.geometry = openmc.Geometry([cell1, cell2, cell3]) model.settings.particles = 100 @@ -130,5 +131,6 @@ def test_rejection(run_in_tmpdir): joint_region = cell1.region | cell2.region for p in particles: assert p.r in joint_region + assert p.r not in non_source_region openmc.lib.finalize() From 2b401bc1f1229b0b594bd9e60900134934e3d3ec Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 28 Sep 2022 10:26:13 -0500 Subject: [PATCH 1024/2654] Update tests/unit_tests/test_source.py Co-authored-by: Jonathan Shimwell --- tests/unit_tests/test_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_source.py b/tests/unit_tests/test_source.py index ca3ee7f55..1e4766b45 100644 --- a/tests/unit_tests/test_source.py +++ b/tests/unit_tests/test_source.py @@ -131,6 +131,6 @@ def test_rejection(run_in_tmpdir): joint_region = cell1.region | cell2.region for p in particles: assert p.r in joint_region - assert p.r not in non_source_region + assert p.r not in non_source_region openmc.lib.finalize() From 10abbe910add1bcd42aa0ca425a55e5fc1ced52c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 28 Sep 2022 13:25:00 -0500 Subject: [PATCH 1025/2654] Clarify probability units for decay_photon_energy --- openmc/data/decay.py | 3 ++- openmc/material.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 6672add3b..d7ededf33 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -596,7 +596,8 @@ def decay_photon_energy(nuclide: str) -> Univariate: Returns ------- openmc.stats.Univariate - Distribution of energies in [eV] of photons emitted from decay + Distribution of energies in [eV] of photons emitted from decay. Note + that the probabilities represent intensities, given as [decay/sec]. """ if not _DECAY_PHOTON_ENERGY: chain_file = openmc.config.get('chain_file') diff --git a/openmc/material.py b/openmc/material.py index 52978dbbe..16b5a3048 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -95,7 +95,7 @@ class Material(IDManagerMixin): decay_photon_energy : openmc.stats.Univariate Energy distribution of photons emitted from decay of unstable nuclides within the material. The integral of this distribution is the total - intensity of the photon source. + intensity of the photon source in [decay/sec]. .. versionadded:: 0.14.0 From fe90b8e22063b7c3ca309d60ebb8996b1c8dbd2c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Sep 2022 15:23:00 -0500 Subject: [PATCH 1026/2654] Adding properties for number of DAGMC cells/surfaces --- openmc/universe.py | 40 ++++++++++++++++++++++++++++++++++ tests/unit_tests/dagmc/test.py | 8 +++++++ 2 files changed, 48 insertions(+) diff --git a/openmc/universe.py b/openmc/universe.py index 2ca4ad388..6b5e777ec 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -730,6 +730,46 @@ class DAGMCUniverse(UniverseBase): def get_all_materials(self, memo=None): return OrderedDict() + def _n_geom_elements(self, geom_type): + """ + Helper function for retrieving the number geometric entities in a DAGMC + file + + Parameters + ---------- + + geom_type : str + The type of geometric entity to count. One of {'Volume', 'Surface'}. Returns + the runtime number of voumes in the DAGMC model (includes implicit complement). + """ + cv.check_value('geometry type', geom_type, ('volume', 'surface')) + + def decode_str_tag(tag_val): + return tag_val.tobytes().decode().replace('\x00', '') + + with h5py.File(self.filename) as dagmc_file: + category_data = dagmc_file['tstt/tags/CATEGORY/values'] + category_strs = map(decode_str_tag, category_data) + # add one assuming implicit complement doesn't exist + n = sum([v == geom_type.capitalize() for v in category_strs]) + + # check for presence of an implicit complement in the file and + # increment the number of cells if it doesn't exist + if geom_type == 'volume': + name_data = dagmc_file['tstt/tags/NAME/values'] + name_strs = map(decode_str_tag, name_data) + if not sum(['impl_complement' in n for n in name_strs]): + n += 1 + return n + + @property + def n_cells(self): + return self._n_geom_elements('volume') + + @property + def n_surfaces(self): + return self._n_geom_elements('surface') + def create_xml_subelement(self, xml_element, memo=None): if memo and self in memo: return diff --git a/tests/unit_tests/dagmc/test.py b/tests/unit_tests/dagmc/test.py index b3e2c390f..352fe8895 100644 --- a/tests/unit_tests/dagmc/test.py +++ b/tests/unit_tests/dagmc/test.py @@ -33,6 +33,14 @@ def dagmc_model(request): dagmc_universe = openmc.DAGMCUniverse('dagmc.h5m') model.geometry = openmc.Geometry(dagmc_universe) + # check number of surfaces and volumes for this pincell model there should + # be 5 volumes: two fuel regions, water, graveyard, implicit complement (the + # implicit complement cell is created automatically at runtime) + # and 21 surfaces: 3 cylinders (9 surfaces) and a bounding cubic shell + # (12 surfaces) + assert dagmc_universe.n_cells == 5 + assert dagmc_universe.n_surfaces == 21 + # tally tally = openmc.Tally() tally.scores = ['total'] From a0a5afcbca47b8429ba058caa23ee8619cca59ba Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Sep 2022 15:34:27 -0500 Subject: [PATCH 1027/2654] Formatting and docstrs. --- openmc/universe.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 6b5e777ec..b3a5cf14b 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -624,11 +624,11 @@ class DAGMCUniverse(UniverseBase): name : str, optional Name of the universe. If not specified, the name is the empty string. auto_geom_ids : bool - Set IDs automatically on initialization (True) or report overlaps - in ID space between CSG and DAGMC (False) + Set IDs automatically on initialization (True) or report overlaps in ID + space between CSG and DAGMC (False) auto_mat_ids : bool - Set IDs automatically on initialization (True) or report overlaps - in ID space between OpenMC and UWUW materials (False) + Set IDs automatically on initialization (True) or report overlaps in ID + space between OpenMC and UWUW materials (False) Attributes ---------- @@ -639,11 +639,11 @@ class DAGMCUniverse(UniverseBase): filename : str Path to the DAGMC file used to represent this universe. auto_geom_ids : bool - Set IDs automatically on initialization (True) or report overlaps - in ID space between CSG and DAGMC (False) + Set IDs automatically on initialization (True) or report overlaps in ID + space between CSG and DAGMC (False) auto_mat_ids : bool - Set IDs automatically on initialization (True) or report overlaps - in ID space between OpenMC and UWUW materials (False) + Set IDs automatically on initialization (True) or report overlaps in ID + space between OpenMC and UWUW materials (False) bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box of the universe. @@ -652,6 +652,12 @@ class DAGMCUniverse(UniverseBase): DAGMC h5m file. This is useful when naming openmc.Material() objects as each material name present in the DAGMC h5m file must have a matching openmc.Material() with the same name. + n_cells : int + The number of cells in the DAGMC model. This is the number of cells at + runtime and accounts for the implicit complement volume if it isn't + present in the DAGMC file. + n_surfaces : int + The number of surfaces in the model. .. versionadded:: 0.13.1 """ @@ -737,10 +743,14 @@ class DAGMCUniverse(UniverseBase): Parameters ---------- - geom_type : str The type of geometric entity to count. One of {'Volume', 'Surface'}. Returns the runtime number of voumes in the DAGMC model (includes implicit complement). + + Returns + ------- + int + Number of geometry elements of the specified type """ cv.check_value('geometry type', geom_type, ('volume', 'surface')) From f038225abe66ae35c6441b59bbf0d55e9a256b83 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Sep 2022 16:04:31 -0500 Subject: [PATCH 1028/2654] Update openmc/universe.py Co-authored-by: Jonathan Shimwell --- openmc/universe.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index b3a5cf14b..3082a0c12 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -760,7 +760,6 @@ class DAGMCUniverse(UniverseBase): with h5py.File(self.filename) as dagmc_file: category_data = dagmc_file['tstt/tags/CATEGORY/values'] category_strs = map(decode_str_tag, category_data) - # add one assuming implicit complement doesn't exist n = sum([v == geom_type.capitalize() for v in category_strs]) # check for presence of an implicit complement in the file and From ebf6e24bcf5c3e787ea5dd24a75a3e451494ea22 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Sep 2022 21:19:41 -0500 Subject: [PATCH 1029/2654] Resolving symlink paths --- openmc/universe.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 3082a0c12..f17180965 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -757,7 +757,8 @@ class DAGMCUniverse(UniverseBase): def decode_str_tag(tag_val): return tag_val.tobytes().decode().replace('\x00', '') - with h5py.File(self.filename) as dagmc_file: + dagmc_filepath = Path(self.filename).resolve() + with h5py.File(dagmc_filepath) as dagmc_file: category_data = dagmc_file['tstt/tags/CATEGORY/values'] category_strs = map(decode_str_tag, category_data) n = sum([v == geom_type.capitalize() for v in category_strs]) From 0dd3fff562c317cd8cd601fa89ae67b500941b02 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Sep 2022 22:02:37 -0500 Subject: [PATCH 1030/2654] Improve docstring --- openmc/universe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index f17180965..a326ca812 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -654,7 +654,7 @@ class DAGMCUniverse(UniverseBase): matching openmc.Material() with the same name. n_cells : int The number of cells in the DAGMC model. This is the number of cells at - runtime and accounts for the implicit complement volume if it isn't + runtime and accounts for the implicit complement whether or not is it present in the DAGMC file. n_surfaces : int The number of surfaces in the model. From ed24b2343a1afa7488673230b3a49eecaaeb47b5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Sep 2022 22:05:23 -0500 Subject: [PATCH 1031/2654] typo fix --- openmc/universe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index a326ca812..0c8a26a48 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -647,7 +647,7 @@ class DAGMCUniverse(UniverseBase): bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box of the universe. - material_name : list of str + material_names : list of str Return a sorted list of materials names that are contained within the DAGMC h5m file. This is useful when naming openmc.Material() objects as each material name present in the DAGMC h5m file must have a From f289123394e4245178ed5e0d7bc1d9788f2dcffd Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 30 Sep 2022 14:58:28 +0100 Subject: [PATCH 1032/2654] added *h.in files --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index d59628325..afd016cb0 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -23,6 +23,7 @@ recursive-include examples *.cpp recursive-include examples *.py recursive-include examples *.xml recursive-include include *.h +recursive-include include *.h.in recursive-include include *.hh recursive-include man *.1 recursive-include openmc *.pyx From d96c3673319ec2c1fafd2bfaeb3cbfbddd1ab425 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 30 Sep 2022 12:53:19 -0500 Subject: [PATCH 1033/2654] Using pytest request path to specify dagmc file --- tests/unit_tests/dagmc/test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/dagmc/test.py b/tests/unit_tests/dagmc/test.py index 352fe8895..41e9c0828 100644 --- a/tests/unit_tests/dagmc/test.py +++ b/tests/unit_tests/dagmc/test.py @@ -30,7 +30,8 @@ def dagmc_model(request): model.settings.source = source # geometry - dagmc_universe = openmc.DAGMCUniverse('dagmc.h5m') + dagmc_file = Path(request.fspath).parent / 'dagmc.h5m' + dagmc_universe = openmc.DAGMCUniverse(dagmc_file) model.geometry = openmc.Geometry(dagmc_universe) # check number of surfaces and volumes for this pincell model there should From 6719aa218e78ea0e637b278259db37dc570c8b52 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 30 Sep 2022 13:30:23 -0500 Subject: [PATCH 1034/2654] Update openmc/deplete/nuclide.py per @pshriwise suggestion Co-authored-by: Patrick Shriwise --- openmc/deplete/nuclide.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py index 250861985..b84b91a7f 100644 --- a/openmc/deplete/nuclide.py +++ b/openmc/deplete/nuclide.py @@ -321,7 +321,7 @@ class Nuclide: # TODO: Ugly hack to deal with the fact that # 'source.to_xml_element' will return an xml.etree object # whereas here lxml is being used preferentially. We should just - # switch to use lxml everywhere, + # switch to use lxml everywhere import xml.etree.ElementTree as etree src_elem_xmletree = source.to_xml_element('source') src_elem = ET.fromstring(etree.tostring(src_elem_xmletree)) From 5d441251fc9b924ff0038290e63ffb34d5d9a560 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 30 Sep 2022 13:56:01 -0500 Subject: [PATCH 1035/2654] Apply @pshriwise suggestions from code review Co-authored-by: Patrick Shriwise --- src/source.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index e443c49e6..fc50115cd 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -217,19 +217,14 @@ SourceSite IndependentSource::sample(uint64_t* seed) const if (domain_type_ == DomainType::MATERIAL) { auto mat_index = p.material(); if (mat_index != MATERIAL_VOID) { - if (contains(domain_ids_, model::materials[mat_index]->id())) { - found = true; - } + found = contains(domain_ids_, model::materials[mat_index]->id()); } } else { for (const auto& coord : p.coord()) { auto id = (domain_type_ == DomainType::CELL) ? model::cells[coord.cell]->id_ : model::universes[coord.universe]->id_; - if (contains(domain_ids_, id)) { - found = true; - break; - } + if (found = contains(domain_ids_, id)) break; } } } From 9c13e85dc2c76641723085452a5a92c85a1cc14c Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sat, 1 Oct 2022 09:22:57 -0400 Subject: [PATCH 1036/2654] fix wwinp reader --- openmc/weight_windows.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 9183bb08b..eb30e838a 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -560,10 +560,13 @@ def wwinp_to_wws(path): end_idx = start_idx + (nfx * nfy * nfz) * nt_i * ne_i # read values and reshape according to ordering - # slowest to fastest: z, y, x, e - ww_values = ww_data[start_idx:end_idx].reshape(nfz, nfy, nfx, ne_i) - # swap z and x axes for correct shape and (ijk, e) mesh indexing - ww_values = np.swapaxes(ww_values, 2, 0) + # slowest to fastest: t, e, z, y, x + # reorder with transpose since our ordering is x, y, z, e, t + ww_shape = (nt_i, ne_i, nfz, nfy, nfx) + ww_values = ww_data[start_idx:end_idx].reshape(ww_shape).T + # Only use first time bin since we don't support time dependent weight + # windows yet. + ww_values = ww_values[:, :, :, :, 0] start_idx = end_idx # create a weight window object From 6fe91efd056c1dce808137e9e9c392edfc3259ac Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sun, 2 Oct 2022 10:45:01 -0400 Subject: [PATCH 1037/2654] fixed wwinp reader tests --- tests/unit_tests/weightwindows/test_wwinp_reader.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index 434a36753..437e588f6 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -118,7 +118,13 @@ def test_wwinp_reader(wwinp_data, request): # check the expected weight window values mocked in the file -- # a reversed array of the flat index into the numpy array n_wws = np.prod((*mesh.dimension, e_bounds.size - 1)) - exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1] + nx, ny, nz, ne = mesh.dimension + (e_bounds.size - 1,) + exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1].reshape(nx, ny, nz, ne) + # this is how the ww lower bounds were actually written to file + exp_ww_lb = np.swapaxes(exp_ww_lb, 0, 2).flatten() + # this is how we expect them to be read back in + exp_ww_lb = exp_ww_lb.reshape(ne, nz, ny, nx).T.flatten() + np.testing.assert_array_equal(exp_ww_lb, ww.lower_ww_bounds.flatten()) From e11c42a7d5badf7d4490d653d763a14c15b7524c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 2 Oct 2022 22:05:27 -0500 Subject: [PATCH 1038/2654] pathlib import --- tests/unit_tests/dagmc/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit_tests/dagmc/test.py b/tests/unit_tests/dagmc/test.py index 41e9c0828..072167e79 100644 --- a/tests/unit_tests/dagmc/test.py +++ b/tests/unit_tests/dagmc/test.py @@ -1,6 +1,7 @@ import shutil import numpy as np +from pathlib import Path import pytest import openmc From 1a306c4c15b42d7e37f55e79052a4f85aaf2f004 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 3 Oct 2022 07:15:02 -0400 Subject: [PATCH 1039/2654] rewrote ww test files --- tests/unit_tests/weightwindows/wwinp_n | 480 ++++++++++++------------ tests/unit_tests/weightwindows/wwinp_np | 49 +-- tests/unit_tests/weightwindows/wwinp_p | 64 ++-- 3 files changed, 297 insertions(+), 296 deletions(-) diff --git a/tests/unit_tests/weightwindows/wwinp_n b/tests/unit_tests/weightwindows/wwinp_n index b9611e945..73a4fc496 100644 --- a/tests/unit_tests/weightwindows/wwinp_n +++ b/tests/unit_tests/weightwindows/wwinp_n @@ -20,244 +20,244 @@ 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 1.00000E+00 1.00000E-01 1.46780E-01 - 1.44000E+03 1.43900E+03 1.34400E+03 1.34300E+03 1.24800E+03 1.24700E+03 - 1.15200E+03 1.15100E+03 1.05600E+03 1.05500E+03 9.60000E+02 9.59000E+02 - 8.64000E+02 8.63000E+02 7.68000E+02 7.67000E+02 6.72000E+02 6.71000E+02 - 5.76000E+02 5.75000E+02 4.80000E+02 4.79000E+02 3.84000E+02 3.83000E+02 - 2.88000E+02 2.87000E+02 1.92000E+02 1.91000E+02 9.60000E+01 9.50000E+01 - 1.42800E+03 1.42700E+03 1.33200E+03 1.33100E+03 1.23600E+03 1.23500E+03 - 1.14000E+03 1.13900E+03 1.04400E+03 1.04300E+03 9.48000E+02 9.47000E+02 - 8.52000E+02 8.51000E+02 7.56000E+02 7.55000E+02 6.60000E+02 6.59000E+02 - 5.64000E+02 5.63000E+02 4.68000E+02 4.67000E+02 3.72000E+02 3.71000E+02 - 2.76000E+02 2.75000E+02 1.80000E+02 1.79000E+02 8.40000E+01 8.30000E+01 - 1.41600E+03 1.41500E+03 1.32000E+03 1.31900E+03 1.22400E+03 1.22300E+03 - 1.12800E+03 1.12700E+03 1.03200E+03 1.03100E+03 9.36000E+02 9.35000E+02 - 8.40000E+02 8.39000E+02 7.44000E+02 7.43000E+02 6.48000E+02 6.47000E+02 - 5.52000E+02 5.51000E+02 4.56000E+02 4.55000E+02 3.60000E+02 3.59000E+02 - 2.64000E+02 2.63000E+02 1.68000E+02 1.67000E+02 7.20000E+01 7.10000E+01 - 1.40400E+03 1.40300E+03 1.30800E+03 1.30700E+03 1.21200E+03 1.21100E+03 - 1.11600E+03 1.11500E+03 1.02000E+03 1.01900E+03 9.24000E+02 9.23000E+02 - 8.28000E+02 8.27000E+02 7.32000E+02 7.31000E+02 6.36000E+02 6.35000E+02 - 5.40000E+02 5.39000E+02 4.44000E+02 4.43000E+02 3.48000E+02 3.47000E+02 - 2.52000E+02 2.51000E+02 1.56000E+02 1.55000E+02 6.00000E+01 5.90000E+01 - 1.39200E+03 1.39100E+03 1.29600E+03 1.29500E+03 1.20000E+03 1.19900E+03 - 1.10400E+03 1.10300E+03 1.00800E+03 1.00700E+03 9.12000E+02 9.11000E+02 - 8.16000E+02 8.15000E+02 7.20000E+02 7.19000E+02 6.24000E+02 6.23000E+02 - 5.28000E+02 5.27000E+02 4.32000E+02 4.31000E+02 3.36000E+02 3.35000E+02 - 2.40000E+02 2.39000E+02 1.44000E+02 1.43000E+02 4.80000E+01 4.70000E+01 - 1.38000E+03 1.37900E+03 1.28400E+03 1.28300E+03 1.18800E+03 1.18700E+03 - 1.09200E+03 1.09100E+03 9.96000E+02 9.95000E+02 9.00000E+02 8.99000E+02 - 8.04000E+02 8.03000E+02 7.08000E+02 7.07000E+02 6.12000E+02 6.11000E+02 - 5.16000E+02 5.15000E+02 4.20000E+02 4.19000E+02 3.24000E+02 3.23000E+02 - 2.28000E+02 2.27000E+02 1.32000E+02 1.31000E+02 3.60000E+01 3.50000E+01 - 1.36800E+03 1.36700E+03 1.27200E+03 1.27100E+03 1.17600E+03 1.17500E+03 - 1.08000E+03 1.07900E+03 9.84000E+02 9.83000E+02 8.88000E+02 8.87000E+02 - 7.92000E+02 7.91000E+02 6.96000E+02 6.95000E+02 6.00000E+02 5.99000E+02 - 5.04000E+02 5.03000E+02 4.08000E+02 4.07000E+02 3.12000E+02 3.11000E+02 - 2.16000E+02 2.15000E+02 1.20000E+02 1.19000E+02 2.40000E+01 2.30000E+01 - 1.35600E+03 1.35500E+03 1.26000E+03 1.25900E+03 1.16400E+03 1.16300E+03 - 1.06800E+03 1.06700E+03 9.72000E+02 9.71000E+02 8.76000E+02 8.75000E+02 - 7.80000E+02 7.79000E+02 6.84000E+02 6.83000E+02 5.88000E+02 5.87000E+02 - 4.92000E+02 4.91000E+02 3.96000E+02 3.95000E+02 3.00000E+02 2.99000E+02 - 2.04000E+02 2.03000E+02 1.08000E+02 1.07000E+02 1.20000E+01 1.10000E+01 - 1.43800E+03 1.43700E+03 1.34200E+03 1.34100E+03 1.24600E+03 1.24500E+03 - 1.15000E+03 1.14900E+03 1.05400E+03 1.05300E+03 9.58000E+02 9.57000E+02 - 8.62000E+02 8.61000E+02 7.66000E+02 7.65000E+02 6.70000E+02 6.69000E+02 - 5.74000E+02 5.73000E+02 4.78000E+02 4.77000E+02 3.82000E+02 3.81000E+02 - 2.86000E+02 2.85000E+02 1.90000E+02 1.89000E+02 9.40000E+01 9.30000E+01 - 1.42600E+03 1.42500E+03 1.33000E+03 1.32900E+03 1.23400E+03 1.23300E+03 - 1.13800E+03 1.13700E+03 1.04200E+03 1.04100E+03 9.46000E+02 9.45000E+02 - 8.50000E+02 8.49000E+02 7.54000E+02 7.53000E+02 6.58000E+02 6.57000E+02 - 5.62000E+02 5.61000E+02 4.66000E+02 4.65000E+02 3.70000E+02 3.69000E+02 - 2.74000E+02 2.73000E+02 1.78000E+02 1.77000E+02 8.20000E+01 8.10000E+01 - 1.41400E+03 1.41300E+03 1.31800E+03 1.31700E+03 1.22200E+03 1.22100E+03 - 1.12600E+03 1.12500E+03 1.03000E+03 1.02900E+03 9.34000E+02 9.33000E+02 - 8.38000E+02 8.37000E+02 7.42000E+02 7.41000E+02 6.46000E+02 6.45000E+02 - 5.50000E+02 5.49000E+02 4.54000E+02 4.53000E+02 3.58000E+02 3.57000E+02 - 2.62000E+02 2.61000E+02 1.66000E+02 1.65000E+02 7.00000E+01 6.90000E+01 - 1.40200E+03 1.40100E+03 1.30600E+03 1.30500E+03 1.21000E+03 1.20900E+03 - 1.11400E+03 1.11300E+03 1.01800E+03 1.01700E+03 9.22000E+02 9.21000E+02 - 8.26000E+02 8.25000E+02 7.30000E+02 7.29000E+02 6.34000E+02 6.33000E+02 - 5.38000E+02 5.37000E+02 4.42000E+02 4.41000E+02 3.46000E+02 3.45000E+02 - 2.50000E+02 2.49000E+02 1.54000E+02 1.53000E+02 5.80000E+01 5.70000E+01 - 1.39000E+03 1.38900E+03 1.29400E+03 1.29300E+03 1.19800E+03 1.19700E+03 - 1.10200E+03 1.10100E+03 1.00600E+03 1.00500E+03 9.10000E+02 9.09000E+02 - 8.14000E+02 8.13000E+02 7.18000E+02 7.17000E+02 6.22000E+02 6.21000E+02 - 5.26000E+02 5.25000E+02 4.30000E+02 4.29000E+02 3.34000E+02 3.33000E+02 - 2.38000E+02 2.37000E+02 1.42000E+02 1.41000E+02 4.60000E+01 4.50000E+01 - 1.37800E+03 1.37700E+03 1.28200E+03 1.28100E+03 1.18600E+03 1.18500E+03 - 1.09000E+03 1.08900E+03 9.94000E+02 9.93000E+02 8.98000E+02 8.97000E+02 - 8.02000E+02 8.01000E+02 7.06000E+02 7.05000E+02 6.10000E+02 6.09000E+02 - 5.14000E+02 5.13000E+02 4.18000E+02 4.17000E+02 3.22000E+02 3.21000E+02 - 2.26000E+02 2.25000E+02 1.30000E+02 1.29000E+02 3.40000E+01 3.30000E+01 - 1.36600E+03 1.36500E+03 1.27000E+03 1.26900E+03 1.17400E+03 1.17300E+03 - 1.07800E+03 1.07700E+03 9.82000E+02 9.81000E+02 8.86000E+02 8.85000E+02 - 7.90000E+02 7.89000E+02 6.94000E+02 6.93000E+02 5.98000E+02 5.97000E+02 - 5.02000E+02 5.01000E+02 4.06000E+02 4.05000E+02 3.10000E+02 3.09000E+02 - 2.14000E+02 2.13000E+02 1.18000E+02 1.17000E+02 2.20000E+01 2.10000E+01 - 1.35400E+03 1.35300E+03 1.25800E+03 1.25700E+03 1.16200E+03 1.16100E+03 - 1.06600E+03 1.06500E+03 9.70000E+02 9.69000E+02 8.74000E+02 8.73000E+02 - 7.78000E+02 7.77000E+02 6.82000E+02 6.81000E+02 5.86000E+02 5.85000E+02 - 4.90000E+02 4.89000E+02 3.94000E+02 3.93000E+02 2.98000E+02 2.97000E+02 - 2.02000E+02 2.01000E+02 1.06000E+02 1.05000E+02 1.00000E+01 9.00000E+00 - 1.43600E+03 1.43500E+03 1.34000E+03 1.33900E+03 1.24400E+03 1.24300E+03 - 1.14800E+03 1.14700E+03 1.05200E+03 1.05100E+03 9.56000E+02 9.55000E+02 - 8.60000E+02 8.59000E+02 7.64000E+02 7.63000E+02 6.68000E+02 6.67000E+02 - 5.72000E+02 5.71000E+02 4.76000E+02 4.75000E+02 3.80000E+02 3.79000E+02 - 2.84000E+02 2.83000E+02 1.88000E+02 1.87000E+02 9.20000E+01 9.10000E+01 - 1.42400E+03 1.42300E+03 1.32800E+03 1.32700E+03 1.23200E+03 1.23100E+03 - 1.13600E+03 1.13500E+03 1.04000E+03 1.03900E+03 9.44000E+02 9.43000E+02 - 8.48000E+02 8.47000E+02 7.52000E+02 7.51000E+02 6.56000E+02 6.55000E+02 - 5.60000E+02 5.59000E+02 4.64000E+02 4.63000E+02 3.68000E+02 3.67000E+02 - 2.72000E+02 2.71000E+02 1.76000E+02 1.75000E+02 8.00000E+01 7.90000E+01 - 1.41200E+03 1.41100E+03 1.31600E+03 1.31500E+03 1.22000E+03 1.21900E+03 - 1.12400E+03 1.12300E+03 1.02800E+03 1.02700E+03 9.32000E+02 9.31000E+02 - 8.36000E+02 8.35000E+02 7.40000E+02 7.39000E+02 6.44000E+02 6.43000E+02 - 5.48000E+02 5.47000E+02 4.52000E+02 4.51000E+02 3.56000E+02 3.55000E+02 - 2.60000E+02 2.59000E+02 1.64000E+02 1.63000E+02 6.80000E+01 6.70000E+01 - 1.40000E+03 1.39900E+03 1.30400E+03 1.30300E+03 1.20800E+03 1.20700E+03 - 1.11200E+03 1.11100E+03 1.01600E+03 1.01500E+03 9.20000E+02 9.19000E+02 - 8.24000E+02 8.23000E+02 7.28000E+02 7.27000E+02 6.32000E+02 6.31000E+02 - 5.36000E+02 5.35000E+02 4.40000E+02 4.39000E+02 3.44000E+02 3.43000E+02 - 2.48000E+02 2.47000E+02 1.52000E+02 1.51000E+02 5.60000E+01 5.50000E+01 - 1.38800E+03 1.38700E+03 1.29200E+03 1.29100E+03 1.19600E+03 1.19500E+03 - 1.10000E+03 1.09900E+03 1.00400E+03 1.00300E+03 9.08000E+02 9.07000E+02 - 8.12000E+02 8.11000E+02 7.16000E+02 7.15000E+02 6.20000E+02 6.19000E+02 - 5.24000E+02 5.23000E+02 4.28000E+02 4.27000E+02 3.32000E+02 3.31000E+02 - 2.36000E+02 2.35000E+02 1.40000E+02 1.39000E+02 4.40000E+01 4.30000E+01 - 1.37600E+03 1.37500E+03 1.28000E+03 1.27900E+03 1.18400E+03 1.18300E+03 - 1.08800E+03 1.08700E+03 9.92000E+02 9.91000E+02 8.96000E+02 8.95000E+02 - 8.00000E+02 7.99000E+02 7.04000E+02 7.03000E+02 6.08000E+02 6.07000E+02 - 5.12000E+02 5.11000E+02 4.16000E+02 4.15000E+02 3.20000E+02 3.19000E+02 - 2.24000E+02 2.23000E+02 1.28000E+02 1.27000E+02 3.20000E+01 3.10000E+01 - 1.36400E+03 1.36300E+03 1.26800E+03 1.26700E+03 1.17200E+03 1.17100E+03 - 1.07600E+03 1.07500E+03 9.80000E+02 9.79000E+02 8.84000E+02 8.83000E+02 - 7.88000E+02 7.87000E+02 6.92000E+02 6.91000E+02 5.96000E+02 5.95000E+02 - 5.00000E+02 4.99000E+02 4.04000E+02 4.03000E+02 3.08000E+02 3.07000E+02 - 2.12000E+02 2.11000E+02 1.16000E+02 1.15000E+02 2.00000E+01 1.90000E+01 - 1.35200E+03 1.35100E+03 1.25600E+03 1.25500E+03 1.16000E+03 1.15900E+03 - 1.06400E+03 1.06300E+03 9.68000E+02 9.67000E+02 8.72000E+02 8.71000E+02 - 7.76000E+02 7.75000E+02 6.80000E+02 6.79000E+02 5.84000E+02 5.83000E+02 - 4.88000E+02 4.87000E+02 3.92000E+02 3.91000E+02 2.96000E+02 2.95000E+02 - 2.00000E+02 1.99000E+02 1.04000E+02 1.03000E+02 8.00000E+00 7.00000E+00 - 1.43400E+03 1.43300E+03 1.33800E+03 1.33700E+03 1.24200E+03 1.24100E+03 - 1.14600E+03 1.14500E+03 1.05000E+03 1.04900E+03 9.54000E+02 9.53000E+02 - 8.58000E+02 8.57000E+02 7.62000E+02 7.61000E+02 6.66000E+02 6.65000E+02 - 5.70000E+02 5.69000E+02 4.74000E+02 4.73000E+02 3.78000E+02 3.77000E+02 - 2.82000E+02 2.81000E+02 1.86000E+02 1.85000E+02 9.00000E+01 8.90000E+01 - 1.42200E+03 1.42100E+03 1.32600E+03 1.32500E+03 1.23000E+03 1.22900E+03 - 1.13400E+03 1.13300E+03 1.03800E+03 1.03700E+03 9.42000E+02 9.41000E+02 - 8.46000E+02 8.45000E+02 7.50000E+02 7.49000E+02 6.54000E+02 6.53000E+02 - 5.58000E+02 5.57000E+02 4.62000E+02 4.61000E+02 3.66000E+02 3.65000E+02 - 2.70000E+02 2.69000E+02 1.74000E+02 1.73000E+02 7.80000E+01 7.70000E+01 - 1.41000E+03 1.40900E+03 1.31400E+03 1.31300E+03 1.21800E+03 1.21700E+03 - 1.12200E+03 1.12100E+03 1.02600E+03 1.02500E+03 9.30000E+02 9.29000E+02 - 8.34000E+02 8.33000E+02 7.38000E+02 7.37000E+02 6.42000E+02 6.41000E+02 - 5.46000E+02 5.45000E+02 4.50000E+02 4.49000E+02 3.54000E+02 3.53000E+02 - 2.58000E+02 2.57000E+02 1.62000E+02 1.61000E+02 6.60000E+01 6.50000E+01 - 1.39800E+03 1.39700E+03 1.30200E+03 1.30100E+03 1.20600E+03 1.20500E+03 - 1.11000E+03 1.10900E+03 1.01400E+03 1.01300E+03 9.18000E+02 9.17000E+02 - 8.22000E+02 8.21000E+02 7.26000E+02 7.25000E+02 6.30000E+02 6.29000E+02 - 5.34000E+02 5.33000E+02 4.38000E+02 4.37000E+02 3.42000E+02 3.41000E+02 - 2.46000E+02 2.45000E+02 1.50000E+02 1.49000E+02 5.40000E+01 5.30000E+01 - 1.38600E+03 1.38500E+03 1.29000E+03 1.28900E+03 1.19400E+03 1.19300E+03 - 1.09800E+03 1.09700E+03 1.00200E+03 1.00100E+03 9.06000E+02 9.05000E+02 - 8.10000E+02 8.09000E+02 7.14000E+02 7.13000E+02 6.18000E+02 6.17000E+02 - 5.22000E+02 5.21000E+02 4.26000E+02 4.25000E+02 3.30000E+02 3.29000E+02 - 2.34000E+02 2.33000E+02 1.38000E+02 1.37000E+02 4.20000E+01 4.10000E+01 - 1.37400E+03 1.37300E+03 1.27800E+03 1.27700E+03 1.18200E+03 1.18100E+03 - 1.08600E+03 1.08500E+03 9.90000E+02 9.89000E+02 8.94000E+02 8.93000E+02 - 7.98000E+02 7.97000E+02 7.02000E+02 7.01000E+02 6.06000E+02 6.05000E+02 - 5.10000E+02 5.09000E+02 4.14000E+02 4.13000E+02 3.18000E+02 3.17000E+02 - 2.22000E+02 2.21000E+02 1.26000E+02 1.25000E+02 3.00000E+01 2.90000E+01 - 1.36200E+03 1.36100E+03 1.26600E+03 1.26500E+03 1.17000E+03 1.16900E+03 - 1.07400E+03 1.07300E+03 9.78000E+02 9.77000E+02 8.82000E+02 8.81000E+02 - 7.86000E+02 7.85000E+02 6.90000E+02 6.89000E+02 5.94000E+02 5.93000E+02 - 4.98000E+02 4.97000E+02 4.02000E+02 4.01000E+02 3.06000E+02 3.05000E+02 - 2.10000E+02 2.09000E+02 1.14000E+02 1.13000E+02 1.80000E+01 1.70000E+01 - 1.35000E+03 1.34900E+03 1.25400E+03 1.25300E+03 1.15800E+03 1.15700E+03 - 1.06200E+03 1.06100E+03 9.66000E+02 9.65000E+02 8.70000E+02 8.69000E+02 - 7.74000E+02 7.73000E+02 6.78000E+02 6.77000E+02 5.82000E+02 5.81000E+02 - 4.86000E+02 4.85000E+02 3.90000E+02 3.89000E+02 2.94000E+02 2.93000E+02 - 1.98000E+02 1.97000E+02 1.02000E+02 1.01000E+02 6.00000E+00 5.00000E+00 - 1.43200E+03 1.43100E+03 1.33600E+03 1.33500E+03 1.24000E+03 1.23900E+03 - 1.14400E+03 1.14300E+03 1.04800E+03 1.04700E+03 9.52000E+02 9.51000E+02 - 8.56000E+02 8.55000E+02 7.60000E+02 7.59000E+02 6.64000E+02 6.63000E+02 - 5.68000E+02 5.67000E+02 4.72000E+02 4.71000E+02 3.76000E+02 3.75000E+02 - 2.80000E+02 2.79000E+02 1.84000E+02 1.83000E+02 8.80000E+01 8.70000E+01 - 1.42000E+03 1.41900E+03 1.32400E+03 1.32300E+03 1.22800E+03 1.22700E+03 - 1.13200E+03 1.13100E+03 1.03600E+03 1.03500E+03 9.40000E+02 9.39000E+02 - 8.44000E+02 8.43000E+02 7.48000E+02 7.47000E+02 6.52000E+02 6.51000E+02 - 5.56000E+02 5.55000E+02 4.60000E+02 4.59000E+02 3.64000E+02 3.63000E+02 - 2.68000E+02 2.67000E+02 1.72000E+02 1.71000E+02 7.60000E+01 7.50000E+01 - 1.40800E+03 1.40700E+03 1.31200E+03 1.31100E+03 1.21600E+03 1.21500E+03 - 1.12000E+03 1.11900E+03 1.02400E+03 1.02300E+03 9.28000E+02 9.27000E+02 - 8.32000E+02 8.31000E+02 7.36000E+02 7.35000E+02 6.40000E+02 6.39000E+02 - 5.44000E+02 5.43000E+02 4.48000E+02 4.47000E+02 3.52000E+02 3.51000E+02 - 2.56000E+02 2.55000E+02 1.60000E+02 1.59000E+02 6.40000E+01 6.30000E+01 - 1.39600E+03 1.39500E+03 1.30000E+03 1.29900E+03 1.20400E+03 1.20300E+03 - 1.10800E+03 1.10700E+03 1.01200E+03 1.01100E+03 9.16000E+02 9.15000E+02 - 8.20000E+02 8.19000E+02 7.24000E+02 7.23000E+02 6.28000E+02 6.27000E+02 - 5.32000E+02 5.31000E+02 4.36000E+02 4.35000E+02 3.40000E+02 3.39000E+02 - 2.44000E+02 2.43000E+02 1.48000E+02 1.47000E+02 5.20000E+01 5.10000E+01 - 1.38400E+03 1.38300E+03 1.28800E+03 1.28700E+03 1.19200E+03 1.19100E+03 - 1.09600E+03 1.09500E+03 1.00000E+03 9.99000E+02 9.04000E+02 9.03000E+02 - 8.08000E+02 8.07000E+02 7.12000E+02 7.11000E+02 6.16000E+02 6.15000E+02 - 5.20000E+02 5.19000E+02 4.24000E+02 4.23000E+02 3.28000E+02 3.27000E+02 - 2.32000E+02 2.31000E+02 1.36000E+02 1.35000E+02 4.00000E+01 3.90000E+01 - 1.37200E+03 1.37100E+03 1.27600E+03 1.27500E+03 1.18000E+03 1.17900E+03 - 1.08400E+03 1.08300E+03 9.88000E+02 9.87000E+02 8.92000E+02 8.91000E+02 - 7.96000E+02 7.95000E+02 7.00000E+02 6.99000E+02 6.04000E+02 6.03000E+02 - 5.08000E+02 5.07000E+02 4.12000E+02 4.11000E+02 3.16000E+02 3.15000E+02 - 2.20000E+02 2.19000E+02 1.24000E+02 1.23000E+02 2.80000E+01 2.70000E+01 - 1.36000E+03 1.35900E+03 1.26400E+03 1.26300E+03 1.16800E+03 1.16700E+03 - 1.07200E+03 1.07100E+03 9.76000E+02 9.75000E+02 8.80000E+02 8.79000E+02 - 7.84000E+02 7.83000E+02 6.88000E+02 6.87000E+02 5.92000E+02 5.91000E+02 - 4.96000E+02 4.95000E+02 4.00000E+02 3.99000E+02 3.04000E+02 3.03000E+02 - 2.08000E+02 2.07000E+02 1.12000E+02 1.11000E+02 1.60000E+01 1.50000E+01 - 1.34800E+03 1.34700E+03 1.25200E+03 1.25100E+03 1.15600E+03 1.15500E+03 - 1.06000E+03 1.05900E+03 9.64000E+02 9.63000E+02 8.68000E+02 8.67000E+02 - 7.72000E+02 7.71000E+02 6.76000E+02 6.75000E+02 5.80000E+02 5.79000E+02 - 4.84000E+02 4.83000E+02 3.88000E+02 3.87000E+02 2.92000E+02 2.91000E+02 - 1.96000E+02 1.95000E+02 1.00000E+02 9.90000E+01 4.00000E+00 3.00000E+00 - 1.43000E+03 1.42900E+03 1.33400E+03 1.33300E+03 1.23800E+03 1.23700E+03 - 1.14200E+03 1.14100E+03 1.04600E+03 1.04500E+03 9.50000E+02 9.49000E+02 - 8.54000E+02 8.53000E+02 7.58000E+02 7.57000E+02 6.62000E+02 6.61000E+02 - 5.66000E+02 5.65000E+02 4.70000E+02 4.69000E+02 3.74000E+02 3.73000E+02 - 2.78000E+02 2.77000E+02 1.82000E+02 1.81000E+02 8.60000E+01 8.50000E+01 - 1.41800E+03 1.41700E+03 1.32200E+03 1.32100E+03 1.22600E+03 1.22500E+03 - 1.13000E+03 1.12900E+03 1.03400E+03 1.03300E+03 9.38000E+02 9.37000E+02 - 8.42000E+02 8.41000E+02 7.46000E+02 7.45000E+02 6.50000E+02 6.49000E+02 - 5.54000E+02 5.53000E+02 4.58000E+02 4.57000E+02 3.62000E+02 3.61000E+02 - 2.66000E+02 2.65000E+02 1.70000E+02 1.69000E+02 7.40000E+01 7.30000E+01 - 1.40600E+03 1.40500E+03 1.31000E+03 1.30900E+03 1.21400E+03 1.21300E+03 - 1.11800E+03 1.11700E+03 1.02200E+03 1.02100E+03 9.26000E+02 9.25000E+02 - 8.30000E+02 8.29000E+02 7.34000E+02 7.33000E+02 6.38000E+02 6.37000E+02 - 5.42000E+02 5.41000E+02 4.46000E+02 4.45000E+02 3.50000E+02 3.49000E+02 - 2.54000E+02 2.53000E+02 1.58000E+02 1.57000E+02 6.20000E+01 6.10000E+01 - 1.39400E+03 1.39300E+03 1.29800E+03 1.29700E+03 1.20200E+03 1.20100E+03 - 1.10600E+03 1.10500E+03 1.01000E+03 1.00900E+03 9.14000E+02 9.13000E+02 - 8.18000E+02 8.17000E+02 7.22000E+02 7.21000E+02 6.26000E+02 6.25000E+02 - 5.30000E+02 5.29000E+02 4.34000E+02 4.33000E+02 3.38000E+02 3.37000E+02 - 2.42000E+02 2.41000E+02 1.46000E+02 1.45000E+02 5.00000E+01 4.90000E+01 - 1.38200E+03 1.38100E+03 1.28600E+03 1.28500E+03 1.19000E+03 1.18900E+03 - 1.09400E+03 1.09300E+03 9.98000E+02 9.97000E+02 9.02000E+02 9.01000E+02 - 8.06000E+02 8.05000E+02 7.10000E+02 7.09000E+02 6.14000E+02 6.13000E+02 - 5.18000E+02 5.17000E+02 4.22000E+02 4.21000E+02 3.26000E+02 3.25000E+02 - 2.30000E+02 2.29000E+02 1.34000E+02 1.33000E+02 3.80000E+01 3.70000E+01 - 1.37000E+03 1.36900E+03 1.27400E+03 1.27300E+03 1.17800E+03 1.17700E+03 - 1.08200E+03 1.08100E+03 9.86000E+02 9.85000E+02 8.90000E+02 8.89000E+02 - 7.94000E+02 7.93000E+02 6.98000E+02 6.97000E+02 6.02000E+02 6.01000E+02 - 5.06000E+02 5.05000E+02 4.10000E+02 4.09000E+02 3.14000E+02 3.13000E+02 - 2.18000E+02 2.17000E+02 1.22000E+02 1.21000E+02 2.60000E+01 2.50000E+01 - 1.35800E+03 1.35700E+03 1.26200E+03 1.26100E+03 1.16600E+03 1.16500E+03 - 1.07000E+03 1.06900E+03 9.74000E+02 9.73000E+02 8.78000E+02 8.77000E+02 - 7.82000E+02 7.81000E+02 6.86000E+02 6.85000E+02 5.90000E+02 5.89000E+02 - 4.94000E+02 4.93000E+02 3.98000E+02 3.97000E+02 3.02000E+02 3.01000E+02 - 2.06000E+02 2.05000E+02 1.10000E+02 1.09000E+02 1.40000E+01 1.30000E+01 - 1.34600E+03 1.34500E+03 1.25000E+03 1.24900E+03 1.15400E+03 1.15300E+03 - 1.05800E+03 1.05700E+03 9.62000E+02 9.61000E+02 8.66000E+02 8.65000E+02 - 7.70000E+02 7.69000E+02 6.74000E+02 6.73000E+02 5.78000E+02 5.77000E+02 - 4.82000E+02 4.81000E+02 3.86000E+02 3.85000E+02 2.90000E+02 2.89000E+02 - 1.94000E+02 1.93000E+02 9.80000E+01 9.70000E+01 2.00000E+00 1.00000E+00 + 1.44000E+03 1.34400E+03 1.24800E+03 1.15200E+03 1.05600E+03 9.60000E+02 + 8.64000E+02 7.68000E+02 6.72000E+02 5.76000E+02 4.80000E+02 3.84000E+02 + 2.88000E+02 1.92000E+02 9.60000E+01 1.42800E+03 1.33200E+03 1.23600E+03 + 1.14000E+03 1.04400E+03 9.48000E+02 8.52000E+02 7.56000E+02 6.60000E+02 + 5.64000E+02 4.68000E+02 3.72000E+02 2.76000E+02 1.80000E+02 8.40000E+01 + 1.41600E+03 1.32000E+03 1.22400E+03 1.12800E+03 1.03200E+03 9.36000E+02 + 8.40000E+02 7.44000E+02 6.48000E+02 5.52000E+02 4.56000E+02 3.60000E+02 + 2.64000E+02 1.68000E+02 7.20000E+01 1.40400E+03 1.30800E+03 1.21200E+03 + 1.11600E+03 1.02000E+03 9.24000E+02 8.28000E+02 7.32000E+02 6.36000E+02 + 5.40000E+02 4.44000E+02 3.48000E+02 2.52000E+02 1.56000E+02 6.00000E+01 + 1.39200E+03 1.29600E+03 1.20000E+03 1.10400E+03 1.00800E+03 9.12000E+02 + 8.16000E+02 7.20000E+02 6.24000E+02 5.28000E+02 4.32000E+02 3.36000E+02 + 2.40000E+02 1.44000E+02 4.80000E+01 1.38000E+03 1.28400E+03 1.18800E+03 + 1.09200E+03 9.96000E+02 9.00000E+02 8.04000E+02 7.08000E+02 6.12000E+02 + 5.16000E+02 4.20000E+02 3.24000E+02 2.28000E+02 1.32000E+02 3.60000E+01 + 1.36800E+03 1.27200E+03 1.17600E+03 1.08000E+03 9.84000E+02 8.88000E+02 + 7.92000E+02 6.96000E+02 6.00000E+02 5.04000E+02 4.08000E+02 3.12000E+02 + 2.16000E+02 1.20000E+02 2.40000E+01 1.35600E+03 1.26000E+03 1.16400E+03 + 1.06800E+03 9.72000E+02 8.76000E+02 7.80000E+02 6.84000E+02 5.88000E+02 + 4.92000E+02 3.96000E+02 3.00000E+02 2.04000E+02 1.08000E+02 1.20000E+01 + 1.43800E+03 1.34200E+03 1.24600E+03 1.15000E+03 1.05400E+03 9.58000E+02 + 8.62000E+02 7.66000E+02 6.70000E+02 5.74000E+02 4.78000E+02 3.82000E+02 + 2.86000E+02 1.90000E+02 9.40000E+01 1.42600E+03 1.33000E+03 1.23400E+03 + 1.13800E+03 1.04200E+03 9.46000E+02 8.50000E+02 7.54000E+02 6.58000E+02 + 5.62000E+02 4.66000E+02 3.70000E+02 2.74000E+02 1.78000E+02 8.20000E+01 + 1.41400E+03 1.31800E+03 1.22200E+03 1.12600E+03 1.03000E+03 9.34000E+02 + 8.38000E+02 7.42000E+02 6.46000E+02 5.50000E+02 4.54000E+02 3.58000E+02 + 2.62000E+02 1.66000E+02 7.00000E+01 1.40200E+03 1.30600E+03 1.21000E+03 + 1.11400E+03 1.01800E+03 9.22000E+02 8.26000E+02 7.30000E+02 6.34000E+02 + 5.38000E+02 4.42000E+02 3.46000E+02 2.50000E+02 1.54000E+02 5.80000E+01 + 1.39000E+03 1.29400E+03 1.19800E+03 1.10200E+03 1.00600E+03 9.10000E+02 + 8.14000E+02 7.18000E+02 6.22000E+02 5.26000E+02 4.30000E+02 3.34000E+02 + 2.38000E+02 1.42000E+02 4.60000E+01 1.37800E+03 1.28200E+03 1.18600E+03 + 1.09000E+03 9.94000E+02 8.98000E+02 8.02000E+02 7.06000E+02 6.10000E+02 + 5.14000E+02 4.18000E+02 3.22000E+02 2.26000E+02 1.30000E+02 3.40000E+01 + 1.36600E+03 1.27000E+03 1.17400E+03 1.07800E+03 9.82000E+02 8.86000E+02 + 7.90000E+02 6.94000E+02 5.98000E+02 5.02000E+02 4.06000E+02 3.10000E+02 + 2.14000E+02 1.18000E+02 2.20000E+01 1.35400E+03 1.25800E+03 1.16200E+03 + 1.06600E+03 9.70000E+02 8.74000E+02 7.78000E+02 6.82000E+02 5.86000E+02 + 4.90000E+02 3.94000E+02 2.98000E+02 2.02000E+02 1.06000E+02 1.00000E+01 + 1.43600E+03 1.34000E+03 1.24400E+03 1.14800E+03 1.05200E+03 9.56000E+02 + 8.60000E+02 7.64000E+02 6.68000E+02 5.72000E+02 4.76000E+02 3.80000E+02 + 2.84000E+02 1.88000E+02 9.20000E+01 1.42400E+03 1.32800E+03 1.23200E+03 + 1.13600E+03 1.04000E+03 9.44000E+02 8.48000E+02 7.52000E+02 6.56000E+02 + 5.60000E+02 4.64000E+02 3.68000E+02 2.72000E+02 1.76000E+02 8.00000E+01 + 1.41200E+03 1.31600E+03 1.22000E+03 1.12400E+03 1.02800E+03 9.32000E+02 + 8.36000E+02 7.40000E+02 6.44000E+02 5.48000E+02 4.52000E+02 3.56000E+02 + 2.60000E+02 1.64000E+02 6.80000E+01 1.40000E+03 1.30400E+03 1.20800E+03 + 1.11200E+03 1.01600E+03 9.20000E+02 8.24000E+02 7.28000E+02 6.32000E+02 + 5.36000E+02 4.40000E+02 3.44000E+02 2.48000E+02 1.52000E+02 5.60000E+01 + 1.38800E+03 1.29200E+03 1.19600E+03 1.10000E+03 1.00400E+03 9.08000E+02 + 8.12000E+02 7.16000E+02 6.20000E+02 5.24000E+02 4.28000E+02 3.32000E+02 + 2.36000E+02 1.40000E+02 4.40000E+01 1.37600E+03 1.28000E+03 1.18400E+03 + 1.08800E+03 9.92000E+02 8.96000E+02 8.00000E+02 7.04000E+02 6.08000E+02 + 5.12000E+02 4.16000E+02 3.20000E+02 2.24000E+02 1.28000E+02 3.20000E+01 + 1.36400E+03 1.26800E+03 1.17200E+03 1.07600E+03 9.80000E+02 8.84000E+02 + 7.88000E+02 6.92000E+02 5.96000E+02 5.00000E+02 4.04000E+02 3.08000E+02 + 2.12000E+02 1.16000E+02 2.00000E+01 1.35200E+03 1.25600E+03 1.16000E+03 + 1.06400E+03 9.68000E+02 8.72000E+02 7.76000E+02 6.80000E+02 5.84000E+02 + 4.88000E+02 3.92000E+02 2.96000E+02 2.00000E+02 1.04000E+02 8.00000E+00 + 1.43400E+03 1.33800E+03 1.24200E+03 1.14600E+03 1.05000E+03 9.54000E+02 + 8.58000E+02 7.62000E+02 6.66000E+02 5.70000E+02 4.74000E+02 3.78000E+02 + 2.82000E+02 1.86000E+02 9.00000E+01 1.42200E+03 1.32600E+03 1.23000E+03 + 1.13400E+03 1.03800E+03 9.42000E+02 8.46000E+02 7.50000E+02 6.54000E+02 + 5.58000E+02 4.62000E+02 3.66000E+02 2.70000E+02 1.74000E+02 7.80000E+01 + 1.41000E+03 1.31400E+03 1.21800E+03 1.12200E+03 1.02600E+03 9.30000E+02 + 8.34000E+02 7.38000E+02 6.42000E+02 5.46000E+02 4.50000E+02 3.54000E+02 + 2.58000E+02 1.62000E+02 6.60000E+01 1.39800E+03 1.30200E+03 1.20600E+03 + 1.11000E+03 1.01400E+03 9.18000E+02 8.22000E+02 7.26000E+02 6.30000E+02 + 5.34000E+02 4.38000E+02 3.42000E+02 2.46000E+02 1.50000E+02 5.40000E+01 + 1.38600E+03 1.29000E+03 1.19400E+03 1.09800E+03 1.00200E+03 9.06000E+02 + 8.10000E+02 7.14000E+02 6.18000E+02 5.22000E+02 4.26000E+02 3.30000E+02 + 2.34000E+02 1.38000E+02 4.20000E+01 1.37400E+03 1.27800E+03 1.18200E+03 + 1.08600E+03 9.90000E+02 8.94000E+02 7.98000E+02 7.02000E+02 6.06000E+02 + 5.10000E+02 4.14000E+02 3.18000E+02 2.22000E+02 1.26000E+02 3.00000E+01 + 1.36200E+03 1.26600E+03 1.17000E+03 1.07400E+03 9.78000E+02 8.82000E+02 + 7.86000E+02 6.90000E+02 5.94000E+02 4.98000E+02 4.02000E+02 3.06000E+02 + 2.10000E+02 1.14000E+02 1.80000E+01 1.35000E+03 1.25400E+03 1.15800E+03 + 1.06200E+03 9.66000E+02 8.70000E+02 7.74000E+02 6.78000E+02 5.82000E+02 + 4.86000E+02 3.90000E+02 2.94000E+02 1.98000E+02 1.02000E+02 6.00000E+00 + 1.43200E+03 1.33600E+03 1.24000E+03 1.14400E+03 1.04800E+03 9.52000E+02 + 8.56000E+02 7.60000E+02 6.64000E+02 5.68000E+02 4.72000E+02 3.76000E+02 + 2.80000E+02 1.84000E+02 8.80000E+01 1.42000E+03 1.32400E+03 1.22800E+03 + 1.13200E+03 1.03600E+03 9.40000E+02 8.44000E+02 7.48000E+02 6.52000E+02 + 5.56000E+02 4.60000E+02 3.64000E+02 2.68000E+02 1.72000E+02 7.60000E+01 + 1.40800E+03 1.31200E+03 1.21600E+03 1.12000E+03 1.02400E+03 9.28000E+02 + 8.32000E+02 7.36000E+02 6.40000E+02 5.44000E+02 4.48000E+02 3.52000E+02 + 2.56000E+02 1.60000E+02 6.40000E+01 1.39600E+03 1.30000E+03 1.20400E+03 + 1.10800E+03 1.01200E+03 9.16000E+02 8.20000E+02 7.24000E+02 6.28000E+02 + 5.32000E+02 4.36000E+02 3.40000E+02 2.44000E+02 1.48000E+02 5.20000E+01 + 1.38400E+03 1.28800E+03 1.19200E+03 1.09600E+03 1.00000E+03 9.04000E+02 + 8.08000E+02 7.12000E+02 6.16000E+02 5.20000E+02 4.24000E+02 3.28000E+02 + 2.32000E+02 1.36000E+02 4.00000E+01 1.37200E+03 1.27600E+03 1.18000E+03 + 1.08400E+03 9.88000E+02 8.92000E+02 7.96000E+02 7.00000E+02 6.04000E+02 + 5.08000E+02 4.12000E+02 3.16000E+02 2.20000E+02 1.24000E+02 2.80000E+01 + 1.36000E+03 1.26400E+03 1.16800E+03 1.07200E+03 9.76000E+02 8.80000E+02 + 7.84000E+02 6.88000E+02 5.92000E+02 4.96000E+02 4.00000E+02 3.04000E+02 + 2.08000E+02 1.12000E+02 1.60000E+01 1.34800E+03 1.25200E+03 1.15600E+03 + 1.06000E+03 9.64000E+02 8.68000E+02 7.72000E+02 6.76000E+02 5.80000E+02 + 4.84000E+02 3.88000E+02 2.92000E+02 1.96000E+02 1.00000E+02 4.00000E+00 + 1.43000E+03 1.33400E+03 1.23800E+03 1.14200E+03 1.04600E+03 9.50000E+02 + 8.54000E+02 7.58000E+02 6.62000E+02 5.66000E+02 4.70000E+02 3.74000E+02 + 2.78000E+02 1.82000E+02 8.60000E+01 1.41800E+03 1.32200E+03 1.22600E+03 + 1.13000E+03 1.03400E+03 9.38000E+02 8.42000E+02 7.46000E+02 6.50000E+02 + 5.54000E+02 4.58000E+02 3.62000E+02 2.66000E+02 1.70000E+02 7.40000E+01 + 1.40600E+03 1.31000E+03 1.21400E+03 1.11800E+03 1.02200E+03 9.26000E+02 + 8.30000E+02 7.34000E+02 6.38000E+02 5.42000E+02 4.46000E+02 3.50000E+02 + 2.54000E+02 1.58000E+02 6.20000E+01 1.39400E+03 1.29800E+03 1.20200E+03 + 1.10600E+03 1.01000E+03 9.14000E+02 8.18000E+02 7.22000E+02 6.26000E+02 + 5.30000E+02 4.34000E+02 3.38000E+02 2.42000E+02 1.46000E+02 5.00000E+01 + 1.38200E+03 1.28600E+03 1.19000E+03 1.09400E+03 9.98000E+02 9.02000E+02 + 8.06000E+02 7.10000E+02 6.14000E+02 5.18000E+02 4.22000E+02 3.26000E+02 + 2.30000E+02 1.34000E+02 3.80000E+01 1.37000E+03 1.27400E+03 1.17800E+03 + 1.08200E+03 9.86000E+02 8.90000E+02 7.94000E+02 6.98000E+02 6.02000E+02 + 5.06000E+02 4.10000E+02 3.14000E+02 2.18000E+02 1.22000E+02 2.60000E+01 + 1.35800E+03 1.26200E+03 1.16600E+03 1.07000E+03 9.74000E+02 8.78000E+02 + 7.82000E+02 6.86000E+02 5.90000E+02 4.94000E+02 3.98000E+02 3.02000E+02 + 2.06000E+02 1.10000E+02 1.40000E+01 1.34600E+03 1.25000E+03 1.15400E+03 + 1.05800E+03 9.62000E+02 8.66000E+02 7.70000E+02 6.74000E+02 5.78000E+02 + 4.82000E+02 3.86000E+02 2.90000E+02 1.94000E+02 9.80000E+01 2.00000E+00 + 1.43900E+03 1.34300E+03 1.24700E+03 1.15100E+03 1.05500E+03 9.59000E+02 + 8.63000E+02 7.67000E+02 6.71000E+02 5.75000E+02 4.79000E+02 3.83000E+02 + 2.87000E+02 1.91000E+02 9.50000E+01 1.42700E+03 1.33100E+03 1.23500E+03 + 1.13900E+03 1.04300E+03 9.47000E+02 8.51000E+02 7.55000E+02 6.59000E+02 + 5.63000E+02 4.67000E+02 3.71000E+02 2.75000E+02 1.79000E+02 8.30000E+01 + 1.41500E+03 1.31900E+03 1.22300E+03 1.12700E+03 1.03100E+03 9.35000E+02 + 8.39000E+02 7.43000E+02 6.47000E+02 5.51000E+02 4.55000E+02 3.59000E+02 + 2.63000E+02 1.67000E+02 7.10000E+01 1.40300E+03 1.30700E+03 1.21100E+03 + 1.11500E+03 1.01900E+03 9.23000E+02 8.27000E+02 7.31000E+02 6.35000E+02 + 5.39000E+02 4.43000E+02 3.47000E+02 2.51000E+02 1.55000E+02 5.90000E+01 + 1.39100E+03 1.29500E+03 1.19900E+03 1.10300E+03 1.00700E+03 9.11000E+02 + 8.15000E+02 7.19000E+02 6.23000E+02 5.27000E+02 4.31000E+02 3.35000E+02 + 2.39000E+02 1.43000E+02 4.70000E+01 1.37900E+03 1.28300E+03 1.18700E+03 + 1.09100E+03 9.95000E+02 8.99000E+02 8.03000E+02 7.07000E+02 6.11000E+02 + 5.15000E+02 4.19000E+02 3.23000E+02 2.27000E+02 1.31000E+02 3.50000E+01 + 1.36700E+03 1.27100E+03 1.17500E+03 1.07900E+03 9.83000E+02 8.87000E+02 + 7.91000E+02 6.95000E+02 5.99000E+02 5.03000E+02 4.07000E+02 3.11000E+02 + 2.15000E+02 1.19000E+02 2.30000E+01 1.35500E+03 1.25900E+03 1.16300E+03 + 1.06700E+03 9.71000E+02 8.75000E+02 7.79000E+02 6.83000E+02 5.87000E+02 + 4.91000E+02 3.95000E+02 2.99000E+02 2.03000E+02 1.07000E+02 1.10000E+01 + 1.43700E+03 1.34100E+03 1.24500E+03 1.14900E+03 1.05300E+03 9.57000E+02 + 8.61000E+02 7.65000E+02 6.69000E+02 5.73000E+02 4.77000E+02 3.81000E+02 + 2.85000E+02 1.89000E+02 9.30000E+01 1.42500E+03 1.32900E+03 1.23300E+03 + 1.13700E+03 1.04100E+03 9.45000E+02 8.49000E+02 7.53000E+02 6.57000E+02 + 5.61000E+02 4.65000E+02 3.69000E+02 2.73000E+02 1.77000E+02 8.10000E+01 + 1.41300E+03 1.31700E+03 1.22100E+03 1.12500E+03 1.02900E+03 9.33000E+02 + 8.37000E+02 7.41000E+02 6.45000E+02 5.49000E+02 4.53000E+02 3.57000E+02 + 2.61000E+02 1.65000E+02 6.90000E+01 1.40100E+03 1.30500E+03 1.20900E+03 + 1.11300E+03 1.01700E+03 9.21000E+02 8.25000E+02 7.29000E+02 6.33000E+02 + 5.37000E+02 4.41000E+02 3.45000E+02 2.49000E+02 1.53000E+02 5.70000E+01 + 1.38900E+03 1.29300E+03 1.19700E+03 1.10100E+03 1.00500E+03 9.09000E+02 + 8.13000E+02 7.17000E+02 6.21000E+02 5.25000E+02 4.29000E+02 3.33000E+02 + 2.37000E+02 1.41000E+02 4.50000E+01 1.37700E+03 1.28100E+03 1.18500E+03 + 1.08900E+03 9.93000E+02 8.97000E+02 8.01000E+02 7.05000E+02 6.09000E+02 + 5.13000E+02 4.17000E+02 3.21000E+02 2.25000E+02 1.29000E+02 3.30000E+01 + 1.36500E+03 1.26900E+03 1.17300E+03 1.07700E+03 9.81000E+02 8.85000E+02 + 7.89000E+02 6.93000E+02 5.97000E+02 5.01000E+02 4.05000E+02 3.09000E+02 + 2.13000E+02 1.17000E+02 2.10000E+01 1.35300E+03 1.25700E+03 1.16100E+03 + 1.06500E+03 9.69000E+02 8.73000E+02 7.77000E+02 6.81000E+02 5.85000E+02 + 4.89000E+02 3.93000E+02 2.97000E+02 2.01000E+02 1.05000E+02 9.00000E+00 + 1.43500E+03 1.33900E+03 1.24300E+03 1.14700E+03 1.05100E+03 9.55000E+02 + 8.59000E+02 7.63000E+02 6.67000E+02 5.71000E+02 4.75000E+02 3.79000E+02 + 2.83000E+02 1.87000E+02 9.10000E+01 1.42300E+03 1.32700E+03 1.23100E+03 + 1.13500E+03 1.03900E+03 9.43000E+02 8.47000E+02 7.51000E+02 6.55000E+02 + 5.59000E+02 4.63000E+02 3.67000E+02 2.71000E+02 1.75000E+02 7.90000E+01 + 1.41100E+03 1.31500E+03 1.21900E+03 1.12300E+03 1.02700E+03 9.31000E+02 + 8.35000E+02 7.39000E+02 6.43000E+02 5.47000E+02 4.51000E+02 3.55000E+02 + 2.59000E+02 1.63000E+02 6.70000E+01 1.39900E+03 1.30300E+03 1.20700E+03 + 1.11100E+03 1.01500E+03 9.19000E+02 8.23000E+02 7.27000E+02 6.31000E+02 + 5.35000E+02 4.39000E+02 3.43000E+02 2.47000E+02 1.51000E+02 5.50000E+01 + 1.38700E+03 1.29100E+03 1.19500E+03 1.09900E+03 1.00300E+03 9.07000E+02 + 8.11000E+02 7.15000E+02 6.19000E+02 5.23000E+02 4.27000E+02 3.31000E+02 + 2.35000E+02 1.39000E+02 4.30000E+01 1.37500E+03 1.27900E+03 1.18300E+03 + 1.08700E+03 9.91000E+02 8.95000E+02 7.99000E+02 7.03000E+02 6.07000E+02 + 5.11000E+02 4.15000E+02 3.19000E+02 2.23000E+02 1.27000E+02 3.10000E+01 + 1.36300E+03 1.26700E+03 1.17100E+03 1.07500E+03 9.79000E+02 8.83000E+02 + 7.87000E+02 6.91000E+02 5.95000E+02 4.99000E+02 4.03000E+02 3.07000E+02 + 2.11000E+02 1.15000E+02 1.90000E+01 1.35100E+03 1.25500E+03 1.15900E+03 + 1.06300E+03 9.67000E+02 8.71000E+02 7.75000E+02 6.79000E+02 5.83000E+02 + 4.87000E+02 3.91000E+02 2.95000E+02 1.99000E+02 1.03000E+02 7.00000E+00 + 1.43300E+03 1.33700E+03 1.24100E+03 1.14500E+03 1.04900E+03 9.53000E+02 + 8.57000E+02 7.61000E+02 6.65000E+02 5.69000E+02 4.73000E+02 3.77000E+02 + 2.81000E+02 1.85000E+02 8.90000E+01 1.42100E+03 1.32500E+03 1.22900E+03 + 1.13300E+03 1.03700E+03 9.41000E+02 8.45000E+02 7.49000E+02 6.53000E+02 + 5.57000E+02 4.61000E+02 3.65000E+02 2.69000E+02 1.73000E+02 7.70000E+01 + 1.40900E+03 1.31300E+03 1.21700E+03 1.12100E+03 1.02500E+03 9.29000E+02 + 8.33000E+02 7.37000E+02 6.41000E+02 5.45000E+02 4.49000E+02 3.53000E+02 + 2.57000E+02 1.61000E+02 6.50000E+01 1.39700E+03 1.30100E+03 1.20500E+03 + 1.10900E+03 1.01300E+03 9.17000E+02 8.21000E+02 7.25000E+02 6.29000E+02 + 5.33000E+02 4.37000E+02 3.41000E+02 2.45000E+02 1.49000E+02 5.30000E+01 + 1.38500E+03 1.28900E+03 1.19300E+03 1.09700E+03 1.00100E+03 9.05000E+02 + 8.09000E+02 7.13000E+02 6.17000E+02 5.21000E+02 4.25000E+02 3.29000E+02 + 2.33000E+02 1.37000E+02 4.10000E+01 1.37300E+03 1.27700E+03 1.18100E+03 + 1.08500E+03 9.89000E+02 8.93000E+02 7.97000E+02 7.01000E+02 6.05000E+02 + 5.09000E+02 4.13000E+02 3.17000E+02 2.21000E+02 1.25000E+02 2.90000E+01 + 1.36100E+03 1.26500E+03 1.16900E+03 1.07300E+03 9.77000E+02 8.81000E+02 + 7.85000E+02 6.89000E+02 5.93000E+02 4.97000E+02 4.01000E+02 3.05000E+02 + 2.09000E+02 1.13000E+02 1.70000E+01 1.34900E+03 1.25300E+03 1.15700E+03 + 1.06100E+03 9.65000E+02 8.69000E+02 7.73000E+02 6.77000E+02 5.81000E+02 + 4.85000E+02 3.89000E+02 2.93000E+02 1.97000E+02 1.01000E+02 5.00000E+00 + 1.43100E+03 1.33500E+03 1.23900E+03 1.14300E+03 1.04700E+03 9.51000E+02 + 8.55000E+02 7.59000E+02 6.63000E+02 5.67000E+02 4.71000E+02 3.75000E+02 + 2.79000E+02 1.83000E+02 8.70000E+01 1.41900E+03 1.32300E+03 1.22700E+03 + 1.13100E+03 1.03500E+03 9.39000E+02 8.43000E+02 7.47000E+02 6.51000E+02 + 5.55000E+02 4.59000E+02 3.63000E+02 2.67000E+02 1.71000E+02 7.50000E+01 + 1.40700E+03 1.31100E+03 1.21500E+03 1.11900E+03 1.02300E+03 9.27000E+02 + 8.31000E+02 7.35000E+02 6.39000E+02 5.43000E+02 4.47000E+02 3.51000E+02 + 2.55000E+02 1.59000E+02 6.30000E+01 1.39500E+03 1.29900E+03 1.20300E+03 + 1.10700E+03 1.01100E+03 9.15000E+02 8.19000E+02 7.23000E+02 6.27000E+02 + 5.31000E+02 4.35000E+02 3.39000E+02 2.43000E+02 1.47000E+02 5.10000E+01 + 1.38300E+03 1.28700E+03 1.19100E+03 1.09500E+03 9.99000E+02 9.03000E+02 + 8.07000E+02 7.11000E+02 6.15000E+02 5.19000E+02 4.23000E+02 3.27000E+02 + 2.31000E+02 1.35000E+02 3.90000E+01 1.37100E+03 1.27500E+03 1.17900E+03 + 1.08300E+03 9.87000E+02 8.91000E+02 7.95000E+02 6.99000E+02 6.03000E+02 + 5.07000E+02 4.11000E+02 3.15000E+02 2.19000E+02 1.23000E+02 2.70000E+01 + 1.35900E+03 1.26300E+03 1.16700E+03 1.07100E+03 9.75000E+02 8.79000E+02 + 7.83000E+02 6.87000E+02 5.91000E+02 4.95000E+02 3.99000E+02 3.03000E+02 + 2.07000E+02 1.11000E+02 1.50000E+01 1.34700E+03 1.25100E+03 1.15500E+03 + 1.05900E+03 9.63000E+02 8.67000E+02 7.71000E+02 6.75000E+02 5.79000E+02 + 4.83000E+02 3.87000E+02 2.91000E+02 1.95000E+02 9.90000E+01 3.00000E+00 + 1.42900E+03 1.33300E+03 1.23700E+03 1.14100E+03 1.04500E+03 9.49000E+02 + 8.53000E+02 7.57000E+02 6.61000E+02 5.65000E+02 4.69000E+02 3.73000E+02 + 2.77000E+02 1.81000E+02 8.50000E+01 1.41700E+03 1.32100E+03 1.22500E+03 + 1.12900E+03 1.03300E+03 9.37000E+02 8.41000E+02 7.45000E+02 6.49000E+02 + 5.53000E+02 4.57000E+02 3.61000E+02 2.65000E+02 1.69000E+02 7.30000E+01 + 1.40500E+03 1.30900E+03 1.21300E+03 1.11700E+03 1.02100E+03 9.25000E+02 + 8.29000E+02 7.33000E+02 6.37000E+02 5.41000E+02 4.45000E+02 3.49000E+02 + 2.53000E+02 1.57000E+02 6.10000E+01 1.39300E+03 1.29700E+03 1.20100E+03 + 1.10500E+03 1.00900E+03 9.13000E+02 8.17000E+02 7.21000E+02 6.25000E+02 + 5.29000E+02 4.33000E+02 3.37000E+02 2.41000E+02 1.45000E+02 4.90000E+01 + 1.38100E+03 1.28500E+03 1.18900E+03 1.09300E+03 9.97000E+02 9.01000E+02 + 8.05000E+02 7.09000E+02 6.13000E+02 5.17000E+02 4.21000E+02 3.25000E+02 + 2.29000E+02 1.33000E+02 3.70000E+01 1.36900E+03 1.27300E+03 1.17700E+03 + 1.08100E+03 9.85000E+02 8.89000E+02 7.93000E+02 6.97000E+02 6.01000E+02 + 5.05000E+02 4.09000E+02 3.13000E+02 2.17000E+02 1.21000E+02 2.50000E+01 + 1.35700E+03 1.26100E+03 1.16500E+03 1.06900E+03 9.73000E+02 8.77000E+02 + 7.81000E+02 6.85000E+02 5.89000E+02 4.93000E+02 3.97000E+02 3.01000E+02 + 2.05000E+02 1.09000E+02 1.30000E+01 1.34500E+03 1.24900E+03 1.15300E+03 + 1.05700E+03 9.61000E+02 8.65000E+02 7.69000E+02 6.73000E+02 5.77000E+02 + 4.81000E+02 3.85000E+02 2.89000E+02 1.93000E+02 9.70000E+01 1.00000E+00 diff --git a/tests/unit_tests/weightwindows/wwinp_np b/tests/unit_tests/weightwindows/wwinp_np index 6d77afc3e..ed2073cf9 100644 --- a/tests/unit_tests/weightwindows/wwinp_np +++ b/tests/unit_tests/weightwindows/wwinp_np @@ -13,30 +13,30 @@ 1.00000E+00 1.00000E+00 6.66667E+01 1.00000E+00 1.00000E+00 1.00000E+02 1.00000E+00 1.00000E-01 1.46780E-01 2.15440E-01 - 1.44000E+02 1.43000E+02 1.42000E+02 1.26000E+02 1.25000E+02 1.24000E+02 - 1.08000E+02 1.07000E+02 1.06000E+02 9.00000E+01 8.90000E+01 8.80000E+01 - 7.20000E+01 7.10000E+01 7.00000E+01 5.40000E+01 5.30000E+01 5.20000E+01 - 3.60000E+01 3.50000E+01 3.40000E+01 1.80000E+01 1.70000E+01 1.60000E+01 - 1.41000E+02 1.40000E+02 1.39000E+02 1.23000E+02 1.22000E+02 1.21000E+02 - 1.05000E+02 1.04000E+02 1.03000E+02 8.70000E+01 8.60000E+01 8.50000E+01 - 6.90000E+01 6.80000E+01 6.70000E+01 5.10000E+01 5.00000E+01 4.90000E+01 - 3.30000E+01 3.20000E+01 3.10000E+01 1.50000E+01 1.40000E+01 1.30000E+01 - 1.38000E+02 1.37000E+02 1.36000E+02 1.20000E+02 1.19000E+02 1.18000E+02 - 1.02000E+02 1.01000E+02 1.00000E+02 8.40000E+01 8.30000E+01 8.20000E+01 - 6.60000E+01 6.50000E+01 6.40000E+01 4.80000E+01 4.70000E+01 4.60000E+01 - 3.00000E+01 2.90000E+01 2.80000E+01 1.20000E+01 1.10000E+01 1.00000E+01 - 1.35000E+02 1.34000E+02 1.33000E+02 1.17000E+02 1.16000E+02 1.15000E+02 - 9.90000E+01 9.80000E+01 9.70000E+01 8.10000E+01 8.00000E+01 7.90000E+01 - 6.30000E+01 6.20000E+01 6.10000E+01 4.50000E+01 4.40000E+01 4.30000E+01 - 2.70000E+01 2.60000E+01 2.50000E+01 9.00000E+00 8.00000E+00 7.00000E+00 - 1.32000E+02 1.31000E+02 1.30000E+02 1.14000E+02 1.13000E+02 1.12000E+02 - 9.60000E+01 9.50000E+01 9.40000E+01 7.80000E+01 7.70000E+01 7.60000E+01 - 6.00000E+01 5.90000E+01 5.80000E+01 4.20000E+01 4.10000E+01 4.00000E+01 - 2.40000E+01 2.30000E+01 2.20000E+01 6.00000E+00 5.00000E+00 4.00000E+00 - 1.29000E+02 1.28000E+02 1.27000E+02 1.11000E+02 1.10000E+02 1.09000E+02 - 9.30000E+01 9.20000E+01 9.10000E+01 7.50000E+01 7.40000E+01 7.30000E+01 - 5.70000E+01 5.60000E+01 5.50000E+01 3.90000E+01 3.80000E+01 3.70000E+01 - 2.10000E+01 2.00000E+01 1.90000E+01 3.00000E+00 2.00000E+00 1.00000E+00 + 1.44000E+02 1.26000E+02 1.08000E+02 9.00000E+01 7.20000E+01 5.40000E+01 + 3.60000E+01 1.80000E+01 1.41000E+02 1.23000E+02 1.05000E+02 8.70000E+01 + 6.90000E+01 5.10000E+01 3.30000E+01 1.50000E+01 1.38000E+02 1.20000E+02 + 1.02000E+02 8.40000E+01 6.60000E+01 4.80000E+01 3.00000E+01 1.20000E+01 + 1.35000E+02 1.17000E+02 9.90000E+01 8.10000E+01 6.30000E+01 4.50000E+01 + 2.70000E+01 9.00000E+00 1.32000E+02 1.14000E+02 9.60000E+01 7.80000E+01 + 6.00000E+01 4.20000E+01 2.40000E+01 6.00000E+00 1.29000E+02 1.11000E+02 + 9.30000E+01 7.50000E+01 5.70000E+01 3.90000E+01 2.10000E+01 3.00000E+00 + 1.43000E+02 1.25000E+02 1.07000E+02 8.90000E+01 7.10000E+01 5.30000E+01 + 3.50000E+01 1.70000E+01 1.40000E+02 1.22000E+02 1.04000E+02 8.60000E+01 + 6.80000E+01 5.00000E+01 3.20000E+01 1.40000E+01 1.37000E+02 1.19000E+02 + 1.01000E+02 8.30000E+01 6.50000E+01 4.70000E+01 2.90000E+01 1.10000E+01 + 1.34000E+02 1.16000E+02 9.80000E+01 8.00000E+01 6.20000E+01 4.40000E+01 + 2.60000E+01 8.00000E+00 1.31000E+02 1.13000E+02 9.50000E+01 7.70000E+01 + 5.90000E+01 4.10000E+01 2.30000E+01 5.00000E+00 1.28000E+02 1.10000E+02 + 9.20000E+01 7.40000E+01 5.60000E+01 3.80000E+01 2.00000E+01 2.00000E+00 + 1.42000E+02 1.24000E+02 1.06000E+02 8.80000E+01 7.00000E+01 5.20000E+01 + 3.40000E+01 1.60000E+01 1.39000E+02 1.21000E+02 1.03000E+02 8.50000E+01 + 6.70000E+01 4.90000E+01 3.10000E+01 1.30000E+01 1.36000E+02 1.18000E+02 + 1.00000E+02 8.20000E+01 6.40000E+01 4.60000E+01 2.80000E+01 1.00000E+01 + 1.33000E+02 1.15000E+02 9.70000E+01 7.90000E+01 6.10000E+01 4.30000E+01 + 2.50000E+01 7.00000E+00 1.30000E+02 1.12000E+02 9.40000E+01 7.60000E+01 + 5.80000E+01 4.00000E+01 2.20000E+01 4.00000E+00 1.27000E+02 1.09000E+02 + 9.10000E+01 7.30000E+01 5.50000E+01 3.70000E+01 1.90000E+01 1.00000E+00 1.00000E+02 4.80000E+01 4.20000E+01 3.60000E+01 3.00000E+01 2.40000E+01 1.80000E+01 1.20000E+01 6.00000E+00 4.70000E+01 4.10000E+01 3.50000E+01 2.90000E+01 @@ -46,3 +46,4 @@ 9.00000E+00 3.00000E+00 4.40000E+01 3.80000E+01 3.20000E+01 2.60000E+01 2.00000E+01 1.40000E+01 8.00000E+00 2.00000E+00 4.30000E+01 3.70000E+01 3.10000E+01 2.50000E+01 1.90000E+01 1.30000E+01 7.00000E+00 1.00000E+00 + diff --git a/tests/unit_tests/weightwindows/wwinp_p b/tests/unit_tests/weightwindows/wwinp_p index 95315692f..a9f9f98df 100644 --- a/tests/unit_tests/weightwindows/wwinp_p +++ b/tests/unit_tests/weightwindows/wwinp_p @@ -13,36 +13,36 @@ 1.00000E+00 -5.00000E+01 1.00000E+00 5.00000E+01 1.00000E+00 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 - 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 - 1.58000E+02 1.57000E+02 1.28000E+02 1.27000E+02 1.26000E+02 1.25000E+02 - 9.60000E+01 9.50000E+01 9.40000E+01 9.30000E+01 6.40000E+01 6.30000E+01 - 6.20000E+01 6.10000E+01 3.20000E+01 3.10000E+01 3.00000E+01 2.90000E+01 - 1.88000E+02 1.87000E+02 1.86000E+02 1.85000E+02 1.56000E+02 1.55000E+02 - 1.54000E+02 1.53000E+02 1.24000E+02 1.23000E+02 1.22000E+02 1.21000E+02 - 9.20000E+01 9.10000E+01 9.00000E+01 8.90000E+01 6.00000E+01 5.90000E+01 - 5.80000E+01 5.70000E+01 2.80000E+01 2.70000E+01 2.60000E+01 2.50000E+01 - 1.84000E+02 1.83000E+02 1.82000E+02 1.81000E+02 1.52000E+02 1.51000E+02 - 1.50000E+02 1.49000E+02 1.20000E+02 1.19000E+02 1.18000E+02 1.17000E+02 - 8.80000E+01 8.70000E+01 8.60000E+01 8.50000E+01 5.60000E+01 5.50000E+01 - 5.40000E+01 5.30000E+01 2.40000E+01 2.30000E+01 2.20000E+01 2.10000E+01 - 1.80000E+02 1.79000E+02 1.78000E+02 1.77000E+02 1.48000E+02 1.47000E+02 - 1.46000E+02 1.45000E+02 1.16000E+02 1.15000E+02 1.14000E+02 1.13000E+02 - 8.40000E+01 8.30000E+01 8.20000E+01 8.10000E+01 5.20000E+01 5.10000E+01 - 5.00000E+01 4.90000E+01 2.00000E+01 1.90000E+01 1.80000E+01 1.70000E+01 - 1.76000E+02 1.75000E+02 1.74000E+02 1.73000E+02 1.44000E+02 1.43000E+02 - 1.42000E+02 1.41000E+02 1.12000E+02 1.11000E+02 1.10000E+02 1.09000E+02 - 8.00000E+01 7.90000E+01 7.80000E+01 7.70000E+01 4.80000E+01 4.70000E+01 - 4.60000E+01 4.50000E+01 1.60000E+01 1.50000E+01 1.40000E+01 1.30000E+01 - 1.72000E+02 1.71000E+02 1.70000E+02 1.69000E+02 1.40000E+02 1.39000E+02 - 1.38000E+02 1.37000E+02 1.08000E+02 1.07000E+02 1.06000E+02 1.05000E+02 - 7.60000E+01 7.50000E+01 7.40000E+01 7.30000E+01 4.40000E+01 4.30000E+01 - 4.20000E+01 4.10000E+01 1.20000E+01 1.10000E+01 1.00000E+01 9.00000E+00 - 1.68000E+02 1.67000E+02 1.66000E+02 1.65000E+02 1.36000E+02 1.35000E+02 - 1.34000E+02 1.33000E+02 1.04000E+02 1.03000E+02 1.02000E+02 1.01000E+02 - 7.20000E+01 7.10000E+01 7.00000E+01 6.90000E+01 4.00000E+01 3.90000E+01 - 3.80000E+01 3.70000E+01 8.00000E+00 7.00000E+00 6.00000E+00 5.00000E+00 - 1.64000E+02 1.63000E+02 1.62000E+02 1.61000E+02 1.32000E+02 1.31000E+02 - 1.30000E+02 1.29000E+02 1.00000E+02 9.90000E+01 9.80000E+01 9.70000E+01 - 6.80000E+01 6.70000E+01 6.60000E+01 6.50000E+01 3.60000E+01 3.50000E+01 - 3.40000E+01 3.30000E+01 4.00000E+00 3.00000E+00 2.00000E+00 1.00000E+00 + 1.92000E+02 1.60000E+02 1.28000E+02 9.60000E+01 6.40000E+01 3.20000E+01 + 1.88000E+02 1.56000E+02 1.24000E+02 9.20000E+01 6.00000E+01 2.80000E+01 + 1.84000E+02 1.52000E+02 1.20000E+02 8.80000E+01 5.60000E+01 2.40000E+01 + 1.80000E+02 1.48000E+02 1.16000E+02 8.40000E+01 5.20000E+01 2.00000E+01 + 1.76000E+02 1.44000E+02 1.12000E+02 8.00000E+01 4.80000E+01 1.60000E+01 + 1.72000E+02 1.40000E+02 1.08000E+02 7.60000E+01 4.40000E+01 1.20000E+01 + 1.68000E+02 1.36000E+02 1.04000E+02 7.20000E+01 4.00000E+01 8.00000E+00 + 1.64000E+02 1.32000E+02 1.00000E+02 6.80000E+01 3.60000E+01 4.00000E+00 + 1.91000E+02 1.59000E+02 1.27000E+02 9.50000E+01 6.30000E+01 3.10000E+01 + 1.87000E+02 1.55000E+02 1.23000E+02 9.10000E+01 5.90000E+01 2.70000E+01 + 1.83000E+02 1.51000E+02 1.19000E+02 8.70000E+01 5.50000E+01 2.30000E+01 + 1.79000E+02 1.47000E+02 1.15000E+02 8.30000E+01 5.10000E+01 1.90000E+01 + 1.75000E+02 1.43000E+02 1.11000E+02 7.90000E+01 4.70000E+01 1.50000E+01 + 1.71000E+02 1.39000E+02 1.07000E+02 7.50000E+01 4.30000E+01 1.10000E+01 + 1.67000E+02 1.35000E+02 1.03000E+02 7.10000E+01 3.90000E+01 7.00000E+00 + 1.63000E+02 1.31000E+02 9.90000E+01 6.70000E+01 3.50000E+01 3.00000E+00 + 1.90000E+02 1.58000E+02 1.26000E+02 9.40000E+01 6.20000E+01 3.00000E+01 + 1.86000E+02 1.54000E+02 1.22000E+02 9.00000E+01 5.80000E+01 2.60000E+01 + 1.82000E+02 1.50000E+02 1.18000E+02 8.60000E+01 5.40000E+01 2.20000E+01 + 1.78000E+02 1.46000E+02 1.14000E+02 8.20000E+01 5.00000E+01 1.80000E+01 + 1.74000E+02 1.42000E+02 1.10000E+02 7.80000E+01 4.60000E+01 1.40000E+01 + 1.70000E+02 1.38000E+02 1.06000E+02 7.40000E+01 4.20000E+01 1.00000E+01 + 1.66000E+02 1.34000E+02 1.02000E+02 7.00000E+01 3.80000E+01 6.00000E+00 + 1.62000E+02 1.30000E+02 9.80000E+01 6.60000E+01 3.40000E+01 2.00000E+00 + 1.89000E+02 1.57000E+02 1.25000E+02 9.30000E+01 6.10000E+01 2.90000E+01 + 1.85000E+02 1.53000E+02 1.21000E+02 8.90000E+01 5.70000E+01 2.50000E+01 + 1.81000E+02 1.49000E+02 1.17000E+02 8.50000E+01 5.30000E+01 2.10000E+01 + 1.77000E+02 1.45000E+02 1.13000E+02 8.10000E+01 4.90000E+01 1.70000E+01 + 1.73000E+02 1.41000E+02 1.09000E+02 7.70000E+01 4.50000E+01 1.30000E+01 + 1.69000E+02 1.37000E+02 1.05000E+02 7.30000E+01 4.10000E+01 9.00000E+00 + 1.65000E+02 1.33000E+02 1.01000E+02 6.90000E+01 3.70000E+01 5.00000E+00 + 1.61000E+02 1.29000E+02 9.70000E+01 6.50000E+01 3.30000E+01 1.00000E+00 From 4957ba240b1f6f77f1e7811e26e4214fac18acde Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 3 Oct 2022 07:17:07 -0400 Subject: [PATCH 1040/2654] revert to original expected ww lb --- tests/unit_tests/weightwindows/test_wwinp_reader.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index 437e588f6..8d7cd5f7d 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -118,12 +118,7 @@ def test_wwinp_reader(wwinp_data, request): # check the expected weight window values mocked in the file -- # a reversed array of the flat index into the numpy array n_wws = np.prod((*mesh.dimension, e_bounds.size - 1)) - nx, ny, nz, ne = mesh.dimension + (e_bounds.size - 1,) - exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1].reshape(nx, ny, nz, ne) - # this is how the ww lower bounds were actually written to file - exp_ww_lb = np.swapaxes(exp_ww_lb, 0, 2).flatten() - # this is how we expect them to be read back in - exp_ww_lb = exp_ww_lb.reshape(ne, nz, ny, nx).T.flatten() + exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1] np.testing.assert_array_equal(exp_ww_lb, ww.lower_ww_bounds.flatten()) From 6bc2ee8e4fd2ad0c2fc950fa7a7b09c97163557c Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 3 Oct 2022 07:19:58 -0400 Subject: [PATCH 1041/2654] updated cyl and t wwlb for future tests --- tests/unit_tests/weightwindows/wwinp_cyl | 64 ++++++++++++------------ tests/unit_tests/weightwindows/wwinp_t | 64 ++++++++++++------------ 2 files changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/unit_tests/weightwindows/wwinp_cyl b/tests/unit_tests/weightwindows/wwinp_cyl index 890844b87..aac9d46f2 100644 --- a/tests/unit_tests/weightwindows/wwinp_cyl +++ b/tests/unit_tests/weightwindows/wwinp_cyl @@ -14,35 +14,35 @@ 1.00000E+00 0.00000E+01 1.00000E+00 3.14159E+00 1.00000E+00 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 - 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 - 1.58000E+02 1.57000E+02 1.28000E+02 1.27000E+02 1.26000E+02 1.25000E+02 - 9.60000E+01 9.50000E+01 9.40000E+01 9.30000E+01 6.40000E+01 6.30000E+01 - 6.20000E+01 6.10000E+01 3.20000E+01 3.10000E+01 3.00000E+01 2.90000E+01 - 1.88000E+02 1.87000E+02 1.86000E+02 1.85000E+02 1.56000E+02 1.55000E+02 - 1.54000E+02 1.53000E+02 1.24000E+02 1.23000E+02 1.22000E+02 1.21000E+02 - 9.20000E+01 9.10000E+01 9.00000E+01 8.90000E+01 6.00000E+01 5.90000E+01 - 5.80000E+01 5.70000E+01 2.80000E+01 2.70000E+01 2.60000E+01 2.50000E+01 - 1.84000E+02 1.83000E+02 1.82000E+02 1.81000E+02 1.52000E+02 1.51000E+02 - 1.50000E+02 1.49000E+02 1.20000E+02 1.19000E+02 1.18000E+02 1.17000E+02 - 8.80000E+01 8.70000E+01 8.60000E+01 8.50000E+01 5.60000E+01 5.50000E+01 - 5.40000E+01 5.30000E+01 2.40000E+01 2.30000E+01 2.20000E+01 2.10000E+01 - 1.80000E+02 1.79000E+02 1.78000E+02 1.77000E+02 1.48000E+02 1.47000E+02 - 1.46000E+02 1.45000E+02 1.16000E+02 1.15000E+02 1.14000E+02 1.13000E+02 - 8.40000E+01 8.30000E+01 8.20000E+01 8.10000E+01 5.20000E+01 5.10000E+01 - 5.00000E+01 4.90000E+01 2.00000E+01 1.90000E+01 1.80000E+01 1.70000E+01 - 1.76000E+02 1.75000E+02 1.74000E+02 1.73000E+02 1.44000E+02 1.43000E+02 - 1.42000E+02 1.41000E+02 1.12000E+02 1.11000E+02 1.10000E+02 1.09000E+02 - 8.00000E+01 7.90000E+01 7.80000E+01 7.70000E+01 4.80000E+01 4.70000E+01 - 4.60000E+01 4.50000E+01 1.60000E+01 1.50000E+01 1.40000E+01 1.30000E+01 - 1.72000E+02 1.71000E+02 1.70000E+02 1.69000E+02 1.40000E+02 1.39000E+02 - 1.38000E+02 1.37000E+02 1.08000E+02 1.07000E+02 1.06000E+02 1.05000E+02 - 7.60000E+01 7.50000E+01 7.40000E+01 7.30000E+01 4.40000E+01 4.30000E+01 - 4.20000E+01 4.10000E+01 1.20000E+01 1.10000E+01 1.00000E+01 9.00000E+00 - 1.68000E+02 1.67000E+02 1.66000E+02 1.65000E+02 1.36000E+02 1.35000E+02 - 1.34000E+02 1.33000E+02 1.04000E+02 1.03000E+02 1.02000E+02 1.01000E+02 - 7.20000E+01 7.10000E+01 7.00000E+01 6.90000E+01 4.00000E+01 3.90000E+01 - 3.80000E+01 3.70000E+01 8.00000E+00 7.00000E+00 6.00000E+00 5.00000E+00 - 1.64000E+02 1.63000E+02 1.62000E+02 1.61000E+02 1.32000E+02 1.31000E+02 - 1.30000E+02 1.29000E+02 1.00000E+02 9.90000E+01 9.80000E+01 9.70000E+01 - 6.80000E+01 6.70000E+01 6.60000E+01 6.50000E+01 3.60000E+01 3.50000E+01 - 3.40000E+01 3.30000E+01 4.00000E+00 3.00000E+00 2.00000E+00 1.00000E+00 + 1.92000E+02 1.60000E+02 1.28000E+02 9.60000E+01 6.40000E+01 3.20000E+01 + 1.88000E+02 1.56000E+02 1.24000E+02 9.20000E+01 6.00000E+01 2.80000E+01 + 1.84000E+02 1.52000E+02 1.20000E+02 8.80000E+01 5.60000E+01 2.40000E+01 + 1.80000E+02 1.48000E+02 1.16000E+02 8.40000E+01 5.20000E+01 2.00000E+01 + 1.76000E+02 1.44000E+02 1.12000E+02 8.00000E+01 4.80000E+01 1.60000E+01 + 1.72000E+02 1.40000E+02 1.08000E+02 7.60000E+01 4.40000E+01 1.20000E+01 + 1.68000E+02 1.36000E+02 1.04000E+02 7.20000E+01 4.00000E+01 8.00000E+00 + 1.64000E+02 1.32000E+02 1.00000E+02 6.80000E+01 3.60000E+01 4.00000E+00 + 1.91000E+02 1.59000E+02 1.27000E+02 9.50000E+01 6.30000E+01 3.10000E+01 + 1.87000E+02 1.55000E+02 1.23000E+02 9.10000E+01 5.90000E+01 2.70000E+01 + 1.83000E+02 1.51000E+02 1.19000E+02 8.70000E+01 5.50000E+01 2.30000E+01 + 1.79000E+02 1.47000E+02 1.15000E+02 8.30000E+01 5.10000E+01 1.90000E+01 + 1.75000E+02 1.43000E+02 1.11000E+02 7.90000E+01 4.70000E+01 1.50000E+01 + 1.71000E+02 1.39000E+02 1.07000E+02 7.50000E+01 4.30000E+01 1.10000E+01 + 1.67000E+02 1.35000E+02 1.03000E+02 7.10000E+01 3.90000E+01 7.00000E+00 + 1.63000E+02 1.31000E+02 9.90000E+01 6.70000E+01 3.50000E+01 3.00000E+00 + 1.90000E+02 1.58000E+02 1.26000E+02 9.40000E+01 6.20000E+01 3.00000E+01 + 1.86000E+02 1.54000E+02 1.22000E+02 9.00000E+01 5.80000E+01 2.60000E+01 + 1.82000E+02 1.50000E+02 1.18000E+02 8.60000E+01 5.40000E+01 2.20000E+01 + 1.78000E+02 1.46000E+02 1.14000E+02 8.20000E+01 5.00000E+01 1.80000E+01 + 1.74000E+02 1.42000E+02 1.10000E+02 7.80000E+01 4.60000E+01 1.40000E+01 + 1.70000E+02 1.38000E+02 1.06000E+02 7.40000E+01 4.20000E+01 1.00000E+01 + 1.66000E+02 1.34000E+02 1.02000E+02 7.00000E+01 3.80000E+01 6.00000E+00 + 1.62000E+02 1.30000E+02 9.80000E+01 6.60000E+01 3.40000E+01 2.00000E+00 + 1.89000E+02 1.57000E+02 1.25000E+02 9.30000E+01 6.10000E+01 2.90000E+01 + 1.85000E+02 1.53000E+02 1.21000E+02 8.90000E+01 5.70000E+01 2.50000E+01 + 1.81000E+02 1.49000E+02 1.17000E+02 8.50000E+01 5.30000E+01 2.10000E+01 + 1.77000E+02 1.45000E+02 1.13000E+02 8.10000E+01 4.90000E+01 1.70000E+01 + 1.73000E+02 1.41000E+02 1.09000E+02 7.70000E+01 4.50000E+01 1.30000E+01 + 1.69000E+02 1.37000E+02 1.05000E+02 7.30000E+01 4.10000E+01 9.00000E+00 + 1.65000E+02 1.33000E+02 1.01000E+02 6.90000E+01 3.70000E+01 5.00000E+00 + 1.61000E+02 1.29000E+02 9.70000E+01 6.50000E+01 3.30000E+01 1.00000E+00 diff --git a/tests/unit_tests/weightwindows/wwinp_t b/tests/unit_tests/weightwindows/wwinp_t index f1aa26d6d..a12668aa4 100644 --- a/tests/unit_tests/weightwindows/wwinp_t +++ b/tests/unit_tests/weightwindows/wwinp_t @@ -15,35 +15,35 @@ 1.00000E+02 -5.00000E+01 1.00000E+00 5.00000E+01 1.00000E+00 1.00000E-01 1.46780E-01 2.15440E-01 3.16230E-01 - 1.92000E+02 1.91000E+02 1.90000E+02 1.89000E+02 1.60000E+02 1.59000E+02 - 1.58000E+02 1.57000E+02 1.28000E+02 1.27000E+02 1.26000E+02 1.25000E+02 - 9.60000E+01 9.50000E+01 9.40000E+01 9.30000E+01 6.40000E+01 6.30000E+01 - 6.20000E+01 6.10000E+01 3.20000E+01 3.10000E+01 3.00000E+01 2.90000E+01 - 1.88000E+02 1.87000E+02 1.86000E+02 1.85000E+02 1.56000E+02 1.55000E+02 - 1.54000E+02 1.53000E+02 1.24000E+02 1.23000E+02 1.22000E+02 1.21000E+02 - 9.20000E+01 9.10000E+01 9.00000E+01 8.90000E+01 6.00000E+01 5.90000E+01 - 5.80000E+01 5.70000E+01 2.80000E+01 2.70000E+01 2.60000E+01 2.50000E+01 - 1.84000E+02 1.83000E+02 1.82000E+02 1.81000E+02 1.52000E+02 1.51000E+02 - 1.50000E+02 1.49000E+02 1.20000E+02 1.19000E+02 1.18000E+02 1.17000E+02 - 8.80000E+01 8.70000E+01 8.60000E+01 8.50000E+01 5.60000E+01 5.50000E+01 - 5.40000E+01 5.30000E+01 2.40000E+01 2.30000E+01 2.20000E+01 2.10000E+01 - 1.80000E+02 1.79000E+02 1.78000E+02 1.77000E+02 1.48000E+02 1.47000E+02 - 1.46000E+02 1.45000E+02 1.16000E+02 1.15000E+02 1.14000E+02 1.13000E+02 - 8.40000E+01 8.30000E+01 8.20000E+01 8.10000E+01 5.20000E+01 5.10000E+01 - 5.00000E+01 4.90000E+01 2.00000E+01 1.90000E+01 1.80000E+01 1.70000E+01 - 1.76000E+02 1.75000E+02 1.74000E+02 1.73000E+02 1.44000E+02 1.43000E+02 - 1.42000E+02 1.41000E+02 1.12000E+02 1.11000E+02 1.10000E+02 1.09000E+02 - 8.00000E+01 7.90000E+01 7.80000E+01 7.70000E+01 4.80000E+01 4.70000E+01 - 4.60000E+01 4.50000E+01 1.60000E+01 1.50000E+01 1.40000E+01 1.30000E+01 - 1.72000E+02 1.71000E+02 1.70000E+02 1.69000E+02 1.40000E+02 1.39000E+02 - 1.38000E+02 1.37000E+02 1.08000E+02 1.07000E+02 1.06000E+02 1.05000E+02 - 7.60000E+01 7.50000E+01 7.40000E+01 7.30000E+01 4.40000E+01 4.30000E+01 - 4.20000E+01 4.10000E+01 1.20000E+01 1.10000E+01 1.00000E+01 9.00000E+00 - 1.68000E+02 1.67000E+02 1.66000E+02 1.65000E+02 1.36000E+02 1.35000E+02 - 1.34000E+02 1.33000E+02 1.04000E+02 1.03000E+02 1.02000E+02 1.01000E+02 - 7.20000E+01 7.10000E+01 7.00000E+01 6.90000E+01 4.00000E+01 3.90000E+01 - 3.80000E+01 3.70000E+01 8.00000E+00 7.00000E+00 6.00000E+00 5.00000E+00 - 1.64000E+02 1.63000E+02 1.62000E+02 1.61000E+02 1.32000E+02 1.31000E+02 - 1.30000E+02 1.29000E+02 1.00000E+02 9.90000E+01 9.80000E+01 9.70000E+01 - 6.80000E+01 6.70000E+01 6.60000E+01 6.50000E+01 3.60000E+01 3.50000E+01 - 3.40000E+01 3.30000E+01 4.00000E+00 3.00000E+00 2.00000E+00 1.00000E+00 + 1.92000E+02 1.60000E+02 1.28000E+02 9.60000E+01 6.40000E+01 3.20000E+01 + 1.88000E+02 1.56000E+02 1.24000E+02 9.20000E+01 6.00000E+01 2.80000E+01 + 1.84000E+02 1.52000E+02 1.20000E+02 8.80000E+01 5.60000E+01 2.40000E+01 + 1.80000E+02 1.48000E+02 1.16000E+02 8.40000E+01 5.20000E+01 2.00000E+01 + 1.76000E+02 1.44000E+02 1.12000E+02 8.00000E+01 4.80000E+01 1.60000E+01 + 1.72000E+02 1.40000E+02 1.08000E+02 7.60000E+01 4.40000E+01 1.20000E+01 + 1.68000E+02 1.36000E+02 1.04000E+02 7.20000E+01 4.00000E+01 8.00000E+00 + 1.64000E+02 1.32000E+02 1.00000E+02 6.80000E+01 3.60000E+01 4.00000E+00 + 1.91000E+02 1.59000E+02 1.27000E+02 9.50000E+01 6.30000E+01 3.10000E+01 + 1.87000E+02 1.55000E+02 1.23000E+02 9.10000E+01 5.90000E+01 2.70000E+01 + 1.83000E+02 1.51000E+02 1.19000E+02 8.70000E+01 5.50000E+01 2.30000E+01 + 1.79000E+02 1.47000E+02 1.15000E+02 8.30000E+01 5.10000E+01 1.90000E+01 + 1.75000E+02 1.43000E+02 1.11000E+02 7.90000E+01 4.70000E+01 1.50000E+01 + 1.71000E+02 1.39000E+02 1.07000E+02 7.50000E+01 4.30000E+01 1.10000E+01 + 1.67000E+02 1.35000E+02 1.03000E+02 7.10000E+01 3.90000E+01 7.00000E+00 + 1.63000E+02 1.31000E+02 9.90000E+01 6.70000E+01 3.50000E+01 3.00000E+00 + 1.90000E+02 1.58000E+02 1.26000E+02 9.40000E+01 6.20000E+01 3.00000E+01 + 1.86000E+02 1.54000E+02 1.22000E+02 9.00000E+01 5.80000E+01 2.60000E+01 + 1.82000E+02 1.50000E+02 1.18000E+02 8.60000E+01 5.40000E+01 2.20000E+01 + 1.78000E+02 1.46000E+02 1.14000E+02 8.20000E+01 5.00000E+01 1.80000E+01 + 1.74000E+02 1.42000E+02 1.10000E+02 7.80000E+01 4.60000E+01 1.40000E+01 + 1.70000E+02 1.38000E+02 1.06000E+02 7.40000E+01 4.20000E+01 1.00000E+01 + 1.66000E+02 1.34000E+02 1.02000E+02 7.00000E+01 3.80000E+01 6.00000E+00 + 1.62000E+02 1.30000E+02 9.80000E+01 6.60000E+01 3.40000E+01 2.00000E+00 + 1.89000E+02 1.57000E+02 1.25000E+02 9.30000E+01 6.10000E+01 2.90000E+01 + 1.85000E+02 1.53000E+02 1.21000E+02 8.90000E+01 5.70000E+01 2.50000E+01 + 1.81000E+02 1.49000E+02 1.17000E+02 8.50000E+01 5.30000E+01 2.10000E+01 + 1.77000E+02 1.45000E+02 1.13000E+02 8.10000E+01 4.90000E+01 1.70000E+01 + 1.73000E+02 1.41000E+02 1.09000E+02 7.70000E+01 4.50000E+01 1.30000E+01 + 1.69000E+02 1.37000E+02 1.05000E+02 7.30000E+01 4.10000E+01 9.00000E+00 + 1.65000E+02 1.33000E+02 1.01000E+02 6.90000E+01 3.70000E+01 5.00000E+00 + 1.61000E+02 1.29000E+02 9.70000E+01 6.50000E+01 3.30000E+01 1.00000E+00 From f9ba64eeb3881f320e9c70e66189f2f011c45a85 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 3 Oct 2022 07:22:26 -0400 Subject: [PATCH 1042/2654] Update tests/unit_tests/weightwindows/test_wwinp_reader.py --- tests/unit_tests/weightwindows/test_wwinp_reader.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index 8d7cd5f7d..434a36753 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -119,7 +119,6 @@ def test_wwinp_reader(wwinp_data, request): # a reversed array of the flat index into the numpy array n_wws = np.prod((*mesh.dimension, e_bounds.size - 1)) exp_ww_lb = np.linspace(1, n_wws, n_wws)[::-1] - np.testing.assert_array_equal(exp_ww_lb, ww.lower_ww_bounds.flatten()) From a32a5fbf0d18bf31eaa79b2d11e2bd11f2e4c4bf Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 3 Oct 2022 16:58:11 +0100 Subject: [PATCH 1043/2654] review suggestion from @RemDelaporteMathurin --- openmc/mesh.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 0dc390ebe..e0d8eb61b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1143,6 +1143,7 @@ class CylindricalMesh(StructuredMesh): domain, dimension=[100, 100, 100], mesh_id=None, + phi_grid=[0.0, 2*pi], name='' ): """Create mesh from an existing openmc cell, region, universe or @@ -1160,6 +1161,9 @@ class CylindricalMesh(StructuredMesh): phi_grid, z_grid) mesh_id : int Unique identifier for the mesh + phi_grid : numpy.ndarray + 1-D array of mesh boundary points along the phi-axis in radians. + The default value is [0, 2π], i.e. the full phi range. name : str Name of the mesh @@ -1188,7 +1192,7 @@ class CylindricalMesh(StructuredMesh): ] ) mesh.r_grid = np.linspace(0, max_bounding_box_radius, num=dimension[0]+1) - mesh.phi_grid = np.linspace(0, 2*np.pi, num=dimension[1]+1) + mesh.phi_grid = np.linspace(phi_grid[0], phi_grid[1], num=dimension[1]+1) mesh.z_grid = np.linspace( cached_bb[0][2], cached_bb[1][2], From 314f3dbbab75104f217d1e20e2146ced28108707 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 4 Oct 2022 10:11:06 +0200 Subject: [PATCH 1044/2654] do not define these functions if no MCPL present --- src/state_point.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index babd670a2..5b00f302d 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -602,6 +602,7 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } +#ifdef OPENMC_MCPL void write_mcpl_point(const char *filename, bool surf_source_bank) { std::string filename_; @@ -639,7 +640,7 @@ void write_mcpl_point(const char *filename, bool surf_source_bank) } } - +#endif void write_source_bank(hid_t group_id, bool surf_source_bank) { @@ -757,6 +758,7 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +#ifdef OPENMC_MCPL void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) { int64_t dims_size = settings::n_particles; @@ -837,7 +839,7 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) } } - +#endif // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) From 90fe5cb79cd8dc8978db0754d34cd66e818e8f05 Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 4 Oct 2022 21:00:17 +0100 Subject: [PATCH 1045/2654] added py3.9 and py3.10 --- .github/workflows/ci.yml | 8 +++++++- setup.py | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 050c8e287..a165998d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,12 @@ jobs: python-version: 3.8 omp: n mpi: y + - python-version: 3.9 + omp: n + mpi: n + - python-version: '3.10' + omp: n + mpi: n name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }}, mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }}, libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }} @@ -78,7 +84,7 @@ jobs: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} diff --git a/setup.py b/setup.py index 477f29dec..43b515934 100755 --- a/setup.py +++ b/setup.py @@ -61,6 +61,7 @@ kwargs = { 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', ], # Dependencies From facc1995e342fbfd8e0c13ff42550beabec5d4fe Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Wed, 5 Oct 2022 09:29:19 +0200 Subject: [PATCH 1046/2654] marks --- openmc/mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index a4c50a608..4059fee2d 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -165,7 +165,7 @@ class StructuredMesh(MeshBase): pass @property - def vertices(self): + def vertices(self): # TODO needs changing """Return coordinates of mesh vertices. Returns @@ -178,7 +178,7 @@ class StructuredMesh(MeshBase): return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) @property - def centroids(self): + def centroids(self): # TODO needs changing """Return coordinates of mesh element centroids. Returns From afbd994d4ff0504bd35722873152813efe907321 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 5 Oct 2022 08:45:59 +0100 Subject: [PATCH 1047/2654] review suggestions from Remi and Paul MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Paul Romano Co-authored-by: Rémi Delaporte-Mathurin <40028739+RemDelaporteMathurin@users.noreply.github.com> --- openmc/mesh.py | 8 ++++---- tests/unit_tests/test_mesh_from_domain.py | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index e0d8eb61b..57fd8fb21 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1141,9 +1141,9 @@ class CylindricalMesh(StructuredMesh): def from_domain( cls, domain, - dimension=[100, 100, 100], + dimension=(100, 100, 100), mesh_id=None, - phi_grid=[0.0, 2*pi], + phi_grid=(0.0, 2*pi), name='' ): """Create mesh from an existing openmc cell, region, universe or @@ -1152,7 +1152,7 @@ class CylindricalMesh(StructuredMesh): Parameters ---------- - domain : {openmc.Cell, openmc.Region, openmc.Universe, openmc.Geometry} + domain : openmc.Cell or openmc.Region or openmc.Universe or openmc.Geometry The object passed in will be used as a template for this mesh. The bounding box of the property of the object passed will be used to set the r_grid, z_grid ranges. @@ -1163,7 +1163,7 @@ class CylindricalMesh(StructuredMesh): Unique identifier for the mesh phi_grid : numpy.ndarray 1-D array of mesh boundary points along the phi-axis in radians. - The default value is [0, 2π], i.e. the full phi range. + The default value is (0, 2π), i.e., the full phi range. name : str Name of the mesh diff --git a/tests/unit_tests/test_mesh_from_domain.py b/tests/unit_tests/test_mesh_from_domain.py index 64b9424b9..cbc32b8fa 100644 --- a/tests/unit_tests/test_mesh_from_domain.py +++ b/tests/unit_tests/test_mesh_from_domain.py @@ -19,9 +19,9 @@ def test_reg_mesh_from_cell(): def test_cylindrical_mesh_from_cell(): """Tests a CylindricalMesh can be made from a Cell and the specified dimensions are propagated through. Cell is not centralized""" - cy_surface = openmc. openmc.ZCylinder(r=50) - z_surface_1 = openmc. openmc.ZPlane(z0=30) - z_surface_2 = openmc. openmc.ZPlane(z0=0) + cy_surface = openmc.ZCylinder(r=50) + z_surface_1 = openmc.ZPlane(z0=30) + z_surface_2 = openmc.ZPlane(z0=0) cell = openmc.Cell(region=-cy_surface & -z_surface_1 & +z_surface_2) mesh = openmc.CylindricalMesh.from_domain(cell, dimension=[2, 4, 3]) @@ -48,9 +48,9 @@ def test_reg_mesh_from_region(): def test_cylindrical_mesh_from_region(): """Tests a CylindricalMesh can be made from a Region and the specified dimensions are propagated through. Cell is centralized""" - cy_surface = openmc. openmc.ZCylinder(r=6) - z_surface_1 = openmc. openmc.ZPlane(z0=30) - z_surface_2 = openmc. openmc.ZPlane(z0=-30) + cy_surface = openmc.ZCylinder(r=6) + z_surface_1 = openmc.ZPlane(z0=30) + z_surface_2 = openmc.ZPlane(z0=-30) cell = openmc.Cell(region=-cy_surface & -z_surface_1 & +z_surface_2) mesh = openmc.CylindricalMesh.from_domain(cell, dimension=[6, 2, 3]) From 9a61aed2efe4bb798f16b9018ad3a8edb003d68e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 5 Oct 2022 09:03:30 +0100 Subject: [PATCH 1048/2654] doc string related review suggestions --- openmc/mesh.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 57fd8fb21..d4db5011b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -514,7 +514,7 @@ class RegularMesh(StructuredMesh): def from_domain( cls, domain, - dimension=[100, 100, 100], + dimension=(10, 10, 10), mesh_id=None, name='' ): @@ -1141,14 +1141,12 @@ class CylindricalMesh(StructuredMesh): def from_domain( cls, domain, - dimension=(100, 100, 100), + dimension=(10, 10, 10), mesh_id=None, - phi_grid=(0.0, 2*pi), + phi_grid_bounds=(0.0, 2*pi), name='' ): - """Create mesh from an existing openmc cell, region, universe or - geometry by making use of the objects bounding box property. phi_grid - is set to have a range of 0 to 2π by default. + """Creates a regular CylindricalMesh from an existing openmc domain. Parameters ---------- @@ -1161,9 +1159,9 @@ class CylindricalMesh(StructuredMesh): phi_grid, z_grid) mesh_id : int Unique identifier for the mesh - phi_grid : numpy.ndarray - 1-D array of mesh boundary points along the phi-axis in radians. - The default value is (0, 2π), i.e., the full phi range. + phi_grid_bounds : numpy.ndarray + Mesh bounds points along the phi-axis in radians. The default value + is (0, 2π), i.e., the full phi range. name : str Name of the mesh @@ -1191,8 +1189,16 @@ class CylindricalMesh(StructuredMesh): cached_bb[1][1], ] ) - mesh.r_grid = np.linspace(0, max_bounding_box_radius, num=dimension[0]+1) - mesh.phi_grid = np.linspace(phi_grid[0], phi_grid[1], num=dimension[1]+1) + mesh.r_grid = np.linspace( + 0, + max_bounding_box_radius, + num=dimension[0]+1 + ) + mesh.phi_grid = np.linspace( + phi_grid_bounds[0], + phi_grid_bounds[1], + num=dimension[1]+1 + ) mesh.z_grid = np.linspace( cached_bb[0][2], cached_bb[1][2], From 2de20231ad584fa7a77a5b135c82f6e995671bcc Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:56:36 +0200 Subject: [PATCH 1049/2654] use find_package instead - MCPL now supports this --- CMakeLists.txt | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be56f1c12..98dc4fcaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,13 @@ if(${HDF5_VERSION} VERSION_GREATER_EQUAL 1.12.0) list(APPEND cxxflags -DH5Oget_info_by_idx_vers=1 -DH5O_info_t_vers=1) endif() +#=============================================================================== +# MCPL +#=============================================================================== +if (OPENMC_USE_MCPL) + find_package(MCPL REQUIRED) +endif() + #=============================================================================== # Set compile/link flags based on which compiler is being used #=============================================================================== @@ -155,10 +162,6 @@ if(OPENMC_ENABLE_COVERAGE) list(APPEND ldflags --coverage) endif() -if(OPENMC_USE_MCPL) - list(APPEND ldflags -lmcpl) -endif() - # Show flags being used message(STATUS "OpenMC C++ flags: ${cxxflags}") message(STATUS "OpenMC Linker flags: ${ldflags}") @@ -413,10 +416,6 @@ endif() if (OPENMC_USE_MPI) target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) endif() -if(OPENMC_USE_MCPL) - target_compile_definitions(libopenmc PUBLIC -DOPENMC_MCPL) -endif() - # Set git SHA1 hash as a compile definition if(GIT_FOUND) @@ -460,6 +459,11 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() +if (OPENMC_USE_MCPL) + target_compile_definitions(libopenmc PUBLIC OPENMC_MCPL) + target_link_libraries(libopenmc MCPL::mcpl) +endif() + #=============================================================================== # openmc executable #=============================================================================== From 7418cb99dd7c22e80532dcc46a9d2c4c04ceb63d Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:59:02 +0200 Subject: [PATCH 1050/2654] add mcpl-output settings --- include/openmc/settings.h | 1 + src/settings.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 1e061b235..66825867d 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -48,6 +48,7 @@ extern bool source_latest; //!< write latest source at each batch? extern bool source_separate; //!< write source to separate file? extern bool source_write; //!< write source in HDF5 files? extern bool surf_source_write; //!< write surface source file? +extern bool surf_mcpl_write; //!< write surface mcpl file? extern bool surf_source_read; //!< read surface source file? extern bool survival_biasing; //!< use survival biasing? extern bool temperature_multipole; //!< use multipole data? diff --git a/src/settings.cpp b/src/settings.cpp index 11dd96e02..d1762596c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -61,6 +61,7 @@ bool source_latest {false}; bool source_separate {false}; bool source_write {true}; bool surf_source_write {false}; +bool surf_mcpl_write {false}; bool surf_source_read {false}; bool survival_biasing {false}; bool temperature_multipole {false}; @@ -682,9 +683,14 @@ void read_settings_xml() max_surface_particles = std::stoll(get_node_value(node_ssw, "max_particles")); } +#ifdef OPENMC_MCPL + if(check_for_node(node_ssw, "mcpl")){ + surf_mcpl_write=true; + } +#endif } - // If source is not seperate and is to be written out in the statepoint file, + // If source is not separate and is to be written out in the statepoint file, // make sure that the sourcepoint batch numbers are contained in the // statepoint list if (!source_separate) { From 172c518f0e161d0176385c67d3717ad9fb229038 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:59:28 +0200 Subject: [PATCH 1051/2654] fix typo --- src/simulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 05c8c0450..353ef9926 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -409,7 +409,7 @@ void finalize_batch() if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ auto filename = settings::path_output + ".mcpl"; - write_mcplt_source_point(filename.c_str(), true); + write_mcpl_source_point(filename.c_str(), true); } From 83e2921034f5c448d500b93634999cdb3f350e0b Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 11:00:39 +0200 Subject: [PATCH 1052/2654] add cond. compilation guards for MCPL functions --- src/state_point.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index babd670a2..7c1a45447 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -602,7 +602,8 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } -void write_mcpl_point(const char *filename, bool surf_source_bank) +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename, bool surf_source_bank) { std::string filename_; if (filename) { @@ -639,7 +640,7 @@ void write_mcpl_point(const char *filename, bool surf_source_bank) } } - +#endif void write_source_bank(hid_t group_id, bool surf_source_bank) { @@ -757,6 +758,7 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +#ifdef OPENMC_MCPL void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) { int64_t dims_size = settings::n_particles; @@ -837,7 +839,7 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) } } - +#endif // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) From 5e82bb2e1f1b2857375566f98669be6c93b22638 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 09:12:01 +0200 Subject: [PATCH 1053/2654] expose a python function to check for mcpl --- openmc/lib/__init__.py | 3 +++ src/source.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/openmc/lib/__init__.py b/openmc/lib/__init__.py index c14b0d9c2..1e337fc07 100644 --- a/openmc/lib/__init__.py +++ b/openmc/lib/__init__.py @@ -48,6 +48,9 @@ def _coord_levels(): def _libmesh_enabled(): return c_bool.in_dll(_dll, "LIBMESH_ENABLED").value +def _mcpl_enabled(): + return c_bool.in_dll(_dll, "MCPL_ENABLED").value + from .error import * from .core import * from .nuclide import * diff --git a/src/source.cpp b/src/source.cpp index 49e51c4b1..eace931d6 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -41,6 +41,12 @@ namespace openmc { // Global variables //============================================================================== +#ifdef OPENMC_MCPL +const bool MCPL_ENABLED = true; +#else +const bool MCPL_ENABLED = false; +#endif + namespace model { vector> external_sources; From 6038555def28547a0f392f0eeded8d8d49269d51 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 1054/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- include/openmc/state_point.h | 9 +++ src/state_point.cpp | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 5ada2bf88..2d92c935a 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -9,6 +9,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { void load_state_point(); @@ -21,5 +25,10 @@ void write_tally_results_nr(hid_t file_id); void restart_set_keff(); void write_unstructured_mesh_results(); +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename_, bool surf_source_bank = false); +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); +#endif + } // namespace openmc #endif // OPENMC_STATE_POINT_H diff --git a/src/state_point.cpp b/src/state_point.cpp index 9ea045915..babd670a2 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -28,6 +28,10 @@ #include "openmc/timer.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) @@ -598,6 +602,45 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } +void write_mcpl_point(const char *filename, bool surf_source_bank) +{ + std::string filename_; + if (filename) { + filename_ = filename; + } else { + // Determine width for zero padding + int w = std::to_string(settings::n_max_batches).size(); + + filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, + simulation::current_batch, w); + } + + mcpl_outfile_t file_id; + + std::string line; + if (mpi::master) { + // this must be rewritten: file_open is h5-specific + file_id = mcpl_create_outfile(filename_.c_str()); + //write_attribute(file_id, "filetype", "source"); + //write header stuff (oopy in xml-files as binary blobs for instance)) + if (VERSION_DEV){ + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}-development"); + } else { + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}"); + } + mcpl_hdr_set_srcname(file_id,line.c_str()); + } + + write_mcpl_source_bank(file_id, surf_source_bank); + + if (mpi::master) { + //change this - this is h5 specific + mcpl_closeandgzip_outfile(file_id); + } + +} + + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); @@ -714,6 +757,88 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) +{ + int64_t dims_size = settings::n_particles; + int64_t count_size = simulation::work_per_rank; + + // Set vectors for source bank and starting bank index of each process + vector* bank_index = &simulation::work_index; + vector* source_bank = &simulation::source_bank; + vector surf_source_index_vector; + vector surf_source_bank_vector; + + if(surf_source_bank) { + surf_source_index_vector = calculate_surf_source_size(); + dims_size = surf_source_index_vector[mpi::n_procs]; + count_size = simulation::surf_source_bank.size(); + + bank_index = &surf_source_index_vector; + + // Copy data in a SharedArray into a vector. + surf_source_bank_vector.resize(count_size); + surf_source_bank_vector.assign(simulation::surf_source_bank.data(), + simulation::surf_source_bank.data() + count_size); + source_bank = &surf_source_bank_vector; + } + + if (mpi::master) { + //write particles from the master node + //loop over the other nodes and receive data - then write those. + for (int i = 0; i < mpi::n_procs; ++i) { +#ifdef OPENMC_MPI + if (i>0) + MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + mpi::intracomm, MPI_STATUS_IGNORE); +#endif + //now write the source_banke data again. + for (vector::iterator _site=source_bank->begin(); _site!=source_bank->end();_site++){ + //particle is now at the iterator + //write it to the mcpl-file + mcpl_particle_t p; + p.position[0]=_site->r.x; + p.position[1]=_site->r.y; + p.position[2]=_site->r.z; + + p.direction[0]=_site->u.x; + p.direction[1]=_site->u.y; + p.direction[2]=_site->u.x; + + //mcpl stores kinetic energy in MeV + p.ekin=_site->E*1e-6; + + p.time=_site->time*1e3; + + p.weight=_site->wgt; + + switch(_site->particle){ + case ParticleType::neutron: + p.pdgcode=2112; + break; + case ParticleType::photon: + p.pdgcode=22; + break; + case ParticleType::electron: + p.pdgcode=11; + break; + case ParticleType::positron: + p.pdgcode=-11; + break; + } + + mcpl_add_particle(file_id,&p); + } + } + } else { +#ifdef OPENMC_MPI + MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + mpi::intracomm); +#endif + } + +} + + // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) { From 2ba7f8d1882cf5e2562b473e233b4ca84ab81080 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 23:06:19 +0200 Subject: [PATCH 1055/2654] add a trigger to simulation control --- src/simulation.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/simulation.cpp b/src/simulation.cpp index b70535c33..05c8c0450 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -406,6 +406,13 @@ void finalize_batch() auto filename = settings::path_output + "surface_source.h5"; write_source_point(filename.c_str(), true); } + + if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + auto filename = settings::path_output + ".mcpl"; + write_mcplt_source_point(filename.c_str(), true); + } + + } void initialize_generation() From 91cd304f0e4fd32eb6df0bdb75dd3f7d169013ce Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:56:36 +0200 Subject: [PATCH 1056/2654] use find_package instead - MCPL now supports this --- CMakeLists.txt | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be56f1c12..98dc4fcaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,13 @@ if(${HDF5_VERSION} VERSION_GREATER_EQUAL 1.12.0) list(APPEND cxxflags -DH5Oget_info_by_idx_vers=1 -DH5O_info_t_vers=1) endif() +#=============================================================================== +# MCPL +#=============================================================================== +if (OPENMC_USE_MCPL) + find_package(MCPL REQUIRED) +endif() + #=============================================================================== # Set compile/link flags based on which compiler is being used #=============================================================================== @@ -155,10 +162,6 @@ if(OPENMC_ENABLE_COVERAGE) list(APPEND ldflags --coverage) endif() -if(OPENMC_USE_MCPL) - list(APPEND ldflags -lmcpl) -endif() - # Show flags being used message(STATUS "OpenMC C++ flags: ${cxxflags}") message(STATUS "OpenMC Linker flags: ${ldflags}") @@ -413,10 +416,6 @@ endif() if (OPENMC_USE_MPI) target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) endif() -if(OPENMC_USE_MCPL) - target_compile_definitions(libopenmc PUBLIC -DOPENMC_MCPL) -endif() - # Set git SHA1 hash as a compile definition if(GIT_FOUND) @@ -460,6 +459,11 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() +if (OPENMC_USE_MCPL) + target_compile_definitions(libopenmc PUBLIC OPENMC_MCPL) + target_link_libraries(libopenmc MCPL::mcpl) +endif() + #=============================================================================== # openmc executable #=============================================================================== From 9b58c2f6dc93c4c51ce6ee7a26e7ffc645434020 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:59:02 +0200 Subject: [PATCH 1057/2654] add mcpl-output settings --- include/openmc/settings.h | 1 + src/settings.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 1e061b235..66825867d 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -48,6 +48,7 @@ extern bool source_latest; //!< write latest source at each batch? extern bool source_separate; //!< write source to separate file? extern bool source_write; //!< write source in HDF5 files? extern bool surf_source_write; //!< write surface source file? +extern bool surf_mcpl_write; //!< write surface mcpl file? extern bool surf_source_read; //!< read surface source file? extern bool survival_biasing; //!< use survival biasing? extern bool temperature_multipole; //!< use multipole data? diff --git a/src/settings.cpp b/src/settings.cpp index 11dd96e02..d1762596c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -61,6 +61,7 @@ bool source_latest {false}; bool source_separate {false}; bool source_write {true}; bool surf_source_write {false}; +bool surf_mcpl_write {false}; bool surf_source_read {false}; bool survival_biasing {false}; bool temperature_multipole {false}; @@ -682,9 +683,14 @@ void read_settings_xml() max_surface_particles = std::stoll(get_node_value(node_ssw, "max_particles")); } +#ifdef OPENMC_MCPL + if(check_for_node(node_ssw, "mcpl")){ + surf_mcpl_write=true; + } +#endif } - // If source is not seperate and is to be written out in the statepoint file, + // If source is not separate and is to be written out in the statepoint file, // make sure that the sourcepoint batch numbers are contained in the // statepoint list if (!source_separate) { From 43538ac2021f36caf0d72e002a119a806aa14b71 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:59:28 +0200 Subject: [PATCH 1058/2654] fix typo --- src/simulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 05c8c0450..353ef9926 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -409,7 +409,7 @@ void finalize_batch() if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ auto filename = settings::path_output + ".mcpl"; - write_mcplt_source_point(filename.c_str(), true); + write_mcpl_source_point(filename.c_str(), true); } From cba745b28b6e384311393c177456b518b60b4f55 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 11:00:39 +0200 Subject: [PATCH 1059/2654] add cond. compilation guards for MCPL functions --- src/state_point.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index babd670a2..7c1a45447 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -602,7 +602,8 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } -void write_mcpl_point(const char *filename, bool surf_source_bank) +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename, bool surf_source_bank) { std::string filename_; if (filename) { @@ -639,7 +640,7 @@ void write_mcpl_point(const char *filename, bool surf_source_bank) } } - +#endif void write_source_bank(hid_t group_id, bool surf_source_bank) { @@ -757,6 +758,7 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +#ifdef OPENMC_MCPL void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) { int64_t dims_size = settings::n_particles; @@ -837,7 +839,7 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) } } - +#endif // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) From 179df586853b65600518a0ea62526cc2193e0206 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 16 Sep 2022 16:07:22 +0200 Subject: [PATCH 1060/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- src/source.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/source.cpp b/src/source.cpp index eace931d6..bd76969d1 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -391,6 +391,79 @@ CustomSourceWrapper::~CustomSourceWrapper() } +MCPLFileSource::~MCPLFileSource(){ + mcpl_close_file(mcpl_file); +} + +SourceSite MCPLFileSource::sample(uint64_t* seed) const +{ + size_t i_site = sites_.size() * prn(seed); + return sites_[i_site]; +} + +void MCPLFileSource::read_source_bank(vector &sites_) +{ + sites_.resize(n_sites); + for (int i=0;ipdgcode; + while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { + mcpl_particle=mcpl_read(mcpl_file); + pdg=mcpl_particle->pdgcode; + //should check for file exhaustion. This could happen if particles are other than + //neutrons, photons, electrons, or positrons. + } + + switch(pdg){ + case 2112: + omc_particle_.particle=ParticleType::neutron; + break; + case 22: + omc_particle_.particle=ParticleType::photon; + break; + case 11: + omc_particle_.particle=ParticleType::electron; + break; + case -11: + omc_particle_.particle=ParticleType::positron; + break; + } + + //particle is good, convert to openmc-formalism + omc_particle_.r.x=mcpl_particle->position[0]; + omc_particle_.r.y=mcpl_particle->position[1]; + omc_particle_.r.z=mcpl_particle->position[2]; + + omc_particle_.u.x=mcpl_particle->direction[0]; + omc_particle_.u.y=mcpl_particle->direction[1]; + omc_particle_.u.z=mcpl_particle->direction[2]; + + //mcpl stores kinetic energy in MeV + omc_particle_.E=mcpl_particle->ekin*1e6; + //mcpl stores time in ms + omc_particle_.time=mcpl_particle->time*1e-3; + omc_particle_.wgt=mcpl_particle->weight; + omc_particle_.delayed_group=0; + return omc_particle_; +} +#endif //OPENMC_MCPL +======= +>>>>>>> 380cfc150b449ef56debb5261caa010a52c42bdd +======= +#endif +>>>>>>> 71568d4f4 (refactor MCPL file read part of FileSource) +>>>>>>> 55f2be19e (refactor MCPL file read part of FileSource) + //============================================================================== // Non-member functions //============================================================================== From e3fbeac636c2e9a47599c60e04b2a1ba4d9ba46d Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 1061/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- src/source.cpp | 6 ------ src/state_point.cpp | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index bd76969d1..f205a0a25 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -457,12 +457,6 @@ SourceSite MCPLFileSource::read_single_particle() const return omc_particle_; } #endif //OPENMC_MCPL -======= ->>>>>>> 380cfc150b449ef56debb5261caa010a52c42bdd -======= -#endif ->>>>>>> 71568d4f4 (refactor MCPL file read part of FileSource) ->>>>>>> 55f2be19e (refactor MCPL file read part of FileSource) //============================================================================== // Non-member functions diff --git a/src/state_point.cpp b/src/state_point.cpp index 7c1a45447..31979c0c5 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -642,6 +642,7 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) } #endif + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); From 3b7c4f6d2f141311cba5ad9e5f773b3bc3381852 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 4 Oct 2022 10:11:06 +0200 Subject: [PATCH 1062/2654] do not define these functions if no MCPL present --- src/state_point.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 31979c0c5..7c1a45447 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -642,7 +642,6 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) } #endif - void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); From 6a9a1ad2937b40c7a23fc16086518b2f99bac297 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 5 Oct 2022 11:46:00 +0100 Subject: [PATCH 1063/2654] added phi_grid_bounds to CylindricalMesh tests --- tests/unit_tests/test_mesh_from_domain.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/unit_tests/test_mesh_from_domain.py b/tests/unit_tests/test_mesh_from_domain.py index cbc32b8fa..b4edae196 100644 --- a/tests/unit_tests/test_mesh_from_domain.py +++ b/tests/unit_tests/test_mesh_from_domain.py @@ -40,24 +40,28 @@ def test_reg_mesh_from_region(): mesh = openmc.RegularMesh.from_domain(region) assert isinstance(mesh, openmc.RegularMesh) - assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values + assert np.array_equal(mesh.dimension, (10, 10, 10)) # default values assert np.array_equal(mesh.lower_left, region.bounding_box[0]) assert np.array_equal(mesh.upper_right, region.bounding_box[1]) def test_cylindrical_mesh_from_region(): """Tests a CylindricalMesh can be made from a Region and the specified - dimensions are propagated through. Cell is centralized""" + dimensions and phi_grid_bounds are propagated through. Cell is centralized""" cy_surface = openmc.ZCylinder(r=6) z_surface_1 = openmc.ZPlane(z0=30) z_surface_2 = openmc.ZPlane(z0=-30) cell = openmc.Cell(region=-cy_surface & -z_surface_1 & +z_surface_2) - mesh = openmc.CylindricalMesh.from_domain(cell, dimension=[6, 2, 3]) + mesh = openmc.CylindricalMesh.from_domain( + cell, + dimension=(6, 2, 3), + phi_grid_bounds=(0., np.pi) + ) assert isinstance(mesh, openmc.CylindricalMesh) assert np.array_equal(mesh.dimension, (6, 2, 3)) assert np.array_equal(mesh.r_grid, [0., 1., 2., 3., 4., 5., 6.]) - assert np.array_equal(mesh.phi_grid, [0., np.pi, 2.*np.pi]) + assert np.array_equal(mesh.phi_grid, [0., 0.5*np.pi, np.pi]) assert np.array_equal(mesh.z_grid, [-30., -10., 10., 30.]) @@ -70,7 +74,7 @@ def test_reg_mesh_from_universe(): mesh = openmc.RegularMesh.from_domain(universe) assert isinstance(mesh, openmc.RegularMesh) - assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values + assert np.array_equal(mesh.dimension, (10, 10, 10)) # default values assert np.array_equal(mesh.lower_left, universe.bounding_box[0]) assert np.array_equal(mesh.upper_right, universe.bounding_box[1]) @@ -85,7 +89,7 @@ def test_reg_mesh_from_geometry(): mesh = openmc.RegularMesh.from_domain(geometry) assert isinstance(mesh, openmc.RegularMesh) - assert np.array_equal(mesh.dimension, (100, 100, 100)) # default values + assert np.array_equal(mesh.dimension, (10, 10, 10)) # default values assert np.array_equal(mesh.lower_left, geometry.bounding_box[0]) assert np.array_equal(mesh.upper_right, geometry.bounding_box[1]) From 982377b0cdfc573469aad799852a0f2dd50b2e68 Mon Sep 17 00:00:00 2001 From: erkn Date: Wed, 5 Oct 2022 14:31:05 +0200 Subject: [PATCH 1064/2654] fix misnamed variable and remove accientally committed code --- src/source.cpp | 169 ++----------------------------------------------- 1 file changed, 4 insertions(+), 165 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index e1891c5e9..e35734747 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -308,16 +308,16 @@ FileSource::FileSource(mcpl_file_t mcpl_file) switch(pdg){ case 2112: - omc_particle_.particle=ParticleType::neutron; + site_.particle=ParticleType::neutron; break; case 22: - omc_particle_.particle=ParticleType::photon; + site_.particle=ParticleType::photon; break; case 11: - omc_particle_.particle=ParticleType::electron; + site_.particle=ParticleType::electron; break; case -11: - omc_particle_.particle=ParticleType::positron; + site_.particle=ParticleType::positron; break; } @@ -401,167 +401,6 @@ CustomSourceWrapper::~CustomSourceWrapper() #endif } -<<<<<<< HEAD -<<<<<<< HEAD -#ifdef OPENMC_MCPL -//=========================================================================== -// Read particles from an MCPL-file -//=========================================================================== -MCPLFileSource::MCPLFileSource(std::string path) -{ - // Check if source file exists - if (!file_exists(path)) { - fatal_error(fmt::format("Source file '{}' does not exist.", path)); - } - - // Read the source from a binary file instead of sampling from some - // assumed source distribution - write_message(6, "Reading mcpl source file from {}",path); - - // Open the mcpl file - mcpl_file = mcpl_open_file(path.c_str()); - - //do checks on the mcpl_file to see if particles are many enough. - // should model this on the example source shown in the docs. - n_sites=mcpl_hdr_nparticles(mcpl_file); - - read_source_bank(sites_); -} -<<<<<<< HEAD - -MCPLFileSource::~MCPLFileSource(){ - mcpl_close_file(mcpl_file); -} - -SourceSite MCPLFileSource::sample(uint64_t* seed) const -{ - size_t i_site = sites_.size() * prn(seed); - return sites_[i_site]; -} - -void MCPLFileSource::read_source_bank(vector &sites_) -{ - sites_.resize(n_sites); - for (int i=0;ipdgcode; - while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { - mcpl_particle=mcpl_read(mcpl_file); - pdg=mcpl_particle->pdgcode; - //should check for file exhaustion. This could happen if particles are other than - //neutrons, photons, electrons, or positrons. - } - - switch(pdg){ - case 2112: - omc_particle_.particle=ParticleType::neutron; - break; - case 22: - omc_particle_.particle=ParticleType::photon; - break; - case 11: - omc_particle_.particle=ParticleType::electron; - break; - case -11: - omc_particle_.particle=ParticleType::positron; - break; - } - - //particle is good, convert to openmc-formalism - omc_particle_.r.x=mcpl_particle->position[0]; - omc_particle_.r.y=mcpl_particle->position[1]; - omc_particle_.r.z=mcpl_particle->position[2]; - - omc_particle_.u.x=mcpl_particle->direction[0]; - omc_particle_.u.y=mcpl_particle->direction[1]; - omc_particle_.u.z=mcpl_particle->direction[2]; - - //mcpl stores kinetic energy in MeV - omc_particle_.E=mcpl_particle->ekin*1e6; - //mcpl stores time in ms - omc_particle_.time=mcpl_particle->time*1e-3; - omc_particle_.wgt=mcpl_particle->weight; - omc_particle_.delayed_group=0; - return omc_particle_; -} -#endif //OPENMC_MCPL - -MCPLFileSource::~MCPLFileSource(){ - mcpl_close_file(mcpl_file); -} - -SourceSite MCPLFileSource::sample(uint64_t* seed) const -{ - size_t i_site = sites_.size() * prn(seed); - return sites_[i_site]; -} - -void MCPLFileSource::read_source_bank(vector &sites_) -{ - sites_.resize(n_sites); - for (int i=0;ipdgcode; - while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { - mcpl_particle=mcpl_read(mcpl_file); - pdg=mcpl_particle->pdgcode; - //should check for file exhaustion. This could happen if particles are other than - //neutrons, photons, electrons, or positrons. - } - - switch(pdg){ - case 2112: - omc_particle_.particle=ParticleType::neutron; - break; - case 22: - omc_particle_.particle=ParticleType::photon; - break; - case 11: - omc_particle_.particle=ParticleType::electron; - break; - case -11: - omc_particle_.particle=ParticleType::positron; - break; - } - - //particle is good, convert to openmc-formalism - omc_particle_.r.x=mcpl_particle->position[0]; - omc_particle_.r.y=mcpl_particle->position[1]; - omc_particle_.r.z=mcpl_particle->position[2]; - - omc_particle_.u.x=mcpl_particle->direction[0]; - omc_particle_.u.y=mcpl_particle->direction[1]; - omc_particle_.u.z=mcpl_particle->direction[2]; - - //mcpl stores kinetic energy in MeV - omc_particle_.E=mcpl_particle->ekin*1e6; - //mcpl stores time in ms - omc_particle_.time=mcpl_particle->time*1e-3; - omc_particle_.wgt=mcpl_particle->weight; - omc_particle_.delayed_group=0; - return omc_particle_; -} -#endif //OPENMC_MCPL //============================================================================== // Non-member functions From 004199c49d43031e9737f0f70b5b9ae66626c654 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 5 Oct 2022 09:08:02 -0500 Subject: [PATCH 1065/2654] Handle possibility of .ppm file in Universe.plot --- openmc/plots.py | 4 +++- openmc/universe.py | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/openmc/plots.py b/openmc/plots.py index b22ee9125..2708683b1 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -171,7 +171,9 @@ def _get_plot_image(plot, cwd): stem = plot.filename if plot.filename is not None else f'plot_{plot.id}' png_file = Path(cwd) / f'{stem}.png' if not png_file.exists(): - raise FileNotFoundError(f"Could not find .png image for plot {plot.id}") + raise FileNotFoundError( + f"Could not find .png image for plot {plot.id}. Your version of " + "OpenMC may not be built against libpng.") return Image(str(png_file)) diff --git a/openmc/universe.py b/openmc/universe.py index 0c8a26a48..db828e33c 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -358,7 +358,10 @@ class Universe(UniverseBase): model.plot_geometry(False, cwd=tmpdir, openmc_exec=openmc_exec) # Read image from file - img = mpimg.imread(Path(tmpdir) / f'plot_{plot.id}.png') + img_path = Path(tmpdir) / f'plot_{plot.id}.png' + if not img_path.is_file(): + img_path = img_path.with_suffix('.ppm') + img = mpimg.imread(img_path) # Create a figure sized such that the size of the axes within # exactly matches the number of pixels specified From fe04a839c289acc094ef97dd111eb65d2c4836ae Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 5 Oct 2022 14:28:18 -0500 Subject: [PATCH 1066/2654] Make sure Material.decay_photon_energy works with no unstable nuclides --- openmc/data/decay.py | 12 ++++++------ openmc/material.py | 11 ++++++----- tests/unit_tests/test_material.py | 6 ++++++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index d7ededf33..801ef4410 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -1,10 +1,9 @@ from collections.abc import Iterable from io import StringIO from math import log -from pathlib import Path import re +from typing import Optional from warnings import warn -from xml.etree import ElementTree as ET import numpy as np from uncertainties import ufloat, UFloat @@ -579,7 +578,7 @@ class Decay(EqualityMixin): _DECAY_PHOTON_ENERGY = {} -def decay_photon_energy(nuclide: str) -> Univariate: +def decay_photon_energy(nuclide: str) -> Optional[Univariate]: """Get photon energy distribution resulting from the decay of a nuclide This function relies on data stored in a depletion chain. Before calling it @@ -595,9 +594,10 @@ def decay_photon_energy(nuclide: str) -> Univariate: Returns ------- - openmc.stats.Univariate - Distribution of energies in [eV] of photons emitted from decay. Note - that the probabilities represent intensities, given as [decay/sec]. + openmc.stats.Univariate or None + Distribution of energies in [eV] of photons emitted from decay, or None + if no photon source exists. Note that the probabilities represent + intensities, given as [decay/sec]. """ if not _DECAY_PHOTON_ENERGY: chain_file = openmc.config.get('chain_file') diff --git a/openmc/material.py b/openmc/material.py index 16b5a3048..e99eec52c 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -92,10 +92,11 @@ class Material(IDManagerMixin): fissionable_mass : float Mass of fissionable nuclides in the material in [g]. Requires that the :attr:`volume` attribute is set. - decay_photon_energy : openmc.stats.Univariate + decay_photon_energy : openmc.stats.Univariate or None Energy distribution of photons emitted from decay of unstable nuclides - within the material. The integral of this distribution is the total - intensity of the photon source in [decay/sec]. + within the material, or None if no photon source exists. The integral of + this distribution is the total intensity of the photon source in + [decay/sec]. .. versionadded:: 0.14.0 @@ -264,7 +265,7 @@ class Material(IDManagerMixin): return density*self.volume @property - def decay_photon_energy(self) -> Univariate: + def decay_photon_energy(self) -> Optional[Univariate]: atoms = self.get_nuclide_atoms() dists = [] probs = [] @@ -273,7 +274,7 @@ class Material(IDManagerMixin): if source_per_atom is not None: dists.append(source_per_atom) probs.append(num_atoms) - return openmc.data.combine_distributions(dists, probs) + return openmc.data.combine_distributions(dists, probs) if dists else None @classmethod def from_hdf5(cls, group: h5py.Group): diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 58df246dd..80935d68d 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -573,3 +573,9 @@ def test_decay_photon_energy(): assert src.integral() == pytest.approx(sum( intensity(decay_photon_energy(nuc)) for nuc in m.get_nuclides() )) + + # A material with no unstable nuclides should have no decay photon source + stable = openmc.Material() + stable.add_nuclide('Gd156', 1.0) + stable.volume = 1.0 + assert stable.decay_photon_energy is None From 5582180e31668e76115ad6cdcaba6b38fa0210f6 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Wed, 5 Oct 2022 17:45:51 -0400 Subject: [PATCH 1067/2654] Can now print build info --- CMakeLists.txt | 13 ++++++++++ include/openmc/output.h | 3 +++ src/initialize.cpp | 4 +++ src/output.cpp | 56 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 521b46cfc..ad1478de8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -482,6 +482,19 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() +#=============================================================================== +# Log build info that this executable can report later +#=============================================================================== +target_compile_definitions(libopenmc PRIVATE BUILD_TYPE=${CMAKE_BUILD_TYPE}) +target_compile_definitions(libopenmc PRIVATE COMPILER_ID=${CMAKE_CXX_COMPILER_ID}) +target_compile_definitions(libopenmc PRIVATE COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}) +if (OPENMC_ENABLE_PROFILE) + target_compile_definitions(libopenmc PRIVATE PROFILINGBUILD) +endif() +if (OPENMC_ENABLE_COVERAGE) + target_compile_definitions(libopenmc PRIVATE COVERAGEBUILD) +endif() + #=============================================================================== # openmc executable #=============================================================================== diff --git a/include/openmc/output.h b/include/openmc/output.h index 2ebe2711f..cf5b49607 100644 --- a/include/openmc/output.h +++ b/include/openmc/output.h @@ -40,6 +40,9 @@ void print_usage(); //! Display current version and copright/license information void print_version(); +//! Display compile flags employed, etc +void print_build_info(); + //! Display header listing what physical values will displayed void print_columns(); diff --git a/src/initialize.cpp b/src/initialize.cpp index 9c20a1f3c..e2503bc6e 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -262,6 +262,10 @@ int parse_command_line(int argc, char* argv[]) print_version(); return OPENMC_E_UNASSIGNED; + } else if (arg == "-b" || arg == "--build-info") { + print_build_info(); + return OPENMC_E_UNASSIGNED; + } else if (arg == "-t" || arg == "--track") { settings::write_all_tracks = true; diff --git a/src/output.cpp b/src/output.cpp index 56fea4db9..5daf652dc 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -325,6 +325,7 @@ void print_usage() "max_tracks)\n" " -e, --event Run using event-based parallelism\n" " -v, --version Show version information\n" + " -b, --build-info Show compile options\n" " -h, --help Show this message\n"); } } @@ -347,6 +348,61 @@ void print_version() //============================================================================== +void print_build_info() +{ + const std::string n("no"); + const std::string y("yes"); + + std::string mpi(n); + std::string phdf5(n); + std::string dagmc(n); + std::string libmesh(n); + std::string png(n); + std::string profiling(n); + std::string coverage(n); + +#ifdef PHDF5 + phdf5 = y; +#endif +#ifdef OPENMC_MPI + mpi = y; +#endif +#ifdef DAGMC + dagmc = y; +#endif +#ifdef LIBMESH + libmesh = y; +#endif +#ifdef USE_LIBPNG + png = y; +#endif +#ifdef PROFILINGBUILD + profiling = y; +#endif +#ifdef COVERAGEBUILD + coverage = y; +#endif + + // Wraps macro variables in quotes +#define STRINGIFY(x) STRINGIFY2(x) +#define STRINGIFY2(x) #x + + if (mpi::master) { + fmt::print("Build type: {}\n", STRINGIFY(BUILD_TYPE)); + fmt::print("Compiler ID: {} {}\n", STRINGIFY(COMPILER_ID), + STRINGIFY(COMPILER_VERSION)); + fmt::print("MPI enabled: {}\n", mpi); + fmt::print("Parallel HDF5 enabled: {}\n", phdf5); + fmt::print("PNG support: {}\n", png); + fmt::print("DAGMC support: {}\n", dagmc); + fmt::print("libMesh support: {}\n", libmesh); + fmt::print("Coverage testing: {}\n", coverage); + fmt::print("Profiling flags: {}\n", profiling); + } +} + +//============================================================================== + void print_columns() { if (settings::entropy_on) { From 12f088a5ce68c639c9772574eb69c4be5de452fe Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 6 Oct 2022 01:33:21 +0200 Subject: [PATCH 1068/2654] must have a full filename --- src/simulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 353ef9926..2c9e7e856 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -408,7 +408,7 @@ void finalize_batch() } if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ - auto filename = settings::path_output + ".mcpl"; + auto filename = settings::path_output + "surface_source.mcpl"; write_mcpl_source_point(filename.c_str(), true); } From 169d6d93dcee45696bef96c4cb9b8ec8b5659791 Mon Sep 17 00:00:00 2001 From: myerspat Date: Wed, 5 Oct 2022 21:14:48 -0400 Subject: [PATCH 1069/2654] Added Doxygen comments to Region data and methods. Added default implementation for new void functions. --- include/openmc/cell.h | 58 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 0891c062f..248c2b23d 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -62,34 +62,84 @@ public: //---------------------------------------------------------------------------- // Methods + + //! \brief Determine if a cell contains the particle at a given location. + //! + //! The bounds of the cell are determined by a logical expression involving + //! surface half-spaces. The expression used is given in infix notation + //! + //! The function is split into two cases, one for simple cells (those + //! involving only the intersection of half-spaces) and one for complex cells. + //! Both cases use short circuiting; however, in the case fo complex cells, + //! the complexity increases with the binary operators involved. + //! \param r The 3D Cartesian coordinate to check. + //! \param u A direction used to "break ties" the coordinates are very + //! close to a surface. + //! \param on_surface The signed index of a surface that the coordinate is + //! known to be on. This index takes precedence over surface sense + //! calculations. + bool contains(Position r, Direction u, int32_t on_surface) const; + + //! Find the oncoming boundary of this cell. std::pair distance( Position r, Direction u, int32_t on_surface, Particle* p) const; - bool contains(Position r, Direction u, int32_t on_surface) const; + + //! Get the BoundingBox for this cell. BoundingBox bounding_box(int32_t cell_id) const; + + //! Get the CSG expression as a string std::string str() const; + + //! Get a vector containing all the surfaces in the region expression vector surfaces() const; //---------------------------------------------------------------------------- // Accessors + + //! Get Boolean of if the cell is simple or not bool is_simple() const { return simple_; } private: //---------------------------------------------------------------------------- // Private Methods + + //! Get a vector of the region expression in postfix notation vector generate_postfix(int32_t cell_id) const; + + //! Determine if a particle is inside the cell for a simple cell (only + //! intersection operators) bool contains_simple(Position r, Direction u, int32_t on_surface) const; + + //! Determine if a particle is inside the cell for a complex cell. + //! + //! Uses the comobination of half-spaces and binary operators to determine + //! if short circuiting can be used. Short cicuiting uses the relative and + //! absolute depth of parenthases in the expression. bool contains_complex(Position r, Direction u, int32_t on_surface) const; + + //! BoundingBox if the paritcle is in a simple cell. BoundingBox bounding_box_simple() const; + + //! BoundingBox if the particle is in a complex cell. BoundingBox bounding_box_complex(vector postfix) const; + + //! Enfource precedence: Parenthases, Complement, Intersection, Union void add_precedence(); + + //! Add parenthesis to enforce precedence std::vector::iterator add_parentheses( std::vector::iterator start); + + //! Remove complement operators from the expression void remove_complement_ops(); + + //! Remove complement operators by using DeMorgan's laws void apply_demorgan( vector::iterator start, vector::iterator stop); //---------------------------------------------------------------------------- // Private Data + //! Definition of spatial region as Boolean expression of half-spaces // TODO: Should this be a vector of some other type vector expression_; @@ -98,8 +148,6 @@ private: //============================================================================== -// TODO: Think about what data members really need to live in this class versus -// putting them in the Region class class Cell { public: //---------------------------------------------------------------------------- @@ -155,10 +203,10 @@ public: virtual BoundingBox bounding_box() const = 0; //! Get a vector of surfaces in the cell - virtual vector surfaces() const = 0; + virtual vector surfaces() const { return vector(); } //! Check if the cell region expression is simple - virtual bool is_simple() const = 0; + virtual bool is_simple() const { return true; } //---------------------------------------------------------------------------- // Accessors From 3779db43b82b0e938c0bc104b1474a98ce581bc9 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 6 Oct 2022 14:55:01 +0100 Subject: [PATCH 1070/2654] assume cython is present --- setup.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index 477f29dec..eec331353 100755 --- a/setup.py +++ b/setup.py @@ -5,11 +5,7 @@ import sys import numpy as np from setuptools import setup, find_packages -try: - from Cython.Build import cythonize - have_cython = True -except ImportError: - have_cython = False +from Cython.Build import cythonize # Determine shared library suffix @@ -76,13 +72,9 @@ kwargs = { 'test': ['pytest', 'pytest-cov', 'colorama'], 'vtk': ['vtk'], }, + # Cython is used to add resonance reconstruction and fast float_endf + 'ext_modules': cythonize('openmc/data/*.pyx'), + 'include_dirs': [np.get_include()] } -# If Cython is present, add resonance reconstruction and fast float_endf -if have_cython: - kwargs.update({ - 'ext_modules': cythonize('openmc/data/*.pyx'), - 'include_dirs': [np.get_include()] - }) - setup(**kwargs) From 0a04c20c744ca10dce3e2b9e254635a3d7245bf6 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 6 Oct 2022 15:57:48 +0100 Subject: [PATCH 1071/2654] removed py3.6 --- .github/workflows/ci.yml | 3 --- docs/source/devguide/styleguide.rst | 2 +- docs/source/usersguide/install.rst | 2 +- setup.py | 4 ++-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 050c8e287..b7c548a37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,9 +34,6 @@ jobs: vectfit: [n] include: - - python-version: 3.6 - omp: n - mpi: n - python-version: 3.7 omp: n mpi: n diff --git a/docs/source/devguide/styleguide.rst b/docs/source/devguide/styleguide.rst index 44d80915e..2a744b819 100644 --- a/docs/source/devguide/styleguide.rst +++ b/docs/source/devguide/styleguide.rst @@ -142,7 +142,7 @@ Style for Python code should follow PEP8_. Docstrings for functions and methods should follow numpydoc_ style. -Python code should work with Python 3.6+. +Python code should work with Python 3.7+. Use of third-party Python packages should be limited to numpy_, scipy_, matplotlib_, pandas_, and h5py_. Use of other third-party packages must be diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index b57958814..74be9ba0b 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -511,7 +511,7 @@ to install the Python package in :ref:`"editable" mode `. Prerequisites ------------- -The Python API works with Python 3.6+. In addition to Python itself, the API +The Python API works with Python 3.7+. In addition to Python itself, the API relies on a number of third-party packages. All prerequisites can be installed using Conda_ (recommended), pip_, or through the package manager in most Linux distributions. diff --git a/setup.py b/setup.py index 477f29dec..2a7e6a58d 100755 --- a/setup.py +++ b/setup.py @@ -57,14 +57,14 @@ kwargs = { 'Topic :: Scientific/Engineering' 'Programming Language :: C++', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', ], # Dependencies - 'python_requires': '>=3.6', + 'python_requires': '>=3.7', 'install_requires': [ 'numpy>=1.9', 'h5py', 'scipy', 'ipython', 'matplotlib', 'pandas', 'lxml', 'uncertainties' From f60520e8c55e36c5dedb9d0ac52b1de035c02d0a Mon Sep 17 00:00:00 2001 From: myerspat Date: Thu, 6 Oct 2022 12:28:18 -0400 Subject: [PATCH 1072/2654] Removed simple_ from dagmc --- src/dagmc.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 0e04869fd..a1b937e52 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -557,7 +557,6 @@ DAGCell::DAGCell(std::shared_ptr dag_ptr, int32_t dag_idx) : Cell {}, dagmc_ptr_(dag_ptr), dag_index_(dag_idx) { geom_type_ = GeometryType::DAG; - simple_ = true; }; std::pair DAGCell::distance( From 2a4c8bbb9b0253562131ddd207ebf1be523edc69 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 06:47:11 +0000 Subject: [PATCH 1073/2654] centre attribute to CylindricalMesh and SphericalMesh --- openmc/mesh.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 4059fee2d..59d64a146 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1052,6 +1052,7 @@ class CylindricalMesh(StructuredMesh): self._r_grid = None self._phi_grid = [0.0, 2*pi] self._z_grid = None + self._centre = [0, 0, 0] @property def dimension(self): @@ -1284,6 +1285,7 @@ class SphericalMesh(StructuredMesh): self._r_grid = None self._theta_grid = [0, pi] self._phi_grid = [0, 2*pi] + self._centre = [0, 0, 0] @property def dimension(self): From c20b351a2fa26d8198f833b256d140178b4c4e9c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 06:49:13 +0000 Subject: [PATCH 1074/2654] write to xml --- openmc/mesh.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 59d64a146..cc828acdc 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1161,6 +1161,9 @@ class CylindricalMesh(StructuredMesh): subelement = ET.SubElement(element, "z_grid") subelement.text = ' '.join(map(str, self.z_grid)) + subelement = ET.SubElement(element, "centre") + subelement.text = ' '.join(map(str, self.centre)) + return element @classmethod @@ -1184,6 +1187,8 @@ class CylindricalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] mesh.z_grid = [float(x) for x in get_text(elem, "z_grid").split()] + # TODO: add read centre + return mesh @property @@ -1394,6 +1399,9 @@ class SphericalMesh(StructuredMesh): subelement = ET.SubElement(element, "phi_grid") subelement.text = ' '.join(map(str, self.phi_grid)) + subelement = ET.SubElement(element, "centre") + subelement.text = ' '.join(map(str, self.centre)) + return element @classmethod @@ -1417,6 +1425,8 @@ class SphericalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.theta_grid = [float(x) for x in get_text(elem, "theta_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] + + # TODO: add read centre return mesh @property From 81ac9b0fd900df2d21cb194fbf242375844c9658 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 06:50:45 +0000 Subject: [PATCH 1075/2654] setters/getters --- openmc/mesh.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index cc828acdc..3efa1e114 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1064,6 +1064,10 @@ class CylindricalMesh(StructuredMesh): def n_dimension(self): return 3 + @property + def centre(self): + return self._centre + @property def r_grid(self): return self._r_grid @@ -1090,6 +1094,11 @@ class CylindricalMesh(StructuredMesh): for p in range(1, np + 1) for r in range(1, nr + 1)) + @centre.setter + def centre(self, coords): + cv.check_type('mesh r_grid', coords, Iterable, Real) + self._centre = np.asarray(coords) + @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) @@ -1302,6 +1311,10 @@ class SphericalMesh(StructuredMesh): def n_dimension(self): return 3 + @property + def centre(self): + return self._centre + @property def r_grid(self): return self._r_grid @@ -1328,6 +1341,11 @@ class SphericalMesh(StructuredMesh): for t in range(1, nt + 1) for r in range(1, nr + 1)) + @centre.setter + def centre(self, coords): + cv.check_type('mesh r_grid', coords, Iterable, Real) + self._centre = np.asarray(coords) + @r_grid.setter def r_grid(self, grid): cv.check_type('mesh r_grid', grid, Iterable, Real) From f0f5e34b33e79fe5818ae227bd5da192a208bf40 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 06:55:56 +0000 Subject: [PATCH 1076/2654] read centre from xml --- src/mesh.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/mesh.cpp b/src/mesh.cpp index d9ad0ce8a..8307e5fe8 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -955,6 +955,7 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "phi_grid"); grid_[2] = get_node_array(node, "z_grid"); + centre = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -983,6 +984,11 @@ StructuredMesh::MeshIndex CylindricalMesh::get_indices( mapped_r[1] += 2 * M_PI; } + // TODO: pass centre as argument + mapped_r[0] += centre[0] + mapped_r[1] += centre[1] + mapped_r[2] += centre[2] + MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); idx[1] = sanitize_phi(idx[1]); @@ -1187,6 +1193,7 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "theta_grid"); grid_[2] = get_node_array(node, "phi_grid"); + centre = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -1216,6 +1223,11 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( mapped_r[2] += 2 * M_PI; } + // TODO: pass centre as argument + mapped_r[0] += centre[0] + mapped_r[1] += centre[1] + mapped_r[2] += centre[2] + MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); idx[1] = sanitize_theta(idx[1]); From 5787616ae41593bac4d100da162da5a8f98a1cea Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 07:18:00 +0000 Subject: [PATCH 1077/2654] added two tests to check centre was written/read to/from xml --- tests/unit_tests/test_cylindrical_mesh.py | 30 +++++++++++++++++++++++ tests/unit_tests/test_spherical_mesh.py | 30 +++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tests/unit_tests/test_cylindrical_mesh.py create mode 100644 tests/unit_tests/test_spherical_mesh.py diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py new file mode 100644 index 000000000..89322d704 --- /dev/null +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -0,0 +1,30 @@ +import openmc +import numpy as np + +def test_centre_read_write_to_xml(): + """Tests that the centre attribute can be written and read back to XML + """ + # build + mesh = openmc.CylindricalMesh() + mesh.phi_grid = [1, 2, 3] + mesh.z_grid = [1, 2, 3] + mesh.r_grid = [1, 2, 3] + + mesh.centre = [0.1, 0.2, 0.3] + + tally = openmc.Tally() + + mesh_filter = openmc.MeshFilter(mesh) + tally.filters.append(mesh_filter) + + tally.scores.append("heating") + + tallies = openmc.Tallies([tally]) + + tallies.export_to_xml() + + # read back + new_tallies = openmc.Tallies.from_xml() + new_tally = new_tallies[0] + new_mesh = new_tally.filters[0].mesh + assert np.allclose(new_mesh.centre, mesh.centre) \ No newline at end of file diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py new file mode 100644 index 000000000..cdeb188ec --- /dev/null +++ b/tests/unit_tests/test_spherical_mesh.py @@ -0,0 +1,30 @@ +import openmc +import numpy as np + +def test_centre_read_write_to_xml(): + """Tests that the centre attribute can be written and read back to XML + """ + # build + mesh = openmc.SphericalMesh() + mesh.phi_grid = [1, 2, 3] + mesh.theta_grid = [1, 2, 3] + mesh.r_grid = [1, 2, 3] + + mesh.centre = [0.1, 0.2, 0.3] + + tally = openmc.Tally() + + mesh_filter = openmc.MeshFilter(mesh) + tally.filters.append(mesh_filter) + + tally.scores.append("heating") + + tallies = openmc.Tallies([tally]) + + tallies.export_to_xml() + + # read back + new_tallies = openmc.Tallies.from_xml() + new_tally = new_tallies[0] + new_mesh = new_tally.filters[0].mesh + assert np.allclose(new_mesh.centre, mesh.centre) \ No newline at end of file From 16add87c05a2a228daabb4f99a3c09c0defe2b46 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 07:18:52 +0000 Subject: [PATCH 1078/2654] now reads back from xml --- openmc/mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 3efa1e114..abc46c70b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1196,7 +1196,7 @@ class CylindricalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] mesh.z_grid = [float(x) for x in get_text(elem, "z_grid").split()] - # TODO: add read centre + mesh.centre = [float(x) for x in get_text(elem, "centre").split()] return mesh @@ -1443,8 +1443,8 @@ class SphericalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.theta_grid = [float(x) for x in get_text(elem, "theta_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] + mesh.centre = [float(x) for x in get_text(elem, "centre").split()] - # TODO: add read centre return mesh @property From 21200d9b6eb6f07c0dbb1e2885c6c367dea54100 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 07:42:34 +0000 Subject: [PATCH 1079/2654] offsets the write_to_vtk coordinates --- openmc/mesh.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index abc46c70b..8f47e4e7b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1052,7 +1052,7 @@ class CylindricalMesh(StructuredMesh): self._r_grid = None self._phi_grid = [0.0, 2*pi] self._z_grid = None - self._centre = [0, 0, 0] + self._centre = [0., 0., 0.] @property def dimension(self): @@ -1251,6 +1251,11 @@ class CylindricalMesh(StructuredMesh): pts_cartesian[:, 0] = r * np.cos(phi) pts_cartesian[:, 1] = r * np.sin(phi) + # offset with centre + pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.centre[0] + pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.centre[1] + pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.centre[2] + return super().write_data_to_vtk( points=pts_cartesian, filename=filename, @@ -1299,7 +1304,7 @@ class SphericalMesh(StructuredMesh): self._r_grid = None self._theta_grid = [0, pi] self._phi_grid = [0, 2*pi] - self._centre = [0, 0, 0] + self._centre = [0., 0., 0.] @property def dimension(self): @@ -1500,6 +1505,11 @@ class SphericalMesh(StructuredMesh): pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) pts_cartesian[:, 2] = r * np.cos(phi) + # offset with centre + pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.centre[0] + pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.centre[1] + pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.centre[2] + return super().write_data_to_vtk( points=pts_cartesian, filename=filename, From 896ae2792ec6e1dfdaa2f7054dda5cb890d7e43f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 08:40:04 +0000 Subject: [PATCH 1080/2654] centre to centre_ --- src/mesh.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 8307e5fe8..5fa46cd85 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -955,7 +955,7 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "phi_grid"); grid_[2] = get_node_array(node, "z_grid"); - centre = get_node_array(node, "centre"); + centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -985,9 +985,9 @@ StructuredMesh::MeshIndex CylindricalMesh::get_indices( } // TODO: pass centre as argument - mapped_r[0] += centre[0] - mapped_r[1] += centre[1] - mapped_r[2] += centre[2] + mapped_r[0] += centre_[0] + mapped_r[1] += centre_[1] + mapped_r[2] += centre_[2] MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); @@ -1193,7 +1193,7 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "theta_grid"); grid_[2] = get_node_array(node, "phi_grid"); - centre = get_node_array(node, "centre"); + centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -1224,9 +1224,9 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( } // TODO: pass centre as argument - mapped_r[0] += centre[0] - mapped_r[1] += centre[1] - mapped_r[2] += centre[2] + mapped_r[0] += centre_[0] + mapped_r[1] += centre_[1] + mapped_r[2] += centre_[2] MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); From d194e000803acc3c6e35c9e95d27859ae43d6b99 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 09:00:27 +0000 Subject: [PATCH 1081/2654] test if grid_ is defined in this scope --- src/mesh.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mesh.cpp b/src/mesh.cpp index 5fa46cd85..7a0a243f0 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1223,6 +1223,9 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( mapped_r[2] += 2 * M_PI; } + // test + coucou = grid_[0] + // TODO: pass centre as argument mapped_r[0] += centre_[0] mapped_r[1] += centre_[1] From a104c1f890055f5822d2b93db08bdcad255a17a0 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 09:07:51 +0000 Subject: [PATCH 1082/2654] [skip ci] removed test --- src/mesh.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 7a0a243f0..5fa46cd85 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1223,9 +1223,6 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( mapped_r[2] += 2 * M_PI; } - // test - coucou = grid_[0] - // TODO: pass centre as argument mapped_r[0] += centre_[0] mapped_r[1] += centre_[1] From bdd13ba3f4c29512f0fc24d4cf856f010a982e1c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 09:15:27 +0000 Subject: [PATCH 1083/2654] attempt #2 --- src/mesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 5fa46cd85..9fde3dbe1 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -955,7 +955,7 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "phi_grid"); grid_[2] = get_node_array(node, "z_grid"); - centre_ = get_node_array(node, "centre"); + double centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -1193,7 +1193,7 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "theta_grid"); grid_[2] = get_node_array(node, "phi_grid"); - centre_ = get_node_array(node, "centre"); + double centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); From e394637f2f873ca3cec6417a02031f340650e368 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 09:32:08 +0000 Subject: [PATCH 1084/2654] declare variable with auto --- src/mesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 9fde3dbe1..ad67b2ba4 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -955,7 +955,7 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "phi_grid"); grid_[2] = get_node_array(node, "z_grid"); - double centre_ = get_node_array(node, "centre"); + auto centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -1193,7 +1193,7 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "theta_grid"); grid_[2] = get_node_array(node, "phi_grid"); - double centre_ = get_node_array(node, "centre"); + auto centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); From 61b4f30dd4f1ce0bd44e339b59a7cfe31fef057f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 10:59:35 +0000 Subject: [PATCH 1085/2654] declaring centre_ in C file --- include/openmc/mesh.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index eece0f1ff..e6f5ce98b 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -359,6 +359,8 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; + array centre_; + int set_grid(); @@ -413,6 +415,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; + array centre_; int set_grid(); From fc5aa68d732fb15e99e103d1543451dbb57f99ab Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 10:59:52 +0000 Subject: [PATCH 1086/2654] removed auto + ; --- src/mesh.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index ad67b2ba4..c049549eb 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -955,7 +955,7 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "phi_grid"); grid_[2] = get_node_array(node, "z_grid"); - auto centre_ = get_node_array(node, "centre"); + centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -985,9 +985,9 @@ StructuredMesh::MeshIndex CylindricalMesh::get_indices( } // TODO: pass centre as argument - mapped_r[0] += centre_[0] - mapped_r[1] += centre_[1] - mapped_r[2] += centre_[2] + mapped_r[0] += centre_[0]; + mapped_r[1] += centre_[1]; + mapped_r[2] += centre_[2]; MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); @@ -1193,7 +1193,7 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "theta_grid"); grid_[2] = get_node_array(node, "phi_grid"); - auto centre_ = get_node_array(node, "centre"); + centre_ = get_node_array(node, "centre"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -1224,9 +1224,9 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( } // TODO: pass centre as argument - mapped_r[0] += centre_[0] - mapped_r[1] += centre_[1] - mapped_r[2] += centre_[2] + mapped_r[0] += centre_[0]; + mapped_r[1] += centre_[1]; + mapped_r[2] += centre_[2]; MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); From e1dbe49bbbcae3c227190f48e2d6d89945b64187 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 11:06:24 +0000 Subject: [PATCH 1087/2654] correct type for centre_ --- include/openmc/mesh.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index e6f5ce98b..ea6b01aa6 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -359,7 +359,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - array centre_; + vector centre_; int set_grid(); @@ -415,7 +415,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - array centre_; + vector centre_; int set_grid(); From 1ed096f6608b0caad5f2f17f4cfc34c278d78b95 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 7 Oct 2022 12:53:34 +0000 Subject: [PATCH 1088/2654] added centre tag to standard --- tests/regression_tests/filter_mesh/inputs_true.dat | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/regression_tests/filter_mesh/inputs_true.dat b/tests/regression_tests/filter_mesh/inputs_true.dat index d0c481d60..c42f3cd43 100644 --- a/tests/regression_tests/filter_mesh/inputs_true.dat +++ b/tests/regression_tests/filter_mesh/inputs_true.dat @@ -57,11 +57,13 @@ 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 -7.5 -6.5625 -5.625 -4.6875 -3.75 -2.8125 -1.875 -0.9375 0.0 0.9375 1.875 2.8125 3.75 4.6875 5.625 6.5625 7.5 + 0.0 0.0 0.0 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 0.0 0.39269908169872414 0.7853981633974483 1.1780972450961724 1.5707963267948966 1.9634954084936207 2.356194490192345 2.748893571891069 3.141592653589793 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 + 0.0 0.0 0.0 1 From 0706a0eca305c8fc4a0a5cbfb0c5b6e46099753e Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 11 Oct 2022 00:46:32 +0200 Subject: [PATCH 1089/2654] fix malformed format string --- src/state_point.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 7c1a45447..e197ee162 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -625,9 +625,9 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) //write_attribute(file_id, "filetype", "source"); //write header stuff (oopy in xml-files as binary blobs for instance)) if (VERSION_DEV){ - line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}-development"); + line=fmt::format("OpenMC {0}.{1}.{2}-development",VERSION_MAJOR,VERSION_MINOR,VERSION_RELEASE); } else { - line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}"); + line=fmt::format("OpenMC {0}.{1}.{2}",VERSION_MAJOR,VERSION_MINOR,VERSION_RELEASE); } mcpl_hdr_set_srcname(file_id,line.c_str()); } From aeadaf0b2f1a59fcd2c3f8cb3ad8fa7dab36e342 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 11 Oct 2022 00:48:44 +0200 Subject: [PATCH 1090/2654] fix typo causing unit length errors --- src/state_point.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index e197ee162..a8a4be034 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -802,9 +802,11 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) p.position[1]=_site->r.y; p.position[2]=_site->r.z; + //mcpl requires that the direction vector is unit length + //which is also the case in openmc p.direction[0]=_site->u.x; p.direction[1]=_site->u.y; - p.direction[2]=_site->u.x; + p.direction[2]=_site->u.z; //mcpl stores kinetic energy in MeV p.ekin=_site->E*1e-6; From 72251eb30a996e6aaa9672292a1483c69d53a652 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 11 Oct 2022 02:00:33 +0200 Subject: [PATCH 1091/2654] enable mcpl surf_source_write in the python layer --- openmc/settings.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 2d8121659..45ff0edc6 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -165,6 +165,7 @@ class Settings: banked (int) :max_particles: Maximum number of particles to be banked on surfaces per process (int) + :mcpl: Output in the form of an MCPL-file (bool) survival_biasing : bool Indicate whether survival biasing is to be used tabular_legendre : dict @@ -643,7 +644,7 @@ class Settings: cv.check_type('surface source writing options', surf_source_write, Mapping) for key, value in surf_source_write.items(): cv.check_value('surface source writing key', key, - ('surface_ids', 'max_particles')) + ('surface_ids', 'max_particles', 'mcpl')) if key == 'surface_ids': cv.check_type('surface ids for source banking', value, Iterable, Integral) @@ -655,6 +656,9 @@ class Settings: value, Integral) cv.check_greater_than('maximum particle banks on surfaces per process', value, 0) + elif key == 'mcpl': + cv.check_type('write to an MCPL-format file', value, bool) + self._surf_source_write = surf_source_write @confidence_intervals.setter @@ -1023,6 +1027,9 @@ class Settings: if 'max_particles' in self._surf_source_write: subelement = ET.SubElement(element, "max_particles") subelement.text = str(self._surf_source_write['max_particles']) + if 'mcpl' in self._surf_source_write: + subelement = ET.SubElement(element, "mcpl") + subelement.text = str(self._surf_source_write['mcpl']).lower() def _create_confidence_intervals(self, root): if self._confidence_intervals is not None: From 3e2ddceaac8484503c57fef4248af50399067b96 Mon Sep 17 00:00:00 2001 From: josh Date: Tue, 11 Oct 2022 03:03:50 +0000 Subject: [PATCH 1092/2654] Add tolerance for interp temps outside of bounds --- docs/source/io_formats/settings.rst | 11 +++++++-- openmc/settings.py | 16 +++++++------ src/cell.cpp | 4 ++-- src/nuclide.cpp | 35 +++++++++++++++++++++++++++++ src/thermal.cpp | 35 +++++++++++++++++++++-------- 5 files changed, 81 insertions(+), 20 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 1a8f63716..7a794bf00 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -832,7 +832,9 @@ cell, the nearest temperature at which cross sections are given is to be applied, within a given tolerance (see :ref:`temperature_tolerance`). A value of "interpolation" indicates that cross sections are to be linear-linear interpolated between temperatures at which nuclear data are present (see -:ref:`temperature_treatment`). +:ref:`temperature_treatment`). With the "interpolation" method, temperatures +outside of the bounds of the nuclear data may be accepted, provided they still +fall within the tolerance (see :ref:`temperature_tolerance`). *Default*: "nearest" @@ -871,7 +873,12 @@ The ```` element specifies a tolerance in Kelvin that is to be applied when the "nearest" temperature method is used. For example, if a cell temperature is 340 K and the tolerance is 15 K, then the closest temperature in the range of 325 K to 355 K will be used to evaluate cross -sections. +sections. If the ```` is "interpolation", the tolerance +specified applies to cell temperatures outside of the data bounds. For example, +If a cell is specified at 695K, a tolerance of 15K and data only available at +700K and 1000K, the cell's cross sections will be evaluated at 700K, since +desired temperature of 695K is within the tolerance of the actual data despite +not being bounded on both sides. *Default*: 10 K diff --git a/openmc/settings.py b/openmc/settings.py index ad5a9b28a..9d9b421ca 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -186,13 +186,15 @@ class Settings: 'default', 'method', 'range', 'tolerance', and 'multipole'. The value for 'default' should be a float representing the default temperature in Kelvin. The value for 'method' should be 'nearest' or 'interpolation'. - If the method is 'nearest', 'tolerance' indicates a range of temperature - within which cross sections may be used. The value for 'range' should be - a pair a minimum and maximum temperatures which are used to indicate - that cross sections be loaded at all temperatures within the - range. 'multipole' is a boolean indicating whether or not the windowed - multipole method should be used to evaluate resolved resonance cross - sections. + If the method is 'nearest', 'tolerance' indicates a range of + temperature within which cross sections may be used. If the method is + 'interpolation', 'tolerance' indicates the range of temperatures outside + of the available cross section temperatures where cross sections will + evaluate to the nearer bound. The value for 'range' should be a pair a + minimum and maximum temperatures which are used to indicate that cross + sections be loaded at all temperatures within the range. 'multipole' is + a boolean indicating whether or not the windowed multipole method should + be used to evaluate resolved resonance cross sections. trace : tuple or list Show detailed information about a single particle, indicated by three integers: the batch number, generation number, and particle number diff --git a/src/cell.cpp b/src/cell.cpp index 4ff35498c..d69f79a3e 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -334,10 +334,10 @@ double Cell::temperature(int32_t instance) const void Cell::set_temperature(double T, int32_t instance, bool set_contained) { if (settings::temperature_method == TemperatureMethod::INTERPOLATION) { - if (T < data::temperature_min) { + if (T < data::temperature_min - settings::temperature_tolerance) { throw std::runtime_error {"Temperature is below minimum temperature at " "which data is available."}; - } else if (T > data::temperature_max) { + } else if (T > data::temperature_max + settings::temperature_tolerance) { throw std::runtime_error {"Temperature is above maximum temperature at " "which data is available."}; } diff --git a/src/nuclide.cpp b/src/nuclide.cpp index 564e27d44..4c1706509 100644 --- a/src/nuclide.cpp +++ b/src/nuclide.cpp @@ -169,6 +169,22 @@ Nuclide::Nuclide(hid_t group, const vector& temperature) } if (!found_pair) { + // If no pairs found, check if the desired temperature falls just + // outside of data + if (T_desired - temps_available.front() <= + -settings::temperature_tolerance) { + if (!contains(temps_to_read, temps_available.front())) { + temps_to_read.push_back(std::round(temps_available.front())); + } + break; + } + if (T_desired - temps_available.back() <= + settings::temperature_tolerance) { + if (!contains(temps_to_read, temps_available.back())) { + temps_to_read.push_back(std::round(temps_available.back())); + } + break; + } fatal_error( "Nuclear data library does not contain cross sections for " + name_ + " at temperatures that bound " + std::to_string(T_desired) + " K."); @@ -646,6 +662,16 @@ void Nuclide::calculate_xs( } break; case TemperatureMethod::INTERPOLATION: + // If current kT outside of the bounds of available, snap to the bound + if (kT < kTs_.front()) { + i_temp = 0; + break; + } + if (kT > kTs_.back()) { + i_temp = kTs_.size() - 1; + break; + } + // Find temperatures that bound the actual temperature for (i_temp = 0; i_temp < kTs_.size() - 1; ++i_temp) { if (kTs_[i_temp] <= kT && kT < kTs_[i_temp + 1]) @@ -969,6 +995,15 @@ std::pair Nuclide::find_temperature(double T) const } break; case TemperatureMethod::INTERPOLATION: + // If current kT outside of the bounds of available, snap to the bound + if (kT < kTs_.front()) { + i_temp = 0; + break; + } + if (kT > kTs_.back()) { + i_temp = kTs_.size() - 1; + break; + } // Find temperatures that bound the actual temperature while (kTs_[i_temp + 1] < kT && i_temp + 1 < n - 1) ++i_temp; diff --git a/src/thermal.cpp b/src/thermal.cpp index 1a9592d0a..66e1fb009 100644 --- a/src/thermal.cpp +++ b/src/thermal.cpp @@ -117,6 +117,16 @@ ThermalScattering::ThermalScattering( } } if (!found) { + // If no pairs found, check if the desired temperature falls within + // bounds' tolerance + if (T - temps_available[0] <= -settings::temperature_tolerance) { + temps_to_read.push_back(std::round(temps_available[0])); + break; + } + if (T - temps_available[n - 1] <= settings::temperature_tolerance) { + temps_to_read.push_back(std::round(temps_available[n - 1])); + break; + } fatal_error( fmt::format("Nuclear data library does not contain cross " "sections for {} at temperatures that bound {} K.", @@ -159,20 +169,27 @@ void ThermalScattering::calculate_xs(double E, double sqrtkT, int* i_temp, auto n = kTs_.size(); if (n > 1) { - // Find temperatures that bound the actual temperature - while (kTs_[i + 1] < kT && i + 1 < n - 1) - ++i; - if (settings::temperature_method == TemperatureMethod::NEAREST) { + while (kTs_[i + 1] < kT && i + 1 < n - 1) + ++i; // Pick closer of two bounding temperatures if (kT - kTs_[i] > kTs_[i + 1] - kT) ++i; - } else { - // Randomly sample between temperature i and i+1 - double f = (kT - kTs_[i]) / (kTs_[i + 1] - kTs_[i]); - if (f > prn(seed)) - ++i; + // If current kT outside of the bounds of available, snap to the bound + if (kT < kTs_.front()) { + i = 0; + } else if (kT > kTs_.back()) { + i = kTs_.size() - 1; + } else { + // Find temperatures that bound the actual temperature + while (kTs_[i + 1] < kT && i + 1 < n - 1) + ++i; + // Randomly sample between temperature i and i+1 + double f = (kT - kTs_[i]) / (kTs_[i + 1] - kTs_[i]); + if (f > prn(seed)) + ++i; + } } } From bf0c5d7f9a8d118e4770d4ed4ca184c93aa30896 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 22 Jun 2022 22:50:07 +0200 Subject: [PATCH 1093/2654] add placeholder skeleton for MCPL-input --- include/openmc/source.h | 19 +++++++++++++++++++ src/source.cpp | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/openmc/source.h b/include/openmc/source.h index 04b9ff856..0f1965cb8 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -110,6 +110,25 @@ private: vector sites_; //!< Source sites from a file }; +//============================================================================== +// MCPL-file input source +//============================================================================== +class MCPLFileSource : public Source { +public: + // Constructors, destructors + MCPLFileSource(std::string path); + ~MCPLFileSource(); + + // Defer implementation to custom source library + SourceSite sample(uint64_t* seed) const override + +private: + vector sites_; //! Date: Thu, 23 Jun 2022 11:34:53 +0200 Subject: [PATCH 1094/2654] include mcpl header --- src/source.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/source.cpp b/src/source.cpp index 1e84f8334..7c1184602 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -33,6 +33,10 @@ #include "openmc/state_point.h" #include "openmc/xml_interface.h" +#ifdef HAS_MCPL +#include +#endif + namespace openmc { //============================================================================== From 249a554980801a3c2cc3be336369c95c0e447436 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 23 Jun 2022 11:35:46 +0200 Subject: [PATCH 1095/2654] declarations of MCPL-internals --- include/openmc/source.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index 0f1965cb8..24a3d10ae 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -119,11 +119,20 @@ public: MCPLFileSource(std::string path); ~MCPLFileSource(); - // Defer implementation to custom source library - SourceSite sample(uint64_t* seed) const override + // Properties + ParticleType particle_type() const { return particle_; } + + //! Sample from the external source distribution + //! \param[inout] seed Pseudorandom seed pointer + //! \return Site read from MCPL-file + SourceSite sample(uint64_t* seed) const override; private: + ParticleType particle_ {ParticleType::neutron}; //!< Type of particle emitted vector sites_; //! Date: Thu, 23 Jun 2022 11:37:05 +0200 Subject: [PATCH 1096/2654] internals of sample and constructor --- src/source.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 7c1184602..3dfd00707 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -383,7 +383,7 @@ CustomSourceWrapper::~CustomSourceWrapper() } //=========================================================================== -// Read an MCPL-file +// Read particles from an MCPL-file //=========================================================================== MCPLFileSource::MCPLFileSource(std::string path) { @@ -394,12 +394,55 @@ MCPLFileSource::MCPLFileSource(std::string path) // Read the source from a binary file instead of sampling from some // assumed source distribution - write_message(6, "Reading source file from {}...", path); + write_message(6, "Reading mcpl source file from {}",path); // Open the mcpl file - id_t file_id = mcpl_open(path.c_str) - + mcpl_file = mcpl_open(path.c_str); + //do checks on the mcpl_file to see if particles are many enough. + // should model this on the example source shown in the docs. + uint64_t nparticles=mcpl_hdr_nparticles(mcpl_file); + +} + +MCPLFileSource::~MCPLFilsSource(){ + mcpl_close_file(mcpl_file); +} + +SourceSite MCPLFileSource::sample(uint64_t *seed){ + SourceSite omc_particle; + mcpl_particle *mcpl_particle; + //extract particle from mcpl-file + mcpl_particle=mcpl_reazd(mcplfile); + // check if it is a neutron or a photon. otherwise skip + while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) + { + mcpl_particle(mcpl_read(mcplfile); + //check for file exhaustion + } + + if(mcpl_particle->pdgcode=2112) { + omc_particle_=ParticleType::neutron; + } else { + omc_particle_=Particletype::photon; + } + + //particle is good, convert to openmc-formalism + omc_particle.r.x=mcpl_particle.x; + omc_particle.r.y=mcpl_particle.y; + omc_particle.r.z=mcpl_particle.z; + + omc_particle.u.x=mcpl_particle->direction[0]; + omc_particle.u.y=mcpl_particle->direction[1]; + omc_particle.u.z=mcpl_particle->direction[2]; + + //mcpl stores particles in MeV + omc_particle.E=mcpl_particle->ekin*1e6; + + omc_particle.t=mcpl_particle->time*1e-3; + omc_particle.wgt=mcpl_particle->weight; + omc_particle.delayed_group=0; + return omc_particle; } From 999acbba9a9f69648e9b91198fe4ff0792838b1d Mon Sep 17 00:00:00 2001 From: erkn Date: Mon, 27 Jun 2022 23:25:35 +0200 Subject: [PATCH 1097/2654] (wip): skeleton for input only test --- .../regression_tests/source_mcpl_file/test.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/test.py diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py new file mode 100644 index 000000000..5a6a87d87 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -0,0 +1,52 @@ +import pathlib as pl +import os +import shutil +import subprocess +import textwrap + +import openmc +import pytest + +from tests.testing_harness import TestHarness + +def model(): + subprocess.run(['gcc','-o gen_dummt_mcpl.out','-lm','-lmcpl','gen_dummy_mcpl.c'] ) + subprocess.run(['./gen_dummy_mcpl.out']) + +class SourceMCPLFileTestHarness(TestHarness): + def execute_test(self): + """Run OpenMC with the appropriate arguments and check the outputs.""" + try: + self._create_input() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._compare_results() + finally: + self._cleanup() + + def update_results(self): + """Update the results_true using the current version of OpenMC.""" + try: + self._create_input() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._overwrite_results() + finally: + self._cleanup() + + def _test_output_created(self): + """Check that the output files were created""" + stat epoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) + assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ + 'exist.' + assert statepoint[0].endswith('h5'), \ + 'statepoint file does not end with h5.' + +def test_mcpl_source_file(): + harness = SourceMCPLFileTestHarness('statepoint.10.h5') + harness.main() + From 3e805cce158630e70df95abb5d20368983339031 Mon Sep 17 00:00:00 2001 From: erkn Date: Mon, 27 Jun 2022 23:26:01 +0200 Subject: [PATCH 1098/2654] c-prog to generate a dummy mcpl --- .../source_mcpl_file/gen_dummy_mcpl.c | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c new file mode 100644 index 000000000..7b5a933f1 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include + +const int batches=10; +const int particles=10000; + +double rand01(){ + double r=rand()/((double) RAND_MAX); + return r; +} + + +int main(int argc, char **argv){ + char outfilename[128]; + snprintf(outfilename,127,"source.%d.mcpl",batches); + + /*generate an mcpl_header_of sorts*/ + mcpl_outfile_t outfile=mcpl_create_outfile(outfilename); + mcpl_particle_t *particle, Particle; + + char line[256]; + snprintf(line,255,"gen_dummy_mcpl.c"); + mcpl_hdr_set_srcname(outfile,line); + mcpl_enable_universal_pdgcode(outfile,2112);/*all particles are neutrons*/ + snprintf(line,255,"Dummy MCPL-file for testing OpenMC mcpl input"); + mcpl_hdr_add_comment(outfile,line); + + /*also add the instrument file and the command line as blobs*/ + FILE *fp; + if( (fp=fopen("gen_dummy_mcpl.c","rb"))!=NULL){ + unsigned char *buffer; + int size,status; + /*find the file size by seeking to end, "tell" the position, and then go back again*/ + fseek(fp, 0L, SEEK_END); + size = ftell(fp); // get current file pointer + fseek(fp, 0L, SEEK_SET); // seek back to beginning of file + if ( size && (buffer=malloc(size))!=NULL){ + if (size!=(fread(buffer,1,size,fp))){ + fprintf(stderr,"Warning: c source generator file not read cleanly\n"); + } + mcpl_hdr_add_data(outfile, "mcpl_point_source_file_generator", size, buffer); + free(buffer); + } + fclose(fp); + } else { + fprintf(stderr,"Warning: could not open c source generator file, hence not embedded.\n"); + } + + + /*the main particle loop*/ + particle=&Particle; + int i; + for (i=0;iposition[0]=0; + particle->position[1]=0; + particle->position[2]=0; + + /*generate a random direction on unit sphere*/ + double nrm=2.0; + double vx,vy,vz; + int iter=0; + do { + if(iter>100){ + printf("warning: exceeed max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); + } + vx=rand01()*2.0-1.0; + vy=rand01()*2.0-1.0; + vz=rand01()*2.0-1.0; + nrm=(vx*vx + vy*vy + vz*vz); + iter++; + } while (nrm>1.0); + vx/=sqrt(nrm); + vy/=sqrt(nrm); + vz/=sqrt(nrm); + particle->direction[0]=vx; + particle->direction[1]=vy; + particle->direction[2]=vz; + + /*generate the kinetic energy (in MeV) of the particle*/ + particle->ekin=1e-3; + + /*set time=0*/ + particle->time=0; + /*set weight*/ + particle->weight=1; + + particle->userflags=0; + mcpl_add_particle(outfile,particle); + } + mcpl_closeandgzip_outfile(outfile); +} From c6b42e828cf8bf9bccf77d296976ff83902fb346 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 5 Jul 2022 01:30:07 +0200 Subject: [PATCH 1099/2654] don't zip the output-file --- .../source_mcpl_file/gen_dummy_mcpl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c index 7b5a933f1..f35a07fc4 100644 --- a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -54,20 +54,20 @@ int main(int argc, char **argv){ int i; for (i=0;iposition[0]=0; particle->position[1]=0; particle->position[2]=0; - + /*generate a random direction on unit sphere*/ double nrm=2.0; double vx,vy,vz; int iter=0; do { if(iter>100){ - printf("warning: exceeed max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); + printf("Warning: Exceeded max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); } vx=rand01()*2.0-1.0; vy=rand01()*2.0-1.0; @@ -82,9 +82,9 @@ int main(int argc, char **argv){ particle->direction[1]=vy; particle->direction[2]=vz; - /*generate the kinetic energy (in MeV) of the particle*/ + /*generate the kinetic energy (in MeV) of the particle*/ particle->ekin=1e-3; - + /*set time=0*/ particle->time=0; /*set weight*/ @@ -93,5 +93,5 @@ int main(int argc, char **argv){ particle->userflags=0; mcpl_add_particle(outfile,particle); } - mcpl_closeandgzip_outfile(outfile); + mcpl_close_outfile(outfile); } From b2f83857e4af32848570abc33985a40587e77489 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 5 Jul 2022 01:53:14 +0200 Subject: [PATCH 1100/2654] now compiles fine if mcpl is indeed installed --- .../regression_tests/source_mcpl_file/test.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 5a6a87d87..0adf67f1a 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -3,16 +3,13 @@ import os import shutil import subprocess import textwrap - +import glob import openmc import pytest from tests.testing_harness import TestHarness -def model(): - subprocess.run(['gcc','-o gen_dummt_mcpl.out','-lm','-lmcpl','gen_dummy_mcpl.c'] ) - subprocess.run(['./gen_dummy_mcpl.out']) - + class SourceMCPLFileTestHarness(TestHarness): def execute_test(self): """Run OpenMC with the appropriate arguments and check the outputs.""" @@ -26,6 +23,10 @@ class SourceMCPLFileTestHarness(TestHarness): finally: self._cleanup() + def _create_input(self): + subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) + subprocess.run(['./gen_dummy_mcpl.out']) + def update_results(self): """Update the results_true using the current version of OpenMC.""" try: @@ -40,13 +41,19 @@ class SourceMCPLFileTestHarness(TestHarness): def _test_output_created(self): """Check that the output files were created""" - stat epoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' assert statepoint[0].endswith('h5'), \ 'statepoint file does not end with h5.' + def _cleanup(self): + super()._cleanup() + source_mcpl=glob.glob(os.path.join(os.getcwd(),'source*.mcpl')) + for f in source_mcpl: + if (os.path.exists(f)): + os.remove(f) + def test_mcpl_source_file(): harness = SourceMCPLFileTestHarness('statepoint.10.h5') harness.main() - From 005189bfdfa9f956139af45c6504e22d2eb8659c Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 11 Jul 2022 09:49:29 +0200 Subject: [PATCH 1101/2654] fix misprints --- src/source.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 3dfd00707..3ef5ae16f 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -413,7 +413,7 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ SourceSite omc_particle; mcpl_particle *mcpl_particle; //extract particle from mcpl-file - mcpl_particle=mcpl_reazd(mcplfile); + mcpl_particle=mcpl_read(mcplfile); // check if it is a neutron or a photon. otherwise skip while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { @@ -421,9 +421,9 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ //check for file exhaustion } - if(mcpl_particle->pdgcode=2112) { + if(mcpl_particle->pdgcode==2112) { omc_particle_=ParticleType::neutron; - } else { + } else if (mcpl_particle->pdgcode==22){ omc_particle_=Particletype::photon; } @@ -436,9 +436,9 @@ SourceSite MCPLFileSource::sample(uint64_t *seed){ omc_particle.u.y=mcpl_particle->direction[1]; omc_particle.u.z=mcpl_particle->direction[2]; - //mcpl stores particles in MeV + //mcpl stores kinetic energy in MeV omc_particle.E=mcpl_particle->ekin*1e6; - + //mcpl stores time in ms omc_particle.t=mcpl_particle->time*1e-3; omc_particle.wgt=mcpl_particle->weight; omc_particle.delayed_group=0; From 935396e40bf97a6ba4a9dcf2dcac30b5a80056ba Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 13:48:55 +0200 Subject: [PATCH 1102/2654] add necessary xmls --- tests/regression_tests/source_mcpl_file/geometry.xml | 8 ++++++++ tests/regression_tests/source_mcpl_file/materials.xml | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/geometry.xml create mode 100644 tests/regression_tests/source_mcpl_file/materials.xml diff --git a/tests/regression_tests/source_mcpl_file/geometry.xml b/tests/regression_tests/source_mcpl_file/geometry.xml new file mode 100644 index 000000000..bc56030e1 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/geometry.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/regression_tests/source_mcpl_file/materials.xml b/tests/regression_tests/source_mcpl_file/materials.xml new file mode 100644 index 000000000..2472a7471 --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/materials.xml @@ -0,0 +1,9 @@ + + + + + + + + + From e87ebfebc29b07f9ca575629364165fc129ed512 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 13:49:56 +0200 Subject: [PATCH 1103/2654] set seed to make test deteministic --- tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c index f35a07fc4..61eea95c6 100644 --- a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c +++ b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c @@ -52,6 +52,7 @@ int main(int argc, char **argv){ /*the main particle loop*/ particle=&Particle; int i; + srand(1234); for (i=0;i Date: Tue, 12 Jul 2022 13:50:35 +0200 Subject: [PATCH 1104/2654] test target result --- tests/regression_tests/source_mcpl_file/results_true.dat | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/results_true.dat diff --git a/tests/regression_tests/source_mcpl_file/results_true.dat b/tests/regression_tests/source_mcpl_file/results_true.dat new file mode 100644 index 000000000..f2209006a --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +3.017557E-01 3.398770E-03 From c21ff938c79bd905bb0f6e60c7abbf960b3d87f3 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 13:50:53 +0200 Subject: [PATCH 1105/2654] yet another necessary file --- tests/regression_tests/source_mcpl_file/settings.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/regression_tests/source_mcpl_file/settings.xml diff --git a/tests/regression_tests/source_mcpl_file/settings.xml b/tests/regression_tests/source_mcpl_file/settings.xml new file mode 100644 index 000000000..8b1510e0c --- /dev/null +++ b/tests/regression_tests/source_mcpl_file/settings.xml @@ -0,0 +1,11 @@ + + + + 10 + 5 + 1000 + + + source.10.mcpl + + From a123d239ddf016167cef9c99add91c5f665ac19c Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 12 Jul 2022 14:40:01 +0200 Subject: [PATCH 1106/2654] add a check that the test input got created as intended --- tests/regression_tests/source_mcpl_file/test.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 0adf67f1a..922ddddd3 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -15,6 +15,7 @@ class SourceMCPLFileTestHarness(TestHarness): """Run OpenMC with the appropriate arguments and check the outputs.""" try: self._create_input() + self._test_input_created() self._run_openmc() self._test_output_created() results = self._get_results() @@ -31,6 +32,7 @@ class SourceMCPLFileTestHarness(TestHarness): """Update the results_true using the current version of OpenMC.""" try: self._create_input() + self._test_input_created() self._run_openmc() self._test_output_created() results = self._get_results() @@ -39,6 +41,14 @@ class SourceMCPLFileTestHarness(TestHarness): finally: self._cleanup() + def _test_input_created(self): + """Check that the input mcpl.file was generated as it should""" + mcplfile=glob.glob(os.path.join(os.getcwd(),'source.10.mcpl')) + assert len(mcplfile) == 1, 'Either multiple or no mcpl files ' \ + 'exist.' + assert mcplfile[0].endswith('mcpl'), \ + 'output file does not end with mcpl.' + def _test_output_created(self): """Check that the output files were created""" statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) @@ -55,5 +65,5 @@ class SourceMCPLFileTestHarness(TestHarness): os.remove(f) def test_mcpl_source_file(): - harness = SourceMCPLFileTestHarness('statepoint.10.h5') + harness = SourceMCPLFileTestHarness('source.10.mcpl') harness.main() From 1509420c214275d2c27b458caefdfc943cd413de Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 10:25:55 +0200 Subject: [PATCH 1107/2654] fix bugs and finalize interface to MCPL --- include/openmc/source.h | 22 +++++++------ src/source.cpp | 73 +++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index 24a3d10ae..0c944aef9 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -14,6 +14,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { //============================================================================== @@ -110,6 +114,7 @@ private: vector sites_; //!< Source sites from a file }; +#ifdef OPENMC_MCPL //============================================================================== // MCPL-file input source //============================================================================== @@ -119,24 +124,21 @@ public: MCPLFileSource(std::string path); ~MCPLFileSource(); - // Properties - ParticleType particle_type() const { return particle_; } - + // Methods //! Sample from the external source distribution //! \param[inout] seed Pseudorandom seed pointer //! \return Site read from MCPL-file - SourceSite sample(uint64_t* seed) const override; + SourceSite sample(uint64_t* seed) const; private: - ParticleType particle_ {ParticleType::neutron}; //!< Type of particle emitted + SourceSite read_single_particle() const; + void read_source_bank(vector &sites_); + vector sites_; //! #endif @@ -382,6 +382,7 @@ CustomSourceWrapper::~CustomSourceWrapper() #endif } +#ifdef OPENMC_MCPL //=========================================================================== // Read particles from an MCPL-file //=========================================================================== @@ -397,54 +398,70 @@ MCPLFileSource::MCPLFileSource(std::string path) write_message(6, "Reading mcpl source file from {}",path); // Open the mcpl file - mcpl_file = mcpl_open(path.c_str); + mcpl_file = mcpl_open_file(path.c_str()); //do checks on the mcpl_file to see if particles are many enough. // should model this on the example source shown in the docs. - uint64_t nparticles=mcpl_hdr_nparticles(mcpl_file); + n_sites=mcpl_hdr_nparticles(mcpl_file); + read_source_bank(sites_); } -MCPLFileSource::~MCPLFilsSource(){ +MCPLFileSource::~MCPLFileSource(){ mcpl_close_file(mcpl_file); } -SourceSite MCPLFileSource::sample(uint64_t *seed){ - SourceSite omc_particle; - mcpl_particle *mcpl_particle; +SourceSite MCPLFileSource::sample(uint64_t* seed) const +{ + size_t i_site = sites_.size() * prn(seed); + return sites_[i_site]; +} + +void MCPLFileSource::read_source_bank(vector &sites_) +{ + sites_.resize(n_sites); + for (int i=0;ipdgcode!=2112 && mcpl_particle->pdgcode!=22 ) - { - mcpl_particle(mcpl_read(mcplfile); - //check for file exhaustion + mcpl_particle=mcpl_read(mcpl_file); + // check if it is a neutron or a photon. otherwise skip + while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { + mcpl_particle=mcpl_read(mcpl_file); + //should check for file exhaustion This could happen if particles are other than + //neutrons or photons } if(mcpl_particle->pdgcode==2112) { - omc_particle_=ParticleType::neutron; - } else if (mcpl_particle->pdgcode==22){ - omc_particle_=Particletype::photon; + omc_particle_.particle=ParticleType::neutron; + } else if (mcpl_particle->pdgcode==22) { + omc_particle_.particle=ParticleType::photon; } //particle is good, convert to openmc-formalism - omc_particle.r.x=mcpl_particle.x; - omc_particle.r.y=mcpl_particle.y; - omc_particle.r.z=mcpl_particle.z; + omc_particle_.r.x=mcpl_particle->position[0]; + omc_particle_.r.y=mcpl_particle->position[1]; + omc_particle_.r.z=mcpl_particle->position[2]; - omc_particle.u.x=mcpl_particle->direction[0]; - omc_particle.u.y=mcpl_particle->direction[1]; - omc_particle.u.z=mcpl_particle->direction[2]; + omc_particle_.u.x=mcpl_particle->direction[0]; + omc_particle_.u.y=mcpl_particle->direction[1]; + omc_particle_.u.z=mcpl_particle->direction[2]; //mcpl stores kinetic energy in MeV - omc_particle.E=mcpl_particle->ekin*1e6; + omc_particle_.E=mcpl_particle->ekin*1e6; //mcpl stores time in ms - omc_particle.t=mcpl_particle->time*1e-3; - omc_particle.wgt=mcpl_particle->weight; - omc_particle.delayed_group=0; - return omc_particle; + omc_particle_.time=mcpl_particle->time*1e-3; + omc_particle_.wgt=mcpl_particle->weight; + omc_particle_.delayed_group=0; + return omc_particle_; } - +#endif //OPENMC_MCPL //============================================================================== // Non-member functions From 2cbcd53f077b3afc7d01e0ebfe70ba1e0790fe39 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 10:26:24 +0200 Subject: [PATCH 1108/2654] add an option to turn on mcpl-support --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 521b46cfc..1408e85af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) option(OPENMC_USE_MPI "Enable MPI" OFF) +option(OPENMC_USE_MCPL "Enable MPCPL" OFF) # Warnings for deprecated options foreach(OLD_OPT IN ITEMS "openmp" "profile" "coverage" "dagmc" "libmesh") @@ -185,6 +186,10 @@ if(OPENMC_ENABLE_COVERAGE) list(APPEND ldflags --coverage) endif() +if(OPENMC_USE_MCPL) + list(APPEND ldflags -lmcpl) +endif() + # Show flags being used message(STATUS "OpenMC C++ flags: ${cxxflags}") message(STATUS "OpenMC Linker flags: ${ldflags}") @@ -439,6 +444,10 @@ endif() if (OPENMC_USE_MPI) target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) endif() +if(OPENMC_USE_MCPL) + target_compile_definitions(libopenmc PUBLIC -DOPENMC_MCPL) +endif() + # Set git SHA1 hash as a compile definition if(GIT_FOUND) From 46e648cf383df7b7b72b4f1f5c389f3c191c69a1 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 10:27:18 +0200 Subject: [PATCH 1109/2654] add a source type to the settings interface --- src/settings.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/settings.cpp b/src/settings.cpp index eb0d4936c..12e0a8050 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -430,6 +430,9 @@ void read_settings_xml() if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); model::external_sources.push_back(make_unique(path)); + } else if (check_for_node(node, "mcpl")) { + auto path = get_node_value(node, "mcpl", false, true); + model::external_sources.push_back(make_unique(path)); } else if (check_for_node(node, "library")) { // Get shared library path and parameters auto path = get_node_value(node, "library", false, true); From 96ae7b4228798549d1bb969777a73f926ba19465 Mon Sep 17 00:00:00 2001 From: erkn Date: Sat, 9 Jul 2022 16:31:00 +0200 Subject: [PATCH 1110/2654] fix misprints --- src/source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/source.cpp b/src/source.cpp index bdfe5349c..4b27bdc7e 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -392,7 +392,7 @@ MCPLFileSource::MCPLFileSource(std::string path) if (!file_exists(path)) { fatal_error(fmt::format("Source file '{}' does not exist.", path)); } - + // Read the source from a binary file instead of sampling from some // assumed source distribution write_message(6, "Reading mcpl source file from {}",path); From 2fa445193870a1bd6818fd82d1ea755e890c2309 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 12:13:10 +0200 Subject: [PATCH 1111/2654] only add mcpl-support if OPENMC_MCPL is defined --- src/settings.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/settings.cpp b/src/settings.cpp index 12e0a8050..d419cab06 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -430,9 +430,11 @@ void read_settings_xml() if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); model::external_sources.push_back(make_unique(path)); +#ifdef OPENMC_MCPL } else if (check_for_node(node, "mcpl")) { auto path = get_node_value(node, "mcpl", false, true); model::external_sources.push_back(make_unique(path)); +#endif } else if (check_for_node(node, "library")) { // Get shared library path and parameters auto path = get_node_value(node, "library", false, true); From 2773add0473f28d225c1ad9efbc6fcc9e97230ed Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 14:13:33 +0200 Subject: [PATCH 1112/2654] needed to avoid name clashes with other tests --- tests/regression_tests/source_mcpl_file/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/regression_tests/source_mcpl_file/__init__.py diff --git a/tests/regression_tests/source_mcpl_file/__init__.py b/tests/regression_tests/source_mcpl_file/__init__.py new file mode 100644 index 000000000..e69de29bb From bb8c022d77f8e22ad3d856edeb2b1a16a6311067 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 13 Jul 2022 20:55:53 +0200 Subject: [PATCH 1113/2654] fail without tripping the entire test-process --- tests/regression_tests/source_mcpl_file/test.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 922ddddd3..f55a76904 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -1,11 +1,6 @@ -import pathlib as pl import os -import shutil import subprocess -import textwrap import glob -import openmc -import pytest from tests.testing_harness import TestHarness @@ -25,7 +20,8 @@ class SourceMCPLFileTestHarness(TestHarness): self._cleanup() def _create_input(self): - subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) + compiled=subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) + assert compiled==0, 'Could not compile mcpl-file generator code' subprocess.run(['./gen_dummy_mcpl.out']) def update_results(self): From 2730f1954f154df24ed7171e9dda39e4325c1b2c Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 09:11:41 +0200 Subject: [PATCH 1114/2654] allow electrons and positrons as well --- src/source.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 4b27bdc7e..cfcd79e0a 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -429,19 +429,30 @@ SourceSite MCPLFileSource::read_single_particle() const { SourceSite omc_particle_; const mcpl_particle_t *mcpl_particle; - //extract particle from mcpl-file + // extract particle from mcpl-file mcpl_particle=mcpl_read(mcpl_file); - // check if it is a neutron or a photon. otherwise skip - while ( mcpl_particle->pdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { + // check if it is a neutron, photon, electron, or positron. Otherwise skip. + int pdg=mcpl_particle->pdgcode; + while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { mcpl_particle=mcpl_read(mcpl_file); - //should check for file exhaustion This could happen if particles are other than - //neutrons or photons + pdg=mcpl_particle->pdgcode; + //should check for file exhaustion. This could happen if particles are other than + //neutrons, photons, electrons, or positrons. } - if(mcpl_particle->pdgcode==2112) { - omc_particle_.particle=ParticleType::neutron; - } else if (mcpl_particle->pdgcode==22) { - omc_particle_.particle=ParticleType::photon; + switch(pdg){ + case 2112: + omc_particle_.particle=ParticleType::neutron; + break; + case 22: + omc_particle_.particle=ParticleType::photon; + break; + case 11: + omc_particle_.particle=ParticleType::electron; + break; + case -11: + omc_particle_.particle=ParticleType::positron; + break; } //particle is good, convert to openmc-formalism From 3b052f03cfce7605bf96641346800022e462a02a Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 09:12:01 +0200 Subject: [PATCH 1115/2654] expose a python function to check for mcpl --- openmc/lib/__init__.py | 3 +++ src/source.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/openmc/lib/__init__.py b/openmc/lib/__init__.py index c14b0d9c2..1e337fc07 100644 --- a/openmc/lib/__init__.py +++ b/openmc/lib/__init__.py @@ -48,6 +48,9 @@ def _coord_levels(): def _libmesh_enabled(): return c_bool.in_dll(_dll, "LIBMESH_ENABLED").value +def _mcpl_enabled(): + return c_bool.in_dll(_dll, "MCPL_ENABLED").value + from .error import * from .core import * from .nuclide import * diff --git a/src/source.cpp b/src/source.cpp index cfcd79e0a..dbfcd1ceb 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -43,6 +43,12 @@ namespace openmc { // Global variables //============================================================================== +#ifdef OPENMC_MCPL +const bool MCPL_ENABLED = true; +#else +const bool MCPL_ENABLED = false; +#endif + namespace model { vector> external_sources; From 5640bdb9eb25bc5675928490ef4bf925e9155ae1 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 15 Jul 2022 21:35:59 +0200 Subject: [PATCH 1116/2654] fix typo Co-authored-by: Paul Romano --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1408e85af..32beb41ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) option(OPENMC_USE_MPI "Enable MPI" OFF) -option(OPENMC_USE_MCPL "Enable MPCPL" OFF) +option(OPENMC_USE_MCPL "Enable MCPL" OFF) # Warnings for deprecated options foreach(OLD_OPT IN ITEMS "openmp" "profile" "coverage" "dagmc" "libmesh") From 95338eada002270c437906cb55607945dabe39b0 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 9 Aug 2022 08:12:19 +0200 Subject: [PATCH 1117/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- include/openmc/source.h | 30 +-------- src/settings.cpp | 2 +- src/source.cpp | 139 ++++++++++++++-------------------------- 3 files changed, 52 insertions(+), 119 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index 0c944aef9..bb7e2d55f 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -106,7 +106,9 @@ class FileSource : public Source { public: // Constructors explicit FileSource(std::string path); - +#ifdef OPENMC_MCPL + explicit FileSource(mcpl_file_t mcpl_file); +#endif // Methods SourceSite sample(uint64_t* seed) const override; @@ -114,32 +116,6 @@ private: vector sites_; //!< Source sites from a file }; -#ifdef OPENMC_MCPL -//============================================================================== -// MCPL-file input source -//============================================================================== -class MCPLFileSource : public Source { -public: - // Constructors, destructors - MCPLFileSource(std::string path); - ~MCPLFileSource(); - - // Methods - //! Sample from the external source distribution - //! \param[inout] seed Pseudorandom seed pointer - //! \return Site read from MCPL-file - SourceSite sample(uint64_t* seed) const; - -private: - SourceSite read_single_particle() const; - void read_source_bank(vector &sites_); - - vector sites_; //!(path)); + model::external_sources.push_back(make_unique(mcpl_open_file(path.c_str()))); #endif } else if (check_for_node(node, "library")) { // Get shared library path and parameters diff --git a/src/source.cpp b/src/source.cpp index dbfcd1ceb..e43f03929 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -329,6 +329,54 @@ FileSource::FileSource(std::string path) file_close(file_id); } +#ifdef OPENMC_MCPL +FileSource::FileSource(mcpl_file_t mcpl_file) +{ + //do checks on the mcpl_file to see if particles are many enough. + // should model this on the example source shown in the docs. + size_t n_sites=mcpl_hdr_nparticles(mcpl_file); + + sites_.resize(n_sites); + for (int i=0;ipdgcode!=2112 && mcpl_particle->pdgcode!=22 ) { + mcpl_particle=mcpl_read(mcpl_file); + //should check for file exhaustion This could happen if particles are other than + //neutrons or photons + } + + if(mcpl_particle->pdgcode==2112) { + site_.particle=ParticleType::neutron; + } else if (mcpl_particle->pdgcode==22) { + site_.particle=ParticleType::photon; + } + + //particle is good, convert to openmc-formalism + site_.r.x=mcpl_particle->position[0]; + site_.r.y=mcpl_particle->position[1]; + site_.r.z=mcpl_particle->position[2]; + + site_.u.x=mcpl_particle->direction[0]; + site_.u.y=mcpl_particle->direction[1]; + site_.u.z=mcpl_particle->direction[2]; + + //mcpl stores kinetic energy in MeV + site_.E=mcpl_particle->ekin*1e6; + //mcpl stores time in ms + site_.time=mcpl_particle->time*1e-3; + site_.wgt=mcpl_particle->weight; + site_.delayed_group=0; + sites_[i]=site_; + } + mcpl_close_file(mcpl_file); +} +#endif //OPENMC_MCPL + SourceSite FileSource::sample(uint64_t* seed) const { size_t i_site = sites_.size() * prn(seed); @@ -388,97 +436,6 @@ CustomSourceWrapper::~CustomSourceWrapper() #endif } -#ifdef OPENMC_MCPL -//=========================================================================== -// Read particles from an MCPL-file -//=========================================================================== -MCPLFileSource::MCPLFileSource(std::string path) -{ - // Check if source file exists - if (!file_exists(path)) { - fatal_error(fmt::format("Source file '{}' does not exist.", path)); - } - - // Read the source from a binary file instead of sampling from some - // assumed source distribution - write_message(6, "Reading mcpl source file from {}",path); - - // Open the mcpl file - mcpl_file = mcpl_open_file(path.c_str()); - - //do checks on the mcpl_file to see if particles are many enough. - // should model this on the example source shown in the docs. - n_sites=mcpl_hdr_nparticles(mcpl_file); - - read_source_bank(sites_); -} - -MCPLFileSource::~MCPLFileSource(){ - mcpl_close_file(mcpl_file); -} - -SourceSite MCPLFileSource::sample(uint64_t* seed) const -{ - size_t i_site = sites_.size() * prn(seed); - return sites_[i_site]; -} - -void MCPLFileSource::read_source_bank(vector &sites_) -{ - sites_.resize(n_sites); - for (int i=0;ipdgcode; - while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { - mcpl_particle=mcpl_read(mcpl_file); - pdg=mcpl_particle->pdgcode; - //should check for file exhaustion. This could happen if particles are other than - //neutrons, photons, electrons, or positrons. - } - - switch(pdg){ - case 2112: - omc_particle_.particle=ParticleType::neutron; - break; - case 22: - omc_particle_.particle=ParticleType::photon; - break; - case 11: - omc_particle_.particle=ParticleType::electron; - break; - case -11: - omc_particle_.particle=ParticleType::positron; - break; - } - - //particle is good, convert to openmc-formalism - omc_particle_.r.x=mcpl_particle->position[0]; - omc_particle_.r.y=mcpl_particle->position[1]; - omc_particle_.r.z=mcpl_particle->position[2]; - - omc_particle_.u.x=mcpl_particle->direction[0]; - omc_particle_.u.y=mcpl_particle->direction[1]; - omc_particle_.u.z=mcpl_particle->direction[2]; - - //mcpl stores kinetic energy in MeV - omc_particle_.E=mcpl_particle->ekin*1e6; - //mcpl stores time in ms - omc_particle_.time=mcpl_particle->time*1e-3; - omc_particle_.wgt=mcpl_particle->weight; - omc_particle_.delayed_group=0; - return omc_particle_; -} -#endif //OPENMC_MCPL //============================================================================== // Non-member functions From 5462216deba46d017db7905a312f0ed458cde6a7 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 1118/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- include/openmc/state_point.h | 9 +++ src/state_point.cpp | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 5ada2bf88..2d92c935a 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -9,6 +9,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { void load_state_point(); @@ -21,5 +25,10 @@ void write_tally_results_nr(hid_t file_id); void restart_set_keff(); void write_unstructured_mesh_results(); +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename_, bool surf_source_bank = false); +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); +#endif + } // namespace openmc #endif // OPENMC_STATE_POINT_H diff --git a/src/state_point.cpp b/src/state_point.cpp index 470dd7718..dfbd7f65c 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -28,6 +28,10 @@ #include "openmc/timer.h" #include "openmc/vector.h" +#ifdef OPENMC_MCPL +#include +#endif + namespace openmc { extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) @@ -599,6 +603,45 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } +void write_mcpl_point(const char *filename, bool surf_source_bank) +{ + std::string filename_; + if (filename) { + filename_ = filename; + } else { + // Determine width for zero padding + int w = std::to_string(settings::n_max_batches).size(); + + filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, + simulation::current_batch, w); + } + + mcpl_outfile_t file_id; + + std::string line; + if (mpi::master) { + // this must be rewritten: file_open is h5-specific + file_id = mcpl_create_outfile(filename_.c_str()); + //write_attribute(file_id, "filetype", "source"); + //write header stuff (oopy in xml-files as binary blobs for instance)) + if (VERSION_DEV){ + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}-development"); + } else { + line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}"); + } + mcpl_hdr_set_srcname(file_id,line.c_str()); + } + + write_mcpl_source_bank(file_id, surf_source_bank); + + if (mpi::master) { + //change this - this is h5 specific + mcpl_closeandgzip_outfile(file_id); + } + +} + + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); @@ -715,6 +758,88 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) +{ + int64_t dims_size = settings::n_particles; + int64_t count_size = simulation::work_per_rank; + + // Set vectors for source bank and starting bank index of each process + vector* bank_index = &simulation::work_index; + vector* source_bank = &simulation::source_bank; + vector surf_source_index_vector; + vector surf_source_bank_vector; + + if(surf_source_bank) { + surf_source_index_vector = calculate_surf_source_size(); + dims_size = surf_source_index_vector[mpi::n_procs]; + count_size = simulation::surf_source_bank.size(); + + bank_index = &surf_source_index_vector; + + // Copy data in a SharedArray into a vector. + surf_source_bank_vector.resize(count_size); + surf_source_bank_vector.assign(simulation::surf_source_bank.data(), + simulation::surf_source_bank.data() + count_size); + source_bank = &surf_source_bank_vector; + } + + if (mpi::master) { + //write particles from the master node + //loop over the other nodes and receive data - then write those. + for (int i = 0; i < mpi::n_procs; ++i) { +#ifdef OPENMC_MPI + if (i>0) + MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + mpi::intracomm, MPI_STATUS_IGNORE); +#endif + //now write the source_banke data again. + for (vector::iterator _site=source_bank->begin(); _site!=source_bank->end();_site++){ + //particle is now at the iterator + //write it to the mcpl-file + mcpl_particle_t p; + p.position[0]=_site->r.x; + p.position[1]=_site->r.y; + p.position[2]=_site->r.z; + + p.direction[0]=_site->u.x; + p.direction[1]=_site->u.y; + p.direction[2]=_site->u.x; + + //mcpl stores kinetic energy in MeV + p.ekin=_site->E*1e-6; + + p.time=_site->time*1e3; + + p.weight=_site->wgt; + + switch(_site->particle){ + case ParticleType::neutron: + p.pdgcode=2112; + break; + case ParticleType::photon: + p.pdgcode=22; + break; + case ParticleType::electron: + p.pdgcode=11; + break; + case ParticleType::positron: + p.pdgcode=-11; + break; + } + + mcpl_add_particle(file_id,&p); + } + } + } else { +#ifdef OPENMC_MPI + MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + mpi::intracomm); +#endif + } + +} + + // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) { From 1519f4f3e6acc5d91dbbb7c952589a2fe39e5537 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 23:06:19 +0200 Subject: [PATCH 1119/2654] add a trigger to simulation control --- src/simulation.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/simulation.cpp b/src/simulation.cpp index d7292cb9d..9c19c2106 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -407,6 +407,13 @@ void finalize_batch() auto filename = settings::path_output + "surface_source.h5"; write_source_point(filename.c_str(), true); } + + if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + auto filename = settings::path_output + ".mcpl"; + write_mcplt_source_point(filename.c_str(), true); + } + + } void initialize_generation() From f76e416ee64524ef06705db4f2fa306e4be472f1 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:56:36 +0200 Subject: [PATCH 1120/2654] use find_package instead - MCPL now supports this --- CMakeLists.txt | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32beb41ec..24018eb0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,6 +159,13 @@ if(${HDF5_VERSION} VERSION_GREATER_EQUAL 1.12.0) list(APPEND cxxflags -DH5Oget_info_by_idx_vers=1 -DH5O_info_t_vers=1) endif() +#=============================================================================== +# MCPL +#=============================================================================== +if (OPENMC_USE_MCPL) + find_package(MCPL REQUIRED) +endif() + #=============================================================================== # Set compile/link flags based on which compiler is being used #=============================================================================== @@ -186,10 +193,6 @@ if(OPENMC_ENABLE_COVERAGE) list(APPEND ldflags --coverage) endif() -if(OPENMC_USE_MCPL) - list(APPEND ldflags -lmcpl) -endif() - # Show flags being used message(STATUS "OpenMC C++ flags: ${cxxflags}") message(STATUS "OpenMC Linker flags: ${ldflags}") @@ -444,10 +447,6 @@ endif() if (OPENMC_USE_MPI) target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) endif() -if(OPENMC_USE_MCPL) - target_compile_definitions(libopenmc PUBLIC -DOPENMC_MCPL) -endif() - # Set git SHA1 hash as a compile definition if(GIT_FOUND) @@ -491,6 +490,11 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() +if (OPENMC_USE_MCPL) + target_compile_definitions(libopenmc PUBLIC OPENMC_MCPL) + target_link_libraries(libopenmc MCPL::mcpl) +endif() + #=============================================================================== # openmc executable #=============================================================================== From b6aa2dc429bf7545826991c426bf0843624c7377 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:59:02 +0200 Subject: [PATCH 1121/2654] add mcpl-output settings --- include/openmc/settings.h | 1 + src/settings.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 1e061b235..66825867d 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -48,6 +48,7 @@ extern bool source_latest; //!< write latest source at each batch? extern bool source_separate; //!< write source to separate file? extern bool source_write; //!< write source in HDF5 files? extern bool surf_source_write; //!< write surface source file? +extern bool surf_mcpl_write; //!< write surface mcpl file? extern bool surf_source_read; //!< read surface source file? extern bool survival_biasing; //!< use survival biasing? extern bool temperature_multipole; //!< use multipole data? diff --git a/src/settings.cpp b/src/settings.cpp index 11dd96e02..d1762596c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -61,6 +61,7 @@ bool source_latest {false}; bool source_separate {false}; bool source_write {true}; bool surf_source_write {false}; +bool surf_mcpl_write {false}; bool surf_source_read {false}; bool survival_biasing {false}; bool temperature_multipole {false}; @@ -682,9 +683,14 @@ void read_settings_xml() max_surface_particles = std::stoll(get_node_value(node_ssw, "max_particles")); } +#ifdef OPENMC_MCPL + if(check_for_node(node_ssw, "mcpl")){ + surf_mcpl_write=true; + } +#endif } - // If source is not seperate and is to be written out in the statepoint file, + // If source is not separate and is to be written out in the statepoint file, // make sure that the sourcepoint batch numbers are contained in the // statepoint list if (!source_separate) { From 22ce618601c8dbefd4759c51d50b7a17ba09dbba Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:59:28 +0200 Subject: [PATCH 1122/2654] fix typo --- src/simulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 9c19c2106..fcb115849 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -410,7 +410,7 @@ void finalize_batch() if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ auto filename = settings::path_output + ".mcpl"; - write_mcplt_source_point(filename.c_str(), true); + write_mcpl_source_point(filename.c_str(), true); } From 76e726b527c1b738b8b5842999e69ec4d6c4c57d Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 11:00:39 +0200 Subject: [PATCH 1123/2654] add cond. compilation guards for MCPL functions --- src/state_point.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index dfbd7f65c..14a541128 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -603,7 +603,8 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } -void write_mcpl_point(const char *filename, bool surf_source_bank) +#ifdef OPENMC_MCPL +void write_mcpl_source_point(const char *filename, bool surf_source_bank) { std::string filename_; if (filename) { @@ -640,7 +641,7 @@ void write_mcpl_point(const char *filename, bool surf_source_bank) } } - +#endif void write_source_bank(hid_t group_id, bool surf_source_bank) { @@ -758,6 +759,7 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } +#ifdef OPENMC_MCPL void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) { int64_t dims_size = settings::n_particles; @@ -838,7 +840,7 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) } } - +#endif // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) From bdc76d95fce06f3e94dea3afa9b8305309958179 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 16 Sep 2022 16:07:22 +0200 Subject: [PATCH 1124/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- src/source.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/source.cpp b/src/source.cpp index e43f03929..cf584e12e 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -437,6 +437,79 @@ CustomSourceWrapper::~CustomSourceWrapper() } +MCPLFileSource::~MCPLFileSource(){ + mcpl_close_file(mcpl_file); +} + +SourceSite MCPLFileSource::sample(uint64_t* seed) const +{ + size_t i_site = sites_.size() * prn(seed); + return sites_[i_site]; +} + +void MCPLFileSource::read_source_bank(vector &sites_) +{ + sites_.resize(n_sites); + for (int i=0;ipdgcode; + while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { + mcpl_particle=mcpl_read(mcpl_file); + pdg=mcpl_particle->pdgcode; + //should check for file exhaustion. This could happen if particles are other than + //neutrons, photons, electrons, or positrons. + } + + switch(pdg){ + case 2112: + omc_particle_.particle=ParticleType::neutron; + break; + case 22: + omc_particle_.particle=ParticleType::photon; + break; + case 11: + omc_particle_.particle=ParticleType::electron; + break; + case -11: + omc_particle_.particle=ParticleType::positron; + break; + } + + //particle is good, convert to openmc-formalism + omc_particle_.r.x=mcpl_particle->position[0]; + omc_particle_.r.y=mcpl_particle->position[1]; + omc_particle_.r.z=mcpl_particle->position[2]; + + omc_particle_.u.x=mcpl_particle->direction[0]; + omc_particle_.u.y=mcpl_particle->direction[1]; + omc_particle_.u.z=mcpl_particle->direction[2]; + + //mcpl stores kinetic energy in MeV + omc_particle_.E=mcpl_particle->ekin*1e6; + //mcpl stores time in ms + omc_particle_.time=mcpl_particle->time*1e-3; + omc_particle_.wgt=mcpl_particle->weight; + omc_particle_.delayed_group=0; + return omc_particle_; +} +#endif //OPENMC_MCPL +======= +>>>>>>> 380cfc150b449ef56debb5261caa010a52c42bdd +======= +#endif +>>>>>>> 71568d4f4 (refactor MCPL file read part of FileSource) +>>>>>>> 55f2be19e (refactor MCPL file read part of FileSource) + //============================================================================== // Non-member functions //============================================================================== From 6bceb7c30c05509823a7b0a6cb2e518d3a7ff5e4 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 1125/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- src/source.cpp | 6 ------ src/state_point.cpp | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index cf584e12e..99ec3a74d 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -503,12 +503,6 @@ SourceSite MCPLFileSource::read_single_particle() const return omc_particle_; } #endif //OPENMC_MCPL -======= ->>>>>>> 380cfc150b449ef56debb5261caa010a52c42bdd -======= -#endif ->>>>>>> 71568d4f4 (refactor MCPL file read part of FileSource) ->>>>>>> 55f2be19e (refactor MCPL file read part of FileSource) //============================================================================== // Non-member functions diff --git a/src/state_point.cpp b/src/state_point.cpp index 14a541128..1b133a121 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -643,6 +643,7 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) } #endif + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); From 56cddd25e2d8540da5356fbbe8f3bbde13ce11b5 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 4 Oct 2022 10:11:06 +0200 Subject: [PATCH 1126/2654] do not define these functions if no MCPL present --- src/state_point.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 1b133a121..14a541128 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -643,7 +643,6 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) } #endif - void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); From 3c33ec3b9fc513794e7e683620fbce99aedb9bcb Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 9 Aug 2022 08:12:19 +0200 Subject: [PATCH 1127/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- src/source.cpp | 67 -------------------------------------------------- 1 file changed, 67 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 99ec3a74d..e43f03929 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -437,73 +437,6 @@ CustomSourceWrapper::~CustomSourceWrapper() } -MCPLFileSource::~MCPLFileSource(){ - mcpl_close_file(mcpl_file); -} - -SourceSite MCPLFileSource::sample(uint64_t* seed) const -{ - size_t i_site = sites_.size() * prn(seed); - return sites_[i_site]; -} - -void MCPLFileSource::read_source_bank(vector &sites_) -{ - sites_.resize(n_sites); - for (int i=0;ipdgcode; - while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { - mcpl_particle=mcpl_read(mcpl_file); - pdg=mcpl_particle->pdgcode; - //should check for file exhaustion. This could happen if particles are other than - //neutrons, photons, electrons, or positrons. - } - - switch(pdg){ - case 2112: - omc_particle_.particle=ParticleType::neutron; - break; - case 22: - omc_particle_.particle=ParticleType::photon; - break; - case 11: - omc_particle_.particle=ParticleType::electron; - break; - case -11: - omc_particle_.particle=ParticleType::positron; - break; - } - - //particle is good, convert to openmc-formalism - omc_particle_.r.x=mcpl_particle->position[0]; - omc_particle_.r.y=mcpl_particle->position[1]; - omc_particle_.r.z=mcpl_particle->position[2]; - - omc_particle_.u.x=mcpl_particle->direction[0]; - omc_particle_.u.y=mcpl_particle->direction[1]; - omc_particle_.u.z=mcpl_particle->direction[2]; - - //mcpl stores kinetic energy in MeV - omc_particle_.E=mcpl_particle->ekin*1e6; - //mcpl stores time in ms - omc_particle_.time=mcpl_particle->time*1e-3; - omc_particle_.wgt=mcpl_particle->weight; - omc_particle_.delayed_group=0; - return omc_particle_; -} -#endif //OPENMC_MCPL - //============================================================================== // Non-member functions //============================================================================== From 52cf6823e6c1df7dbcc30b0c860412dc124a18a3 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 1128/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- src/state_point.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/state_point.cpp b/src/state_point.cpp index 14a541128..1b133a121 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -643,6 +643,7 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) } #endif + void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); From 9d7105ebc7ff43d973f55d59a815d62be0a8ba5b Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 6 Sep 2022 02:22:21 +0200 Subject: [PATCH 1129/2654] wip add MCPL-out to openmc code for writing a source_bank/point compiles but is untested --- src/state_point.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 1b133a121..c41c3dd53 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -603,6 +603,7 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } + #ifdef OPENMC_MCPL void write_mcpl_source_point(const char *filename, bool surf_source_bank) { @@ -641,8 +642,8 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) } } -#endif +#endif void write_source_bank(hid_t group_id, bool surf_source_bank) { From cd9eb5b1b237bbd420b7c2eef93023d3e1f1e20b Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Tue, 6 Sep 2022 23:06:19 +0200 Subject: [PATCH 1130/2654] add a trigger to simulation control --- src/simulation.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index fcb115849..7fda9d523 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -408,10 +408,10 @@ void finalize_batch() write_source_point(filename.c_str(), true); } - if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ - auto filename = settings::path_output + ".mcpl"; - write_mcpl_source_point(filename.c_str(), true); - } +if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + auto filename = settings::path_output + ".mcpl"; + write_mcpl_source_point(filename.c_str(), true); +} } From 8b783749341798cc9c8bc71d0ab374297824f1fc Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 10:59:28 +0200 Subject: [PATCH 1131/2654] fix typo --- src/simulation.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 7fda9d523..fcb115849 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -408,10 +408,10 @@ void finalize_batch() write_source_point(filename.c_str(), true); } -if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ - auto filename = settings::path_output + ".mcpl"; - write_mcpl_source_point(filename.c_str(), true); -} + if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + auto filename = settings::path_output + ".mcpl"; + write_mcpl_source_point(filename.c_str(), true); + } } From 172fec23568ae6793c2b23c1b54e02c6b01483d7 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 5 Oct 2022 11:00:39 +0200 Subject: [PATCH 1132/2654] add cond. compilation guards for MCPL functions --- src/state_point.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index c41c3dd53..14a541128 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -603,7 +603,6 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } - #ifdef OPENMC_MCPL void write_mcpl_source_point(const char *filename, bool surf_source_bank) { @@ -642,7 +641,6 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) } } - #endif void write_source_bank(hid_t group_id, bool surf_source_bank) From 9065bdac3aeafe0d411c2d4a26ef873e39cb4c40 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 16 Sep 2022 16:07:22 +0200 Subject: [PATCH 1133/2654] refactor MCPL file read part of FileSource A new constructor is added to FileSource that reads from a given MCPL-file. --- src/source.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/source.cpp b/src/source.cpp index e43f03929..3e1ddb3f3 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -436,7 +436,6 @@ CustomSourceWrapper::~CustomSourceWrapper() #endif } - //============================================================================== // Non-member functions //============================================================================== From 28cd0c5d3ae44a1ab3fe11f3ced08d6589530aa6 Mon Sep 17 00:00:00 2001 From: erkn Date: Wed, 5 Oct 2022 14:31:05 +0200 Subject: [PATCH 1134/2654] fix misnamed variable and remove accientally committed code --- src/source.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 3e1ddb3f3..d3037386b 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -350,10 +350,19 @@ FileSource::FileSource(mcpl_file_t mcpl_file) //neutrons or photons } - if(mcpl_particle->pdgcode==2112) { - site_.particle=ParticleType::neutron; - } else if (mcpl_particle->pdgcode==22) { - site_.particle=ParticleType::photon; + switch(pdg){ + case 2112: + site_.particle=ParticleType::neutron; + break; + case 22: + site_.particle=ParticleType::photon; + break; + case 11: + site_.particle=ParticleType::electron; + break; + case -11: + site_.particle=ParticleType::positron; + break; } //particle is good, convert to openmc-formalism From 6e523fa1f8ca0b6eef6a5e110fc7ceb86446d8f6 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 6 Oct 2022 01:33:21 +0200 Subject: [PATCH 1135/2654] must have a full filename --- src/simulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index fcb115849..82fce7c22 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -409,7 +409,7 @@ void finalize_batch() } if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ - auto filename = settings::path_output + ".mcpl"; + auto filename = settings::path_output + "surface_source.mcpl"; write_mcpl_source_point(filename.c_str(), true); } From 93a9270efcf0697db410c21d184b4e0d933da875 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 11 Oct 2022 00:46:32 +0200 Subject: [PATCH 1136/2654] fix malformed format string --- src/state_point.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 14a541128..acae2e8d0 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -626,9 +626,9 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) //write_attribute(file_id, "filetype", "source"); //write header stuff (oopy in xml-files as binary blobs for instance)) if (VERSION_DEV){ - line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}-development"); + line=fmt::format("OpenMC {0}.{1}.{2}-development",VERSION_MAJOR,VERSION_MINOR,VERSION_RELEASE); } else { - line=fmt::format("OpenMC {VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_RELEASE}"); + line=fmt::format("OpenMC {0}.{1}.{2}",VERSION_MAJOR,VERSION_MINOR,VERSION_RELEASE); } mcpl_hdr_set_srcname(file_id,line.c_str()); } From 59a949de362f5133c43971636bcb71a557ae03e0 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 11 Oct 2022 00:48:44 +0200 Subject: [PATCH 1137/2654] fix typo causing unit length errors --- src/state_point.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index acae2e8d0..fb915484b 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -803,9 +803,11 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) p.position[1]=_site->r.y; p.position[2]=_site->r.z; + //mcpl requires that the direction vector is unit length + //which is also the case in openmc p.direction[0]=_site->u.x; p.direction[1]=_site->u.y; - p.direction[2]=_site->u.x; + p.direction[2]=_site->u.z; //mcpl stores kinetic energy in MeV p.ekin=_site->E*1e-6; From 7759028d803d052f220abbc00a876a1c33b00949 Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 11 Oct 2022 02:00:33 +0200 Subject: [PATCH 1138/2654] enable mcpl surf_source_write in the python layer --- openmc/settings.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index ad5a9b28a..0937a3e48 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -171,6 +171,7 @@ class Settings: banked (int) :max_particles: Maximum number of particles to be banked on surfaces per process (int) + :mcpl: Output in the form of an MCPL-file (bool) survival_biasing : bool Indicate whether survival biasing is to be used tabular_legendre : dict @@ -652,7 +653,7 @@ class Settings: cv.check_type('surface source writing options', surf_source_write, Mapping) for key, value in surf_source_write.items(): cv.check_value('surface source writing key', key, - ('surface_ids', 'max_particles')) + ('surface_ids', 'max_particles', 'mcpl')) if key == 'surface_ids': cv.check_type('surface ids for source banking', value, Iterable, Integral) @@ -664,6 +665,9 @@ class Settings: value, Integral) cv.check_greater_than('maximum particle banks on surfaces per process', value, 0) + elif key == 'mcpl': + cv.check_type('write to an MCPL-format file', value, bool) + self._surf_source_write = surf_source_write @confidence_intervals.setter @@ -1032,6 +1036,9 @@ class Settings: if 'max_particles' in self._surf_source_write: subelement = ET.SubElement(element, "max_particles") subelement.text = str(self._surf_source_write['max_particles']) + if 'mcpl' in self._surf_source_write: + subelement = ET.SubElement(element, "mcpl") + subelement.text = str(self._surf_source_write['mcpl']).lower() def _create_confidence_intervals(self, root): if self._confidence_intervals is not None: From 94547f7c4b4128306a21a15d9adce1ac34d01c43 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 15:24:13 +0000 Subject: [PATCH 1139/2654] new type for centre_ --- include/openmc/mesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index ea6b01aa6..8fdf62ecb 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -359,7 +359,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - vector centre_; + array centre_; int set_grid(); From 15f45bcd1d7f6edf48c37213f0305803b41b584c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 15:29:10 +0000 Subject: [PATCH 1140/2654] substract before mapping --- src/mesh.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index c049549eb..36e4d5049 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -976,6 +976,11 @@ StructuredMesh::MeshIndex CylindricalMesh::get_indices( mapped_r[0] = std::hypot(r.x, r.y); mapped_r[2] = r[2]; + + mapped_r[0] += centre_[0]; + mapped_r[1] += centre_[1]; + mapped_r[2] += centre_[2]; + if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; } else { @@ -984,11 +989,6 @@ StructuredMesh::MeshIndex CylindricalMesh::get_indices( mapped_r[1] += 2 * M_PI; } - // TODO: pass centre as argument - mapped_r[0] += centre_[0]; - mapped_r[1] += centre_[1]; - mapped_r[2] += centre_[2]; - MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); idx[1] = sanitize_phi(idx[1]); @@ -1213,6 +1213,11 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( Position mapped_r; mapped_r[0] = r.norm(); + + mapped_r[0] += centre_[0]; + mapped_r[1] += centre_[1]; + mapped_r[2] += centre_[2]; + if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; mapped_r[2] = 0.0; @@ -1223,11 +1228,6 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( mapped_r[2] += 2 * M_PI; } - // TODO: pass centre as argument - mapped_r[0] += centre_[0]; - mapped_r[1] += centre_[1]; - mapped_r[2] += centre_[2]; - MeshIndex idx = StructuredMesh::get_indices(mapped_r, in_mesh); idx[1] = sanitize_theta(idx[1]); From 27e3bb427a3cf991dfa7f14680e8098835251443 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 15:36:58 +0000 Subject: [PATCH 1141/2654] array for origin CylindricalMesh --- include/openmc/mesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 8fdf62ecb..e6f5ce98b 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -415,7 +415,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - vector centre_; + array centre_; int set_grid(); From 76fbdf7fbf627a177017853583c378192912d6b4 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 15:41:38 +0000 Subject: [PATCH 1142/2654] centre to origin --- include/openmc/mesh.h | 4 ++-- openmc/mesh.py | 52 +++++++++++++++++++++---------------------- src/mesh.cpp | 16 ++++++------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index e6f5ce98b..9a0b5d5b8 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -359,7 +359,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - array centre_; + array origin; int set_grid(); @@ -415,7 +415,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - array centre_; + array origin_; int set_grid(); diff --git a/openmc/mesh.py b/openmc/mesh.py index f381d99b0..da00750c1 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1052,7 +1052,7 @@ class CylindricalMesh(StructuredMesh): self._r_grid = None self._phi_grid = [0.0, 2*pi] self._z_grid = None - self._centre = [0., 0., 0.] + self._origin = [0., 0., 0.] @property def dimension(self): @@ -1065,8 +1065,8 @@ class CylindricalMesh(StructuredMesh): return 3 @property - def centre(self): - return self._centre + def origin(self): + return self._origin @property def r_grid(self): @@ -1094,10 +1094,10 @@ class CylindricalMesh(StructuredMesh): for p in range(1, np + 1) for r in range(1, nr + 1)) - @centre.setter - def centre(self, coords): + @origin.setter + def origin(self, coords): cv.check_type('mesh r_grid', coords, Iterable, Real) - self._centre = np.asarray(coords) + self._origin = np.asarray(coords) @r_grid.setter def r_grid(self, grid): @@ -1240,8 +1240,8 @@ class CylindricalMesh(StructuredMesh): subelement = ET.SubElement(element, "z_grid") subelement.text = ' '.join(map(str, self.z_grid)) - subelement = ET.SubElement(element, "centre") - subelement.text = ' '.join(map(str, self.centre)) + subelement = ET.SubElement(element, "origin") + subelement.text = ' '.join(map(str, self.origin)) return element @@ -1266,7 +1266,7 @@ class CylindricalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] mesh.z_grid = [float(x) for x in get_text(elem, "z_grid").split()] - mesh.centre = [float(x) for x in get_text(elem, "centre").split()] + mesh.origin = [float(x) for x in get_text(elem, "origin").split()] return mesh @@ -1321,10 +1321,10 @@ class CylindricalMesh(StructuredMesh): pts_cartesian[:, 0] = r * np.cos(phi) pts_cartesian[:, 1] = r * np.sin(phi) - # offset with centre - pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.centre[0] - pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.centre[1] - pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.centre[2] + # offset with origin + pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] + pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] + pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] return super().write_data_to_vtk( points=pts_cartesian, @@ -1374,7 +1374,7 @@ class SphericalMesh(StructuredMesh): self._r_grid = None self._theta_grid = [0, pi] self._phi_grid = [0, 2*pi] - self._centre = [0., 0., 0.] + self._origin = [0., 0., 0.] @property def dimension(self): @@ -1387,8 +1387,8 @@ class SphericalMesh(StructuredMesh): return 3 @property - def centre(self): - return self._centre + def origin(self): + return self._origin @property def r_grid(self): @@ -1416,10 +1416,10 @@ class SphericalMesh(StructuredMesh): for t in range(1, nt + 1) for r in range(1, nr + 1)) - @centre.setter - def centre(self, coords): + @origin.setter + def origin(self, coords): cv.check_type('mesh r_grid', coords, Iterable, Real) - self._centre = np.asarray(coords) + self._origin = np.asarray(coords) @r_grid.setter def r_grid(self, grid): @@ -1492,8 +1492,8 @@ class SphericalMesh(StructuredMesh): subelement = ET.SubElement(element, "phi_grid") subelement.text = ' '.join(map(str, self.phi_grid)) - subelement = ET.SubElement(element, "centre") - subelement.text = ' '.join(map(str, self.centre)) + subelement = ET.SubElement(element, "origin") + subelement.text = ' '.join(map(str, self.origin)) return element @@ -1518,7 +1518,7 @@ class SphericalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.theta_grid = [float(x) for x in get_text(elem, "theta_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] - mesh.centre = [float(x) for x in get_text(elem, "centre").split()] + mesh.origin = [float(x) for x in get_text(elem, "origin").split()] return mesh @@ -1575,10 +1575,10 @@ class SphericalMesh(StructuredMesh): pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) pts_cartesian[:, 2] = r * np.cos(phi) - # offset with centre - pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.centre[0] - pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.centre[1] - pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.centre[2] + # offset with origin + pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] + pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] + pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] return super().write_data_to_vtk( points=pts_cartesian, diff --git a/src/mesh.cpp b/src/mesh.cpp index 36e4d5049..982b2e2dc 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -955,7 +955,7 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "phi_grid"); grid_[2] = get_node_array(node, "z_grid"); - centre_ = get_node_array(node, "centre"); + origin_ = get_node_array(node, "origin"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -977,9 +977,9 @@ StructuredMesh::MeshIndex CylindricalMesh::get_indices( mapped_r[0] = std::hypot(r.x, r.y); mapped_r[2] = r[2]; - mapped_r[0] += centre_[0]; - mapped_r[1] += centre_[1]; - mapped_r[2] += centre_[2]; + mapped_r[0] += origin_[0]; + mapped_r[1] += origin_[1]; + mapped_r[2] += origin_[2]; if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; @@ -1193,7 +1193,7 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "theta_grid"); grid_[2] = get_node_array(node, "phi_grid"); - centre_ = get_node_array(node, "centre"); + origin_ = get_node_array(node, "origin"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -1214,9 +1214,9 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( mapped_r[0] = r.norm(); - mapped_r[0] += centre_[0]; - mapped_r[1] += centre_[1]; - mapped_r[2] += centre_[2]; + mapped_r[0] += origin_[0]; + mapped_r[1] += origin_[1]; + mapped_r[2] += origin_[2]; if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; From b2d1729287c7174503c94e2b1cb5a39c2cb5a05e Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 16:08:03 +0000 Subject: [PATCH 1143/2654] origin_ instead of origin --- include/openmc/mesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 9a0b5d5b8..52f64701b 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -359,7 +359,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - array origin; + array origin_; int set_grid(); From adad6e7cd43a6d0a3e6ffd31f98bd7030158ee15 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 11 Oct 2022 11:21:31 -0500 Subject: [PATCH 1144/2654] Making origin type Positiong. Adding function to parse position from node. --- include/openmc/mesh.h | 5 ++--- include/openmc/xml_interface.h | 4 ++++ src/mesh.cpp | 4 ++-- src/xml_interface.cpp | 7 +++++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 9a0b5d5b8..c690dc4fe 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -359,8 +359,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - array origin; - + Position origin_; int set_grid(); @@ -415,7 +414,7 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - array origin_; + Position origin_; int set_grid(); diff --git a/include/openmc/xml_interface.h b/include/openmc/xml_interface.h index d96bb6cc2..bd6554c13 100644 --- a/include/openmc/xml_interface.h +++ b/include/openmc/xml_interface.h @@ -9,6 +9,7 @@ #include "xtensor/xadapt.hpp" #include "xtensor/xarray.hpp" +#include "openmc/position.h" #include "openmc/vector.h" namespace openmc { @@ -49,5 +50,8 @@ xt::xarray get_node_xarray( return xt::adapt(v, shape); } +Position get_node_position( + pugi::xml_node node, const char* name, bool lowercase = false); + } // namespace openmc #endif // OPENMC_XML_INTERFACE_H diff --git a/src/mesh.cpp b/src/mesh.cpp index 982b2e2dc..e9c185c8f 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -955,7 +955,7 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "phi_grid"); grid_[2] = get_node_array(node, "z_grid"); - origin_ = get_node_array(node, "origin"); + origin_ = get_node_position(node, "origin"); if (int err = set_grid()) { fatal_error(openmc_err_msg); @@ -1193,7 +1193,7 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} grid_[0] = get_node_array(node, "r_grid"); grid_[1] = get_node_array(node, "theta_grid"); grid_[2] = get_node_array(node, "phi_grid"); - origin_ = get_node_array(node, "origin"); + origin_ = get_node_position(node, "origin"); if (int err = set_grid()) { fatal_error(openmc_err_msg); diff --git a/src/xml_interface.cpp b/src/xml_interface.cpp index cf3b981e5..6ce465baf 100644 --- a/src/xml_interface.cpp +++ b/src/xml_interface.cpp @@ -48,4 +48,11 @@ bool get_node_value_bool(pugi::xml_node node, const char* name) return false; } +Position get_node_position( + pugi::xml_node node, const char* name, bool lowercase) +{ + vector arr = get_node_array(node, name, lowercase); + return Position(arr); +} + } // namespace openmc From a97b202c2d5113795ff39ab95827fd61ecf3ba7f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 16:41:43 +0000 Subject: [PATCH 1145/2654] updated to_hdf5 --- src/mesh.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mesh.cpp b/src/mesh.cpp index e9c185c8f..57fe49ba6 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1178,6 +1178,7 @@ void CylindricalMesh::to_hdf5(hid_t group) const write_dataset(mesh_group, "r_grid", grid_[0]); write_dataset(mesh_group, "phi_grid", grid_[1]); write_dataset(mesh_group, "z_grid", grid_[2]); + write_dataset(mesh_group, "origin", origin_); close_group(mesh_group); } @@ -1447,6 +1448,7 @@ void SphericalMesh::to_hdf5(hid_t group) const write_dataset(mesh_group, "r_grid", grid_[0]); write_dataset(mesh_group, "theta_grid", grid_[1]); write_dataset(mesh_group, "phi_grid", grid_[2]); + write_dataset(mesh_group, "origin", origin_); close_group(mesh_group); } From 3792c6fb70786638d39c88201fc248464c0bd905 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 17:11:54 +0000 Subject: [PATCH 1146/2654] fixed unit test --- tests/unit_tests/test_spherical_mesh.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index cdeb188ec..4d389a6bd 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -1,8 +1,8 @@ import openmc import numpy as np -def test_centre_read_write_to_xml(): - """Tests that the centre attribute can be written and read back to XML +def test_origin_read_write_to_xml(): + """Tests that the origin attribute can be written and read back to XML """ # build mesh = openmc.SphericalMesh() @@ -10,7 +10,7 @@ def test_centre_read_write_to_xml(): mesh.theta_grid = [1, 2, 3] mesh.r_grid = [1, 2, 3] - mesh.centre = [0.1, 0.2, 0.3] + mesh.origin = [0.1, 0.2, 0.3] tally = openmc.Tally() @@ -27,4 +27,4 @@ def test_centre_read_write_to_xml(): new_tallies = openmc.Tallies.from_xml() new_tally = new_tallies[0] new_mesh = new_tally.filters[0].mesh - assert np.allclose(new_mesh.centre, mesh.centre) \ No newline at end of file + assert np.allclose(new_mesh.origin, mesh.origin) \ No newline at end of file From 48d75accdd3d8ddd80e560c56b64a49e3c7b21dd Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 17:12:55 +0000 Subject: [PATCH 1147/2654] fixed cylindrical mesh test --- tests/unit_tests/test_cylindrical_mesh.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index 89322d704..952e8cf5a 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -1,8 +1,8 @@ import openmc import numpy as np -def test_centre_read_write_to_xml(): - """Tests that the centre attribute can be written and read back to XML +def test_origin_read_write_to_xml(): + """Tests that the origin attribute can be written and read back to XML """ # build mesh = openmc.CylindricalMesh() @@ -10,7 +10,7 @@ def test_centre_read_write_to_xml(): mesh.z_grid = [1, 2, 3] mesh.r_grid = [1, 2, 3] - mesh.centre = [0.1, 0.2, 0.3] + mesh.origin = [0.1, 0.2, 0.3] tally = openmc.Tally() @@ -27,4 +27,4 @@ def test_centre_read_write_to_xml(): new_tallies = openmc.Tallies.from_xml() new_tally = new_tallies[0] new_mesh = new_tally.filters[0].mesh - assert np.allclose(new_mesh.centre, mesh.centre) \ No newline at end of file + assert np.allclose(new_mesh.origin, mesh.origin) \ No newline at end of file From c6b89feaef6fc8093fc012e0a4a426541c7d434d Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 11 Oct 2022 17:14:21 +0000 Subject: [PATCH 1148/2654] fixed gold standard --- tests/regression_tests/filter_mesh/inputs_true.dat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/filter_mesh/inputs_true.dat b/tests/regression_tests/filter_mesh/inputs_true.dat index c42f3cd43..8b08a2a3c 100644 --- a/tests/regression_tests/filter_mesh/inputs_true.dat +++ b/tests/regression_tests/filter_mesh/inputs_true.dat @@ -57,13 +57,13 @@ 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 -7.5 -6.5625 -5.625 -4.6875 -3.75 -2.8125 -1.875 -0.9375 0.0 0.9375 1.875 2.8125 3.75 4.6875 5.625 6.5625 7.5 - 0.0 0.0 0.0 + 0.0 0.0 0.0 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 0.0 0.39269908169872414 0.7853981633974483 1.1780972450961724 1.5707963267948966 1.9634954084936207 2.356194490192345 2.748893571891069 3.141592653589793 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 - 0.0 0.0 0.0 + 0.0 0.0 0.0 1 From 444a80012bf6d246842f133a89943ccf1004fd87 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 11 Oct 2022 23:38:13 -0500 Subject: [PATCH 1149/2654] Naming tally in activation unit test --- tests/unit_tests/test_deplete_activation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 1842ad8ac..2dc911c86 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -33,7 +33,7 @@ def model(): ) model.settings.run_mode = 'fixed source' - rx_tally = openmc.Tally() + rx_tally = openmc.Tally(name='activation tally') rx_tally.scores = ['(n,gamma)'] model.tallies.append(rx_tally) @@ -53,7 +53,8 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts # Determine (n.gamma) reaction rate using initial run sp = model.run() with openmc.StatePoint(sp) as sp: - tally = sp.tallies[1] + print(sp.tallies) + tally = sp.get_tally(name='activation tally') capture_rate = tally.mean.flat[0] # Create one-nuclide depletion chain From e3f1bdaca1f5144563c4ceac45f10e4b0b5b7963 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 12 Oct 2022 19:30:38 +0200 Subject: [PATCH 1150/2654] enable mcpl from the python layer if the source filename ends with mcpl use that --- openmc/source.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/source.py b/openmc/source.py index 48e14f6f7..fdb2d5bc2 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -223,7 +223,10 @@ class Source: if self.particle != 'neutron': element.set("particle", self.particle) if self.file is not None: - element.set("file", self.file) + if (self.file.endswith('.mcpl')): + element.set("mcpl", self.file) + else: + element.set("file", self.file) if self.library is not None: element.set("library", self.library) if self.parameters is not None: From ca396268b586719df5638057b9161dbb2cdb048a Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 12 Oct 2022 19:32:09 +0200 Subject: [PATCH 1151/2654] protect against compilation wo mcpl --- src/simulation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 82fce7c22..d90c33ffd 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -407,12 +407,12 @@ void finalize_batch() auto filename = settings::path_output + "surface_source.h5"; write_source_point(filename.c_str(), true); } - +#ifdef OPENMC_MCPL if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ auto filename = settings::path_output + "surface_source.mcpl"; write_mcpl_source_point(filename.c_str(), true); } - +#endif } From 94fb5f8fa6818f88c9fcf9007535a80846cb6c2d Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 12 Oct 2022 19:32:40 +0200 Subject: [PATCH 1152/2654] enable MPI mpi-nodes are gathered sequentially (as for h5) --- src/state_point.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index fb915484b..983147c62 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -786,30 +786,40 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) } if (mpi::master) { - //write particles from the master node + // Particles are writeen to disk from the master node only + + // Save source bank sites since the array is overwritten below +#ifdef OPENMC_MPI + vector temp_source {source_bank->begin(), source_bank->end()}; +#endif + //loop over the other nodes and receive data - then write those. for (int i = 0; i < mpi::n_procs; ++i) { + // number of particles for node node i + size_t count[] { + static_cast((*bank_index)[i + 1] - (*bank_index)[i])}; + #ifdef OPENMC_MPI if (i>0) MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, mpi::intracomm, MPI_STATUS_IGNORE); #endif - //now write the source_banke data again. + // now write the source_bank data again. for (vector::iterator _site=source_bank->begin(); _site!=source_bank->end();_site++){ - //particle is now at the iterator - //write it to the mcpl-file + // particle is now at the iterator + // write it to the mcpl-file mcpl_particle_t p; p.position[0]=_site->r.x; p.position[1]=_site->r.y; p.position[2]=_site->r.z; - //mcpl requires that the direction vector is unit length - //which is also the case in openmc + // mcpl requires that the direction vector is unit length + // which is also the case in openmc p.direction[0]=_site->u.x; p.direction[1]=_site->u.y; p.direction[2]=_site->u.z; - //mcpl stores kinetic energy in MeV + // mcpl stores kinetic energy in MeV p.ekin=_site->E*1e-6; p.time=_site->time*1e3; @@ -834,6 +844,10 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) mcpl_add_particle(file_id,&p); } } +#ifdef OPENMC_MPI + // Restore state of source bank + std::copy(temp_source.begin(), temp_source.end(), source_bank->begin()); +#endif } else { #ifdef OPENMC_MPI MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, From b0a300aedcd453b46f530547afbb6280c4b564f0 Mon Sep 17 00:00:00 2001 From: josh Date: Thu, 13 Oct 2022 21:24:25 +0000 Subject: [PATCH 1153/2654] add to existing temp interp test, update doccs --- docs/source/io_formats/settings.rst | 8 +- tests/unit_tests/test_temp_interp.py | 121 ++++++++++++++++++++++++--- 2 files changed, 113 insertions(+), 16 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 7a794bf00..1a29e00ee 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -875,10 +875,10 @@ cell temperature is 340 K and the tolerance is 15 K, then the closest temperature in the range of 325 K to 355 K will be used to evaluate cross sections. If the ```` is "interpolation", the tolerance specified applies to cell temperatures outside of the data bounds. For example, -If a cell is specified at 695K, a tolerance of 15K and data only available at -700K and 1000K, the cell's cross sections will be evaluated at 700K, since -desired temperature of 695K is within the tolerance of the actual data despite -not being bounded on both sides. +if a cell is specified at 695K, a tolerance of 15K and data is only available +at 700K and 1000K, the cell's cross sections will be evaluated at 700K, since +the desired temperature of 695K is within the tolerance of the actual data +despite not being bounded on both sides. *Default*: 10 K diff --git a/tests/unit_tests/test_temp_interp.py b/tests/unit_tests/test_temp_interp.py index f87d52961..c64ebe46a 100644 --- a/tests/unit_tests/test_temp_interp.py +++ b/tests/unit_tests/test_temp_interp.py @@ -86,6 +86,70 @@ def make_fake_cross_section(): lib.export_to_xml('cross_sections_fake.xml') +def fake_thermal_scattering(): + """Create a fake thermal scattering library for U-235 at 294K and 600K + """ + fake_tsl = openmc.data.ThermalScattering("c_U_fake", 1.9968, 4.9, [0.0253]) + fake_tsl.nuclides = ['U235'] + + # Create elastic reaction + bragg_edges = [0.00370672, 0.00494229] + factors = [0.00375735, 0.01386287] + coherent_xs = openmc.data.CoherentElastic(bragg_edges, factors) + incoherent_xs_294 = openmc.data.Tabulated1D([0.00370672, 0.00370672], [0.00370672, 0.00370672]) + elastic_xs_base = openmc.data.Sum((coherent_xs, incoherent_xs_294)) + elastic_xs = {'294K': elastic_xs_base, '600K': elastic_xs_base} + coherent_dist = openmc.data.CoherentElasticAE(coherent_xs) + incoherent_dist_294 = openmc.data.IncoherentElasticAEDiscrete([ + [-0.6, -0.18, 0.18, 0.6], [-0.6, -0.18, 0.18, 0.6] + ]) + incoherent_dist_600 = openmc.data.IncoherentElasticAEDiscrete([ + [-0.1, -0.2, 0.2, 0.1], [-0.1, -0.2, 0.2, 0.1] + ]) + elastic_dist = { + '294K': openmc.data.MixedElasticAE(coherent_dist, incoherent_dist_294), + '600K': openmc.data.MixedElasticAE(coherent_dist, incoherent_dist_600) + } + fake_tsl.elastic = openmc.data.ThermalScatteringReaction(elastic_xs, elastic_dist) + + # Create inelastic reaction + inelastic_xs = { + '294K': openmc.data.Tabulated1D([1.0e-5, 4.9], [13.4, 3.35]), + '600K': openmc.data.Tabulated1D([1.0e-2, 10], [1.4, 5]) + } + breakpoints = [3] + interpolation = [2] + energy = [1.0e-5, 4.3e-2, 4.9] + energy_out = [ + openmc.data.Tabular([0.0002, 0.067, 0.146, 0.366], [0.25, 0.25, 0.25, 0.25]), + openmc.data.Tabular([0.0001, 0.009, 0.137, 0.277], [0.25, 0.25, 0.25, 0.25]), + openmc.data.Tabular([0.0579, 4.555, 4.803, 4.874], [0.25, 0.25, 0.25, 0.25]), + ] + for eout in energy_out: + eout.normalize() + eout.c = eout.cdf() + discrete = openmc.stats.Discrete([-0.9, -0.6, -0.3, -0.1, 0.1, 0.3, 0.6, 0.9], [1/8]*8) + discrete.c = discrete.cdf()[1:] + mu = [[discrete]*4]*3 + dist = openmc.data.IncoherentInelasticAE( + breakpoints, interpolation, energy, energy_out, mu) + inelastic_dist = {'294K': dist, '600K': dist} + inelastic = openmc.data.ThermalScatteringReaction(inelastic_xs, inelastic_dist) + fake_tsl.inelastic = inelastic + + return fake_tsl + + +def edit_fake_cross_sections(): + """Edit the test cross sections xml to include fake thermal scattering data + """ + lib = openmc.data.DataLibrary.from_xml("cross_sections_fake.xml") + c_U_fake = fake_thermal_scattering() + c_U_fake.export_to_hdf5("c_U_fake.h5") + lib.register_file("c_U_fake.h5") + lib.export_to_xml("cross_sections_fake.xml") + + @pytest.fixture(scope='module') def model(tmp_path_factory): tmp_path = tmp_path_factory.mktemp("temp_interp") @@ -119,21 +183,23 @@ def model(tmp_path_factory): @pytest.mark.parametrize( - ["method", "temperature", "fission_expected"], + ["method", "temperature", "fission_expected", "tolerance"], [ - ("nearest", 300.0, 0.5), - ("nearest", 600.0, 1.0), - ("nearest", 900.0, 0.5), - ("interpolation", 360.0, 0.6), - ("interpolation", 450.0, 0.75), - ("interpolation", 540.0, 0.9), - ("interpolation", 660.0, 0.9), - ("interpolation", 750.0, 0.75), - ("interpolation", 840.0, 0.6), + ("nearest", 300.0, 0.5, 10), + ("nearest", 600.0, 1.0, 10), + ("nearest", 900.0, 0.5, 10), + ("interpolation", 360.0, 0.6, 10), + ("interpolation", 450.0, 0.75, 10), + ("interpolation", 540.0, 0.9, 10), + ("interpolation", 660.0, 0.9, 10), + ("interpolation", 750.0, 0.75, 10), + ("interpolation", 840.0, 0.6, 10), + ("interpolation", 295.0, 0.5, 10), + ("interpolation", 990.0, 0.5, 100), ] ) -def test_interpolation(model, method, temperature, fission_expected): - model.settings.temperature = {'method': method, 'default': temperature} +def test_interpolation(model, method, temperature, fission_expected, tolerance): + model.settings.temperature = {'method': method, 'default': temperature, "tolerance": tolerance} sp_filename = model.run() with openmc.StatePoint(sp_filename) as sp: t = sp.tallies[model.tallies[0].id] @@ -152,3 +218,34 @@ def test_interpolation(model, method, temperature, fission_expected): assert k.n == pytest.approx(nu*fission_expected) else: assert abs(k.n - nu*fission_expected) <= 3*k.s + + +def test_temperature_interpolation_tolerance(model): + """Test applying global and cell temperatures with thermal scattering libraries + """ + edit_fake_cross_sections() + model.materials[0].add_s_alpha_beta("c_U_fake") + + # Default k-effective, using the thermal scattering data's minimum available temperature + model.settings.temperature = {'method': "nearest", 'default': 294, "tolerance": 50} + sp_filename = model.run() + with openmc.StatePoint(sp_filename) as sp: + default_k = sp.keff.n + + # Get k-effective with temperature below the minimum but in interpolation mode + model.settings.temperature = {'method': "interpolation", 'default': 255, "tolerance": 50} + sp_filename = model.run() + with openmc.StatePoint(sp_filename) as sp: + interpolated_k = sp.keff.n + + # Get the k-effective with the temperature applied to the cell, instead of globally + model.settings.temperature = {'method': "interpolation", 'default': 500, "tolerance": 50} + for cell in model.geometry.get_all_cells().values(): + cell.temperature = 275 + sp_filename = model.run() + with openmc.StatePoint(sp_filename) as sp: + cell_k = sp.keff.n + + # All calculated k-effectives should be equal + assert default_k == pytest.approx(interpolated_k) + assert interpolated_k == pytest.approx(cell_k) From 81fa3b45a35595f4913845d5cc1a4580e173d0d7 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 13 Oct 2022 23:09:12 +0200 Subject: [PATCH 1154/2654] mcpl-file output simimlar to regular source output file --- include/openmc/settings.h | 1 + src/settings.cpp | 1 + src/simulation.cpp | 14 ++++++++++++++ 3 files changed, 16 insertions(+) diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 66825867d..5b755784e 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -47,6 +47,7 @@ extern "C" bool run_CE; //!< run with continuous-energy data? extern bool source_latest; //!< write latest source at each batch? extern bool source_separate; //!< write source to separate file? extern bool source_write; //!< write source in HDF5 files? +extern bool source_mcpl_write; //!< write source in mcpl files? extern bool surf_source_write; //!< write surface source file? extern bool surf_mcpl_write; //!< write surface mcpl file? extern bool surf_source_read; //!< read surface source file? diff --git a/src/settings.cpp b/src/settings.cpp index d1762596c..7aed383da 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -60,6 +60,7 @@ bool run_CE {true}; bool source_latest {false}; bool source_separate {false}; bool source_write {true}; +bool source_mcpl_write {true}; bool surf_source_write {false}; bool surf_mcpl_write {false}; bool surf_source_read {false}; diff --git a/src/simulation.cpp b/src/simulation.cpp index d90c33ffd..70053a9a8 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -399,6 +399,20 @@ void finalize_batch() auto filename = settings::path_output + "source.h5"; write_source_point(filename.c_str()); } + +#ifdef OPENMC_MCPL + if (contains(settings::sourcepoint_batch, simulation::current_batch) && + settings::source_mcpl_write && settings::source_separate) { + write_mcpl_source_point(nullptr); + } + + // Write a continously-overwritten source point if requested. + if (settings::source_latest && setting::source_mcpl_write) { + auto filename = settings::path_output + "source.mcpl"; + write_mcpl_source_point(filename.c_str()); + } +#endif + } // Write out surface source if requested. From 5da08f6b0e1aa687b242bab32facdd5f29cf0d9d Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 14 Oct 2022 01:40:52 +0200 Subject: [PATCH 1155/2654] fix logic to avoid writing both kinds of source file --- src/settings.cpp | 3 +++ src/simulation.cpp | 43 +++++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 7aed383da..9098eb620 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -654,6 +654,9 @@ void read_settings_xml() if (check_for_node(node_sp, "write")) { source_write = get_node_value_bool(node_sp, "write"); } + if (check_for_node(node_sp, "mcpl")) { + source_write = get_node_value_bool(node_sp, "mcpl"); + } if (check_for_node(node_sp, "overwrite_latest")) { source_latest = get_node_value_bool(node_sp, "overwrite_latest"); source_separate = source_latest; diff --git a/src/simulation.cpp b/src/simulation.cpp index 70053a9a8..d7cc2237d 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -389,30 +389,33 @@ void finalize_batch() if (settings::run_mode == RunMode::EIGENVALUE) { // Write out a separate source point if it's been specified for this batch - if (contains(settings::sourcepoint_batch, simulation::current_batch) && - settings::source_write && settings::source_separate) { - write_source_point(nullptr); - } - - // Write a continously-overwritten source point if requested. - if (settings::source_latest) { - auto filename = settings::path_output + "source.h5"; - write_source_point(filename.c_str()); - } - #ifdef OPENMC_MCPL - if (contains(settings::sourcepoint_batch, simulation::current_batch) && - settings::source_mcpl_write && settings::source_separate) { - write_mcpl_source_point(nullptr); - } + if(! settings::source_mcpl_write) { +#endif + if (contains(settings::sourcepoint_batch, simulation::current_batch) && + settings::source_write && settings::source_separate) { + write_source_point(nullptr); + } - // Write a continously-overwritten source point if requested. - if (settings::source_latest && setting::source_mcpl_write) { - auto filename = settings::path_output + "source.mcpl"; - write_mcpl_source_point(filename.c_str()); + // Write a continously-overwritten source point if requested. + if (settings::source_latest) { + auto filename = settings::path_output + "source.h5"; + write_source_point(filename.c_str()); + } +#ifdef OPENMC_MCPL + } else { + if (contains(settings::sourcepoint_batch, simulation::current_batch) && + settings::source_mcpl_write && settings::source_separate) { + write_mcpl_source_point(nullptr); + } + + // Write a continously-overwritten source point if requested. + if (settings::source_latest && settings::source_mcpl_write) { + auto filename = settings::path_output + "source.mcpl"; + write_mcpl_source_point(filename.c_str()); + } } #endif - } // Write out surface source if requested. From 344efa8de6454998dd55d00d6f213946d266cadf Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 14 Oct 2022 01:41:21 +0200 Subject: [PATCH 1156/2654] don't compress by default --- src/state_point.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 983147c62..d0fe92bdf 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -637,7 +637,7 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) if (mpi::master) { //change this - this is h5 specific - mcpl_closeandgzip_outfile(file_id); + mcpl_close_outfile(file_id); } } From 04edce7dc29543fe4e8f730f9ee516ae87c61195 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 14 Oct 2022 01:41:44 +0200 Subject: [PATCH 1157/2654] do read and write regression test almost dientical to source_file reg. test --- .../source_mcpl_file/results_true.dat | 2 +- .../source_mcpl_file/settings.xml | 6 +- .../regression_tests/source_mcpl_file/test.py | 146 +++++++++++------- 3 files changed, 97 insertions(+), 57 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/results_true.dat b/tests/regression_tests/source_mcpl_file/results_true.dat index f2209006a..19460623f 100644 --- a/tests/regression_tests/source_mcpl_file/results_true.dat +++ b/tests/regression_tests/source_mcpl_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.017557E-01 3.398770E-03 +3.039964E-01 3.654869E-04 diff --git a/tests/regression_tests/source_mcpl_file/settings.xml b/tests/regression_tests/source_mcpl_file/settings.xml index 8b1510e0c..47b010bff 100644 --- a/tests/regression_tests/source_mcpl_file/settings.xml +++ b/tests/regression_tests/source_mcpl_file/settings.xml @@ -1,11 +1,15 @@ + + 10 5 1000 - source.10.mcpl + + -4 -4 -4 4 4 4 + diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index f55a76904..a005fc2d8 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -1,65 +1,101 @@ -import os -import subprocess +#!/usr/bin/env python + import glob +import os -from tests.testing_harness import TestHarness +from tests.testing_harness import * -class SourceMCPLFileTestHarness(TestHarness): - def execute_test(self): - """Run OpenMC with the appropriate arguments and check the outputs.""" - try: - self._create_input() - self._test_input_created() - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._compare_results() - finally: - self._cleanup() +settings1=""" + + + + + 10 + 5 + 1000 + + + + -4 -4 -4 4 4 4 + + + +""" - def _create_input(self): - compiled=subprocess.run(['gcc','-o','gen_dummy_mcpl.out','gen_dummy_mcpl.c','-lm','-lmcpl']) - assert compiled==0, 'Could not compile mcpl-file generator code' - subprocess.run(['./gen_dummy_mcpl.out']) +settings2 = """ + + + 10 + 5 + 1000 + + + source.10.{0} + + +""" - def update_results(self): - """Update the results_true using the current version of OpenMC.""" - try: - self._create_input() - self._test_input_created() - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._overwrite_results() - finally: - self._cleanup() - def _test_input_created(self): - """Check that the input mcpl.file was generated as it should""" - mcplfile=glob.glob(os.path.join(os.getcwd(),'source.10.mcpl')) - assert len(mcplfile) == 1, 'Either multiple or no mcpl files ' \ - 'exist.' - assert mcplfile[0].endswith('mcpl'), \ - 'output file does not end with mcpl.' +class SourceFileTestHarness(TestHarness): + def execute_test(self): + """Run OpenMC with the appropriate arguments and check the outputs.""" + try: + self._run_openmc() + self._test_output_created() + self._run_openmc_restart() + results = self._get_results() + self._write_results(results) + self._compare_results() + finally: + self._cleanup() - def _test_output_created(self): - """Check that the output files were created""" - statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) - assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ - 'exist.' - assert statepoint[0].endswith('h5'), \ - 'statepoint file does not end with h5.' + def update_results(self): + """Update the results_true using the current version of OpenMC.""" + try: + self._run_openmc() + self._test_output_created() + self._run_openmc_restart() + results = self._get_results() + self._write_results(results) + self._overwrite_results() + finally: + self._cleanup() - def _cleanup(self): - super()._cleanup() - source_mcpl=glob.glob(os.path.join(os.getcwd(),'source*.mcpl')) - for f in source_mcpl: - if (os.path.exists(f)): - os.remove(f) + def _test_output_created(self): + """Make sure statepoint and source files have been created.""" + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) + assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ + 'exist.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' -def test_mcpl_source_file(): - harness = SourceMCPLFileTestHarness('source.10.mcpl') - harness.main() + source = glob.glob(os.path.join(os.getcwd(), 'source.10.mcpl*')) + assert len(source) == 1, 'Either multiple or no source files exist.' + assert source[0].endswith('mcpl') or source[0].endswith('mcpl.gz'), \ + 'Source file is not a MCPL file.' + + def _run_openmc_restart(self): + # Get the name of the source file. + source = glob.glob(os.path.join(os.getcwd(), 'source.10.*')) + + # Write the new settings.xml file. + with open('settings.xml','w') as fh: + fh.write(settings2.format(source[0].split('.')[-1])) + + # Run OpenMC. + self._run_openmc() + + def _cleanup(self): + TestHarness._cleanup(self) + output = glob.glob(os.path.join(os.getcwd(), 'source.*')) + #for f in output: + # if os.path.exists(f): + # os.remove(f) + with open('settings.xml','w') as fh: + fh.write(settings1) + + +def test_source_file(): + harness = SourceFileTestHarness('statepoint.10.h5') + harness.main() From 7cb6883647b16227eb4bcdd26ab082734cca6459 Mon Sep 17 00:00:00 2001 From: josh Date: Sun, 16 Oct 2022 03:57:11 +0000 Subject: [PATCH 1158/2654] output bounding temp for cell temp out of bounds --- src/cell.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index d69f79a3e..30663e04d 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -334,12 +334,12 @@ double Cell::temperature(int32_t instance) const void Cell::set_temperature(double T, int32_t instance, bool set_contained) { if (settings::temperature_method == TemperatureMethod::INTERPOLATION) { - if (T < data::temperature_min - settings::temperature_tolerance) { - throw std::runtime_error {"Temperature is below minimum temperature at " - "which data is available."}; - } else if (T > data::temperature_max + settings::temperature_tolerance) { - throw std::runtime_error {"Temperature is above maximum temperature at " - "which data is available."}; + if (T < (data::temperature_min - settings::temperature_tolerance)) { + throw std::runtime_error {fmt::format("Temperature of {} K is below minimum temperature at " + "which data is available of {} K.", T, data::temperature_min)}; + } else if (T > (data::temperature_max + settings::temperature_tolerance)) { + throw std::runtime_error {fmt::format("Temperature of {} K is above maximum temperature at " + "which data is available of {} K.", T, data::temperature_max)}; } } From 6c4554f1c7df48659dfd1f056fe1d7104043e9f0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 16 Oct 2022 11:42:05 +0200 Subject: [PATCH 1159/2654] Add missing f prefix for an f-string --- openmc/data/decay.py | 4 +++- src/distribution.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index d7ededf33..bb27ccf4c 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -559,7 +559,9 @@ class Decay(EqualityMixin): raise NotImplementedError("Multiple interpolation regions: {name}, {particle}") interpolation = INTERPOLATION_SCHEME[f.interpolation[0]] if interpolation not in ('histogram', 'linear-linear'): - raise NotImplementedError("Continuous spectra with {interpolation} interpolation ({name}, {particle}) not supported") + raise NotImplementedError( + f"Continuous spectra with {interpolation} interpolation " + f"({name}, {particle}) not supported") intensity = spectra['continuous_normalization'].n rates = decay_constant * intensity * f.y diff --git a/src/distribution.cpp b/src/distribution.cpp index 6bf51df6a..fc0297fec 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -179,7 +179,7 @@ Tabular::Tabular(pugi::xml_node node) interp_ = Interpolation::lin_lin; } else { openmc::fatal_error( - "Unknown interpolation type for distribution: " + temp); + "Unsupported interpolation type for distribution: " + temp); } } else { interp_ = Interpolation::histogram; From 358e7b39181e8c6b51aad24a4d9a18e09119082b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 16 Oct 2022 12:19:12 +0200 Subject: [PATCH 1160/2654] Change assert_sample_mean to use 4sigma CI --- tests/unit_tests/test_stats.py | 78 +++++++++++++--------------------- 1 file changed, 29 insertions(+), 49 deletions(-) diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index e752c004f..378e1fc0b 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -7,9 +7,12 @@ import openmc.stats def assert_sample_mean(samples, expected_mean): - std_dev = samples.std() / np.sqrt(samples.size) - assert np.abs(expected_mean - samples.mean()) < 3*std_dev + # Calculate sample standard deviation + std_dev = samples.std() / np.sqrt(samples.size - 1) + # Means should agree within 4 sigma 99.993% of the time. Note that this is + # expected to fail about 1 out of 16,000 times + assert np.abs(expected_mean - samples.mean()) < 4*std_dev def test_discrete(): @@ -40,9 +43,9 @@ def test_discrete(): d3 = openmc.stats.Discrete(vals, probs) # sample discrete distribution and check that the mean of the samples is - # within 3 std. dev. of the expected mean + # within 4 std. dev. of the expected mean n_samples = 1_000_000 - samples = d3.sample(n_samples, seed=100) + samples = d3.sample(n_samples) assert_sample_mean(samples, exp_mean) @@ -86,11 +89,11 @@ def test_uniform(): np.testing.assert_array_equal(t.p, [1/(b-a), 1/(b-a)]) assert t.interpolation == 'histogram' - # Sample distribution and check that the mean of the samples is within 3 + # Sample distribution and check that the mean of the samples is within 4 # std. dev. of the expected mean exp_mean = 0.5 * (a + b) n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) + samples = d.sample(n_samples) assert_sample_mean(samples, exp_mean) @@ -105,12 +108,13 @@ def test_powerlaw(): assert d.n == n assert len(d) == 3 - exp_mean = 100.0 * (n+1) / (n+2) + # Determine mean of distribution + exp_mean = (n+1)*(b**(n+2) - a**(n+2))/((n+2)*(b**(n+1) - a**(n+1))) # sample power law distribution and check that the mean of the samples is - # within 3 std. dev. of the expected mean + # within 4 std. dev. of the expected mean n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) + samples = d.sample(n_samples) assert_sample_mean(samples, exp_mean) @@ -126,13 +130,13 @@ def test_maxwell(): exp_mean = 3/2 * theta # sample maxwell distribution and check that the mean of the samples is - # within 3 std. dev. of the expected mean + # within 4 std. dev. of the expected mean n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) + samples = d.sample(n_samples) assert_sample_mean(samples, exp_mean) - # A second sample with a different seed - samples_2 = d.sample(n_samples, seed=200) + # A second sample starting from a different seed + samples_2 = d.sample(n_samples) assert_sample_mean(samples_2, exp_mean) assert samples_2.mean() != samples.mean() @@ -154,9 +158,9 @@ def test_watt(): exp_mean = 3/2 * a + a**2 * b / 4 # sample Watt distribution and check that the mean of the samples is within - # 3 std. dev. of the expected mean + # 4 std. dev. of the expected mean n_samples = 1_000_000 - samples = d.sample(n_samples, seed=100) + samples = d.sample(n_samples) assert_sample_mean(samples, exp_mean) @@ -176,28 +180,16 @@ def test_tabular(): d = openmc.stats.Tabular(x, p) n_samples = 100_000 - samples = d.sample(n_samples, seed=100) - diff = np.abs(samples - d.mean()) - # within_1_sigma = np.count_nonzero(diff < samples.std()) - # assert within_1_sigma / n_samples >= 0.68 - within_2_sigma = np.count_nonzero(diff < 2*samples.std()) - assert within_2_sigma / n_samples >= 0.95 - within_3_sigma = np.count_nonzero(diff < 3*samples.std()) - assert within_3_sigma / n_samples >= 0.99 + samples = d.sample(n_samples) + assert_sample_mean(samples, d.mean()) # test histogram sampling d = openmc.stats.Tabular(x, p, interpolation='histogram') d.normalize() assert d.integral() == pytest.approx(1.0) - samples = d.sample(n_samples, seed=100) - diff = np.abs(samples - d.mean()) - # within_1_sigma = np.count_nonzero(diff < samples.std()) - # assert within_1_sigma / n_samples >= 0.68 - within_2_sigma = np.count_nonzero(diff < 2*samples.std()) - assert within_2_sigma / n_samples >= 0.95 - within_3_sigma = np.count_nonzero(diff < 3*samples.std()) - assert within_3_sigma / n_samples >= 0.99 + samples = d.sample(n_samples) + assert_sample_mean(samples, d.mean()) def test_legendre(): @@ -361,15 +353,9 @@ def test_normal(): assert len(d) == 2 # sample normal distribution - n_samples = 10000 - samples = d.sample(n_samples, seed=100) - samples = np.abs(samples - mean) - within_1_sigma = np.count_nonzero(samples < std_dev) - assert within_1_sigma / n_samples >= 0.68 - within_2_sigma = np.count_nonzero(samples < 2*std_dev) - assert within_2_sigma / n_samples >= 0.95 - within_3_sigma = np.count_nonzero(samples < 3*std_dev) - assert within_3_sigma / n_samples >= 0.99 + n_samples = 100_000 + samples = d.sample(n_samples) + assert_sample_mean(samples, mean) def test_muir(): @@ -386,15 +372,9 @@ def test_muir(): assert isinstance(d, openmc.stats.Normal) # sample muir distribution - n_samples = 10000 - samples = d.sample(n_samples, seed=100) - samples = np.abs(samples - mean) - within_1_sigma = np.count_nonzero(samples < d.std_dev) - assert within_1_sigma / n_samples >= 0.68 - within_2_sigma = np.count_nonzero(samples < 2*d.std_dev) - assert within_2_sigma / n_samples >= 0.95 - within_3_sigma = np.count_nonzero(samples < 3*d.std_dev) - assert within_3_sigma / n_samples >= 0.99 + n_samples = 100_000 + samples = d.sample(n_samples) + assert_sample_mean(samples, mean) def test_combine_distributions(): From de636b42a91c330311cc1474673f7fca5d8f3b42 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sun, 16 Oct 2022 13:14:46 +0100 Subject: [PATCH 1161/2654] py3.10 as main build matrix --- .github/workflows/ci.yml | 47 +++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a165998d4..e267c0d8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - python-version: [3.8] + python-version: ['3.10'] mpi: [n, y] omp: [n, y] dagmc: [n] @@ -34,38 +34,35 @@ jobs: vectfit: [n] include: - - python-version: 3.6 - omp: n - mpi: n - python-version: 3.7 omp: n mpi: n - - dagmc: y - python-version: 3.8 - mpi: y - omp: y - - libmesh: y - python-version: 3.8 - mpi: y - omp: y - - libmesh: y - python-version: 3.8 - mpi: n - omp: y - - event: y - python-version: 3.8 - omp: y - mpi: n - - vectfit: y - python-version: 3.8 + - python-version: 3.8 omp: n - mpi: y + mpi: n - python-version: 3.9 omp: n mpi: n - - python-version: '3.10' - omp: n + - dagmc: y + python-version: '3.10' + mpi: y + omp: y + - libmesh: y + python-version: '3.10' + mpi: y + omp: y + - libmesh: y + python-version: '3.10' mpi: n + omp: y + - event: y + python-version: '3.10' + omp: y + mpi: n + - vectfit: y + python-version: '3.10' + omp: n + mpi: y name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }}, mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }}, libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }} From 0587aeeaa4bf834e89eb9309c4729f315d001f03 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 18 Oct 2022 11:58:24 -0500 Subject: [PATCH 1162/2654] Allow EnergyFunctionFilter interpolation to be set from C API --- include/openmc/capi.h | 3 + include/openmc/tallies/filter_energyfunc.h | 6 +- openmc/lib/filter.py | 26 ++++- src/tallies/filter_energyfunc.cpp | 114 +++++++++++++++------ tests/unit_tests/test_lib.py | 5 + 5 files changed, 119 insertions(+), 35 deletions(-) diff --git a/include/openmc/capi.h b/include/openmc/capi.h index 29e900965..ce58bed12 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -38,6 +38,9 @@ int openmc_energyfunc_filter_get_energy( int openmc_energyfunc_filter_get_y(int32_t index, size_t* n, const double** y); int openmc_energyfunc_filter_set_data( int32_t index, size_t n, const double* energies, const double* y); +int openmc_energyfunc_filter_set_interpolation( + int32_t index, const char* interp); +int openmc_energyfunc_filter_get_interpolation(int32_t index, int* interp); int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_materials( diff --git a/include/openmc/tallies/filter_energyfunc.h b/include/openmc/tallies/filter_energyfunc.h index f650976ef..373fee8dd 100644 --- a/include/openmc/tallies/filter_energyfunc.h +++ b/include/openmc/tallies/filter_energyfunc.h @@ -40,8 +40,9 @@ public: const vector& energy() const { return energy_; } const vector& y() const { return y_; } - Interpolation interpolation_; + Interpolation interpolation() const { return interpolation_; } void set_data(gsl::span energy, gsl::span y); + void set_interpolation(const std::string& interpolation); private: //---------------------------------------------------------------------------- @@ -52,6 +53,9 @@ private: //! Interpolant values. vector y_; + + //! Interpolation scheme + Interpolation interpolation_ {Interpolation::lin_lin}; }; } // namespace openmc diff --git a/openmc/lib/filter.py b/openmc/lib/filter.py index 5d2231cc2..04da92459 100644 --- a/openmc/lib/filter.py +++ b/openmc/lib/filter.py @@ -7,6 +7,7 @@ import numpy as np from numpy.ctypeslib import as_array from openmc.exceptions import AllocationError, InvalidIDError +from openmc.data.function import INTERPOLATION_SCHEME from . import _dll from .core import _FortranObjectWithID from .error import _error_handler @@ -16,9 +17,9 @@ from .mesh import _get_mesh __all__ = [ 'Filter', 'AzimuthalFilter', 'CellFilter', 'CellbornFilter', 'CellfromFilter', - 'CellInstanceFilter', 'CollisionFilter', 'DistribcellFilter', 'DelayedGroupFilter', - 'EnergyFilter', 'EnergyoutFilter', 'EnergyFunctionFilter', 'LegendreFilter', - 'MaterialFilter', 'MeshFilter', 'MeshSurfaceFilter', 'MuFilter', 'ParticleFilter', + 'CellInstanceFilter', 'CollisionFilter', 'DistribcellFilter', 'DelayedGroupFilter', + 'EnergyFilter', 'EnergyoutFilter', 'EnergyFunctionFilter', 'LegendreFilter', + 'MaterialFilter', 'MeshFilter', 'MeshSurfaceFilter', 'MuFilter', 'ParticleFilter', 'PolarFilter', 'SphericalHarmonicsFilter', 'SpatialLegendreFilter', 'SurfaceFilter', 'UniverseFilter', 'ZernikeFilter', 'ZernikeRadialFilter', 'filters' ] @@ -47,6 +48,12 @@ _dll.openmc_energyfunc_filter_get_y.resttpe = c_int _dll.openmc_energyfunc_filter_get_y.errcheck = _error_handler _dll.openmc_energyfunc_filter_get_y.argtypes = [ c_int32, POINTER(c_size_t), POINTER(POINTER(c_double))] +_dll.openmc_energyfunc_filter_get_interpolation.resttpe = c_int +_dll.openmc_energyfunc_filter_get_interpolation.errcheck = _error_handler +_dll.openmc_energyfunc_filter_get_interpolation.argtypes = [c_int32, POINTER(c_int)] +_dll.openmc_energyfunc_filter_set_interpolation.resttpe = c_int +_dll.openmc_energyfunc_filter_set_interpolation.errcheck = _error_handler +_dll.openmc_energyfunc_filter_set_interpolation.argtypes = [c_int32, c_char_p] _dll.openmc_filter_get_id.argtypes = [c_int32, POINTER(c_int32)] _dll.openmc_filter_get_id.restype = c_int _dll.openmc_filter_get_id.errcheck = _error_handler @@ -247,6 +254,8 @@ class EnergyFunctionFilter(Filter): Independent variable for the interpolation y : numpy.ndarray Dependent variable for the interpolation + interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log', 'quadratic', 'cubic'} + Interpolation scheme """ energy_array = np.asarray(energy) y_array = np.asarray(y) @@ -264,6 +273,17 @@ class EnergyFunctionFilter(Filter): def y(self): return self._get_attr(_dll.openmc_energyfunc_filter_get_y) + @property + def interpolation(self) -> str: + interp = c_int() + _dll.openmc_energyfunc_filter_get_interpolation(self._index, interp) + return INTERPOLATION_SCHEME[interp.value] + + @interpolation.setter + def interpolation(self, interp: str): + interp_ptr = c_char_p(interp.encode()) + _dll.openmc_energyfunc_filter_set_interpolation(self._index, interp_ptr) + def _get_attr(self, cfunc): array_p = POINTER(c_double)() n = c_size_t() diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp index b961105a2..93ae24b2a 100644 --- a/src/tallies/filter_energyfunc.cpp +++ b/src/tallies/filter_energyfunc.cpp @@ -25,42 +25,14 @@ void EnergyFunctionFilter::from_xml(pugi::xml_node node) fatal_error("y values not specified for EnergyFunction filter."); auto y = get_node_array(node, "y"); + this->set_data(energy, y); // default to linear-linear interpolation interpolation_ = Interpolation::lin_lin; if (check_for_node(node, "interpolation")) { std::string interpolation = get_node_value(node, "interpolation"); - if (interpolation == "histogram") { - interpolation_ = Interpolation::histogram; - } else if (interpolation == "linear-linear") { - interpolation_ = Interpolation::lin_lin; - } else if (interpolation == "linear-log") { - interpolation_ = Interpolation::lin_log; - } else if (interpolation == "log-linear") { - interpolation_ = Interpolation::log_lin; - } else if (interpolation == "log-log") { - interpolation_ = Interpolation::log_log; - } else if (interpolation == "quadratic") { - if (energy.size() < 3) - fatal_error( - fmt::format("Quadratic interpolation on EnergyFunctionFilter {} " - "requires at least 3 data points.", - id())); - interpolation_ = Interpolation::quadratic; - } else if (interpolation == "cubic") { - if (energy.size() < 4) - fatal_error(fmt::format("Cubic interpolation on EnergyFunctionFilter " - "{} requires at least 4 data points.", - id())); - interpolation_ = Interpolation::cubic; - } else { - fatal_error(fmt::format( - "Found invalid interpolation type '{}' on EnergyFunctionFilter {}.", - interpolation, id())); - } + this->set_interpolation(interpolation); } - - this->set_data(energy, y); } void EnergyFunctionFilter::set_data( @@ -86,6 +58,38 @@ void EnergyFunctionFilter::set_data( } } +void EnergyFunctionFilter::set_interpolation(const std::string& interpolation) +{ + if (interpolation == "histogram") { + interpolation_ = Interpolation::histogram; + } else if (interpolation == "linear-linear") { + interpolation_ = Interpolation::lin_lin; + } else if (interpolation == "linear-log") { + interpolation_ = Interpolation::lin_log; + } else if (interpolation == "log-linear") { + interpolation_ = Interpolation::log_lin; + } else if (interpolation == "log-log") { + interpolation_ = Interpolation::log_log; + } else if (interpolation == "quadratic") { + if (energy_.size() < 3) + fatal_error( + fmt::format("Quadratic interpolation on EnergyFunctionFilter {} " + "requires at least 3 data points.", + this->id())); + interpolation_ = Interpolation::quadratic; + } else if (interpolation == "cubic") { + if (energy_.size() < 4) + fatal_error(fmt::format("Cubic interpolation on EnergyFunctionFilter " + "{} requires at least 4 data points.", + this->id())); + interpolation_ = Interpolation::cubic; + } else { + fatal_error(fmt::format( + "Found invalid interpolation type '{}' on EnergyFunctionFilter {}.", + interpolation, this->id())); + } +} + void EnergyFunctionFilter::get_all_bins( const Particle& p, TallyEstimator estimator, FilterMatch& match) const { @@ -105,7 +109,8 @@ void EnergyFunctionFilter::to_statepoint(hid_t filter_group) const write_dataset(filter_group, "energy", energy_); write_dataset(filter_group, "y", y_); hid_t y_dataset = open_dataset(filter_group, "y"); - write_attribute(y_dataset, "interpolation", static_cast(interpolation_)); + write_attribute( + y_dataset, "interpolation", static_cast(interpolation_)); close_dataset(y_dataset); } @@ -189,4 +194,51 @@ extern "C" int openmc_energyfunc_filter_get_y( return 0; } +extern "C" int openmc_energyfunc_filter_set_interpolation( + int32_t index, const char* interp) +{ + // ensure this is a valid index to allocated filter + if (int err = verify_filter(index)) + return err; + + // get a pointer to the filter + const auto& filt_base = model::tally_filters[index].get(); + // downcast to EnergyFunctionFilter + auto* filt = dynamic_cast(filt_base); + + // check if a valid filter was produced + if (!filt) { + set_errmsg( + "Tried to set interpolation data for non-energy function filter."); + return OPENMC_E_INVALID_TYPE; + } + + // Set interpolation + filt->set_interpolation(interp); + return 0; +} + +extern "C" int openmc_energyfunc_filter_get_interpolation( + int32_t index, int* interp) +{ + // ensure this is a valid index to allocated filter + if (int err = verify_filter(index)) + return err; + + // get a pointer to the filter + const auto& filt_base = model::tally_filters[index].get(); + // downcast to EnergyFunctionFilter + auto* filt = dynamic_cast(filt_base); + + // check if a valid filter was produced + if (!filt) { + set_errmsg( + "Tried to set interpolation data for non-energy function filter."); + return OPENMC_E_INVALID_TYPE; + } + + *interp = static_cast(filt->interpolation()); + return 0; +} + } // namespace openmc diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index 5063646f7..0633ceb18 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -283,6 +283,11 @@ def test_energy_function_filter(lib_init): assert len(efunc.y) == 2 assert (efunc.y == [0.0, 2.0]).all() + # Default should be lin-lin + assert efunc.interpolation == 'linear-linear' + efunc.interpolation = 'histogram' + assert efunc.interpolation == 'histogram' + def test_tally(lib_init): t = openmc.lib.tallies[1] From 2ae5ccb031c481d4e97c40c843186396c0fd8ffc Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 18 Oct 2022 12:02:02 -0500 Subject: [PATCH 1163/2654] Fix EnergyFunctionFilter.from_xml_element --- openmc/filter.py | 2 +- tests/unit_tests/test_filters.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index d83b9f6ba..d6571cd5a 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -2095,7 +2095,7 @@ class EnergyFunctionFilter(Filter): y = [float(x) for x in get_text(elem, 'y').split()] out = cls(energy, y, filter_id=filter_id) if elem.find('interpolation') is not None: - out.interpolation = elem.find('interpolation') + out.interpolation = elem.find('interpolation').text return out def can_merge(self, other): diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index a20b129e9..8a6f095ef 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -254,3 +254,18 @@ def test_lethargy_bin_width(): energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] assert f.lethargy_bin_width[0] == np.log10(energy_bins[1]/energy_bins[0]) assert f.lethargy_bin_width[-1] == np.log10(energy_bins[-1]/energy_bins[-2]) + + +def test_energyfunc(): + f = openmc.EnergyFunctionFilter( + [0.0, 10.0, 2.0e3, 1.0e6, 20.0e6], + [1.0, 0.9, 0.8, 0.7, 0.6], + 'histogram' + ) + + # Make sure XML roundtrip works + elem = f.to_xml_element() + new_f = openmc.EnergyFunctionFilter.from_xml_element(elem) + np.testing.assert_allclose(f.energy, new_f.energy) + np.testing.assert_allclose(f.y, new_f.y) + assert f.interpolation == new_f.interpolation From 1814f826c9ec1e621374457886ed7900d82b27ce Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 18 Oct 2022 12:02:22 -0500 Subject: [PATCH 1164/2654] Remove deprecated cylinder_from_points name in docs --- docs/source/pythonapi/model.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index 5dd3d3293..636935c6b 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -11,7 +11,6 @@ Convenience Functions :template: myfunction.rst openmc.model.borated_water - openmc.model.cylinder_from_points openmc.model.hexagonal_prism openmc.model.rectangular_prism openmc.model.subdivide From b7cbd59a13f36eae6fae7ce94fc41a5a2dd6c720 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 19 Oct 2022 13:02:07 -0500 Subject: [PATCH 1165/2654] Changing types to mitigate overflow problems --- src/volume_calc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/volume_calc.cpp b/src/volume_calc.cpp index 3ae98fdc3..002171d49 100644 --- a/src/volume_calc.cpp +++ b/src/volume_calc.cpp @@ -99,9 +99,9 @@ vector VolumeCalculation::execute() const { // Shared data that is collected from all threads int n = domain_ids_.size(); - vector> master_indices( + vector> master_indices( n); // List of material indices for each domain - vector> master_hits( + vector> master_hits( n); // Number of hits for each material in each domain int iterations = 0; @@ -281,7 +281,7 @@ vector VolumeCalculation::execute() const #endif if (mpi::master) { - int total_hits = 0; + size_t total_hits = 0; for (int j = 0; j < master_indices[i_domain].size(); ++j) { total_hits += master_hits[i_domain][j]; double f = From e64fb4cd41d059b56df055525b313ebf4a45fcd5 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 19 Oct 2022 14:16:52 -0400 Subject: [PATCH 1166/2654] added volume read and write to xml --- openmc/cell.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openmc/cell.py b/openmc/cell.py index 4b419e1c6..0cea73b32 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -634,6 +634,9 @@ class Cell(IDManagerMixin): if self.rotation is not None: element.set("rotation", ' '.join(map(str, self.rotation.ravel()))) + if self.volume is not None: + element.set("volume", str(self.volume)) + return element @classmethod @@ -687,6 +690,9 @@ class Cell(IDManagerMixin): c.temperature = [float(t_i) for t_i in t.split()] else: c.temperature = float(t) + v = get_text(elem, 'volume') + if v is not None: + c.volume = float(v) for key in ('temperature', 'rotation', 'translation'): value = get_text(elem, key) if value is not None: From 2a802a11a4dd7b08b15c0851927f9439c6faf892 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 19 Oct 2022 13:23:26 -0500 Subject: [PATCH 1167/2654] Add warning of possible overflow. --- include/openmc/constants.h | 5 +++++ src/volume_calc.cpp | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index fa2251b84..eadff1726 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -339,6 +339,11 @@ enum class RunMode { enum class GeometryType { CSG, DAG }; +//============================================================================== +// Volume Calculation Constants + +constexpr size_t SIZE_T_MAX {std::numeric_limits::max()}; + } // namespace openmc #endif // OPENMC_CONSTANTS_H diff --git a/src/volume_calc.cpp b/src/volume_calc.cpp index 002171d49..56134f367 100644 --- a/src/volume_calc.cpp +++ b/src/volume_calc.cpp @@ -225,6 +225,13 @@ vector VolumeCalculation::execute() const iterations++; size_t total_samples = iterations * n_samples_; + // warn user if total sample size is greater than what the size_t type can + // represent + if (total_samples > SIZE_T_MAX) { + warning("The number of samples has exceeded the size_t type. Volume " + "results may be inaccurate."); + } + // reset double trigger_val = -INFTY; From 1a67755f6aca5dac26dcc686c60c95b0809986e3 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 19 Oct 2022 14:27:18 -0400 Subject: [PATCH 1168/2654] update unit test --- tests/unit_tests/test_cell.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index faecf0b63..56e610e26 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -294,9 +294,11 @@ def test_to_xml_element(cell_with_lattice): c = cells[0] c.temperature = 900.0 + c.volume = 1.0 elem = c.create_xml_subelement(root) assert elem.get('region') == str(c.region) assert elem.get('temperature') == str(c.temperature) + assert elem.get('volume') == str(c.volume) @pytest.mark.parametrize("rotation", [ From f07b0295f9909c20c62c08b8046deb09db0f1e21 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 20 Oct 2022 12:12:36 -0400 Subject: [PATCH 1169/2654] buildinfo printed on -v flag --- CMakeLists.txt | 4 ++-- src/initialize.cpp | 3 --- src/output.cpp | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad1478de8..04c712a17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -489,10 +489,10 @@ target_compile_definitions(libopenmc PRIVATE BUILD_TYPE=${CMAKE_BUILD_TYPE}) target_compile_definitions(libopenmc PRIVATE COMPILER_ID=${CMAKE_CXX_COMPILER_ID}) target_compile_definitions(libopenmc PRIVATE COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}) if (OPENMC_ENABLE_PROFILE) - target_compile_definitions(libopenmc PRIVATE PROFILINGBUILD) + target_compile_definitions(libopenmc PRIVATE PROFILINGBUILD) endif() if (OPENMC_ENABLE_COVERAGE) - target_compile_definitions(libopenmc PRIVATE COVERAGEBUILD) + target_compile_definitions(libopenmc PRIVATE COVERAGEBUILD) endif() #=============================================================================== diff --git a/src/initialize.cpp b/src/initialize.cpp index e2503bc6e..aa353aa9c 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -260,9 +260,6 @@ int parse_command_line(int argc, char* argv[]) } else if (arg == "-v" || arg == "--version") { print_version(); - return OPENMC_E_UNASSIGNED; - - } else if (arg == "-b" || arg == "--build-info") { print_build_info(); return OPENMC_E_UNASSIGNED; diff --git a/src/output.cpp b/src/output.cpp index 5daf652dc..84e50462c 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -325,7 +325,6 @@ void print_usage() "max_tracks)\n" " -e, --event Run using event-based parallelism\n" " -v, --version Show version information\n" - " -b, --build-info Show compile options\n" " -h, --help Show this message\n"); } } From f58f4783751334ee35b6667c083f55e793d39250 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 20 Oct 2022 16:58:50 -0400 Subject: [PATCH 1170/2654] align spaces --- src/output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/output.cpp b/src/output.cpp index 84e50462c..59cb15712 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -396,7 +396,7 @@ void print_build_info() fmt::print("DAGMC support: {}\n", dagmc); fmt::print("libMesh support: {}\n", libmesh); fmt::print("Coverage testing: {}\n", coverage); - fmt::print("Profiling flags: {}\n", profiling); + fmt::print("Profiling flags: {}\n", profiling); } } From 06729507ce333ead873a78a3456d49bece14a4aa Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 20 Oct 2022 20:46:47 -0500 Subject: [PATCH 1171/2654] Moving to uint64_t and updating MPI types as requested by @paulromano --- include/openmc/constants.h | 3 ++- include/openmc/volume_calc.h | 7 +++++-- src/volume_calc.cpp | 38 +++++++++++++++++++----------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index eadff1726..8bb2cb1bf 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -5,6 +5,7 @@ #define OPENMC_CONSTANTS_H #include +#include #include #include "openmc/array.h" @@ -342,7 +343,7 @@ enum class GeometryType { CSG, DAG }; //============================================================================== // Volume Calculation Constants -constexpr size_t SIZE_T_MAX {std::numeric_limits::max()}; +constexpr uint64_t UINT64_T_MAX {std::numeric_limits::max()}; } // namespace openmc diff --git a/include/openmc/volume_calc.h b/include/openmc/volume_calc.h index db96f250f..2efd955f0 100644 --- a/include/openmc/volume_calc.h +++ b/include/openmc/volume_calc.h @@ -1,6 +1,9 @@ #ifndef OPENMC_VOLUME_CALC_H #define OPENMC_VOLUME_CALC_H +#include +#include + #include "openmc/array.h" #include "openmc/position.h" #include "openmc/tallies/trigger.h" @@ -10,7 +13,6 @@ #include "xtensor/xtensor.hpp" #include -#include namespace openmc { @@ -69,7 +71,8 @@ private: //! \param[in] i_material Index in global materials vector //! \param[in,out] indices Vector of material indices //! \param[in,out] hits Number of hits corresponding to each material - void check_hit(int i_material, vector& indices, vector& hits) const; + void check_hit( + int i_material, vector& indices, vector& hits) const; }; //============================================================================== diff --git a/src/volume_calc.cpp b/src/volume_calc.cpp index 56134f367..126edd927 100644 --- a/src/volume_calc.cpp +++ b/src/volume_calc.cpp @@ -99,16 +99,16 @@ vector VolumeCalculation::execute() const { // Shared data that is collected from all threads int n = domain_ids_.size(); - vector> master_indices( + vector> master_indices( n); // List of material indices for each domain - vector> master_hits( + vector> master_hits( n); // Number of hits for each material in each domain int iterations = 0; // Divide work over MPI processes - size_t min_samples = n_samples_ / mpi::n_procs; - size_t remainder = n_samples_ % mpi::n_procs; - size_t i_start, i_end; + uint64_t min_samples = n_samples_ / mpi::n_procs; + uint64_t remainder = n_samples_ % mpi::n_procs; + uint64_t i_start, i_end; if (mpi::rank < remainder) { i_start = (min_samples + 1) * mpi::rank; i_end = i_start + min_samples + 1; @@ -123,14 +123,14 @@ vector VolumeCalculation::execute() const #pragma omp parallel { // Variables that are private to each thread - vector> indices(n); - vector> hits(n); + vector> indices(n); + vector> hits(n); Particle p; // Sample locations and count hits #pragma omp for for (size_t i = i_start; i < i_end; i++) { - int64_t id = iterations * n_samples_ + i; + uint64_t id = iterations * n_samples_ + i; uint64_t seed = init_seed(id, STREAM_VOLUME); p.n_coord() = 1; @@ -223,12 +223,13 @@ vector VolumeCalculation::execute() const // bump iteration counter and get total number // of samples at this point iterations++; - size_t total_samples = iterations * n_samples_; + uint64_t total_samples = iterations * n_samples_; // warn user if total sample size is greater than what the size_t type can // represent - if (total_samples > SIZE_T_MAX) { - warning("The number of samples has exceeded the size_t type. Volume " + if (total_samples > UINT64_T_MAX) { + warning("The number of samples has exceeded the type used to track hits. " + "Volume " "results may be inaccurate."); } @@ -253,10 +254,11 @@ vector VolumeCalculation::execute() const if (mpi::master) { for (int j = 1; j < mpi::n_procs; j++) { int q; + // retrieve results MPI_Recv( - &q, 1, MPI_INTEGER, j, 2 * j, mpi::intracomm, MPI_STATUS_IGNORE); - vector buffer(2 * q); - MPI_Recv(buffer.data(), 2 * q, MPI_INTEGER, j, 2 * j + 1, + &q, 1, MPI_UINT64_T, j, 2 * j, mpi::intracomm, MPI_STATUS_IGNORE); + vector buffer(2 * q); + MPI_Recv(buffer.data(), 2 * q, MPI_UINT64_T, j, 2 * j + 1, mpi::intracomm, MPI_STATUS_IGNORE); for (int k = 0; k < q; ++k) { bool already_added = false; @@ -275,14 +277,14 @@ vector VolumeCalculation::execute() const } } else { int q = master_indices[i_domain].size(); - vector buffer(2 * q); + vector buffer(2 * q); for (int k = 0; k < q; ++k) { buffer[2 * k] = master_indices[i_domain][k]; buffer[2 * k + 1] = master_hits[i_domain][k]; } - MPI_Send(&q, 1, MPI_INTEGER, 0, 2 * mpi::rank, mpi::intracomm); - MPI_Send(buffer.data(), 2 * q, MPI_INTEGER, 0, 2 * mpi::rank + 1, + MPI_Send(&q, 1, MPI_UINT64_T, 0, 2 * mpi::rank, mpi::intracomm); + MPI_Send(buffer.data(), 2 * q, MPI_UINT64_T, 0, 2 * mpi::rank + 1, mpi::intracomm); } #endif @@ -471,7 +473,7 @@ void VolumeCalculation::to_hdf5( } void VolumeCalculation::check_hit( - int i_material, vector& indices, vector& hits) const + int i_material, vector& indices, vector& hits) const { // Check if this material was previously hit and if so, increment count From 93065d188bdffe09138b6ecc34c686ae4d52432d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 20 Oct 2022 20:54:43 -0500 Subject: [PATCH 1172/2654] Fixing sign for uint max comparison --- src/volume_calc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/volume_calc.cpp b/src/volume_calc.cpp index 126edd927..e36b88904 100644 --- a/src/volume_calc.cpp +++ b/src/volume_calc.cpp @@ -227,7 +227,7 @@ vector VolumeCalculation::execute() const // warn user if total sample size is greater than what the size_t type can // represent - if (total_samples > UINT64_T_MAX) { + if (total_samples == UINT64_T_MAX) { warning("The number of samples has exceeded the type used to track hits. " "Volume " "results may be inaccurate."); From 0e0cd0a22d059159a8799906f57d12cec99c1a89 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Mon, 13 Sep 2021 01:25:36 -0300 Subject: [PATCH 1173/2654] Added hooks for NCrystal --- CMakeLists.txt | 16 +++++++++ include/openmc/material.h | 8 +++++ include/openmc/particle_data.h | 3 ++ include/openmc/physics.h | 27 ++++++++++++++++ include/openmc/settings.h | 3 ++ openmc/material.py | 59 ++++++++++++++++++++++++++++++++++ src/material.cpp | 36 ++++++++++++++++++++- src/physics.cpp | 21 +++++++++++- src/settings.cpp | 4 +++ 9 files changed, 175 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 521b46cfc..7be54dc3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF) option(OPENMC_USE_MPI "Enable MPI" OFF) +option(OPENMC_USE_NCRYSTAL "Enable support for NCrystal scattering" OFF) # Warnings for deprecated options foreach(OLD_OPT IN ITEMS "openmp" "profile" "coverage" "dagmc" "libmesh") @@ -98,6 +99,14 @@ macro(find_package_write_status pkg) endif() endmacro() +#=============================================================================== +# NCrystal Scattering Support +#=============================================================================== + +if(OPENMC_USE_NCRYSTAL) + find_package(NCrystal REQUIRED PATH_SUFFIXES ./)#fixme +endif() + #=============================================================================== # DAGMC Geometry Support - need DAGMC/MOAB #=============================================================================== @@ -482,6 +491,13 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() +if(OPENMC_USE_NCRYSTAL) + target_compile_definitions(libopenmc PRIVATE NCRYSTAL) + target_link_libraries(libopenmc NCrystal::NCrystal) +endif() + + + #=============================================================================== # openmc executable #=============================================================================== diff --git a/include/openmc/material.h b/include/openmc/material.h index b251a3ca8..55f8ae20d 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -15,6 +15,10 @@ #include "openmc/particle.h" #include "openmc/vector.h" +#ifdef NCRYSTAL +#include "NCrystal/NCrystal.hh" +#endif + namespace openmc { //============================================================================== @@ -157,6 +161,10 @@ public: std::string name_; //!< Name of material vector nuclide_; //!< Indices in nuclides vector vector element_; //!< Indices in elements vector +#ifdef NCRYSTAL + std::string cfg_; //!< NCrystal configuration string + std::shared_ptr m_NCrystal_mat_; +#endif xt::xtensor atom_density_; //!< Nuclide atom density in [atom/b-cm] double density_; //!< Total atom density in [atom/b-cm] double density_gpcc_; //!< Total atom density in [g/cm^3] diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index d3d00571a..06ca5990a 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -162,6 +162,9 @@ struct MacroXS { double fission; //!< macroscopic fission xs double nu_fission; //!< macroscopic production xs double photon_prod; //!< macroscopic photon production xs +#ifdef NCRYSTAL + double NCrystal_XS; //!< macroscopic cross section of processes handled by NCrystal +#endif // Photon cross sections double coherent; //!< macroscopic coherent xs diff --git a/include/openmc/physics.h b/include/openmc/physics.h index 262b3a884..a1db07291 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -8,6 +8,10 @@ #include "openmc/reaction.h" #include "openmc/vector.h" +#ifdef NCRYSTAL +#include "NCrystal/NCRNG.hh" +#endif + namespace openmc { //============================================================================== @@ -101,6 +105,29 @@ void sample_secondary_photons(Particle& p, int i_nuclide); //! \param[in] p, particle to be split or rouletted with the weight window. void split_particle(Particle& p); +#ifdef NCRYSTAL +//============================================================================== +// NCrystal wrapper class for the OpenMC random number generator +//============================================================================== + +class NcrystalRNG_Wrapper : public NCrystal::RNGStream { + uint64_t* openmc_seed_; +public: + constexpr NcrystalRNG_Wrapper(uint64_t* s) noexcept : openmc_seed_(s) {} + //Can be cheaply created on the stack just before being used in calls to + //ProcImpl::Scatter objects, like: + // + // RNG_Wrapper rng(seed); + // +protected: + //double actualGenerate() override { return prn(openmc_seed_); } + double actualGenerate() override { + return std::max( std::numeric_limits::min(), prn(openmc_seed_) ); + } + +}; +#endif + } // namespace openmc #endif // OPENMC_PHYSICS_H diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 1e061b235..ba1a30e30 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -120,6 +120,9 @@ extern int trigger_batch_interval; //!< Batch interval for triggers extern "C" int verbosity; //!< How verbose to make output extern double weight_cutoff; //!< Weight cutoff for Russian roulette extern double weight_survive; //!< Survival weight after Russian roulette +#ifdef NCRYSTAL +extern double ncrystal_max_energy; // Energy in eV to switch between NCrystal and ENDF +#endif } // namespace settings //============================================================================== diff --git a/openmc/material.py b/openmc/material.py index e99eec52c..1fe62961d 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -118,6 +118,7 @@ class Material(IDManagerMixin): self._volume = None self._atoms = {} self._isotropic = [] + self._NCrystal_cfg = None # A list of tuples (nuclide, percent, percent type) self._nuclides = [] @@ -140,6 +141,8 @@ class Material(IDManagerMixin): string += '{: <16}\n'.format('\tS(a,b) Tables') + string += '{: <16}=\t{}\n'.format('\tNCrystal conf', self._NCrystal_cfg) + for sab in self._sab: string += '{: <16}=\t{}\n'.format('\tS(a,b)', sab) @@ -331,6 +334,48 @@ class Material(IDManagerMixin): return material + @classmethod + def from_NCrystal(cls, cfg): + """Create material from NCrystal configuration string + Density is set from the NCrystal value, + and material temperature from the configuration string. + + Parameters + ---------- + cfg : str + NCrystal configuration string + + Returns + ------- + openmc.Material + Material instance + + """ + + try: + import NCrystal + except ImportError: + raise SystemExit("ERROR: NCrystal Python module is required.") + + NC_mat = NCrystal.createInfo(cfg) + NC_comp = NC_mat.getComposition() + + # Create the Material + material = cls() + + for frac, atom in NC_comp: + if (atom.A() == 0): + material.add_element(atom.displayLabel(), frac, 'ao') + else: + material.add_nuclide(atom.displayLabel(), frac, 'ao') + + material._NCrystal_cfg = cfg + material._density_units = "g/cm3" + material._density = NC_mat.getDensity() + material.temperature = NC_mat.getTemperature() + + return material + def add_volume_information(self, volume_calc): """Add volume information to a material. @@ -405,6 +450,9 @@ class Material(IDManagerMixin): 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) + if self._NCrystal_cfg is not None: + raise ValueError("Cannot add nuclides to NCrystal material") + # If nuclide name doesn't look valid, give a warning try: Z, _, _ = openmc.data.zam(nuclide) @@ -609,6 +657,9 @@ class Material(IDManagerMixin): raise ValueError("Element name should be given by the " "element's symbol or name, e.g., 'Zr', 'zirconium'") + if self._NCrystal_cfg is not None: + raise ValueError("Cannot add elements to NCrystal material") + # Allow for element identifier to be given as a symbol or name if len(element) > 2: el = element.lower() @@ -1135,6 +1186,14 @@ class Material(IDManagerMixin): if self._volume: element.set("volume", str(self._volume)) + if self._NCrystal_cfg: + if self._sab: + raise ValueError("NCrystal materials are not compatible with S(a,b).") + if self._macroscopic is not None: + raise ValueError("NCrystal materials are not compatible macroscopic cross sections.") + + element.set("cfg", str(self._NCrystal_cfg)) + # Create temperature XML subelement if self.temperature is not None: element.set("temperature", str(self.temperature)) diff --git a/src/material.cpp b/src/material.cpp index 30dfa5ed5..d7fae8361 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -60,6 +60,14 @@ Material::Material(pugi::xml_node node) name_ = get_node_value(node, "name"); } +#ifdef NCRYSTAL + if (check_for_node(node, "cfg")) { + cfg_ = get_node_value(node, "cfg"); + write_message(5, "NCrystal config string: >>{}<< ", cfg_); + m_NCrystal_mat_ = NCrystal::FactImpl::createScatter(cfg_); + } +#endif + if (check_for_node(node, "depletable")) { depletable_ = get_node_value_bool(node, "depletable"); } @@ -792,6 +800,17 @@ void Material::calculate_neutron_xs(Particle& p) const // Initialize position in i_sab_nuclides int j = 0; +#ifdef NCRYSTAL + double ncrystal_xs = -1; + + if (m_NCrystal_mat_ != nullptr && p.E() < settings::ncrystal_max_energy){ + // Calculate scattering XS per atom with NCrystal, only once per material + NCrystal::CachePtr dummyCache; + auto nc_energy = NCrystal::NeutronEnergy{p.E()}; + ncrystal_xs = m_NCrystal_mat_->crossSection( dummyCache, nc_energy, {p.u().x, p.u().y, p.u().z}).get(); + } +#endif + // Add contribution from each nuclide in material for (int i = 0; i < nuclide_.size(); ++i) { // ====================================================================== @@ -830,10 +849,25 @@ void Material::calculate_neutron_xs(Particle& p) const int i_nuclide = nuclide_[i]; // Calculate microscopic cross section for this nuclide - const auto& micro {p.neutron_xs(i_nuclide)}; +#ifndef NCRYSTAL + const +#endif + auto& micro {p.neutron_xs(i_nuclide)}; if (p.E() != micro.last_E || p.sqrtkT() != micro.last_sqrtkT || i_sab != micro.index_sab || sab_frac != micro.sab_frac) { data::nuclides[i_nuclide]->calculate_xs(i_sab, i_grid, sab_frac, p); +#ifdef NCRYSTAL + if (ncrystal_xs >= 0.0){ + if ( micro.thermal > 0 || micro.thermal_elastic > 0) { + fatal_error("S(a,b) treatment and NCrystal are not compatible."); + } + data::nuclides[i_nuclide]->calculate_elastic_xs(p); + // remove free atom cross section + // and replace it by scattering cross section per atom from NCrystal + micro.total = micro.total - micro.elastic + ncrystal_xs; + micro.elastic = ncrystal_xs; + } +#endif } // ====================================================================== diff --git a/src/physics.cpp b/src/physics.cpp index bcdcf7ecf..9eff4aed7 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -140,8 +140,27 @@ void sample_neutron_reaction(Particle& p) // Sample a scattering reaction and determine the secondary energy of the // exiting neutron - scatter(p, i_nuclide); +#ifdef NCRYSTAL + if (model::materials[p.material_]->m_NCrystal_mat_ != nullptr && p.E() < settings::ncrystal_max_energy){ + + NcrystalRNG_Wrapper rng(p.current_seed()); // Initialize RNG + //create a cache pointer for multi thread physics + NCrystal::CachePtr dummyCache;//fixme: avoid recreating here (triggers malloc) + auto nc_energy = NCrystal::NeutronEnergy{p.E()}; + auto outcome = model::materials[p.material_]->m_NCrystal_mat_->sampleScatter( dummyCache, rng , nc_energy, {p.u().x, p.u().y, p.u().z}); + p.E_last() = p.E(); + p.E() = outcome.ekin.get(); + Direction u_old {p.u()}; + p.u() = Direction(outcome.direction[0], outcome.direction[1], outcome.direction[2]); + p.mu_ = u_old.dot(p.u()); + p.event_mt_ = ELASTIC;//fixme: define a new label for NCrystal? + } else { + scatter(p, i_nuclide); + } +#else + scatter(p, i_nuclide); +#endif // Advance URR seed stream 'N' times after energy changes if (p.E() != p.E_last()) { p.stream() = STREAM_URR_PTABLE; diff --git a/src/settings.cpp b/src/settings.cpp index eb0d4936c..3f3e97054 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -118,6 +118,10 @@ int verbosity {7}; double weight_cutoff {0.25}; double weight_survive {1.0}; +#ifdef NCRYSTAL +double ncrystal_max_energy{5.0}; +#endif + } // namespace settings //============================================================================== From 0f33e0b11c6add029f354eb3e5c89b002eec7500 Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Tue, 13 Sep 2022 14:22:04 +0200 Subject: [PATCH 1174/2654] Add temporary requirement of natural elements in NCrystal materials --- openmc/material.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 1fe62961d..0a293eb0f 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -364,10 +364,9 @@ class Material(IDManagerMixin): material = cls() for frac, atom in NC_comp: - if (atom.A() == 0): - material.add_element(atom.displayLabel(), frac, 'ao') - else: - material.add_nuclide(atom.displayLabel(), frac, 'ao') + if not atom.isNaturalElement(): + raise ValueError('NCrystal-OpenMC interface only works with natural elements for now.') + material.add_element(atom.elementName(), frac, 'ao') material._NCrystal_cfg = cfg material._density_units = "g/cm3" From 9c54ac0b6b53336f834b5f868aa85e3e140239f8 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Tue, 13 Sep 2022 16:07:50 +0200 Subject: [PATCH 1175/2654] Fix access to private attributes --- include/openmc/material.h | 6 ++++++ src/physics.cpp | 9 ++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/openmc/material.h b/include/openmc/material.h index 55f8ae20d..eef557088 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -155,6 +155,12 @@ public: //! \return Temperature in [K] double temperature() const; +#ifdef NCRYSTAL + //! Gwet pointer to NCrystal material object + //! \return Pointer to NCrystal material object + std::shared_ptr m_NCrystal_mat() const {return m_NCrystal_mat_}; +#endif + //---------------------------------------------------------------------------- // Data int32_t id_ {C_NONE}; //!< Unique ID diff --git a/src/physics.cpp b/src/physics.cpp index 9eff4aed7..948307521 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -142,19 +142,18 @@ void sample_neutron_reaction(Particle& p) // exiting neutron #ifdef NCRYSTAL - if (model::materials[p.material_]->m_NCrystal_mat_ != nullptr && p.E() < settings::ncrystal_max_energy){ - + if (model::materials[p.material()]->m_NCrystal_mat() != nullptr && p.E() < settings::ncrystal_max_energy){ NcrystalRNG_Wrapper rng(p.current_seed()); // Initialize RNG //create a cache pointer for multi thread physics NCrystal::CachePtr dummyCache;//fixme: avoid recreating here (triggers malloc) auto nc_energy = NCrystal::NeutronEnergy{p.E()}; - auto outcome = model::materials[p.material_]->m_NCrystal_mat_->sampleScatter( dummyCache, rng , nc_energy, {p.u().x, p.u().y, p.u().z}); + auto outcome = model::materials[p.material()]->m_NCrystal_mat()->sampleScatter( dummyCache, rng , nc_energy, {p.u().x, p.u().y, p.u().z}); p.E_last() = p.E(); p.E() = outcome.ekin.get(); Direction u_old {p.u()}; p.u() = Direction(outcome.direction[0], outcome.direction[1], outcome.direction[2]); - p.mu_ = u_old.dot(p.u()); - p.event_mt_ = ELASTIC;//fixme: define a new label for NCrystal? + p.mu() = u_old.dot(p.u()); + p.event_mt() = ELASTIC;//fixme: define a new label for NCrystal? } else { scatter(p, i_nuclide); } From 70d5c76ebd70cf43349423f17028c3cb1dfe1daa Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Tue, 13 Sep 2022 16:10:05 +0200 Subject: [PATCH 1176/2654] Fixed material.h --- include/openmc/material.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/material.h b/include/openmc/material.h index eef557088..10e64773e 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -158,7 +158,7 @@ public: #ifdef NCRYSTAL //! Gwet pointer to NCrystal material object //! \return Pointer to NCrystal material object - std::shared_ptr m_NCrystal_mat() const {return m_NCrystal_mat_}; + std::shared_ptr m_NCrystal_mat() const {return m_NCrystal_mat_; }; #endif //---------------------------------------------------------------------------- From 29a10eafd3db601ffa9a7e7bf882431c150ee1b2 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Fri, 16 Sep 2022 09:03:09 -0300 Subject: [PATCH 1177/2654] Removed MacroNCrystalXS This was left from a previous implementation. Now it is not needed because NCrystal just takes over all neutron scattering events below a given energy threshold. --- include/openmc/particle_data.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 06ca5990a..d3d00571a 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -162,9 +162,6 @@ struct MacroXS { double fission; //!< macroscopic fission xs double nu_fission; //!< macroscopic production xs double photon_prod; //!< macroscopic photon production xs -#ifdef NCRYSTAL - double NCrystal_XS; //!< macroscopic cross section of processes handled by NCrystal -#endif // Photon cross sections double coherent; //!< macroscopic coherent xs From 2e19260dea9176f03f2d5d80be19c8c819d339d3 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Mon, 26 Sep 2022 11:19:54 +0200 Subject: [PATCH 1178/2654] Implement recommended changes --- CMakeLists.txt | 2 +- include/openmc/material.h | 8 ++++---- include/openmc/physics.h | 10 ++-------- openmc/material.py | 31 ++++++++++++++----------------- src/material.cpp | 16 +++++++++------- src/physics.cpp | 10 +++++----- 6 files changed, 35 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7be54dc3e..7080accfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ endmacro() #=============================================================================== if(OPENMC_USE_NCRYSTAL) - find_package(NCrystal REQUIRED PATH_SUFFIXES ./)#fixme + find_package(NCrystal REQUIRED) endif() #=============================================================================== diff --git a/include/openmc/material.h b/include/openmc/material.h index 10e64773e..30d8ffb7d 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -156,9 +156,9 @@ public: double temperature() const; #ifdef NCRYSTAL - //! Gwet pointer to NCrystal material object + //! Get pointer to NCrystal material object //! \return Pointer to NCrystal material object - std::shared_ptr m_NCrystal_mat() const {return m_NCrystal_mat_; }; + std::shared_ptr ncrystal_mat() const {return ncrystal_mat_; }; #endif //---------------------------------------------------------------------------- @@ -168,8 +168,8 @@ public: vector nuclide_; //!< Indices in nuclides vector vector element_; //!< Indices in elements vector #ifdef NCRYSTAL - std::string cfg_; //!< NCrystal configuration string - std::shared_ptr m_NCrystal_mat_; + std::string ncrystal_cfg_; //!< NCrystal configuration string + std::shared_ptr ncrystal_mat_; #endif xt::xtensor atom_density_; //!< Nuclide atom density in [atom/b-cm] double density_; //!< Total atom density in [atom/b-cm] diff --git a/include/openmc/physics.h b/include/openmc/physics.h index a1db07291..109f7caff 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -110,17 +110,11 @@ void split_particle(Particle& p); // NCrystal wrapper class for the OpenMC random number generator //============================================================================== -class NcrystalRNG_Wrapper : public NCrystal::RNGStream { +class NCrystalRNGWrapper : public NCrystal::RNGStream { uint64_t* openmc_seed_; public: - constexpr NcrystalRNG_Wrapper(uint64_t* s) noexcept : openmc_seed_(s) {} - //Can be cheaply created on the stack just before being used in calls to - //ProcImpl::Scatter objects, like: - // - // RNG_Wrapper rng(seed); - // + constexpr NCrystalRNGWrapper(uint64_t* seed) noexcept : openmc_seed_(seed) {} protected: - //double actualGenerate() override { return prn(openmc_seed_); } double actualGenerate() override { return std::max( std::numeric_limits::min(), prn(openmc_seed_) ); } diff --git a/openmc/material.py b/openmc/material.py index 0a293eb0f..15d1f8ac9 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -118,7 +118,7 @@ class Material(IDManagerMixin): self._volume = None self._atoms = {} self._isotropic = [] - self._NCrystal_cfg = None + self._ncrystal_cfg = None # A list of tuples (nuclide, percent, percent type) self._nuclides = [] @@ -141,7 +141,7 @@ class Material(IDManagerMixin): string += '{: <16}\n'.format('\tS(a,b) Tables') - string += '{: <16}=\t{}\n'.format('\tNCrystal conf', self._NCrystal_cfg) + string += '{: <16}=\t{}\n'.format('\tNCrystal conf', self._ncrystal_cfg) for sab in self._sab: string += '{: <16}=\t{}\n'.format('\tS(a,b)', sab) @@ -335,7 +335,7 @@ class Material(IDManagerMixin): return material @classmethod - def from_NCrystal(cls, cfg): + def from_ncrystal(cls, cfg): """Create material from NCrystal configuration string Density is set from the NCrystal value, and material temperature from the configuration string. @@ -352,26 +352,23 @@ class Material(IDManagerMixin): """ - try: - import NCrystal - except ImportError: - raise SystemExit("ERROR: NCrystal Python module is required.") + import NCrystal - NC_mat = NCrystal.createInfo(cfg) - NC_comp = NC_mat.getComposition() + nc_mat = NCrystal.createInfo(cfg) + nc_comp = nc_mat.getComposition() # Create the Material material = cls() - for frac, atom in NC_comp: + for frac, atom in nc_comp: if not atom.isNaturalElement(): raise ValueError('NCrystal-OpenMC interface only works with natural elements for now.') material.add_element(atom.elementName(), frac, 'ao') - material._NCrystal_cfg = cfg + material._ncrystal_cfg = cfg material._density_units = "g/cm3" - material._density = NC_mat.getDensity() - material.temperature = NC_mat.getTemperature() + material._density = nc_mat.getDensity() + material.temperature = nc_mat.getTemperature() return material @@ -449,7 +446,7 @@ class Material(IDManagerMixin): 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) - if self._NCrystal_cfg is not None: + if self._ncrystal_cfg is not None: raise ValueError("Cannot add nuclides to NCrystal material") # If nuclide name doesn't look valid, give a warning @@ -656,7 +653,7 @@ class Material(IDManagerMixin): raise ValueError("Element name should be given by the " "element's symbol or name, e.g., 'Zr', 'zirconium'") - if self._NCrystal_cfg is not None: + if self._ncrystal_cfg is not None: raise ValueError("Cannot add elements to NCrystal material") # Allow for element identifier to be given as a symbol or name @@ -1185,13 +1182,13 @@ class Material(IDManagerMixin): if self._volume: element.set("volume", str(self._volume)) - if self._NCrystal_cfg: + if self._ncrystal_cfg: if self._sab: raise ValueError("NCrystal materials are not compatible with S(a,b).") if self._macroscopic is not None: raise ValueError("NCrystal materials are not compatible macroscopic cross sections.") - element.set("cfg", str(self._NCrystal_cfg)) + element.set("cfg", str(self._ncrystal_cfg)) # Create temperature XML subelement if self.temperature is not None: diff --git a/src/material.cpp b/src/material.cpp index d7fae8361..13acbba1f 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -63,8 +63,8 @@ Material::Material(pugi::xml_node node) #ifdef NCRYSTAL if (check_for_node(node, "cfg")) { cfg_ = get_node_value(node, "cfg"); - write_message(5, "NCrystal config string: >>{}<< ", cfg_); - m_NCrystal_mat_ = NCrystal::FactImpl::createScatter(cfg_); + write_message(5, "NCrystal config string: '{}'", ncrystal_cfg_); + ncrystal_mat_ = NCrystal::FactImpl::createScatter(ncrystal_cfg_); } #endif @@ -803,11 +803,11 @@ void Material::calculate_neutron_xs(Particle& p) const #ifdef NCRYSTAL double ncrystal_xs = -1; - if (m_NCrystal_mat_ != nullptr && p.E() < settings::ncrystal_max_energy){ + if (ncrystal_mat_ && p.E() < settings::ncrystal_max_energy){ // Calculate scattering XS per atom with NCrystal, only once per material - NCrystal::CachePtr dummyCache; + NCrystal::CachePtr dummy_cache; auto nc_energy = NCrystal::NeutronEnergy{p.E()}; - ncrystal_xs = m_NCrystal_mat_->crossSection( dummyCache, nc_energy, {p.u().x, p.u().y, p.u().z}).get(); + ncrystal_xs = ncrystal_mat_->crossSection( dummy_cache, nc_energy, {p.u().x, p.u().y, p.u().z}).get(); } #endif @@ -849,8 +849,10 @@ void Material::calculate_neutron_xs(Particle& p) const int i_nuclide = nuclide_[i]; // Calculate microscopic cross section for this nuclide -#ifndef NCRYSTAL - const +#ifdef NCRYSTAL + auto& micro {p.neutron_xs(i_nuclide)}; +#else + const auto& micro {p.neutron_xs(i_nuclide)}; #endif auto& micro {p.neutron_xs(i_nuclide)}; if (p.E() != micro.last_E || p.sqrtkT() != micro.last_sqrtkT || diff --git a/src/physics.cpp b/src/physics.cpp index 948307521..bad499772 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -142,18 +142,18 @@ void sample_neutron_reaction(Particle& p) // exiting neutron #ifdef NCRYSTAL - if (model::materials[p.material()]->m_NCrystal_mat() != nullptr && p.E() < settings::ncrystal_max_energy){ - NcrystalRNG_Wrapper rng(p.current_seed()); // Initialize RNG + if (model::materials[p.material()]->ncrystal_mat() && p.E() < settings::ncrystal_max_energy){ + NCrystalRNGWrapper rng(p.current_seed()); // Initialize RNG //create a cache pointer for multi thread physics - NCrystal::CachePtr dummyCache;//fixme: avoid recreating here (triggers malloc) + NCrystal::CachePtr dummy_cache; auto nc_energy = NCrystal::NeutronEnergy{p.E()}; - auto outcome = model::materials[p.material()]->m_NCrystal_mat()->sampleScatter( dummyCache, rng , nc_energy, {p.u().x, p.u().y, p.u().z}); + auto outcome = model::materials[p.material()]->ncrystal_mat()->sampleScatter( dummy_cache, rng , nc_energy, {p.u().x, p.u().y, p.u().z}); p.E_last() = p.E(); p.E() = outcome.ekin.get(); Direction u_old {p.u()}; p.u() = Direction(outcome.direction[0], outcome.direction[1], outcome.direction[2]); p.mu() = u_old.dot(p.u()); - p.event_mt() = ELASTIC;//fixme: define a new label for NCrystal? + p.event_mt() = ELASTIC; } else { scatter(p, i_nuclide); } From 5afcc9e49b60ec1c5e2290d4725bac7a96e1692e Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Mon, 26 Sep 2022 11:30:39 +0200 Subject: [PATCH 1179/2654] Apply clang-format --- include/openmc/material.h | 13 ++++++++----- include/openmc/physics.h | 17 ++++++++++------- include/openmc/settings.h | 3 ++- src/material.cpp | 33 ++++++++++++++++++--------------- src/physics.cpp | 18 +++++++++++------- src/settings.cpp | 2 +- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/include/openmc/material.h b/include/openmc/material.h index 30d8ffb7d..47e3e6a16 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -158,15 +158,18 @@ public: #ifdef NCRYSTAL //! Get pointer to NCrystal material object //! \return Pointer to NCrystal material object - std::shared_ptr ncrystal_mat() const {return ncrystal_mat_; }; + std::shared_ptr ncrystal_mat() const + { + return ncrystal_mat_; + }; #endif //---------------------------------------------------------------------------- // Data - int32_t id_ {C_NONE}; //!< Unique ID - std::string name_; //!< Name of material - vector nuclide_; //!< Indices in nuclides vector - vector element_; //!< Indices in elements vector + int32_t id_ {C_NONE}; //!< Unique ID + std::string name_; //!< Name of material + vector nuclide_; //!< Indices in nuclides vector + vector element_; //!< Indices in elements vector #ifdef NCRYSTAL std::string ncrystal_cfg_; //!< NCrystal configuration string std::shared_ptr ncrystal_mat_; diff --git a/include/openmc/physics.h b/include/openmc/physics.h index 109f7caff..23995e7af 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -111,14 +111,17 @@ void split_particle(Particle& p); //============================================================================== class NCrystalRNGWrapper : public NCrystal::RNGStream { - uint64_t* openmc_seed_; -public: - constexpr NCrystalRNGWrapper(uint64_t* seed) noexcept : openmc_seed_(seed) {} -protected: - double actualGenerate() override { - return std::max( std::numeric_limits::min(), prn(openmc_seed_) ); - } + uint64_t* openmc_seed_; +public: + constexpr NCrystalRNGWrapper(uint64_t* seed) noexcept : openmc_seed_(seed) {} + +protected: + double actualGenerate() override + { + return std::max( + std::numeric_limits::min(), prn(openmc_seed_)); + } }; #endif diff --git a/include/openmc/settings.h b/include/openmc/settings.h index ba1a30e30..9bb447005 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -121,7 +121,8 @@ extern "C" int verbosity; //!< How verbose to make output extern double weight_cutoff; //!< Weight cutoff for Russian roulette extern double weight_survive; //!< Survival weight after Russian roulette #ifdef NCRYSTAL -extern double ncrystal_max_energy; // Energy in eV to switch between NCrystal and ENDF +extern double + ncrystal_max_energy; //!< Energy in eV to switch between NCrystal and ENDF #endif } // namespace settings diff --git a/src/material.cpp b/src/material.cpp index 13acbba1f..e894084e2 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -64,7 +64,7 @@ Material::Material(pugi::xml_node node) if (check_for_node(node, "cfg")) { cfg_ = get_node_value(node, "cfg"); write_message(5, "NCrystal config string: '{}'", ncrystal_cfg_); - ncrystal_mat_ = NCrystal::FactImpl::createScatter(ncrystal_cfg_); + ncrystal_mat_ = NCrystal::FactImpl::createScatter(ncrystal_cfg_); } #endif @@ -375,8 +375,8 @@ void Material::finalize() this->init_thermal(); } -// Normalize density -this->normalize_density(); + // Normalize density + this->normalize_density(); } void Material::normalize_density() @@ -803,11 +803,14 @@ void Material::calculate_neutron_xs(Particle& p) const #ifdef NCRYSTAL double ncrystal_xs = -1; - if (ncrystal_mat_ && p.E() < settings::ncrystal_max_energy){ + if (ncrystal_mat_ && p.E() < settings::ncrystal_max_energy) { // Calculate scattering XS per atom with NCrystal, only once per material NCrystal::CachePtr dummy_cache; - auto nc_energy = NCrystal::NeutronEnergy{p.E()}; - ncrystal_xs = ncrystal_mat_->crossSection( dummy_cache, nc_energy, {p.u().x, p.u().y, p.u().z}).get(); + auto nc_energy = NCrystal::NeutronEnergy {p.E()}; + ncrystal_xs = + ncrystal_mat_ + ->crossSection(dummy_cache, nc_energy, {p.u().x, p.u().y, p.u().z}) + .get(); } #endif @@ -859,15 +862,15 @@ void Material::calculate_neutron_xs(Particle& p) const i_sab != micro.index_sab || sab_frac != micro.sab_frac) { data::nuclides[i_nuclide]->calculate_xs(i_sab, i_grid, sab_frac, p); #ifdef NCRYSTAL - if (ncrystal_xs >= 0.0){ - if ( micro.thermal > 0 || micro.thermal_elastic > 0) { - fatal_error("S(a,b) treatment and NCrystal are not compatible."); - } - data::nuclides[i_nuclide]->calculate_elastic_xs(p); - // remove free atom cross section - // and replace it by scattering cross section per atom from NCrystal - micro.total = micro.total - micro.elastic + ncrystal_xs; - micro.elastic = ncrystal_xs; + if (ncrystal_xs >= 0.0) { + if (micro.thermal > 0 || micro.thermal_elastic > 0) { + fatal_error("S(a,b) treatment and NCrystal are not compatible."); + } + data::nuclides[i_nuclide]->calculate_elastic_xs(p); + // remove free atom cross section + // and replace it by scattering cross section per atom from NCrystal + micro.total = micro.total - micro.elastic + ncrystal_xs; + micro.elastic = ncrystal_xs; } #endif } diff --git a/src/physics.cpp b/src/physics.cpp index bad499772..e19640314 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -138,20 +138,24 @@ void sample_neutron_reaction(Particle& p) if (!p.alive()) return; - // Sample a scattering reaction and determine the secondary energy of the - // exiting neutron + // Sample a scattering reaction and determine the secondary energy of the + // exiting neutron #ifdef NCRYSTAL - if (model::materials[p.material()]->ncrystal_mat() && p.E() < settings::ncrystal_max_energy){ + if (model::materials[p.material()]->ncrystal_mat() && + p.E() < settings::ncrystal_max_energy) { NCrystalRNGWrapper rng(p.current_seed()); // Initialize RNG - //create a cache pointer for multi thread physics + // create a cache pointer for multi thread physics NCrystal::CachePtr dummy_cache; - auto nc_energy = NCrystal::NeutronEnergy{p.E()}; - auto outcome = model::materials[p.material()]->ncrystal_mat()->sampleScatter( dummy_cache, rng , nc_energy, {p.u().x, p.u().y, p.u().z}); + auto nc_energy = NCrystal::NeutronEnergy {p.E()}; + auto outcome = + model::materials[p.material()]->ncrystal_mat()->sampleScatter( + dummy_cache, rng, nc_energy, {p.u().x, p.u().y, p.u().z}); p.E_last() = p.E(); p.E() = outcome.ekin.get(); Direction u_old {p.u()}; - p.u() = Direction(outcome.direction[0], outcome.direction[1], outcome.direction[2]); + p.u() = Direction( + outcome.direction[0], outcome.direction[1], outcome.direction[2]); p.mu() = u_old.dot(p.u()); p.event_mt() = ELASTIC; } else { diff --git a/src/settings.cpp b/src/settings.cpp index 3f3e97054..87c24eedd 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -119,7 +119,7 @@ double weight_cutoff {0.25}; double weight_survive {1.0}; #ifdef NCRYSTAL -double ncrystal_max_energy{5.0}; +double ncrystal_max_energy {5.0}; #endif } // namespace settings From fdf763e801b1439da96009fd5dadeadeb93e36f7 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Mon, 26 Sep 2022 12:35:12 +0200 Subject: [PATCH 1180/2654] Couple of fixes --- src/material.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/material.cpp b/src/material.cpp index e894084e2..9531e9f43 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -62,7 +62,7 @@ Material::Material(pugi::xml_node node) #ifdef NCRYSTAL if (check_for_node(node, "cfg")) { - cfg_ = get_node_value(node, "cfg"); + ncrystal_cfg_ = get_node_value(node, "cfg"); write_message(5, "NCrystal config string: '{}'", ncrystal_cfg_); ncrystal_mat_ = NCrystal::FactImpl::createScatter(ncrystal_cfg_); } @@ -857,7 +857,6 @@ void Material::calculate_neutron_xs(Particle& p) const #else const auto& micro {p.neutron_xs(i_nuclide)}; #endif - auto& micro {p.neutron_xs(i_nuclide)}; if (p.E() != micro.last_E || p.sqrtkT() != micro.last_sqrtkT || i_sab != micro.index_sab || sab_frac != micro.sab_frac) { data::nuclides[i_nuclide]->calculate_xs(i_sab, i_grid, sab_frac, p); From 52ee2c37ced8fce859d2ec6a06c6909dd0d04b44 Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Thu, 20 Oct 2022 11:36:22 +0200 Subject: [PATCH 1181/2654] Print where NCrystal was found as suggested by @paulromano Co-authored-by: Paul Romano --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7080accfd..2815230d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,7 @@ endmacro() if(OPENMC_USE_NCRYSTAL) find_package(NCrystal REQUIRED) + message(STATUS "Found NCrystal: ${NCrystal_DIR} (version ${NCrystal_VERSION})") endif() #=============================================================================== From a5b811ec899470f9b0bb3e387f0f672ae8490321 Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Thu, 20 Oct 2022 13:25:05 +0200 Subject: [PATCH 1182/2654] Use new NCrystal getFlattenedComposition method to better support more complicated materials --- openmc/material.py | 63 +++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 15d1f8ac9..de4a22cb8 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -335,15 +335,23 @@ class Material(IDManagerMixin): return material @classmethod - def from_ncrystal(cls, cfg): - """Create material from NCrystal configuration string - Density is set from the NCrystal value, - and material temperature from the configuration string. - + def from_ncrystal(cls, cfg, material_id=None, name=''): + """Create material from NCrystal configuration string. Density, + temperature, and material composition, and (ultimately) thermal neutron + scattering, will be automatically be provided by NCrystal based on this + string. The name and material_id parameters are simply passed on to the + Material constructor. + Parameters ---------- cfg : str NCrystal configuration string + material_id : int, optional + Unique identifier for the material. If not specified, an identifier will + automatically be assigned. + name : str, optional + Name of the material. If not specified, the name will be the empty + string. Returns ------- @@ -353,22 +361,43 @@ class Material(IDManagerMixin): """ import NCrystal - nc_mat = NCrystal.createInfo(cfg) - nc_comp = nc_mat.getComposition() + + def openmc_natabund( Z ): + #nc_mat.getFlattenedComposition might need natural abundancies. + #This call-back function is used so NCrystal can flatten composition + #using OpenMC's natural abundancies. In practice this function will + #only get invoked in the unlikely case where a material is specified + #by referring both to natural elements and specific isotopes of the + #same element. + elem_name = openmc.data.ATOMIC_SYMBOL.get( Z, None ) + if not elem_name: + raise ValueError( f'Element with Z={Z} is not known' ) + l = [] + for iso_name,abund in openmc.data.isotopes( elem_name ): + l.append( ( int(iso_name[ len(elem_name) : ]), abund ) ) + return l + + flat_compos = nc_mat.getFlattenedComposition( preferNaturalElements = True, + naturalAbundProvider = openmc_natabund ) # Create the Material - material = cls() + material = cls( material_id = material_id, + name = name, + temperature = nc_mat.getTemperature() ) - for frac, atom in nc_comp: - if not atom.isNaturalElement(): - raise ValueError('NCrystal-OpenMC interface only works with natural elements for now.') - material.add_element(atom.elementName(), frac, 'ao') + for Z, A_vals in flat_compos: + elemname = openmc.data.ATOMIC_SYMBOL.get(Z,None) + if not elemname: + raise ValueError(f'Element with Z={Z} is not known') + for A, frac in A_vals: + if A: + material.add_nuclide( elemname + str(A), frac, 'ao' ) + else: + material.add_element( elemname, frac, 'ao' ) - material._ncrystal_cfg = cfg - material._density_units = "g/cm3" - material._density = nc_mat.getDensity() - material.temperature = nc_mat.getTemperature() + material.set_density( 'g/cm3', nc_mat.getDensity() ) + material._ncrystal_cfg = NCrystal.normaliseCfg( cfg ) return material @@ -1186,7 +1215,7 @@ class Material(IDManagerMixin): if self._sab: raise ValueError("NCrystal materials are not compatible with S(a,b).") if self._macroscopic is not None: - raise ValueError("NCrystal materials are not compatible macroscopic cross sections.") + raise ValueError("NCrystal materials are not compatible with macroscopic cross sections.") element.set("cfg", str(self._ncrystal_cfg)) From f2e807e942ed421cd03fc87823c579e47dfcce3c Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Thu, 20 Oct 2022 13:26:45 +0200 Subject: [PATCH 1183/2654] Move NCrystalRNGWrapper data member into explicit private section as requested --- include/openmc/physics.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/openmc/physics.h b/include/openmc/physics.h index 23995e7af..806297c4e 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -111,8 +111,6 @@ void split_particle(Particle& p); //============================================================================== class NCrystalRNGWrapper : public NCrystal::RNGStream { - uint64_t* openmc_seed_; - public: constexpr NCrystalRNGWrapper(uint64_t* seed) noexcept : openmc_seed_(seed) {} @@ -122,6 +120,8 @@ protected: return std::max( std::numeric_limits::min(), prn(openmc_seed_)); } +private: + uint64_t* openmc_seed_; }; #endif From aca4fcb42bbfb45bd3ded0f9f1bbf8b7107aa632 Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Fri, 21 Oct 2022 10:30:05 +0200 Subject: [PATCH 1184/2654] NCrystal cfgstr printout now mentions material ID --- src/material.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/material.cpp b/src/material.cpp index 9531e9f43..32f5f2e86 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -63,7 +63,7 @@ Material::Material(pugi::xml_node node) #ifdef NCRYSTAL if (check_for_node(node, "cfg")) { ncrystal_cfg_ = get_node_value(node, "cfg"); - write_message(5, "NCrystal config string: '{}'", ncrystal_cfg_); + write_message(5, "NCrystal config string for material #{}: '{}'", this->id(), ncrystal_cfg_); ncrystal_mat_ = NCrystal::FactImpl::createScatter(ncrystal_cfg_); } #endif From b0743dfdea203372844e3d4901d8d0f8b2150b0c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 21 Oct 2022 11:56:21 +0200 Subject: [PATCH 1185/2654] fixed cv.check_type origin --- openmc/mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index da00750c1..807886988 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1096,7 +1096,7 @@ class CylindricalMesh(StructuredMesh): @origin.setter def origin(self, coords): - cv.check_type('mesh r_grid', coords, Iterable, Real) + cv.check_type('mesh origin', coords, Iterable, Real) self._origin = np.asarray(coords) @r_grid.setter @@ -1418,7 +1418,7 @@ class SphericalMesh(StructuredMesh): @origin.setter def origin(self, coords): - cv.check_type('mesh r_grid', coords, Iterable, Real) + cv.check_type('mesh origin', coords, Iterable, Real) self._origin = np.asarray(coords) @r_grid.setter From 3347aeaa032ffa4668e6d149e5400d9d16dd2d7e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 21 Oct 2022 07:07:44 -0500 Subject: [PATCH 1186/2654] Fixes related to #2253 and #2270 --- include/openmc/constants.h | 5 ----- src/output.cpp | 7 ++++--- src/volume_calc.cpp | 11 +++++------ 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index 8bb2cb1bf..a1cc2939c 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -340,11 +340,6 @@ enum class RunMode { enum class GeometryType { CSG, DAG }; -//============================================================================== -// Volume Calculation Constants - -constexpr uint64_t UINT64_T_MAX {std::numeric_limits::max()}; - } // namespace openmc #endif // OPENMC_CONSTANTS_H diff --git a/src/output.cpp b/src/output.cpp index 59cb15712..18efed656 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -1,8 +1,8 @@ #include "openmc/output.h" #include // for transform, max -#include // for strlen #include // for stdout +#include // for strlen #include // for time, localtime #include #include // for setw, setprecision, put_time @@ -134,9 +134,10 @@ void header(const char* msg, int level) auto out = header(msg); // Print header based on verbosity level. - if (settings::verbosity >= level) + if (settings::verbosity >= level) { fmt::print("\n{}\n\n", out); std::fflush(stdout); + } } //============================================================================== @@ -396,7 +397,7 @@ void print_build_info() fmt::print("DAGMC support: {}\n", dagmc); fmt::print("libMesh support: {}\n", libmesh); fmt::print("Coverage testing: {}\n", coverage); - fmt::print("Profiling flags: {}\n", profiling); + fmt::print("Profiling flags: {}\n", profiling); } } diff --git a/src/volume_calc.cpp b/src/volume_calc.cpp index e36b88904..0b1ea3575 100644 --- a/src/volume_calc.cpp +++ b/src/volume_calc.cpp @@ -225,12 +225,11 @@ vector VolumeCalculation::execute() const iterations++; uint64_t total_samples = iterations * n_samples_; - // warn user if total sample size is greater than what the size_t type can + // warn user if total sample size is greater than what the uin64_t type can // represent - if (total_samples == UINT64_T_MAX) { + if (total_samples == std::numeric_limits::max()) { warning("The number of samples has exceeded the type used to track hits. " - "Volume " - "results may be inaccurate."); + "Volume results may be inaccurate."); } // reset @@ -246,8 +245,8 @@ vector VolumeCalculation::execute() const // Create 2D array to store atoms/uncertainty for each nuclide. Later this // is compressed into vectors storing only those nuclides that are // non-zero - auto n_nuc = settings::run_CE ? data::nuclides.size() - : data::mg.nuclides_.size(); + auto n_nuc = + settings::run_CE ? data::nuclides.size() : data::mg.nuclides_.size(); xt::xtensor atoms({n_nuc, 2}, 0.0); #ifdef OPENMC_MPI From a0e5ba441865309aeca84ad87604002e5fba99a8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 18 Oct 2022 13:34:30 -0500 Subject: [PATCH 1187/2654] Add 0.13.2 release notes --- docs/source/io_formats/statepoint.rst | 3 +- docs/source/pythonapi/stats.rst | 6 ++ docs/source/releasenotes/0.14.0.rst | 99 +++++++++++++++++++++++++++ docs/source/releasenotes/index.rst | 1 + openmc/material.py | 4 ++ openmc/universe.py | 9 ++- 6 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 docs/source/releasenotes/0.14.0.rst diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index a05034a2d..9a08eed73 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -109,7 +109,8 @@ The current version of the statepoint file format is 17.0. - **y** (*double[]*) -- Interpolant values for energyfunction interpolation. Only used for 'energyfunction' filters. - :Attributes: - **interpolation** (*int*) -- Interpolation type. Only used for + :Attributes: + - **interpolation** (*int*) -- Interpolation type. Only used for 'energyfunction' filters. **/tallies/derivatives/derivative /** diff --git a/docs/source/pythonapi/stats.rst b/docs/source/pythonapi/stats.rst index 10be9454f..fb6383fc7 100644 --- a/docs/source/pythonapi/stats.rst +++ b/docs/source/pythonapi/stats.rst @@ -22,6 +22,12 @@ Univariate Probability Distributions openmc.stats.Legendre openmc.stats.Mixture openmc.stats.Normal + +.. autosummary:: + :toctree: generated + :nosignatures: + :template: myfunction.rst + openmc.stats.muir Angular Distributions diff --git a/docs/source/releasenotes/0.14.0.rst b/docs/source/releasenotes/0.14.0.rst new file mode 100644 index 000000000..a1f84adb5 --- /dev/null +++ b/docs/source/releasenotes/0.14.0.rst @@ -0,0 +1,99 @@ +==================== +What's New in 0.14.0 +==================== + +.. currentmodule:: openmc + +------- +Summary +------- + +This release of OpenMC includes several bug fixes, performance improvements for +complex geometries and depletion simulations, and other general enhancements. +Notably, a capability has been added to compute the photon spectra from decay of +unstable nuclides. Alongside that, a new :data:`openmc.config` configuration +variable has been introduced that allows easier configuration of data sources. +Additionally, users can now perform cell or material rejection when sampling +external source distributions. Finally, + +------------------------------------ +Compatibility Notes and Deprecations +------------------------------------ + +- If you are building against libMesh for unstructured mesh tally support, + version 1.6 or higher is now required. +- The ``openmc.stats.Muir`` class has been replaced by a + :func:`openmc.stats.muir` function that returns an instance of + :class:`openmc.stats.Normal`. + +------------ +New Features +------------ + +- The :meth:`openmc.Material.get_nuclide_atom_densities` method now takes an + optional ``nuclide`` argument. +- Functions/methods in the :mod:`openmc.deplete` module now accept times in + Julian years (``'a'``). +- The :meth:`openmc.Universe.plot` method now allows a pre-existing axes object + to be passed in. +- Performance optimization for geometries with many complex regions. +- Performance optimization for depletion by avoiding deepcopies and caching + reaction rates. +- The :class:`openmc.RegularMesh` class now has a + :meth:`~openmc.RegularMesh.from_domain` classmethod. +- The :class:`openmc.CylindricalMesh` class now has a + :meth:`~openmc.CylindricalMesh.from_domain` classmethod. +- Improved method to condense diffusion coefficients from the :mod:`openmc.mgxs` + module. +- A new :data:`openmc.config` configuration variable has been introduced that + allows data sources to be specified at runtime or via environment variables. +- The :class:`openmc.EnergyFunctionFilter` class now supports multiple + interpolation schemes, not just linear-linear interpolation. +- The :class:`openmc.DAGMCUniverse` class now has ``material_names``, + ``n_cells``, and ``n_surfaces`` attributes. +- A new :func:`openmc.data.decay_photon_energy` function has been added that + returns the energy spectrum of photons emitted from the decay of an unstable + nuclide. +- The :class:`openmc.Material` class also has a new + :attr:`~openmc.Material.decay_photon_energy` attribute that gives the decay + photon energy spectrum from the material based on its constituent nuclides. +- The :class:`openmc.deplete.StepResult` now has a + :meth:`~openmc.deplete.StepResult.get_material` method. +- The :class:`openmc.Source` class now takes a ``domains`` argument that + specifies a list of cells, materials, or universes that is used to reject + source sites (i.e., if the sampled sites are not within the specified domain, + they are rejected). + +--------- +Bug Fixes +--------- + +- `Delay call to Tally::set_strides ` +- `Fix reading reference direction from XML for angular distributions `_ +- `Fix erroneous behavior in Material.add_components `_ +- `Fix reading thermal elastic data from ACE `_ +- `Fix reading source file with time attribute `_ +- `Fix conversion of multiple thermal scattering data files from ACE `_ +- `Fix reading values from wwinp file `_ +- `Handle possibility of .ppm file in Universe.plot `_ +- `Update volume calc types to mitigate overflow issues `_ + +------------ +Contributors +------------ + +- `Lewis Gross `_ +- `Andrew Johnson `_ +- `Miriam Kreher `_ +- `James Logan `_ +- `Jose Ignacio Marquez Damien `_ +- `Josh May `_ +- `Patrick Myers `_ +- `Adam Nelson `_ +- `April Novak `_ +- `Ethan Peterson `_ +- `Gavin Ridley `_ +- `Paul Romano `_ +- `Patrick Shriwise `_ +- `Jonathan Shimwell `_ +- `Olek Yardas `_ diff --git a/docs/source/releasenotes/index.rst b/docs/source/releasenotes/index.rst index 34ddb285a..5753c8bae 100644 --- a/docs/source/releasenotes/index.rst +++ b/docs/source/releasenotes/index.rst @@ -7,6 +7,7 @@ Release Notes .. toctree:: :maxdepth: 1 + 0.14.0 0.13.1 0.13.0 0.12.2 diff --git a/openmc/material.py b/openmc/material.py index e99eec52c..652ee89a9 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -825,6 +825,8 @@ class Material(IDManagerMixin): element : str Specifies the element to match when searching through the nuclides + .. versionadded:: 0.14.0 + Returns ------- nuclides : list of str @@ -877,6 +879,8 @@ class Material(IDManagerMixin): Nuclide for which atom density is desired. If not specified, the atom density for each nuclide in the material is given. + .. versionadded:: 0.14.0 + Returns ------- nuclides : dict diff --git a/openmc/universe.py b/openmc/universe.py index db828e33c..b74d98adb 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -650,19 +650,26 @@ class DAGMCUniverse(UniverseBase): bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box of the universe. + + .. versionadded:: 0.13.1 material_names : list of str Return a sorted list of materials names that are contained within the DAGMC h5m file. This is useful when naming openmc.Material() objects as each material name present in the DAGMC h5m file must have a matching openmc.Material() with the same name. + + .. versionadded:: 0.14.0 n_cells : int The number of cells in the DAGMC model. This is the number of cells at runtime and accounts for the implicit complement whether or not is it present in the DAGMC file. + + .. versionadded:: 0.14.0 n_surfaces : int The number of surfaces in the model. - .. versionadded:: 0.13.1 + .. versionadded:: 0.14.0 + """ def __init__(self, From 53b6d8ab11a300b8c8a373d5a62e558f90b5dade Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 19 Oct 2022 08:04:50 -0500 Subject: [PATCH 1188/2654] Change 0.14.0 --> 0.13.2 --- CMakeLists.txt | 4 ++-- docs/source/conf.py | 4 ++-- docs/source/releasenotes/{0.14.0.rst => 0.13.2.rst} | 2 +- docs/source/releasenotes/index.rst | 2 +- openmc/__init__.py | 2 +- openmc/data/decay.py | 2 +- openmc/deplete/stepresult.py | 2 +- openmc/material.py | 6 +++--- openmc/stats/univariate.py | 2 +- openmc/universe.py | 6 +++--- 10 files changed, 16 insertions(+), 16 deletions(-) rename docs/source/releasenotes/{0.14.0.rst => 0.13.2.rst} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 04c712a17..3fb04850c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ project(openmc C CXX) # Set version numbers set(OPENMC_VERSION_MAJOR 0) -set(OPENMC_VERSION_MINOR 14) -set(OPENMC_VERSION_RELEASE 0) +set(OPENMC_VERSION_MINOR 13) +set(OPENMC_VERSION_RELEASE 2) set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) diff --git a/docs/source/conf.py b/docs/source/conf.py index 98ccdee44..29b5ae84c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -69,9 +69,9 @@ copyright = '2011-2022, Massachusetts Institute of Technology, UChicago Argonne # built documents. # # The short X.Y version. -version = "0.14" +version = "0.13" # The full version, including alpha/beta/rc tags. -release = "0.14.0" +release = "0.13.2" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/releasenotes/0.14.0.rst b/docs/source/releasenotes/0.13.2.rst similarity index 99% rename from docs/source/releasenotes/0.14.0.rst rename to docs/source/releasenotes/0.13.2.rst index a1f84adb5..e00a02bae 100644 --- a/docs/source/releasenotes/0.14.0.rst +++ b/docs/source/releasenotes/0.13.2.rst @@ -1,5 +1,5 @@ ==================== -What's New in 0.14.0 +What's New in 0.13.2 ==================== .. currentmodule:: openmc diff --git a/docs/source/releasenotes/index.rst b/docs/source/releasenotes/index.rst index 5753c8bae..910737a41 100644 --- a/docs/source/releasenotes/index.rst +++ b/docs/source/releasenotes/index.rst @@ -7,7 +7,7 @@ Release Notes .. toctree:: :maxdepth: 1 - 0.14.0 + 0.13.2 0.13.1 0.13.0 0.12.2 diff --git a/openmc/__init__.py b/openmc/__init__.py index 214695e67..bee851ae1 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -38,4 +38,4 @@ from .config import * from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.14.0-dev' +__version__ = '0.13.2-dev' diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 29574e001..8268d4a36 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -587,7 +587,7 @@ def decay_photon_energy(nuclide: str) -> Optional[Univariate]: for the first time, you need to ensure that a depletion chain has been specified in openmc.config['chain_file']. - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 Parameters ---------- diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index e462f1754..c8b35a1fa 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -202,7 +202,7 @@ class StepResult: def get_material(self, mat_id): """Return material object for given depleted composition - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 Parameters ---------- diff --git a/openmc/material.py b/openmc/material.py index 652ee89a9..1979b3958 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -98,7 +98,7 @@ class Material(IDManagerMixin): this distribution is the total intensity of the photon source in [decay/sec]. - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 """ @@ -825,7 +825,7 @@ class Material(IDManagerMixin): element : str Specifies the element to match when searching through the nuclides - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 Returns ------- @@ -879,7 +879,7 @@ class Material(IDManagerMixin): Nuclide for which atom density is desired. If not specified, the atom density for each nuclide in the material is given. - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 Returns ------- diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 28f60de6d..de8d08ded 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -729,7 +729,7 @@ def muir(e0, m_rat, kt): distribution: the mean energy of particles ``e0``, the mass of reactants ``m_rat``, and the ion temperature ``kt``. - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 Parameters ---------- diff --git a/openmc/universe.py b/openmc/universe.py index b74d98adb..94ea5624a 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -658,17 +658,17 @@ class DAGMCUniverse(UniverseBase): as each material name present in the DAGMC h5m file must have a matching openmc.Material() with the same name. - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 n_cells : int The number of cells in the DAGMC model. This is the number of cells at runtime and accounts for the implicit complement whether or not is it present in the DAGMC file. - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 n_surfaces : int The number of surfaces in the model. - .. versionadded:: 0.14.0 + .. versionadded:: 0.13.2 """ From 6d499fa0c0c343764550ae95f0314fd68ef29861 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 19 Oct 2022 11:17:39 -0500 Subject: [PATCH 1189/2654] Fix missing underscore in release notes --- docs/source/releasenotes/0.13.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/releasenotes/0.13.2.rst b/docs/source/releasenotes/0.13.2.rst index e00a02bae..e9175358b 100644 --- a/docs/source/releasenotes/0.13.2.rst +++ b/docs/source/releasenotes/0.13.2.rst @@ -68,7 +68,7 @@ New Features Bug Fixes --------- -- `Delay call to Tally::set_strides ` +- `Delay call to Tally::set_strides `_ - `Fix reading reference direction from XML for angular distributions `_ - `Fix erroneous behavior in Material.add_components `_ - `Fix reading thermal elastic data from ACE `_ From 2e433653cce277bd58400c1641d236be88b41a35 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 19 Oct 2022 09:42:16 -0500 Subject: [PATCH 1190/2654] Avoid warning message on clang --- src/source.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/source.cpp b/src/source.cpp index fc50115cd..d201e3c03 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -224,7 +224,8 @@ SourceSite IndependentSource::sample(uint64_t* seed) const auto id = (domain_type_ == DomainType::CELL) ? model::cells[coord.cell]->id_ : model::universes[coord.universe]->id_; - if (found = contains(domain_ids_, id)) break; + if ((found = contains(domain_ids_, id))) + break; } } } From 4fd665c008dcc2467d652c4ffedfd5ac88a87d27 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 19 Oct 2022 09:43:35 -0500 Subject: [PATCH 1191/2654] Remove -dev on version number --- include/openmc/version.h.in | 2 +- openmc/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index e1c2b0541..a518e0d63 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -10,7 +10,7 @@ namespace openmc { constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {true}; +constexpr bool VERSION_DEV {false}; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/openmc/__init__.py b/openmc/__init__.py index bee851ae1..ca21bf17b 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -38,4 +38,4 @@ from .config import * from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.13.2-dev' +__version__ = '0.13.2' From a3dd55d8bc4b28323b73e9a36c52f950db6ea1fb Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Fri, 21 Oct 2022 15:04:57 +0200 Subject: [PATCH 1192/2654] first stab at gha-install-ncrystal.sh --- tools/ci/gha-install-ncrystal.sh | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100755 tools/ci/gha-install-ncrystal.sh diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh new file mode 100755 index 000000000..c18087f23 --- /dev/null +++ b/tools/ci/gha-install-ncrystal.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -ex +cd $HOME + +#Use the NCrystal develop branch (in the near future we can move this to master): +git clone https://github.com/mctools/ncrystal --branch develop --single-branch --depth 1 ncrystal_src + +SRC_DIR="$PWD/ncrystal_src" +BLD_DIR="$PWD/ncrystal_bld" +INST_DIR="$PWD/ncrystal_inst" +PYTHON=$(which python3) + +CPU_COUNT=1 + +mkdir "$BLD_DIR" +cd ncrystal_bld + +#cmake -Dstatic=on .. && make 2>/dev/null && sudo make install + +cmake \ + "${SRC_DIR}" \ + -DBUILD_SHARED_LIBS=ON \ + -DNCRYSTAL_NOTOUCH_CMAKE_BUILD_TYPE=ON \ + -DMODIFY_RPATH=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_EXAMPLES=OFF \ + -DINSTALL_SETUPSH=OFF \ + -DEMBED_DATA=ON \ + -DINSTALL_DATA=OFF \ + -DNO_DIRECT_PYMODINST=ON \ + -DPython3_EXECUTABLE="$PYTHON" + +make -j${CPU_COUNT:-1} +make install + +#Note: There is no "make test" or "make ctest" functionality for NCrystal +# yet. If it appears in the future, we should add it here. + + +#The next stuff is not pretty, but it is needed as a temporary +#workaround until NCrystal add better support for system-wide +#installations in CMake: + +cat < ./findncrystallib.py +import pathlib +libname = pathlib.Path('./cfg_ncrystal_libname.txt').read_text().strip() +libs = list(pathlib.Path("/usr").glob("**/lib*/**/%s"%libname)) +assert len(libs)==1 +pathlib.Path('ncrystal_liblocation.txt').write_text(str(libs[0])) +EOF + +python3 ./findncrystallib.py + +TMPNCRYSTALLIBLOCATION=$(cat ./ncrystal_liblocation.txt) + +cat < ./ncrystal_pypkg/NCrystal/_nclibpath.py +#File autogenerated for working with systemwide install of NCrystal: +import pathlib +liblocation = pathlib.Path('${TMPNCRYSTALLIBLOCATION}'.strip()) +EOF + +$PYTHON -m pip install ./ncrystal_pypkg/ -vv From b874d83634962c9e1fcae2d0ffc360437e11abf5 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 21 Oct 2022 15:55:08 +0200 Subject: [PATCH 1193/2654] only translate when origin is not 0, 0, 0 --- openmc/mesh.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 807886988..b4cd04d51 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1322,9 +1322,10 @@ class CylindricalMesh(StructuredMesh): pts_cartesian[:, 1] = r * np.sin(phi) # offset with origin - pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] - pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] - pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] + if self.origin != [0.0, 0.0, 0.0]: + pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] + pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] + pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] return super().write_data_to_vtk( points=pts_cartesian, @@ -1576,9 +1577,10 @@ class SphericalMesh(StructuredMesh): pts_cartesian[:, 2] = r * np.cos(phi) # offset with origin - pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] - pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] - pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] + if self.origin != [0.0, 0.0, 0.0]: + pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] + pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] + pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] return super().write_data_to_vtk( points=pts_cartesian, From 1f973e1ebee9db7b8ce3a52ae3e9b6e8580758f9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 21 Oct 2022 11:47:36 -0500 Subject: [PATCH 1194/2654] Change version number to 0.13.3-dev --- CMakeLists.txt | 2 +- docs/source/conf.py | 2 +- include/openmc/version.h.in | 2 +- openmc/__init__.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fb04850c..317fd57a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(openmc C CXX) # Set version numbers set(OPENMC_VERSION_MAJOR 0) set(OPENMC_VERSION_MINOR 13) -set(OPENMC_VERSION_RELEASE 2) +set(OPENMC_VERSION_RELEASE 3) set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) diff --git a/docs/source/conf.py b/docs/source/conf.py index 29b5ae84c..f08333279 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -71,7 +71,7 @@ copyright = '2011-2022, Massachusetts Institute of Technology, UChicago Argonne # The short X.Y version. version = "0.13" # The full version, including alpha/beta/rc tags. -release = "0.13.2" +release = "0.13.3" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index a518e0d63..e1c2b0541 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -10,7 +10,7 @@ namespace openmc { constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {false}; +constexpr bool VERSION_DEV {true}; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/openmc/__init__.py b/openmc/__init__.py index ca21bf17b..f9abe5dc1 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -38,4 +38,4 @@ from .config import * from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.13.2' +__version__ = '0.13.3-dev' From 1a7066a885a8ad5e01d9971fc3e885612e9ca7f3 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 21 Oct 2022 18:38:44 +0100 Subject: [PATCH 1195/2654] added type hints for source.py --- openmc/source.py | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/openmc/source.py b/openmc/source.py index 48e14f6f7..1fb9ee44b 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -2,6 +2,8 @@ from collections.abc import Iterable from enum import Enum from numbers import Real import warnings +import typing # imported separately as py3.8 requires typing.Iterable +from typing import Optional, Union from xml.etree import ElementTree as ET import numpy as np @@ -9,6 +11,7 @@ import h5py import openmc import openmc.checkvalue as cv +from openmc.checkvalue import PathLike from openmc.stats.multivariate import UnitSphere, Spatial from openmc.stats.univariate import Univariate from ._xml import get_text @@ -70,9 +73,19 @@ class Source: """ - def __init__(self, space=None, angle=None, energy=None, time=None, filename=None, - library=None, parameters=None, strength=1.0, particle='neutron', - domains=None): + def __init__( + self, + space: Optional[openmc.stats.Spatial] = None, + angle: Optional[openmc.stats.Spatial] = None, + energy: Optional[openmc.stats.Univariate] = None, + time: Optional[openmc.stats.Univariate] = None, + filename: Optional[str] = None, + library: Optional[str] = None, + parameters: Optional[str] = None, + strength: float = 1.0, + particle: str = 'neutron', + domains: Optional[Union[openmc.Cell, openmc.Material, openmc.Universe]] = None + ): self._space = None self._angle = None self._energy = None @@ -244,7 +257,7 @@ class Source: return element @classmethod - def from_xml_element(cls, elem): + def from_xml_element(cls, elem: ET.Element): """Generate source from an XML element Parameters @@ -349,8 +362,18 @@ class SourceParticle: Type of the particle """ - def __init__(self, r=(0., 0., 0.), u=(0., 0., 1.), E=1.0e6, time=0.0, wgt=1.0, - delayed_group=0, surf_id=0, particle=ParticleType.NEUTRON): + def __init__( + self, + r: typing.Iterable[float, float, float] = (0., 0., 0.), + u: typing.Iterable[float, float, float] = (0., 0., 1.), + E: float = 1.0e6, + time: float = 0.0, + wgt: float = 1.0, + delayed_group: int = 0, + surf_id: int = 0, + particle: ParticleType = ParticleType.NEUTRON + ): + self.r = tuple(r) self.u = tuple(u) self.E = float(E) @@ -377,7 +400,10 @@ class SourceParticle: self.delayed_group, self.surf_id, self.particle.value) -def write_source_file(source_particles, filename, **kwargs): +def write_source_file( + source_particles: typing.Iterable[openmc.SourceParticle], + filename: PathLike, **kwargs +): """Write a source file using a collection of source particles Parameters From 17a65520272f37c0de337d30c6c6f04c51923271 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 21 Oct 2022 18:47:07 +0100 Subject: [PATCH 1196/2654] added return types --- openmc/source.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/source.py b/openmc/source.py index 1fb9ee44b..0a6dc2016 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -222,7 +222,7 @@ class Source: cv.check_value('source particle', particle, ['neutron', 'photon']) self._particle = particle - def to_xml_element(self): + def to_xml_element(self) -> ET.Element: """Return XML representation of the source Returns @@ -257,7 +257,7 @@ class Source: return element @classmethod - def from_xml_element(cls, elem: ET.Element): + def from_xml_element(cls, elem: ET.Element) -> openmc.Source: """Generate source from an XML element Parameters @@ -387,7 +387,7 @@ class SourceParticle: name = self.particle.name.lower() return f'' - def to_tuple(self): + def to_tuple(self) -> tuple: """Return source particle attributes as a tuple Returns From 4116f6cda0b8a1d18741bb89f08aeca7f88510af Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 21 Oct 2022 19:04:45 +0100 Subject: [PATCH 1197/2654] used forwards ref to avoid circlar imports --- openmc/source.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/source.py b/openmc/source.py index 0a6dc2016..05954da77 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -3,7 +3,7 @@ from enum import Enum from numbers import Real import warnings import typing # imported separately as py3.8 requires typing.Iterable -from typing import Optional, Union +from typing import Optional, Union, Tuple from xml.etree import ElementTree as ET import numpy as np @@ -84,7 +84,7 @@ class Source: parameters: Optional[str] = None, strength: float = 1.0, particle: str = 'neutron', - domains: Optional[Union[openmc.Cell, openmc.Material, openmc.Universe]] = None + domains: Optional[Union[openmc.Cell, openmc.Material, 'openmc.Universe']] = None ): self._space = None self._angle = None @@ -257,7 +257,7 @@ class Source: return element @classmethod - def from_xml_element(cls, elem: ET.Element) -> openmc.Source: + def from_xml_element(cls, elem: ET.Element) -> 'openmc.Source': """Generate source from an XML element Parameters @@ -364,8 +364,8 @@ class SourceParticle: """ def __init__( self, - r: typing.Iterable[float, float, float] = (0., 0., 0.), - u: typing.Iterable[float, float, float] = (0., 0., 1.), + r: Tuple[float, float, float] = (0., 0., 0.), + u: Tuple[float, float, float] = (0., 0., 1.), E: float = 1.0e6, time: float = 0.0, wgt: float = 1.0, @@ -401,7 +401,7 @@ class SourceParticle: def write_source_file( - source_particles: typing.Iterable[openmc.SourceParticle], + source_particles: 'typing.Iterable[openmc.SourceParticle]', filename: PathLike, **kwargs ): """Write a source file using a collection of source particles From a9933c5ecf948bcbfbadb4b03156e5c2db2e5822 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 24 Oct 2022 13:23:15 -0400 Subject: [PATCH 1198/2654] bounds.reshape doesn't modify bounds it returns a new array --- openmc/weight_windows.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index eb30e838a..7e5f41bb1 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -206,9 +206,9 @@ class WeightWindows(IDManagerMixin): # reshape data according to mesh and energy bins bounds = np.asarray(bounds) if isinstance(self.mesh, UnstructuredMesh): - bounds.reshape(-1, self.num_energy_bins) + bounds = bounds.reshape(-1, self.num_energy_bins) else: - bounds.reshape(*self.mesh.dimension, self.num_energy_bins) + bounds = bounds.reshape(*self.mesh.dimension, self.num_energy_bins) self._lower_ww_bounds = bounds @property @@ -225,9 +225,9 @@ class WeightWindows(IDManagerMixin): # reshape data according to mesh and energy bins bounds = np.asarray(bounds) if isinstance(self.mesh, UnstructuredMesh): - bounds.reshape(-1, self.num_energy_bins) + bounds = bounds.reshape(-1, self.num_energy_bins) else: - bounds.reshape(*self.mesh.dimension, self.num_energy_bins) + bounds = bounds.reshape(*self.mesh.dimension, self.num_energy_bins) self._upper_ww_bounds = bounds @property From 58b1a80b64011fc608232bed0522b991fbb93185 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Mon, 24 Oct 2022 13:02:09 -0500 Subject: [PATCH 1199/2654] small grammar fix in Settings.temperature docstring --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index ad5a9b28a..5aaebdfe4 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -188,7 +188,7 @@ class Settings: Kelvin. The value for 'method' should be 'nearest' or 'interpolation'. If the method is 'nearest', 'tolerance' indicates a range of temperature within which cross sections may be used. The value for 'range' should be - a pair a minimum and maximum temperatures which are used to indicate + a pair of a minimum and maximum temperature which are used to indicate that cross sections be loaded at all temperatures within the range. 'multipole' is a boolean indicating whether or not the windowed multipole method should be used to evaluate resolved resonance cross From 3d26f1992c9389a7356051b0d379a88eb730c516 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 24 Oct 2022 19:13:22 +0100 Subject: [PATCH 1200/2654] added test for lower ww shape --- tests/unit_tests/weightwindows/test.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit_tests/weightwindows/test.py b/tests/unit_tests/weightwindows/test.py index d065ef6d2..51e2fdc62 100644 --- a/tests/unit_tests/weightwindows/test.py +++ b/tests/unit_tests/weightwindows/test.py @@ -195,3 +195,19 @@ def test_weightwindows(model): compare_results('neutron', analog_tally, ww_tally) compare_results('photon', analog_tally, ww_tally) + + +def test_lower_ww_bounds_shape(): + """checks that lower_ww_bounds is reshaped to the mesh dimension when set""" + ww_mesh = openmc.RegularMesh() + ww_mesh.lower_left = (-10, -10, -10) + ww_mesh.upper_right = (10, 10, 10) + ww_mesh.dimension = (2, 3, 4) + + ww = openmc.WeightWindows( + mesh=ww_mesh, + lower_ww_bounds=[1]*24, + upper_bound_ratio=5, + energy_bounds=(1, 1e40) + ) + assert ww.lower_ww_bounds.shape == (2, 3, 4, 1) From 89ba5afb6ccd4c6e81824b149b29a8d734e98b36 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Mon, 24 Oct 2022 13:36:36 -0500 Subject: [PATCH 1201/2654] Use @lewisgross1296 suggestion Co-authored-by: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 5aaebdfe4..d60c6cb64 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -188,7 +188,7 @@ class Settings: Kelvin. The value for 'method' should be 'nearest' or 'interpolation'. If the method is 'nearest', 'tolerance' indicates a range of temperature within which cross sections may be used. The value for 'range' should be - a pair of a minimum and maximum temperature which are used to indicate + a pair of minimum and maximum temperatures which are used to indicate that cross sections be loaded at all temperatures within the range. 'multipole' is a boolean indicating whether or not the windowed multipole method should be used to evaluate resolved resonance cross From d78433ad3dcf2dc648a81f3032e2b2a537a88f6b Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 24 Oct 2022 16:47:34 -0400 Subject: [PATCH 1202/2654] reshape in from_xml and update inputs --- openmc/weight_windows.py | 5 +++++ tests/regression_tests/weightwindows/inputs_true.dat | 8 ++++---- tests/regression_tests/weightwindows/results_true.dat | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 7e5f41bb1..4088cb2d4 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -341,6 +341,11 @@ class WeightWindows(IDManagerMixin): particle_type = get_text(elem, 'particle_type') survival_ratio = float(get_text(elem, 'survival_ratio')) + ww_shape = (len(e_bounds) - 1,) + mesh.dimension[::-1] + print(ww_shape) + lower_ww_bounds = np.array(lower_ww_bounds).reshape(ww_shape).T + upper_ww_bounds = np.array(upper_ww_bounds).reshape(ww_shape).T + max_lower_bound_ratio = None if get_text(elem, 'max_lower_bound_ratio'): max_lower_bound_ratio = float(get_text(elem, 'max_lower_bound_ratio')) diff --git a/tests/regression_tests/weightwindows/inputs_true.dat b/tests/regression_tests/weightwindows/inputs_true.dat index e6a0ad55f..eb42baddf 100644 --- a/tests/regression_tests/weightwindows/inputs_true.dat +++ b/tests/regression_tests/weightwindows/inputs_true.dat @@ -48,8 +48,8 @@ 2 neutron 0.0 0.5 20000000.0 - -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 7.695031155172816e-14 -1.0 7.476545089278482e-06 -1.0 2.1612150425221703e-06 -1.0 -1.0 -1.0 2.1360401784344975e-18 -1.0 1.3455341306162382e-05 -1.0 3.353295403842037e-05 -1.0 3.0160758454323657e-07 -1.0 1.0262431550731535e-13 -1.0 1.6859219614058024e-19 -1.0 3.853097455417877e-06 -1.0 4.354946981329799e-05 -1.0 7.002861620919232e-08 -1.0 -1.0 -1.0 -1.0 -1.0 1.6205064883026195e-11 -1.0 1.7041669224797384e-09 -1.0 1.8747824667478637e-14 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 5.619835883512353e-14 -1.0 1.951356547084204e-15 -1.0 8.48176145671274e-10 -1.0 -1.0 -1.0 1.4508262073256659e-13 -1.0 4.109066205029878e-05 -1.0 0.00020573181450240786 -1.0 2.124999182004655e-05 -1.0 5.5379154134462336e-08 -1.0 1.5550455959178486e-06 -1.0 0.0007213722022489493 -1.0 0.007673145137236567 -1.0 0.0008175033526488423 -1.0 1.008394964750947e-06 -1.0 6.848642863465585e-07 -1.0 0.0010737081832502356 -1.0 0.007197662162700777 -1.0 0.0007151459162818186 -1.0 2.253382683081525e-06 -1.0 1.3181562352445092e-10 -1.0 1.93847081892941e-05 -1.0 0.00046029617115127556 -1.0 2.5629068330446215e-05 -1.0 5.504813693036933e-12 -1.0 -1.0 -1.0 3.3164825349503764e-16 -1.0 3.937160538176268e-07 -1.0 -1.0 -1.0 -1.0 -1.0 1.5172912057312398e-14 -1.0 6.315154082213375e-07 -1.0 3.855884234344845e-06 -1.0 1.7770136411255912e-05 -1.0 1.6421491993751715e-11 -1.0 5.97653814110781e-06 -1.0 0.001959411999677113 -1.0 0.013330619853379314 -1.0 0.0017950613169359904 -1.0 2.4306375693722205e-06 -1.0 6.922231352729155e-05 -1.0 0.08657573566388353 -1.0 -1.0 -1.0 0.0835648710074336 -1.0 0.00016419031150495913 -1.0 9.03108551826469e-05 -1.0 0.0848872967381878 -1.0 -1.0 -1.0 0.08288806458368345 -1.0 5.6949597066784976e-05 -1.0 8.037131813528501e-07 -1.0 0.0016637126543321873 -1.0 0.01664109232689093 -1.0 0.0018327593437608 -1.0 6.542700644645627e-07 -1.0 -1.0 -1.0 6.655926357459275e-08 -1.0 5.783974359937857e-06 -1.0 2.679340942769232e-06 -1.0 -1.0 -1.0 -1.0 -1.0 2.1040609012865134e-05 -1.0 2.9282097947816224e-05 -1.0 1.284759166582202e-05 -1.0 1.0092905083158804e-11 -1.0 1.3228013765525015e-05 -1.0 0.007136750029575816 -1.0 0.06539005235506369 -1.0 0.0064803314120165335 -1.0 2.6011787393916806e-06 -1.0 8.887234042637684e-05 -1.0 0.5 -1.0 -1.0 -1.0 0.4877856021170283 -1.0 0.00017699858357744463 -1.0 0.0001670700632870335 -1.0 0.4899999304038166 -1.0 -1.0 -1.0 0.48573842213878143 -1.0 0.00021534568699157805 -1.0 7.84289689494925e-06 -1.0 0.0063790654507599135 -1.0 0.06550426960512012 -1.0 0.006639379668946672 -1.0 7.754700849337902e-06 -1.0 2.7207433165796702e-11 -1.0 5.985108617124989e-06 -1.0 3.634644995026692e-05 -1.0 3.932389299316285e-06 -1.0 -1.0 -1.0 -1.0 -1.0 1.271128669411295e-07 -1.0 8.846493399850663e-06 -1.0 2.499931357628383e-07 -1.0 8.533030345699353e-17 -1.0 1.6699254277734109e-06 -1.0 0.0017541380096893788 -1.0 0.015148978428271613 -1.0 0.0016279794552427574 -1.0 2.380955631371226e-06 -1.0 2.1648918040467363e-05 -1.0 0.0833931797381589 -1.0 -1.0 -1.0 0.08285899874014539 -1.0 2.762955748645507e-05 -1.0 5.1161740516205715e-05 -1.0 0.08095280568305474 -1.0 -1.0 -1.0 0.08636569925236791 -1.0 3.452537179033895e-05 -1.0 3.5981031766416143e-06 -1.0 0.001570829313580841 -1.0 0.01621821782442112 -1.0 0.0015447823995470042 -1.0 7.989579285134734e-06 -1.0 -1.0 -1.0 2.594951085377588e-06 -1.0 4.323138781337963e-05 -1.0 6.948292975998466e-07 -1.0 -1.0 -1.0 -1.0 -1.0 2.4469456008493614e-09 -1.0 9.041149893307806e-07 -1.0 2.2060992580622125e-11 -1.0 -1.0 -1.0 1.681305446488884e-11 -1.0 7.091263906557291e-05 -1.0 0.00027464244062887683 -1.0 1.28584557092134e-05 -1.0 2.0295213621716706e-09 -1.0 1.2911827198500372e-08 -1.0 0.0009127050763987511 -1.0 0.007385384405891666 -1.0 0.0010019432401508087 -1.0 1.080711295768551e-05 -1.0 8.020767115181574e-07 -1.0 0.0009252532821720597 -1.0 0.007188410694198128 -1.0 0.0007245451610090619 -1.0 2.5157355790201773e-07 -1.0 1.4825219199133353e-12 -1.0 4.756872959630257e-05 -1.0 0.0002668579837809081 -1.0 2.8226276944532696e-05 -1.0 5.182269672663266e-10 -1.0 -1.0 -1.0 2.936268747135548e-14 -1.0 2.5447281241730366e-07 -1.0 3.89841667138598e-08 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 2.639268952045579e-10 -1.0 3.7051518220083886e-06 -1.0 1.1333627604823673e-09 -1.0 -1.0 -1.0 -1.0 -1.0 1.2296747260635405e-06 -1.0 7.962899789920809e-06 -1.0 8.211982683649991e-09 -1.0 -1.0 -1.0 -1.0 -1.0 2.5639656866250453e-06 -1.0 2.2487617828938326e-05 -1.0 3.2799045883372075e-06 -1.0 4.076762579823379e-17 -1.0 1.5476769237571295e-14 -1.0 1.0305672698745657e-11 -1.0 1.957092814065688e-05 -1.0 3.8523247550378815e-12 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 2.7697233171399416e-13 -1.0 -1.0 -1.0 -1.0 -1.0 - -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 7.695031155172816e-13 -10.0 7.476545089278483e-05 -10.0 2.1612150425221703e-05 -10.0 -10.0 -10.0 2.1360401784344976e-17 -10.0 0.00013455341306162382 -10.0 0.00033532954038420373 -10.0 3.0160758454323656e-06 -10.0 1.0262431550731535e-12 -10.0 1.6859219614058023e-18 -10.0 3.853097455417877e-05 -10.0 0.00043549469813297995 -10.0 7.002861620919232e-07 -10.0 -10.0 -10.0 -10.0 -10.0 1.6205064883026195e-10 -10.0 1.7041669224797384e-08 -10.0 1.8747824667478637e-13 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 5.619835883512353e-13 -10.0 1.951356547084204e-14 -10.0 8.48176145671274e-09 -10.0 -10.0 -10.0 1.4508262073256658e-12 -10.0 0.0004109066205029878 -10.0 0.0020573181450240785 -10.0 0.00021249991820046548 -10.0 5.537915413446234e-07 -10.0 1.5550455959178486e-05 -10.0 0.0072137220224894934 -10.0 0.07673145137236567 -10.0 0.008175033526488424 -10.0 1.0083949647509469e-05 -10.0 6.848642863465585e-06 -10.0 0.010737081832502356 -10.0 0.07197662162700777 -10.0 0.007151459162818186 -10.0 2.253382683081525e-05 -10.0 1.3181562352445092e-09 -10.0 0.000193847081892941 -10.0 0.004602961711512756 -10.0 0.00025629068330446217 -10.0 5.504813693036933e-11 -10.0 -10.0 -10.0 3.3164825349503764e-15 -10.0 3.937160538176268e-06 -10.0 -10.0 -10.0 -10.0 -10.0 1.51729120573124e-13 -10.0 6.3151540822133754e-06 -10.0 3.855884234344845e-05 -10.0 0.0001777013641125591 -10.0 1.6421491993751715e-10 -10.0 5.97653814110781e-05 -10.0 0.01959411999677113 -10.0 0.13330619853379314 -10.0 0.017950613169359905 -10.0 2.4306375693722206e-05 -10.0 0.0006922231352729155 -10.0 0.8657573566388354 -10.0 -10.0 -10.0 0.8356487100743359 -10.0 0.0016419031150495913 -10.0 0.000903108551826469 -10.0 0.848872967381878 -10.0 -10.0 -10.0 0.8288806458368345 -10.0 0.0005694959706678497 -10.0 8.037131813528501e-06 -10.0 0.016637126543321872 -10.0 0.1664109232689093 -10.0 0.018327593437608 -10.0 6.5427006446456266e-06 -10.0 -10.0 -10.0 6.655926357459275e-07 -10.0 5.7839743599378564e-05 -10.0 2.679340942769232e-05 -10.0 -10.0 -10.0 -10.0 -10.0 0.00021040609012865135 -10.0 0.00029282097947816227 -10.0 0.0001284759166582202 -10.0 1.0092905083158804e-10 -10.0 0.00013228013765525016 -10.0 0.07136750029575815 -10.0 0.6539005235506369 -10.0 0.06480331412016534 -10.0 2.6011787393916804e-05 -10.0 0.0008887234042637684 -10.0 5.0 -10.0 -10.0 -10.0 4.877856021170283 -10.0 0.0017699858357744464 -10.0 0.001670700632870335 -10.0 4.899999304038166 -10.0 -10.0 -10.0 4.8573842213878144 -10.0 0.0021534568699157807 -10.0 7.84289689494925e-05 -10.0 0.06379065450759913 -10.0 0.6550426960512012 -10.0 0.06639379668946672 -10.0 7.754700849337902e-05 -10.0 2.7207433165796704e-10 -10.0 5.985108617124989e-05 -10.0 0.0003634644995026692 -10.0 3.9323892993162844e-05 -10.0 -10.0 -10.0 -10.0 -10.0 1.271128669411295e-06 -10.0 8.846493399850663e-05 -10.0 2.499931357628383e-06 -10.0 8.533030345699353e-16 -10.0 1.669925427773411e-05 -10.0 0.017541380096893787 -10.0 0.15148978428271614 -10.0 0.016279794552427576 -10.0 2.380955631371226e-05 -10.0 0.00021648918040467362 -10.0 0.8339317973815891 -10.0 -10.0 -10.0 0.828589987401454 -10.0 0.0002762955748645507 -10.0 0.0005116174051620571 -10.0 0.8095280568305474 -10.0 -10.0 -10.0 0.8636569925236791 -10.0 0.0003452537179033895 -10.0 3.5981031766416144e-05 -10.0 0.015708293135808408 -10.0 0.16218217824421122 -10.0 0.015447823995470043 -10.0 7.989579285134734e-05 -10.0 -10.0 -10.0 2.594951085377588e-05 -10.0 0.0004323138781337963 -10.0 6.948292975998466e-06 -10.0 -10.0 -10.0 -10.0 -10.0 2.4469456008493615e-08 -10.0 9.041149893307805e-06 -10.0 2.2060992580622125e-10 -10.0 -10.0 -10.0 1.681305446488884e-10 -10.0 0.0007091263906557291 -10.0 0.002746424406288768 -10.0 0.000128584557092134 -10.0 2.0295213621716707e-08 -10.0 1.2911827198500372e-07 -10.0 0.009127050763987512 -10.0 0.07385384405891665 -10.0 0.010019432401508087 -10.0 0.0001080711295768551 -10.0 8.020767115181574e-06 -10.0 0.009252532821720597 -10.0 0.07188410694198127 -10.0 0.0072454516100906195 -10.0 2.515735579020177e-06 -10.0 1.4825219199133352e-11 -10.0 0.0004756872959630257 -10.0 0.0026685798378090807 -10.0 0.000282262769445327 -10.0 5.182269672663266e-09 -10.0 -10.0 -10.0 2.9362687471355483e-13 -10.0 2.5447281241730365e-06 -10.0 3.89841667138598e-07 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 2.639268952045579e-09 -10.0 3.7051518220083885e-05 -10.0 1.1333627604823672e-08 -10.0 -10.0 -10.0 -10.0 -10.0 1.2296747260635405e-05 -10.0 7.96289978992081e-05 -10.0 8.211982683649991e-08 -10.0 -10.0 -10.0 -10.0 -10.0 2.5639656866250452e-05 -10.0 0.00022487617828938325 -10.0 3.2799045883372076e-05 -10.0 4.076762579823379e-16 -10.0 1.5476769237571296e-13 -10.0 1.0305672698745658e-10 -10.0 0.0001957092814065688 -10.0 3.852324755037882e-11 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 2.7697233171399415e-12 -10.0 -10.0 -10.0 -10.0 -10.0 + -1.0 0.007673145137236567 6.542700644645627e-07 0.0017541380096893788 0.0007245451610090619 7.476545089278482e-06 2.253382683081525e-06 2.1040609012865134e-05 0.08285899874014539 -1.0 1.0262431550731535e-13 3.3164825349503764e-16 0.0064803314120165335 3.5981031766416143e-06 -1.0 1.6205064883026195e-11 1.7770136411255912e-05 0.0001670700632870335 4.323138781337963e-05 -1.0 -1.0 6.922231352729155e-05 0.06550426960512012 -1.0 2.5639656866250453e-06 1.4508262073256659e-13 -1.0 -1.0 0.0009127050763987511 3.8523247550378815e-12 -1.0 0.0008175033526488423 -1.0 0.015148978428271613 2.5157355790201773e-07 2.1612150425221703e-06 1.3181562352445092e-10 2.9282097947816224e-05 2.762955748645507e-05 2.936268747135548e-14 1.6859219614058024e-19 3.937160538176268e-07 2.6011787393916806e-06 0.001570829313580841 -1.0 1.7041669224797384e-09 1.6421491993751715e-11 0.4899999304038166 6.948292975998466e-07 -1.0 -1.0 0.08657573566388353 0.006639379668946672 1.681305446488884e-11 2.2487617828938326e-05 4.109066205029878e-05 0.08288806458368345 -1.0 0.007385384405891666 -1.0 -1.0 1.008394964750947e-06 6.655926357459275e-08 0.0016279794552427574 1.4825219199133353e-12 -1.0 1.93847081892941e-05 1.284759166582202e-05 5.1161740516205715e-05 2.5447281241730366e-07 3.853097455417877e-06 -1.0 8.887234042637684e-05 0.01621821782442112 -1.0 1.8747824667478637e-14 5.97653814110781e-06 -1.0 -1.0 1.2296747260635405e-06 -1.0 -1.0 7.754700849337902e-06 7.091263906557291e-05 3.2799045883372075e-06 0.00020573181450240786 5.6949597066784976e-05 1.271128669411295e-07 0.0010019432401508087 -1.0 -1.0 6.848642863465585e-07 5.783974359937857e-06 2.380955631371226e-06 4.756872959630257e-05 2.1360401784344975e-18 0.00046029617115127556 1.0092905083158804e-11 0.08095280568305474 3.89841667138598e-08 4.354946981329799e-05 -1.0 0.5 0.0015447823995470042 -1.0 -1.0 0.001959411999677113 0.48573842213878143 -1.0 7.962899789920809e-06 5.619835883512353e-14 0.0835648710074336 2.7207433165796702e-11 0.00027464244062887683 4.076762579823379e-17 2.124999182004655e-05 8.037131813528501e-07 8.846493399850663e-06 1.080711295768551e-05 -1.0 -1.0 0.0010737081832502356 2.679340942769232e-06 2.1648918040467363e-05 0.0002668579837809081 1.3455341306162382e-05 2.5629068330446215e-05 1.3228013765525015e-05 -1.0 -1.0 7.002861620919232e-08 1.5172912057312398e-14 -1.0 7.989579285134734e-06 2.639268952045579e-10 -1.0 0.013330619853379314 0.00021534568699157805 2.4469456008493614e-09 8.211982683649991e-09 1.951356547084204e-15 0.00016419031150495913 5.985108617124989e-06 1.28584557092134e-05 1.5476769237571295e-14 5.5379154134462336e-08 0.0016637126543321873 2.499931357628383e-07 8.020767115181574e-07 2.7697233171399416e-13 -1.0 0.007197662162700777 -1.0 0.0833931797381589 2.8226276944532696e-05 3.353295403842037e-05 5.504813693036933e-12 0.007136750029575816 0.08636569925236791 -1.0 -1.0 6.315154082213375e-07 0.4877856021170283 -1.0 3.7051518220083886e-06 -1.0 0.0017950613169359904 7.84289689494925e-06 9.041149893307806e-07 -1.0 8.48176145671274e-10 9.03108551826469e-05 3.634644995026692e-05 2.0295213621716706e-09 1.0305672698745657e-11 1.5550455959178486e-06 0.01664109232689093 8.533030345699353e-17 0.0009252532821720597 -1.0 7.695031155172816e-14 0.0007151459162818186 -1.0 -1.0 5.182269672663266e-10 3.0160758454323657e-07 -1.0 0.06539005235506369 3.452537179033895e-05 -1.0 -1.0 3.855884234344845e-06 0.00017699858357744463 2.594951085377588e-06 1.1333627604823673e-09 -1.0 2.4306375693722205e-06 0.0063790654507599135 2.2060992580622125e-11 -1.0 -1.0 0.0848872967381878 3.932389299316285e-06 1.2911827198500372e-08 1.957092814065688e-05 0.0007213722022489493 0.0018327593437608 1.6699254277734109e-06 0.007188410694198128 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 + -10.0 0.07673145137236567 6.5427006446456266e-06 0.017541380096893787 0.0072454516100906195 7.476545089278483e-05 2.253382683081525e-05 0.00021040609012865135 0.828589987401454 -10.0 1.0262431550731535e-12 3.3164825349503764e-15 0.06480331412016534 3.5981031766416144e-05 -10.0 1.6205064883026195e-10 0.0001777013641125591 0.001670700632870335 0.0004323138781337963 -10.0 -10.0 0.0006922231352729155 0.6550426960512012 -10.0 2.5639656866250452e-05 1.4508262073256658e-12 -10.0 -10.0 0.009127050763987512 3.852324755037882e-11 -10.0 0.008175033526488424 -10.0 0.15148978428271614 2.515735579020177e-06 2.1612150425221703e-05 1.3181562352445092e-09 0.00029282097947816227 0.0002762955748645507 2.9362687471355483e-13 1.6859219614058023e-18 3.937160538176268e-06 2.6011787393916804e-05 0.015708293135808408 -10.0 1.7041669224797384e-08 1.6421491993751715e-10 4.899999304038166 6.948292975998466e-06 -10.0 -10.0 0.8657573566388354 0.06639379668946672 1.681305446488884e-10 0.00022487617828938325 0.0004109066205029878 0.8288806458368345 -10.0 0.07385384405891665 -10.0 -10.0 1.0083949647509469e-05 6.655926357459275e-07 0.016279794552427576 1.4825219199133352e-11 -10.0 0.000193847081892941 0.0001284759166582202 0.0005116174051620571 2.5447281241730365e-06 3.853097455417877e-05 -10.0 0.0008887234042637684 0.16218217824421122 -10.0 1.8747824667478637e-13 5.97653814110781e-05 -10.0 -10.0 1.2296747260635405e-05 -10.0 -10.0 7.754700849337902e-05 0.0007091263906557291 3.2799045883372076e-05 0.0020573181450240785 0.0005694959706678497 1.271128669411295e-06 0.010019432401508087 -10.0 -10.0 6.848642863465585e-06 5.7839743599378564e-05 2.380955631371226e-05 0.0004756872959630257 2.1360401784344976e-17 0.004602961711512756 1.0092905083158804e-10 0.8095280568305474 3.89841667138598e-07 0.00043549469813297995 -10.0 5.0 0.015447823995470043 -10.0 -10.0 0.01959411999677113 4.8573842213878144 -10.0 7.96289978992081e-05 5.619835883512353e-13 0.8356487100743359 2.7207433165796704e-10 0.002746424406288768 4.076762579823379e-16 0.00021249991820046548 8.037131813528501e-06 8.846493399850663e-05 0.0001080711295768551 -10.0 -10.0 0.010737081832502356 2.679340942769232e-05 0.00021648918040467362 0.0026685798378090807 0.00013455341306162382 0.00025629068330446217 0.00013228013765525016 -10.0 -10.0 7.002861620919232e-07 1.51729120573124e-13 -10.0 7.989579285134734e-05 2.639268952045579e-09 -10.0 0.13330619853379314 0.0021534568699157807 2.4469456008493615e-08 8.211982683649991e-08 1.951356547084204e-14 0.0016419031150495913 5.985108617124989e-05 0.000128584557092134 1.5476769237571296e-13 5.537915413446234e-07 0.016637126543321872 2.499931357628383e-06 8.020767115181574e-06 2.7697233171399415e-12 -10.0 0.07197662162700777 -10.0 0.8339317973815891 0.000282262769445327 0.00033532954038420373 5.504813693036933e-11 0.07136750029575815 0.8636569925236791 -10.0 -10.0 6.3151540822133754e-06 4.877856021170283 -10.0 3.7051518220083885e-05 -10.0 0.017950613169359905 7.84289689494925e-05 9.041149893307805e-06 -10.0 8.48176145671274e-09 0.000903108551826469 0.0003634644995026692 2.0295213621716707e-08 1.0305672698745658e-10 1.5550455959178486e-05 0.1664109232689093 8.533030345699353e-16 0.009252532821720597 -10.0 7.695031155172816e-13 0.007151459162818186 -10.0 -10.0 5.182269672663266e-09 3.0160758454323656e-06 -10.0 0.6539005235506369 0.0003452537179033895 -10.0 -10.0 3.855884234344845e-05 0.0017699858357744464 2.594951085377588e-05 1.1333627604823672e-08 -10.0 2.4306375693722206e-05 0.06379065450759913 2.2060992580622125e-10 -10.0 -10.0 0.848872967381878 3.9323892993162844e-05 1.2911827198500372e-07 0.0001957092814065688 0.0072137220224894934 0.018327593437608 1.669925427773411e-05 0.07188410694198127 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 3 1.5 10 @@ -64,8 +64,8 @@ 2 neutron 0.0 0.5 20000000.0 - -1.0 -1.0 -1.0 5.447493368067179e-10 -1.0 4.0404626147344e-13 -1.0 9.382800796426366e-17 -1.0 -1.0 -1.0 5.752120832330886e-11 -1.0 3.520674728719278e-05 -1.0 8.76041935303527e-05 -1.0 3.136829920007009e-05 -1.0 -1.0 -1.0 4.233410073487772e-06 -1.0 0.00025519632243117644 -1.0 0.0004777967757842694 -1.0 0.00035983547999740665 -1.0 4.6258592060517866e-07 -1.0 4.587143797469485e-08 -1.0 0.00012918433677593975 -1.0 0.000469589568463265 -1.0 8.862760180332873e-05 -1.0 3.2790914744011534e-06 -1.0 1.1514579117272292e-10 -1.0 2.2950716170641463e-05 -1.0 6.92296299242814e-05 -1.0 2.1606550732170693e-05 -1.0 2.617878055106949e-16 -1.0 -1.0 -1.0 -1.0 -1.0 1.722191123879782e-08 -1.0 -1.0 -1.0 -1.0 -1.0 2.1234980618763222e-13 -1.0 1.4628847959717225e-05 -1.0 2.777791741571174e-05 -1.0 9.53380658669839e-06 -1.0 1.078687446476881e-14 -1.0 3.0571050855707084e-06 -1.0 0.0008231482263927564 -1.0 0.0038811025614225057 -1.0 0.0012297303081805393 -1.0 4.6842350882367666e-05 -1.0 0.00016757997590048827 -1.0 0.011724714376848187 -1.0 0.06827568359008944 -1.0 0.011440381012864086 -1.0 0.0003782322077390033 -1.0 5.098747893974248e-05 -1.0 0.01208261392046878 -1.0 0.06428782790571179 -1.0 0.011294708566804167 -1.0 8.168081568291806e-05 -1.0 2.34750482787598e-05 -1.0 0.0008787411098754915 -1.0 0.0051513292132259495 -1.0 0.0011028020390507682 -1.0 1.0882011018684852e-06 -1.0 1.0588257623722672e-07 -1.0 2.7044817176109556e-05 -1.0 2.6211239246796104e-05 -1.0 2.0707648529746894e-06 -1.0 -1.0 -1.0 1.3806577785135177e-06 -1.0 0.00010077009726691265 -1.0 0.00043130977711323417 -1.0 0.0001335621430311088 -1.0 3.792209399652396e-06 -1.0 0.00022057970761624768 -1.0 0.01884234453311008 -1.0 0.11510120013926417 -1.0 0.01825795827020865 -1.0 0.00020848309220162036 -1.0 0.0013332554437480327 -1.0 0.49317081643076643 -1.0 -1.0 -1.0 0.4899952354672477 -1.0 0.0014957033281168012 -1.0 0.001550036616828061 -1.0 0.4897735047310072 -1.0 -1.0 -1.0 0.5 -1.0 0.0011076796092102186 -1.0 0.0002792896409558745 -1.0 0.01721806295736377 -1.0 0.11891251244906934 -1.0 0.019040707071165303 -1.0 0.00017329528628152923 -1.0 4.670673837764874e-08 -1.0 0.00012637534695610975 -1.0 0.00027052054298385255 -1.0 0.0001497958445994315 -1.0 3.2478301680021854e-08 -1.0 7.239087311622819e-08 -1.0 0.00046693784586018913 -1.0 0.001537590300149361 -1.0 0.00023686818807101741 -1.0 8.616027294555462e-07 -1.0 0.0002362355168421952 -1.0 0.05708498338352203 -1.0 0.42372713683725016 -1.0 0.054902816619122045 -1.0 0.00030002326388383244 -1.0 0.0023295401596005313 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 0.0027847329307350423 -1.0 0.003432919201293737 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 0.002672923773363389 -1.0 0.0003182108781955478 -1.0 0.05639071613735579 -1.0 0.4346984808472855 -1.0 0.05500108683629957 -1.0 0.00024175998138228048 -1.0 2.774067049392004e-07 -1.0 0.0003257646134837451 -1.0 0.0012648333883989995 -1.0 0.0002981891705231209 -1.0 4.986698316296507e-06 -1.0 3.419181071650816e-06 -1.0 0.00010814452764860558 -1.0 0.0006934466049804711 -1.0 0.00025106741008066317 -1.0 5.515522196186723e-06 -1.0 0.00014242053195529864 -1.0 0.018541112907970003 -1.0 0.12364069326350118 -1.0 0.017602971074583987 -1.0 0.00021305826462238593 -1.0 0.0015016500045374082 -1.0 0.4903495510314233 -1.0 -1.0 -1.0 0.4952432605379829 -1.0 0.0017693279949094218 -1.0 0.0009304497896205121 -1.0 0.4873897581604287 -1.0 -1.0 -1.0 0.4981497862127628 -1.0 0.0011273340972061078 -1.0 0.00014126153603265097 -1.0 0.01729816946709781 -1.0 0.11819165666519223 -1.0 0.017802624844035688 -1.0 0.0001319677450153934 -1.0 2.210707325798542e-07 -1.0 0.00017287873387910357 -1.0 0.0005197081842709918 -1.0 9.256616392487858e-05 -1.0 1.0325207105027347e-08 -1.0 2.027381220364608e-16 -1.0 1.2257360246712472e-05 -1.0 3.8561696337086434e-05 -1.0 1.8064550990294753e-05 -1.0 7.691527781829036e-17 -1.0 1.298062961617927e-05 -1.0 0.001178616843705956 -1.0 0.004441328419270369 -1.0 0.0008919466185572302 -1.0 5.272021975060514e-06 -1.0 0.00016079768514218546 -1.0 0.011128424196387618 -1.0 0.06433819434431046 -1.0 0.010955637485319249 -1.0 8.370896020975689e-05 -1.0 0.00022234471595443313 -1.0 0.01102706140784316 -1.0 0.06684484191345574 -1.0 0.011113024641218336 -1.0 0.00012558879474108074 -1.0 1.0044390728858277e-05 -1.0 0.000808100901275472 -1.0 0.005384625561469684 -1.0 0.001146714816952061 -1.0 3.5740607788414942e-06 -1.0 2.2512327083641865e-10 -1.0 6.717625881826167e-05 -1.0 6.949587369646497e-05 -1.0 2.9093345975075226e-05 -1.0 -1.0 -1.0 -1.0 -1.0 8.582011716859219e-15 -1.0 8.304845400451923e-08 -1.0 4.5757238372058234e-11 -1.0 -1.0 -1.0 1.3116807133030035e-15 -1.0 2.6866894852481906e-05 -1.0 4.3166052799897375e-05 -1.0 6.401055165502384e-06 -1.0 5.726152701849347e-16 -1.0 8.541606727879512e-07 -1.0 0.0002029396545382813 -1.0 0.0004299195570308035 -1.0 8.544159282151438e-05 -1.0 1.0995322456277382e-06 -1.0 1.289814511028015e-06 -1.0 0.00011042047857307253 -1.0 0.0006870228272606287 -1.0 0.0001399807456616496 -1.0 4.279460329782799e-09 -1.0 1.2907171695294846e-13 -1.0 1.9257248009114363e-05 -1.0 9.332371598523186e-05 -1.0 1.3106335518133802e-05 -1.0 6.574706543646946e-16 -1.0 -1.0 -1.0 3.8270536025799805e-15 -1.0 2.101790478097517e-09 -1.0 9.904481358675478e-13 -1.0 -1.0 - -10.0 -10.0 -10.0 5.447493368067179e-09 -10.0 4.0404626147344005e-12 -10.0 9.382800796426367e-16 -10.0 -10.0 -10.0 5.752120832330886e-10 -10.0 0.0003520674728719278 -10.0 0.0008760419353035269 -10.0 0.0003136829920007009 -10.0 -10.0 -10.0 4.233410073487772e-05 -10.0 0.0025519632243117644 -10.0 0.004777967757842694 -10.0 0.0035983547999740664 -10.0 4.625859206051786e-06 -10.0 4.587143797469485e-07 -10.0 0.0012918433677593976 -10.0 0.0046958956846326495 -10.0 0.0008862760180332873 -10.0 3.279091474401153e-05 -10.0 1.151457911727229e-09 -10.0 0.00022950716170641464 -10.0 0.0006922962992428139 -10.0 0.00021606550732170693 -10.0 2.6178780551069492e-15 -10.0 -10.0 -10.0 -10.0 -10.0 1.722191123879782e-07 -10.0 -10.0 -10.0 -10.0 -10.0 2.123498061876322e-12 -10.0 0.00014628847959717226 -10.0 0.0002777791741571174 -10.0 9.53380658669839e-05 -10.0 1.078687446476881e-13 -10.0 3.0571050855707086e-05 -10.0 0.008231482263927564 -10.0 0.03881102561422506 -10.0 0.012297303081805393 -10.0 0.00046842350882367664 -10.0 0.0016757997590048828 -10.0 0.11724714376848187 -10.0 0.6827568359008944 -10.0 0.11440381012864086 -10.0 0.003782322077390033 -10.0 0.0005098747893974248 -10.0 0.1208261392046878 -10.0 0.6428782790571179 -10.0 0.11294708566804167 -10.0 0.0008168081568291806 -10.0 0.000234750482787598 -10.0 0.008787411098754914 -10.0 0.0515132921322595 -10.0 0.011028020390507681 -10.0 1.0882011018684853e-05 -10.0 1.0588257623722672e-06 -10.0 0.00027044817176109554 -10.0 0.000262112392467961 -10.0 2.0707648529746893e-05 -10.0 -10.0 -10.0 1.3806577785135176e-05 -10.0 0.0010077009726691265 -10.0 0.004313097771132342 -10.0 0.001335621430311088 -10.0 3.792209399652396e-05 -10.0 0.0022057970761624767 -10.0 0.1884234453311008 -10.0 1.1510120013926417 -10.0 0.1825795827020865 -10.0 0.0020848309220162036 -10.0 0.013332554437480326 -10.0 4.931708164307665 -10.0 -10.0 -10.0 4.899952354672477 -10.0 0.014957033281168012 -10.0 0.01550036616828061 -10.0 4.897735047310072 -10.0 -10.0 -10.0 5.0 -10.0 0.011076796092102187 -10.0 0.002792896409558745 -10.0 0.17218062957363772 -10.0 1.1891251244906933 -10.0 0.19040707071165303 -10.0 0.0017329528628152924 -10.0 4.670673837764874e-07 -10.0 0.0012637534695610975 -10.0 0.0027052054298385255 -10.0 0.001497958445994315 -10.0 3.2478301680021856e-07 -10.0 7.239087311622819e-07 -10.0 0.004669378458601891 -10.0 0.01537590300149361 -10.0 0.002368681880710174 -10.0 8.61602729455546e-06 -10.0 0.002362355168421952 -10.0 0.5708498338352204 -10.0 4.237271368372502 -10.0 0.5490281661912204 -10.0 0.0030002326388383245 -10.0 0.023295401596005315 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 0.027847329307350423 -10.0 0.03432919201293737 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 0.026729237733633893 -10.0 0.0031821087819554777 -10.0 0.5639071613735579 -10.0 4.346984808472855 -10.0 0.5500108683629957 -10.0 0.0024175998138228046 -10.0 2.774067049392004e-06 -10.0 0.0032576461348374514 -10.0 0.012648333883989995 -10.0 0.002981891705231209 -10.0 4.986698316296507e-05 -10.0 3.419181071650816e-05 -10.0 0.0010814452764860557 -10.0 0.006934466049804711 -10.0 0.0025106741008066318 -10.0 5.515522196186723e-05 -10.0 0.0014242053195529865 -10.0 0.18541112907970003 -10.0 1.2364069326350118 -10.0 0.17602971074583987 -10.0 0.0021305826462238594 -10.0 0.015016500045374082 -10.0 4.903495510314233 -10.0 -10.0 -10.0 4.952432605379829 -10.0 0.01769327994909422 -10.0 0.00930449789620512 -10.0 4.873897581604287 -10.0 -10.0 -10.0 4.981497862127628 -10.0 0.011273340972061077 -10.0 0.0014126153603265096 -10.0 0.1729816946709781 -10.0 1.1819165666519222 -10.0 0.1780262484403569 -10.0 0.001319677450153934 -10.0 2.210707325798542e-06 -10.0 0.0017287873387910357 -10.0 0.0051970818427099184 -10.0 0.0009256616392487858 -10.0 1.0325207105027347e-07 -10.0 2.027381220364608e-15 -10.0 0.00012257360246712473 -10.0 0.00038561696337086434 -10.0 0.00018064550990294753 -10.0 7.6915277818290365e-16 -10.0 0.00012980629616179268 -10.0 0.01178616843705956 -10.0 0.04441328419270369 -10.0 0.008919466185572301 -10.0 5.272021975060514e-05 -10.0 0.0016079768514218546 -10.0 0.11128424196387618 -10.0 0.6433819434431045 -10.0 0.10955637485319249 -10.0 0.0008370896020975689 -10.0 0.0022234471595443312 -10.0 0.1102706140784316 -10.0 0.6684484191345574 -10.0 0.11113024641218336 -10.0 0.0012558879474108074 -10.0 0.00010044390728858278 -10.0 0.00808100901275472 -10.0 0.05384625561469684 -10.0 0.01146714816952061 -10.0 3.574060778841494e-05 -10.0 2.2512327083641864e-09 -10.0 0.0006717625881826168 -10.0 0.0006949587369646498 -10.0 0.0002909334597507523 -10.0 -10.0 -10.0 -10.0 -10.0 8.582011716859219e-14 -10.0 8.304845400451923e-07 -10.0 4.5757238372058235e-10 -10.0 -10.0 -10.0 1.3116807133030034e-14 -10.0 0.00026866894852481903 -10.0 0.00043166052799897375 -10.0 6.401055165502385e-05 -10.0 5.726152701849347e-15 -10.0 8.541606727879512e-06 -10.0 0.0020293965453828133 -10.0 0.004299195570308035 -10.0 0.0008544159282151438 -10.0 1.0995322456277382e-05 -10.0 1.289814511028015e-05 -10.0 0.0011042047857307254 -10.0 0.006870228272606287 -10.0 0.0013998074566164962 -10.0 4.279460329782799e-08 -10.0 1.2907171695294846e-12 -10.0 0.00019257248009114364 -10.0 0.0009332371598523186 -10.0 0.000131063355181338 -10.0 6.574706543646946e-15 -10.0 -10.0 -10.0 3.8270536025799805e-14 -10.0 2.101790478097517e-08 -10.0 9.904481358675478e-12 -10.0 -10.0 + -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 0.06827568359008944 0.00017329528628152923 0.018541112907970003 0.011113024641218336 8.76041935303527e-05 8.168081568291806e-05 0.00046693784586018913 0.4952432605379829 2.2512327083641865e-10 4.6258592060517866e-07 2.7044817176109556e-05 0.054902816619122045 0.00014126153603265097 8.304845400451923e-08 2.2950716170641463e-05 0.0001335621430311088 0.003432919201293737 0.0005197081842709918 5.726152701849347e-16 -1.0 0.0013332554437480327 0.4346984808472855 7.691527781829036e-17 0.00011042047857307253 3.0571050855707084e-06 -1.0 4.986698316296507e-06 0.011128424196387618 1.3106335518133802e-05 5.447493368067179e-10 0.011440381012864086 4.670673837764874e-08 0.12364069326350118 0.00012558879474108074 3.136829920007009e-05 2.34750482787598e-05 0.001537590300149361 0.0017693279949094218 6.717625881826167e-05 4.587143797469485e-08 2.6211239246796104e-05 0.00030002326388383244 0.01729816946709781 4.5757238372058234e-11 6.92296299242814e-05 3.792209399652396e-06 -1.0 9.256616392487858e-05 8.541606727879512e-07 -1.0 0.49317081643076643 0.05500108683629957 1.298062961617927e-05 0.0006870228272606287 0.0008231482263927564 0.5 3.419181071650816e-06 0.06433819434431046 6.574706543646946e-16 4.0404626147344e-13 0.0003782322077390033 0.00012637534695610975 0.017602971074583987 1.0044390728858277e-05 -1.0 0.0008787411098754915 0.00023686818807101741 0.0009304497896205121 6.949587369646497e-05 0.00012918433677593975 2.0707648529746894e-06 0.0023295401596005313 0.11819165666519223 -1.0 2.1606550732170693e-05 0.00022057970761624768 -1.0 1.0325207105027347e-08 0.0002029396545382813 2.1234980618763222e-13 -1.0 0.00024175998138228048 0.001178616843705956 0.0001399807456616496 0.0038811025614225057 0.0011076796092102186 0.00010814452764860558 0.010955637485319249 -1.0 9.382800796426366e-17 5.098747893974248e-05 0.00027052054298385255 0.00021305826462238593 0.000808100901275472 4.233410073487772e-06 0.0051513292132259495 8.616027294555462e-07 0.4873897581604287 2.9093345975075226e-05 0.000469589568463265 -1.0 -1.0 0.017802624844035688 1.3116807133030035e-15 2.617878055106949e-16 0.01884234453311008 -1.0 2.027381220364608e-16 0.0004299195570308035 1.4628847959717225e-05 0.4899952354672477 2.774067049392004e-07 0.004441328419270369 4.279460329782799e-09 0.0012297303081805393 0.0002792896409558745 0.0006934466049804711 8.370896020975689e-05 3.8270536025799805e-15 -1.0 0.01208261392046878 0.0001497958445994315 0.0015016500045374082 0.005384625561469684 0.00025519632243117644 0.0011028020390507682 0.0002362355168421952 -1.0 -1.0 8.862760180332873e-05 1.3806577785135177e-06 -1.0 0.0001319677450153934 2.6866894852481906e-05 -1.0 0.11510120013926417 0.002672923773363389 1.2257360246712472e-05 8.544159282151438e-05 2.777791741571174e-05 0.0014957033281168012 0.0003257646134837451 0.0008919466185572302 1.2907171695294846e-13 4.6842350882367666e-05 0.01721806295736377 0.00025106741008066317 0.00022234471595443313 2.101790478097517e-09 5.752120832330886e-11 0.06428782790571179 3.2478301680021854e-08 0.4903495510314233 0.001146714816952061 0.0004777967757842694 1.0882011018684852e-06 0.05708498338352203 0.4981497862127628 -1.0 3.2790914744011534e-06 0.00010077009726691265 -1.0 2.210707325798542e-07 4.3166052799897375e-05 -1.0 0.01825795827020865 0.0003182108781955478 3.8561696337086434e-05 1.0995322456277382e-06 9.53380658669839e-06 0.001550036616828061 0.0012648333883989995 5.272021975060514e-06 1.9257248009114363e-05 0.00016757997590048827 0.11891251244906934 5.515522196186723e-06 0.01102706140784316 9.904481358675478e-13 3.520674728719278e-05 0.011294708566804167 7.239087311622819e-08 -1.0 3.5740607788414942e-06 0.00035983547999740665 1.0588257623722672e-07 0.42372713683725016 0.0011273340972061078 8.582011716859219e-15 1.1514579117272292e-10 0.00043130977711323417 0.0027847329307350423 0.00017287873387910357 6.401055165502384e-06 1.722191123879782e-08 0.00020848309220162036 0.05639071613735579 1.8064550990294753e-05 1.289814511028015e-06 1.078687446476881e-14 0.4897735047310072 0.0002981891705231209 0.00016079768514218546 9.332371598523186e-05 0.011724714376848187 0.019040707071165303 0.00014242053195529864 0.06684484191345574 -1.0 + -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 0.6827568359008944 0.0017329528628152924 0.18541112907970003 0.11113024641218336 0.0008760419353035269 0.0008168081568291806 0.004669378458601891 4.952432605379829 2.2512327083641864e-09 4.625859206051786e-06 0.00027044817176109554 0.5490281661912204 0.0014126153603265096 8.304845400451923e-07 0.00022950716170641464 0.001335621430311088 0.03432919201293737 0.0051970818427099184 5.726152701849347e-15 -10.0 0.013332554437480326 4.346984808472855 7.6915277818290365e-16 0.0011042047857307254 3.0571050855707086e-05 -10.0 4.986698316296507e-05 0.11128424196387618 0.000131063355181338 5.447493368067179e-09 0.11440381012864086 4.670673837764874e-07 1.2364069326350118 0.0012558879474108074 0.0003136829920007009 0.000234750482787598 0.01537590300149361 0.01769327994909422 0.0006717625881826168 4.587143797469485e-07 0.000262112392467961 0.0030002326388383245 0.1729816946709781 4.5757238372058235e-10 0.0006922962992428139 3.792209399652396e-05 -10.0 0.0009256616392487858 8.541606727879512e-06 -10.0 4.931708164307665 0.5500108683629957 0.00012980629616179268 0.006870228272606287 0.008231482263927564 5.0 3.419181071650816e-05 0.6433819434431045 6.574706543646946e-15 4.0404626147344005e-12 0.003782322077390033 0.0012637534695610975 0.17602971074583987 0.00010044390728858278 -10.0 0.008787411098754914 0.002368681880710174 0.00930449789620512 0.0006949587369646498 0.0012918433677593976 2.0707648529746893e-05 0.023295401596005315 1.1819165666519222 -10.0 0.00021606550732170693 0.0022057970761624767 -10.0 1.0325207105027347e-07 0.0020293965453828133 2.123498061876322e-12 -10.0 0.0024175998138228046 0.01178616843705956 0.0013998074566164962 0.03881102561422506 0.011076796092102187 0.0010814452764860557 0.10955637485319249 -10.0 9.382800796426367e-16 0.0005098747893974248 0.0027052054298385255 0.0021305826462238594 0.00808100901275472 4.233410073487772e-05 0.0515132921322595 8.61602729455546e-06 4.873897581604287 0.0002909334597507523 0.0046958956846326495 -10.0 -10.0 0.1780262484403569 1.3116807133030034e-14 2.6178780551069492e-15 0.1884234453311008 -10.0 2.027381220364608e-15 0.004299195570308035 0.00014628847959717226 4.899952354672477 2.774067049392004e-06 0.04441328419270369 4.279460329782799e-08 0.012297303081805393 0.002792896409558745 0.006934466049804711 0.0008370896020975689 3.8270536025799805e-14 -10.0 0.1208261392046878 0.001497958445994315 0.015016500045374082 0.05384625561469684 0.0025519632243117644 0.011028020390507681 0.002362355168421952 -10.0 -10.0 0.0008862760180332873 1.3806577785135176e-05 -10.0 0.001319677450153934 0.00026866894852481903 -10.0 1.1510120013926417 0.026729237733633893 0.00012257360246712473 0.0008544159282151438 0.0002777791741571174 0.014957033281168012 0.0032576461348374514 0.008919466185572301 1.2907171695294846e-12 0.00046842350882367664 0.17218062957363772 0.0025106741008066318 0.0022234471595443312 2.101790478097517e-08 5.752120832330886e-10 0.6428782790571179 3.2478301680021856e-07 4.903495510314233 0.01146714816952061 0.004777967757842694 1.0882011018684853e-05 0.5708498338352204 4.981497862127628 -10.0 3.279091474401153e-05 0.0010077009726691265 -10.0 2.210707325798542e-06 0.00043166052799897375 -10.0 0.1825795827020865 0.0031821087819554777 0.00038561696337086434 1.0995322456277382e-05 9.53380658669839e-05 0.01550036616828061 0.012648333883989995 5.272021975060514e-05 0.00019257248009114364 0.0016757997590048828 1.1891251244906933 5.515522196186723e-05 0.1102706140784316 9.904481358675478e-12 0.0003520674728719278 0.11294708566804167 7.239087311622819e-07 -10.0 3.574060778841494e-05 0.0035983547999740664 1.0588257623722672e-06 4.237271368372502 0.011273340972061077 8.582011716859219e-14 1.151457911727229e-09 0.004313097771132342 0.027847329307350423 0.0017287873387910357 6.401055165502385e-05 1.722191123879782e-07 0.0020848309220162036 0.5639071613735579 0.00018064550990294753 1.289814511028015e-05 1.078687446476881e-13 4.897735047310072 0.002981891705231209 0.0016079768514218546 0.0009332371598523186 0.11724714376848187 0.19040707071165303 0.0014242053195529865 0.6684484191345574 -10.0 3 1.5 10 diff --git a/tests/regression_tests/weightwindows/results_true.dat b/tests/regression_tests/weightwindows/results_true.dat index 971401995..6c05af31a 100644 --- a/tests/regression_tests/weightwindows/results_true.dat +++ b/tests/regression_tests/weightwindows/results_true.dat @@ -1 +1 @@ -f10c722e27d1f0a69f700bc72c4b7751f375dc0a74e049c9abb4b261d2265155c0e516e7e38f9751b83a24eac07e944e51740d398b720524cf8cd6bf0b8c51fc \ No newline at end of file +ebc761815175b25fc95a226174928c226a3ab5dbf3b2a2abf09e079a0b87dee1dee74aa9b9eaec35acd58b8c481d264be7e9b3f052905bcc14ccd76f36b01549 \ No newline at end of file From 7c9a18ddd0b969eafd4fd7a000403c43a522e206 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 24 Oct 2022 16:49:09 -0400 Subject: [PATCH 1203/2654] Update openmc/weight_windows.py --- openmc/weight_windows.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 4088cb2d4..3a9bfff6d 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -342,7 +342,6 @@ class WeightWindows(IDManagerMixin): survival_ratio = float(get_text(elem, 'survival_ratio')) ww_shape = (len(e_bounds) - 1,) + mesh.dimension[::-1] - print(ww_shape) lower_ww_bounds = np.array(lower_ww_bounds).reshape(ww_shape).T upper_ww_bounds = np.array(upper_ww_bounds).reshape(ww_shape).T From a67b330d8f1ae8bcef1e5534459dc116f2bda21d Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 13 Oct 2022 11:57:39 -0400 Subject: [PATCH 1204/2654] round and change default to True --- openmc/geometry.py | 5 +++-- openmc/model/model.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 58a33c1b1..edf4c4782 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -75,7 +75,7 @@ class Geometry: if universe.id in volume_calc.volumes: universe.add_volume_information(volume_calc) - def export_to_xml(self, path='geometry.xml', remove_surfs=False): + def export_to_xml(self, path='geometry.xml', remove_surfs=True): """Export geometry to an XML file. Parameters @@ -411,7 +411,8 @@ class Geometry: """ tally = defaultdict(list) for surf in self.get_all_surfaces().values(): - coeffs = tuple(surf._coefficients[k] for k in surf._coeff_keys) + coeffs = tuple(round(surf._coefficients[k], 10) + for k in surf._coeff_keys) key = (surf._type,) + coeffs tally[key].append(surf) return {replace.id: keep diff --git a/openmc/model/model.py b/openmc/model/model.py index 625094cce..a48730091 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -397,7 +397,7 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.', remove_surfs=False): + def export_to_xml(self, directory='.', remove_surfs=True): """Export model to XML files. Parameters From 1ab2cbec40ab75452b710b4a3d200ec3f2b5011f Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 13 Oct 2022 13:24:03 -0400 Subject: [PATCH 1205/2654] revert to False because of failing tests --- openmc/geometry.py | 2 +- openmc/model/model.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index edf4c4782..0fd8e02fe 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -75,7 +75,7 @@ class Geometry: if universe.id in volume_calc.volumes: universe.add_volume_information(volume_calc) - def export_to_xml(self, path='geometry.xml', remove_surfs=True): + def export_to_xml(self, path='geometry.xml', remove_surfs=False): """Export geometry to an XML file. Parameters diff --git a/openmc/model/model.py b/openmc/model/model.py index a48730091..625094cce 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -397,7 +397,7 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.', remove_surfs=True): + def export_to_xml(self, directory='.', remove_surfs=False): """Export model to XML files. Parameters From 4604c10da11f2ef3c66c44ae80d6a7f8f452b2d3 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sun, 16 Oct 2022 13:06:37 -0400 Subject: [PATCH 1206/2654] added attributes and warnings --- openmc/geometry.py | 76 +++++++++++++++++++++++++++++++++++++++---- openmc/model/model.py | 7 +++- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 0fd8e02fe..e3bb4a1cd 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -3,10 +3,11 @@ from collections.abc import Iterable from copy import deepcopy from pathlib import Path from xml.etree import ElementTree as ET +import warnings import openmc import openmc._xml as xml -from .checkvalue import check_type +from .checkvalue import check_type, check_less_than, check_greater_than class Geometry: @@ -17,6 +18,13 @@ class Geometry: root : openmc.UniverseBase or Iterable of openmc.Cell, optional Root universe which contains all others, or an iterable of cells that should be used to create a root universe. + cull_surfaces : bool, optional + Whether to remove redundant surfaces when the geometry is exported. + Defaults to False. + surface_precision : int, optional + Number of decimal places to round to for comparing the coefficients of + surfaces for considering them topologically equivalent. Defaults to 10 + decimal places. Attributes ---------- @@ -25,12 +33,19 @@ class Geometry: bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box of the universe. + cull_surfaces : bool + Whether to remove redundant surfaces when the geometry is exported. + surface_precision : int + Number of decimal places to round to for comparing the coefficients of + surfaces for considering them topologically equivalent. """ - def __init__(self, root=None): + def __init__(self, root=None, cull_surfaces=False, surface_precision=10): self._root_universe = None self._offsets = {} + self.cull_surfaces = cull_surfaces + self.surface_precision = surface_precision if root is not None: if isinstance(root, openmc.UniverseBase): self.root_universe = root @@ -48,11 +63,31 @@ class Geometry: def bounding_box(self): return self.root_universe.bounding_box + @property + def cull_surfaces(self): + return self._cull_surfaces + + @property + def surface_precision(self): + return self._surface_precision + @root_universe.setter def root_universe(self, root_universe): check_type('root universe', root_universe, openmc.UniverseBase) self._root_universe = root_universe + @cull_surfaces.setter + def cull_surfaces(self, cull_surfaces): + check_type('cull surfaces', cull_surfaces, bool) + self._cull_surfaces = cull_surfaces + + @surface_precision.setter + def surface_precision(self, surface_precision): + check_type('surface precision', surface_precision, int) + check_less_than('surface_precision', surface_precision, 16) + check_greater_than('surface_precision', surface_precision, 0) + self._surface_precision = surface_precision + def add_volume_information(self, volume_calc): """Add volume information from a stochastic volume calculation. @@ -91,6 +126,11 @@ class Geometry: """ # Find and remove redundant surfaces from the geometry if remove_surfs: + warnings.warn("remove_surfs kwarg will be deprecated soon, please " + "set the Geometry.cull_surfaces attribute instead.") + self.cull_surfaces = True + + if self.cull_surfaces: self.remove_redundant_surfaces() # Create XML representation @@ -396,11 +436,18 @@ class Geometry: surfaces = cell.region.get_surfaces(surfaces) return surfaces - def get_redundant_surfaces(self): + def get_redundant_surfaces(self, precision=None): """Return all of the topologically redundant surface IDs .. versionadded:: 0.12 + Parameters + ---------- + precision : int, optional + The number of decimal places to round to for considering surface + coefficients to be equal. Defaults to the value specified by + Geometry.surface_precision. + Returns ------- dict @@ -409,9 +456,12 @@ class Geometry: that should replace it. """ + precision = self.surface_precision if precision is None else precision + check_less_than('precision', precision, 16) + check_greater_than('precision', precision, 0) tally = defaultdict(list) for surf in self.get_all_surfaces().values(): - coeffs = tuple(round(surf._coefficients[k], 10) + coeffs = tuple(round(surf._coefficients[k], precision) for k in surf._coeff_keys) key = (surf._type,) + coeffs tally[key].append(surf) @@ -565,11 +615,23 @@ class Geometry: """ return self._get_domains_by_name(name, case_sensitive, matching, 'lattice') - def remove_redundant_surfaces(self): - """Remove redundant surfaces from the geometry""" + def remove_redundant_surfaces(self, precision=None): + """Remove redundant surfaces from the geometry. + + Parameters + ---------- + precision : int, optional + The number of decimal places to round to for considering surface + coefficients to be equal. Defaults to the value specified by + Geometry.surface_precision. + + """ + precision = self.surface_precision if precision is None else precision + check_less_than('precision', precision, 16) + check_greater_than('precision', precision, 0) # Get redundant surfaces - redundant_surfaces = self.get_redundant_surfaces() + redundant_surfaces = self.get_redundant_surfaces(precision=precision) # Iterate through all cells contained in the geometry for cell in self.get_all_cells().values(): diff --git a/openmc/model/model.py b/openmc/model/model.py index 625094cce..8a57c88e4 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -5,6 +5,7 @@ import os from pathlib import Path from numbers import Integral from tempfile import NamedTemporaryFile +import warnings import h5py @@ -417,7 +418,11 @@ class Model: d.mkdir(parents=True) self.settings.export_to_xml(d) - self.geometry.export_to_xml(d, remove_surfs=remove_surfs) + if remove_surfs: + warnings.warn("remove_surfs kwarg will be deprecated soon, please " + "set the Geometry.cull_surfaces attribute instead.") + self.geometry.cull_surfaces = True + self.geometry.export_to_xml(d) # If a materials collection was specified, export it. Otherwise, look # for all materials in the geometry and use that to automatically build From fec53aa1fa8690757141a196f71abe20e0694b78 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 18 Oct 2022 09:16:09 -0400 Subject: [PATCH 1207/2654] updated tests --- tests/unit_tests/test_geometry.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py index 64a97e0a1..2034a5764 100644 --- a/tests/unit_tests/test_geometry.py +++ b/tests/unit_tests/test_geometry.py @@ -302,7 +302,7 @@ def test_rotation_matrix(): assert geom.find((0.0, -0.5, 0.0))[-1] == c1 assert geom.find((0.0, -1.5, 0.0))[-1] == c2 -def test_remove_redundant_surfaces(): +def test_remove_redundant_surfaces(run_in_tmpdir): """Test ability to remove redundant surfaces""" m1 = openmc.Material() @@ -338,13 +338,16 @@ def test_remove_redundant_surfaces(): clad = get_cyl_cell(r1, r2, z1, z2, m2) water = get_cyl_cell(r2, r3, z1, z2, m3) root = openmc.Universe(cells=[fuel, clad, water]) - geom = openmc.Geometry(root) - + geom = openmc.Geometry(root, cull_surfaces=True) + model = openmc.model.Model(geometry=geom, + materials=openmc.Materials([m1, m2, m3])) + # There should be 6 redundant surfaces in this geometry n_redundant_surfs = len(geom.get_redundant_surfaces().keys()) assert n_redundant_surfs == 6 - # Remove redundant surfaces - geom.remove_redundant_surfaces() + # Remove redundant surfaces on export + model.export_to_xml() + geom = openmc.Geometry.from_xml() # There should be 0 remaining redundant surfaces n_redundant_surfs = len(geom.get_redundant_surfaces().keys()) assert n_redundant_surfs == 0 From 33021f7af18c095fa8b0a18cb51c5aac852eeb28 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 24 Oct 2022 16:55:48 -0400 Subject: [PATCH 1208/2654] removed precision parameter --- openmc/geometry.py | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index e3bb4a1cd..5efd5381e 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -436,18 +436,14 @@ class Geometry: surfaces = cell.region.get_surfaces(surfaces) return surfaces - def get_redundant_surfaces(self, precision=None): - """Return all of the topologically redundant surface IDs + def get_redundant_surfaces(self): + """Return all of the topologically redundant surface IDs. + + Uses surface_precision attribute of Geometry instance for rounding and + comparing surface coefficients. .. versionadded:: 0.12 - Parameters - ---------- - precision : int, optional - The number of decimal places to round to for considering surface - coefficients to be equal. Defaults to the value specified by - Geometry.surface_precision. - Returns ------- dict @@ -456,12 +452,9 @@ class Geometry: that should replace it. """ - precision = self.surface_precision if precision is None else precision - check_less_than('precision', precision, 16) - check_greater_than('precision', precision, 0) tally = defaultdict(list) for surf in self.get_all_surfaces().values(): - coeffs = tuple(round(surf._coefficients[k], precision) + coeffs = tuple(round(surf._coefficients[k], self.surface_precision) for k in surf._coeff_keys) key = (surf._type,) + coeffs tally[key].append(surf) @@ -615,23 +608,11 @@ class Geometry: """ return self._get_domains_by_name(name, case_sensitive, matching, 'lattice') - def remove_redundant_surfaces(self, precision=None): - """Remove redundant surfaces from the geometry. - - Parameters - ---------- - precision : int, optional - The number of decimal places to round to for considering surface - coefficients to be equal. Defaults to the value specified by - Geometry.surface_precision. - - """ - precision = self.surface_precision if precision is None else precision - check_less_than('precision', precision, 16) - check_greater_than('precision', precision, 0) + def remove_redundant_surfaces(self): + """Remove redundant surfaces from the geometry.""" # Get redundant surfaces - redundant_surfaces = self.get_redundant_surfaces(precision=precision) + redundant_surfaces = self.get_redundant_surfaces() # Iterate through all cells contained in the geometry for cell in self.get_all_cells().values(): From a46cafa7fe05a391f9c3e85a5f89c53233af29c1 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 26 Oct 2022 08:20:25 -0400 Subject: [PATCH 1209/2654] addressed @pshriwise comments --- openmc/geometry.py | 33 ++++++++++++------------------- openmc/model/model.py | 4 ++-- tests/unit_tests/test_geometry.py | 3 ++- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 5efd5381e..2cdc356e8 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -18,13 +18,6 @@ class Geometry: root : openmc.UniverseBase or Iterable of openmc.Cell, optional Root universe which contains all others, or an iterable of cells that should be used to create a root universe. - cull_surfaces : bool, optional - Whether to remove redundant surfaces when the geometry is exported. - Defaults to False. - surface_precision : int, optional - Number of decimal places to round to for comparing the coefficients of - surfaces for considering them topologically equivalent. Defaults to 10 - decimal places. Attributes ---------- @@ -33,7 +26,7 @@ class Geometry: bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box of the universe. - cull_surfaces : bool + merge_surfaces : bool Whether to remove redundant surfaces when the geometry is exported. surface_precision : int Number of decimal places to round to for comparing the coefficients of @@ -41,11 +34,11 @@ class Geometry: """ - def __init__(self, root=None, cull_surfaces=False, surface_precision=10): + def __init__(self, root=None): self._root_universe = None self._offsets = {} - self.cull_surfaces = cull_surfaces - self.surface_precision = surface_precision + self.merge_surfaces = False + self.surface_precision = 10 if root is not None: if isinstance(root, openmc.UniverseBase): self.root_universe = root @@ -64,8 +57,8 @@ class Geometry: return self.root_universe.bounding_box @property - def cull_surfaces(self): - return self._cull_surfaces + def merge_surfaces(self): + return self._merge_surfaces @property def surface_precision(self): @@ -76,10 +69,10 @@ class Geometry: check_type('root universe', root_universe, openmc.UniverseBase) self._root_universe = root_universe - @cull_surfaces.setter - def cull_surfaces(self, cull_surfaces): - check_type('cull surfaces', cull_surfaces, bool) - self._cull_surfaces = cull_surfaces + @merge_surfaces.setter + def merge_surfaces(self, merge_surfaces): + check_type('merge surfaces', merge_surfaces, bool) + self._merge_surfaces = merge_surfaces @surface_precision.setter def surface_precision(self, surface_precision): @@ -127,10 +120,10 @@ class Geometry: # Find and remove redundant surfaces from the geometry if remove_surfs: warnings.warn("remove_surfs kwarg will be deprecated soon, please " - "set the Geometry.cull_surfaces attribute instead.") - self.cull_surfaces = True + "set the Geometry.merge_surfaces attribute instead.") + self.merge_surfaces = True - if self.cull_surfaces: + if self.merge_surfaces: self.remove_redundant_surfaces() # Create XML representation diff --git a/openmc/model/model.py b/openmc/model/model.py index 8a57c88e4..7126987cb 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -420,8 +420,8 @@ class Model: self.settings.export_to_xml(d) if remove_surfs: warnings.warn("remove_surfs kwarg will be deprecated soon, please " - "set the Geometry.cull_surfaces attribute instead.") - self.geometry.cull_surfaces = True + "set the Geometry.merge_surfaces attribute instead.") + self.geometry.merge_surfaces = True self.geometry.export_to_xml(d) # If a materials collection was specified, export it. Otherwise, look diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py index 2034a5764..6a092126e 100644 --- a/tests/unit_tests/test_geometry.py +++ b/tests/unit_tests/test_geometry.py @@ -338,7 +338,8 @@ def test_remove_redundant_surfaces(run_in_tmpdir): clad = get_cyl_cell(r1, r2, z1, z2, m2) water = get_cyl_cell(r2, r3, z1, z2, m3) root = openmc.Universe(cells=[fuel, clad, water]) - geom = openmc.Geometry(root, cull_surfaces=True) + geom = openmc.Geometry(root) + geom.merge_surfaces=True model = openmc.model.Model(geometry=geom, materials=openmc.Materials([m1, m2, m3])) From e8d3e14adf16ad0ebe6413e0d7e81a22bab0cee2 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 26 Oct 2022 12:13:43 -0400 Subject: [PATCH 1210/2654] cache redundant_surfaces --- openmc/geometry.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 2cdc356e8..08608a5cd 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -37,6 +37,7 @@ class Geometry: def __init__(self, root=None): self._root_universe = None self._offsets = {} + self._redundant_surface_map = None self.merge_surfaces = False self.surface_precision = 10 if root is not None: @@ -445,15 +446,21 @@ class Geometry: that should replace it. """ - tally = defaultdict(list) - for surf in self.get_all_surfaces().values(): - coeffs = tuple(round(surf._coefficients[k], self.surface_precision) - for k in surf._coeff_keys) - key = (surf._type,) + coeffs - tally[key].append(surf) - return {replace.id: keep - for keep, *redundant in tally.values() - for replace in redundant} + # check if redundant surfaces have not been calculated yet + if self._redundant_surface_map is None: + tally = defaultdict(list) + for surf in self.get_all_surfaces().values(): + coeffs = tuple(round(surf._coefficients[k], + self.surface_precision) + for k in surf._coeff_keys) + key = (surf._type,) + coeffs + tally[key].append(surf) + + self._redundant_surface_map = {replace.id: keep + for keep, *redundant in tally.values() + for replace in redundant} + + return self._redundant_surface_map def _get_domains_by_name(self, name, case_sensitive, matching, domain_type): if not case_sensitive: @@ -607,11 +614,14 @@ class Geometry: # Get redundant surfaces redundant_surfaces = self.get_redundant_surfaces() - # Iterate through all cells contained in the geometry - for cell in self.get_all_cells().values(): - # Recursively remove redundant surfaces from regions - if cell.region: - cell.region.remove_redundant_surfaces(redundant_surfaces) + if redundant_surfaces: + # Iterate through all cells contained in the geometry + for cell in self.get_all_cells().values(): + # Recursively remove redundant surfaces from regions + if cell.region: + cell.region.remove_redundant_surfaces(redundant_surfaces) + + self._redundant_surface_map = None def determine_paths(self, instances_only=False): """Determine paths through CSG tree for cells and materials. From 6131136bd1a1433af676841c3493b0c79991b88b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 26 Oct 2022 18:33:26 +0100 Subject: [PATCH 1211/2654] swapped from 2016 to 2020 amdc data --- openmc/data/data.py | 2 +- openmc/data/mass16.txt | 3475 -------------------------------- openmc/data/mass_1.mas20.txt | 3594 ++++++++++++++++++++++++++++++++++ setup.py | 2 +- 4 files changed, 3596 insertions(+), 3477 deletions(-) delete mode 100644 openmc/data/mass16.txt create mode 100644 openmc/data/mass_1.mas20.txt diff --git a/openmc/data/data.py b/openmc/data/data.py index 0c4495ede..361aa6457 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -224,7 +224,7 @@ def atomic_mass(isotope): if not _ATOMIC_MASS: # Load data from AME2016 file - mass_file = os.path.join(os.path.dirname(__file__), 'mass16.txt') + mass_file = os.path.join(os.path.dirname(__file__), 'mass_1.mas20.txt') with open(mass_file, 'r') as ame: # Read lines in file starting at line 40 for line in itertools.islice(ame, 39, None): diff --git a/openmc/data/mass16.txt b/openmc/data/mass16.txt deleted file mode 100644 index 4b479be45..000000000 --- a/openmc/data/mass16.txt +++ /dev/null @@ -1,3475 +0,0 @@ -1 a0boogfu A T O M I C M A S S A D J U S T M E N T -0 DATE 1 Mar 2017 TIME 17:26 -0 ********************* A= 0 TO 295 - * file : mass16.txt * - ********************* - - This is one file out of a series of 3 files published in: - "The Ame2016 atomic mass evaluation (I)" by W.J.Huang, G.Audi, M.Wang, F.G.Kondev, S.Naimi and X.Xu - Chinese Physics C41 030002, March 2017. - "The Ame2016 atomic mass evaluation (II)" by M.Wang, G.Audi, F.G.Kondev, W.J.Huang, S.Naimi and X.Xu - Chinese Physics C41 030003, March 2017. - for files : mass16.txt : atomic masses - rct1-16.txt : react and sep energies, part 1 - rct2-16.txt : react and sep energies, part 2 - A fourth file is the "Rounded" version of the atomic mass table (the first file) - mass16round.txt : atomic masses "Rounded" version - - All files are 3436 lines long with 124 character per line. - Headers are 39 lines long. - Values in files 1, 2 and 3 are unrounded copy of the published ones - Values in file 4 are exact copy of the published ones - - col 1 : Fortran character control: 1 = page feed 0 = line feed - format : a1,i3,i5,i5,i5,1x,a3,a4,1x,f13.5,f11.5,f11.3,f9.3,1x,a2,f11.3,f9.3,1x,i3,1x,f12.5,f11.5 - cc NZ N Z A el o mass unc binding unc B beta unc atomic_mass unc - Warnings : this format is identical to the ones used in Ame2003 and Ame2012 - in particular "Mass Excess" and "Atomic Mass" values are given now, when necessary, - with 5 digits after decimal point. - decimal point is replaced by # for (non-experimental) estimated values. - * in place of value : not calculable - -....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+...10....+...11....+...12.... - - - MASS LIST - for analysis - -1N-Z N Z A EL O MASS EXCESS BINDING ENERGY/A BETA-DECAY ENERGY ATOMIC MASS - (keV) (keV) (keV) (micro-u) -0 1 1 0 1 n 8071.31713 0.00046 0.0 0.0 B- 782.347 0.000 1 008664.91582 0.00049 - -1 0 1 1 H 7288.97061 0.00009 0.0 0.0 B- * 1 007825.03224 0.00009 -0 0 1 1 2 H 13135.72176 0.00011 1112.283 0.000 B- * 2 014101.77811 0.00012 -0 1 2 1 3 H 14949.80993 0.00022 2827.265 0.000 B- 18.592 0.000 3 016049.28199 0.00023 - -1 1 2 3 He 14931.21793 0.00021 2572.680 0.000 B- -13736# 2000# 3 016029.32265 0.00022 - -3 0 3 3 Li -pp 28667# 2000# -2267# 667# B- * 3 030775# 2147# -0 2 3 1 4 H -n 24621.127 100.000 1720.449 25.000 B- 22196.211 100.000 4 026431.868 107.354 - 0 2 2 4 He 2424.91561 0.00006 7073.915 0.000 B- -22898.273 212.132 4 002603.25413 0.00006 - -2 1 3 4 Li -p 25323.189 212.132 1153.760 53.033 B- * 4 027185.562 227.733 -0 3 4 1 5 H -nn 32892.444 89.443 1336.359 17.889 B- 21661.211 91.652 5 035311.493 96.020 - 1 3 2 5 He -n 11231.233 20.000 5512.132 4.000 B- -447.654 53.852 5 012057.224 21.470 - -1 2 3 5 Li -p 11678.886 50.000 5266.132 10.000 B- -25460# 2003# 5 012537.800 53.677 - -3 1 4 5 Be x 37139# 2003# 18# 401# B- * 5 039870# 2150# -0 4 5 1 6 H -3n 41875.721 254.127 961.639 42.354 B- 24283.626 254.127 6 044955.437 272.816 - 2 4 2 6 He 17592.095 0.053 4878.519 0.009 B- 3505.216 0.053 6 018885.891 0.057 - 0 3 3 6 Li 14086.87895 0.00144 5332.331 0.000 B- -4288.154 5.448 6 015122.88742 0.00155 - -2 2 4 6 Be - 18375.033 5.448 4487.247 0.908 B- -28945# 2003# 6 019726.409 5.848 - -4 1 5 6 B x 47320# 2003# -467# 334# B- * 6 050800# 2150# -0 5 6 1 7 H -nn 49135# 1004# 940# 143# B- 23062# 1004# 7 052749# 1078# - 3 5 2 7 He -n 26073.126 7.559 4123.057 1.080 B- 11166.021 7.559 7 027990.654 8.115 - 1 4 3 7 Li 14907.10529 0.00423 5606.439 0.001 B- -861.893 0.071 7 016003.43666 0.00454 - -1 3 4 7 Be 15768.999 0.071 5371.548 0.010 B- -11907.551 25.150 7 016928.717 0.076 - -3 2 5 7 B p4n 27676.550 25.150 3558.705 3.593 B- * 7 029712.000 27.000 -0 4 6 2 8 He 31609.681 0.089 3924.520 0.011 B- 10663.878 0.100 8 033934.390 0.095 - 2 5 3 8 Li 20945.804 0.047 5159.712 0.006 B- 16004.133 0.059 8 022486.246 0.050 - 0 4 4 8 Be -a 4941.671 0.035 7062.435 0.004 B- -17979.896 1.000 8 005305.102 0.037 - -2 3 5 8 B 22921.567 1.000 4717.155 0.125 B- -12142.701 18.270 8 024607.316 1.073 - -4 2 6 8 C 35064.268 18.243 3101.524 2.280 B- * 8 037643.042 19.584 -0 5 7 2 9 He 40935.826 46.816 3349.037 5.202 B- 15980.924 46.817 9 043946.419 50.259 - 3 6 3 9 Li -3n 24954.902 0.186 5037.768 0.021 B- 13606.449 0.201 9 026790.191 0.200 - 1 5 4 9 Be 11348.453 0.077 6462.668 0.009 B- -1068.035 0.899 9 012183.066 0.082 - -1 4 5 9 B - 12416.488 0.903 6257.070 0.100 B- -16494.484 2.319 9 013329.649 0.969 - -3 3 6 9 C -pp 28910.972 2.137 4337.423 0.237 B- * 9 031037.207 2.293 -0 6 8 2 10 He -nn 49197.143 92.848 2995.134 9.285 B- 16144.519 93.715 10 052815.308 99.676 - 4 7 3 10 Li -n 33052.624 12.721 4531.351 1.272 B- 20445.136 12.722 10 035483.453 13.656 - 2 6 4 10 Be 12607.488 0.081 6497.630 0.008 B- 556.878 0.082 10 013534.695 0.086 - 0 5 5 10 B 12050.609 0.015 6475.083 0.002 B- -3648.062 0.069 10 012936.862 0.016 - -2 4 6 10 C 15698.672 0.070 6032.042 0.007 B- -23101.355 400.000 10 016853.218 0.075 - -4 3 7 10 N -- 38800.026 400.000 3643.672 40.000 B- * 10 041653.543 429.417 -0 5 8 3 11 Li x 40728.254 0.615 4155.381 0.056 B- 20551.087 0.659 11 043723.581 0.660 - 3 7 4 11 Be 20177.167 0.238 5952.540 0.022 B- 11509.460 0.238 11 021661.081 0.255 - 1 6 5 11 B 8667.707 0.012 6927.732 0.001 B- -1981.689 0.061 11 009305.166 0.013 - -1 5 6 11 C 10649.396 0.060 6676.456 0.005 B- -13654.163 46.154 11 011432.597 0.064 - -3 4 7 11 N -p 24303.559 46.154 5364.046 4.196 B- * 11 026090.945 49.548 -0 6 9 3 12 Li -n 49009.571 30.006 3791.600 2.501 B- 23931.812 30.067 12 052613.941 32.213 - 4 8 4 12 Be 25077.760 1.909 5720.722 0.159 B- 11708.363 2.321 12 026922.083 2.048 - 2 7 5 12 B 13369.397 1.321 6631.223 0.110 B- 13369.397 1.321 12 014352.638 1.418 - 0 6 6 12 C 0.0 0.0 7680.144 0.000 B- -17338.068 1.000 12 000000.0 0.0 - -2 5 7 12 N 17338.068 1.000 6170.109 0.083 B- -14576.544 24.021 12 018613.182 1.073 - -4 4 8 12 O -pp 31914.613 24.000 4890.202 2.000 B- * 12 034261.747 25.765 -0 7 10 3 13 Li -nn 56980.888 70.003 3507.630 5.385 B- 23321.812 70.739 13 061171.503 75.150 - 5 9 4 13 Be -n 33659.077 10.180 5241.435 0.783 B- 17097.130 10.230 13 036134.507 10.929 - 3 8 5 13 B -nn 16561.947 1.000 6496.419 0.077 B- 13436.938 1.000 13 017779.981 1.073 - 1 7 6 13 C 3125.00888 0.00021 7469.849 0.000 B- -2220.472 0.270 13 003354.83521 0.00023 - -1 6 7 13 N 5345.481 0.270 7238.863 0.021 B- -17769.951 9.530 13 005738.609 0.289 - -3 5 8 13 O +3n 23115.432 9.526 5811.763 0.733 B- * 13 024815.437 10.226 -0 6 10 4 14 Be x 39954.498 132.245 4993.897 9.446 B- 16290.813 133.936 14 042892.920 141.970 - 4 9 5 14 B 23663.685 21.213 6101.644 1.515 B- 20643.792 21.213 14 025404.012 22.773 - 2 8 6 14 C 3019.89278 0.00376 7520.319 0.000 B- 156.476 0.004 14 003241.98843 0.00403 - 0 7 7 14 N 2863.41672 0.00019 7475.614 0.000 B- -5144.364 0.025 14 003074.00446 0.00021 - -2 6 8 14 O 8007.781 0.025 7052.278 0.002 B- -23956.622 41.119 14 008596.706 0.027 - -4 5 9 14 F -p 31964.402 41.119 5285.208 2.937 B- * 14 034315.199 44.142 -0 7 11 4 15 Be -n 49825.815 165.797 4540.970 11.053 B- 20867.573 167.126 15 053490.215 177.990 - 5 10 5 15 B 28958.242 21.032 5879.985 1.402 B- 19085.098 21.047 15 031087.953 22.578 - 3 9 6 15 C -n 9873.144 0.800 7100.169 0.053 B- 9771.705 0.800 15 010599.256 0.858 - 1 8 7 15 N 101.43871 0.00060 7699.460 0.000 B- -2754.166 0.491 15 000108.89894 0.00065 - -1 7 8 15 O 2855.605 0.491 7463.692 0.033 B- -13711.146 14.009 15 003065.618 0.526 - -3 6 9 15 F -p 16566.751 14.000 6497.459 0.933 B- -23648.622 68.138 15 017785.139 15.029 - -5 5 10 15 Ne -pp 40215.373 66.684 4868.728 4.446 B- * 15 043172.980 71.588 -0 8 12 4 16 Be -nn 57447.132 165.797 4285.285 10.362 B- 20334.623 167.608 16 061672.036 177.990 - 6 11 5 16 B 37112.510 24.569 5507.302 1.536 B- 23418.378 24.828 16 039841.920 26.375 - 4 10 6 16 C -nn 13694.132 3.578 6922.054 0.224 B- 8010.225 4.254 16 014701.256 3.840 - 2 9 7 16 N -n 5683.907 2.301 7373.796 0.144 B- 10420.908 2.301 16 006101.925 2.470 - 0 8 8 16 O -4737.00135 0.00016 7976.206 0.000 B- -15417.254 8.321 15 994914.61960 0.00017 - -2 7 9 16 F - 10680.253 8.321 6963.731 0.520 B- -13306.523 22.106 16 011465.723 8.932 - -4 6 10 16 Ne -- 23986.776 20.480 6083.177 1.280 B- * 16 025750.864 21.986 -0 7 12 5 17 B x 43716.317 204.104 5269.667 12.006 B- 22684.419 204.841 17 046931.399 219.114 - 5 11 6 17 C 2p-n 21031.898 17.365 6558.024 1.021 B- 13161.820 22.946 17 022578.672 18.641 - 3 10 7 17 N +p 7870.079 15.000 7286.229 0.882 B- 8678.842 15.000 17 008448.877 16.103 - 1 9 8 17 O -808.76348 0.00066 7750.728 0.000 B- -2760.465 0.248 16 999131.75664 0.00070 - -1 8 9 17 F 1951.702 0.248 7542.328 0.015 B- -14548.746 0.432 17 002095.238 0.266 - -3 7 10 17 Ne 16500.447 0.354 6640.499 0.021 B- -18672.766 1001.356 17 017713.959 0.380 - -5 6 11 17 Na x 35173.214 1001.356 5496.080 58.903 B- * 17 037760.000 1075.000 -0 8 13 5 18 B -n 51792.634 204.165 4976.630 11.342 B- 26873.370 206.357 18 055601.682 219.180 - 6 12 6 18 C ++ 24919.264 30.000 6426.131 1.667 B- 11806.096 35.282 18 026751.932 32.206 - 4 11 7 18 N + 13113.168 18.570 7038.562 1.032 B- 13895.984 18.570 18 014077.565 19.935 - 2 10 8 18 O -782.81560 0.00071 7767.097 0.000 B- -1655.929 0.463 17 999159.61284 0.00076 - 0 9 9 18 F 873.113 0.463 7631.638 0.026 B- -4444.501 0.589 18 000937.325 0.497 - -2 8 10 18 Ne 5317.614 0.363 7341.257 0.020 B- -19720.374 93.882 18 005708.693 0.390 - -4 7 11 18 Na 25037.988 93.881 6202.217 5.216 B- * 18 026879.386 100.785 -0 9 14 5 19 B x 59770.244 525.363 4719.634 27.651 B- 27356.492 534.496 19 064166.000 564.000 - 7 13 6 19 C -n 32413.752 98.389 6118.273 5.178 B- 16557.471 99.748 19 034797.596 105.625 - 5 12 7 19 N p-2n 15856.282 16.404 6948.543 0.863 B- 12523.424 16.614 19 017022.419 17.610 - 3 11 8 19 O -n 3332.858 2.637 7566.495 0.139 B- 4820.302 2.637 19 003577.970 2.830 - 1 10 9 19 F -1487.44420 0.00086 7779.018 0.000 B- -3239.494 0.160 18 998403.16288 0.00093 - -1 9 10 19 Ne +3n 1752.050 0.160 7567.343 0.008 B- -11177.340 10.536 19 001880.903 0.171 - -3 8 11 19 Na 12929.390 10.535 6937.885 0.554 B- -18898.998 51.099 19 013880.272 11.309 - -5 7 12 19 Mg -pp 31828.389 50.001 5902.025 2.632 B- * 19 034169.182 53.678 -0 10 15 5 20 B x 68450# 800# 4453# 40# B- 30946# 833# 20 073484# 859# - 8 14 6 20 C x 37503.563 230.625 5961.435 11.531 B- 15737.067 243.746 20 040261.732 247.585 - 6 13 7 20 N x 21766.496 78.894 6709.171 3.945 B- 17970.324 78.899 20 023367.295 84.696 - 4 12 8 20 O -nn 3796.172 0.885 7568.570 0.044 B- 3813.635 0.885 20 004075.358 0.950 - 2 11 9 20 F -n -17.463 0.030 7720.134 0.002 B- 7024.467 0.030 19 999981.252 0.031 - 0 10 10 20 Ne -7041.93055 0.00157 8032.240 0.000 B- -13892.535 1.114 19 992440.17619 0.00168 - -2 9 11 20 Na 6850.604 1.114 7298.496 0.056 B- -10627.088 2.171 20 007354.426 1.195 - -4 8 12 20 Mg +t 17477.692 1.863 6728.025 0.093 B- * 20 018763.075 2.000 -0 11 16 5 21 B x 77330# 900# 4203# 43# B- 31687# 1079# 21 083017# 966# - 9 15 6 21 C x 45643# 596# 5674# 28# B- 20411# 611# 21 049000# 640# - 7 14 7 21 N x 25231.913 134.048 6609.015 6.383 B- 17169.878 134.584 21 027087.573 143.906 - 5 13 8 21 O -3n 8062.035 12.000 7389.374 0.571 B- 8109.640 12.134 21 008654.950 12.882 - 3 12 9 21 F -nn -47.605 1.800 7738.293 0.086 B- 5684.171 1.800 20 999948.894 1.932 - 1 11 10 21 Ne -5731.776 0.038 7971.713 0.002 B- -3547.145 0.090 20 993846.685 0.041 - -1 10 11 21 Na -2184.631 0.098 7765.547 0.005 B- -13088.480 0.761 20 997654.702 0.105 - -3 9 12 21 Mg x 10903.850 0.755 7105.031 0.036 B- -16086# 596# 21 011705.764 0.810 - -5 8 13 21 Al x 26990# 596# 6302# 28# B- * 21 028975# 640# -0 10 16 6 22 C -nn 53611.197 231.490 5421.077 10.522 B- 21846.396 311.063 22 057553.990 248.515 - 8 15 7 22 N x 31764.801 207.779 6378.534 9.445 B- 22481.768 215.435 22 034100.918 223.060 - 6 14 8 22 O -4n 9283.033 56.921 7364.871 2.587 B- 6489.660 58.256 22 009965.746 61.107 - 4 13 9 22 F + 2793.373 12.399 7624.295 0.564 B- 10818.092 12.399 22 002998.809 13.310 - 2 12 10 22 Ne -8024.719 0.018 8080.465 0.001 B- -2843.207 0.171 21 991385.109 0.018 - 0 11 11 22 Na -5181.511 0.171 7915.667 0.008 B- -4781.578 0.321 21 994437.418 0.183 - -2 10 12 22 Mg -399.933 0.313 7662.761 0.014 B- -18601# 401# 21 999570.654 0.335 - -4 9 13 22 Al x 18201# 401# 6782# 18# B- -15137# 643# 22 019540# 430# - -6 8 14 22 Si x 33338# 503# 6058# 23# B- * 22 035790# 540# -0 11 17 6 23 C x 64171# 997# 5077# 43# B- 27450# 1082# 23 068890# 1070# - 9 16 7 23 N x 36720.425 420.570 6236.671 18.286 B- 22099.056 437.827 23 039421.000 451.500 - 7 15 8 23 O x 14621.369 121.712 7163.485 5.292 B- 11336.106 126.190 23 015696.686 130.663 - 5 14 9 23 F 3285.263 33.320 7622.344 1.449 B- 8439.312 33.321 23 003526.874 35.770 - 3 13 10 23 Ne -n -5154.049 0.104 7955.256 0.005 B- 4375.804 0.104 22 994466.900 0.112 - 1 12 11 23 Na -9529.85248 0.00181 8111.493 0.000 B- -4056.340 0.158 22 989769.28199 0.00194 - -1 11 12 23 Mg - -5473.513 0.158 7901.115 0.007 B- -12221.583 0.379 22 994123.941 0.170 - -3 10 13 23 Al -- 6748.070 0.345 7335.727 0.015 B- -16949# 503# 23 007244.351 0.370 - -5 9 14 23 Si x 23697# 503# 6565# 22# B- * 23 025440# 540# -0 10 17 7 24 N x 46938# 401# 5887# 17# B- 28438# 433# 24 050390# 430# - 8 16 8 24 O x 18500.402 164.874 7039.685 6.870 B- 10955.887 191.633 24 019861.000 177.000 - 6 15 9 24 F x 7544.515 97.670 7463.582 4.070 B- 13496.161 97.672 24 008099.370 104.853 - 4 14 10 24 Ne -nn -5951.646 0.513 7993.325 0.021 B- 2466.255 0.513 23 993610.645 0.550 - 2 13 11 24 Na -n -8417.901 0.017 8063.488 0.001 B- 5515.669 0.021 23 990963.011 0.017 - 0 12 12 24 Mg -13933.569 0.013 8260.709 0.001 B- -13884.704 0.233 23 985041.697 0.014 - -2 11 13 24 Al ep -48.865 0.233 7649.582 0.010 B- -10794.060 19.473 23 999947.541 0.250 - -4 10 14 24 Si -- 10745.195 19.472 7167.232 0.811 B- -22574# 503# 24 011535.441 20.904 - -6 9 15 24 P x 33320# 503# 6194# 21# B- * 24 035770# 540# -0 11 18 7 25 N x 55983# 503# 5613# 20# B- 28654# 529# 25 060100# 540# - 9 17 8 25 O -n 27329.027 165.084 6727.805 6.603 B- 15994.862 191.191 25 029338.919 177.225 - 7 16 9 25 F x 11334.166 96.442 7336.306 3.858 B- 13369.667 100.721 25 012167.727 103.535 - 5 15 10 25 Ne -2035.502 29.045 7839.799 1.162 B- 7322.312 29.070 24 997814.799 31.181 - 3 14 11 25 Na -nn -9357.813 1.200 8101.397 0.048 B- 3834.969 1.201 24 989953.973 1.288 - 1 13 12 25 Mg -13192.783 0.047 8223.502 0.002 B- -4276.808 0.045 24 985836.964 0.050 - -1 12 13 25 Al -8915.975 0.065 8021.136 0.003 B- -12743.299 10.000 24 990428.306 0.069 - -3 11 14 25 Si +3n 3827.324 10.000 7480.110 0.400 B- -15911# 401# 25 004108.801 10.735 - -5 10 15 25 P x 19738# 401# 6812# 16# B- * 25 021190# 430# -0 10 18 8 26 O -nn 34661.037 164.950 6497.478 6.344 B- 16012.161 198.932 26 037210.155 177.081 - 8 17 9 26 F x 18648.875 111.199 7083.240 4.277 B- 18167.762 112.716 26 020020.392 119.377 - 6 16 10 26 Ne x 481.114 18.429 7751.910 0.709 B- 7341.893 18.758 26 000516.496 19.784 - 4 15 11 26 Na x -6860.780 3.502 8004.201 0.135 B- 9353.763 3.502 25 992634.649 3.759 - 2 14 12 26 Mg -16214.542 0.030 8333.870 0.001 B- -4004.391 0.063 25 982592.971 0.032 - 0 13 13 26 Al -12210.151 0.067 8149.765 0.003 B- -5069.136 0.085 25 986891.863 0.071 - -2 12 14 26 Si - -7141.015 0.108 7924.708 0.004 B- -18114# 196# 25 992333.804 0.115 - -4 11 15 26 P x 10973# 196# 7198# 8# B- -16106# 627# 26 011780# 210# - -6 10 16 26 S x 27079# 596# 6548# 23# B- * 26 029070# 640# -0 11 19 8 27 O x 44670# 500# 6185# 19# B- 19220# 634# 27 047955# 537# - 9 18 9 27 F x 25450.279 389.830 6867.932 14.438 B- 18399.370 400.258 27 027322.000 418.500 - 7 17 10 27 Ne x 7050.909 90.770 7520.414 3.362 B- 12568.699 90.847 27 007569.462 97.445 - 5 16 11 27 Na ++ -5517.790 3.726 7956.946 0.138 B- 9068.821 3.727 26 994076.408 4.000 - 3 15 12 27 Mg -n -14586.611 0.050 8263.852 0.002 B- 2610.251 0.069 26 984340.628 0.053 - 1 14 13 27 Al -17196.861 0.047 8331.553 0.002 B- -4812.359 0.096 26 981538.408 0.050 - -1 13 14 27 Si - -12384.503 0.107 8124.341 0.004 B- -11662.044 26.340 26 986704.688 0.115 - -3 12 15 27 P p4n -722.458 26.340 7663.438 0.976 B- -17750# 400# 26 999224.409 28.277 - -5 11 16 27 S - 17028# 401# 6977# 15# B- * 27 018280# 430# -0 12 20 8 28 O x 52080# 699# 5988# 25# B- 18338# 802# 28 055910# 750# - 10 19 9 28 F -n 33741.596 393.024 6614.792 14.037 B- 22441.859 412.748 28 036223.095 421.928 - 8 18 10 28 Ne x 11299.737 126.068 7388.346 4.502 B- 12288.052 126.483 28 012130.767 135.339 - 6 17 11 28 Na x -988.315 10.246 7799.264 0.366 B- 14030.529 10.440 27 998939.000 11.000 - 4 16 12 28 Mg + -15018.845 2.001 8272.413 0.071 B- 1831.800 2.000 27 983876.606 2.148 - 2 15 13 28 Al -n -16850.645 0.077 8309.894 0.003 B- 4642.150 0.077 27 981910.087 0.083 - 0 14 14 28 Si -21492.79430 0.00049 8447.744 0.000 B- -14345.055 1.152 27 976926.53499 0.00052 - -2 13 15 28 P -7147.740 1.152 7907.479 0.041 B- -11220.945 160.004 27 992326.585 1.236 - -4 12 16 28 S -- 4073.206 160.000 7478.790 5.714 B- -23443# 617# 28 004372.766 171.767 - -6 11 17 28 Cl x 27516# 596# 6614# 21# B- * 28 029540# 640# -0 11 20 9 29 F x 40150.186 525.363 6444.031 18.116 B- 21750.385 546.221 29 043103.000 564.000 - 9 19 10 29 Ne x 18399.801 149.505 7167.067 5.155 B- 15719.807 149.685 29 019753.000 160.500 - 7 18 11 29 Na 2679.994 7.337 7682.151 0.253 B- 13282.824 13.557 29 002877.092 7.876 - 5 17 12 29 Mg x -10602.829 11.400 8113.202 0.393 B- 7604.931 11.405 28 988617.393 12.238 - 3 16 13 29 Al x -18207.760 0.345 8348.464 0.012 B- 3687.318 0.345 28 980453.164 0.370 - 1 15 14 29 Si -21895.07838 0.00056 8448.635 0.000 B- -4942.230 0.359 28 976494.66525 0.00060 - -1 14 15 29 P -16952.848 0.359 8251.236 0.012 B- -13796.432 50.001 28 981800.368 0.385 - -3 13 16 29 S +3n -3156.416 50.000 7748.520 1.724 B- -16318.592 195.192 28 996611.448 53.677 - -5 12 17 29 Cl -p 13162.176 188.680 7158.832 6.506 B- * 29 014130.178 202.555 -0 12 21 9 30 F x 48112# 596# 6233# 20# B- 24832# 648# 30 051650# 640# - 10 20 10 30 Ne 23280.117 253.250 7034.531 8.442 B- 14805.448 253.295 30 024992.235 271.875 - 8 19 11 30 Na 8474.670 4.727 7501.968 0.158 B- 17358.490 5.850 30 009097.932 5.074 - 6 18 12 30 Mg x -8883.820 3.447 8054.506 0.115 B- 6981.024 4.496 29 990462.826 3.700 - 4 17 13 30 Al x -15864.844 2.888 8261.128 0.096 B- 8568.116 2.888 29 982968.388 3.100 - 2 16 14 30 Si -n -24432.960 0.022 8520.654 0.001 B- -4232.106 0.061 29 973770.136 0.023 - 0 15 15 30 P - -20200.854 0.065 8353.506 0.002 B- -6141.601 0.196 29 978313.489 0.069 - -2 14 16 30 S - -14059.253 0.206 8122.707 0.007 B- -18502# 196# 29 984906.769 0.221 - -4 13 17 30 Cl x 4443# 196# 7480# 7# B- -16488# 284# 30 004770# 210# - -6 12 18 30 Ar -pp 20931.147 206.155 6904.204 6.872 B- * 30 022470.511 221.316 -0 13 22 9 31 F -nn 56143# 546# 6033# 18# B- 24961# 608# 31 060272# 587# - 11 21 10 31 Ne 31181.591 266.195 6813.090 8.587 B- 18935.559 266.562 31 033474.816 285.772 - 9 20 11 31 Na x 12246.031 13.972 7398.677 0.451 B- 15368.182 14.307 31 013146.656 15.000 - 7 19 12 31 Mg x -3122.151 3.074 7869.188 0.099 B- 11828.555 3.801 30 996648.232 3.300 - 5 18 13 31 Al x -14950.706 2.236 8225.517 0.072 B- 7998.330 2.236 30 983949.756 2.400 - 3 17 14 31 Si -n -22949.036 0.043 8458.291 0.001 B- 1491.505 0.043 30 975363.194 0.046 - 1 16 15 31 P -24440.54095 0.00067 8481.167 0.000 B- -5398.016 0.229 30 973761.99863 0.00072 - -1 15 16 31 S -19042.525 0.229 8281.800 0.007 B- -12007.974 3.454 30 979557.007 0.246 - -3 14 17 31 Cl -- -7034.551 3.447 7869.209 0.111 B- -18360# 200# 30 992448.098 3.700 - -5 13 18 31 Ar - 11325# 200# 7252# 6# B- * 31 012158# 215# -0 12 22 10 32 Ne x 36999# 503# 6671# 16# B- 18359# 504# 32 039720# 540# - 10 21 11 32 Na x 18640.151 37.260 7219.881 1.164 B- 19469.051 37.402 32 020011.026 40.000 - 8 20 12 32 Mg x -828.900 3.260 7803.840 0.102 B- 10270.467 7.879 31 999110.139 3.500 - 6 19 13 32 Al x -11099.367 7.173 8100.344 0.224 B- 12978.319 7.179 31 988084.339 7.700 - 4 18 14 32 Si x -24077.686 0.298 8481.468 0.009 B- 227.188 0.301 31 974151.539 0.320 - 2 17 15 32 P -n -24304.874 0.040 8464.120 0.001 B- 1710.660 0.040 31 973907.643 0.042 - 0 16 16 32 S -26015.53355 0.00132 8493.129 0.000 B- -12680.860 0.562 31 972071.17443 0.00141 - -2 15 17 32 Cl -13334.674 0.562 8072.404 0.018 B- -11134.323 1.857 31 985684.637 0.603 - -4 14 18 32 Ar x -2200.351 1.770 7700.008 0.055 B- -23299# 401# 31 997637.826 1.900 - -6 13 19 32 K x 21098# 401# 6947# 13# B- * 32 022650# 430# -0 13 23 10 33 Ne x 45997# 596# 6440# 18# B- 22217# 747# 33 049380# 640# - 11 22 11 33 Na x 23780.110 449.912 7089.926 13.634 B- 18817.813 449.921 33 025529.000 483.000 - 9 21 12 33 Mg x 4962.297 2.888 7636.455 0.088 B- 13459.677 7.559 33 005327.245 3.100 - 7 20 13 33 Al x -8497.380 6.986 8020.616 0.212 B- 12016.945 7.021 32 990877.687 7.500 - 5 19 14 33 Si x -20514.325 0.699 8361.059 0.021 B- 5823.021 1.295 32 977976.964 0.750 - 3 18 15 33 P + -26337.346 1.090 8513.806 0.033 B- 248.508 1.090 32 971725.694 1.170 - 1 17 16 33 S -26585.85434 0.00135 8497.630 0.000 B- -5582.517 0.391 32 971458.90985 0.00145 - -1 16 17 33 Cl -21003.337 0.391 8304.755 0.012 B- -11619.044 0.560 32 977451.989 0.419 - -3 15 18 33 Ar x -9384.292 0.401 7928.955 0.012 B- -16426# 196# 32 989925.547 0.430 - -5 14 19 33 K x 7042# 196# 7407# 6# B- * 33 007560# 210# -0 14 24 10 34 Ne -nn 52842# 513# 6287# 15# B- 21161# 789# 34 056728# 551# - 12 23 11 34 Na x 31680.111 599.416 6886.437 17.630 B- 23356.764 600.112 34 034010.000 643.500 - 10 22 12 34 Mg x 8323.348 28.876 7550.390 0.849 B- 11323.637 29.039 34 008935.481 31.000 - 8 21 13 34 Al x -3000.289 3.074 7860.428 0.090 B- 16956.563 14.448 33 996779.057 3.300 - 6 20 14 34 Si +pp -19956.852 14.118 8336.141 0.415 B- 4591.847 14.141 33 978575.437 15.155 - 4 19 15 34 P x -24548.698 0.810 8448.185 0.024 B- 5382.987 0.812 33 973645.887 0.870 - 2 18 16 34 S -29931.685 0.045 8583.498 0.001 B- -5491.603 0.038 33 967867.012 0.047 - 0 17 17 34 Cl -24440.082 0.049 8398.970 0.001 B- -6061.792 0.063 33 973762.491 0.052 - -2 16 18 34 Ar -18378.290 0.078 8197.672 0.002 B- -17158# 196# 33 980270.093 0.083 - -4 15 19 34 K x -1220# 196# 7670# 6# B- -15072# 357# 33 998690# 210# - -6 14 20 34 Ca x 13851# 298# 7204# 9# B- * 34 014870# 320# -0 13 24 11 35 Na -n 38231# 670# 6733# 19# B- 22592# 723# 35 041043# 720# - 11 23 12 35 Mg x 15639.784 269.668 7356.233 7.705 B- 15863.512 269.768 35 016790.000 289.500 - 9 22 13 35 Al x -223.728 7.359 7787.124 0.210 B- 14167.729 36.605 34 999759.817 7.900 - 7 21 14 35 Si 2p-n -14391.457 35.857 8169.563 1.024 B- 10466.342 35.905 34 984550.134 38.494 - 5 20 15 35 P +p -24857.799 1.866 8446.249 0.053 B- 3988.407 1.867 34 973314.053 2.003 - 3 19 16 35 S -28846.206 0.040 8537.850 0.001 B- 167.322 0.026 34 969032.322 0.043 - 1 18 17 35 Cl -29013.528 0.035 8520.278 0.001 B- -5966.243 0.679 34 968852.694 0.038 - -1 17 18 35 Ar - -23047.284 0.680 8327.461 0.019 B- -11874.394 0.852 34 975257.721 0.730 - -3 16 19 35 K 4n -11172.891 0.512 7965.840 0.015 B- -15961# 196# 34 988005.407 0.550 - -5 15 20 35 Ca x 4788# 196# 7487# 6# B- * 35 005140# 210# -0 14 25 11 36 Na -n 46303# 678# 6546# 19# B- 25923# 967# 36 049708# 728# - 12 24 12 36 Mg x 20380.157 690.237 7244.419 19.173 B- 14429.774 706.243 36 021879.000 741.000 - 10 23 13 36 Al x 5950.384 149.505 7623.515 4.153 B- 18386.508 165.851 36 006388.000 160.500 - 8 22 14 36 Si x -12436.124 71.797 8112.519 1.994 B- 7814.911 72.985 35 986649.271 77.077 - 6 21 15 36 P + -20251.034 13.114 8307.868 0.364 B- 10413.096 13.112 35 978259.619 14.078 - 4 20 16 36 S -30664.131 0.188 8575.389 0.005 B- -1142.126 0.189 35 967080.699 0.201 - 2 19 17 36 Cl -29522.005 0.036 8521.931 0.001 B- 709.535 0.045 35 968306.822 0.038 - 0 18 18 36 Ar -30231.540 0.027 8519.909 0.001 B- -12814.475 0.342 35 967545.105 0.028 - -2 17 19 36 K -17417.065 0.341 8142.219 0.009 B- -10965.916 40.001 35 981302.010 0.366 - -4 16 20 36 Ca 4n -6451.149 40.000 7815.879 1.111 B- -21802# 301# 35 993074.406 42.941 - -6 15 21 36 Sc x 15351# 298# 7189# 8# B- * 36 016480# 320# -0 15 26 11 37 Na -nn 53534# 687# 6392# 19# B- 25323# 980# 37 057471# 737# - 13 25 12 37 Mg -n 28211.474 698.947 7055.111 18.890 B- 18401.911 721.814 37 030286.265 750.350 - 11 24 13 37 Al x 9809.563 180.244 7531.315 4.871 B- 16381.075 213.168 37 010531.000 193.500 - 9 23 14 37 Si x -6571.511 113.809 7952.903 3.076 B- 12424.486 119.969 36 992945.191 122.179 - 7 22 15 37 P p-2n -18995.998 37.948 8267.555 1.026 B- 7900.419 37.947 36 979606.956 40.738 - 5 21 16 37 S -n -26896.417 0.198 8459.935 0.005 B- 4865.121 0.196 36 971125.507 0.212 - 3 20 17 37 Cl -31761.538 0.052 8570.281 0.001 B- -813.873 0.200 36 965902.584 0.055 - 1 19 18 37 Ar - -30947.664 0.207 8527.139 0.006 B- -6147.465 0.227 36 966776.314 0.221 - -1 18 19 37 K -p -24800.199 0.094 8339.847 0.003 B- -11664.133 0.641 36 973375.889 0.100 - -3 17 20 37 Ca x -13136.066 0.634 8003.456 0.017 B- -16656# 300# 36 985897.852 0.680 - -5 16 21 37 Sc x 3520# 300# 7532# 8# B- * 37 003779# 322# -0 14 26 12 38 Mg x 34074# 503# 6928# 13# B- 17864# 627# 38 036580# 540# - 12 25 13 38 Al x 16209.859 374.461 7377.097 9.854 B- 20380.157 388.847 38 017402.000 402.000 - 10 24 14 38 Si x -4170.299 104.793 7892.829 2.758 B- 10451.265 127.474 37 995523.000 112.500 - 8 23 15 38 P x -14621.563 72.581 8147.274 1.910 B- 12239.640 72.934 37 984303.105 77.918 - 6 22 16 38 S + -26861.203 7.172 8448.782 0.189 B- 2936.900 7.171 37 971163.310 7.699 - 4 21 17 38 Cl -n -29798.103 0.098 8505.481 0.003 B- 4916.718 0.218 37 968010.418 0.105 - 2 20 18 38 Ar -34714.821 0.195 8614.280 0.005 B- -5914.066 0.045 37 962732.104 0.209 - 0 19 19 38 K -28800.755 0.195 8438.058 0.005 B- -6742.256 0.063 37 969081.116 0.209 - -2 18 20 38 Ca -22058.499 0.194 8240.043 0.005 B- -17809# 200# 37 976319.226 0.208 - -4 17 21 38 Sc x -4249# 200# 7751# 5# B- -15119# 361# 37 995438# 215# - -6 16 22 38 Ti x 10870# 300# 7332# 8# B- * 38 011669# 322# -0 15 27 12 39 Mg -n 42275# 513# 6747# 13# B- 21625# 650# 39 045384# 551# - 13 26 13 39 Al x 20650# 400# 7281# 10# B- 18330# 422# 39 022169# 429# - 11 25 14 39 Si x 2320.352 135.532 7730.979 3.475 B- 15094.986 176.232 39 002491.000 145.500 - 9 24 15 39 P x -12774.634 112.645 8097.969 2.888 B- 10388.033 123.243 38 986285.865 120.929 - 7 23 16 39 S 2p-n -23162.667 50.000 8344.269 1.282 B- 6637.538 50.030 38 975133.852 53.677 - 5 22 17 39 Cl -nn -29800.205 1.732 8494.402 0.044 B- 3441.985 5.292 38 968008.162 1.859 - 3 21 18 39 Ar + -33242.190 5.000 8562.598 0.128 B- 565.000 5.000 38 964313.039 5.367 - 1 20 19 39 K -33807.19010 0.00458 8557.025 0.000 B- -6524.488 0.596 38 963706.48661 0.00492 - -1 19 20 39 Ca -27282.702 0.596 8369.670 0.015 B- -13109.993 24.007 38 970710.813 0.640 - -3 18 21 39 Sc 2n-p -14172.709 24.000 8013.456 0.615 B- -16373# 202# 38 984784.970 25.765 - -5 17 22 39 Ti x 2200# 200# 7574# 5# B- * 39 002362# 215# -0 16 28 12 40 Mg x 48350# 500# 6628# 13# B- 20760# 640# 40 051906# 537# - 14 27 13 40 Al x 27590# 400# 7127# 10# B- 22160# 528# 40 029619# 429# - 12 26 14 40 Si x 5429.679 345.119 7661.754 8.628 B- 13544.049 377.749 40 005829.000 370.500 - 10 25 15 40 P x -8114.370 153.582 7980.796 3.840 B- 14723.476 153.633 39 991288.865 164.876 - 8 24 16 40 S -22837.846 3.982 8329.325 0.100 B- 4719.967 32.312 39 975482.562 4.274 - 6 23 17 40 Cl + -27557.813 32.066 8427.765 0.802 B- 7482.082 32.066 39 970415.469 34.423 - 4 22 18 40 Ar -35039.89464 0.00224 8595.259 0.000 B- -1504.403 0.056 39 962383.12378 0.00240 - 2 21 19 40 K -33535.492 0.056 8538.090 0.001 B- 1310.893 0.060 39 963998.166 0.060 - 0 20 20 40 Ca -34846.384 0.021 8551.303 0.001 B- -14323.050 2.828 39 962590.865 0.022 - -2 19 21 40 Sc - -20523.335 2.828 8173.669 0.071 B- -11672.950 160.025 39 977967.292 3.036 - -4 18 22 40 Ti -- -8850.384 160.000 7862.286 4.000 B- -21020# 340# 39 990498.721 171.767 - -6 17 23 40 V x 12170# 300# 7317# 7# B- * 40 013065# 322# -0 15 28 13 41 Al x 33420# 500# 7008# 12# B- 21300# 747# 41 035878# 537# - 13 27 14 41 Si x 12119.668 554.705 7508.573 13.529 B- 17099.435 567.571 41 013011.000 595.500 - 11 26 15 41 P x -4979.767 120.163 7906.551 2.931 B- 14028.810 120.233 40 994654.000 129.000 - 9 25 16 41 S x -19008.577 4.099 8229.635 0.100 B- 8298.611 68.846 40 979593.451 4.400 - 7 24 17 41 Cl x -27307.189 68.723 8412.959 1.676 B- 5760.317 68.724 40 970684.525 73.777 - 5 23 18 41 Ar -n -33067.505 0.347 8534.372 0.008 B- 2492.038 0.347 40 964500.571 0.372 - 3 22 19 41 K -35559.54331 0.00380 8576.072 0.000 B- -421.653 0.138 40 961825.25796 0.00408 - 1 21 20 41 Ca -35137.890 0.138 8546.706 0.003 B- -6495.478 0.158 40 962277.921 0.147 - -1 20 21 41 Sc -28642.412 0.083 8369.198 0.002 B- -12944.875 27.945 40 969251.104 0.088 - -3 19 22 41 Ti x -15697.537 27.945 8034.388 0.682 B- -16018# 202# 40 983148.000 30.000 - -5 18 23 41 V x 320# 200# 7625# 5# B- * 41 000344# 215# -0 16 29 13 42 Al x 40100# 600# 6874# 14# B- 23630# 781# 42 043049# 644# - 14 28 14 42 Si x 16470# 500# 7418# 12# B- 15460# 591# 42 017681# 537# - 12 27 15 42 P x 1009.740 314.379 7767.866 7.485 B- 18647.485 314.392 42 001084.000 337.500 - 10 26 16 42 S x -17637.746 2.794 8193.227 0.067 B- 7194.021 59.681 41 981065.100 3.000 - 8 25 17 42 Cl x -24831.767 59.616 8345.886 1.419 B- 9590.908 59.895 41 973342.000 64.000 - 6 24 18 42 Ar x -34422.675 5.775 8555.613 0.138 B- 599.351 5.776 41 963045.736 6.200 - 4 23 19 42 K -n -35022.026 0.106 8551.256 0.003 B- 3525.219 0.183 41 962402.306 0.113 - 2 22 20 42 Ca -38547.245 0.149 8616.563 0.004 B- -6426.092 0.097 41 958617.828 0.159 - 0 21 21 42 Sc -32121.153 0.169 8444.933 0.004 B- -7016.479 0.224 41 965516.522 0.181 - -2 20 22 42 Ti -25104.674 0.277 8259.247 0.007 B- -17485# 196# 41 973049.022 0.297 - -4 19 23 42 V x -7620# 196# 7824# 5# B- -14350# 445# 41 991820# 210# - -6 18 24 42 Cr x 6730# 400# 7464# 10# B- * 42 007225# 429# -0 17 30 13 43 Al x 47020# 800# 6741# 19# B- 23919# 998# 43 050478# 859# - 15 29 14 43 Si x 23101# 596# 7279# 14# B- 18421# 814# 43 024800# 640# - 13 28 15 43 P x 4679.826 554.705 7689.572 12.900 B- 16875.285 554.727 43 005024.000 595.500 - 11 27 16 43 S x -12195.459 4.970 8063.827 0.116 B- 11964.049 62.058 42 986907.635 5.335 - 9 26 17 43 Cl x -24159.508 61.858 8323.866 1.439 B- 7850.300 62.086 42 974063.700 66.407 - 7 25 18 43 Ar x -32009.808 5.310 8488.237 0.123 B- 4565.581 5.325 42 965636.055 5.700 - 5 24 19 43 K -4n -36575.389 0.410 8576.220 0.010 B- 1833.434 0.469 42 960734.703 0.440 - 3 23 20 43 Ca -38408.822 0.228 8600.663 0.005 B- -2220.720 1.865 42 958766.430 0.244 - 1 22 21 43 Sc -p -36188.102 1.863 8530.825 0.043 B- -6867.020 7.481 42 961150.472 1.999 - -1 21 22 43 Ti -n2p -29321.082 7.245 8352.932 0.168 B- -11404.726 43.457 42 968522.521 7.777 - -3 20 23 43 V x -17916.356 42.849 8069.512 0.996 B- -15946# 402# 42 980766.000 46.000 - -5 19 24 43 Cr x -1970# 400# 7680# 9# B- * 42 997885# 429# -0 16 30 14 44 Si x 28513# 596# 7174# 14# B- 18063# 778# 44 030610# 640# - 14 29 15 44 P x 10450# 500# 7567# 11# B- 19655# 500# 44 011219# 537# - 12 28 16 44 S x -9204.233 5.216 7996.015 0.119 B- 11180.290 136.421 43 990118.848 5.600 - 10 27 17 44 Cl x -20384.523 136.321 8232.332 3.098 B- 12288.731 136.330 43 978116.312 146.346 - 8 26 18 44 Ar x -32673.255 1.584 8493.840 0.036 B- 3108.237 1.638 43 964923.816 1.700 - 6 25 19 44 K x -35781.492 0.419 8546.701 0.010 B- 5687.183 0.530 43 961586.986 0.450 - 4 24 20 44 Ca -41468.675 0.325 8658.175 0.007 B- -3652.690 1.757 43 955481.543 0.348 - 2 23 21 44 Sc -p -37815.985 1.756 8557.379 0.040 B- -267.416 1.890 43 959402.867 1.884 - 0 22 22 44 Ti -a -37548.569 0.700 8533.520 0.016 B- -13432.189 181.643 43 959689.951 0.751 - -2 21 23 44 V x -24116.380 181.641 8210.463 4.128 B- -10756# 351# 43 974110.000 195.000 - -4 20 24 44 Cr x -13360# 300# 7948# 7# B- -20390# 583# 43 985657# 322# - -6 19 25 44 Mn x 7030# 500# 7467# 11# B- * 44 007547# 537# -0 17 31 14 45 Si x 37490# 700# 6995# 16# B- 21890# 860# 45 040247# 751# - 15 30 15 45 P x 15600# 500# 7464# 11# B- 19589# 1150# 45 016747# 537# - 13 29 16 45 S x -3989.589 1035.356 7881.807 23.008 B- 14272.954 1044.271 44 995717.000 1111.500 - 11 28 17 45 Cl x -18262.543 136.163 8181.598 3.026 B- 11508.254 136.164 44 980394.353 146.177 - 9 27 18 45 Ar x -29770.796 0.512 8419.952 0.011 B- 6844.841 0.731 44 968039.733 0.550 - 7 26 19 45 K x -36615.638 0.522 8554.674 0.012 B- 4196.536 0.637 44 960691.493 0.560 - 5 25 20 45 Ca -40812.174 0.366 8630.545 0.008 B- 259.722 0.747 44 956186.326 0.392 - 3 24 21 45 Sc -41071.896 0.675 8618.931 0.015 B- -2062.056 0.509 44 955907.503 0.724 - 1 23 22 45 Ti -39009.840 0.845 8555.722 0.019 B- -7123.824 0.214 44 958121.211 0.907 - -1 22 23 45 V -31886.016 0.872 8380.029 0.019 B- -12371.217 35.408 44 965768.951 0.935 - -3 21 24 45 Cr x -19514.799 35.397 8087.728 0.787 B- -14265# 401# 44 979050.000 38.000 - -5 20 25 45 Mn x -5250# 400# 7753# 9# B- -19012# 565# 44 994364# 429# - -7 19 26 45 Fe -pp 13762# 400# 7313# 9# B- * 45 014774# 429# -0 16 31 15 46 P x 22970# 700# 7317# 15# B- 22630# 860# 46 024659# 751# - 14 30 16 46 S x 340# 500# 7792# 11# B- 14199# 542# 46 000365# 537# - 12 29 17 46 Cl x -13859.398 208.661 8083.480 4.536 B- 15913.528 208.664 45 985121.323 224.006 - 10 28 18 46 Ar x -29772.926 1.118 8412.419 0.024 B- 5640.997 1.333 45 968037.446 1.200 - 8 27 19 46 K x -35413.924 0.727 8518.042 0.016 B- 7725.438 2.350 45 961981.586 0.780 - 6 26 20 46 Ca -43139.361 2.235 8668.979 0.049 B- -1378.143 2.333 45 953687.988 2.399 - 4 25 21 46 Sc -n -41761.219 0.683 8622.012 0.015 B- 2366.581 0.667 45 955167.485 0.732 - 2 24 22 46 Ti -44127.799 0.165 8656.451 0.004 B- -7052.449 0.093 45 952626.856 0.176 - 0 23 23 46 V -37075.351 0.202 8486.130 0.004 B- -7603.784 11.455 45 960197.971 0.216 - -2 22 24 46 Cr -29471.567 11.453 8303.823 0.249 B- -16902# 400# 45 968360.970 12.295 - -4 21 25 46 Mn x -12570# 400# 7919# 9# B- -13480# 640# 45 986506# 429# - -6 20 26 46 Fe x 910# 500# 7609# 11# B- * 46 000977# 537# -0 17 32 15 47 P x 29710# 800# 7190# 17# B- 22340# 944# 47 031895# 859# - 15 31 16 47 S x 7370# 500# 7648# 11# B- 17150# 640# 47 007912# 537# - 13 30 17 47 Cl x -9780# 400# 7996# 9# B- 15587# 400# 46 989501# 429# - 11 29 18 47 Ar x -25366.338 1.118 8311.404 0.024 B- 10345.638 1.789 46 972768.114 1.200 - 9 28 19 47 K x -35711.976 1.397 8514.879 0.030 B- 6632.442 2.625 46 961661.614 1.500 - 7 27 20 47 Ca -42344.418 2.222 8639.349 0.047 B- 1992.177 1.185 46 954541.394 2.385 - 5 26 21 47 Sc -44336.595 1.933 8665.090 0.041 B- 600.769 1.929 46 952402.704 2.074 - 3 25 22 47 Ti -44937.364 0.115 8661.227 0.002 B- -2930.746 0.138 46 951757.752 0.123 - 1 24 23 47 V -42006.618 0.169 8582.225 0.004 B- -7444.040 6.032 46 954904.038 0.181 - -1 23 24 47 Cr -34562.578 6.030 8407.195 0.128 B- -11996.204 32.240 46 962895.544 6.473 - -3 22 25 47 Mn x -22566.374 31.671 8135.311 0.674 B- -15697# 501# 46 975774.000 34.000 - -5 21 26 47 Fe x -6870# 500# 7785# 11# B- -17240# 781# 46 992625# 537# - -7 20 27 47 Co x 10370# 600# 7401# 13# B- * 47 011133# 644# -0 16 32 16 48 S x 12761# 596# 7545# 12# B- 17042# 778# 48 013700# 640# - 14 31 17 48 Cl x -4280# 500# 7883# 10# B- 18001# 587# 47 995405# 537# - 12 30 18 48 Ar x -22281.337 307.393 8242.132 6.404 B- 10003.140 307.394 47 976080.000 330.000 - 10 29 19 48 K x -32284.477 0.773 8434.232 0.016 B- 11940.153 0.779 47 965341.186 0.830 - 8 28 20 48 Ca -44224.629 0.096 8666.686 0.002 B- 279.213 4.950 47 952522.904 0.103 - 6 27 21 48 Sc -44503.842 4.951 8656.204 0.103 B- 3988.866 4.950 47 952223.157 5.314 - 4 26 22 48 Ti -48492.709 0.109 8723.006 0.002 B- -4015.015 0.969 47 947940.932 0.117 - 2 25 23 48 V -44477.694 0.975 8623.061 0.020 B- -1655.673 7.388 47 952251.229 1.046 - 0 24 24 48 Cr +nn -42822.020 7.324 8572.269 0.153 B- -13525.682 10.087 47 954028.667 7.862 - -2 23 25 48 Mn -29296.338 6.939 8274.185 0.145 B- -11296# 400# 47 968549.085 7.449 - -4 22 26 48 Fe x -18000# 400# 8023# 8# B- -19500# 640# 47 980676# 429# - -6 21 27 48 Co x 1500# 500# 7600# 10# B- -15293# 708# 48 001610# 537# - -8 20 28 48 Ni -pp 16793# 502# 7265# 10# B- * 48 018028# 538# -0 17 33 16 49 S -n 21093# 667# 7385# 14# B- 20153# 897# 49 022644# 716# - 15 32 17 49 Cl x 940# 600# 7781# 12# B- 18130# 721# 49 001009# 644# - 13 31 18 49 Ar x -17190# 400# 8135# 8# B- 12422# 400# 48 981546# 429# - 11 30 19 49 K x -29611.490 0.801 8372.274 0.016 B- 11688.275 0.826 48 968210.755 0.860 - 9 29 20 49 Ca -n -41299.765 0.201 8594.844 0.004 B- 5261.500 2.702 48 955662.875 0.216 - 7 28 21 49 Sc -46561.265 2.698 8686.256 0.055 B- 2002.522 2.697 48 950014.423 2.896 - 5 27 22 49 Ti -48563.787 0.114 8711.157 0.002 B- -601.856 0.820 48 947864.627 0.122 - 3 26 23 49 V - -47961.931 0.828 8682.908 0.017 B- -2628.871 2.391 48 948510.746 0.889 - 1 25 24 49 Cr -45333.060 2.243 8613.291 0.046 B- -7712.426 0.233 48 951332.955 2.407 - -1 24 25 49 Mn -37620.634 2.255 8439.929 0.046 B- -12869.907 24.324 48 959612.585 2.420 - -3 23 26 49 Fe x -24750.727 24.219 8161.311 0.494 B- -14870# 501# 48 973429.000 26.000 - -5 22 27 49 Co x -9880# 500# 7842# 10# B- -18080# 781# 48 989393# 537# - -7 21 28 49 Ni x 8200# 600# 7457# 12# B- * 49 008803# 644# -0 16 33 17 50 Cl x 7740# 600# 7651# 12# B- 21069# 781# 50 008309# 644# - 14 32 18 50 Ar x -13330# 500# 8056# 10# B- 12398# 500# 49 985690# 537# - 12 31 19 50 K x -25727.848 7.731 8288.582 0.155 B- 13861.376 7.892 49 972380.017 8.300 - 10 30 20 50 Ca x -39589.224 1.584 8550.163 0.032 B- 4958.158 15.084 49 957499.217 1.700 - 8 29 21 50 Sc -pn -44547.382 15.000 8633.679 0.300 B- 6884.278 15.000 49 952176.415 16.103 - 6 28 22 50 Ti -51431.660 0.121 8755.718 0.002 B- -2207.647 0.426 49 944785.839 0.129 - 4 27 23 50 V +n -49224.013 0.409 8695.918 0.008 B- 1038.059 0.299 49 947155.845 0.438 - 2 26 24 50 Cr -50262.072 0.437 8701.032 0.009 B- -7634.477 0.067 49 946041.443 0.468 - 0 25 25 50 Mn -42627.595 0.442 8532.696 0.009 B- -8151.139 8.395 49 954237.391 0.474 - -2 24 26 50 Fe x -34476.456 8.383 8354.026 0.168 B- -16846# 400# 49 962988.000 9.000 - -4 23 27 50 Co x -17630# 400# 8001# 8# B- -13510# 640# 49 981073# 429# - -6 22 28 50 Ni x -4120# 500# 7716# 10# B- * 49 995577# 537# -0 17 34 17 51 Cl x 14290# 700# 7530# 14# B- 20980# 922# 51 015341# 751# - 15 33 18 51 Ar x -6690# 600# 7926# 12# B- 15826# 600# 50 992818# 644# - 13 32 19 51 K x -22516.196 13.047 8221.349 0.256 B- 13816.107 13.057 50 975827.867 14.006 - 11 31 20 51 Ca x -36332.304 0.522 8476.913 0.010 B- 6896.381 20.007 50 960995.665 0.560 - 9 30 21 51 Sc -p2n -43228.684 20.000 8596.796 0.392 B- 6504.153 20.006 50 953592.095 21.471 - 7 29 22 51 Ti -n -49732.837 0.505 8708.988 0.010 B- 2471.005 0.644 50 946609.600 0.541 - 5 28 23 51 V -52203.842 0.401 8742.099 0.008 B- -752.447 0.213 50 943956.867 0.430 - 3 27 24 51 Cr -51451.395 0.400 8712.005 0.008 B- -3207.518 0.346 50 944764.652 0.429 - 1 26 25 51 Mn -48243.877 0.502 8633.772 0.010 B- -8041.321 8.977 50 948208.065 0.539 - -1 25 26 51 Fe -40202.555 8.964 8460.759 0.176 B- -12860.412 49.260 50 956840.779 9.623 - -3 24 27 51 Co x -27342.143 48.438 8193.254 0.950 B- -15442# 503# 50 970647.000 52.000 - -5 23 28 51 Ni x -11900# 500# 7875# 10# B- * 50 987225# 537# -0 16 34 18 52 Ar x -1280# 600# 7825# 12# B- 15858# 601# 51 998626# 644# - 14 33 19 52 K x -17137.627 33.534 8115.029 0.645 B- 17128.639 33.540 51 981602.000 36.000 - 12 32 20 52 Ca x -34266.266 0.671 8429.381 0.013 B- 6177.013 81.855 51 963213.648 0.720 - 10 31 21 52 Sc x -40443.279 81.852 8533.125 1.574 B- 9026.541 82.157 51 956582.351 87.871 - 8 30 22 52 Ti -nn -49469.820 7.072 8691.667 0.136 B- 1973.948 7.085 51 946891.960 7.592 - 6 29 23 52 V -n -51443.769 0.420 8714.582 0.008 B- 3975.473 0.531 51 944772.839 0.450 - 4 28 24 52 Cr -55419.242 0.340 8775.989 0.007 B- -4711.958 1.851 51 940504.992 0.364 - 2 27 25 52 Mn -50707.284 1.845 8670.329 0.035 B- -2376.920 5.017 51 945563.488 1.980 - 0 26 26 52 Fe -48330.363 5.117 8609.574 0.098 B- -13969.413 9.822 51 948115.217 5.493 - -2 25 27 52 Co x -34360.951 8.383 8325.886 0.161 B- -12031# 400# 51 963112.000 9.000 - -4 24 28 52 Ni x -22330# 400# 8079# 8# B- -20049# 721# 51 976028# 429# - -6 23 29 52 Cu x -2280# 600# 7679# 12# B- * 51 997552# 644# -0 17 35 18 53 Ar x 6791# 699# 7677# 13# B- 19086# 708# 53 007290# 750# - 15 34 19 53 K x -12295.721 111.779 8022.848 2.109 B- 17091.983 120.047 52 986800.000 120.000 - 13 33 20 53 Ca x -29387.704 43.780 8330.577 0.826 B- 9519.104 103.774 52 968451.000 47.000 - 11 32 21 53 Sc x -38906.808 94.087 8495.421 1.775 B- 7924.253 137.339 52 958231.821 101.006 - 9 31 22 53 Ti + -46831.061 100.049 8630.174 1.888 B- 5020.000 100.000 52 949724.785 107.406 - 7 30 23 53 V +p -51851.061 3.120 8710.130 0.059 B- 3435.938 3.102 52 944335.593 3.349 - 5 29 24 53 Cr -55286.999 0.348 8760.198 0.007 B- -596.884 0.356 52 940646.961 0.373 - 3 28 25 53 Mn -54690.116 0.450 8734.175 0.009 B- -3742.586 1.686 52 941287.742 0.483 - 1 27 26 53 Fe -50947.530 1.656 8648.799 0.031 B- -8288.101 0.443 52 945305.574 1.777 - -1 26 27 53 Co -42659.428 1.713 8477.658 0.032 B- -13028.604 25.209 52 954203.217 1.839 - -3 25 28 53 Ni x -29630.824 25.150 8217.074 0.475 B- -16361# 501# 52 968190.000 27.000 - -5 24 29 53 Cu x -13270# 500# 7894# 9# B- * 52 985754# 537# -0 16 35 19 54 K x -5002# 596# 7889# 11# B- 20158# 598# 53 994630# 640# - 14 34 20 54 Ca x -25160.585 48.438 8247.496 0.897 B- 8730.315 277.066 53 972989.000 52.000 - 12 33 21 54 Sc x -33890.900 272.800 8394.681 5.052 B- 11731.081 284.990 53 963616.620 292.862 - 10 32 22 54 Ti x -45621.981 82.461 8597.435 1.527 B- 4271.192 83.815 53 951022.786 88.526 - 8 31 23 54 V + -49893.173 15.004 8662.043 0.278 B- 7041.592 15.000 53 946437.472 16.107 - 6 30 24 54 Cr -56934.765 0.353 8777.955 0.007 B- -1377.136 1.008 53 938878.012 0.378 - 4 29 25 54 Mn -p -55557.629 1.059 8737.965 0.020 B- 696.872 1.076 53 940356.429 1.136 - 2 28 26 54 Fe -56254.500 0.372 8736.382 0.007 B- -8244.547 0.089 53 939608.306 0.399 - 0 27 27 54 Co -48009.953 0.383 8569.217 0.007 B- -8731.646 4.673 53 948459.192 0.411 - -2 26 28 54 Ni x -39278.308 4.657 8393.032 0.086 B- -17868# 400# 53 957833.000 5.000 - -4 25 29 54 Cu x -21410# 400# 8048# 7# B- -15139# 565# 53 977015# 429# - -6 24 30 54 Zn -pp -6272# 400# 7753# 7# B- * 53 993267# 430# -0 17 36 19 55 K x 708# 699# 7788# 13# B- 19058# 760# 55 000760# 750# - 15 35 20 55 Ca x -18350# 300# 8120# 5# B- 11809# 544# 54 980300# 322# - 13 34 21 55 Sc x -30159.352 454.342 8320.955 8.261 B- 11508.735 482.226 54 967622.601 487.756 - 11 33 22 55 Ti -41668.088 161.602 8515.980 2.938 B- 7476.498 157.206 54 955267.465 173.486 - 9 32 23 55 V -49144.586 95.104 8637.692 1.729 B- 5965.125 95.103 54 947241.114 102.098 - 7 31 24 55 Cr -55109.710 0.399 8731.924 0.007 B- 2602.703 0.368 54 940837.289 0.428 - 5 30 25 55 Mn -57712.413 0.303 8765.022 0.006 B- -231.114 0.179 54 938043.172 0.325 - 3 29 26 55 Fe -57481.300 0.342 8746.595 0.006 B- -3451.417 0.324 54 938291.283 0.367 - 1 28 27 55 Co -54029.883 0.428 8669.618 0.008 B- -8694.034 0.578 54 941996.531 0.459 - -1 27 28 55 Ni - -45335.849 0.719 8497.320 0.013 B- -13700.449 155.561 54 951329.961 0.771 - -3 26 29 55 Cu x -31635.399 155.559 8233.996 2.828 B- -17065# 429# 54 966038.000 167.000 - -5 25 30 55 Zn x -14570# 400# 7909# 7# B- * 54 984358# 429# -0 18 37 19 56 K x 7927# 801# 7664# 14# B- 21825# 895# 56 008510# 860# - 16 36 20 56 Ca x -13898# 400# 8040# 7# B- 10954# 710# 55 985080# 429# - 14 35 21 56 Sc x -24852.260 586.841 8221.728 10.479 B- 14467.788 599.236 55 973320.000 630.000 - 12 34 22 56 Ti -39320.048 121.247 8466.110 2.165 B- 6834.833 194.550 55 957788.190 130.164 - 10 33 23 56 V -46154.881 176.898 8574.191 3.159 B- 9130.120 176.899 55 950450.694 189.907 - 8 32 24 56 Cr ++ -55285.001 0.603 8723.258 0.011 B- 1626.538 0.561 55 940649.107 0.647 - 6 31 25 56 Mn -n -56911.538 0.331 8738.333 0.006 B- 3695.544 0.207 55 938902.947 0.355 - 4 30 26 56 Fe -60607.082 0.302 8790.354 0.005 B- -4566.680 0.411 55 934935.617 0.324 - 2 29 27 56 Co -56040.402 0.493 8694.836 0.009 B- -2132.863 0.374 55 939838.150 0.529 - 0 28 28 56 Ni -53907.539 0.422 8642.779 0.008 B- -15264.511 14.910 55 942127.872 0.452 - -2 27 29 56 Cu x -38643.029 14.904 8356.227 0.266 B- -13253# 400# 55 958515.000 16.000 - -4 26 30 56 Zn x -25390# 400# 8106# 7# B- -22000# 640# 55 972743# 429# - -6 25 31 56 Ga x -3390# 500# 7699# 9# B- * 55 996361# 537# -0 17 37 20 57 Ca x -6874# 400# 7917# 7# B- 14121# 1364# 56 992620# 429# - 15 36 21 57 Sc x -20995.875 1304.092 8151.433 22.879 B- 12919.758 1329.062 56 977460.000 1400.000 - 13 35 22 57 Ti x -33915.633 256.417 8364.370 4.499 B- 10497.818 268.750 56 963590.068 275.274 - 11 34 23 57 V x -44413.450 80.479 8534.817 1.412 B- 8111.252 80.486 56 952320.197 86.397 - 9 33 24 57 Cr x -52524.702 1.068 8663.394 0.019 B- 4961.548 1.846 56 943612.409 1.146 - 7 32 25 57 Mn -57486.251 1.505 8736.713 0.026 B- 2695.589 1.526 56 938285.968 1.615 - 5 31 26 57 Fe -60181.839 0.304 8770.279 0.005 B- -836.276 0.451 56 935392.134 0.326 - 3 30 27 57 Co -59345.564 0.533 8741.882 0.009 B- -3261.731 0.642 56 936289.913 0.572 - 1 29 28 57 Ni -56083.833 0.582 8670.933 0.010 B- -8774.947 0.439 56 939791.525 0.624 - -1 28 29 57 Cu -47308.886 0.519 8503.262 0.009 B- -14759# 200# 56 949211.819 0.557 - -3 27 30 57 Zn x -32550# 200# 8231# 4# B- -17540# 447# 56 965056# 215# - -5 26 31 57 Ga x -15010# 400# 7909# 7# B- * 56 983886# 429# -0 18 38 20 58 Ca x -1919# 500# 7835# 9# B- 12957# 640# 57 997940# 537# - 16 37 21 58 Sc x -14876# 400# 8045# 7# B- 16234# 447# 57 984030# 429# - 14 36 22 58 Ti x -31110# 200# 8311# 3# B- 9292# 219# 57 966602# 215# - 12 35 23 58 V x -40401.753 89.374 8457.658 1.541 B- 11590.049 89.386 57 956626.932 95.947 - 10 34 24 58 Cr x -51991.801 1.490 8643.998 0.026 B- 3835.759 3.085 57 944184.502 1.600 - 8 33 25 58 Mn x -55827.560 2.701 8696.643 0.047 B- 6327.553 2.723 57 940066.646 2.900 - 6 32 26 58 Fe -62155.113 0.343 8792.250 0.006 B- -2307.955 1.139 57 933273.738 0.368 - 4 31 27 58 Co -59847.158 1.160 8738.969 0.020 B- 381.586 1.107 57 935751.429 1.245 - 2 30 28 58 Ni -60228.744 0.373 8732.059 0.006 B- -8561.019 0.443 57 935341.780 0.400 - 0 29 29 58 Cu -51667.725 0.578 8570.967 0.010 B- -9368.981 50.002 57 944532.413 0.621 - -2 28 30 58 Zn -- -42298.744 50.001 8395.944 0.862 B- -18759# 304# 57 954590.428 53.678 - -4 27 31 58 Ga x -23540# 300# 8059# 5# B- -16459# 583# 57 974729# 322# - -6 26 32 58 Ge x -7080# 500# 7762# 9# B- * 57 992399# 537# -0 17 38 21 59 Sc x -10302# 400# 7967# 7# B- 15208# 447# 58 988940# 429# - 15 37 22 59 Ti x -25510# 200# 8212# 3# B- 12322# 258# 58 972614# 215# - 13 36 23 59 V x -37832.015 161.874 8407.555 2.744 B- 10253.745 270.218 58 959385.659 173.778 - 11 35 24 59 Cr x -48085.760 216.367 8568.087 3.667 B- 7439.560 216.380 58 948377.810 232.279 - 9 34 25 59 Mn x -55525.320 2.329 8680.921 0.039 B- 5139.485 2.356 58 940391.113 2.500 - 7 33 26 59 Fe -60664.805 0.355 8754.771 0.006 B- 1564.903 0.369 58 934873.649 0.380 - 5 32 27 59 Co -62229.709 0.418 8768.035 0.007 B- -1073.002 0.194 58 933193.656 0.448 - 3 31 28 59 Ni -61156.707 0.374 8736.588 0.006 B- -4798.380 0.397 58 934345.571 0.402 - 1 30 29 59 Cu -56358.327 0.544 8642.000 0.009 B- -9142.775 0.602 58 939496.844 0.584 - -1 29 30 59 Zn -47215.551 0.771 8473.777 0.013 B- -13455# 170# 58 949312.017 0.827 - -3 28 31 59 Ga x -33760# 170# 8232# 3# B- -17890# 434# 58 963757# 183# - -5 27 32 59 Ge x -15870# 400# 7916# 7# B- * 58 982963# 429# -0 18 39 21 60 Sc x -4052# 500# 7865# 8# B- 18278# 583# 59 995650# 537# - 16 38 22 60 Ti x -22330# 300# 8157# 5# B- 10912# 372# 59 976028# 322# - 14 37 23 60 V x -33241.956 220.159 8325.450 3.669 B- 13427.621 293.169 59 964313.290 236.350 - 12 36 24 60 Cr x -46669.576 193.593 8536.205 3.227 B- 6298.361 193.607 59 949898.146 207.830 - 10 35 25 60 Mn x -52967.938 2.329 8628.138 0.039 B- 8445.079 4.128 59 943136.576 2.500 - 8 34 26 60 Fe -nn -61413.017 3.409 8755.851 0.057 B- 237.293 3.411 59 934070.411 3.659 - 6 33 27 60 Co -n -61650.309 0.424 8746.766 0.007 B- 2822.809 0.212 59 933815.667 0.455 - 4 32 28 60 Ni -64473.118 0.376 8780.774 0.006 B- -6127.982 1.573 59 930785.256 0.403 - 2 31 29 60 Cu - -58345.137 1.618 8665.602 0.027 B- -4170.797 1.629 59 937363.916 1.736 - 0 30 30 60 Zn -54174.340 0.564 8583.050 0.009 B- -14584# 200# 59 941841.450 0.605 - -2 29 31 60 Ga x -39590# 200# 8327# 3# B- -12501# 361# 59 957498# 215# - -4 28 32 60 Ge x -27090# 300# 8106# 5# B- -21620# 500# 59 970918# 322# - -6 27 33 60 As x -5470# 400# 7732# 7# B- * 59 994128# 429# -0 19 40 21 61 Sc x 931# 600# 7787# 10# B- 17281# 721# 61 001000# 644# - 17 39 22 61 Ti x -16350# 400# 8057# 7# B- 14157# 979# 60 982448# 429# - 15 38 23 61 V x -30506.429 894.234 8276.439 14.660 B- 11968.800 899.958 60 967250.000 960.000 - 13 37 24 61 Cr x -42475.229 101.341 8459.824 1.661 B- 9266.893 101.367 60 954400.963 108.793 - 11 36 25 61 Mn x -51742.122 2.329 8598.915 0.038 B- 7178.372 3.497 60 944452.544 2.500 - 9 35 26 61 Fe x -58920.494 2.608 8703.768 0.043 B- 3977.572 2.742 60 936746.244 2.800 - 7 34 27 61 Co p2n -62898.066 0.846 8756.148 0.014 B- 1323.839 0.790 60 932476.145 0.908 - 5 33 28 61 Ni -64221.905 0.378 8765.025 0.006 B- -2237.845 0.966 60 931054.945 0.405 - 3 32 29 61 Cu p2n -61984.059 0.953 8715.514 0.016 B- -5635.156 15.903 60 933457.371 1.023 - 1 31 30 61 Zn -56348.903 15.899 8610.309 0.261 B- -9214.245 37.679 60 939506.960 17.068 - -1 30 31 61 Ga -47134.659 37.994 8446.431 0.623 B- -13775# 302# 60 949398.859 40.787 - -3 29 32 61 Ge x -33360# 300# 8208# 5# B- -16459# 424# 60 964187# 322# - -5 28 33 61 As x -16900# 300# 7925# 5# B- * 60 981857# 322# -0 18 40 22 62 Ti x -12500# 400# 7995# 6# B- 12977# 499# 61 986581# 429# - 16 39 23 62 V x -25476# 298# 8192# 5# B- 15419# 333# 61 972650# 320# - 14 38 24 62 Cr x -40894.961 148.099 8428.069 2.389 B- 7628.996 148.244 61 956097.451 158.991 - 12 37 25 62 Mn IT -48523.957 6.542 8538.499 0.106 B- 10354.091 7.114 61 947907.386 7.023 - 10 36 26 62 Fe x -58878.048 2.794 8692.882 0.045 B- 2546.235 18.784 61 936791.812 3.000 - 8 35 27 62 Co + -61424.282 18.575 8721.332 0.300 B- 5322.040 18.570 61 934058.317 19.940 - 6 34 28 62 Ni -66746.323 0.439 8794.553 0.007 B- -3958.896 0.475 61 928344.871 0.470 - 4 33 29 62 Cu - -62787.426 0.647 8718.081 0.010 B- -1619.455 0.651 61 932594.921 0.694 - 2 32 30 62 Zn -61167.972 0.625 8679.343 0.010 B- -9181.066 0.376 61 934333.477 0.670 - 0 31 31 62 Ga -51986.906 0.647 8518.642 0.010 B- -10247# 140# 61 944189.757 0.694 - -2 30 32 62 Ge x -41740# 140# 8341# 2# B- -17420# 331# 61 955190# 150# - -4 29 33 62 As x -24320# 300# 8047# 5# B- * 61 973891# 322# -0 19 41 22 63 Ti x -5750# 500# 7889# 8# B- 16140# 640# 62 993827# 537# - 17 40 23 63 V x -21890# 400# 8133# 6# B- 14117# 537# 62 976500# 429# - 15 39 24 63 Cr x -36007.474 358.073 8344.828 5.684 B- 10879.579 358.092 62 961344.384 384.407 - 13 38 25 63 Mn x -46887.053 3.726 8505.101 0.059 B- 8748.568 5.692 62 949664.675 4.000 - 11 37 26 63 Fe -55635.621 4.302 8631.549 0.068 B- 6215.819 19.067 62 940272.700 4.618 - 9 36 27 63 Co -61851.440 18.575 8717.795 0.295 B- 3661.335 18.570 62 933599.744 19.941 - 7 35 28 63 Ni -65512.775 0.440 8763.493 0.007 B- 66.977 0.015 62 929669.139 0.472 - 5 34 29 63 Cu -65579.752 0.440 8752.138 0.007 B- -3366.355 1.546 62 929597.236 0.472 - 3 33 30 63 Zn -62213.397 1.561 8686.285 0.025 B- -5666.304 2.034 62 933211.167 1.676 - 1 32 31 63 Ga x -56547.093 1.304 8583.926 0.021 B- -9625.877 37.283 62 939294.195 1.400 - -1 31 32 63 Ge x -46921.216 37.260 8418.716 0.591 B- -13421# 204# 62 949628.000 40.000 - -3 30 33 63 As x -33500# 200# 8193# 3# B- * 62 964036# 215# -0 20 42 22 64 Ti x -1025# 600# 7818# 9# B- 15295# 721# 63 998900# 644# - 18 41 23 64 V x -16320# 400# 8045# 6# B- 17160# 594# 63 982480# 429# - 16 40 24 64 Cr x -33479.757 439.665 8301.058 6.870 B- 9509.277 439.679 63 964058.000 472.000 - 14 39 25 64 Mn x -42989.035 3.540 8437.417 0.055 B- 11980.510 6.140 63 953849.370 3.800 - 12 38 26 64 Fe x -54969.544 5.017 8612.388 0.078 B- 4822.785 20.625 63 940987.763 5.386 - 10 37 27 64 Co + -59792.329 20.006 8675.520 0.313 B- 7306.592 20.000 63 935810.291 21.476 - 8 36 28 64 Ni -67098.921 0.475 8777.461 0.007 B- -1674.376 0.225 63 927966.341 0.510 - 6 35 29 64 Cu -65424.545 0.448 8739.075 0.007 B- 579.469 0.650 63 929763.857 0.481 - 4 34 30 64 Zn -66004.014 0.647 8735.905 0.010 B- -7171.194 1.483 63 929141.772 0.694 - 2 33 31 64 Ga -58832.821 1.429 8611.631 0.022 B- -4517.325 3.991 63 936840.365 1.533 - 0 32 32 64 Ge x -54315.496 3.726 8528.823 0.058 B- -14783# 203# 63 941689.913 4.000 - -2 31 33 64 As -p -39532# 203# 8286# 3# B- -12832# 543# 63 957560# 218# - -4 30 34 64 Se x -26700# 503# 8073# 8# B- * 63 971336# 540# -0 19 42 23 65 V x -11780# 500# 7976# 8# B- 16440# 583# 64 987354# 537# - 17 41 24 65 Cr x -28220# 300# 8217# 5# B- 12748# 300# 64 969705# 322# - 15 40 25 65 Mn x -40967.339 3.726 8400.681 0.057 B- 10250.557 6.326 64 956019.750 4.000 - 13 39 26 65 Fe x -51217.895 5.112 8546.346 0.079 B- 7967.303 5.520 64 945015.324 5.487 - 11 38 27 65 Co x -59185.198 2.083 8656.884 0.032 B- 5940.487 2.141 64 936462.073 2.235 - 9 37 28 65 Ni -n -65125.685 0.495 8736.240 0.008 B- 2137.975 0.706 64 930084.697 0.531 - 7 36 29 65 Cu -67263.660 0.650 8757.096 0.010 B- -1351.640 0.360 64 927789.487 0.697 - 5 35 30 65 Zn -65912.019 0.650 8724.265 0.010 B- -3254.513 0.662 64 929240.532 0.697 - 3 34 31 65 Ga -62657.507 0.815 8662.160 0.013 B- -6179.291 2.313 64 932734.395 0.874 - 1 33 32 65 Ge -56478.216 2.165 8555.058 0.033 B- -9541.165 84.794 64 939368.137 2.323 - -1 32 33 65 As x -46937.051 84.766 8396.234 1.304 B- -13917# 312# 64 949611.000 91.000 - -3 31 34 65 Se x -33020# 300# 8170# 5# B- * 64 964552# 322# -0 20 43 23 66 V x -5610# 500# 7884# 8# B- 19110# 640# 65 993977# 537# - 18 42 24 66 Cr x -24720# 400# 8161# 6# B- 12030# 400# 65 973462# 429# - 16 41 25 66 Mn x -36750.387 11.178 8331.798 0.169 B- 13317.452 11.906 65 960546.834 12.000 - 14 40 26 66 Fe x -50067.839 4.099 8521.724 0.062 B- 6340.694 14.561 65 946249.960 4.400 - 12 39 27 66 Co x -56408.533 13.972 8605.941 0.212 B- 9597.752 14.042 65 939442.945 15.000 - 10 38 28 66 Ni x -66006.285 1.397 8739.508 0.021 B- 251.987 1.543 65 929139.334 1.500 - 8 37 29 66 Cu -66258.272 0.655 8731.472 0.010 B- 2640.888 0.931 65 928868.814 0.703 - 6 36 30 66 Zn -68899.160 0.749 8759.632 0.011 B- -5175.500 0.800 65 926033.704 0.804 - 4 35 31 66 Ga - -63723.660 1.096 8669.361 0.017 B- -2116.628 2.639 65 931589.832 1.176 - 2 34 32 66 Ge x -61607.032 2.401 8625.437 0.036 B- -9581.955 6.168 65 933862.126 2.577 - 0 33 33 66 As x -52025.077 5.682 8468.403 0.086 B- -10365# 200# 65 944148.779 6.100 - -2 32 34 66 Se x -41660# 200# 8300# 3# B- * 65 955276# 215# -0 21 44 23 67 V x -650# 600# 7812# 9# B- 18030# 721# 66 999302# 644# - 19 43 24 67 Cr x -18680# 400# 8070# 6# B- 14780# 500# 66 979946# 429# - 17 42 25 67 Mn x -33460# 300# 8279# 4# B- 12150# 404# 66 964079# 322# - 15 41 26 67 Fe x -45610.155 270.285 8448.469 4.034 B- 9711.620 270.362 66 951035.482 290.163 - 13 40 27 67 Co x -55321.775 6.443 8581.741 0.096 B- 8420.905 7.061 66 940609.628 6.917 - 11 39 28 67 Ni x -63742.680 2.888 8695.750 0.043 B- 3576.832 3.023 66 931569.414 3.100 - 9 38 29 67 Cu -67319.513 0.894 8737.458 0.013 B- 560.800 0.830 66 927729.526 0.959 - 7 37 30 67 Zn -67880.313 0.760 8734.152 0.011 B- -1001.265 1.122 66 927127.482 0.815 - 5 36 31 67 Ga -66879.048 1.181 8707.531 0.018 B- -4220.819 4.799 66 928202.384 1.268 - 3 35 32 67 Ge -n2p -62658.230 4.661 8632.857 0.070 B- -6071.005 4.682 66 932733.620 5.003 - 1 34 33 67 As -56587.225 0.443 8530.568 0.007 B- -10006.936 67.069 66 939251.111 0.475 - -1 33 34 67 Se x -46580.289 67.068 8369.534 1.001 B- -13790# 405# 66 949994.000 72.000 - -3 32 35 67 Br x -32790# 400# 8152# 6# B- * 66 964798# 429# -0 20 44 24 68 Cr x -14800# 500# 8013# 7# B- 13580# 640# 67 984112# 537# - 18 43 25 68 Mn x -28380# 400# 8201# 6# B- 15107# 541# 67 969533# 429# - 16 42 26 68 Fe x -43486.914 365.259 8411.698 5.371 B- 8443.751 411.489 67 953314.875 392.121 - 14 41 27 68 Co x -51930.665 189.497 8524.366 2.787 B- 11533.150 189.520 67 944250.135 203.433 - 12 40 28 68 Ni x -63463.814 2.981 8682.466 0.044 B- 2103.220 3.375 67 931868.789 3.200 - 10 39 29 68 Cu x -65567.035 1.584 8701.890 0.023 B- 4440.057 1.767 67 929610.889 1.700 - 8 38 30 68 Zn -70007.092 0.784 8755.680 0.012 B- -2921.100 1.200 67 924844.291 0.841 - 6 37 31 68 Ga - -67085.992 1.433 8701.218 0.021 B- -107.203 2.361 67 927980.221 1.538 - 4 36 32 68 Ge x -66978.789 1.876 8688.136 0.028 B- -8084.270 2.632 67 928095.308 2.014 - 2 35 33 68 As -58894.519 1.846 8557.745 0.027 B- -4705.078 1.911 67 936774.130 1.981 - 0 34 34 68 Se x -54189.441 0.496 8477.047 0.007 B- -15398# 259# 67 941825.239 0.532 - -2 33 35 68 Br -p -38791# 259# 8239# 4# B- * 67 958356# 278# -0 21 45 24 69 Cr x -8580# 500# 7924# 7# B- 16190# 640# 68 990789# 537# - 19 44 25 69 Mn x -24770# 400# 8147# 6# B- 14259# 565# 68 973408# 429# - 17 43 26 69 Fe x -39030# 400# 8342# 6# B- 11250# 424# 68 958100# 429# - 15 42 27 69 Co x -50279.157 140.506 8493.865 2.036 B- 9699.492 140.556 68 946023.102 150.839 - 13 41 28 69 Ni x -59978.648 3.726 8623.099 0.054 B- 5757.564 3.979 68 935610.268 4.000 - 11 40 29 69 Cu x -65736.213 1.397 8695.204 0.020 B- 2681.632 1.610 68 929429.268 1.500 - 9 39 30 69 Zn -n -68417.845 0.800 8722.729 0.012 B- 909.964 1.426 68 926550.418 0.858 - 7 38 31 69 Ga -69327.809 1.197 8724.579 0.017 B- -2227.146 0.550 68 925573.531 1.285 - 5 37 32 69 Ge -67100.663 1.318 8680.963 0.019 B- -3988.492 31.982 68 927964.471 1.414 - 3 36 33 69 As -63112.171 31.999 8611.821 0.464 B- -6677.465 32.021 68 932246.294 34.352 - 1 35 34 69 Se -56434.706 1.490 8503.707 0.022 B- -10175.236 42.029 68 939414.847 1.599 - -1 34 35 69 Br -p -46259.470 42.003 8344.902 0.609 B- -13825# 403# 68 950338.413 45.092 - -3 33 36 69 Kr x -32435# 401# 8133# 6# B- * 68 965180# 430# -0 22 46 24 70 Cr x -4480# 600# 7867# 9# B- 15020# 781# 69 995191# 644# - 20 45 25 70 Mn x -19500# 500# 8070# 7# B- 17010# 640# 69 979066# 537# - 18 44 26 70 Fe x -36510# 400# 8302# 6# B- 10120# 500# 69 960805# 429# - 16 43 27 70 Co x -46630# 300# 8436# 4# B- 12584# 300# 69 949941# 322# - 14 42 28 70 Ni x -59213.860 2.144 8604.291 0.031 B- 3762.513 2.401 69 936431.303 2.301 - 12 41 29 70 Cu x -62976.373 1.082 8646.865 0.015 B- 6588.362 2.202 69 932392.079 1.161 - 10 40 30 70 Zn -69564.735 1.918 8729.808 0.027 B- -654.595 1.574 69 925319.181 2.058 - 8 39 31 70 Ga -68910.140 1.201 8709.280 0.017 B- 1651.736 1.462 69 926021.917 1.289 - 6 38 32 70 Ge -70561.876 0.838 8721.700 0.012 B- -6220.000 50.000 69 924248.706 0.900 - 4 37 33 70 As - -64341.876 50.007 8621.666 0.714 B- -2411.985 50.032 69 930926.151 53.684 - 2 36 34 70 Se x -61929.891 1.584 8576.033 0.023 B- -10504.272 14.988 69 933515.523 1.700 - 0 35 35 70 Br x -51425.619 14.904 8414.796 0.213 B- -10325# 201# 69 944792.323 16.000 - -2 34 36 70 Kr x -41100# 200# 8256# 3# B- * 69 955877# 215# -0 21 46 25 71 Mn x -15570# 500# 8015# 7# B- 15860# 640# 70 983285# 537# - 19 45 26 71 Fe x -31430# 400# 8227# 6# B- 12940# 613# 70 966259# 429# - 17 44 27 71 Co x -44369.926 465.030 8398.734 6.550 B- 11036.302 465.035 70 952366.923 499.230 - 15 43 28 71 Ni x -55406.228 2.237 8543.156 0.032 B- 7304.899 2.688 70 940518.964 2.401 - 13 42 29 71 Cu x -62711.127 1.490 8635.022 0.021 B- 4617.651 3.044 70 932676.832 1.600 - 11 41 30 71 Zn -67328.777 2.654 8689.041 0.037 B- 2810.358 2.775 70 927719.580 2.849 - 9 40 31 71 Ga -70139.135 0.812 8717.604 0.011 B- -232.638 0.223 70 924702.536 0.871 - 7 39 32 71 Ge -69906.497 0.834 8703.309 0.012 B- -2013.400 4.082 70 924952.284 0.894 - 5 38 33 71 As - -67893.097 4.167 8663.932 0.059 B- -4746.590 5.017 70 927113.758 4.473 - 3 37 34 71 Se x -63146.507 2.794 8586.060 0.039 B- -6644.089 6.082 70 932209.432 3.000 - 1 36 35 71 Br -56502.418 5.402 8481.462 0.076 B- -10175.212 128.845 70 939342.156 5.799 - -1 35 36 71 Kr -46327.205 128.769 8327.130 1.814 B- -14267# 420# 70 950265.696 138.238 - -3 34 37 71 Rb x -32060# 400# 8115# 6# B- * 70 965582# 429# -0 22 47 25 72 Mn x -9900# 600# 7937# 8# B- 18530# 781# 71 989372# 644# - 20 46 26 72 Fe x -28430# 500# 8184# 7# B- 11769# 640# 71 969479# 537# - 18 45 27 72 Co x -40200# 400# 8336# 6# B- 14027# 400# 71 956844# 429# - 16 44 28 72 Ni x -54226.060 2.237 8520.211 0.031 B- 5556.938 2.637 71 941785.926 2.401 - 14 43 29 72 Cu x -59782.999 1.397 8586.525 0.019 B- 8362.487 2.558 71 935820.307 1.500 - 12 42 30 72 Zn x -68145.486 2.142 8691.805 0.030 B- 442.807 2.294 71 926842.807 2.300 - 10 41 31 72 Ga -68588.293 0.819 8687.089 0.011 B- 3997.607 0.822 71 926367.434 0.878 - 8 40 32 72 Ge -72585.900 0.076 8731.745 0.001 B- -4356.102 4.082 71 922075.826 0.081 - 6 39 33 72 As - -68229.798 4.083 8660.378 0.057 B- -361.618 4.528 71 926752.295 4.383 - 4 38 34 72 Se x -67868.180 1.956 8644.489 0.027 B- -8806.437 2.208 71 927140.507 2.100 - 2 37 35 72 Br x -59061.743 1.025 8511.312 0.014 B- -5121.168 8.076 71 936594.607 1.100 - 0 36 36 72 Kr x -53940.575 8.011 8429.319 0.111 B- -15611# 500# 71 942092.407 8.600 - -2 35 37 72 Rb x -38330# 500# 8202# 7# B- * 71 958851# 537# -0 21 47 26 73 Fe x -22900# 500# 8106# 7# B- 14518# 640# 72 975416# 537# - 19 46 27 73 Co x -37418# 400# 8295# 5# B- 12690# 400# 72 959830# 429# - 17 45 28 73 Ni x -50108.152 2.423 8457.652 0.033 B- 8879.285 3.104 72 946206.683 2.601 - 15 44 29 73 Cu -58987.437 1.942 8568.569 0.027 B- 6605.966 2.691 72 936674.378 2.084 - 13 43 30 73 Zn x -65593.402 1.863 8648.345 0.026 B- 4105.932 2.506 72 929582.582 2.000 - 11 42 31 73 Ga x -69699.335 1.677 8693.873 0.023 B- 1598.188 1.678 72 925174.682 1.800 - 9 41 32 73 Ge -71297.523 0.057 8705.049 0.001 B- -344.776 3.853 72 923458.956 0.061 - 7 40 33 73 As -70952.747 3.853 8689.609 0.053 B- -2725.360 7.399 72 923829.089 4.136 - 5 39 34 73 Se -68227.387 7.424 8641.558 0.102 B- -4579.912 10.388 72 926754.883 7.969 - 3 38 35 73 Br x -63647.475 7.266 8568.103 0.100 B- -7095.725 9.801 72 931671.621 7.800 - 1 37 36 73 Kr x -56551.751 6.578 8460.184 0.090 B- -10470# 200# 72 939289.195 7.061 - -1 36 37 73 Rb -p -46082# 200# 8306# 3# B- -14131# 448# 72 950529# 215# - -3 35 38 73 Sr x -31950# 401# 8102# 5# B- * 72 965700# 430# -0 22 48 26 74 Fe x -19590# 600# 8061# 8# B- 13230# 781# 73 978969# 644# - 20 47 27 74 Co x -32820# 500# 8229# 7# B- 15636# 537# 73 964766# 537# - 18 46 28 74 Ni x -48456# 196# 8430# 3# B- 7550# 196# 73 947980# 210# - 16 45 29 74 Cu x -56006.205 6.148 8521.562 0.083 B- 9750.507 6.642 73 939874.862 6.600 - 14 44 30 74 Zn x -65756.712 2.515 8642.754 0.034 B- 2292.905 3.910 73 929407.262 2.700 - 12 43 31 74 Ga x -68049.617 2.994 8663.167 0.040 B- 5372.824 2.994 73 926945.726 3.214 - 10 42 32 74 Ge -73422.442 0.013 8725.200 0.000 B- -2562.387 1.693 73 921177.762 0.013 - 8 41 33 74 As -70860.054 1.693 8680.001 0.023 B- 1353.147 1.693 73 923928.598 1.817 - 6 40 34 74 Se -72213.201 0.015 8687.715 0.000 B- -6925.049 5.835 73 922475.935 0.015 - 4 39 35 74 Br -65288.153 5.835 8583.561 0.079 B- -2956.317 6.173 73 929910.281 6.264 - 2 38 36 74 Kr -62331.836 2.013 8533.038 0.027 B- -10415.827 3.424 73 933084.017 2.161 - 0 37 37 74 Rb -51916.009 3.027 8381.712 0.041 B- -11089# 100# 73 944265.868 3.249 - -2 36 38 74 Sr x -40827# 100# 8221# 1# B- * 73 956170# 107# -0 23 49 26 75 Fe x -13640# 600# 7982# 8# B- 16010# 781# 74 985357# 644# - 21 48 27 75 Co x -29649# 500# 8185# 7# B- 14380# 583# 74 968170# 537# - 19 47 28 75 Ni x -44030# 300# 8366# 4# B- 10441# 300# 74 952732# 322# - 17 46 29 75 Cu x -54471.341 2.330 8495.094 0.031 B- 8087.567 3.042 74 941522.606 2.501 - 15 45 30 75 Zn x -62558.908 1.956 8592.497 0.026 B- 5905.672 3.113 74 932840.246 2.100 - 13 44 31 75 Ga x -68464.580 2.422 8660.808 0.032 B- 3392.384 2.422 74 926500.246 2.600 - 11 43 32 75 Ge -n -71856.965 0.052 8695.609 0.001 B- 1177.231 0.885 74 922858.371 0.055 - 9 42 33 75 As -73034.195 0.884 8700.874 0.012 B- -864.714 0.882 74 921594.562 0.948 - 7 41 34 75 Se -72169.481 0.073 8678.913 0.001 B- -3062.472 4.285 74 922522.871 0.078 - 5 40 35 75 Br x -69107.009 4.285 8627.649 0.057 B- -4783.385 9.167 74 925810.570 4.600 - 3 39 36 75 Kr x -64323.624 8.104 8553.439 0.108 B- -7104.929 8.189 74 930945.746 8.700 - 1 38 37 75 Rb x -57218.694 1.180 8448.275 0.016 B- -10600.000 220.000 74 938573.201 1.266 - -1 37 38 75 Sr - -46618.694 220.003 8296.511 2.933 B- -14799# 372# 74 949952.770 236.183 - -3 36 39 75 Y x -31820# 300# 8089# 4# B- * 74 965840# 322# -0 22 49 27 76 Co x -24510# 600# 8116# 8# B- 17120# 721# 75 973687# 644# - 20 48 28 76 Ni x -41630# 400# 8331# 5# B- 9346# 400# 75 955308# 429# - 18 47 29 76 Cu x -50975.985 6.707 8443.527 0.088 B- 11327.031 6.863 75 945275.025 7.200 - 16 46 30 76 Zn -62303.016 1.456 8582.273 0.019 B- 3993.624 2.438 75 933114.957 1.562 - 14 45 31 76 Ga x -66296.640 1.956 8624.526 0.026 B- 6916.249 1.956 75 928827.625 2.100 - 12 44 32 76 Ge -73212.889 0.018 8705.236 0.000 B- -921.512 0.886 75 921402.726 0.019 - 10 43 33 76 As -n -72291.377 0.886 8682.816 0.012 B- 2960.573 0.886 75 922392.010 0.951 - 8 42 34 76 Se -75251.950 0.016 8711.477 0.000 B- -4962.881 9.322 75 919213.704 0.017 - 6 41 35 76 Br - -70289.068 9.322 8635.882 0.123 B- -1275.355 10.149 75 924541.577 10.007 - 4 40 36 76 Kr -69013.714 4.013 8608.807 0.053 B- -8534.633 4.121 75 925910.726 4.308 - 2 39 37 76 Rb x -60479.081 0.938 8486.215 0.012 B- -6231.442 34.478 75 935073.032 1.006 - 0 38 38 76 Sr x -54247.639 34.465 8393.929 0.453 B- -15768# 302# 75 941762.761 37.000 - -2 37 39 76 Y x -38480# 300# 8176# 4# B- * 75 958690# 322# -0 23 50 27 77 Co x -21015# 600# 8070# 8# B- 15785# 781# 76 977440# 644# - 21 49 28 77 Ni x -36800# 500# 8265# 6# B- 11824# 522# 76 960494# 537# - 19 48 29 77 Cu x -48624# 149# 8408# 2# B- 10165# 149# 76 947800# 160# - 17 47 30 77 Zn -58789.195 1.973 8530.003 0.026 B- 7203.149 3.124 76 936887.199 2.117 - 15 46 31 77 Ga x -65992.344 2.422 8613.390 0.031 B- 5220.518 2.422 76 929154.300 2.600 - 13 45 32 77 Ge -n -71212.862 0.053 8671.028 0.001 B- 2703.456 1.694 76 923549.844 0.056 - 11 44 33 77 As -73916.318 1.693 8695.978 0.022 B- 683.170 1.693 76 920647.564 1.817 - 9 43 34 77 Se -74599.488 0.062 8694.690 0.001 B- -1364.680 2.810 76 919914.150 0.067 - 7 42 35 77 Br - -73234.809 2.811 8666.806 0.037 B- -3065.366 3.424 76 921379.194 3.017 - 5 41 36 77 Kr x -70169.443 1.956 8616.836 0.025 B- -5338.951 2.351 76 924670.000 2.100 - 3 40 37 77 Rb x -64830.492 1.304 8537.339 0.017 B- -7027.055 8.024 76 930401.600 1.400 - 1 39 38 77 Sr x -57803.436 7.918 8435.918 0.103 B- -11365# 203# 76 937945.455 8.500 - -1 38 39 77 Y -p -46439# 203# 8278# 3# B- -14399# 448# 76 950146# 218# - -3 37 40 77 Zr x -32040# 400# 8081# 5# B- * 76 965604# 429# -0 22 50 28 78 Ni x -33890# 600# 8225# 8# B- 10608# 783# 77 963618# 644# - 20 49 29 78 Cu x -44497.469 503.007 8350.925 6.449 B- 12985.766 503.011 77 952230.000 540.000 - 18 48 30 78 Zn -57483.235 1.944 8507.379 0.025 B- 6222.716 2.719 77 938289.205 2.086 - 16 47 31 78 Ga -63705.950 1.903 8577.127 0.024 B- 8156.099 4.015 77 931608.845 2.043 - 14 46 32 78 Ge -nn -71862.050 3.536 8671.663 0.045 B- 954.890 10.400 77 922852.912 3.795 - 12 45 33 78 As +pn -72816.940 9.781 8673.875 0.125 B- 4209.004 9.782 77 921827.795 10.500 - 10 44 34 78 Se -77025.944 0.179 8717.806 0.002 B- -3573.784 3.575 77 917309.243 0.191 - 8 43 35 78 Br - -73452.160 3.580 8661.959 0.046 B- 726.116 3.584 77 921145.859 3.842 - 6 42 36 78 Kr -74178.275 0.307 8661.238 0.004 B- -7242.857 3.252 77 920366.341 0.329 - 4 41 37 78 Rb x -66935.419 3.237 8558.350 0.042 B- -3761.477 8.125 77 928141.868 3.475 - 2 40 38 78 Sr x -63173.941 7.452 8500.096 0.096 B- -11001# 298# 77 932179.980 8.000 - 0 39 39 78 Y x -52173# 298# 8349# 4# B- -11323# 499# 77 943990# 320# - -2 38 40 78 Zr x -40850# 400# 8194# 5# B- * 77 956146# 429# -0 23 51 28 79 Ni x -27570# 600# 8143# 8# B- 14170# 671# 78 970402# 644# - 21 50 29 79 Cu x -41740# 300# 8312# 4# B- 11692# 300# 78 955190# 322# - 19 49 30 79 Zn -53432.295 2.225 8450.582 0.028 B- 9115.384 2.901 78 942638.068 2.388 - 17 48 31 79 Ga -62547.679 1.868 8556.063 0.024 B- 6978.913 37.147 78 932852.301 2.005 - 15 47 32 79 Ge -69526.592 37.181 8634.501 0.471 B- 4109.457 37.456 78 925360.129 39.915 - 13 46 33 79 As -73636.049 5.328 8676.616 0.067 B- 2281.410 5.331 78 920948.445 5.719 - 11 45 34 79 Se -n -75917.459 0.223 8695.592 0.003 B- 150.576 1.038 78 918499.251 0.238 - 9 44 35 79 Br +n -76068.035 1.021 8687.594 0.013 B- -1625.778 3.333 78 918337.601 1.095 - 7 43 36 79 Kr - -74442.257 3.486 8657.112 0.044 B- -3639.271 4.092 78 920082.945 3.742 - 5 42 37 79 Rb x -70802.985 2.142 8601.142 0.027 B- -5326.096 8.653 78 923989.864 2.300 - 3 41 38 79 Sr x -65476.889 8.383 8523.820 0.106 B- -7659.056 79.620 78 929707.664 9.000 - 1 40 39 79 Y x -57817.833 79.177 8416.967 1.002 B- -11048# 310# 78 937930.000 85.000 - -1 39 40 79 Zr x -46770# 300# 8267# 4# B- -15120# 583# 78 949790# 322# - -3 38 41 79 Nb x -31650# 500# 8066# 6# B- * 78 966022# 537# -0 24 52 28 80 Ni x -22630# 700# 8080# 9# B- 13570# 806# 79 975706# 751# - 22 51 29 80 Cu x -36200# 400# 8240# 5# B- 15449# 400# 79 961138# 429# - 20 50 30 80 Zn -51648.612 2.585 8423.545 0.032 B- 7575.055 3.877 79 944552.930 2.774 - 18 49 31 80 Ga x -59223.667 2.891 8508.454 0.036 B- 10311.639 3.541 79 936420.774 3.103 - 16 48 32 80 Ge x -69535.306 2.054 8627.570 0.026 B- 2679.187 3.915 79 925350.774 2.205 - 14 47 33 80 As x -72214.493 3.333 8651.280 0.042 B- 5544.964 3.445 79 922474.548 3.577 - 12 46 34 80 Se -77759.457 0.963 8710.813 0.012 B- -1870.464 0.310 79 916521.785 1.034 - 10 45 35 80 Br - -75888.993 1.012 8677.653 0.013 B- 2004.353 1.154 79 918529.810 1.086 - 8 44 36 80 Kr -77893.346 0.691 8692.928 0.009 B- -5717.879 1.987 79 916378.048 0.742 - 6 43 37 80 Rb x -72175.467 1.863 8611.675 0.023 B- -1864.009 3.933 79 922516.444 2.000 - 4 42 38 80 Sr x -70311.459 3.464 8578.596 0.043 B- -9163.307 7.139 79 924517.540 3.718 - 2 41 39 80 Y x -61148.152 6.242 8454.275 0.078 B- -6788# 300# 79 934354.755 6.701 - 0 40 40 80 Zr x -54360# 300# 8360# 4# B- -15940# 500# 79 941642# 322# - -2 39 41 80 Nb x -38420# 400# 8151# 5# B- * 79 958754# 429# -0 23 52 29 81 Cu x -31420# 500# 8179# 6# B- 14779# 500# 80 966269# 537# - 21 51 30 81 Zn x -46199.663 5.030 8351.925 0.062 B- 11428.292 5.996 80 950402.619 5.400 - 19 50 31 81 Ga x -57627.954 3.264 8483.357 0.040 B- 8663.733 3.851 80 938133.842 3.503 - 17 49 32 81 Ge x -66291.687 2.055 8580.658 0.025 B- 6241.617 3.344 80 928832.942 2.205 - 15 48 33 81 As -72533.304 2.644 8648.056 0.033 B- 3855.684 2.812 80 922132.290 2.838 - 13 47 34 81 Se -76388.988 0.992 8685.999 0.012 B- 1588.046 1.389 80 917993.044 1.065 - 11 46 35 81 Br -77977.034 0.978 8695.946 0.012 B- -280.853 0.471 80 916288.206 1.049 - 9 45 36 81 Kr -77696.181 1.074 8682.820 0.013 B- -2239.511 5.019 80 916589.714 1.152 - 7 44 37 81 Rb -75456.670 4.904 8645.513 0.061 B- -3928.545 5.817 80 918993.927 5.264 - 5 43 38 81 Sr x -71528.125 3.128 8587.354 0.039 B- -5815.214 6.245 80 923211.394 3.358 - 3 42 39 81 Y x -65712.912 5.405 8505.902 0.067 B- -8252.773 94.236 80 929454.283 5.802 - 1 41 40 81 Zr x -57460.139 94.081 8394.358 1.161 B- -11100# 411# 80 938314.000 101.000 - -1 40 41 81 Nb x -46360# 400# 8248# 5# B- -14610# 640# 80 950230# 429# - -3 39 42 81 Mo x -31750# 500# 8058# 6# B- * 80 965915# 537# -0 24 53 29 82 Cu x -25320# 600# 8103# 7# B- 16994# 600# 81 972818# 644# - 22 52 30 82 Zn x -42313.954 3.074 8301.117 0.037 B- 10616.764 3.916 81 954574.099 3.300 - 20 51 31 82 Ga x -52930.719 2.426 8421.049 0.030 B- 12484.348 3.296 81 943176.533 2.604 - 18 50 32 82 Ge x -65415.067 2.241 8563.756 0.027 B- 4690.352 4.345 81 929774.033 2.405 - 16 49 33 82 As x -70105.419 3.729 8611.414 0.045 B- 7488.463 3.758 81 924738.733 4.003 - 14 48 34 82 Se -77593.882 0.467 8693.196 0.006 B- -95.221 1.077 81 916699.537 0.500 - 12 47 35 82 Br -77498.661 0.971 8682.494 0.012 B- 3093.124 0.971 81 916801.760 1.042 - 10 46 36 82 Kr -80591.78515 0.00549 8710.675 0.000 B- -4403.982 3.009 81 913481.15520 0.00589 - 8 45 37 82 Rb IT -76187.803 3.009 8647.427 0.037 B- -177.751 6.705 81 918209.024 3.230 - 6 44 38 82 Sr -76010.053 5.992 8635.718 0.073 B- -7945.961 8.132 81 918399.847 6.432 - 4 43 39 82 Y x -68064.091 5.499 8529.275 0.067 B- -4432.804 12.457 81 926930.188 5.902 - 2 42 40 82 Zr x -63631.287 11.178 8465.676 0.136 B- -11541# 300# 81 931689.000 12.000 - 0 41 41 82 Nb x -52090# 300# 8315# 4# B- -11720# 500# 81 944079# 322# - -2 40 42 82 Mo x -40370# 400# 8163# 5# B- * 81 956661# 429# -0 23 53 30 83 Zn x -36290# 300# 8226# 4# B- 12967# 300# 82 961041# 322# - 21 52 31 83 Ga x -49257.122 2.613 8372.575 0.031 B- 11719.312 3.559 82 947120.301 2.804 - 19 51 32 83 Ge x -60976.435 2.427 8504.345 0.029 B- 8692.888 3.698 82 934539.101 2.605 - 17 50 33 83 As x -69669.323 2.799 8599.653 0.034 B- 5671.207 4.129 82 925206.901 3.004 - 15 49 34 83 Se -n -75340.530 3.036 8658.555 0.037 B- 3673.179 4.839 82 919118.609 3.259 - 13 48 35 83 Br -79013.709 3.795 8693.384 0.046 B- 976.924 3.795 82 915175.289 4.073 - 11 47 36 83 Kr -79990.633 0.009 8695.729 0.000 B- -920.004 2.329 82 914126.518 0.009 - 9 46 37 83 Rb -79070.630 2.329 8675.218 0.028 B- -2273.024 6.424 82 915114.182 2.500 - 7 45 38 83 Sr -76797.606 6.834 8638.407 0.082 B- -4591.941 19.844 82 917554.374 7.336 - 5 44 39 83 Y x -72205.665 18.631 8573.656 0.224 B- -6294.012 19.707 82 922484.025 20.000 - 3 43 40 83 Zr x -65911.654 6.430 8488.399 0.077 B- -8355.571 151.039 82 929240.925 6.902 - 1 42 41 83 Nb x -57556.083 150.902 8378.304 1.818 B- -11216# 428# 82 938211.000 162.000 - -1 41 42 83 Mo x -46340# 401# 8234# 5# B- -15020# 641# 82 950252# 430# - -3 40 43 83 Tc x -31320# 500# 8043# 6# B- * 82 966377# 537# -0 24 54 30 84 Zn x -31930# 400# 8172# 5# B- 12158# 447# 83 965722# 429# - 22 53 31 84 Ga x -44088# 200# 8307# 2# B- 14061# 200# 83 952670# 215# - 20 52 32 84 Ge x -58148.428 3.171 8465.524 0.038 B- 7705.132 4.479 83 937575.091 3.403 - 18 51 33 84 As x -65853.560 3.171 8547.938 0.038 B- 10094.161 3.722 83 929303.291 3.403 - 16 50 34 84 Se -75947.721 1.961 8658.793 0.023 B- 1835.363 25.765 83 918466.762 2.105 - 14 49 35 84 Br -77783.084 25.730 8671.329 0.306 B- 4656.251 25.730 83 916496.419 27.622 - 12 48 36 84 Kr -82439.33510 0.00379 8717.446 0.000 B- -2680.371 2.194 83 911497.72863 0.00407 - 10 47 37 84 Rb -79758.964 2.194 8676.224 0.026 B- 890.606 2.336 83 914375.225 2.355 - 8 46 38 84 Sr -80649.570 1.243 8677.512 0.015 B- -6755.139 4.411 83 913419.120 1.334 - 6 45 39 84 Y -73894.431 4.299 8587.780 0.051 B- -2472.745 6.977 83 920671.061 4.615 - 4 44 40 84 Zr x -71421.686 5.499 8549.029 0.065 B- -10202.968 14.153 83 923325.662 5.903 - 2 43 41 84 Nb x -61218.717 13.041 8418.252 0.155 B- -7049# 298# 83 934279.000 14.000 - 0 42 42 84 Mo x -54170# 298# 8325# 4# B- -16470# 499# 83 941846# 320# - -2 41 43 84 Tc x -37700# 400# 8120# 5# B- * 83 959527# 429# -0 25 55 30 85 Zn x -25230# 500# 8092# 6# B- 14619# 582# 84 972914# 537# - 23 54 31 85 Ga x -39849# 298# 8255# 4# B- 13274# 298# 84 957220# 320# - 21 53 32 85 Ge x -53123.420 3.729 8401.768 0.044 B- 10065.724 4.830 84 942969.659 4.003 - 19 52 33 85 As x -63189.144 3.078 8510.984 0.036 B- 9224.492 4.031 84 932163.659 3.304 - 17 51 34 85 Se +3p -72413.636 2.613 8610.304 0.031 B- 6161.833 4.031 84 922260.759 2.804 - 15 50 35 85 Br +n2p -78575.469 3.078 8673.592 0.036 B- 2904.861 3.671 84 915645.759 3.304 - 13 49 36 85 Kr + -81480.331 2.000 8698.562 0.024 B- 687.000 2.000 84 912527.262 2.147 - 11 48 37 85 Rb -82167.33050 0.00498 8697.441 0.000 B- -1064.051 2.813 84 911789.73760 0.00534 - 9 47 38 85 Sr -81103.280 2.813 8675.718 0.033 B- -3261.157 19.173 84 912932.043 3.020 - 7 46 39 85 Y x -77842.123 18.965 8628.148 0.223 B- -4666.934 20.026 84 916433.039 20.360 - 5 45 40 85 Zr x -73175.189 6.430 8564.039 0.076 B- -6895.514 7.625 84 921443.198 6.902 - 3 44 41 85 Nb x -66279.676 4.099 8473.711 0.048 B- -8769.923 16.357 84 928845.837 4.400 - 1 43 42 85 Mo x -57509.753 15.835 8361.331 0.186 B- -11660# 400# 84 938260.737 17.000 - -1 42 43 85 Tc x -45850# 400# 8215# 5# B- -14900# 640# 84 950778# 429# - -3 41 44 85 Ru x -30950# 500# 8030# 6# B- * 84 966774# 537# -0 24 55 31 86 Ga x -34080# 400# 8186# 5# B- 15320# 593# 85 963414# 429# - 22 54 32 86 Ge x -49399.922 437.802 8354.629 5.091 B- 9562.221 437.816 85 946967.000 470.000 - 20 53 33 86 As x -58962.142 3.450 8456.721 0.040 B- 11541.024 4.267 85 936701.533 3.703 - 18 52 34 86 Se x -70503.167 2.520 8581.822 0.029 B- 5129.085 3.972 85 924311.733 2.705 - 16 51 35 86 Br +pp -75632.252 3.078 8632.365 0.036 B- 7633.414 3.078 85 918805.433 3.304 - 14 50 36 86 Kr -83265.66564 0.00369 8712.029 0.000 B- -518.672 0.200 85 910610.62627 0.00396 - 12 49 37 86 Rb -n -82746.993 0.200 8696.901 0.002 B- 1776.096 0.200 85 911167.443 0.214 - 10 48 38 86 Sr -84523.08935 0.00522 8708.456 0.000 B- -5240.000 14.142 85 909260.72631 0.00561 - 8 47 39 86 Y - -79283.089 14.142 8638.428 0.164 B- -1314.075 14.585 85 914886.098 15.182 - 6 46 40 86 Zr -77969.014 3.566 8614.051 0.041 B- -8834.960 6.552 85 916296.815 3.827 - 4 45 41 86 Nb x -69134.054 5.499 8502.222 0.064 B- -5023.810 6.642 85 925781.535 5.903 - 2 44 42 86 Mo x -64110.245 3.726 8434.709 0.043 B- -12540# 300# 85 931174.817 4.000 - 0 43 43 86 Tc x -51570# 300# 8280# 3# B- -11800# 500# 85 944637# 322# - -2 42 44 86 Ru x -39770# 400# 8133# 5# B- * 85 957305# 429# -0 25 56 31 87 Ga x -29250# 500# 8129# 6# B- 14828# 583# 86 968599# 537# - 23 55 32 87 Ge x -44078# 300# 8290# 3# B- 11540# 300# 86 952680# 322# - 21 54 33 87 As x -55617.907 2.985 8413.851 0.034 B- 10808.218 3.726 86 940291.718 3.204 - 19 53 34 87 Se x -66426.125 2.241 8529.091 0.026 B- 7465.552 3.877 86 928688.618 2.405 - 17 52 35 87 Br 2p-n -73891.676 3.171 8605.910 0.036 B- 6817.845 3.181 86 920674.018 3.404 - 15 51 36 87 Kr -n -80709.522 0.246 8675.283 0.003 B- 3888.269 0.246 86 913354.759 0.264 - 13 50 37 87 Rb -84597.791 0.006 8710.983 0.000 B- 282.275 0.006 86 909180.531 0.006 - 11 49 38 87 Sr -84880.06595 0.00510 8705.236 0.000 B- -1861.690 1.128 86 908877.49615 0.00548 - 9 48 39 87 Y - -83018.376 1.128 8674.844 0.013 B- -3671.239 4.296 86 910876.102 1.210 - 7 47 40 87 Zr -79347.137 4.146 8623.654 0.048 B- -5472.651 7.963 86 914817.339 4.450 - 5 46 41 87 Nb x -73874.486 6.802 8551.757 0.078 B- -6989.678 7.378 86 920692.472 7.302 - 3 45 42 87 Mo -66884.808 2.857 8462.424 0.033 B- -9194.764 5.073 86 928196.201 3.067 - 1 44 43 87 Tc x -57690.044 4.192 8347.744 0.048 B- -12170# 400# 86 938067.187 4.500 - -1 43 44 87 Ru x -45520# 400# 8199# 5# B- * 86 951132# 429# -0 24 56 32 88 Ge x -40138# 400# 8243# 5# B- 10582# 445# 87 956910# 429# - 22 55 33 88 As x -50720# 196# 8354# 2# B- 13164# 196# 87 945550# 210# - 20 54 34 88 Se x -63884.195 3.357 8495.004 0.038 B- 6831.763 4.613 87 931417.491 3.604 - 18 53 35 88 Br ++ -70715.959 3.171 8563.747 0.036 B- 8975.327 4.106 87 924083.291 3.404 - 16 52 36 88 Kr x -79691.286 2.608 8656.849 0.030 B- 2917.709 2.613 87 914447.881 2.800 - 14 51 37 88 Rb -82608.995 0.159 8681.115 0.002 B- 5312.623 0.159 87 911315.591 0.171 - 12 50 38 88 Sr -87921.61793 0.00558 8732.595 0.000 B- -3622.600 1.500 87 905612.25561 0.00599 - 10 49 39 88 Y - -84299.018 1.500 8682.539 0.017 B- -670.147 5.608 87 909501.276 1.610 - 8 48 40 88 Zr -83628.871 5.403 8666.033 0.061 B- -7455.284 58.886 87 910220.709 5.800 - 6 47 41 88 Nb -76173.586 58.810 8572.424 0.668 B- -3487.042 58.933 87 918224.287 63.134 - 4 46 42 88 Mo x -72686.544 3.819 8523.908 0.043 B- -11005.229 149.088 87 921967.781 4.100 - 2 45 43 88 Tc x -61681.315 149.039 8389.958 1.694 B- -7342# 335# 87 933782.381 160.000 - 0 44 44 88 Ru x -54340# 300# 8298# 3# B- -17479# 500# 87 941664# 322# - -2 43 45 88 Rh x -36860# 400# 8090# 5# B- * 87 960429# 429# -0 25 57 32 89 Ge x -33729# 400# 8169# 4# B- 13069# 499# 88 963790# 429# - 23 56 33 89 As x -46798# 298# 8307# 3# B- 12194# 298# 88 949760# 320# - 21 55 34 89 Se x -58992.391 3.729 8435.279 0.042 B- 9281.872 4.951 88 936669.059 4.003 - 19 54 35 89 Br x -68274.263 3.264 8530.779 0.037 B- 8261.522 3.904 88 926704.559 3.504 - 17 53 36 89 Kr x -76535.785 2.142 8614.815 0.024 B- 5176.604 5.834 88 917835.450 2.300 - 15 52 37 89 Rb -81712.388 5.427 8664.189 0.061 B- 4496.628 5.427 88 912278.137 5.825 - 13 51 38 89 Sr -86209.017 0.092 8705.922 0.001 B- 1499.336 1.615 88 907450.808 0.098 - 11 50 39 89 Y -87708.352 1.612 8713.978 0.018 B- -2832.792 2.776 88 905841.205 1.730 - 9 49 40 89 Zr -84875.561 3.083 8673.359 0.035 B- -4250.351 23.743 88 908882.332 3.310 - 7 48 41 89 Nb -80625.209 23.631 8616.812 0.266 B- -5610.275 23.953 88 913445.272 25.369 - 5 47 42 89 Mo x -75014.935 3.912 8544.984 0.044 B- -7620.087 5.467 88 919468.150 4.200 - 3 46 43 89 Tc x -67394.848 3.819 8450.575 0.043 B- -9135# 298# 88 927648.650 4.100 - 1 45 44 89 Ru x -58260# 298# 8339# 3# B- -12400# 468# 88 937455# 320# - -1 44 45 89 Rh -p -45861# 361# 8191# 4# B- * 88 950767# 387# -0 26 58 32 90 Ge x -29221# 500# 8118# 6# B- 12109# 640# 89 968630# 537# - 24 57 33 90 As x -41330# 400# 8244# 4# B- 14470# 518# 89 955630# 429# - 22 56 34 90 Se x -55800.217 329.749 8395.766 3.664 B- 8200.081 329.766 89 940096.000 354.000 - 20 55 35 90 Br x -64000.298 3.357 8478.186 0.037 B- 10958.952 3.840 89 931292.850 3.604 - 18 54 36 90 Kr x -74959.250 1.863 8591.259 0.021 B- 4405.154 6.746 89 919527.930 2.000 - 16 53 37 90 Rb -79364.404 6.484 8631.512 0.072 B- 6583.723 6.544 89 914798.803 6.960 - 14 52 38 90 Sr -85948.127 2.124 8695.972 0.024 B- 545.934 1.406 89 907730.885 2.280 - 12 51 39 90 Y -86494.062 1.611 8693.345 0.018 B- 2278.474 1.609 89 907144.800 1.729 - 10 50 40 90 Zr -88772.535 0.118 8709.969 0.001 B- -6111.016 3.316 89 904698.758 0.126 - 8 49 41 90 Nb -82661.519 3.317 8633.376 0.037 B- -2489.016 3.316 89 911259.204 3.561 - 6 48 42 90 Mo -80172.503 3.463 8597.028 0.038 B- -9447.816 3.611 89 913931.272 3.717 - 4 47 43 90 Tc x -70724.687 1.025 8483.359 0.011 B- -5840.895 3.869 89 924073.921 1.100 - 2 46 44 90 Ru -64883.792 3.730 8409.768 0.041 B- -13184# 300# 89 930344.379 4.004 - 0 45 45 90 Rh x -51700# 300# 8255# 3# B- -11990# 500# 89 944498# 322# - -2 44 46 90 Pd x -39710# 400# 8113# 4# B- * 89 957370# 429# -0 25 58 33 91 As x -36896# 400# 8193# 4# B- 13684# 589# 90 960390# 429# - 23 57 34 91 Se x -50580.124 433.145 8334.837 4.760 B- 10527.169 433.159 90 945700.000 465.000 - 21 56 35 91 Br -n2p -61107.294 3.544 8441.923 0.039 B- 9866.671 4.190 90 934398.618 3.804 - 19 55 36 91 Kr x -70973.965 2.236 8541.751 0.025 B- 6771.072 8.115 90 923806.310 2.400 - 17 54 37 91 Rb -77745.037 7.801 8607.561 0.086 B- 5906.890 8.873 90 916537.265 8.375 - 15 53 38 91 Sr -83651.927 5.453 8663.875 0.060 B- 2699.369 5.247 90 910195.958 5.853 - 13 52 39 91 Y -86351.295 1.843 8684.941 0.020 B- 1544.271 1.840 90 907298.066 1.978 - 11 51 40 91 Zr -87895.566 0.105 8693.314 0.001 B- -1257.565 2.924 90 905640.223 0.112 - 9 50 41 91 Nb -86638.001 2.926 8670.897 0.032 B- -4429.180 6.744 90 906990.274 3.141 - 7 49 42 91 Mo -82208.821 6.238 8613.628 0.069 B- -6222.175 6.671 90 911745.195 6.696 - 5 48 43 91 Tc -75986.646 2.363 8536.655 0.026 B- -7746.824 3.242 90 918424.975 2.536 - 3 47 44 91 Ru -68239.823 2.221 8442.928 0.024 B- -9670# 298# 90 926741.532 2.384 - 1 46 45 91 Rh x -58570# 298# 8328# 3# B- -12639# 499# 90 937123# 320# - -1 45 46 91 Pd x -45930# 401# 8181# 4# B- * 90 950692# 430# -0 26 59 33 92 As x -30981# 500# 8127# 5# B- 15742# 640# 91 966740# 537# - 24 58 34 92 Se x -46724# 400# 8290# 4# B- 9509# 400# 91 949840# 429# - 22 57 35 92 Br x -56232.805 6.709 8384.911 0.073 B- 12536.514 7.232 91 939631.597 7.202 - 20 56 36 92 Kr x -68769.320 2.701 8512.674 0.029 B- 6003.118 6.692 91 926173.094 2.900 - 18 55 37 92 Rb -74772.438 6.123 8569.422 0.067 B- 8094.923 6.419 91 919728.481 6.573 - 16 54 38 92 Sr -82867.361 3.423 8648.906 0.037 B- 1949.132 9.384 91 911038.224 3.675 - 14 53 39 92 Y -84816.492 9.127 8661.589 0.099 B- 3642.535 9.127 91 908945.745 9.798 - 12 52 40 92 Zr -88459.028 0.102 8692.678 0.001 B- -2005.736 1.782 91 905035.322 0.109 - 10 51 41 92 Nb -86453.292 1.785 8662.372 0.019 B- 355.284 1.791 91 907188.568 1.915 - 8 50 42 92 Mo -86808.576 0.157 8657.730 0.002 B- -7882.884 3.106 91 906807.155 0.168 - 6 49 43 92 Tc -78925.693 3.102 8563.543 0.034 B- -4624.492 4.125 91 915269.779 3.330 - 4 48 44 92 Ru -74301.201 2.718 8504.773 0.030 B- -11302.114 5.153 91 920234.375 2.917 - 2 47 45 92 Rh x -62999.087 4.378 8373.420 0.048 B- -8419# 300# 91 932367.694 4.700 - 0 46 46 92 Pd x -54580# 300# 8273# 3# B- -17450# 583# 91 941406# 322# - -2 45 47 92 Ag x -37130# 500# 8075# 5# B- * 91 960139# 537# -0 25 59 34 93 Se x -40716# 400# 8223# 4# B- 12175# 588# 92 956290# 429# - 23 58 35 93 Br x -52890.230 430.816 8345.598 4.632 B- 11245.765 430.823 92 943220.000 462.500 - 21 57 36 93 Kr x -64135.994 2.515 8458.108 0.027 B- 8483.907 8.224 92 931147.174 2.700 - 19 56 37 93 Rb -72619.901 7.830 8540.920 0.084 B- 7465.938 8.876 92 922039.325 8.406 - 17 55 38 93 Sr -80085.838 7.554 8612.787 0.081 B- 4141.319 11.697 92 914024.311 8.109 - 15 54 39 93 Y -84227.157 10.488 8648.905 0.113 B- 2894.875 10.483 92 909578.422 11.259 - 13 53 40 93 Zr -87122.032 0.457 8671.620 0.005 B- 90.806 1.484 92 906470.646 0.490 - 11 52 41 93 Nb -87212.838 1.491 8664.184 0.016 B- -405.769 1.501 92 906373.161 1.600 - 9 51 42 93 Mo -n -86807.069 0.181 8651.409 0.002 B- -3200.963 1.004 92 906808.773 0.193 - 7 50 43 93 Tc -p -83606.106 1.012 8608.577 0.011 B- -6389.393 2.299 92 910245.149 1.086 - 5 49 44 93 Ru -77216.713 2.065 8531.462 0.022 B- -8204.913 3.343 92 917104.444 2.216 - 3 48 45 93 Rh -69011.800 2.629 8434.825 0.028 B- -10011# 301# 92 925912.781 2.821 - 1 47 46 93 Pd +p -59001# 300# 8319# 3# B- -12734# 501# 92 936660# 323# - -1 46 47 93 Ag x -46267# 401# 8173# 4# B- * 92 950330# 430# -0 26 60 34 94 Se x -36803# 500# 8180# 5# B- 10597# 583# 93 960490# 537# - 24 59 35 94 Br x -47400# 300# 8284# 3# B- 13948# 300# 93 949114# 322# - 22 58 36 94 Kr x -61347.772 12.109 8424.331 0.129 B- 7215.013 12.278 93 934140.454 13.000 - 20 57 37 94 Rb -68562.785 2.029 8492.764 0.022 B- 10282.926 2.623 93 926394.818 2.177 - 18 56 38 94 Sr -78845.711 1.663 8593.834 0.018 B- 3505.752 6.422 93 915355.643 1.785 - 16 55 39 94 Y -82351.463 6.380 8622.806 0.068 B- 4917.859 6.380 93 911592.063 6.849 - 14 54 40 94 Zr -87269.322 0.164 8666.801 0.002 B- -900.260 1.500 93 906312.524 0.175 - 12 53 41 94 Nb -86369.062 1.491 8648.901 0.016 B- 2045.002 1.494 93 907278.992 1.601 - 10 52 42 94 Mo -88414.065 0.141 8662.333 0.002 B- -4255.748 4.069 93 905083.592 0.151 - 8 51 43 94 Tc - -84158.317 4.071 8608.736 0.043 B- -1574.726 5.143 93 909652.325 4.370 - 6 50 44 94 Ru -82583.591 3.143 8583.661 0.033 B- -9675.978 4.615 93 911342.863 3.374 - 4 49 45 94 Rh -72907.613 3.379 8472.402 0.036 B- -6805.345 5.459 93 921730.453 3.627 - 2 48 46 94 Pd x -66102.268 4.287 8391.682 0.046 B- -13693# 400# 93 929036.292 4.602 - 0 47 47 94 Ag x -52410# 400# 8238# 4# B- -12270# 640# 93 943736# 429# - -2 46 48 94 Cd x -40140# 500# 8099# 5# B- * 93 956908# 537# -0 27 61 34 95 Se x -30460# 500# 8112# 5# B- 13311# 582# 94 967300# 537# - 25 60 35 95 Br x -43771# 298# 8244# 3# B- 12388# 299# 94 953010# 320# - 23 59 36 95 Kr x -56158.913 18.630 8365.995 0.196 B- 9732.580 27.513 94 939710.923 20.000 - 21 58 37 95 Rb -65891.493 20.245 8460.208 0.213 B- 9228.058 20.204 94 929262.568 21.734 - 19 57 38 95 Sr -75119.551 5.812 8549.111 0.061 B- 6089.296 7.240 94 919355.840 6.239 - 17 56 39 95 Y -81208.848 6.779 8604.973 0.071 B- 4451.092 6.772 94 912818.711 7.277 - 15 55 40 95 Zr -85659.940 0.869 8643.592 0.009 B- 1126.318 0.985 94 908040.267 0.933 - 13 54 41 95 Nb -86786.258 0.508 8647.212 0.005 B- 925.601 0.494 94 906831.115 0.545 - 11 53 42 95 Mo -87711.858 0.123 8648.720 0.001 B- -1690.518 5.078 94 905837.442 0.132 - 9 52 43 95 Tc -86021.341 5.080 8622.690 0.053 B- -2563.596 10.531 94 907652.287 5.453 - 7 51 44 95 Ru -83457.745 9.502 8587.470 0.100 B- -5117.138 10.266 94 910404.420 10.200 - 5 50 45 95 Rh -78340.606 3.886 8525.370 0.041 B- -8374.706 4.928 94 915897.895 4.171 - 3 49 46 95 Pd x -69965.900 3.031 8428.980 0.032 B- -10369# 298# 94 924888.512 3.253 - 1 48 47 95 Ag x -59597# 298# 8312# 3# B- -12966# 499# 94 936020# 320# - -1 47 48 95 Cd x -46631# 401# 8167# 4# B- * 94 949940# 430# -0 26 61 35 96 Br x -38163# 298# 8184# 3# B- 14916# 299# 95 959030# 320# - 24 60 36 96 Kr x -53079.678 20.493 8330.851 0.213 B- 8274.671 20.765 95 943016.618 22.000 - 22 59 37 96 Rb -61354.349 3.353 8408.896 0.035 B- 11569.808 9.115 95 934133.393 3.599 - 20 58 38 96 Sr -72924.157 8.475 8521.265 0.088 B- 5411.738 9.726 95 921712.692 9.098 - 18 57 39 96 Y -78335.895 6.088 8569.488 0.063 B- 7102.951 6.087 95 915902.953 6.535 - 16 56 40 96 Zr -85438.846 0.114 8635.327 0.001 B- 163.971 0.100 95 908277.621 0.122 - 14 55 41 96 Nb -85602.816 0.147 8628.886 0.002 B- 3192.059 0.107 95 908101.591 0.157 - 12 54 42 96 Mo -88794.876 0.120 8653.987 0.001 B- -2973.242 5.145 95 904674.774 0.128 - 10 53 43 96 Tc - -85821.634 5.146 8614.866 0.054 B- 258.738 5.146 95 907866.681 5.524 - 8 52 44 96 Ru -86080.372 0.170 8609.412 0.002 B- -6392.654 10.000 95 907588.914 0.182 - 6 51 45 96 Rh - -79687.718 10.001 8534.673 0.104 B- -3504.312 10.844 95 914451.710 10.737 - 4 50 46 96 Pd x -76183.406 4.194 8490.020 0.044 B- -11671.771 90.181 95 918213.744 4.502 - 2 49 47 96 Ag ep -64511.636 90.084 8360.290 0.938 B- -8939# 411# 95 930743.906 96.708 - 0 48 48 96 Cd x -55573# 401# 8259# 4# B- -17683# 641# 95 940340# 430# - -2 47 49 96 In x -37890# 500# 8067# 5# B- * 95 959323# 537# -0 27 62 35 97 Br x -34055# 401# 8140# 4# B- 13368# 421# 96 963440# 430# - 25 61 36 97 Kr x -47423.492 130.409 8269.864 1.344 B- 11095.645 130.423 96 949088.784 140.000 - 23 60 37 97 Rb -58519.137 1.912 8376.186 0.020 B- 10062.317 3.888 96 937177.118 2.052 - 21 59 38 97 Sr -68581.454 3.385 8471.856 0.035 B- 7539.969 7.521 96 926374.776 3.633 - 19 58 39 97 Y + -76121.424 6.719 8541.522 0.069 B- 6821.237 6.707 96 918280.286 7.213 - 17 57 40 97 Zr -82942.661 0.414 8603.779 0.004 B- 2663.115 4.248 96 910957.386 0.444 - 15 56 41 97 Nb -85605.776 4.249 8623.168 0.044 B- 1938.915 4.248 96 908098.414 4.561 - 13 55 42 97 Mo -87544.691 0.165 8635.092 0.002 B- -320.266 4.117 96 906016.903 0.176 - 11 54 43 97 Tc -87224.424 4.118 8623.725 0.042 B- -1103.873 4.956 96 906360.723 4.420 - 9 53 44 97 Ru -n -86120.552 2.763 8604.279 0.028 B- -3523.000 35.355 96 907545.779 2.965 - 7 52 45 97 Rh - -82597.552 35.463 8559.894 0.366 B- -4791.709 35.792 96 911327.876 38.071 - 5 51 46 97 Pd x -77805.843 4.844 8502.430 0.050 B- -6980.000 110.000 96 916471.987 5.200 - 3 50 47 97 Ag - -70825.843 110.107 8422.405 1.135 B- -10372# 318# 96 923965.326 118.204 - 1 49 48 97 Cd x -60454# 298# 8307# 3# B- -13264# 499# 96 935100# 320# - -1 48 49 97 In x -47189# 401# 8163# 4# B- * 96 949340# 430# -0 28 63 35 98 Br x -28250# 400# 8080# 4# B- 16061# 499# 97 969672# 429# - 26 62 36 98 Kr x -44311# 298# 8236# 3# B- 10058# 299# 97 952430# 320# - 24 61 37 98 Rb -54369.146 16.083 8330.729 0.164 B- 12053.958 16.403 97 941632.317 17.265 - 22 60 38 98 Sr -66423.104 3.226 8445.745 0.033 B- 5871.673 8.558 97 928691.860 3.463 - 20 59 39 98 Y p-2n -72294.777 7.929 8497.677 0.081 B- 8991.932 11.576 97 922388.360 8.511 - 18 58 40 98 Zr -81286.709 8.451 8581.448 0.086 B- 2237.890 9.819 97 912735.124 9.072 - 16 57 41 98 Nb -pn -83524.598 5.001 8596.301 0.051 B- 4591.373 5.003 97 910332.650 5.369 - 14 56 42 98 Mo -88115.972 0.174 8635.168 0.002 B- -1683.766 3.377 97 905403.608 0.186 - 12 55 43 98 Tc -86432.205 3.380 8610.004 0.034 B- 1792.653 7.157 97 907211.205 3.628 - 10 54 44 98 Ru -88224.858 6.463 8620.313 0.066 B- -5049.653 10.000 97 905286.713 6.937 - 8 53 45 98 Rh - -83175.205 11.906 8560.803 0.121 B- -1854.229 12.816 97 910707.740 12.782 - 6 52 46 98 Pd -81320.975 4.742 8533.899 0.048 B- -8254.560 33.098 97 912698.337 5.090 - 4 51 47 98 Ag -73066.415 32.907 8441.686 0.336 B- -5430.000 40.000 97 921559.972 35.327 - 2 50 48 98 Cd - -67636.415 51.797 8378.295 0.529 B- -13740# 303# 97 927389.317 55.605 - 0 49 49 98 In x -53896# 298# 8230# 3# B- * 97 942140# 320# -0 27 63 36 99 Kr x -38759# 401# 8178# 4# B- 12362# 401# 98 958390# 430# - 25 62 37 99 Rb x -51121.143 4.031 8295.300 0.041 B- 11400.258 6.223 98 945119.192 4.327 - 23 61 38 99 Sr -62521.401 4.741 8402.552 0.048 B- 8128.424 8.138 98 932880.511 5.089 - 21 60 39 99 Y x -70649.825 6.627 8476.755 0.067 B- 6970.792 12.409 98 924154.288 7.114 - 19 59 40 99 Zr -77620.617 10.502 8539.264 0.106 B- 4714.724 15.950 98 916670.835 11.274 - 17 58 41 99 Nb +p -82335.341 12.004 8578.985 0.121 B- 3634.758 12.006 98 911609.371 12.886 - 15 57 42 99 Mo -85970.098 0.229 8607.797 0.002 B- 1357.764 0.890 98 907707.298 0.245 - 13 56 43 99 Tc -87327.862 0.908 8613.610 0.009 B- 297.519 0.946 98 906249.678 0.974 - 11 55 44 99 Ru -87625.381 0.344 8608.712 0.003 B- -2044.081 6.690 98 905930.278 0.369 - 9 54 45 99 Rh -85581.300 6.697 8580.163 0.068 B- -3398.649 8.008 98 908124.690 7.189 - 7 53 46 99 Pd -82182.651 4.981 8537.930 0.050 B- -5470.178 8.004 98 911773.290 5.347 - 5 52 47 99 Ag x -76712.473 6.265 8474.774 0.063 B- -6781.350 6.462 98 917645.768 6.725 - 3 51 48 99 Cd x -69931.123 1.584 8398.373 0.016 B- -8555# 298# 98 924925.847 1.700 - 1 50 49 99 In x -61376# 298# 8304# 3# B- -13432# 585# 98 934110# 320# - -1 49 50 99 Sn x -47944# 503# 8160# 5# B- * 98 948530# 540# -0 28 64 36 100 Kr x -35052# 401# 8140# 4# B- 11195# 401# 99 962370# 430# - 26 63 37 100 Rb x -46247.064 19.561 8244.320 0.196 B- 13573.838 20.831 99 950351.731 21.000 - 24 62 38 100 Sr -59820.903 7.160 8372.234 0.072 B- 7506.493 13.273 99 935779.615 7.686 - 22 61 39 100 Y x -67327.396 11.186 8439.476 0.112 B- 9050.041 13.830 99 927721.063 12.008 - 20 60 40 100 Zr -76377.437 8.149 8522.153 0.081 B- 3419.963 11.398 99 918005.444 8.748 - 18 59 41 100 Nb IT -79797.399 7.986 8548.529 0.080 B- 6395.626 7.992 99 914333.963 8.573 - 16 58 42 100 Mo -86193.025 0.302 8604.662 0.003 B- -172.080 1.371 99 907467.976 0.323 - 14 57 43 100 Tc -n -86020.945 1.351 8595.118 0.014 B- 3206.444 1.376 99 907652.711 1.450 - 12 56 44 100 Ru -89227.389 0.343 8619.359 0.003 B- -3636.262 18.123 99 904210.452 0.368 - 10 55 45 100 Rh -85591.126 18.125 8575.172 0.181 B- -378.348 25.289 99 908114.141 19.458 - 8 54 46 100 Pd -85212.778 17.638 8563.566 0.176 B- -7074.819 18.333 99 908520.315 18.935 - 6 53 47 100 Ag x -78137.959 5.000 8484.994 0.050 B- -3943.363 5.273 99 916115.445 5.367 - 4 52 48 100 Cd -74194.596 1.677 8437.737 0.017 B- -9881.624 182.517 99 920348.820 1.799 - 2 51 49 100 In -64312.972 182.519 8331.097 1.825 B- -7030.000 240.000 99 930957.180 195.942 - 0 50 50 100 Sn - -57282.972 301.518 8252.974 3.015 B- * 99 938504.196 323.693 -0 29 65 36 101 Kr x -29128# 503# 8081# 5# B- 13717# 541# 100 968730# 540# - 27 64 37 101 Rb + -42845# 200# 8209# 2# B- 12480# 200# 100 954004# 215# - 25 63 38 101 Sr x -55324.907 8.480 8324.740 0.084 B- 9736.095 11.055 100 940606.266 9.103 - 23 62 39 101 Y x -65061.002 7.092 8413.391 0.070 B- 8104.955 10.933 100 930154.138 7.614 - 21 61 40 101 Zr -73165.957 8.339 8485.892 0.083 B- 5725.534 9.143 100 921453.110 8.951 - 19 60 41 101 Nb x -78891.491 3.749 8534.835 0.037 B- 4628.458 3.738 100 915306.496 4.024 - 17 59 42 101 Mo -n -83519.949 0.309 8572.915 0.003 B- 2824.645 24.002 100 910337.641 0.331 - 15 58 43 101 Tc + -86344.594 24.004 8593.136 0.238 B- 1613.520 24.000 100 907305.260 25.768 - 13 57 44 101 Ru -87958.114 0.415 8601.365 0.004 B- -545.697 5.852 100 905573.075 0.445 - 11 56 45 101 Rh -87412.416 5.841 8588.216 0.058 B- -1980.284 3.903 100 906158.905 6.270 - 9 55 46 101 Pd -85432.132 4.588 8560.864 0.045 B- -4097.759 6.668 100 908284.828 4.925 - 7 54 47 101 Ag x -81334.374 4.838 8512.546 0.048 B- -5497.918 5.063 100 912683.953 5.193 - 5 53 48 101 Cd x -75836.456 1.490 8450.365 0.015 B- -7223# 196# 100 918586.211 1.600 - 3 52 49 101 In x -68614# 196# 8371# 2# B- -8308# 358# 100 926340# 210# - 1 51 50 101 Sn ep -60305.626 300.005 8281.102 2.970 B- * 100 935259.244 322.068 -0 28 65 37 102 Rb x -37707# 298# 8157# 3# B- 14452# 306# 101 959520# 320# - 26 64 38 102 Sr x -52159.304 67.068 8291.220 0.658 B- 9013.873 67.191 101 944004.680 72.000 - 24 63 39 102 Y x -61173.177 4.077 8371.922 0.040 B- 10414.530 9.669 101 934327.889 4.377 - 22 62 40 102 Zr -71587.707 8.767 8466.355 0.086 B- 4716.837 9.053 101 923147.431 9.412 - 20 61 41 102 Nb -76304.544 2.545 8504.928 0.025 B- 7261.517 8.675 101 918083.697 2.732 - 18 60 42 102 Mo -83566.061 8.312 8568.450 0.081 B- 1006.817 12.373 101 910288.138 8.923 - 16 59 43 102 Tc -84572.878 9.166 8570.650 0.090 B- 4533.558 9.165 101 909207.275 9.840 - 14 58 44 102 Ru -89106.437 0.418 8607.427 0.004 B- -2323.119 6.396 101 904340.300 0.448 - 12 57 45 102 Rh - -86783.318 6.410 8576.981 0.063 B- 1119.853 6.406 101 906834.270 6.881 - 10 56 46 102 Pd -87903.171 0.554 8580.290 0.005 B- -5656.480 8.190 101 905632.058 0.594 - 8 55 47 102 Ag + -82246.691 8.171 8517.164 0.080 B- -2587.000 8.000 101 911704.540 8.771 - 6 54 48 102 Cd -79659.691 1.662 8484.131 0.016 B- -8964.807 4.865 101 914481.799 1.784 - 4 53 49 102 In -70694.884 4.573 8388.571 0.045 B- -5760.000 100.000 101 924105.916 4.909 - 2 52 50 102 Sn - -64934.884 100.105 8324.430 0.981 B- * 101 930289.530 107.466 -0 29 66 37 103 Rb x -33608# 401# 8117# 4# B- 13814# 446# 102 963920# 430# - 27 65 38 103 Sr x -47422# 196# 8243# 2# B- 11035# 196# 102 949090# 210# - 25 64 39 103 Y x -58457.575 11.204 8342.638 0.109 B- 9357.759 14.518 102 937243.208 12.028 - 23 63 40 103 Zr x -67815.334 9.232 8425.895 0.090 B- 7213.337 10.036 102 927197.240 9.911 - 21 62 41 103 Nb x -75028.671 3.935 8488.331 0.038 B- 5931.999 10.036 102 919453.403 4.224 - 19 61 42 103 Mo x -80960.670 9.232 8538.328 0.090 B- 3643.197 13.471 102 913085.140 9.911 - 17 60 43 103 Tc +p -84603.867 9.810 8566.103 0.095 B- 2663.304 9.808 102 909174.008 10.531 - 15 59 44 103 Ru -87267.171 0.443 8584.365 0.004 B- 764.538 2.260 102 906314.833 0.475 - 13 58 45 103 Rh -88031.708 2.301 8584.192 0.022 B- -574.519 2.420 102 905494.068 2.470 - 11 57 46 103 Pd -n -87457.189 0.950 8571.019 0.009 B- -2654.498 4.207 102 906110.840 1.019 - 9 56 47 103 Ag x -84802.692 4.099 8537.651 0.040 B- -4151.075 4.481 102 908960.560 4.400 - 7 55 48 103 Cd -80651.616 1.811 8489.754 0.018 B- -6019.026 9.754 102 913416.923 1.943 - 5 54 49 103 In -74632.591 9.625 8423.721 0.093 B- -7660.000 70.000 102 919878.613 10.332 - 3 53 50 103 Sn - -66972.591 70.659 8341.757 0.686 B- -10794# 306# 102 928101.962 75.855 - 1 52 51 103 Sb x -56178# 298# 8229# 3# B- * 102 939690# 320# -0 28 66 38 104 Sr x -44106# 298# 8210# 3# B- 9958# 499# 103 952650# 320# - 26 65 39 104 Y x -54064# 401# 8298# 4# B- 11660# 401# 103 941960# 430# - 24 64 40 104 Zr x -65724.060 9.325 8402.377 0.090 B- 6094.952 9.699 103 929442.315 10.011 - 22 63 41 104 Nb x -71819.012 2.737 8453.459 0.026 B- 8530.957 9.311 103 922899.115 2.938 - 20 62 42 104 Mo -80349.968 8.921 8527.965 0.086 B- 2153.476 24.167 103 913740.756 9.576 - 18 61 43 104 Tc -82503.444 24.888 8541.149 0.239 B- 5592.266 24.939 103 911428.905 26.718 - 16 60 44 104 Ru -88095.710 2.498 8587.399 0.024 B- -1136.362 3.364 103 905425.360 2.681 - 14 59 45 104 Rh -n -86959.348 2.303 8568.949 0.022 B- 2435.758 2.660 103 906645.295 2.472 - 12 58 46 104 Pd +n -89395.105 1.336 8584.848 0.013 B- -4278.654 4.000 103 904030.401 1.434 - 10 57 47 104 Ag - -85116.452 4.217 8536.184 0.041 B- -1148.072 4.537 103 908623.725 4.527 - 8 56 48 104 Cd -83968.380 1.673 8517.622 0.016 B- -7785.716 6.013 103 909856.230 1.795 - 6 55 49 104 In x -76182.665 5.775 8435.237 0.056 B- -4555.617 8.146 103 918214.540 6.200 - 4 54 50 104 Sn -71627.047 5.745 8383.911 0.055 B- -12453.427 122.579 103 923105.197 6.167 - 2 53 51 104 Sb -p -59173.620 122.444 8256.644 1.177 B- * 103 936474.502 131.449 -0 29 67 38 105 Sr x -38610# 503# 8156# 5# B- 12660# 1428# 104 958550# 540# - 27 66 39 105 Y x -51270.361 1336.694 8269.020 12.730 B- 10194.373 1336.749 104 944959.000 1435.000 - 25 65 40 105 Zr x -61464.734 12.118 8358.659 0.115 B- 8450.817 12.770 104 934014.890 13.008 - 23 64 41 105 Nb x -69915.551 4.028 8431.692 0.038 B- 7421.590 9.920 104 924942.564 4.324 - 21 63 42 105 Mo -77337.141 9.065 8494.923 0.086 B- 4952.947 35.031 104 916975.159 9.731 - 19 62 43 105 Tc -82290.088 35.264 8534.643 0.336 B- 3644.402 35.280 104 911657.952 37.857 - 17 61 44 105 Ru -85934.490 2.499 8561.900 0.024 B- 1916.752 2.851 104 907745.525 2.682 - 15 60 45 105 Rh -87851.243 2.502 8572.704 0.024 B- 566.646 2.346 104 905687.806 2.685 - 13 59 46 105 Pd -88417.888 1.138 8570.650 0.011 B- -1347.052 4.670 104 905079.487 1.222 - 11 58 47 105 Ag -87070.836 4.544 8550.370 0.043 B- -2736.997 4.362 104 906525.607 4.877 - 9 57 48 105 Cd -84333.839 1.392 8516.852 0.013 B- -4693.267 10.341 104 909463.895 1.494 - 7 56 49 105 In x -79640.572 10.246 8464.704 0.098 B- -6302.580 10.989 104 914502.324 11.000 - 5 55 50 105 Sn -73337.992 3.971 8397.228 0.038 B- -9322.510 22.185 104 921268.423 4.263 - 3 54 51 105 Sb +a -64015.482 21.827 8300.992 0.208 B- -11203.972 300.813 104 931276.549 23.431 - 1 53 52 105 Te -a -52811.510 300.020 8186.836 2.857 B- * 104 943304.508 322.084 -0 30 68 38 106 Sr x -34790# 600# 8119# 6# B- 11263# 783# 105 962651# 644# - 28 67 39 106 Y x -46053# 503# 8218# 5# B- 12497# 664# 105 950560# 540# - 26 66 40 106 Zr x -58549.987 433.145 8328.450 4.086 B- 7653.370 433.164 105 937144.000 465.000 - 24 65 41 106 Nb x -66203.357 4.122 8393.271 0.039 B- 9931.170 10.026 105 928927.768 4.424 - 22 64 42 106 Mo x -76134.528 9.140 8479.581 0.086 B- 3641.695 15.284 105 918266.218 9.812 - 20 63 43 106 Tc + -79776.223 12.250 8506.556 0.116 B- 6547.000 11.000 105 914356.697 13.150 - 18 62 44 106 Ru -86323.223 5.391 8560.940 0.051 B- 39.404 0.212 105 907328.203 5.787 - 16 61 45 106 Rh -86362.627 5.390 8553.931 0.051 B- 3544.901 5.335 105 907285.901 5.785 - 14 60 46 106 Pd -89907.527 1.106 8579.992 0.010 B- -2965.145 2.817 105 903480.293 1.186 - 12 59 47 106 Ag -86942.383 3.016 8544.639 0.028 B- 189.755 2.819 105 906663.507 3.237 - 10 58 48 106 Cd -87132.138 1.104 8539.048 0.010 B- -6524.004 12.176 105 906459.797 1.184 - 8 57 49 106 In - -80608.134 12.226 8470.120 0.115 B- -3254.447 13.244 105 913463.603 13.125 - 6 56 50 106 Sn -77353.687 5.091 8432.038 0.048 B- -10880.396 9.025 105 916957.396 5.465 - 4 55 51 106 Sb x -66473.292 7.452 8322.012 0.070 B- -8253.544 100.816 105 928637.982 8.000 - 2 54 52 106 Te -a -58219.748 100.541 8236.767 0.948 B- * 105 937498.526 107.934 -0 31 69 38 107 Sr x -28900# 700# 8064# 7# B- 13465# 862# 106 968975# 751# - 29 68 39 107 Y x -42364# 503# 8182# 5# B- 12015# 1230# 106 954520# 540# - 27 67 40 107 Zr x -54379.688 1122.450 8287.073 10.490 B- 9344.122 1122.479 106 941621.000 1205.000 - 25 66 41 107 Nb x -63723.810 8.023 8367.089 0.075 B- 8827.750 12.232 106 931589.672 8.612 - 23 65 42 107 Mo x -72551.560 9.233 8442.280 0.086 B- 6198.355 12.667 106 922112.692 9.912 - 21 64 43 107 Tc x -78749.914 8.673 8492.897 0.081 B- 5112.598 11.724 106 915458.485 9.310 - 19 63 44 107 Ru -nn -83862.512 8.673 8533.366 0.081 B- 3001.191 14.847 106 909969.885 9.310 - 17 62 45 107 Rh +p -86863.703 12.051 8554.103 0.113 B- 1508.936 12.111 106 906747.974 12.937 - 15 61 46 107 Pd -88372.639 1.201 8560.894 0.011 B- 34.031 2.318 106 905128.064 1.289 - 13 60 47 107 Ag -88406.670 2.382 8553.900 0.022 B- -1416.409 2.567 106 905091.531 2.557 - 11 59 48 107 Cd -86990.261 1.665 8533.351 0.016 B- -3426.000 11.000 106 906612.108 1.787 - 9 58 49 107 In - -83564.261 11.125 8494.021 0.104 B- -5052.033 12.327 106 910290.071 11.943 - 7 57 50 107 Sn x -78512.228 5.310 8439.494 0.050 B- -7858.989 6.738 106 915713.651 5.700 - 5 56 51 107 Sb -70653.239 4.148 8358.734 0.039 B- -10113.913 70.952 106 924150.624 4.452 - 3 55 52 107 Te -a -60539.326 70.830 8256.899 0.662 B- -11110# 308# 106 935008.356 76.039 - 1 54 53 107 I x -49430# 300# 8146# 3# B- * 106 946935# 322# -0 30 69 39 108 Y x -37297# 596# 8134# 6# B- 14056# 718# 107 959960# 640# - 28 68 40 108 Zr x -51353# 401# 8257# 4# B- 8193# 401# 107 944870# 430# - 26 67 41 108 Nb x -59545.765 8.237 8325.665 0.076 B- 11210.177 12.373 107 936074.988 8.842 - 24 66 42 108 Mo x -70755.942 9.233 8422.219 0.085 B- 5166.835 12.734 107 924040.367 9.912 - 22 65 43 108 Tc x -75922.778 8.769 8462.816 0.081 B- 7738.573 11.790 107 918493.541 9.413 - 20 64 44 108 Ru -3n -83661.350 8.680 8527.225 0.080 B- 1370.370 16.469 107 910185.841 9.318 - 18 63 45 108 Rh x -85031.721 13.996 8532.670 0.130 B- 4492.486 14.039 107 908714.688 15.024 - 16 62 46 108 Pd -89524.206 1.108 8567.023 0.010 B- -1917.444 2.633 107 903891.805 1.189 - 14 61 47 108 Ag -n -87606.763 2.388 8542.025 0.022 B- 1645.651 2.639 107 905950.266 2.563 - 12 60 48 108 Cd -89252.414 1.123 8550.019 0.010 B- -5132.595 8.584 107 904183.587 1.205 - 10 59 49 108 In -84119.819 8.641 8495.251 0.080 B- -2049.881 9.836 107 909693.655 9.276 - 8 58 50 108 Sn -82069.938 5.382 8469.027 0.050 B- -9624.607 7.692 107 911894.292 5.778 - 6 57 51 108 Sb x -72445.331 5.496 8372.666 0.051 B- -6663.664 7.712 107 922226.734 5.900 - 4 56 52 108 Te -65781.667 5.411 8303.721 0.050 B- -13132.062 132.370 107 929380.471 5.808 - 2 55 53 108 I -a -52649.605 132.260 8174.884 1.225 B- * 107 943478.321 141.986 -0 31 70 39 109 Y x -33200# 700# 8096# 6# B- 12992# 862# 108 964358# 751# - 29 69 40 109 Zr x -46193# 503# 8208# 5# B- 10497# 566# 108 950410# 540# - 27 68 41 109 Nb x -56689.794 258.490 8297.130 2.371 B- 9976.202 258.732 108 939141.000 277.500 - 25 67 42 109 Mo x -66665.996 11.188 8381.477 0.103 B- 7616.780 14.787 108 928431.106 12.010 - 23 66 43 109 Tc x -74282.775 9.669 8444.178 0.089 B- 6455.626 12.657 108 920254.156 10.380 - 21 65 44 109 Ru -4n -80738.401 8.954 8496.227 0.082 B- 4261.054 9.822 108 913323.756 9.612 - 19 64 45 109 Rh -84999.455 4.039 8528.142 0.037 B- 2607.021 4.187 108 908749.326 4.336 - 17 63 46 109 Pd -87606.476 1.114 8544.882 0.010 B- 1112.950 1.402 108 905950.574 1.195 - 15 62 47 109 Ag -88719.426 1.287 8547.915 0.012 B- -215.105 1.780 108 904755.773 1.381 - 13 61 48 109 Cd -88504.321 1.536 8538.764 0.014 B- -2014.809 4.066 108 904986.698 1.649 - 11 60 49 109 In -86489.511 3.969 8513.102 0.036 B- -3859.327 8.887 108 907149.685 4.261 - 9 59 50 109 Sn -82630.184 7.949 8470.518 0.073 B- -6379.206 8.807 108 911292.843 8.533 - 7 58 51 109 Sb -76250.977 5.265 8404.815 0.048 B- -8535.587 6.850 108 918141.204 5.652 - 5 57 52 109 Te -67715.390 4.382 8319.330 0.040 B- -10042.894 8.030 108 927304.534 4.704 - 3 56 53 109 I -p -57672.496 6.729 8220.016 0.062 B- -11502.948 300.183 108 938086.025 7.223 - 1 55 54 109 Xe -a -46169.548 300.108 8107.306 2.753 B- * 108 950434.948 322.178 -0 30 70 40 110 Zr x -42886# 596# 8177# 5# B- 9424# 1029# 109 953960# 640# - 28 69 41 110 Nb x -52309.909 838.345 8255.260 7.621 B- 12232.677 838.694 109 943843.000 900.000 - 26 68 42 110 Mo x -64542.585 24.223 8359.354 0.220 B- 6491.925 26.018 109 930710.680 26.004 - 24 67 43 110 Tc x -71034.510 9.497 8411.259 0.086 B- 9038.066 12.509 109 923741.312 10.195 - 22 66 44 110 Ru -80072.576 8.924 8486.311 0.081 B- 2756.110 19.404 109 914038.548 9.580 - 20 65 45 110 Rh -82828.686 17.805 8504.254 0.162 B- 5502.218 17.797 109 911079.742 19.114 - 18 64 46 110 Pd -88330.905 0.612 8547.162 0.006 B- -873.603 1.378 109 905172.868 0.657 - 16 63 47 110 Ag -87457.302 1.286 8532.108 0.012 B- 2890.667 1.277 109 906110.719 1.380 - 14 62 48 110 Cd -90347.969 0.380 8551.275 0.003 B- -3878.000 11.547 109 903007.460 0.407 - 12 61 49 110 In - -86469.969 11.553 8508.908 0.105 B- -627.985 17.980 109 907170.665 12.402 - 10 60 50 110 Sn x -85841.983 13.777 8496.087 0.125 B- -8392.250 15.012 109 907844.835 14.790 - 8 59 51 110 Sb x -77449.734 5.962 8412.681 0.054 B- -5219.923 8.875 109 916854.286 6.400 - 6 58 52 110 Te -72229.811 6.575 8358.115 0.060 B- -11765.635 50.978 109 922458.104 7.058 - 4 57 53 110 I -a -60464.176 50.552 8244.043 0.460 B- -8541.551 112.934 109 935089.033 54.270 - 2 56 54 110 Xe -a -51922.625 100.988 8159.280 0.918 B- * 109 944258.765 108.415 -0 31 71 40 111 Zr x -37560# 700# 8128# 6# B- 11316# 760# 110 959678# 751# - 29 70 41 111 Nb x -48875# 298# 8223# 3# B- 11064# 298# 110 947530# 320# - 27 69 42 111 Mo + -59939.761 12.578 8315.292 0.113 B- 9084.861 6.800 110 935652.016 13.502 - 25 68 43 111 Tc x -69024.622 10.581 8390.089 0.095 B- 7760.649 13.848 110 925899.016 11.359 - 23 67 44 111 Ru x -76785.271 9.682 8452.957 0.087 B- 5519.181 11.860 110 917567.616 10.394 - 21 66 45 111 Rh -82304.452 6.850 8495.631 0.062 B- 3681.435 6.887 110 911642.531 7.354 - 19 65 46 111 Pd -n -85985.888 0.731 8521.749 0.007 B- 2229.560 1.572 110 907690.347 0.785 - 17 64 47 111 Ag + -88215.447 1.459 8534.787 0.013 B- 1036.800 1.414 110 905296.816 1.565 - 15 63 48 111 Cd -89252.247 0.357 8537.079 0.003 B- -860.204 3.417 110 904183.766 0.383 - 13 62 49 111 In -88392.043 3.424 8522.282 0.031 B- -2453.456 6.337 110 905107.233 3.675 - 11 61 50 111 Sn +n -85938.587 5.336 8493.130 0.048 B- -5101.851 10.334 110 907741.126 5.728 - 9 60 51 111 Sb x -80836.736 8.849 8440.120 0.080 B- -7249.259 10.937 110 913218.189 9.500 - 7 59 52 111 Te x -73587.477 6.427 8367.763 0.058 B- -8633.692 7.994 110 921000.589 6.900 - 5 58 53 111 I -64953.785 4.754 8282.934 0.043 B- -10558.252 86.830 110 930269.239 5.103 - 3 57 54 111 Xe -a -54395.534 86.700 8180.766 0.781 B- -11575# 214# 110 941603.989 93.076 - 1 56 55 111 Cs x -42821# 196# 8069# 2# B- * 110 954030# 210# -0 32 72 40 112 Zr x -33810# 700# 8094# 6# B- 10463# 760# 111 963703# 751# - 30 71 41 112 Nb x -44274# 298# 8180# 3# B- 13190# 357# 111 952470# 320# - 28 70 42 112 Mo x -57464# 196# 8291# 2# B- 7795# 196# 111 938310# 210# - 26 69 43 112 Tc x -65258.938 5.515 8353.621 0.049 B- 10371.881 11.060 111 929941.644 5.920 - 24 68 44 112 Ru x -75630.818 9.599 8439.242 0.086 B- 4100.685 45.118 111 918806.972 10.305 - 22 67 45 112 Rh -79731.503 44.085 8468.870 0.394 B- 6590.059 43.927 111 914404.705 47.327 - 20 66 46 112 Pd -86321.562 6.544 8520.724 0.058 B- 262.156 6.978 111 907329.986 7.025 - 18 65 47 112 Ag x -86583.718 2.422 8516.080 0.022 B- 3991.141 2.435 111 907048.550 2.600 - 16 64 48 112 Cd -90574.859 0.250 8544.730 0.002 B- -2584.728 4.243 111 902763.883 0.268 - 14 63 49 112 In -87990.131 4.251 8514.667 0.038 B- 664.925 4.243 111 905538.704 4.563 - 12 62 50 112 Sn -88655.056 0.294 8513.618 0.003 B- -7056.091 17.832 111 904824.877 0.315 - 10 61 51 112 Sb x -81598.965 17.829 8443.632 0.159 B- -4031.457 19.702 111 912399.903 19.140 - 8 60 52 112 Te x -77567.508 8.383 8400.652 0.075 B- -10504.178 13.239 111 916727.850 9.000 - 6 59 53 112 I x -67063.330 10.246 8299.879 0.091 B- -7036.991 13.175 111 928004.550 11.000 - 4 58 54 112 Xe -a -60026.338 8.283 8230.064 0.074 B- -13736.062 87.190 111 935559.071 8.891 - 2 57 55 112 Cs -p -46290.277 86.796 8100.435 0.775 B- * 111 950305.341 93.178 -0 31 72 41 113 Nb x -40511# 401# 8146# 4# B- 11979# 500# 112 956510# 430# - 29 71 42 113 Mo x -52490# 300# 8245# 3# B- 10322# 300# 112 943650# 322# - 27 70 43 113 Tc x -62811.541 3.353 8329.464 0.030 B- 9056.578 37.028 112 932569.033 3.600 - 25 69 44 113 Ru -71868.119 36.875 8402.688 0.326 B- 6899.417 37.558 112 922846.396 39.587 - 23 68 45 113 Rh x -78767.536 7.130 8456.821 0.063 B- 4823.555 9.881 112 915439.567 7.653 - 21 67 46 113 Pd x -83591.092 6.945 8492.584 0.061 B- 3435.731 18.033 112 910261.267 7.455 - 19 66 47 113 Ag + -87026.822 16.643 8516.065 0.147 B- 2016.462 16.641 112 906572.858 17.866 - 17 65 48 113 Cd -89043.284 0.244 8526.987 0.002 B- 323.833 0.265 112 904408.097 0.262 - 15 64 49 113 In -89367.117 0.188 8522.929 0.002 B- -1038.985 1.573 112 904060.448 0.202 - 13 63 50 113 Sn -88328.132 1.575 8506.811 0.014 B- -3911.164 17.121 112 905175.845 1.690 - 11 62 51 113 Sb - -84416.968 17.193 8465.275 0.152 B- -6069.939 32.810 112 909374.652 18.457 - 9 61 52 113 Te x -78347.029 27.945 8404.636 0.247 B- -7227.522 29.070 112 915891.000 30.000 - 7 60 53 113 I x -71119.507 8.011 8333.752 0.071 B- -8915.889 10.533 112 923650.064 8.600 - 5 59 54 113 Xe -62203.618 6.840 8247.927 0.061 B- -10439.088 10.970 112 933221.666 7.342 - 3 58 55 113 Cs -p -51764.530 8.577 8148.622 0.076 B- -11980# 298# 112 944428.488 9.207 - 1 57 56 113 Ba x -39784# 298# 8036# 3# B- * 112 957290# 320# -0 32 73 41 114 Nb x -35387# 503# 8100# 4# B- 14420# 585# 113 962010# 540# - 30 72 42 114 Mo x -49807# 298# 8220# 3# B- 8793# 526# 113 946530# 320# - 28 71 43 114 Tc x -58600.288 433.145 8290.259 3.800 B- 11621.524 433.159 113 937090.000 465.000 - 26 70 44 114 Ru x -70221.811 3.550 8385.340 0.031 B- 5488.813 71.643 113 924613.780 3.811 - 24 69 45 114 Rh -75710.625 71.561 8426.624 0.628 B- 7780.319 71.891 113 918721.296 76.824 - 22 68 46 114 Pd x -83490.943 6.945 8488.010 0.061 B- 1439.856 8.311 113 910368.780 7.456 - 20 67 47 114 Ag x -84930.800 4.564 8493.778 0.040 B- 5084.133 4.573 113 908823.031 4.900 - 18 66 48 114 Cd -90014.932 0.276 8531.513 0.002 B- -1445.132 0.382 113 903364.990 0.296 - 16 65 49 114 In -88569.801 0.301 8511.973 0.003 B- 1989.923 0.302 113 904916.402 0.323 - 14 64 50 114 Sn -90559.723 0.029 8522.566 0.000 B- -6063.149 21.838 113 902780.132 0.031 - 12 63 51 114 Sb -84496.574 21.838 8462.518 0.192 B- -2608.005 35.466 113 909289.191 23.444 - 10 62 52 114 Te x -81888.569 27.945 8432.778 0.245 B- -9092# 152# 113 912089.000 30.000 - 8 61 53 114 I x -72796# 149# 8346# 1# B- -5710# 149# 113 921850# 160# - 6 60 54 114 Xe x -67085.890 11.178 8289.205 0.098 B- -12403.629 71.976 113 927980.331 12.000 - 4 59 55 114 Cs -a -54682.261 71.102 8173.538 0.624 B- -8776.835 124.892 113 941296.175 76.331 - 2 58 56 114 Ba -a -45905.426 102.676 8089.686 0.901 B- * 113 950718.495 110.227 -0 33 74 41 115 Nb x -31354# 503# 8065# 4# B- 13395# 643# 114 966340# 540# - 31 73 42 115 Mo x -44749# 401# 8175# 3# B- 11571# 885# 114 951960# 430# - 29 72 43 115 Tc x -56319.990 789.441 8268.527 6.865 B- 9869.744 794.386 114 939538.000 847.500 - 27 71 44 115 Ru x -66189.734 88.496 8347.547 0.770 B- 8040.097 88.790 114 928942.393 95.004 - 25 70 45 115 Rh x -74229.831 7.316 8410.658 0.064 B- 6196.554 15.350 114 920310.993 7.854 - 23 69 46 115 Pd -80426.386 13.546 8457.738 0.118 B- 4556.268 21.649 114 913658.718 14.541 - 21 68 47 115 Ag -84982.654 18.268 8490.555 0.159 B- 3101.825 18.274 114 908767.363 19.611 - 19 67 48 115 Cd -88084.479 0.651 8510.724 0.006 B- 1451.867 0.651 114 905437.417 0.699 - 17 66 49 115 In -89536.346 0.012 8516.546 0.000 B- 497.489 0.010 114 903878.773 0.012 - 15 65 50 115 Sn -90033.835 0.015 8514.069 0.000 B- -3030.432 16.025 114 903344.697 0.016 - 13 64 51 115 Sb x -87003.403 16.025 8480.915 0.139 B- -4940.644 32.214 114 906598.000 17.203 - 11 63 52 115 Te x -82062.759 27.945 8431.150 0.243 B- -5724.962 40.184 114 911902.000 30.000 - 9 62 53 115 I x -76337.797 28.876 8374.564 0.251 B- -7681.049 31.313 114 918048.000 31.000 - 7 61 54 115 Xe x -68656.748 12.109 8300.970 0.105 B- -8957# 103# 114 926293.945 13.000 - 5 60 55 115 Cs x -59699# 102# 8216# 1# B- -10680# 225# 114 935910# 110# - 3 59 56 115 Ba x -49020# 200# 8117# 2# B- * 114 947375# 215# -0 32 74 42 116 Mo x -41500# 500# 8146# 4# B- 9956# 582# 115 955448# 537# - 30 73 43 116 Tc x -51456# 298# 8225# 3# B- 12613# 298# 115 944760# 320# - 28 72 44 116 Ru x -64068.909 3.726 8326.883 0.032 B- 6667.213 73.926 115 931219.193 4.000 - 26 71 45 116 Rh -70736.122 73.832 8377.615 0.636 B- 9095.512 74.169 115 924061.645 79.261 - 24 70 46 116 Pd x -79831.635 7.132 8449.280 0.061 B- 2711.019 7.842 115 914297.210 7.656 - 22 69 47 116 Ag x -82542.653 3.260 8465.907 0.028 B- 6169.827 3.264 115 911386.812 3.500 - 20 68 48 116 Cd -88712.480 0.160 8512.350 0.001 B- -462.731 0.272 115 904763.230 0.172 - 18 67 49 116 In -n -88249.749 0.220 8501.617 0.002 B- 3276.221 0.240 115 905259.992 0.236 - 16 66 50 116 Sn -91525.970 0.096 8523.116 0.001 B- -4703.820 5.160 115 901742.824 0.103 - 14 65 51 116 Sb -86822.150 5.160 8475.821 0.044 B- -1553.189 28.417 115 906792.583 5.539 - 12 64 52 116 Te x -85268.961 27.945 8455.687 0.241 B- -7776.725 100.553 115 908460.000 30.000 - 10 63 53 116 I + -77492.236 96.592 8381.902 0.833 B- -4445.512 95.707 115 916808.658 103.695 - 8 62 54 116 Xe x -73046.724 13.041 8336.834 0.112 B- -11004# 101# 115 921581.112 14.000 - 6 61 55 116 Cs ea -62043# 100# 8235# 1# B- -7463# 224# 115 933395# 108# - 4 60 56 116 Ba x -54580# 200# 8164# 2# B- -13935# 371# 115 941406# 215# - 2 59 57 116 La -a -40645# 312# 8037# 3# B- * 115 956365# 335# -0 33 75 42 117 Mo x -36170# 500# 8100# 4# B- 12212# 641# 116 961170# 537# - 31 74 43 117 Tc x -48382# 401# 8197# 3# B- 11108# 590# 116 948060# 430# - 29 73 44 117 Ru x -59489.865 433.145 8285.562 3.702 B- 9407.508 433.236 116 936135.000 465.000 - 27 72 45 117 Rh x -68897.373 8.892 8359.281 0.076 B- 7527.104 11.411 116 926035.623 9.546 - 25 71 46 117 Pd -76424.477 7.252 8416.929 0.062 B- 5757.537 14.766 116 917954.944 7.785 - 23 70 47 117 Ag -82182.014 13.572 8459.452 0.116 B- 4236.375 13.610 116 911773.974 14.570 - 21 69 48 117 Cd -n -86418.389 1.013 8488.973 0.009 B- 2524.653 4.983 116 907226.038 1.087 - 19 68 49 117 In -88943.042 4.881 8503.865 0.042 B- 1454.709 4.857 116 904515.712 5.239 - 17 67 50 117 Sn -90397.751 0.483 8509.611 0.004 B- -1758.212 8.445 116 902954.017 0.518 - 15 66 51 117 Sb -88639.539 8.437 8487.897 0.072 B- -3544.128 13.079 116 904841.535 9.057 - 13 65 52 117 Te -85095.411 13.456 8450.919 0.115 B- -4659.334 28.673 116 908646.313 14.446 - 11 64 53 117 I -80436.077 26.196 8404.409 0.224 B- -6250.740 28.177 116 913648.314 28.123 - 9 63 54 117 Xe x -74185.337 10.378 8344.297 0.089 B- -7692.245 63.267 116 920358.760 11.141 - 7 62 55 117 Cs x -66493.092 62.410 8271.864 0.533 B- -9035.338 258.002 116 928616.726 67.000 - 5 61 56 117 Ba ep -57457.753 250.340 8187.953 2.140 B- -10987# 321# 116 938316.561 268.750 - 3 60 57 117 La -p -46471# 200# 8087# 2# B- * 116 950111# 215# -0 34 76 42 118 Mo x -32630# 500# 8069# 4# B- 11159# 641# 117 964970# 537# - 32 75 43 118 Tc x -43790# 401# 8157# 3# B- 13470# 448# 117 952990# 430# - 30 74 44 118 Ru x -57260# 200# 8265# 2# B- 7628# 202# 117 938529# 215# - 28 73 45 118 Rh x -64887.460 24.235 8322.858 0.205 B- 10501.286 24.342 117 930340.443 26.017 - 26 72 46 118 Pd -75388.746 2.491 8405.222 0.021 B- 4165.046 3.539 117 919066.847 2.673 - 24 71 47 118 Ag x -79553.792 2.515 8433.889 0.021 B- 7147.849 20.158 117 914595.487 2.700 - 22 70 48 118 Cd -nn -86701.641 20.001 8487.834 0.169 B- 526.570 21.450 117 906921.955 21.471 - 20 69 49 118 In -87228.211 7.752 8485.667 0.066 B- 4424.643 7.740 117 906356.659 8.322 - 18 68 50 118 Sn -91652.853 0.499 8516.533 0.004 B- -3656.640 2.975 117 901606.609 0.536 - 16 67 51 118 Sb - -87996.213 3.016 8478.915 0.026 B- -299.630 18.726 117 905532.174 3.238 - 14 66 52 118 Te +nn -87696.584 18.481 8469.746 0.157 B- -6725.536 27.056 117 905853.839 19.840 - 12 65 53 118 I x -80971.048 19.760 8406.120 0.167 B- -2891.991 22.320 117 913074.000 21.213 - 10 64 54 118 Xe x -78079.057 10.378 8374.981 0.088 B- -9669.689 16.442 117 916178.680 11.141 - 8 63 55 118 Cs IT -68409.367 12.753 8286.404 0.108 B- -6055# 196# 117 926559.519 13.690 - 6 62 56 118 Ba x -62354# 196# 8228# 2# B- -12794# 358# 117 933060# 210# - 4 61 57 118 La x -49560# 300# 8113# 3# B- * 117 946795# 322# -0 33 76 43 119 Tc x -40371# 503# 8128# 4# B- 12193# 585# 118 956660# 540# - 31 75 44 119 Ru x -52564# 298# 8224# 3# B- 10259# 298# 118 943570# 320# - 29 74 45 119 Rh x -62822.794 9.315 8303.394 0.078 B- 8585.108 12.440 118 932556.952 10.000 - 27 73 46 119 Pd x -71407.902 8.245 8368.964 0.069 B- 7237.863 16.855 118 923340.459 8.851 - 25 72 47 119 Ag -78645.765 14.703 8423.212 0.124 B- 5331.303 35.926 118 915570.293 15.783 - 23 71 48 119 Cd -83977.068 37.695 8461.438 0.317 B- 3722.212 38.088 118 909846.903 40.467 - 21 70 49 119 In -87699.281 7.307 8486.143 0.061 B- 2365.742 7.336 118 905850.944 7.844 - 19 69 50 119 Sn -90065.022 0.725 8499.449 0.006 B- -590.843 7.689 118 903311.216 0.778 - 17 68 51 119 Sb -89474.180 7.701 8487.910 0.065 B- -2293.000 2.000 118 903945.512 8.267 - 15 67 52 119 Te - -87181.180 7.957 8462.066 0.067 B- -3415.650 29.055 118 906407.148 8.541 - 13 66 53 119 I x -83765.530 27.945 8426.789 0.235 B- -4971.117 29.810 118 910074.000 30.000 - 11 65 54 119 Xe x -78794.413 10.378 8378.441 0.087 B- -6489.361 17.379 118 915410.713 11.141 - 9 64 55 119 Cs IT -72305.051 13.940 8317.334 0.117 B- -7714.965 200.754 118 922377.330 14.965 - 7 63 56 119 Ba ep -64590.086 200.269 8245.928 1.683 B- -9801# 361# 118 930659.686 214.997 - 5 62 57 119 La x -54790# 300# 8157# 3# B- -10849# 583# 118 941181# 322# - 3 61 58 119 Ce x -43940# 500# 8059# 4# B- * 118 952828# 537# -0 34 77 43 120 Tc x -35518# 503# 8087# 4# B- 14494# 643# 119 961870# 540# - 32 76 44 120 Ru x -50012# 401# 8201# 3# B- 8803# 446# 119 946310# 430# - 30 75 45 120 Rh x -58815# 196# 8268# 2# B- 11466# 196# 119 936860# 210# - 28 74 46 120 Pd -70280.050 2.291 8357.085 0.019 B- 5371.451 5.024 119 924551.258 2.459 - 26 73 47 120 Ag x -75651.502 4.471 8395.327 0.037 B- 8305.853 5.820 119 918784.767 4.800 - 24 72 48 120 Cd x -83957.354 3.726 8458.023 0.031 B- 1771.015 40.183 119 909868.067 4.000 - 22 71 49 120 In + -85728.369 40.010 8466.262 0.333 B- 5370.000 40.000 119 907966.805 42.952 - 20 70 50 120 Sn -91098.369 0.896 8504.492 0.007 B- -2680.608 7.140 119 902201.873 0.962 - 18 69 51 120 Sb - -88417.761 7.196 8475.635 0.060 B- 950.226 7.811 119 905079.624 7.725 - 16 68 52 120 Te -89367.987 3.085 8477.034 0.026 B- -5615.000 15.000 119 904059.514 3.311 - 14 67 53 120 I - -83752.987 15.314 8423.722 0.128 B- -1580.563 19.343 119 910087.465 16.440 - 12 66 54 120 Xe x -82172.423 11.817 8404.031 0.098 B- -8283.785 15.461 119 911784.270 12.686 - 10 65 55 120 Cs IT -73888.639 9.970 8328.480 0.083 B- -5000.000 300.000 119 920677.279 10.702 - 8 64 56 120 Ba - -68888.639 300.166 8280.294 2.501 B- -11319# 424# 119 926045.000 322.241 - 6 63 57 120 La x -57570# 300# 8179# 2# B- -7970# 583# 119 938196# 322# - 4 62 58 120 Ce x -49600# 500# 8107# 4# B- * 119 946752# 537# -0 35 78 43 121 Tc x -31780# 500# 8056# 4# B- 13267# 641# 120 965883# 537# - 33 77 44 121 Ru x -45047# 401# 8159# 3# B- 11203# 738# 120 951640# 430# - 31 76 45 121 Rh x -56250.128 619.444 8245.239 5.119 B- 9932.201 619.453 120 939613.000 665.000 - 29 75 46 121 Pd x -66182.329 3.353 8320.858 0.028 B- 8220.492 12.565 120 928950.343 3.600 - 27 74 47 121 Ag x -74402.821 12.109 8382.330 0.100 B- 6671.005 12.264 120 920125.282 13.000 - 25 73 48 121 Cd x -81073.826 1.942 8430.996 0.016 B- 4762.148 27.483 120 912963.663 2.085 - 23 72 49 121 In +p -85835.974 27.414 8463.887 0.227 B- 3361.291 27.408 120 907851.286 29.430 - 21 71 50 121 Sn -89197.265 0.955 8485.201 0.008 B- 403.057 2.690 120 904242.792 1.025 - 19 70 51 121 Sb -89600.321 2.582 8482.066 0.021 B- -1054.819 25.767 120 903810.093 2.771 - 17 69 52 121 Te -88545.502 25.850 8466.883 0.214 B- -2294.053 26.047 120 904942.488 27.751 - 15 68 53 121 I -86251.449 5.356 8441.458 0.044 B- -3770.463 11.558 120 907405.255 5.749 - 13 67 54 121 Xe -82480.986 10.243 8403.832 0.085 B- -5378.654 13.979 120 911453.014 10.995 - 11 66 55 121 Cs -77102.331 14.290 8352.914 0.118 B- -6357.495 141.176 120 917227.238 15.340 - 9 65 56 121 Ba - -70744.837 141.898 8293.907 1.173 B- -8555# 332# 120 924052.289 152.333 - 7 64 57 121 La x -62190# 300# 8217# 2# B- -9500# 500# 120 933236# 322# - 5 63 58 121 Ce x -52690# 401# 8132# 3# B- -11268# 641# 120 943435# 430# - 3 62 59 121 Pr -p -41422# 500# 8032# 4# B- * 120 955532# 537# -0 34 78 44 122 Ru x -42150# 500# 8135# 4# B- 9930# 583# 121 954750# 537# - 32 77 45 122 Rh x -52080# 300# 8210# 2# B- 12536# 301# 121 944090# 322# - 30 76 46 122 Pd x -64616.161 19.561 8305.975 0.160 B- 6489.948 42.909 121 930631.694 21.000 - 28 75 47 122 Ag x -71106.108 38.191 8352.758 0.313 B- 9506.265 38.260 121 923664.448 41.000 - 26 74 48 122 Cd -80612.374 2.299 8424.266 0.019 B- 2960.368 50.110 121 913459.052 2.468 - 24 73 49 122 In + -83572.741 50.057 8442.118 0.410 B- 6368.592 50.000 121 910280.966 53.738 - 22 72 50 122 Sn -89941.333 2.395 8487.907 0.020 B- -1605.963 3.384 121 903444.001 2.570 - 20 71 51 122 Sb -88335.370 2.578 8468.331 0.021 B- 1979.089 2.127 121 905168.074 2.768 - 18 70 52 122 Te -90314.460 1.507 8478.140 0.012 B- -4234.000 5.000 121 903043.434 1.617 - 16 69 53 122 I - -86080.460 5.222 8437.023 0.043 B- -725.483 12.277 121 907588.820 5.606 - 14 68 54 122 Xe x -85354.977 11.111 8424.664 0.091 B- -7210.218 35.472 121 908367.658 11.928 - 12 67 55 122 Cs -78144.759 33.687 8359.151 0.276 B- -3535.815 43.769 121 916108.145 36.164 - 10 66 56 122 Ba x -74608.944 27.945 8323.756 0.229 B- -10066# 299# 121 919904.000 30.000 - 8 65 57 122 La x -64543# 298# 8235# 2# B- -6669# 499# 121 930710# 320# - 6 64 58 122 Ce x -57874# 401# 8174# 3# B- -13094# 641# 121 937870# 430# - 4 63 59 122 Pr x -44780# 500# 8060# 4# B- * 121 951927# 537# -0 35 79 44 123 Ru x -37080# 500# 8093# 4# B- 12280# 640# 122 960193# 537# - 33 78 45 123 Rh x -49360# 400# 8186# 3# B- 11070# 885# 122 947010# 429# - 31 77 46 123 Pd x -60429.742 789.441 8270.031 6.418 B- 9118.336 790.039 122 935126.000 847.500 - 29 76 47 123 Ag x -69548.078 30.739 8337.803 0.250 B- 7866.103 30.857 122 925337.062 33.000 - 27 75 48 123 Cd -77414.181 2.696 8395.395 0.022 B- 6016.172 19.893 122 916892.453 2.894 - 25 74 49 123 In -83430.353 19.827 8437.946 0.161 B- 4385.828 19.839 122 910433.826 21.285 - 23 73 50 123 Sn -87816.181 2.416 8467.243 0.020 B- 1407.888 2.662 122 905725.446 2.594 - 21 72 51 123 Sb -89224.069 1.506 8472.328 0.012 B- -51.913 0.066 122 904214.016 1.616 - 19 71 52 123 Te -89172.156 1.505 8465.546 0.012 B- -1228.429 3.445 122 904269.747 1.615 - 17 70 53 123 I -87943.727 3.740 8449.198 0.030 B- -2695.027 9.690 122 905588.520 4.014 - 15 69 54 123 Xe -85248.701 9.537 8420.927 0.078 B- -4205.055 15.414 122 908481.750 10.238 - 13 68 55 123 Cs x -81043.646 12.109 8380.379 0.098 B- -5388.693 17.125 122 912996.062 13.000 - 11 67 56 123 Ba x -75654.953 12.109 8330.208 0.098 B- -7004# 196# 122 918781.062 13.000 - 9 66 57 123 La x -68651# 196# 8267# 2# B- -8365# 357# 122 926300# 210# - 7 65 58 123 Ce x -60286# 298# 8193# 2# B- -10056# 499# 122 935280# 320# - 5 64 59 123 Pr x -50230# 400# 8104# 3# B- * 122 946076# 429# -0 36 80 44 124 Ru x -33960# 600# 8068# 5# B- 10929# 721# 123 963542# 644# - 34 79 45 124 Rh x -44890# 400# 8149# 3# B- 13500# 499# 123 951809# 429# - 32 78 46 124 Pd x -58390# 298# 8252# 2# B- 7810# 390# 123 937316# 320# - 30 77 47 124 Ag x -66200.134 251.503 8308.655 2.028 B- 10501.538 251.521 123 928931.229 270.000 - 28 76 48 124 Cd -76701.672 2.995 8387.035 0.024 B- 4168.529 30.539 123 917657.363 3.215 - 26 75 49 124 In -80870.201 30.572 8414.343 0.247 B- 7363.992 30.576 123 913182.263 32.820 - 24 74 50 124 Sn -88234.193 1.014 8467.421 0.008 B- -613.944 1.513 123 905276.692 1.088 - 22 73 51 124 Sb -n -87620.248 1.507 8456.160 0.012 B- 2905.073 0.132 123 905935.789 1.618 - 20 72 52 124 Te -90525.321 1.502 8473.279 0.012 B- -3159.587 1.859 123 902817.064 1.612 - 18 71 53 124 I - -87365.734 2.390 8441.489 0.019 B- 295.686 2.846 123 906209.021 2.566 - 16 70 54 124 Xe -87661.421 1.793 8437.565 0.014 B- -5930.086 8.495 123 905891.588 1.924 - 14 69 55 124 Cs x -81731.334 8.304 8383.432 0.067 B- -2641.559 15.004 123 912257.798 8.914 - 12 68 56 124 Ba x -79089.775 12.497 8355.820 0.101 B- -8831.165 58.030 123 915093.629 13.416 - 10 67 57 124 La x -70258.610 56.669 8278.292 0.457 B- -5343# 303# 123 924574.275 60.836 - 8 66 58 124 Ce x -64916# 298# 8229# 2# B- -11765# 499# 123 930310# 320# - 6 65 59 124 Pr x -53151# 401# 8128# 3# B- -8626# 643# 123 942940# 430# - 4 64 60 124 Nd x -44525# 503# 8052# 4# B- * 123 952200# 540# -0 35 80 45 125 Rh x -42000# 500# 8126# 4# B- 12120# 640# 124 954911# 537# - 33 79 46 125 Pd x -54120# 400# 8216# 3# B- 10400# 589# 124 941900# 429# - 31 78 47 125 Ag x -64519.932 433.145 8293.314 3.465 B- 8828.163 433.154 124 930735.000 465.000 - 29 77 48 125 Cd -73348.095 2.885 8357.681 0.023 B- 7128.710 27.119 124 921257.577 3.097 - 27 76 49 125 In -80476.805 27.023 8408.452 0.216 B- 5419.571 27.011 124 913604.591 29.010 - 25 75 50 125 Sn -85896.376 1.033 8445.550 0.008 B- 2359.899 2.610 124 907786.442 1.109 - 23 74 51 125 Sb + -88256.274 2.599 8458.170 0.021 B- 766.700 2.121 124 905252.987 2.790 - 21 73 52 125 Te -89022.974 1.502 8458.045 0.012 B- -185.770 0.060 124 904429.900 1.612 - 19 72 53 125 I - -88837.204 1.504 8450.300 0.012 B- -1643.824 2.192 124 904629.333 1.614 - 17 71 54 125 Xe -87193.381 1.836 8430.890 0.015 B- -3105.430 7.831 124 906394.050 1.971 - 15 70 55 125 Cs -84087.950 7.744 8399.788 0.062 B- -4418.985 13.446 124 909727.867 8.313 - 13 69 56 125 Ba -79668.965 10.992 8358.178 0.088 B- -5909.481 27.631 124 914471.843 11.800 - 11 68 57 125 La -73759.484 25.997 8304.643 0.208 B- -7102# 197# 124 920815.932 27.909 - 9 67 58 125 Ce x -66658# 196# 8242# 2# B- -8718# 358# 124 928440# 210# - 7 66 59 125 Pr x -57940# 300# 8166# 2# B- -10341# 500# 124 937799# 322# - 5 65 60 125 Nd x -47599# 401# 8077# 3# B- * 124 948900# 430# -0 36 81 45 126 Rh x -37300# 500# 8088# 4# B- 14560# 640# 125 959957# 537# - 34 80 46 126 Pd x -51860# 400# 8197# 3# B- 8820# 447# 125 944326# 429# - 32 79 47 126 Ag x -60680# 200# 8261# 2# B- 11576# 200# 125 934857# 215# - 30 78 48 126 Cd -72256.802 2.476 8346.747 0.020 B- 5516.106 26.908 125 922429.127 2.658 - 28 77 49 126 In -77772.908 26.921 8384.317 0.214 B- 8242.332 27.078 125 916507.344 28.901 - 26 76 50 126 Sn -86015.240 10.447 8443.523 0.083 B- 378.000 30.000 125 907658.836 11.215 - 24 75 51 126 Sb - -86393.240 31.767 8440.314 0.252 B- 3672.108 31.787 125 907253.036 34.103 - 22 74 52 126 Te -90065.348 1.504 8463.248 0.012 B- -2154.031 3.677 125 903310.866 1.614 - 20 73 53 126 I -87911.318 3.809 8439.944 0.030 B- 1235.644 5.173 125 905623.313 4.089 - 18 72 54 126 Xe -89146.962 3.500 8443.541 0.028 B- -4796.133 10.671 125 904296.794 3.757 - 16 71 55 126 Cs -84350.829 10.401 8399.268 0.083 B- -1680.927 16.259 125 909445.655 11.166 - 14 70 56 126 Ba x -82669.902 12.497 8379.718 0.099 B- -7696.435 91.366 125 911250.204 13.416 - 12 69 57 126 La x -74973.468 90.508 8312.426 0.718 B- -4152.910 94.723 125 919512.667 97.163 - 10 68 58 126 Ce x -70820.558 27.945 8273.257 0.222 B- -10497# 198# 125 923971.000 30.000 - 8 67 59 126 Pr x -60324# 196# 8184# 2# B- -7331# 357# 125 935240# 210# - 6 66 60 126 Nd x -52993# 298# 8119# 2# B- -13643# 582# 125 943110# 320# - 4 65 61 126 Pm x -39350# 500# 8005# 4# B- * 125 957756# 537# -0 37 82 45 127 Rh x -34030# 600# 8062# 5# B- 13150# 781# 126 963467# 644# - 35 81 46 127 Pd x -47180# 500# 8159# 4# B- 11260# 539# 126 949350# 537# - 33 80 47 127 Ag x -58440# 200# 8242# 2# B- 10307# 201# 126 937262# 215# - 31 79 48 127 Cd x -68747.402 12.109 8316.945 0.095 B- 8148.782 24.378 126 926196.624 13.000 - 29 78 49 127 In -76896.184 21.157 8374.949 0.167 B- 6574.619 19.098 126 917448.546 22.713 - 27 77 50 127 Sn -83470.803 10.057 8420.557 0.079 B- 3228.674 10.875 126 910390.401 10.796 - 25 76 51 127 Sb -86699.477 5.126 8439.820 0.040 B- 1582.201 4.913 126 906924.277 5.502 - 23 75 52 127 Te -88281.678 1.514 8446.118 0.012 B- 702.231 3.575 126 905225.714 1.625 - 21 74 53 127 I -88983.909 3.647 8445.487 0.029 B- -662.349 2.044 126 904471.838 3.915 - 19 73 54 127 Xe -88321.560 4.110 8434.111 0.032 B- -2081.406 6.421 126 905182.899 4.412 - 17 72 55 127 Cs -86240.154 5.578 8411.562 0.044 B- -3422.210 12.653 126 907417.381 5.988 - 15 71 56 127 Ba -82817.944 11.357 8378.455 0.089 B- -4921.836 27.740 126 911091.275 12.192 - 13 70 57 127 La -77896.108 26.000 8333.540 0.205 B- -5916.772 38.857 126 916375.084 27.912 - 11 69 58 127 Ce x -71979.336 28.876 8280.791 0.227 B- -7436# 198# 126 922727.000 31.000 - 9 68 59 127 Pr x -64543# 196# 8216# 2# B- -9008# 357# 126 930710# 210# - 7 67 60 127 Nd x -55536# 298# 8139# 2# B- -10749# 499# 126 940380# 320# - 5 66 61 127 Pm x -44786# 401# 8048# 3# B- * 126 951920# 430# -0 36 82 46 128 Pd x -44490# 500# 8138# 4# B- 10130# 583# 127 952238# 537# - 34 81 47 128 Ag x -54620# 300# 8211# 2# B- 12622# 300# 127 941363# 322# - 32 80 48 128 Cd -67241.890 7.244 8303.264 0.057 B- 6904.051 153.554 127 927812.857 7.776 - 30 79 49 128 In -74145.941 153.479 8351.090 1.199 B- 9216.067 153.027 127 920401.053 164.766 - 28 78 50 128 Sn -83362.008 17.660 8416.979 0.138 B- 1268.278 13.796 127 910507.197 18.958 - 26 77 51 128 Sb IT -84630.286 19.119 8420.775 0.149 B- 4363.429 19.117 127 909145.645 20.525 - 24 76 52 128 Te -88993.716 0.866 8448.752 0.007 B- -1254.992 3.714 127 904461.311 0.929 - 22 75 53 128 I -87738.724 3.647 8432.836 0.028 B- 2121.575 3.748 127 905808.600 3.915 - 20 74 54 128 Xe -89860.298 1.061 8443.298 0.008 B- -3928.717 5.380 127 903530.996 1.138 - 18 73 55 128 Cs -85931.581 5.443 8406.493 0.043 B- -553.084 7.525 127 907748.648 5.843 - 16 72 56 128 Ba -85378.497 5.195 8396.060 0.041 B- -6753.066 54.695 127 908342.408 5.577 - 14 71 57 128 La x -78625.431 54.448 8337.190 0.425 B- -3091.513 61.200 127 915592.123 58.452 - 12 70 58 128 Ce x -75533.917 27.945 8306.925 0.218 B- -9203.161 40.859 127 918911.000 30.000 - 10 69 59 128 Pr x -66330.757 29.808 8228.913 0.233 B- -6017# 198# 127 928791.000 32.000 - 8 68 60 128 Nd x -60314# 196# 8176# 2# B- -12529# 357# 127 935250# 210# - 6 67 61 128 Pm x -47786# 298# 8072# 2# B- -9116# 582# 127 948700# 320# - 4 66 62 128 Sm x -38670# 500# 7994# 4# B- * 127 958486# 537# -0 37 83 46 129 Pd x -37610# 600# 8084# 5# B- 14370# 721# 128 959624# 644# - 35 82 47 129 Ag x -51980# 400# 8189# 3# B- 11078# 400# 128 944197# 429# - 33 81 48 129 Cd x -63058.046 16.767 8269.034 0.130 B- 9779.674 16.982 128 932304.399 18.000 - 31 80 49 129 In -72837.720 2.693 8338.780 0.021 B- 7753.183 17.302 128 921805.486 2.891 - 29 79 50 129 Sn -80590.903 17.277 8392.818 0.134 B- 4038.404 27.372 128 913482.102 18.547 - 27 78 51 129 Sb + -84629.307 21.231 8418.058 0.165 B- 2375.500 21.213 128 909146.696 22.792 - 25 77 52 129 Te -87004.807 0.869 8430.409 0.007 B- 1502.318 3.142 128 906596.492 0.933 - 23 76 53 129 I -88507.125 3.168 8435.990 0.025 B- 188.934 3.168 128 904983.687 3.401 - 21 75 54 129 Xe -88696.05896 0.00537 8431.390 0.000 B- -1196.813 4.555 128 904780.85892 0.00576 - 19 74 55 129 Cs -87499.246 4.555 8416.047 0.035 B- -2436.048 10.623 128 906065.690 4.889 - 17 73 56 129 Ba -85063.198 10.577 8391.098 0.082 B- -3738.625 21.639 128 908680.896 11.354 - 15 72 57 129 La -81324.573 21.351 8356.052 0.166 B- -5037.077 35.168 128 912694.475 22.920 - 13 71 58 129 Ce x -76287.496 27.945 8310.940 0.217 B- -6513.938 40.859 128 918102.000 30.000 - 11 70 59 129 Pr x -69773.558 29.808 8254.380 0.231 B- -7459# 204# 128 925095.000 32.000 - 9 69 60 129 Nd ep -62315# 202# 8190# 2# B- -9434# 360# 128 933102# 217# - 7 68 61 129 Pm x -52881# 298# 8111# 2# B- -10881# 582# 128 943230# 320# - 5 67 62 129 Sm x -42000# 500# 8021# 4# B- * 128 954911# 537# -0 36 83 47 130 Ag -nn -45697# 500# 8140# 4# B- 15420# 500# 129 950942# 537# - 34 82 48 130 Cd x -61117.589 22.356 8252.586 0.172 B- 8765.617 44.128 129 934387.566 24.000 - 32 81 49 130 In + -69883.206 38.046 8313.996 0.293 B- 10249.000 38.000 129 924977.288 40.844 - 30 80 50 130 Sn -80132.206 1.873 8386.816 0.014 B- 2153.470 14.113 129 913974.533 2.010 - 28 79 51 130 Sb -82285.676 14.212 8397.363 0.109 B- 5067.273 14.212 129 911662.688 15.257 - 26 78 52 130 Te -87352.949 0.011 8430.324 0.000 B- -416.811 3.168 129 906222.747 0.012 - 24 77 53 130 I -n -86936.138 3.168 8421.100 0.024 B- 2944.325 3.168 129 906670.211 3.401 - 22 76 54 130 Xe -89880.463 0.009 8437.731 0.000 B- -2980.720 8.357 129 903509.349 0.010 - 20 75 55 130 Cs -86899.743 8.357 8408.784 0.064 B- 361.801 8.738 129 906709.283 8.971 - 18 74 56 130 Ba -87261.544 2.553 8405.549 0.020 B- -5634.178 26.071 129 906320.874 2.741 - 16 73 57 130 La x -81627.366 25.946 8356.191 0.200 B- -2204.461 38.133 129 912369.413 27.854 - 14 72 58 130 Ce x -79422.905 27.945 8333.216 0.215 B- -8247.448 70.085 129 914736.000 30.000 - 12 71 59 130 Pr x -71175.457 64.273 8263.756 0.494 B- -4579.225 70.085 129 923590.000 69.000 - 10 70 60 130 Nd x -66596.232 27.945 8222.513 0.215 B- -11200# 198# 129 928506.000 30.000 - 8 69 61 130 Pm x -55396# 196# 8130# 2# B- -7890# 446# 129 940530# 210# - 6 68 62 130 Sm x -47506# 401# 8064# 3# B- -13823# 641# 129 949000# 430# - 4 67 63 130 Eu -p -33683# 500# 7951# 4# B- * 129 963840# 537# -0 37 84 47 131 Ag x -40380# 500# 8099# 4# B- 14839# 511# 130 956650# 537# - 35 83 48 131 Cd x -55218.965 102.464 8206.175 0.782 B- 12806.066 102.500 130 940720.000 110.000 - 33 82 49 131 In x -68025.030 2.701 8297.959 0.021 B- 9239.541 4.518 130 926972.122 2.900 - 31 81 50 131 Sn -77264.571 3.621 8362.517 0.028 B- 4716.830 3.962 130 917053.066 3.887 - 29 80 51 131 Sb -81981.401 2.084 8392.552 0.016 B- 3229.611 2.085 130 911989.341 2.236 - 27 79 52 131 Te -n -85211.012 0.061 8411.233 0.001 B- 2231.699 0.608 130 908522.211 0.065 - 25 78 53 131 I + -87442.710 0.605 8422.297 0.005 B- 970.848 0.605 130 906126.384 0.649 - 23 77 54 131 Xe -88413.558 0.009 8423.736 0.000 B- -354.772 4.974 130 905084.136 0.009 - 21 76 55 131 Cs -88058.786 4.974 8415.056 0.038 B- -1375.055 5.279 130 905464.999 5.340 - 19 75 56 131 Ba -86683.731 2.569 8398.587 0.020 B- -2914.475 28.063 130 906941.181 2.757 - 17 74 57 131 La x -83769.256 27.945 8370.367 0.213 B- -4060.816 43.092 130 910070.000 30.000 - 15 73 58 131 Ce -79708.440 32.802 8333.396 0.250 B- -5407.784 55.446 130 914429.465 35.214 - 13 72 59 131 Pr -74300.656 46.995 8286.143 0.359 B- -6532.623 53.081 130 920234.960 50.451 - 11 71 60 131 Nd -67768.033 27.517 8230.304 0.210 B- -8108# 202# 130 927248.020 29.541 - 9 70 61 131 Pm x -59660# 200# 8162# 2# B- -9527# 448# 130 935952# 215# - 7 69 62 131 Sm x -50133# 401# 8084# 3# B- -10863# 566# 130 946180# 430# - 5 68 63 131 Eu -p -39270# 401# 7995# 3# B- * 130 957842# 430# -0 38 85 47 132 Ag x -33790# 500# 8049# 4# B- 16473# 537# 131 963725# 537# - 36 84 48 132 Cd x -50263# 196# 8168# 1# B- 12148# 205# 131 946040# 210# - 34 83 49 132 In + -62411.542 60.033 8253.715 0.455 B- 14135.000 60.000 131 932998.449 64.447 - 32 82 50 132 Sn -76546.542 1.976 8354.872 0.015 B- 3088.729 3.161 131 917823.902 2.121 - 30 81 51 132 Sb -79635.271 2.467 8372.344 0.019 B- 5552.915 4.271 131 914508.015 2.648 - 28 80 52 132 Te -85188.186 3.486 8408.485 0.026 B- 515.304 3.483 131 908546.716 3.742 - 26 79 53 132 I -85703.490 4.065 8406.462 0.031 B- 3575.472 4.065 131 907993.514 4.364 - 24 78 54 132 Xe -89278.96179 0.00515 8427.622 0.000 B- -2126.280 1.036 131 904155.08697 0.00553 - 22 77 55 132 Cs -87152.681 1.036 8405.587 0.008 B- 1282.336 1.478 131 906437.743 1.112 - 20 76 56 132 Ba -88435.017 1.054 8409.375 0.008 B- -4711.367 36.354 131 905061.098 1.131 - 18 75 57 132 La -83723.650 36.359 8367.756 0.275 B- -1252.754 41.718 131 910118.959 39.032 - 16 74 58 132 Ce -82470.896 20.442 8352.338 0.155 B- -7243.440 35.380 131 911463.846 21.945 - 14 73 59 132 Pr x -75227.456 28.876 8291.537 0.219 B- -3801.648 37.679 131 919240.000 31.000 - 12 72 60 132 Nd x -71425.807 24.205 8256.810 0.183 B- -9798# 151# 131 923321.237 25.985 - 10 71 61 132 Pm x -61628# 149# 8177# 1# B- -6548# 333# 131 933840# 160# - 8 70 62 132 Sm x -55079# 298# 8121# 2# B- -12879# 499# 131 940870# 320# - 6 69 63 132 Eu x -42200# 400# 8018# 3# B- * 131 954696# 429# -0 37 85 48 133 Cd x -43920# 298# 8119# 2# B- 13544# 357# 132 952850# 320# - 35 84 49 133 In x -57464# 196# 8215# 1# B- 13410# 196# 132 938310# 210# - 33 83 50 133 Sn -70873.880 1.904 8310.088 0.014 B- 8049.623 3.662 132 923913.756 2.044 - 31 82 51 133 Sb -78923.503 3.128 8364.729 0.024 B- 4013.619 3.518 132 915272.130 3.357 - 29 81 52 133 Te -82937.122 2.066 8389.025 0.016 B- 2921.139 6.751 132 910963.332 2.218 - 27 80 53 133 I ++ -85858.260 6.427 8405.106 0.048 B- 1785.311 6.861 132 907827.361 6.900 - 25 79 54 133 Xe + -87643.571 2.400 8412.647 0.018 B- 427.360 2.400 132 905910.750 2.576 - 23 78 55 133 Cs -88070.931 0.008 8409.978 0.000 B- -517.319 0.992 132 905451.961 0.008 - 21 77 56 133 Ba -87553.613 0.992 8400.206 0.007 B- -2059.230 27.962 132 906007.325 1.065 - 19 76 57 133 La x -85494.383 27.945 8378.841 0.210 B- -3076.168 32.379 132 908218.000 30.000 - 17 75 58 133 Ce x -82418.214 16.354 8349.829 0.123 B- -4480.634 20.583 132 911520.402 17.557 - 15 74 59 133 Pr x -77937.581 12.497 8310.258 0.094 B- -5605.208 48.222 132 916330.561 13.416 - 13 73 60 133 Nd x -72332.372 46.575 8262.231 0.350 B- -6924.726 68.552 132 922348.000 50.000 - 11 72 61 133 Pm x -65407.646 50.301 8204.283 0.378 B- -8177# 302# 132 929782.000 54.000 - 9 71 62 133 Sm x -57231# 298# 8137# 2# B- -9995# 422# 132 938560# 320# - 7 70 63 133 Eu x -47236# 298# 8056# 2# B- -11376# 582# 132 949290# 320# - 5 69 64 133 Gd x -35860# 500# 7964# 4# B- * 132 961503# 537# -0 38 86 48 134 Cd x -38920# 400# 8082# 3# B- 12741# 499# 133 958218# 429# - 36 85 49 134 In x -51661# 298# 8171# 2# B- 14773# 298# 133 944540# 320# - 34 84 50 134 Sn x -66433.748 3.167 8275.171 0.024 B- 7586.794 3.597 133 928680.433 3.400 - 32 83 51 134 Sb x -74020.542 1.705 8325.950 0.013 B- 8513.200 3.233 133 920535.675 1.830 - 30 82 52 134 Te -82533.741 2.746 8383.643 0.020 B- 1509.687 4.933 133 911396.379 2.948 - 28 81 53 134 I -84043.429 4.857 8389.071 0.036 B- 4082.393 4.857 133 909775.663 5.213 - 26 80 54 134 Xe -88125.822 0.009 8413.699 0.000 B- -1234.667 0.018 133 905393.033 0.010 - 24 79 55 134 Cs -86891.154 0.016 8398.646 0.000 B- 2058.699 0.304 133 906718.503 0.017 - 22 78 56 134 Ba -88949.853 0.304 8408.171 0.002 B- -3731.204 19.932 133 904508.399 0.326 - 20 77 57 134 La x -85218.650 19.930 8374.488 0.149 B- -385.760 28.510 133 908514.011 21.395 - 18 76 58 134 Ce x -84832.889 20.387 8365.771 0.152 B- -6304.898 28.781 133 908928.142 21.886 - 16 75 59 134 Pr x -78527.991 20.316 8312.881 0.152 B- -2881.559 23.503 133 915696.729 21.810 - 14 74 60 134 Nd x -75646.432 11.817 8285.538 0.088 B- -8907.681 58.949 133 918790.210 12.686 - 12 73 61 134 Pm x -66738.751 57.753 8213.225 0.431 B- -5363# 204# 133 928353.000 62.000 - 10 72 62 134 Sm x -61376# 196# 8167# 1# B- -11448# 357# 133 934110# 210# - 8 71 63 134 Eu x -49928# 298# 8076# 2# B- -8626# 499# 133 946400# 320# - 6 70 64 134 Gd x -41302# 401# 8006# 3# B- * 133 955660# 430# -0 37 86 49 135 In x -46528# 401# 8132# 3# B- 14104# 401# 134 950050# 430# - 35 85 50 135 Sn x -60632.244 3.074 8230.687 0.023 B- 9058.079 4.052 134 934908.605 3.300 - 33 84 51 135 Sb -69690.323 2.640 8291.989 0.020 B- 8038.457 3.152 134 925184.357 2.834 - 31 83 52 135 Te -77728.780 1.722 8345.738 0.013 B- 6050.366 2.686 134 916554.718 1.848 - 29 82 53 135 I -83779.145 2.061 8384.760 0.015 B- 2634.005 3.868 134 910059.382 2.212 - 27 81 54 135 Xe -86413.151 3.720 8398.476 0.028 B- 1168.492 3.675 134 907231.661 3.993 - 25 80 55 135 Cs -87581.643 0.992 8401.336 0.007 B- 268.855 1.038 134 905977.234 1.064 - 23 79 56 135 Ba -87850.498 0.306 8397.533 0.002 B- -1207.181 9.430 134 905688.606 0.328 - 21 78 57 135 La -86643.317 9.434 8382.795 0.070 B- -2027.146 4.610 134 906984.568 10.127 - 19 77 58 135 Ce -84616.171 10.267 8361.984 0.076 B- -3680.310 15.655 134 909160.799 11.022 - 17 76 59 135 Pr x -80935.861 11.817 8328.928 0.088 B- -4722.252 22.484 134 913111.774 12.686 - 15 75 60 135 Nd x -76213.609 19.128 8288.153 0.142 B- -6161.534 77.838 134 918181.320 20.534 - 13 74 61 135 Pm x -70052.075 75.451 8236.717 0.559 B- -7194.860 172.054 134 924796.000 81.000 - 11 73 62 135 Sm x -62857.215 154.628 8177.626 1.145 B- -8709# 249# 134 932520.000 166.000 - 9 72 63 135 Eu x -54148# 196# 8107# 1# B- -9757# 445# 134 941870# 210# - 7 71 64 135 Gd x -44390# 400# 8029# 3# B- -11565# 566# 134 952345# 429# - 5 70 65 135 Tb -p -32825# 401# 7938# 3# B- * 134 964760# 430# -0 38 87 49 136 In x -40510# 400# 8087# 3# B- 15389# 499# 135 956511# 429# - 36 86 50 136 Sn x -55899# 298# 8195# 2# B- 8608# 298# 135 939990# 320# - 34 85 51 136 Sb -64506.880 5.830 8252.252 0.043 B- 9918.389 6.260 135 930749.011 6.258 - 32 84 52 136 Te -74425.269 2.281 8319.429 0.017 B- 5119.945 14.188 135 920101.182 2.448 - 30 83 53 136 I -79545.214 14.188 8351.323 0.104 B- 6883.945 14.188 135 914604.695 15.231 - 28 82 54 136 Xe -86429.159 0.007 8396.188 0.000 B- -90.462 1.882 135 907214.476 0.007 - 26 81 55 136 Cs + -86338.697 1.882 8389.770 0.014 B- 2548.224 1.857 135 907311.590 2.020 - 24 80 56 136 Ba -88886.921 0.306 8402.755 0.002 B- -2849.443 53.172 135 904575.959 0.328 - 22 79 57 136 La x -86037.479 53.171 8376.050 0.391 B- 470.893 53.173 135 907634.962 57.081 - 20 78 58 136 Ce -86508.372 0.408 8373.760 0.003 B- -5168.017 11.457 135 907129.438 0.438 - 18 77 59 136 Pr -81340.355 11.455 8330.008 0.084 B- -2141.068 16.458 135 912677.532 12.297 - 16 76 60 136 Nd x -79199.287 11.817 8308.512 0.087 B- -8029.371 70.076 135 914976.064 12.686 - 14 75 61 136 Pm x -71169.915 69.073 8243.720 0.508 B- -4359.026 70.194 135 923595.949 74.152 - 12 74 62 136 Sm x -66810.890 12.497 8205.916 0.092 B- -10567# 196# 135 928275.555 13.416 - 10 73 63 136 Eu x -56244# 196# 8122# 1# B- -7154# 357# 135 939620# 210# - 8 72 64 136 Gd x -49090# 298# 8064# 2# B- -12960# 582# 135 947300# 320# - 6 71 65 136 Tb x -36130# 500# 7963# 4# B- * 135 961213# 537# -0 39 88 49 137 In x -35040# 500# 8047# 4# B- 14748# 641# 136 962383# 537# - 37 87 50 137 Sn x -49788# 401# 8149# 3# B- 10272# 404# 136 946550# 430# - 35 86 51 137 Sb x -60060.384 52.164 8218.476 0.381 B- 9243.369 52.206 136 935522.522 56.000 - 33 85 52 137 Te -69303.753 2.100 8280.235 0.015 B- 7052.506 8.643 136 925599.357 2.254 - 31 84 53 137 I p-2n -76356.258 8.383 8326.002 0.061 B- 6027.145 8.384 136 918028.180 9.000 - 29 83 54 137 Xe -n -82383.404 0.103 8364.286 0.001 B- 4162.203 0.373 136 911557.773 0.111 - 27 82 55 137 Cs + -86545.606 0.358 8388.956 0.003 B- 1175.629 0.172 136 907089.464 0.384 - 25 81 56 137 Ba -87721.235 0.314 8391.827 0.002 B- -580.547 1.632 136 905827.375 0.337 - 23 80 57 137 La + -87140.688 1.659 8381.879 0.012 B- -1222.100 1.600 136 906450.618 1.780 - 21 79 58 137 Ce -85918.588 0.437 8367.248 0.003 B- -2716.895 8.133 136 907762.596 0.469 - 19 78 59 137 Pr -83201.693 8.137 8341.706 0.059 B- -3617.126 14.282 136 910679.304 8.735 - 17 77 60 137 Nd -79584.567 11.737 8309.593 0.086 B- -5511.719 17.545 136 914562.448 12.600 - 15 76 61 137 Pm x -74072.848 13.041 8263.651 0.095 B- -6046.323 44.355 136 920479.522 14.000 - 13 75 62 137 Sm -68026.525 42.395 8213.806 0.309 B- -7880.630 42.620 136 926970.517 45.512 - 11 74 63 137 Eu x -60145.895 4.378 8150.573 0.032 B- -8932# 298# 136 935430.722 4.700 - 9 73 64 137 Gd x -51214# 298# 8080# 2# B- -10246# 499# 136 945020# 320# - 7 72 65 137 Tb x -40967# 401# 7999# 3# B- * 136 956020# 430# -0 38 88 50 138 Sn x -44861# 503# 8113# 4# B- 9360# 1177# 137 951840# 540# - 36 87 51 138 Sb x -54220.403 1064.232 8175.091 7.712 B- 11475.582 1064.239 137 941792.000 1142.500 - 34 86 52 138 Te -65695.985 3.787 8252.578 0.027 B- 6283.914 7.063 137 929472.454 4.065 - 32 85 53 138 I x -71979.900 5.962 8292.444 0.043 B- 7992.334 6.588 137 922726.394 6.400 - 30 84 54 138 Xe -79972.233 2.804 8344.690 0.020 B- 2914.704 9.579 137 914146.271 3.010 - 28 83 55 138 Cs -82886.937 9.159 8360.142 0.066 B- 5374.700 9.159 137 911017.207 9.832 - 26 82 56 138 Ba -88261.638 0.317 8393.420 0.002 B- -1742.458 3.191 137 905247.229 0.339 - 24 81 57 138 La -86519.180 3.188 8375.125 0.023 B- 1051.742 4.038 137 907117.834 3.422 - 22 80 58 138 Ce -87570.922 4.931 8377.077 0.036 B- -4437.000 10.000 137 905988.743 5.293 - 20 79 59 138 Pr - -83133.922 11.150 8339.255 0.081 B- -1115.612 16.090 137 910752.059 11.969 - 18 78 60 138 Nd -82018.310 11.601 8325.502 0.084 B- -7077.827 28.756 137 911949.717 12.454 - 16 77 61 138 Pm -74940.483 27.739 8268.544 0.201 B- -3442.721 30.151 137 919548.077 29.778 - 14 76 62 138 Sm x -71497.762 11.817 8237.928 0.086 B- -9748.093 30.341 137 923243.990 12.686 - 12 75 63 138 Eu x -61749.669 27.945 8161.620 0.202 B- -5949# 198# 137 933709.000 30.000 - 10 74 64 138 Gd x -55800# 196# 8113# 1# B- -12132# 357# 137 940096# 210# - 8 73 65 138 Tb x -43668# 298# 8019# 2# B- -8737# 585# 137 953120# 320# - 6 72 66 138 Dy x -34931# 503# 7950# 4# B- * 137 962500# 540# -0 39 89 50 139 Sn x -38440# 500# 8066# 4# B- 11348# 641# 138 958733# 537# - 37 88 51 139 Sb x -49788# 401# 8142# 3# B- 10417# 401# 138 946550# 430# - 35 87 52 139 Te x -60205.072 3.540 8211.771 0.025 B- 8265.882 5.345 138 935367.193 3.800 - 33 86 53 139 I x -68470.954 4.005 8265.609 0.029 B- 7173.622 4.542 138 926493.403 4.300 - 31 85 54 139 Xe x -75644.576 2.142 8311.590 0.015 B- 5056.346 3.801 138 918792.203 2.300 - 29 84 55 139 Cs + -80700.921 3.140 8342.338 0.023 B- 4212.829 3.123 138 913363.992 3.370 - 27 83 56 139 Ba -84913.751 0.319 8367.017 0.002 B- 2312.461 2.013 138 908841.334 0.342 - 25 82 57 139 La -87226.212 2.009 8378.025 0.014 B- -278.350 6.953 138 906358.804 2.156 - 23 81 58 139 Ce -86947.862 7.230 8370.395 0.052 B- -2129.064 2.996 138 906657.625 7.761 - 21 80 59 139 Pr -84818.798 7.809 8349.449 0.056 B- -2804.856 28.033 138 908943.270 8.383 - 19 79 60 139 Nd -82013.942 27.600 8323.642 0.199 B- -4513.460 25.927 138 911954.407 29.630 - 17 78 61 139 Pm -77500.481 13.593 8285.543 0.098 B- -5120.263 17.414 138 916799.806 14.592 - 15 77 62 139 Sm x -72380.219 10.884 8243.078 0.078 B- -6982.177 17.071 138 922296.634 11.684 - 13 76 63 139 Eu x -65398.042 13.151 8187.218 0.095 B- -7767# 196# 138 929792.310 14.117 - 11 75 64 139 Gd x -57632# 196# 8126# 1# B- -9501# 357# 138 938130# 210# - 9 74 65 139 Tb x -48130# 298# 8052# 2# B- -10489# 585# 138 948330# 320# - 7 73 66 139 Dy x -37642# 503# 7971# 4# B- * 138 959590# 540# -0 38 89 51 140 Sb x -43939# 596# 8100# 4# B- 12638# 599# 139 952830# 640# - 36 88 52 140 Te x -56576.228 62.410 8184.847 0.446 B- 7029.985 63.574 139 939262.917 67.000 - 34 87 53 140 I x -63606.213 12.109 8229.473 0.086 B- 9380.238 12.331 139 931715.917 13.000 - 32 86 54 140 Xe x -72986.451 2.329 8290.887 0.017 B- 4063.654 8.525 139 921645.817 2.500 - 30 85 55 140 Cs -77050.105 8.201 8314.325 0.059 B- 6219.249 9.882 139 917283.305 8.804 - 28 84 56 140 Ba -83269.354 7.933 8353.160 0.057 B- 1046.517 7.993 139 910606.666 8.516 - 26 83 57 140 La -84315.871 2.009 8355.047 0.014 B- 3760.218 1.727 139 909483.184 2.156 - 24 82 58 140 Ce -88076.089 1.596 8376.317 0.011 B- -3388.000 6.000 139 905446.424 1.713 - 22 81 59 140 Pr - -84688.089 6.209 8346.529 0.044 B- -429.177 7.101 139 909083.592 6.665 - 20 80 60 140 Nd x -84258.912 3.447 8337.875 0.025 B- -6045.200 24.000 139 909544.332 3.700 - 18 79 61 140 Pm - -78213.712 24.246 8289.107 0.173 B- -2757.777 27.277 139 916034.122 26.029 - 16 78 62 140 Sm x -75455.935 12.497 8263.820 0.089 B- -8470.000 50.000 139 918994.717 13.416 - 14 77 63 140 Eu - -66985.935 51.538 8197.732 0.368 B- -5203.664 58.627 139 928087.637 55.328 - 12 76 64 140 Gd x -61782.271 27.945 8154.975 0.200 B- -11300.000 800.000 139 933674.000 30.000 - 10 75 65 140 Tb - -50482.271 800.488 8068.672 5.718 B- -7652# 895# 139 945805.049 859.359 - 8 74 66 140 Dy x -42830# 401# 8008# 3# B- -13571# 643# 139 954020# 430# - 6 73 67 140 Ho -p -29259# 503# 7906# 4# B- * 139 968589# 540# -0 39 90 51 141 Sb x -39110# 500# 8066# 4# B- 11377# 641# 140 958014# 537# - 37 89 52 141 Te x -50487# 401# 8141# 3# B- 9440# 401# 140 945800# 430# - 35 88 53 141 I x -59926.657 15.835 8202.255 0.112 B- 8270.642 16.097 140 935666.084 17.000 - 33 87 54 141 Xe x -68197.299 2.888 8255.364 0.020 B- 6280.224 9.638 140 926787.184 3.100 - 31 86 55 141 Cs -74477.523 9.195 8294.356 0.065 B- 5255.103 9.617 140 920045.086 9.871 - 29 85 56 141 Ba -79732.626 5.319 8326.078 0.038 B- 3199.010 6.600 140 914403.500 5.710 - 27 84 57 141 La -82931.636 4.219 8343.217 0.030 B- 2501.280 3.928 140 910969.222 4.528 - 25 83 58 141 Ce -85432.916 1.597 8355.408 0.011 B- 582.728 1.202 140 908283.987 1.714 - 23 82 59 141 Pr -86015.644 1.665 8353.992 0.012 B- -1823.014 2.809 140 907658.403 1.787 - 21 81 60 141 Nd - -84192.630 3.265 8335.515 0.023 B- -3669.709 14.349 140 909615.488 3.505 - 19 80 61 141 Pm x -80522.921 13.972 8303.940 0.099 B- -4589.012 16.375 140 913555.084 15.000 - 17 79 62 141 Sm -75933.909 8.539 8265.845 0.061 B- -6008.280 14.285 140 918481.591 9.167 - 15 78 63 141 Eu -69925.629 12.639 8217.684 0.090 B- -6701.405 23.456 140 924931.745 13.568 - 13 77 64 141 Gd x -63224.224 19.760 8164.608 0.140 B- -8683.387 107.098 140 932126.000 21.213 - 11 76 65 141 Tb x -54540.837 105.259 8097.475 0.747 B- -9158# 316# 140 941448.000 113.000 - 9 75 66 141 Dy x -45382# 298# 8027# 2# B- -11018# 499# 140 951280# 320# - 7 74 67 141 Ho -p -34364# 401# 7943# 3# B- * 140 963108# 430# -0 38 90 52 142 Te x -46370# 503# 8111# 4# B- 8400# 627# 141 950220# 540# - 36 89 53 142 I x -54769.984 374.461 8165.019 2.637 B- 10459.655 374.470 141 941202.000 402.000 - 34 88 54 142 Xe x -65229.639 2.701 8233.169 0.019 B- 5284.911 7.565 141 929973.098 2.900 - 32 87 55 142 Cs -70514.550 7.067 8264.877 0.050 B- 7327.714 8.363 141 924299.512 7.586 - 30 86 56 142 Ba -77842.264 5.920 8310.971 0.042 B- 2181.963 8.391 141 916432.888 6.355 - 28 85 57 142 La -80024.227 6.309 8320.828 0.044 B- 4508.961 5.845 141 914090.454 6.773 - 26 84 58 142 Ce -84533.188 2.509 8347.071 0.018 B- -745.712 2.500 141 909249.884 2.693 - 24 83 59 142 Pr -83787.476 1.665 8336.310 0.012 B- 2162.505 1.416 141 910050.440 1.786 - 22 82 60 142 Nd -85949.980 1.368 8346.030 0.010 B- -4807.936 23.629 141 907728.895 1.468 - 20 81 61 142 Pm -81142.044 23.597 8306.662 0.166 B- -2155.574 23.752 141 912890.428 25.332 - 18 80 62 142 Sm -78986.470 3.079 8285.972 0.022 B- -7673.000 30.000 141 915204.532 3.305 - 16 79 63 142 Eu - -71313.470 30.158 8226.427 0.212 B- -4353.955 41.114 141 923441.836 32.375 - 14 78 64 142 Gd x -66959.515 27.945 8190.256 0.197 B- -10400.000 700.000 141 928116.000 30.000 - 12 77 65 142 Tb - -56559.515 700.558 8111.507 4.934 B- -6440# 200# 141 939280.859 752.079 - 10 76 66 142 Dy - -50120# 729# 8061# 5# B- -12869# 831# 141 946194# 782# - 8 75 67 142 Ho x -37250# 401# 7965# 3# B- -9221# 641# 141 960010# 430# - 6 74 68 142 Er x -28030# 500# 7894# 4# B- * 141 969909# 537# -0 39 91 52 143 Te x -40278# 503# 8068# 4# B- 10353# 541# 142 956760# 540# - 37 90 53 143 I x -50630# 200# 8135# 1# B- 9572# 200# 142 945646# 215# - 35 89 54 143 Xe x -60202.873 4.657 8196.885 0.033 B- 7472.636 8.891 142 935369.553 5.000 - 33 88 55 143 Cs -67675.509 7.573 8243.670 0.053 B- 6261.688 9.730 142 927347.348 8.130 - 31 87 56 143 Ba -73937.197 6.756 8281.987 0.047 B- 4234.318 9.969 142 920625.150 7.253 - 29 86 57 143 La -78171.515 7.330 8306.127 0.051 B- 3435.156 7.595 142 916079.422 7.869 - 27 85 58 143 Ce -81606.671 2.508 8324.678 0.018 B- 1461.575 1.866 142 912391.630 2.692 - 25 84 59 143 Pr -83068.246 1.897 8329.428 0.013 B- 933.988 1.368 142 910822.564 2.037 - 23 83 60 143 Nd -84002.234 1.367 8330.488 0.010 B- -1041.583 2.682 142 909819.887 1.467 - 21 82 61 143 Pm -82960.651 2.996 8317.733 0.021 B- -3443.499 3.560 142 910938.073 3.216 - 19 81 62 143 Sm -79517.152 2.804 8288.182 0.020 B- -5275.851 11.338 142 914634.821 3.010 - 17 80 63 143 Eu x -74241.300 10.986 8245.817 0.077 B- -6010.000 200.000 142 920298.681 11.793 - 15 79 64 143 Gd - -68231.300 200.301 8198.318 1.401 B- -7812.117 206.750 142 926750.682 215.032 - 13 78 65 143 Tb x -60419.183 51.232 8138.217 0.358 B- -8250.242 52.866 142 935137.335 55.000 - 11 77 66 143 Dy x -52168.941 13.041 8075.052 0.091 B- -10121# 298# 142 943994.335 14.000 - 9 76 67 143 Ho x -42048# 298# 7999# 2# B- -10788# 499# 142 954860# 320# - 7 75 68 143 Er x -31260# 400# 7918# 3# B- * 142 966441# 429# -0 38 91 53 144 I x -45280# 401# 8098# 3# B- 11592# 401# 143 951390# 430# - 36 90 54 144 Xe x -56872.293 5.310 8172.884 0.037 B- 6399.060 20.820 143 938945.079 5.700 - 34 89 55 144 Cs -63271.353 20.132 8211.889 0.140 B- 8495.768 20.416 143 932075.404 21.612 - 32 88 56 144 Ba -71767.121 7.136 8265.454 0.050 B- 3082.530 14.774 143 922954.821 7.661 - 30 87 57 144 La x -74849.652 12.937 8281.428 0.090 B- 5582.219 13.254 143 919645.589 13.888 - 28 86 58 144 Ce + -80431.870 2.885 8314.760 0.020 B- 318.646 0.832 143 913652.830 3.096 - 26 85 59 144 Pr + -80750.517 2.762 8311.540 0.019 B- 2997.440 2.400 143 913310.750 2.965 - 24 84 60 144 Nd -83747.957 1.367 8326.922 0.009 B- -2331.863 2.646 143 910092.865 1.467 - 22 83 61 144 Pm -81416.093 2.964 8305.296 0.021 B- 549.442 2.668 143 912596.224 3.181 - 20 82 62 144 Sm -81965.535 1.554 8303.679 0.011 B- -6346.402 10.814 143 912006.373 1.668 - 18 81 63 144 Eu -75619.133 10.789 8254.173 0.075 B- -3859.630 29.955 143 918819.517 11.582 - 16 80 64 144 Gd x -71759.504 27.945 8221.937 0.194 B- -9391.323 39.520 143 922963.000 30.000 - 14 79 65 144 Tb x -62368.181 27.945 8151.287 0.194 B- -5798.098 28.851 143 933045.000 30.000 - 12 78 66 144 Dy x -56570.083 7.173 8105.589 0.050 B- -11960.569 11.104 143 939269.514 7.700 - 10 77 67 144 Ho x -44609.513 8.477 8017.097 0.059 B- -8002# 196# 143 952109.714 9.100 - 8 76 68 144 Er x -36608# 196# 7956# 1# B- -14349# 445# 143 960700# 210# - 6 75 69 144 Tm -p -22259# 400# 7851# 3# B- * 143 976104# 429# -0 39 92 53 145 I x -40939# 503# 8068# 3# B- 10554# 503# 144 956050# 540# - 37 91 54 145 Xe x -51493.329 11.178 8135.087 0.077 B- 8561.086 14.393 144 944719.634 12.000 - 35 90 55 145 Cs -60054.415 9.067 8188.733 0.063 B- 7461.761 12.412 144 935528.930 9.733 - 33 89 56 145 Ba x -67516.176 8.477 8234.798 0.058 B- 5319.141 14.912 144 927518.400 9.100 - 31 88 57 145 La -72835.317 12.269 8266.087 0.085 B- 4231.705 35.300 144 921808.066 13.170 - 29 87 58 145 Ce -77067.022 33.902 8289.875 0.234 B- 2558.918 33.635 144 917265.144 36.395 - 27 86 59 145 Pr -79625.940 7.169 8302.127 0.049 B- 1806.012 7.037 144 914518.033 7.696 - 25 85 60 145 Nd -81431.951 1.384 8309.187 0.010 B- -164.478 2.536 144 912579.199 1.485 - 23 84 61 145 Pm -81267.474 2.859 8302.657 0.020 B- -616.156 2.539 144 912755.773 3.068 - 21 83 62 145 Sm -80651.318 1.578 8293.013 0.011 B- -2659.810 2.723 144 913417.244 1.694 - 19 82 63 145 Eu -77991.507 3.106 8269.274 0.021 B- -5065.187 19.953 144 916272.668 3.334 - 17 81 64 145 Gd -72926.320 19.709 8228.946 0.136 B- -6537.909 108.066 144 921710.370 21.158 - 15 80 65 145 Tb -66388.411 109.174 8178.461 0.753 B- -8145.812 109.369 144 928729.105 117.203 - 13 79 66 145 Dy x -58242.599 6.520 8116.888 0.045 B- -9122.493 9.902 144 937473.994 7.000 - 11 78 67 145 Ho x -49120.105 7.452 8048.578 0.051 B- -9880# 200# 144 947267.394 8.000 - 9 77 68 145 Er x -39240# 200# 7975# 1# B- -11657# 280# 144 957874# 215# - 7 76 69 145 Tm -p -27583# 196# 7889# 1# B- * 144 970389# 210# -0 38 92 54 146 Xe x -47954.943 24.219 8110.415 0.166 B- 7355.429 24.391 145 948518.248 26.000 - 36 91 55 146 Cs x -55310.372 2.893 8155.436 0.020 B- 9636.714 21.063 145 940621.870 3.106 - 34 90 56 146 Ba -64947.086 20.863 8216.082 0.143 B- 4103.197 33.503 145 930276.431 22.397 - 32 89 57 146 La -69050.283 33.616 8238.828 0.230 B- 6585.107 34.456 145 925871.468 36.088 - 30 88 58 146 Ce -75635.389 16.306 8278.573 0.112 B- 1045.616 32.519 145 918802.065 17.504 - 28 87 59 146 Pr -76681.006 34.816 8280.376 0.238 B- 4244.861 34.830 145 917679.549 37.376 - 26 86 60 146 Nd -80925.867 1.386 8304.092 0.009 B- -1471.558 4.119 145 913122.503 1.488 - 24 85 61 146 Pm + -79454.309 4.308 8288.654 0.030 B- 1542.000 3.000 145 914702.286 4.624 - 22 84 62 146 Sm -80996.309 3.092 8293.857 0.021 B- -3878.768 5.869 145 913046.881 3.319 - 20 83 63 146 Eu -77117.541 6.026 8261.932 0.041 B- -1031.758 7.076 145 917210.909 6.468 - 18 82 64 146 Gd -76085.783 4.108 8249.506 0.028 B- -8322.173 44.749 145 918318.548 4.409 - 16 81 65 146 Tb -67763.610 44.862 8187.146 0.307 B- -5208.691 45.160 145 927252.768 48.161 - 14 80 66 146 Dy -62554.918 6.695 8146.112 0.046 B- -11316.699 9.392 145 932844.529 7.187 - 12 79 67 146 Ho -51238.219 6.587 8063.242 0.045 B- -6916.206 9.399 145 944993.506 7.071 - 10 78 68 146 Er -44322.012 6.705 8010.512 0.046 B- -13267# 200# 145 952418.359 7.197 - 8 77 69 146 Tm -p -31055# 200# 7914# 1# B- * 145 966661# 215# -0 39 93 54 147 Xe x -42360# 200# 8072# 1# B- 9560# 200# 146 954525# 215# - 37 92 55 147 Cs x -51920.064 8.383 8131.800 0.057 B- 8343.965 21.454 146 944261.515 9.000 - 35 91 56 147 Ba x -60264.029 19.748 8183.240 0.134 B- 6414.361 22.466 146 935303.900 21.200 - 33 90 57 147 La x -66678.390 10.712 8221.553 0.073 B- 5335.501 13.725 146 928417.800 11.500 - 31 89 58 147 Ce -72013.891 8.580 8252.527 0.058 B- 3430.176 15.533 146 922689.903 9.211 - 29 88 59 147 Pr -75444.067 15.857 8270.539 0.108 B- 2702.681 15.860 146 919007.458 17.023 - 27 87 60 147 Nd -78146.748 1.388 8283.603 0.009 B- 895.512 0.482 146 916106.010 1.490 - 25 86 61 147 Pm -79042.260 1.399 8284.372 0.010 B- 224.094 0.293 146 915144.638 1.501 - 23 85 62 147 Sm -79266.354 1.372 8280.575 0.009 B- -1721.598 2.281 146 914904.064 1.473 - 21 84 63 147 Eu -77544.756 2.630 8263.541 0.018 B- -2187.811 2.524 146 916752.276 2.823 - 19 83 64 147 Gd -75356.945 1.965 8243.336 0.013 B- -4614.280 8.147 146 919100.987 2.109 - 17 82 65 147 Tb -70742.665 8.100 8206.624 0.055 B- -6546.628 11.997 146 924054.620 8.695 - 15 81 66 147 Dy x -64196.038 8.849 8156.767 0.060 B- -8438.945 10.164 146 931082.715 9.500 - 13 80 67 147 Ho -55757.092 5.001 8094.037 0.034 B- -9149.286 38.517 146 940142.295 5.368 - 11 79 68 147 Er x -46607.807 38.191 8026.475 0.260 B- -10633.406 38.799 146 949964.458 41.000 - 9 78 69 147 Tm -35974.400 6.839 7948.817 0.047 B- * 146 961379.890 7.341 -0 40 94 54 148 Xe x -38600# 300# 8047# 2# B- 8311# 300# 147 958561# 322# - 38 93 55 148 Cs x -46910.942 13.041 8097.546 0.088 B- 10682.793 64.413 147 949639.029 14.000 - 36 92 56 148 Ba + -57593.735 63.079 8164.441 0.426 B- 5115.000 60.000 147 938170.578 67.718 - 34 91 57 148 La x -62708.735 19.468 8193.716 0.132 B- 7689.672 22.457 147 932679.400 20.900 - 32 90 58 148 Ce -70398.408 11.195 8240.387 0.076 B- 2137.016 12.567 147 924424.196 12.018 - 30 89 59 148 Pr -72535.424 15.043 8249.540 0.102 B- 4872.572 15.090 147 922130.015 16.148 - 28 88 60 148 Nd -77407.996 2.127 8277.177 0.014 B- -542.280 5.874 147 916899.093 2.283 - 26 87 61 148 Pm +p -76865.716 5.723 8268.226 0.039 B- 2470.548 5.642 147 917481.255 6.143 - 24 86 62 148 Sm -79336.264 1.367 8279.633 0.009 B- -3036.933 10.019 147 914829.012 1.467 - 22 85 63 148 Eu -76299.331 10.013 8253.827 0.068 B- -30.003 10.019 147 918089.294 10.748 - 20 84 64 148 Gd -76269.329 1.554 8248.338 0.011 B- -5732.246 12.529 147 918121.503 1.668 - 18 83 65 148 Tb -70537.082 12.464 8204.321 0.084 B- -2677.532 9.596 147 924275.323 13.380 - 16 82 66 148 Dy -67859.550 8.724 8180.943 0.059 B- -9868.393 84.287 147 927149.772 9.366 - 14 81 67 148 Ho x -57991.158 83.834 8108.979 0.566 B- -6512.169 84.458 147 937743.928 90.000 - 12 80 68 148 Er x -51478.989 10.246 8059.692 0.069 B- -12713.962 14.491 147 944735.029 11.000 - 10 79 69 148 Tm x -38765.027 10.246 7968.500 0.069 B- -8435# 400# 147 958384.029 11.000 - 8 78 70 148 Yb x -30330# 400# 7906# 3# B- * 147 967439# 429# -0 39 94 55 149 Cs x -43250# 400# 8073# 3# B- 9870# 593# 148 953569# 429# - 37 93 56 149 Ba x -53120.309 437.802 8133.793 2.938 B- 7099.605 481.431 148 942973.000 470.000 - 35 92 57 149 La + -60219.913 200.262 8176.191 1.344 B- 6450.000 200.000 148 935351.260 214.990 - 33 91 58 149 Ce x -66669.913 10.246 8214.229 0.069 B- 4369.452 14.230 148 928426.900 11.000 - 31 90 59 149 Pr x -71039.366 9.874 8238.303 0.066 B- 3336.100 10.101 148 923736.100 10.600 - 29 89 60 149 Nd -n -74375.466 2.128 8255.442 0.014 B- 1688.790 2.455 148 920154.648 2.284 - 27 88 61 149 Pm -76064.256 2.267 8261.526 0.015 B- 1071.481 1.875 148 918341.658 2.434 - 25 87 62 149 Sm -77135.737 1.311 8263.466 0.009 B- -694.625 3.788 148 917191.375 1.407 - 23 86 63 149 Eu -76441.112 3.951 8253.554 0.027 B- -1314.101 4.136 148 917937.086 4.241 - 21 85 64 149 Gd -75127.011 3.360 8239.484 0.023 B- -3638.343 4.339 148 919347.831 3.607 - 19 84 65 149 Tb -71488.669 3.667 8209.815 0.025 B- -3792.760 9.162 148 923253.753 3.936 - 17 83 66 149 Dy -67695.909 9.221 8179.109 0.062 B- -6049.330 12.803 148 927325.448 9.898 - 15 82 67 149 Ho -61646.578 11.990 8133.259 0.080 B- -7904.963 30.408 148 933819.672 12.871 - 13 81 68 149 Er x -53741.615 27.945 8074.955 0.188 B- -9859# 198# 148 942306.000 30.000 - 11 80 69 149 Tm x -43883# 196# 8004# 1# B- -10684# 358# 148 952890# 210# - 9 79 70 149 Yb x -33198# 300# 7927# 2# B- * 148 964360# 322# -0 40 95 55 150 Cs x -38170# 400# 8039# 3# B- 11730# 500# 149 959023# 429# - 38 94 56 150 Ba x -49900# 300# 8112# 2# B- 6230# 529# 149 946430# 322# - 36 93 57 150 La x -56129.966 435.473 8148.225 2.903 B- 8716.888 435.631 149 939742.000 467.500 - 34 92 58 150 Ce -64846.854 11.697 8201.122 0.078 B- 3453.625 14.291 149 930384.035 12.556 - 32 91 59 150 Pr -68300.479 9.015 8218.931 0.060 B- 5379.276 9.085 149 926676.415 9.678 - 30 90 60 150 Nd -73679.755 1.289 8249.577 0.009 B- -82.616 20.001 149 920901.525 1.384 - 28 89 61 150 Pm + -73597.139 20.041 8243.810 0.134 B- 3454.000 20.000 149 920990.217 21.514 - 26 88 62 150 Sm -77051.139 1.274 8261.621 0.009 B- -2258.905 6.181 149 917282.195 1.368 - 24 87 63 150 Eu -74792.234 6.253 8241.346 0.042 B- 971.700 3.543 149 919707.229 6.712 - 22 86 64 150 Gd -75763.934 6.076 8242.609 0.041 B- -4658.213 8.379 149 918664.066 6.523 - 20 85 65 150 Tb -71105.721 7.384 8206.338 0.049 B- -1796.122 8.389 149 923664.864 7.927 - 18 84 66 150 Dy -69309.600 4.348 8189.149 0.029 B- -7363.719 14.468 149 925593.080 4.667 - 16 83 67 150 Ho -61945.881 14.168 8134.842 0.094 B- -4114.568 13.591 149 933498.358 15.210 - 14 82 68 150 Er -57831.313 17.195 8102.195 0.115 B- -11340# 196# 149 937915.528 18.459 - 12 81 69 150 Tm x -46491# 196# 8021# 1# B- -7852# 358# 149 950090# 210# - 10 80 70 150 Yb x -38638# 300# 7964# 2# B- -13998# 424# 149 958520# 322# - 8 79 71 150 Lu -p -24640# 300# 7865# 2# B- * 149 973548# 322# -0 41 96 55 151 Cs x -34230# 500# 8013# 3# B- 10710# 640# 150 963253# 537# - 39 95 56 151 Ba x -44940# 400# 8079# 3# B- 8370# 591# 150 951755# 429# - 37 94 57 151 La x -53310.333 435.473 8129.043 2.884 B- 7914.718 435.833 150 942769.000 467.500 - 35 93 58 151 Ce x -61225.052 17.698 8176.277 0.117 B- 5554.578 21.189 150 934272.200 19.000 - 33 92 59 151 Pr -66779.630 11.651 8207.881 0.077 B- 4163.358 11.689 150 928309.114 12.507 - 31 91 60 151 Nd -70942.988 1.293 8230.272 0.009 B- 2443.075 4.473 150 923839.565 1.387 - 29 90 61 151 Pm -73386.063 4.653 8241.270 0.031 B- 1190.217 4.476 150 921216.817 4.994 - 27 89 62 151 Sm -74576.279 1.273 8243.971 0.008 B- 76.574 0.538 150 919939.066 1.367 - 25 88 63 151 Eu -74652.854 1.325 8239.297 0.009 B- -464.116 2.779 150 919856.860 1.422 - 23 87 64 151 Gd -74188.737 3.056 8231.043 0.020 B- -2565.233 3.762 150 920355.109 3.280 - 21 86 65 151 Tb -71623.504 4.137 8208.873 0.027 B- -2871.099 4.944 150 923109.001 4.441 - 19 85 66 151 Dy -a -68752.405 3.293 8184.678 0.022 B- -5129.667 8.756 150 926191.253 3.535 - 17 84 67 151 Ho -a -63622.738 8.302 8145.526 0.055 B- -5356.454 18.444 150 931698.177 8.912 - 15 83 68 151 Er x -58266.284 16.470 8104.872 0.109 B- -7493.528 25.460 150 937448.567 17.681 - 13 82 69 151 Tm +a -50772.756 19.416 8050.064 0.129 B- -9230.414 300.136 150 945493.201 20.843 - 11 81 70 151 Yb ep -41542.342 300.492 7983.755 1.990 B- -11434# 425# 150 955402.458 322.591 - 9 80 71 151 Lu -p -30108# 300# 7903# 2# B- * 150 967677# 322# -0 42 97 55 152 Cs x -28930# 500# 7979# 3# B- 12780# 640# 151 968942# 537# - 40 96 56 152 Ba x -41710# 400# 8057# 3# B- 7580# 500# 151 955222# 429# - 38 95 57 152 La x -49290# 300# 8102# 2# B- 9690# 361# 151 947085# 322# - 36 94 58 152 Ce x -58980# 200# 8161# 1# B- 4778# 201# 151 936682# 215# - 34 93 59 152 Pr x -63758.063 18.537 8187.104 0.122 B- 6391.344 30.710 151 931552.900 19.900 - 32 92 60 152 Nd -70149.407 24.485 8224.005 0.161 B- 1104.778 18.501 151 924691.509 26.285 - 30 91 61 152 Pm -71254.186 25.912 8226.127 0.170 B- 3508.417 25.886 151 923505.481 27.817 - 28 90 62 152 Sm -74762.603 1.212 8244.061 0.008 B- -1874.348 0.687 151 919739.040 1.301 - 26 89 63 152 Eu -72888.255 1.326 8226.583 0.009 B- 1818.661 0.702 151 921751.235 1.423 - 24 88 64 152 Gd -74706.916 1.206 8233.401 0.008 B- -3990.000 40.000 151 919798.822 1.294 - 22 87 65 152 Tb - -70716.916 40.018 8202.004 0.263 B- -599.044 40.258 151 924082.263 42.961 - 20 86 66 152 Dy -a -70117.873 4.624 8192.916 0.030 B- -6513.102 13.325 151 924725.363 4.963 - 18 85 67 152 Ho -63604.771 12.529 8144.919 0.082 B- -3104.394 9.815 151 931717.465 13.450 - 16 84 68 152 Er -60500.377 8.830 8119.349 0.058 B- -8780.104 54.743 151 935050.169 9.479 - 14 83 69 152 Tm -51720.273 54.027 8056.438 0.355 B- -5449.892 139.620 151 944476.000 58.000 - 12 82 70 152 Yb -46270.381 149.708 8015.436 0.985 B- -12848# 246# 151 950326.700 160.718 - 10 81 71 152 Lu x -33422# 196# 7926# 1# B- * 151 964120# 210# -0 41 97 56 153 Ba x -36470# 400# 8023# 3# B- 9590# 500# 152 960848# 429# - 39 96 57 153 La x -46060# 300# 8081# 2# B- 8850# 361# 152 950553# 322# - 37 95 58 153 Ce x -54910# 200# 8134# 1# B- 6659# 201# 152 941052# 215# - 35 94 59 153 Pr -61568.463 11.882 8172.036 0.078 B- 5761.834 12.190 152 933903.532 12.755 - 33 93 60 153 Nd -67330.297 2.747 8204.582 0.018 B- 3317.527 9.355 152 927717.949 2.948 - 31 92 61 153 Pm -70647.824 9.066 8221.152 0.059 B- 1911.862 9.093 152 924156.436 9.732 - 29 91 62 153 Sm -n -72559.686 1.219 8228.534 0.008 B- 807.536 0.708 152 922103.969 1.309 - 27 90 63 153 Eu -73367.222 1.330 8228.699 0.009 B- -484.671 0.717 152 921237.043 1.428 - 25 89 64 153 Gd -72882.551 1.203 8220.418 0.008 B- -1569.213 3.845 152 921757.359 1.291 - 23 88 65 153 Tb -71313.338 3.995 8205.048 0.026 B- -2170.394 1.933 152 923441.978 4.289 - 21 87 66 153 Dy -69142.943 4.048 8185.749 0.026 B- -4130.840 6.157 152 925771.992 4.346 - 19 86 67 153 Ho -a -65012.103 5.094 8153.637 0.033 B- -4543.499 9.916 152 930206.632 5.468 - 17 85 68 153 Er -60468.604 9.321 8118.827 0.061 B- -6495.276 12.891 152 935084.279 10.006 - 15 84 69 153 Tm -53973.329 11.983 8071.261 0.078 B- -6765# 196# 152 942057.244 12.864 - 13 83 70 153 Yb x -47208# 196# 8022# 1# B- -8835# 247# 152 949320# 210# - 11 82 71 153 Lu +a -38372.844 150.034 7959.070 0.981 B- -11073# 335# 152 958805.054 161.068 - 9 81 72 153 Hf x -27300# 300# 7882# 2# B- * 152 970692# 322# -0 42 98 56 154 Ba x -32820# 500# 8000# 3# B- 8709# 583# 153 964766# 537# - 40 97 57 154 La x -41530# 300# 8051# 2# B- 10690# 361# 153 955416# 322# - 38 96 58 154 Ce x -52220# 200# 8116# 1# B- 5885# 230# 153 943940# 215# - 36 95 59 154 Pr + -58104.976 113.009 8148.892 0.734 B- 7720.000 100.000 153 937621.738 121.320 - 34 94 60 154 Nd + -65824.976 52.642 8193.942 0.342 B- 2687.000 25.000 153 929333.977 56.513 - 32 93 61 154 Pm IT -68511.976 46.326 8206.310 0.301 B- 3943.200 46.303 153 926449.364 49.733 - 30 92 62 154 Sm -72455.176 1.462 8226.835 0.009 B- -717.056 1.103 153 922216.164 1.569 - 28 91 63 154 Eu -71738.121 1.346 8217.098 0.009 B- 1967.834 0.755 153 922985.955 1.444 - 26 90 64 154 Gd -73705.954 1.197 8224.796 0.008 B- -3549.651 45.298 153 920873.398 1.285 - 24 89 65 154 Tb - -70156.303 45.314 8196.666 0.294 B- 237.604 45.901 153 924684.106 48.646 - 22 88 66 154 Dy -70393.907 7.445 8193.129 0.048 B- -5754.596 10.178 153 924429.028 7.992 - 20 87 67 154 Ho -a -64639.311 8.228 8150.681 0.053 B- -2034.291 9.463 153 930606.841 8.833 - 18 86 68 154 Er -62605.020 4.986 8132.392 0.032 B- -8177.888 14.916 153 932790.743 5.353 - 16 85 69 154 Tm -a -54427.131 14.412 8074.208 0.094 B- -4495.048 13.953 153 941570.067 15.472 - 14 84 70 154 Yb -49932.083 17.281 8039.939 0.112 B- -10217# 197# 153 946395.701 18.552 - 12 83 71 154 Lu +a -39715# 196# 7969# 1# B- -7045# 358# 153 957364# 211# - 10 82 72 154 Hf x -32670# 300# 7918# 2# B- * 153 964927# 322# -0 41 98 57 155 La x -37930# 400# 8028# 3# B- 9850# 500# 154 959280# 429# - 39 97 58 155 Ce x -47780# 300# 8087# 2# B- 7635# 300# 154 948706# 322# - 37 96 59 155 Pr -55415.268 17.198 8131.039 0.111 B- 6868.456 19.472 154 940509.259 18.462 - 35 95 60 155 Nd -62283.724 9.153 8170.304 0.059 B- 4656.207 10.278 154 933135.668 9.826 - 33 94 61 155 Pm -66939.931 4.718 8195.296 0.030 B- 3250.888 4.946 154 928137.024 5.065 - 31 93 62 155 Sm -n -70190.819 1.487 8211.223 0.010 B- 1627.273 1.202 154 924647.051 1.595 - 29 92 63 155 Eu -71818.092 1.401 8216.674 0.009 B- 251.788 0.870 154 922900.102 1.504 - 27 91 64 155 Gd -72069.880 1.191 8213.251 0.008 B- -819.830 9.789 154 922629.796 1.278 - 25 90 65 155 Tb + -71250.050 9.849 8202.914 0.064 B- -2094.500 1.897 154 923509.921 10.573 - 23 89 66 155 Dy -69155.550 9.665 8184.354 0.062 B- -3116.011 16.590 154 925758.459 10.375 - 21 88 67 155 Ho -66039.539 17.474 8159.203 0.113 B- -3830.350 18.474 154 929103.634 18.759 - 19 87 68 155 Er -a -62209.189 6.098 8129.444 0.039 B- -5583.276 11.515 154 933215.684 6.546 - 17 86 69 155 Tm -a -56625.913 9.925 8088.375 0.064 B- -6123.305 19.341 154 939209.578 10.654 - 15 85 70 155 Yb -a -50502.608 16.600 8043.823 0.107 B- -7957.561 25.416 154 945783.217 17.820 - 13 84 71 155 Lu +a -42545.047 19.246 7987.436 0.124 B- -8375# 299# 154 954326.011 20.661 - 11 83 72 155 Hf x -34170# 298# 7928# 2# B- -10242# 423# 154 963317# 320# - 9 82 73 155 Ta -p -23928# 300# 7857# 2# B- * 154 974312# 322# -0 42 99 57 156 La x -33050# 400# 7997# 3# B- 11769# 500# 155 964519# 429# - 40 98 58 156 Ce x -44820# 300# 8068# 2# B- 6748# 361# 155 951884# 322# - 38 97 59 156 Pr x -51568# 200# 8106# 1# B- 8906# 283# 155 944640# 215# - 36 96 60 156 Nd + -60473.644 200.033 8158.066 1.282 B- 3690.000 200.000 155 935078.868 214.744 - 34 95 61 156 Pm -64163.644 3.631 8176.705 0.023 B- 5196.786 9.285 155 931117.490 3.897 - 32 94 62 156 Sm -69360.430 8.546 8205.003 0.055 B- 722.118 7.902 155 925538.511 9.174 - 30 93 63 156 Eu -70082.548 3.590 8204.617 0.023 B- 2452.366 3.409 155 924763.285 3.853 - 28 92 64 156 Gd -72534.914 1.190 8215.322 0.008 B- -2444.117 3.679 155 922130.562 1.277 - 26 91 65 156 Tb -70090.797 3.814 8194.639 0.024 B- 438.167 3.681 155 924754.430 4.094 - 24 90 66 156 Dy -70528.964 1.194 8192.433 0.008 B- -5050.000 60.000 155 924284.038 1.281 - 22 89 67 156 Ho - -65478.964 60.012 8155.046 0.385 B- -1267.255 64.869 155 929705.436 64.425 - 20 88 68 156 Er -64211.709 24.629 8141.908 0.158 B- -7377.159 26.710 155 931065.890 26.440 - 18 87 69 156 Tm -56834.550 14.279 8089.603 0.092 B- -3568.830 12.548 155 938985.597 15.328 - 16 86 70 156 Yb -53265.721 9.308 8061.711 0.060 B- -9566.176 54.916 155 942816.893 9.992 - 14 85 71 156 Lu -a -43699.544 54.122 7995.374 0.347 B- -5882.648 139.709 155 953086.606 58.102 - 12 84 72 156 Hf -37816.896 149.757 7952.650 0.960 B- -11956# 334# 155 959401.889 160.770 - 10 83 73 156 Ta -p -25861# 298# 7871# 2# B- * 155 972237# 320# -0 41 99 58 157 Ce x -39930# 400# 8037# 3# B- 8610# 500# 156 957133# 429# - 39 98 59 157 Pr x -48540# 300# 8086# 2# B- 7921# 301# 156 947890# 322# - 37 97 60 157 Nd -56461.543 24.918 8131.959 0.159 B- 5835.500 25.877 156 939386.037 26.750 - 35 96 61 157 Pm -62297.043 7.006 8164.145 0.045 B- 4380.534 8.265 156 933121.370 7.521 - 33 95 62 157 Sm -66677.577 4.433 8187.063 0.028 B- 2781.331 6.136 156 928418.673 4.759 - 31 94 63 157 Eu -69458.908 4.259 8199.795 0.027 B- 1364.565 4.203 156 925432.791 4.572 - 29 93 64 157 Gd -70823.473 1.189 8203.504 0.008 B- -60.043 0.297 156 923967.870 1.276 - 27 92 65 157 Tb -70763.430 1.222 8198.138 0.008 B- -1338.872 5.134 156 924032.328 1.311 - 25 91 66 157 Dy -69424.558 5.177 8184.627 0.033 B- -2591.725 23.787 156 925469.667 5.557 - 23 90 67 157 Ho -66832.832 23.469 8163.136 0.149 B- -3419.194 33.668 156 928251.999 25.195 - 21 89 68 157 Er -63413.639 26.505 8136.375 0.169 B- -4704.366 38.515 156 931922.655 28.454 - 19 88 69 157 Tm x -58709.273 27.945 8101.428 0.178 B- -5287.374 30.003 156 936973.000 30.000 - 17 87 70 157 Yb -53421.898 10.920 8062.767 0.070 B- -6981.376 14.241 156 942649.230 11.723 - 15 86 71 157 Lu -46440.523 12.078 8013.317 0.077 B- -7537# 196# 156 950144.045 12.965 - 13 85 72 157 Hf -a -38903# 196# 7960# 1# B- -9310# 247# 156 958236# 210# - 11 84 73 157 Ta IT -29593.330 150.069 7896.043 0.956 B- -10123# 427# 156 968230.251 161.105 - 9 83 74 157 W x -19470# 400# 7827# 3# B- * 156 979098# 429# -0 42 100 58 158 Ce x -36660# 400# 8016# 3# B- 7670# 500# 157 960644# 429# - 40 99 59 158 Pr x -44330# 300# 8060# 2# B- 9725# 361# 157 952410# 322# - 38 98 60 158 Nd x -54055# 200# 8116# 1# B- 5035# 201# 157 941970# 215# - 36 97 61 158 Pm -59089.209 13.453 8143.254 0.085 B- 6161.034 14.299 157 936565.121 14.442 - 34 96 62 158 Sm -65250.243 4.892 8177.297 0.031 B- 2004.945 10.369 157 929950.979 5.251 - 32 95 63 158 Eu -67255.188 10.255 8185.035 0.065 B- 3434.358 10.323 157 927798.581 11.008 - 30 94 64 158 Gd -70689.546 1.189 8201.819 0.008 B- -1218.878 0.987 157 924111.646 1.276 - 28 93 65 158 Tb -69470.668 1.401 8189.153 0.009 B- 936.681 2.495 157 925420.166 1.503 - 26 92 66 158 Dy -70407.349 2.365 8190.130 0.015 B- -4219.755 27.005 157 924414.597 2.538 - 24 91 67 158 Ho - -66187.593 27.108 8158.471 0.172 B- -883.785 37.025 157 928944.692 29.101 - 22 90 68 158 Er -65303.808 25.219 8147.926 0.160 B- -6600.615 31.341 157 929893.474 27.074 - 20 89 69 158 Tm -58703.194 25.219 8101.199 0.160 B- -2692.957 26.456 157 936979.525 27.074 - 18 88 70 158 Yb -56010.237 7.994 8079.203 0.051 B- -8798.047 16.872 157 939870.534 8.582 - 16 87 71 158 Lu -a -47212.190 15.125 8018.568 0.096 B- -5109.800 14.937 157 949315.626 16.237 - 14 86 72 158 Hf -42102.390 17.494 7981.276 0.111 B- -10936# 197# 157 954801.222 18.780 - 12 85 73 158 Ta +a -31167# 196# 7907# 1# B- -7534# 358# 157 966541# 210# - 10 84 74 158 W -a -23633# 300# 7854# 2# B- * 157 974629# 322# -0 41 100 59 159 Pr x -41088# 400# 8039# 3# B- 8719# 500# 158 955890# 429# - 39 99 60 159 Nd x -49807# 300# 8089# 2# B- 6747# 300# 158 946530# 322# - 37 98 61 159 Pm -56554.280 10.039 8126.859 0.063 B- 5653.495 11.644 158 939286.479 10.777 - 35 97 62 159 Sm -62207.775 5.934 8157.495 0.037 B- 3835.510 7.324 158 933217.202 6.369 - 33 96 63 159 Eu -66043.285 4.325 8176.697 0.027 B- 2518.150 4.391 158 929099.612 4.643 - 31 95 64 159 Gd -68561.436 1.192 8187.614 0.007 B- 970.927 0.759 158 926396.267 1.279 - 29 94 65 159 Tb -69532.363 1.256 8188.800 0.008 B- -365.229 1.162 158 925353.933 1.348 - 27 93 66 159 Dy -69167.134 1.528 8181.583 0.010 B- -1837.600 2.683 158 925746.023 1.640 - 25 92 67 159 Ho - -67329.534 3.088 8165.105 0.019 B- -2768.500 2.000 158 927718.768 3.314 - 23 91 68 159 Er - -64561.034 3.679 8142.773 0.023 B- -3990.637 28.186 158 930690.875 3.949 - 21 90 69 159 Tm x -60570.398 27.945 8112.754 0.176 B- -4731.792 33.129 158 934975.000 30.000 - 19 89 70 159 Yb x -55838.606 17.794 8078.074 0.112 B- -6130.002 41.655 158 940054.787 19.102 - 17 88 71 159 Lu x -49708.604 37.663 8034.600 0.237 B- -6856.004 41.246 158 946635.615 40.433 - 15 87 72 159 Hf -a -42852.600 16.813 7986.560 0.106 B- -8413.452 25.891 158 953995.838 18.049 - 13 86 73 159 Ta IT -34439.148 19.689 7928.725 0.124 B- -9145# 299# 158 963028.052 21.137 - 11 85 74 159 W -a -25295# 298# 7866# 2# B- -10550# 426# 158 972845# 320# - 9 84 75 159 Re IT -14745# 305# 7795# 2# B- * 158 984171# 327# -0 42 101 59 160 Pr x -36520# 400# 8011# 2# B- 10613# 500# 159 960794# 429# - 40 100 60 160 Nd x -47134# 300# 8073# 2# B- 5868# 361# 159 949400# 322# - 38 99 61 160 Pm x -53002# 200# 8104# 1# B- 7233# 200# 159 943100# 215# - 36 98 62 160 Sm -60234.793 5.934 8144.625 0.037 B- 3245.670 11.183 159 935335.286 6.370 - 34 97 63 160 Eu -63480.463 9.501 8160.021 0.059 B- 4461.278 9.586 159 931850.916 10.199 - 32 96 64 160 Gd -67941.741 1.278 8183.014 0.008 B- -105.483 1.022 159 927061.537 1.371 - 30 95 65 160 Tb -67836.257 1.262 8177.465 0.008 B- 1836.472 1.172 159 927174.778 1.354 - 28 94 66 160 Dy -69672.730 0.772 8184.054 0.005 B- -3290.000 15.000 159 925203.244 0.828 - 26 93 67 160 Ho - -66382.730 15.020 8158.602 0.094 B- -318.502 28.528 159 928735.204 16.124 - 24 92 68 160 Er -66064.228 24.254 8151.721 0.152 B- -5762.200 40.311 159 929077.130 26.037 - 22 91 69 160 Tm -60302.028 34.262 8110.818 0.214 B- -2139.322 35.017 159 935263.106 36.781 - 20 90 70 160 Yb -58162.706 7.233 8092.557 0.045 B- -7892.769 57.280 159 937559.763 7.764 - 18 89 71 160 Lu x -50269.937 56.821 8038.338 0.355 B- -4330.994 57.617 159 946033.000 61.000 - 16 88 72 160 Hf -45938.943 9.541 8006.380 0.060 B- -10115.249 55.147 159 950682.513 10.242 - 14 87 73 160 Ta -a -35823.695 54.316 7938.270 0.339 B- -6497.240 139.859 159 961541.679 58.310 - 12 86 74 160 W -29326.455 149.827 7892.772 0.936 B- -12588# 334# 159 968516.753 160.846 - 10 85 75 160 Re -a -16739# 298# 7809# 2# B- * 159 982030# 320# -0 41 101 60 161 Nd x -42588# 400# 8044# 2# B- 7648# 499# 160 954280# 429# - 39 100 61 161 Pm x -50235# 298# 8087# 2# B- 6436# 298# 160 946070# 320# - 37 99 62 161 Sm -56671.962 6.817 8122.041 0.042 B- 5119.562 12.415 160 939160.143 7.318 - 35 98 63 161 Eu -61791.524 10.399 8148.980 0.065 B- 3714.299 10.525 160 933664.066 11.164 - 33 97 64 161 Gd -n -65505.824 1.622 8167.191 0.010 B- 1955.765 1.442 160 929676.602 1.741 - 31 96 65 161 Tb -67461.589 1.350 8174.479 0.008 B- 594.212 1.260 160 927577.001 1.449 - 29 95 66 161 Dy -68055.801 0.768 8173.310 0.005 B- -858.530 2.166 160 926939.088 0.824 - 27 94 67 161 Ho -67197.270 2.242 8163.119 0.014 B- -1995.663 9.011 160 927860.759 2.406 - 25 93 68 161 Er +n -65201.608 8.780 8145.864 0.055 B- -3302.900 29.292 160 930003.191 9.425 - 23 92 69 161 Tm x -61898.708 27.945 8120.490 0.174 B- -4059.308 31.885 160 933549.000 30.000 - 21 91 70 161 Yb x -57839.400 15.354 8090.417 0.095 B- -5277.056 31.885 160 937906.846 16.483 - 19 90 71 161 Lu x -52562.344 27.945 8052.781 0.174 B- -6247.672 35.909 160 943572.000 30.000 - 17 89 72 161 Hf -46314.672 22.551 8009.117 0.140 B- -7535.674 33.097 160 950279.151 24.209 - 15 88 73 161 Ta +a -38778.997 24.382 7957.452 0.151 B- -8224# 197# 160 958369.031 26.175 - 13 87 74 161 W -a -30555# 196# 7902# 1# B- -9715# 247# 160 967197# 210# - 11 86 75 161 Re -20840.203 149.922 7836.312 0.931 B- -10861# 427# 160 977627.121 160.948 - 9 85 76 161 Os -a -9979# 400# 7764# 2# B- * 160 989287# 429# -0 42 102 60 162 Nd x -39550# 400# 8026# 2# B- 6819# 500# 161 957541# 429# - 40 101 61 162 Pm x -46370# 300# 8063# 2# B- 8160# 358# 161 950220# 322# - 38 100 62 162 Sm x -54530# 196# 8109# 1# B- 4174# 199# 161 941460# 210# - 36 99 63 162 Eu + -58703.401 35.229 8129.438 0.217 B- 5577.000 35.000 161 936979.303 37.819 - 34 98 64 162 Gd -nn -64280.401 4.009 8159.035 0.025 B- 1395.556 36.581 161 930992.146 4.303 - 32 97 65 162 Tb + -65675.958 36.372 8162.820 0.225 B- 2505.521 36.364 161 929493.955 39.046 - 30 96 66 162 Dy -68181.478 0.767 8173.457 0.005 B- -2139.937 3.113 161 926804.168 0.822 - 28 95 67 162 Ho -66041.541 3.166 8155.418 0.020 B- 292.978 3.127 161 929101.485 3.398 - 26 94 68 162 Er -66334.519 0.822 8152.397 0.005 B- -4856.728 26.047 161 928786.960 0.882 - 24 93 69 162 Tm - -61477.791 26.060 8117.588 0.161 B- -1651.444 30.240 161 934000.872 27.977 - 22 92 70 162 Yb x -59826.347 15.359 8102.565 0.095 B- -6994.593 76.592 161 935773.771 16.488 - 20 91 71 162 Lu x -52831.753 75.036 8054.559 0.463 B- -3662.746 75.570 161 943282.776 80.554 - 18 90 72 162 Hf -49169.008 8.968 8027.120 0.055 B- -9388.814 52.931 161 947214.896 9.627 - 16 89 73 162 Ta -a -39780.194 52.238 7964.335 0.322 B- -5780.987 52.239 161 957294.202 56.079 - 14 88 74 162 W -33999.207 17.658 7923.821 0.109 B- -11498# 197# 161 963500.347 18.956 - 12 87 75 162 Re +a -22501# 196# 7848# 1# B- -8061# 358# 161 975844# 210# - 10 86 76 162 Os -a -14440# 300# 7793# 2# B- * 161 984498# 322# -0 41 102 61 163 Pm x -43249# 400# 8044# 2# B- 7471# 499# 162 953570# 429# - 39 101 62 163 Sm x -50720# 298# 8085# 2# B- 5765# 305# 162 945550# 320# - 37 100 63 163 Eu + -56484.886 65.544 8115.471 0.402 B- 4829.000 65.000 162 939360.977 70.364 - 35 99 64 163 Gd -61313.886 8.426 8140.297 0.052 B- 3282.185 9.358 162 934176.832 9.045 - 33 98 65 163 Tb +p -64596.071 4.073 8155.633 0.025 B- 1785.099 4.001 162 930653.261 4.372 - 31 97 66 163 Dy -66381.170 0.765 8161.785 0.005 B- -2.834 0.019 162 928736.879 0.821 - 29 96 67 163 Ho -66378.335 0.765 8156.968 0.005 B- -1210.612 4.575 162 928739.921 0.821 - 27 95 68 163 Er -65167.723 4.639 8144.741 0.028 B- -2439.000 3.000 162 930039.567 4.980 - 25 94 69 163 Tm - -62728.723 5.524 8124.979 0.034 B- -3429.629 16.309 162 932657.941 5.930 - 23 93 70 163 Yb x -59299.094 15.364 8099.138 0.094 B- -4507.685 31.890 162 936339.800 16.493 - 21 92 71 163 Lu x -54791.409 27.945 8066.684 0.171 B- -5527.726 37.348 162 941179.000 30.000 - 19 91 72 163 Hf -49263.682 24.778 8027.972 0.152 B- -6729.054 45.416 162 947113.258 26.599 - 17 90 73 163 Ta -a -42534.629 38.061 7981.890 0.234 B- -7626.436 65.049 162 954337.195 40.860 - 15 89 74 163 W -a -34908.193 52.751 7930.302 0.324 B- -8905.949 55.912 162 962524.511 56.630 - 13 88 75 163 Re +a -26002.244 18.534 7870.865 0.114 B- -9810# 299# 162 972085.441 19.897 - 11 87 76 163 Os -a -16192# 298# 7806# 2# B- * 162 982617# 320# -0 42 103 61 164 Pm x -38870# 400# 8017# 2# B- 9232# 499# 163 958271# 429# - 40 102 62 164 Sm x -48102# 298# 8069# 2# B- 5279# 319# 163 948360# 320# - 38 101 63 164 Eu + -53381# 114# 8096# 1# B- 6393.000 50.000 163 942693# 122# - 36 100 64 164 Gd x -59774# 102# 8130# 1# B- 2304# 143# 163 935830# 110# - 34 99 65 164 Tb + -62077.965 100.003 8139.765 0.610 B- 3890.000 100.000 163 933356.559 107.357 - 32 98 66 164 Dy -65967.965 0.767 8158.714 0.005 B- -986.463 1.415 163 929180.472 0.823 - 30 97 67 164 Ho -64981.503 1.528 8147.929 0.009 B- 961.387 1.420 163 930239.483 1.639 - 28 96 68 164 Er -65942.890 0.775 8149.020 0.005 B- -4038.855 24.401 163 929207.392 0.832 - 26 95 69 164 Tm -61904.035 24.394 8119.623 0.149 B- -886.617 28.829 163 933543.281 26.188 - 24 94 70 164 Yb x -61017.418 15.369 8109.446 0.094 B- -6375.048 31.892 163 934495.103 16.499 - 22 93 71 164 Lu x -54642.370 27.945 8065.804 0.170 B- -2823.865 32.112 163 941339.000 30.000 - 20 92 72 164 Hf -51818.505 15.820 8043.814 0.096 B- -8535.704 32.112 163 944370.544 16.983 - 18 91 73 164 Ta x -43282.800 27.945 7986.997 0.170 B- -5047.041 29.572 163 953534.000 30.000 - 16 90 74 164 W -38235.759 9.674 7951.452 0.059 B- -10763.323 55.406 163 958952.222 10.385 - 14 89 75 164 Re -a -27472.436 54.555 7881.052 0.333 B- -7050.331 140.051 163 970507.124 58.566 - 12 88 76 164 Os -20422.106 149.919 7833.291 0.914 B- -13078# 348# 163 978075.966 160.945 - 10 87 77 164 Ir -a -7344# 314# 7749# 2# B- * 163 992116# 338# -0 41 103 62 165 Sm x -43808# 401# 8043# 2# B- 6916# 424# 164 952970# 430# - 39 102 63 165 Eu + -50724# 138# 8080# 1# B- 5729.000 65.000 164 945546# 148# - 37 101 64 165 Gd + -56453# 121# 8110# 1# B- 4113.000 65.000 164 939395# 130# - 35 100 65 165 Tb x -60566# 102# 8130# 1# B- 3047# 102# 164 934980# 110# - 33 99 66 165 Dy -n -63612.606 0.769 8143.909 0.005 B- 1286.400 0.829 164 931709.054 0.825 - 31 98 67 165 Ho -64899.006 1.010 8146.964 0.006 B- -377.396 1.033 164 930328.047 1.084 - 29 97 68 165 Er -64521.610 0.964 8139.936 0.006 B- -1591.990 1.538 164 930733.198 1.034 - 27 96 69 165 Tm -62929.621 1.671 8125.546 0.010 B- -2634.239 26.592 164 932442.269 1.793 - 25 95 70 165 Yb -60295.382 26.539 8104.839 0.161 B- -3853.140 35.432 164 935270.241 28.490 - 23 94 71 165 Lu -56442.242 26.539 8076.745 0.161 B- -4806.734 38.539 164 939406.758 28.490 - 21 93 72 165 Hf x -51635.507 27.945 8042.872 0.169 B- -5787.655 31.195 164 944567.000 30.000 - 19 92 73 165 Ta -45847.853 13.863 8003.054 0.084 B- -6986.830 28.566 164 950780.303 14.882 - 17 91 74 165 W -38861.022 24.977 7955.968 0.151 B- -8201.246 34.332 164 958280.974 26.813 - 15 90 75 165 Re +a -30659.776 23.594 7901.522 0.143 B- -8865# 197# 164 967085.375 25.329 - 13 89 76 165 Os -a -21795# 196# 7843# 1# B- -10202# 252# 164 976602# 210# - 11 88 77 165 Ir IT -11593# 158# 7776# 1# B- * 164 987555# 170# -0 42 104 62 166 Sm x -40730# 400# 8024# 2# B- 6478# 537# 165 956275# 429# - 40 103 63 166 Eu + -47208# 358# 8059# 2# B- 7322.000 300.000 165 949320# 384# - 38 102 64 166 Gd x -54530# 196# 8098# 1# B- 3355# 208# 165 941460# 210# - 36 101 65 166 Tb + -57884.789 70.005 8113.680 0.422 B- 4700.000 70.000 165 937858.119 75.153 - 34 100 66 166 Dy -n -62584.789 0.867 8137.280 0.005 B- 486.540 0.921 165 932812.461 0.930 - 32 99 67 166 Ho -63071.329 1.010 8135.499 0.006 B- 1854.713 0.922 165 932290.139 1.084 - 30 98 68 166 Er -64926.042 1.165 8141.959 0.007 B- -3037.667 11.547 165 930299.023 1.251 - 28 97 69 166 Tm - -61888.375 11.606 8118.946 0.070 B- -292.635 13.507 165 933560.092 12.459 - 26 96 70 166 Yb +nn -61595.740 7.101 8112.471 0.043 B- -5574.759 30.642 165 933874.249 7.623 - 24 95 71 166 Lu x -56020.981 29.808 8074.175 0.180 B- -2161.998 40.859 165 939859.000 32.000 - 22 94 72 166 Hf x -53858.983 27.945 8056.438 0.168 B- -7761.208 39.520 165 942180.000 30.000 - 20 93 73 166 Ta x -46097.775 27.945 8004.971 0.168 B- -4209.744 29.508 165 950512.000 30.000 - 18 92 74 166 W -41888.031 9.478 7974.898 0.057 B- -9994.553 72.879 165 955031.346 10.174 - 16 91 75 166 Re -a -31893.478 72.310 7909.977 0.436 B- -6461.961 72.387 165 965760.940 77.628 - 14 90 76 166 Os -25431.517 17.966 7866.336 0.108 B- -12078# 197# 165 972698.141 19.287 - 12 89 77 166 Ir -p -13354# 196# 7789# 1# B- -8624# 359# 165 985664# 210# - 10 88 78 166 Pt -a -4730# 300# 7732# 2# B- * 165 994923# 322# -0 41 104 63 167 Eu x -44010# 400# 8040# 2# B- 6803# 499# 166 952753# 429# - 39 103 64 167 Gd x -50813# 298# 8076# 2# B- 5114# 357# 166 945450# 320# - 37 102 65 167 Tb x -55927# 196# 8102# 1# B- 4004# 205# 166 939960# 210# - 35 101 66 167 Dy + -59930.626 60.228 8120.992 0.361 B- 2350.000 60.000 166 935661.823 64.657 - 33 100 67 167 Ho p2n -62280.626 5.234 8130.379 0.031 B- 1010.554 5.208 166 933138.994 5.618 - 31 99 68 167 Er -63291.180 1.166 8131.746 0.007 B- -747.539 1.501 166 932054.119 1.252 - 29 98 69 167 Tm -62543.641 1.298 8122.585 0.008 B- -1953.065 3.798 166 932856.635 1.393 - 27 97 70 167 Yb -60590.576 3.981 8106.205 0.024 B- -3089.451 31.920 166 934953.337 4.273 - 25 96 71 167 Lu x -57501.125 31.671 8083.021 0.190 B- -4033.369 42.237 166 938270.000 34.000 - 23 95 72 167 Hf x -53467.756 27.945 8054.184 0.167 B- -5116.697 39.520 166 942600.000 30.000 - 21 94 73 167 Ta x -48351.059 27.945 8018.861 0.167 B- -6253.001 33.382 166 948093.000 30.000 - 19 93 74 167 W -42098.058 18.261 7976.733 0.109 B- -7267# 44# 166 954805.873 19.603 - 17 92 75 167 Re +a -34831# 40# 7929# 0# B- -8329# 83# 166 962607# 43# - 15 91 76 167 Os -a -26501.993 72.682 7873.974 0.435 B- -9429.554 74.962 166 971548.938 78.027 - 13 90 77 167 Ir -17072.440 18.346 7812.825 0.110 B- -10460# 303# 166 981671.981 19.695 - 11 89 78 167 Pt -a -6612# 302# 7746# 2# B- * 166 992901# 325# -0 42 105 63 168 Eu x -39740# 500# 8014# 3# B- 8623# 641# 167 957337# 537# - 40 104 64 168 Gd x -48363# 401# 8061# 2# B- 4359# 499# 167 948080# 430# - 38 103 65 168 Tb x -52723# 298# 8082# 2# B- 5837# 329# 167 943400# 320# - 36 102 66 168 Dy +pp -58559.566 140.009 8112.536 0.833 B- 1501.605 143.186 167 937133.716 150.305 - 34 101 67 168 Ho + -60061.171 30.023 8116.817 0.179 B- 2930.000 30.000 167 935521.676 32.230 - 32 100 68 168 Er -62991.171 1.168 8129.601 0.007 B- -1678.250 1.870 167 932376.192 1.254 - 30 99 69 168 Tm -61312.921 1.709 8114.954 0.010 B- 268.980 1.887 167 934177.868 1.834 - 28 98 70 168 Yb -61581.901 1.195 8111.898 0.007 B- -4514.051 39.248 167 933889.106 1.282 - 26 97 71 168 Lu - -57067.850 39.266 8080.372 0.234 B- -1707.299 48.195 167 938735.139 42.153 - 24 96 72 168 Hf x -55360.552 27.945 8065.553 0.166 B- -6966.644 39.520 167 940568.000 30.000 - 22 95 73 168 Ta x -48393.908 27.945 8019.428 0.166 B- -3500.799 30.936 167 948047.000 30.000 - 20 94 74 168 W -44893.109 13.271 7993.933 0.079 B- -9098.224 33.556 167 951805.262 14.247 - 18 93 75 168 Re -a -35794.885 30.821 7935.120 0.183 B- -5799.672 32.373 167 961572.608 33.087 - 16 92 76 168 Os -29995.213 9.904 7895.941 0.059 B- -11328.987 56.098 167 967798.812 10.632 - 14 91 77 168 Ir -a -18666.226 55.216 7823.850 0.329 B- -7658.765 140.344 167 979960.981 59.277 - 12 90 78 168 Pt -a -11007.460 149.951 7773.605 0.893 B- * 167 988183.004 160.978 -0 41 105 64 169 Gd x -44153# 503# 8036# 3# B- 6176# 585# 168 952600# 540# - 39 104 65 169 Tb x -50329# 298# 8068# 2# B- 5269# 423# 168 945970# 320# - 37 103 66 169 Dy + -55597.177 300.670 8094.763 1.779 B- 3200.000 300.000 168 940313.971 322.782 - 35 102 67 169 Ho +p -58797.177 20.060 8109.068 0.119 B- 2125.927 20.053 168 936878.630 21.534 - 33 101 68 169 Er -n -60923.104 1.179 8117.019 0.007 B- 352.108 1.114 168 934596.353 1.265 - 31 100 69 169 Tm -61275.212 0.812 8114.473 0.005 B- -897.650 1.141 168 934218.350 0.871 - 29 99 70 169 Yb -n -60377.563 1.205 8104.532 0.007 B- -2293.000 3.000 168 935182.016 1.293 - 27 98 71 169 Lu - -58084.563 3.233 8086.335 0.019 B- -3367.673 28.131 168 937643.653 3.470 - 25 97 72 169 Hf x -54716.889 27.945 8061.778 0.165 B- -4426.460 39.520 168 941259.000 30.000 - 23 96 73 169 Ta x -50290.430 27.945 8030.957 0.165 B- -5372.557 31.925 168 946011.000 30.000 - 21 95 74 169 W -44917.873 15.436 7994.537 0.091 B- -6508.641 19.173 168 951778.677 16.571 - 19 94 75 169 Re +a -38409.232 11.374 7951.395 0.067 B- -7686.541 27.618 168 958765.991 12.210 - 17 93 76 169 Os -a -30722.691 25.167 7901.284 0.149 B- -8628.852 34.276 168 967017.833 27.017 - 15 92 77 169 Ir +a -22093.839 23.308 7845.596 0.138 B- -9581# 197# 168 976281.287 25.021 - 13 91 78 169 Pt -a -12512# 196# 7784# 1# B- -10724# 357# 168 986567# 210# - 11 90 79 169 Au x -1788# 298# 7716# 2# B- * 168 998080# 320# -0 42 106 64 170 Gd x -41380# 596# 8020# 4# B- 5344# 718# 169 955577# 640# - 40 105 65 170 Tb x -46724# 401# 8047# 2# B- 6940# 446# 169 949840# 430# - 38 104 66 170 Dy x -53663# 196# 8083# 1# B- 2575# 202# 169 942390# 210# - 36 103 67 170 Ho + -56238.681 50.024 8093.796 0.294 B- 3870.000 50.000 169 939625.289 53.702 - 34 102 68 170 Er -60108.681 1.546 8111.959 0.009 B- -312.828 1.821 169 935470.673 1.659 - 32 101 69 170 Tm -59795.853 0.801 8105.517 0.005 B- 968.066 0.801 169 935806.507 0.859 - 30 100 70 170 Yb -60763.919 0.010 8106.609 0.000 B- -3457.695 16.843 169 934767.245 0.011 - 28 99 71 170 Lu - -57306.224 16.843 8081.668 0.099 B- -1052.370 32.628 169 938479.234 18.081 - 26 98 72 170 Hf x -56253.854 27.945 8070.875 0.164 B- -6116.190 39.520 169 939609.000 30.000 - 24 97 73 170 Ta x -50137.665 27.945 8030.296 0.164 B- -2846.832 30.904 169 946175.000 30.000 - 22 96 74 170 W -47290.832 13.195 8008.948 0.078 B- -8377.639 26.611 169 949231.200 14.165 - 20 95 75 170 Re -38913.193 23.109 7955.065 0.136 B- -4986.946 25.091 169 958224.966 24.808 - 18 94 76 170 Os -33926.247 9.773 7921.128 0.057 B- -10567# 89# 169 963578.673 10.491 - 16 93 77 170 Ir -a -23360# 89# 7854# 1# B- -7060# 89# 169 974922# 95# - 14 92 78 170 Pt -16299.193 18.247 7808.236 0.107 B- -12547# 197# 169 982502.095 19.588 - 12 91 79 170 Au -p -3752# 196# 7730# 1# B- * 169 995972# 211# -0 41 106 65 171 Tb x -44032# 503# 8031# 3# B- 6157# 585# 170 952730# 540# - 39 105 66 171 Dy x -50189# 298# 8063# 2# B- 4330# 670# 170 946120# 320# - 37 104 67 171 Ho + -54518.956 600.002 8083.608 3.509 B- 3200.000 600.000 170 941471.490 644.128 - 35 103 68 171 Er -57718.956 1.557 8097.746 0.009 B- 1491.342 1.256 170 938036.148 1.670 - 33 102 69 171 Tm -59210.298 0.972 8101.893 0.006 B- 96.512 0.972 170 936435.126 1.043 - 31 101 70 171 Yb -59306.810 0.013 8097.882 0.000 B- -1478.414 1.862 170 936331.517 0.014 - 29 100 71 171 Lu -57828.395 1.862 8084.661 0.011 B- -2397.050 28.936 170 937918.660 1.998 - 27 99 72 171 Hf x -55431.345 28.876 8066.068 0.169 B- -3711.072 40.184 170 940492.000 31.000 - 25 98 73 171 Ta x -51720.273 27.945 8039.791 0.163 B- -4634.183 39.520 170 944476.000 30.000 - 23 97 74 171 W x -47086.090 27.945 8008.115 0.163 B- -5835.810 39.520 170 949451.000 30.000 - 21 96 75 171 Re x -41250.280 27.945 7969.412 0.163 B- -6948.339 33.145 170 955716.000 30.000 - 19 95 76 171 Os -34301.942 17.823 7924.204 0.104 B- -7889.916 42.395 170 963175.348 19.133 - 17 94 77 171 Ir -a -26412.025 38.466 7873.489 0.225 B- -8942.323 82.291 170 971645.522 41.295 - 15 93 78 171 Pt -a -17469.702 72.747 7816.619 0.425 B- -9907.407 75.639 170 981245.502 78.097 - 13 92 79 171 Au -p -7562.295 20.713 7754.106 0.121 B- -11043# 303# 170 991881.542 22.236 - 11 91 80 171 Hg -a 3480# 303# 7685# 2# B- * 171 003736# 325# -0 42 107 65 172 Tb x -39850# 503# 8007# 3# B- 8159# 585# 171 957219# 540# - 40 106 66 172 Dy x -48009# 298# 8050# 2# B- 3474# 357# 171 948460# 320# - 38 105 67 172 Ho x -51484# 196# 8066# 1# B- 5000# 196# 171 944730# 210# - 36 104 68 172 Er -56483.612 4.008 8090.410 0.023 B- 890.767 4.543 171 939362.344 4.302 - 34 103 69 172 Tm -57374.379 5.503 8091.041 0.032 B- 1881.067 5.503 171 938406.067 5.907 - 32 102 70 172 Yb -59255.446 0.014 8097.429 0.000 B- -2519.466 2.336 171 936386.658 0.014 - 30 101 71 172 Lu -56735.980 2.336 8078.232 0.014 B- -333.754 24.540 171 939091.417 2.507 - 28 100 72 172 Hf x -56402.226 24.428 8071.743 0.142 B- -5072.248 37.117 171 939449.716 26.224 - 26 99 73 172 Ta x -51329.977 27.945 8037.705 0.162 B- -2232.791 39.520 171 944895.000 30.000 - 24 98 74 172 W x -49097.186 27.945 8020.175 0.162 B- -7560.080 47.974 171 947292.000 30.000 - 22 97 75 172 Re -41537.106 38.995 7971.672 0.227 B- -4293.264 41.036 171 955408.079 41.862 - 20 96 76 172 Os -37243.842 12.782 7942.163 0.074 B- -9864.473 34.832 171 960017.088 13.721 - 18 95 77 172 Ir -a -27379.369 32.402 7880.263 0.188 B- -6272.449 34.023 171 970607.036 34.785 - 16 94 78 172 Pt -21106.920 10.377 7839.247 0.060 B- -11788.914 57.108 171 977340.788 11.139 - 14 93 79 172 Au -a -9318.006 56.158 7766.158 0.326 B- -8259.262 140.853 171 989996.708 60.287 - 12 92 80 172 Hg -a -1058.744 150.079 7713.591 0.873 B- * 171 998863.391 161.116 -0 41 107 66 173 Dy x -43939# 401# 8027# 2# B- 5412# 499# 172 952830# 430# - 39 106 67 173 Ho x -49351# 298# 8054# 2# B- 4304# 357# 172 947020# 320# - 37 105 68 173 Er x -53654# 196# 8074# 1# B- 2602# 196# 172 942400# 210# - 35 104 69 173 Tm p2n -56256.059 4.400 8084.463 0.025 B- 1295.166 4.400 172 939606.632 4.723 - 33 103 70 173 Yb -57551.225 0.011 8087.427 0.000 B- -670.310 1.567 172 938216.215 0.012 - 31 102 71 173 Lu -56880.916 1.567 8079.030 0.009 B- -1469.132 27.989 172 938935.822 1.682 - 29 101 72 173 Hf x -55411.784 27.945 8066.016 0.162 B- -3015.246 39.520 172 940513.000 30.000 - 27 100 73 173 Ta x -52396.538 27.945 8044.064 0.162 B- -3669.155 39.520 172 943750.000 30.000 - 25 99 74 173 W x -48727.383 27.945 8018.333 0.162 B- -5173.518 39.520 172 947689.000 30.000 - 23 98 75 173 Re x -43553.865 27.945 7983.906 0.162 B- -6115.608 31.697 172 953243.000 30.000 - 21 97 76 173 Os -37438.257 14.959 7944.033 0.086 B- -7169.822 18.583 172 959808.375 16.059 - 19 96 77 173 Ir -30268.435 11.026 7898.067 0.064 B- -8325.524 57.052 172 967505.496 11.837 - 17 95 78 173 Pt -a -21942.911 55.977 7845.420 0.324 B- -9110.471 60.421 172 976443.315 60.093 - 15 94 79 173 Au +a -12832.440 22.784 7788.237 0.132 B- -10123# 197# 172 986223.808 24.459 - 13 93 80 173 Hg -a -2710# 196# 7725# 1# B- * 172 997091# 210# -0 42 108 66 174 Dy x -41370# 503# 8012# 3# B- 4319# 585# 173 955587# 540# - 40 107 67 174 Ho x -45690# 298# 8033# 2# B- 6260# 422# 173 950950# 320# - 38 106 68 174 Er x -51949# 298# 8064# 2# B- 1915# 301# 173 944230# 320# - 36 105 69 174 Tm + -53864.512 44.721 8070.642 0.257 B- 3080.000 44.721 173 942174.064 48.010 - 34 104 70 174 Yb -56944.512 0.011 8083.847 0.000 B- -1374.317 1.567 173 938867.548 0.011 - 32 103 71 174 Lu -55570.195 1.567 8071.453 0.009 B- 274.286 2.169 173 940342.938 1.682 - 30 102 72 174 Hf -55844.481 2.259 8068.533 0.013 B- -4103.715 28.036 173 940048.480 2.424 - 28 101 73 174 Ta x -51740.766 27.945 8040.452 0.161 B- -1513.678 39.520 173 944454.000 30.000 - 26 100 74 174 W x -50227.088 27.945 8027.256 0.161 B- -6553.992 39.520 173 946079.000 30.000 - 24 99 75 174 Re x -43673.096 27.945 7985.094 0.161 B- -3677.681 29.767 173 953115.000 30.000 - 22 98 76 174 Os -39995.416 10.254 7959.461 0.059 B- -9131.924 26.395 173 957063.152 11.008 - 20 97 77 174 Ir -30863.492 24.322 7902.483 0.140 B- -5545.329 26.433 173 966866.676 26.111 - 18 96 78 174 Pt -a -25318.163 10.351 7866.117 0.059 B- -11083# 89# 173 972819.832 11.112 - 16 95 79 174 Au -a -14235# 89# 7798# 1# B- -7594# 89# 173 984718# 95# - 14 94 80 174 Hg -a -6641.009 19.211 7749.784 0.110 B- * 173 992870.583 20.624 -0 41 108 67 175 Ho x -43203# 401# 8019# 2# B- 5449# 566# 174 953620# 430# - 39 107 68 175 Er x -48652# 401# 8045# 2# B- 3659# 404# 174 947770# 430# - 37 106 69 175 Tm + -52310.549 50.000 8061.766 0.286 B- 2385.000 50.000 174 943842.313 53.677 - 35 105 70 175 Yb -54695.549 0.071 8070.925 0.000 B- 470.033 1.206 174 941281.910 0.076 - 33 104 71 175 Lu -55165.582 1.207 8069.140 0.007 B- -683.920 1.952 174 940777.308 1.295 - 31 103 72 175 Hf -54481.662 2.282 8060.761 0.013 B- -2073.015 28.038 174 941511.527 2.449 - 29 102 73 175 Ta x -52408.647 27.945 8044.445 0.160 B- -2775.852 39.520 174 943737.000 30.000 - 27 101 74 175 W x -49632.795 27.945 8024.112 0.160 B- -4344.488 39.520 174 946717.000 30.000 - 25 100 75 175 Re x -45288.307 27.945 7994.816 0.160 B- -5182.931 30.324 174 951381.000 30.000 - 23 99 76 175 Os -40105.376 11.775 7960.729 0.067 B- -6710.870 17.089 174 956945.105 12.640 - 21 98 77 175 Ir -33394.506 12.384 7917.910 0.071 B- -7681.040 22.001 174 964149.521 13.295 - 19 97 78 175 Pt -25713.466 18.185 7869.548 0.104 B- -8309.511 42.705 174 972395.457 19.522 - 17 96 79 175 Au -a -17403.955 38.640 7817.595 0.221 B- -9431.379 82.504 174 981316.085 41.481 - 15 95 80 175 Hg -a -7972.576 72.896 7759.231 0.417 B- * 174 991441.086 78.257 -0 42 109 67 176 Ho x -39290# 503# 7997# 3# B- 7340# 643# 175 957820# 540# - 40 108 68 176 Er x -46631# 401# 8034# 2# B- 2741# 413# 175 949940# 430# - 38 107 69 176 Tm + -49371.314 100.000 8045.121 0.568 B- 4120.000 100.000 175 946997.711 107.354 - 36 106 70 176 Yb -53491.314 0.015 8064.085 0.000 B- -109.078 1.212 175 942574.708 0.015 - 34 105 71 176 Lu -53382.236 1.212 8059.020 0.007 B- 1194.085 0.874 175 942691.809 1.301 - 32 104 72 176 Hf -54576.321 1.481 8061.359 0.008 B- -3210.948 30.775 175 941409.905 1.590 - 30 103 73 176 Ta x -51365.374 30.739 8038.670 0.175 B- -723.771 41.543 175 944857.000 33.000 - 28 102 74 176 W x -50641.603 27.945 8030.112 0.159 B- -5578.718 39.520 175 945634.000 30.000 - 26 101 75 176 Re x -45062.885 27.945 7993.970 0.159 B- -2964.945 39.520 175 951623.000 30.000 - 24 100 76 176 Os x -42097.940 27.945 7972.679 0.159 B- -8219.614 32.580 175 954806.000 30.000 - 22 99 77 176 Ir -33878.326 16.750 7921.531 0.095 B- -4944.459 21.035 175 963630.119 17.981 - 20 98 78 176 Pt -28933.867 12.724 7888.992 0.072 B- -10412.904 35.541 175 968938.214 13.660 - 18 97 79 176 Au -a -18520.963 33.185 7825.383 0.189 B- -6736.013 34.998 175 980116.927 35.625 - 16 96 80 176 Hg -11784.950 11.119 7782.665 0.063 B- -12366.544 75.904 175 987348.335 11.937 - 14 95 81 176 Tl -p 581.594 75.086 7707.955 0.427 B- * 176 000624.367 80.607 -0 41 109 68 177 Er x -42858# 503# 8013# 3# B- 4611# 585# 176 953990# 540# - 39 108 69 177 Tm x -47469# 298# 8035# 2# B- 3517# 298# 176 949040# 320# - 37 107 70 177 Yb -n -50986.397 0.220 8049.973 0.001 B- 1397.409 1.240 176 945263.848 0.236 - 35 106 71 177 Lu -52383.806 1.220 8053.448 0.007 B- 496.810 0.791 176 943763.668 1.310 - 33 105 72 177 Hf -52880.616 1.408 8051.835 0.008 B- -1166.000 3.000 176 943230.320 1.511 - 31 104 73 177 Ta - -51714.616 3.314 8040.827 0.019 B- -2012.890 28.141 176 944482.073 3.557 - 29 103 74 177 W x -49701.726 27.945 8025.035 0.158 B- -3432.555 39.520 176 946643.000 30.000 - 27 102 75 177 Re x -46269.170 27.945 8001.222 0.158 B- -4312.708 31.535 176 950328.000 30.000 - 25 101 76 177 Os +a -41956.462 14.613 7972.436 0.083 B- -5909.041 24.576 176 954957.882 15.687 - 23 100 77 177 Ir x -36047.421 19.760 7934.632 0.112 B- -6676.976 24.801 176 961301.500 21.213 - 21 99 78 177 Pt -29370.444 14.988 7892.489 0.085 B- -7825.341 18.297 176 968469.529 16.090 - 19 98 79 177 Au -21545.103 10.496 7843.858 0.059 B- -8762.561 75.786 176 976870.379 11.268 - 17 97 80 177 Hg -a -12782.542 75.056 7789.932 0.424 B- -9442.016 78.098 176 986277.376 80.575 - 15 96 81 177 Tl IT -3340.526 21.629 7732.167 0.122 B- * 176 996413.797 23.219 -0 42 110 68 178 Er x -40260# 596# 7999# 3# B- 3855# 718# 177 956779# 640# - 40 109 69 178 Tm x -44116# 401# 8016# 2# B- 5580# 401# 177 952640# 430# - 38 108 70 178 Yb -nn -49695.475 10.000 8042.841 0.056 B- 642.309 10.250 177 946649.710 10.735 - 36 107 71 178 Lu -50337.784 2.251 8042.054 0.013 B- 2097.451 2.057 177 945960.162 2.416 - 34 106 72 178 Hf -52435.236 1.412 8049.442 0.008 B- -1837# 52# 177 943708.456 1.516 - 32 105 73 178 Ta IT -50598# 52# 8035# 0# B- -191# 50# 177 945681# 56# - 30 104 74 178 W - -50406.936 15.199 8029.257 0.085 B- -4753.483 31.810 177 945885.925 16.316 - 28 103 75 178 Re x -45653.453 27.945 7998.157 0.157 B- -2109.183 31.093 177 950989.000 30.000 - 26 102 76 178 Os -43544.270 13.632 7981.912 0.077 B- -7292.386 24.006 177 953253.300 14.634 - 24 101 77 178 Ir x -36251.884 19.760 7936.549 0.111 B- -4254.365 22.207 177 961082.000 21.213 - 22 100 78 178 Pt -31997.519 10.133 7908.252 0.057 B- -9693.776 14.297 177 965649.248 10.878 - 20 99 79 178 Au -22303.743 10.086 7849.398 0.057 B- -5987.841 14.755 177 976055.945 10.827 - 18 98 80 178 Hg -a -16315.901 10.770 7811.363 0.061 B- -11526# 90# 177 982484.158 11.562 - 16 97 81 178 Tl -a -4790# 89# 7742# 1# B- -8365# 91# 177 994857# 96# - 14 96 82 178 Pb -a 3574.294 23.963 7690.830 0.135 B- * 178 003837.163 25.724 -0 41 110 69 179 Tm x -41601# 503# 8002# 3# B- 4937# 540# 178 955340# 540# - 39 109 70 179 Yb x -46537# 196# 8025# 1# B- 2521# 196# 178 950040# 210# - 37 108 71 179 Lu -49058.918 5.150 8035.073 0.029 B- 1403.989 5.067 178 947333.082 5.528 - 35 107 72 179 Hf -50462.907 1.413 8038.546 0.008 B- -105.584 0.409 178 945825.838 1.517 - 33 106 73 179 Ta -50357.323 1.463 8033.585 0.008 B- -1062.195 14.520 178 945939.187 1.571 - 31 105 74 179 W -49295.127 14.573 8023.281 0.081 B- -2710.847 26.802 178 947079.501 15.644 - 29 104 75 179 Re -46584.280 24.639 8003.766 0.138 B- -3564.785 29.656 178 949989.715 26.450 - 27 103 76 179 Os -43019.495 16.504 7979.480 0.092 B- -4937.781 19.180 178 953816.669 17.718 - 25 102 77 179 Ir -38081.714 9.771 7947.524 0.055 B- -5813.569 12.613 178 959117.596 10.489 - 23 101 78 179 Pt -32268.145 7.977 7910.675 0.045 B- -7279.578 14.157 178 965358.719 8.563 - 21 100 79 179 Au -24988.567 11.696 7865.637 0.065 B- -8060.433 29.669 178 973173.668 12.555 - 19 99 80 179 Hg -16928.134 27.267 7816.236 0.152 B- -8659.639 47.417 178 981826.899 29.272 - 17 98 81 179 Tl -a -8268.495 38.793 7763.487 0.217 B- -10319.134 84.963 178 991123.405 41.646 - 15 97 82 179 Pb -a 2050.639 75.590 7701.468 0.422 B- * 179 002201.452 81.149 -0 42 111 69 180 Tm x -37920# 503# 7982# 3# B- 6680# 585# 179 959291# 540# - 40 110 70 180 Yb x -44600# 298# 8015# 2# B- 2076# 306# 179 952120# 320# - 38 109 71 180 Lu + -46676.348 70.725 8022.038 0.393 B- 3103.000 70.711 179 949890.876 75.926 - 36 108 72 180 Hf -49779.348 1.419 8034.930 0.008 B- -846.471 2.269 179 946559.669 1.522 - 34 107 73 180 Ta +n -48932.877 1.939 8025.881 0.011 B- 703.238 2.281 179 947468.392 2.081 - 32 106 74 180 W -49636.115 1.436 8025.442 0.008 B- -3798.757 21.440 179 946713.435 1.542 - 30 105 75 180 Re x -45837.359 21.392 7999.991 0.119 B- -1479.549 26.950 179 950791.568 22.965 - 28 104 76 180 Os -44357.810 16.391 7987.425 0.091 B- -6380.284 27.200 179 952379.930 17.596 - 26 103 77 180 Ir x -37977.526 21.706 7947.633 0.121 B- -3541.649 24.323 179 959229.446 23.302 - 24 102 78 180 Pt +a -34435.877 10.974 7923.611 0.061 B- -8810.368 11.973 179 963031.563 11.781 - 22 101 79 180 Au -25625.509 4.786 7870.318 0.027 B- -5375.062 13.524 179 972489.883 5.137 - 20 100 80 180 Hg -20250.447 12.649 7836.110 0.070 B- -10863.800 61.329 179 978260.249 13.579 - 18 99 81 180 Tl -a -9386.647 60.010 7771.409 0.333 B- -7445.267 61.277 179 989923.019 64.423 - 16 98 82 180 Pb -a -1941.380 12.396 7725.700 0.069 B- * 179 997915.842 13.307 -0 43 112 69 181 Tm x -35170# 596# 7967# 3# B- 5918# 667# 180 962243# 640# - 41 111 70 181 Yb x -41088# 298# 7996# 2# B- 3709# 324# 180 955890# 320# - 39 110 71 181 Lu x -44797.410 125.752 8011.929 0.695 B- 2605.421 125.760 180 951908.000 135.000 - 37 109 72 181 Hf -n -47402.831 1.420 8022.002 0.008 B- 1035.480 1.834 180 949110.965 1.524 - 35 108 73 181 Ta -48438.311 1.403 8023.400 0.008 B- -204.493 1.854 180 947999.331 1.506 - 33 107 74 181 W -n -48233.818 1.445 8017.948 0.008 B- -1716.427 12.629 180 948218.863 1.551 - 31 106 75 181 Re 4n -46517.391 12.549 8004.143 0.069 B- -2967.428 28.275 180 950061.523 13.471 - 29 105 76 181 Os -43549.963 25.338 7983.426 0.140 B- -4086.935 25.876 180 953247.188 27.201 - 27 104 77 181 Ir +a -39463.028 5.245 7956.523 0.029 B- -5081.517 14.660 180 957634.694 5.631 - 25 103 78 181 Pt -34381.511 13.689 7924.126 0.076 B- -6510.375 24.216 180 963089.927 14.695 - 23 102 79 181 Au -a -27871.136 19.976 7883.835 0.110 B- -7210.000 25.212 180 970079.103 21.445 - 21 101 80 181 Hg -20661.136 15.382 7839.679 0.085 B- -7862.401 17.876 180 977819.357 16.513 - 19 100 81 181 Tl -12798.735 9.108 7791.918 0.050 B- -9681.385 75.959 180 986259.992 9.778 - 17 99 82 181 Pb -a -3117.350 75.411 7734.107 0.417 B- * 180 996653.386 80.957 -0 42 112 70 182 Yb x -38820# 401# 7984# 2# B- 3060# 446# 181 958325# 430# - 40 111 71 182 Lu x -41880# 196# 7996# 1# B- 4170# 196# 181 955040# 210# - 38 110 72 182 Hf -nn -46049.508 6.165 8014.837 0.034 B- 380.425 6.274 181 950563.816 6.618 - 36 109 73 182 Ta -46429.934 1.405 8012.628 0.008 B- 1816.126 1.399 181 950155.413 1.508 - 34 108 74 182 W -48246.060 0.738 8018.308 0.004 B- -2800.000 101.980 181 948205.721 0.791 - 32 107 75 182 Re IT -45446.060 101.983 7998.625 0.560 B- -836.955 104.276 181 951211.645 109.483 - 30 106 76 182 Os -44609.104 21.745 7989.728 0.119 B- -5557.426 30.207 181 952110.153 23.344 - 28 105 77 182 Ir -39051.679 20.967 7954.894 0.115 B- -2883.230 24.720 181 958076.296 22.509 - 26 104 78 182 Pt -36168.449 13.095 7934.754 0.072 B- -7867.680 24.123 181 961171.571 14.057 - 24 103 79 182 Au -a -28300.768 20.260 7887.226 0.111 B- -4723.846 22.501 181 969617.874 21.749 - 22 102 80 182 Hg -23576.922 9.790 7856.972 0.054 B- -10248.994 15.363 181 974689.132 10.510 - 20 101 81 182 Tl -a -13327.927 11.839 7796.360 0.065 B- -6502.815 16.927 181 985691.880 12.709 - 18 100 82 182 Pb -a -6825.112 12.098 7756.332 0.066 B- * 181 992672.940 12.987 -0 43 113 70 183 Yb x -35100# 401# 7964# 2# B- 4616# 408# 182 962319# 430# - 41 112 71 183 Lu x -39716.110 80.108 7984.812 0.438 B- 3566.687 85.553 182 957363.000 86.000 - 39 111 72 183 Hf + -43282.796 30.034 8000.027 0.164 B- 2010.000 30.000 182 953534.004 32.242 - 37 110 73 183 Ta -n -45292.796 1.419 8006.735 0.008 B- 1072.783 1.413 182 951376.180 1.523 - 35 109 74 183 W -46365.580 0.737 8008.322 0.004 B- -556.000 8.000 182 950224.500 0.790 - 33 108 75 183 Re - -45809.580 8.034 8001.009 0.044 B- -2145.537 50.405 182 950821.390 8.624 - 31 107 76 183 Os -43664.043 49.760 7985.010 0.272 B- -3460.732 52.733 182 953124.719 53.420 - 29 106 77 183 Ir -40203.311 24.398 7961.823 0.133 B- -4430.824 28.923 182 956839.968 26.191 - 27 105 78 183 Pt -35772.487 15.533 7933.336 0.085 B- -5581.004 18.168 182 961596.653 16.675 - 25 104 79 183 Au -30191.483 9.423 7898.564 0.051 B- -6386.809 11.789 182 967588.108 10.116 - 23 103 80 183 Hg -23804.674 7.084 7859.388 0.039 B- -7217.417 11.716 182 974444.629 7.604 - 21 102 81 183 Tl -16587.257 9.331 7815.673 0.051 B- -9012.038 29.657 182 982192.846 10.017 - 19 101 82 183 Pb -a -7575.218 28.151 7762.152 0.154 B- * 182 991867.668 30.221 -0 44 114 70 184 Yb x -32540# 503# 7951# 3# B- 3872# 585# 183 965067# 540# - 42 113 71 184 Lu x -36412# 298# 7967# 2# B- 5087# 301# 183 960910# 320# - 40 112 72 184 Hf + -41499.373 39.706 7990.722 0.216 B- 1340.000 30.000 183 955448.587 42.625 - 38 111 73 184 Ta + -42839.373 26.010 7993.752 0.141 B- 2866.000 26.000 183 954010.038 27.923 - 36 110 74 184 W -45705.373 0.731 8005.077 0.004 B- -1485.739 4.198 183 950933.260 0.785 - 34 109 75 184 Re -44219.634 4.275 7992.750 0.023 B- 32.898 4.140 183 952528.267 4.589 - 32 108 76 184 Os -44252.533 0.827 7988.677 0.005 B- -4641.682 27.957 183 952492.949 0.887 - 30 107 77 184 Ir x -39610.851 27.945 7959.198 0.152 B- -2276.608 31.997 183 957476.000 30.000 - 28 106 78 184 Pt -37334.243 15.584 7942.574 0.085 B- -7015.533 27.185 183 959920.039 16.730 - 26 105 79 184 Au -a -30318.710 22.275 7900.194 0.121 B- -3969.745 24.442 183 967451.524 23.912 - 24 104 80 184 Hg -26348.965 10.062 7874.367 0.055 B- -9465.723 14.200 183 971713.221 10.802 - 22 103 81 184 Tl -16883.242 10.020 7818.671 0.054 B- -5831.720 16.260 183 981875.093 10.757 - 20 102 82 184 Pb -11051.522 12.806 7782.725 0.070 B- -12114.590 79.153 183 988135.702 13.748 - 18 101 83 184 Bi -a 1063.068 78.110 7712.633 0.425 B- * 184 001141.250 83.854 -0 45 115 70 185 Yb x -28500# 503# 7929# 3# B- 5388# 585# 184 969404# 540# - 43 114 71 185 Lu x -33888# 298# 7954# 2# B- 4432# 305# 184 963620# 320# - 41 113 72 185 Hf x -38319.800 64.273 7973.970 0.347 B- 3074.492 65.815 184 958862.000 69.000 - 39 112 73 185 Ta + -41394.293 14.161 7986.360 0.077 B- 1993.500 14.142 184 955561.396 15.202 - 37 111 74 185 W -43387.793 0.733 7992.907 0.004 B- 431.234 0.661 184 953421.286 0.786 - 35 110 75 185 Re -43819.027 0.818 7991.009 0.004 B- -1013.147 0.419 184 952958.337 0.877 - 33 109 76 185 Os -42805.880 0.830 7981.304 0.004 B- -2470.326 27.957 184 954045.995 0.891 - 31 108 77 185 Ir x -40335.553 27.945 7963.722 0.151 B- -3647.414 38.055 184 956698.000 30.000 - 29 107 78 185 Pt -36688.140 25.832 7939.777 0.140 B- -4829.997 25.963 184 960613.659 27.731 - 27 106 79 185 Au x -31858.143 2.608 7909.440 0.014 B- -5674.477 13.886 184 965798.874 2.800 - 25 105 80 185 Hg -26183.666 13.639 7874.538 0.074 B- -6425.925 24.767 184 971890.676 14.641 - 23 104 81 185 Tl IT -19757.741 20.674 7835.575 0.112 B- -8216.521 26.249 184 978789.191 22.194 - 21 103 82 185 Pb -a -11541.220 16.175 7786.932 0.087 B- -9305# 83# 184 987609.989 17.364 - 19 102 83 185 Bi IT -2236# 81# 7732# 0# B- * 184 997600# 87# -0 44 115 71 186 Lu x -30210# 401# 7935# 2# B- 6214# 404# 185 967568# 430# - 42 114 72 186 Hf x -36424.210 51.232 7964.302 0.275 B- 2183.318 78.906 185 960897.000 55.000 - 40 113 73 186 Ta + -38607.528 60.012 7971.835 0.323 B- 3901.000 60.000 185 958553.111 64.425 - 38 112 74 186 W -42508.528 1.212 7988.601 0.007 B- -581.442 1.244 185 954365.215 1.300 - 36 111 75 186 Re -41927.086 0.826 7981.269 0.004 B- 1072.857 0.837 185 954989.419 0.886 - 34 110 76 186 Os -42999.943 0.761 7982.831 0.004 B- -3827.596 16.543 185 953837.660 0.816 - 32 109 77 186 Ir x -39172.346 16.526 7958.047 0.089 B- -1307.903 27.312 185 957946.754 17.740 - 30 108 78 186 Pt -37864.443 21.745 7946.809 0.117 B- -6149.591 30.207 185 959350.846 23.344 - 28 107 79 186 Au -31714.852 20.967 7909.540 0.113 B- -3175.756 23.987 185 965952.703 22.509 - 26 106 80 186 Hg -28539.097 11.650 7888.260 0.063 B- -8652.484 25.209 185 969362.017 12.507 - 24 105 81 186 Tl x -19886.613 22.356 7837.535 0.120 B- -5204.588 25.078 185 978650.841 24.000 - 22 104 82 186 Pb -a -14682.026 11.363 7805.347 0.061 B- -11535.814 20.329 185 984238.196 12.199 - 20 103 83 186 Bi -a -3146.212 16.857 7739.121 0.091 B- -7247.186 24.870 185 996622.402 18.096 - 18 102 84 186 Po -a 4100.974 18.286 7695.951 0.098 B- * 186 004402.577 19.630 -0 45 116 71 187 Lu x -27580# 401# 7922# 2# B- 5237# 499# 186 970392# 430# - 43 115 72 187 Hf x -32817# 298# 7946# 2# B- 4079# 303# 186 964770# 320# - 41 114 73 187 Ta x -36895.546 55.890 7963.212 0.299 B- 3008.424 55.903 186 960391.000 60.000 - 39 113 74 187 W -39903.970 1.212 7975.116 0.006 B- 1312.508 1.122 186 957161.323 1.300 - 37 112 75 187 Re -41216.478 0.736 7977.951 0.004 B- 2.467 0.002 186 955752.288 0.790 - 35 111 76 187 Os -41218.945 0.736 7973.780 0.004 B- -1669.572 27.955 186 955749.640 0.790 - 33 110 77 187 Ir x -39549.372 27.945 7960.668 0.149 B- -2864.323 36.868 186 957542.000 30.000 - 31 109 78 187 Pt -36685.050 24.048 7941.168 0.129 B- -3657.212 27.377 186 960616.976 25.816 - 29 108 79 187 Au -33027.838 22.308 7917.427 0.119 B- -4909.908 26.287 186 964543.155 23.948 - 27 107 80 187 Hg -28117.930 13.905 7886.987 0.074 B- -5673.343 16.067 186 969814.158 14.928 - 25 106 81 187 Tl -22444.587 8.048 7852.464 0.043 B- -7457.628 9.525 186 975904.743 8.640 - 23 105 82 187 Pb -14986.959 5.094 7808.400 0.027 B- -8603.688 11.227 186 983910.836 5.468 - 21 104 83 187 Bi -a -6383.271 10.005 7758.208 0.054 B- -9211.868 33.430 186 993147.276 10.740 - 19 103 84 187 Po -a 2828.597 31.898 7704.763 0.171 B- * 187 003036.624 34.243 -0 46 117 71 188 Lu x -23790# 503# 7902# 3# B- 7089# 585# 187 974460# 540# - 44 116 72 188 Hf x -30879# 298# 7936# 2# B- 2733# 303# 187 966850# 320# - 42 115 73 188 Ta x -33612.030 54.958 7946.321 0.292 B- 5055.781 55.045 187 963916.000 59.000 - 40 114 74 188 W + -38667.811 3.089 7969.052 0.016 B- 349.000 3.000 187 958488.395 3.316 - 38 113 75 188 Re -n -39016.811 0.738 7966.747 0.004 B- 2120.422 0.152 187 958113.728 0.791 - 36 112 76 188 Os -41137.233 0.734 7973.864 0.004 B- -2792.326 9.416 187 955837.361 0.787 - 34 111 77 188 Ir -38344.907 9.423 7954.850 0.050 B- -523.979 8.686 187 958835.046 10.116 - 32 110 78 188 Pt -37820.929 5.304 7947.902 0.028 B- -5449.621 5.953 187 959397.560 5.694 - 30 109 79 188 Au x -32371.308 2.701 7914.753 0.014 B- -2169.394 12.569 187 965247.969 2.900 - 28 108 80 188 Hg -30201.914 12.275 7899.052 0.065 B- -7865.513 32.325 187 967576.910 13.178 - 26 107 81 188 Tl x -22336.400 29.904 7853.053 0.159 B- -4521.198 31.734 187 976020.886 32.103 - 24 106 82 188 Pb -a -17815.202 10.622 7824.843 0.057 B- -10620.515 15.427 187 980874.592 11.403 - 22 105 83 188 Bi -a -7194.687 11.187 7764.189 0.060 B- -6650.374 22.892 187 992276.184 12.009 - 20 104 84 188 Po -a -544.313 19.973 7724.653 0.106 B- * 187 999415.655 21.441 -0 45 117 72 189 Hf x -27162# 298# 7917# 2# B- 4667# 357# 188 970840# 320# - 43 116 73 189 Ta x -31829# 196# 7938# 1# B- 3788# 200# 188 965830# 210# - 41 115 74 189 W x -35617.536 40.054 7953.454 0.212 B- 2361.507 40.883 188 961763.000 43.000 - 39 114 75 189 Re +p -37979.043 8.191 7961.809 0.043 B- 1007.702 8.167 188 959227.817 8.793 - 37 113 76 189 Os -38986.745 0.666 7963.002 0.004 B- -537.159 12.563 188 958146.005 0.715 - 35 112 77 189 Ir -38449.586 12.576 7956.020 0.067 B- -1980.238 13.636 188 958722.669 13.500 - 33 111 78 189 Pt -36469.348 10.090 7941.403 0.053 B- -2887.394 22.474 188 960848.542 10.832 - 31 110 79 189 Au x -33581.955 20.081 7921.987 0.106 B- -3955.554 37.401 188 963948.286 21.558 - 29 109 80 189 Hg -29626.401 31.553 7896.919 0.167 B- -5010.300 32.643 188 968194.748 33.873 - 27 108 81 189 Tl -24616.100 8.368 7866.270 0.044 B- -6772.066 16.364 188 973573.527 8.983 - 25 107 82 189 Pb -17844.035 14.062 7826.299 0.074 B- -7779.374 25.150 188 980843.639 15.096 - 23 106 83 189 Bi -a -10064.660 20.851 7780.999 0.110 B- -8642.656 30.354 188 989195.141 22.384 - 21 105 84 189 Po -a -1422.005 22.059 7731.131 0.117 B- * 188 998473.415 23.681 -0 46 118 72 190 Hf x -25030# 401# 7907# 2# B- 3483# 446# 189 973129# 430# - 44 117 73 190 Ta x -28513# 196# 7921# 1# B- 5869# 200# 189 969390# 210# - 42 116 74 190 W -34382.313 39.726 7947.573 0.209 B- 1253.517 63.522 189 963089.066 42.647 - 40 115 75 190 Re -35635.830 70.852 7950.053 0.373 B- 3071.941 70.854 189 961743.360 76.063 - 38 114 76 190 Os -38707.771 0.650 7962.104 0.003 B- -1954.227 1.213 189 958445.496 0.697 - 36 113 77 190 Ir +n -36753.544 1.370 7947.701 0.007 B- 552.906 1.282 189 960543.445 1.470 - 34 112 78 190 Pt -37306.450 0.657 7946.493 0.003 B- -4472.917 3.509 189 959949.876 0.704 - 32 111 79 190 Au x -32833.533 3.447 7918.834 0.018 B- -1462.836 16.276 189 964751.750 3.700 - 30 110 80 190 Hg -31370.697 15.907 7907.017 0.084 B- -6998.670 17.782 189 966322.169 17.076 - 28 109 81 190 Tl +a -24372.027 7.948 7866.064 0.042 B- -3955.382 14.825 189 973835.551 8.532 - 26 108 82 190 Pb -a -20416.645 12.514 7841.129 0.066 B- -9817.066 25.800 189 978081.828 13.434 - 24 107 83 190 Bi -a -10599.579 22.562 7785.342 0.119 B- -6035.742 26.275 189 988620.883 24.221 - 22 106 84 190 Po -a -4563.837 13.465 7749.458 0.071 B- * 189 995100.519 14.455 -0 45 118 73 191 Ta x -26492# 298# 7911# 2# B- 4684# 301# 190 971560# 320# - 43 117 74 191 W x -31176.173 41.917 7931.435 0.219 B- 3174.124 43.156 190 966531.000 45.000 - 41 116 75 191 Re +p -34350.296 10.265 7943.957 0.054 B- 2044.889 10.244 190 963123.437 11.019 - 39 115 76 191 Os -36395.185 0.659 7950.568 0.003 B- 313.570 1.141 190 960928.159 0.707 - 37 114 77 191 Ir -36708.756 1.311 7948.113 0.007 B- -1010.518 3.636 190 960591.527 1.406 - 35 113 78 191 Pt -35698.237 4.127 7938.727 0.022 B- -1900.333 6.426 190 961676.363 4.430 - 33 112 79 191 Au -33797.904 4.926 7924.681 0.026 B- -3206.008 22.710 190 963716.455 5.288 - 31 111 80 191 Hg -30591.896 22.280 7903.800 0.117 B- -4308.951 23.461 190 967158.247 23.918 - 29 110 81 191 Tl +a -26282.945 7.349 7877.144 0.038 B- -6051.827 37.978 190 971784.096 7.889 - 27 109 82 191 Pb x -20231.118 37.260 7841.363 0.195 B- -6991.772 38.005 190 978281.000 40.000 - 25 108 83 191 Bi -13239.347 7.487 7800.661 0.039 B- -8170.612 10.320 190 985786.975 8.037 - 23 107 84 191 Po -5068.735 7.103 7753.786 0.037 B- -8932.653 17.600 190 994558.488 7.624 - 21 106 85 191 At -a 3863.917 16.103 7702.923 0.084 B- * 191 004148.086 17.287 -0 46 119 73 192 Ta x -23064# 401# 7894# 2# B- 6586# 446# 191 975240# 430# - 44 118 74 192 W x -29649# 196# 7924# 1# B- 1939# 208# 191 968170# 210# - 42 117 75 192 Re x -31588.825 70.794 7930.238 0.369 B- 4293.366 70.831 191 966088.000 76.000 - 40 116 76 192 Os -35882.191 2.315 7948.525 0.012 B- -1046.630 2.397 191 961478.881 2.485 - 38 115 77 192 Ir -34835.561 1.314 7938.999 0.007 B- 1452.896 2.274 191 962602.485 1.410 - 36 114 78 192 Pt -36288.457 2.570 7942.491 0.013 B- -3516.341 15.617 191 961042.736 2.758 - 34 113 79 192 Au - -32772.116 15.827 7920.102 0.082 B- -760.563 22.178 191 964817.684 16.991 - 32 112 80 192 Hg x -32011.553 15.537 7912.066 0.081 B- -6139.307 35.277 191 965634.182 16.679 - 30 111 81 192 Tl x -25872.246 31.671 7876.016 0.165 B- -3316.226 34.348 191 972225.000 34.000 - 28 110 82 192 Pb -a -22556.020 13.295 7854.669 0.069 B- -9021.485 32.917 191 975785.115 14.273 - 26 109 83 192 Bi -a -13534.535 30.112 7803.608 0.157 B- -5463.873 32.096 191 985470.078 32.326 - 24 108 84 192 Po -a -8070.661 11.110 7771.075 0.058 B- -10996.516 30.008 191 991335.788 11.926 - 22 107 85 192 At -a 2925.854 27.876 7709.727 0.145 B- * 192 003141.034 29.926 -0 47 120 73 193 Ta x -20870# 401# 7884# 2# B- 5417# 446# 192 977595# 430# - 45 119 74 193 W x -26287# 196# 7908# 1# B- 3945# 199# 192 971780# 210# - 43 118 75 193 Re x -30231.638 39.123 7923.937 0.203 B- 3162.652 39.192 192 967545.000 42.000 - 41 117 76 193 Os -33394.289 2.321 7936.270 0.012 B- 1141.946 2.400 192 964149.753 2.491 - 39 116 77 193 Ir -34536.235 1.328 7938.133 0.007 B- -56.628 0.300 192 962923.824 1.425 - 37 115 78 193 Pt -34479.608 1.359 7933.786 0.007 B- -1074.787 8.768 192 962984.616 1.458 - 35 114 79 193 Au -33404.821 8.674 7924.164 0.045 B- -2342.642 14.370 192 964138.447 9.311 - 33 113 80 193 Hg -31062.179 15.505 7907.972 0.080 B- -3584.967 16.894 192 966653.377 16.645 - 31 112 81 193 Tl x -27477.212 6.707 7885.344 0.035 B- -5282.723 50.028 192 970501.997 7.200 - 29 111 82 193 Pb x -22194.490 49.577 7853.919 0.257 B- -6309.931 50.152 192 976173.234 53.222 - 27 110 83 193 Bi -15884.559 7.576 7817.171 0.039 B- -7559.241 16.387 192 982947.223 8.132 - 25 109 84 193 Po -a -8325.318 14.531 7773.950 0.075 B- -8257.998 26.059 192 991062.403 15.599 - 23 108 85 193 At -a -67.320 21.632 7727.109 0.112 B- -9110.231 33.144 192 999927.728 23.222 - 21 107 86 193 Rn -a 9042.911 25.112 7675.852 0.130 B- * 193 009707.964 26.958 -0 48 121 73 194 Ta x -17300# 503# 7866# 3# B- 7227# 585# 193 981428# 540# - 46 120 74 194 W x -24526# 298# 7899# 2# B- 2711# 357# 193 973670# 320# - 44 119 75 194 Re x -27237# 196# 7909# 1# B- 5198# 196# 193 970760# 210# - 42 118 76 194 Os + -32435.108 2.403 7932.022 0.012 B- 96.600 2.000 193 965179.477 2.579 - 40 117 77 194 Ir -n -32531.708 1.332 7928.487 0.007 B- 2228.362 1.257 193 965075.773 1.430 - 38 116 78 194 Pt -34760.070 0.496 7935.941 0.003 B- -2548.134 2.117 193 962683.527 0.532 - 36 115 79 194 Au +3n -32211.936 2.118 7918.774 0.011 B- -27.991 3.581 193 965419.062 2.273 - 34 114 80 194 Hg x -32183.945 2.888 7914.597 0.015 B- -5246.454 14.268 193 965449.111 3.100 - 32 113 81 194 Tl x -26937.491 13.972 7883.520 0.072 B- -2729.552 22.343 193 971081.411 15.000 - 30 112 82 194 Pb -24207.940 17.435 7865.418 0.090 B- -8179.128 18.498 193 974011.706 18.717 - 28 111 83 194 Bi +a -16028.811 6.178 7819.225 0.032 B- -5024.156 14.313 193 982792.362 6.632 - 26 110 84 194 Po -a -11004.655 12.911 7789.294 0.067 B- -10284.492 28.076 193 988186.015 13.860 - 24 109 85 194 At -a -720.163 24.931 7732.249 0.129 B- -6443.658 30.119 193 999226.872 26.764 - 22 108 86 194 Rn -a 5723.495 16.899 7695.001 0.087 B- * 194 006144.424 18.141 -0 47 121 74 195 W x -21010# 298# 7882# 2# B- 4569# 422# 194 977445# 320# - 45 120 75 195 Re x -25579# 298# 7902# 2# B- 3933# 303# 194 972540# 320# - 43 119 76 195 Os x -29511.593 55.890 7917.744 0.287 B- 2180.658 55.906 194 968318.000 60.000 - 41 118 77 195 Ir -n -31692.251 1.333 7924.915 0.007 B- 1101.598 1.264 194 965976.967 1.431 - 39 117 78 195 Pt -32793.849 0.503 7926.552 0.003 B- -226.817 1.000 194 964794.353 0.539 - 37 116 79 195 Au -32567.031 1.119 7921.377 0.006 B- -1553.638 23.156 194 965037.851 1.201 - 35 115 80 195 Hg -31013.393 23.142 7909.397 0.119 B- -2858.145 25.657 194 966705.751 24.843 - 33 114 81 195 Tl -28155.248 11.093 7890.728 0.057 B- -4447.555 21.106 194 969774.096 11.909 - 31 113 82 195 Pb -23707.693 17.960 7863.908 0.092 B- -5682.132 18.722 194 974548.743 19.280 - 29 112 83 195 Bi -18025.561 5.287 7830.757 0.027 B- -6969.303 37.737 194 980648.762 5.675 - 27 111 84 195 Po -a -11056.259 37.364 7791.005 0.192 B- -7585.964 38.571 194 988130.617 40.112 - 25 110 85 195 At -a -3470.295 9.573 7748.091 0.049 B- -8520.575 51.401 194 996274.485 10.276 - 23 109 86 195 Rn -a 5050.281 50.502 7700.383 0.259 B- * 195 005421.699 54.216 -0 48 122 74 196 W x -18880# 401# 7872# 2# B- 3662# 499# 195 979731# 430# - 46 121 75 196 Re x -22542# 298# 7887# 2# B- 5735# 301# 195 975800# 320# - 44 120 76 196 Os +pp -28277.105 40.055 7912.229 0.204 B- 1158.388 55.495 195 969643.277 43.000 - 42 119 77 196 Ir + -29435.493 38.414 7914.148 0.196 B- 3209.016 38.411 195 968399.696 41.239 - 40 118 78 196 Pt -32644.510 0.510 7926.529 0.003 B- -1505.803 2.960 195 964954.675 0.547 - 38 117 79 196 Au -31138.706 2.962 7914.855 0.015 B- 687.235 3.118 195 966571.221 3.179 - 36 116 80 196 Hg -31825.941 2.946 7914.369 0.015 B- -4329.349 12.463 195 965833.444 3.163 - 34 115 81 196 Tl x -27496.592 12.109 7888.289 0.062 B- -2148.280 14.356 195 970481.192 13.000 - 32 114 82 196 Pb -25348.312 7.710 7873.337 0.039 B- -7339.281 25.616 195 972787.466 8.277 - 30 113 83 196 Bi x -18009.031 24.428 7831.900 0.125 B- -4535.989 27.916 195 980666.509 26.224 - 28 112 84 196 Po -a -13473.042 13.512 7804.766 0.069 B- -9558.365 33.162 195 985536.094 14.506 - 26 111 85 196 At -a -3914.677 30.284 7752.007 0.155 B- -5885.668 33.540 195 995797.421 32.511 - 24 110 86 196 Rn -a 1970.991 14.417 7717.987 0.074 B- * 196 002115.945 15.476 -0 49 123 74 197 W x -15140# 401# 7854# 2# B- 5363# 499# 196 983747# 430# - 47 122 75 197 Re x -20502# 298# 7878# 2# B- 4807# 357# 196 977990# 320# - 45 121 76 197 Os x -25309# 196# 7898# 1# B- 2955# 197# 196 972830# 210# - 43 120 77 197 Ir +p -28264.105 20.110 7908.999 0.102 B- 2155.645 20.106 196 969657.233 21.588 - 41 119 78 197 Pt -30419.750 0.536 7915.971 0.003 B- 719.988 0.502 196 967343.053 0.575 - 39 118 79 197 Au -31139.738 0.542 7915.654 0.003 B- -599.509 3.202 196 966570.114 0.581 - 37 117 80 197 Hg -30540.229 3.207 7908.640 0.016 B- -2198.580 16.637 196 967213.713 3.442 - 35 116 81 197 Tl +a -28341.649 16.325 7893.508 0.083 B- -3596.247 17.014 196 969573.986 17.526 - 33 115 82 197 Pb -24745.401 4.804 7871.282 0.024 B- -5058.210 9.619 196 973434.717 5.157 - 31 114 83 197 Bi +a -19687.191 8.333 7841.634 0.042 B- -6329.202 50.373 196 978864.929 8.946 - 29 113 84 197 Po -a -13357.990 49.679 7805.535 0.252 B- -7002.739 50.317 196 985659.607 53.332 - 27 112 85 197 At -6355.250 7.983 7766.017 0.041 B- -7865.603 18.054 196 993177.357 8.570 - 25 111 86 197 Rn -a 1510.353 16.193 7722.118 0.082 B- -8743.618 56.762 197 001621.430 17.383 - 23 110 87 197 Fr -a 10253.971 54.404 7673.763 0.276 B- * 197 011008.090 58.404 -0 48 123 75 198 Re x -17139# 401# 7862# 2# B- 6697# 446# 197 981600# 430# - 46 122 76 198 Os x -23837# 196# 7891# 1# B- 1984# 277# 197 974410# 210# - 44 121 77 198 Ir x -25821# 196# 7897# 1# B- 4083# 196# 197 972280# 210# - 42 120 78 198 Pt -29903.999 2.100 7914.150 0.011 B- -323.219 2.059 197 967896.734 2.254 - 40 119 79 198 Au -29580.781 0.540 7908.567 0.003 B- 1373.530 0.490 197 968243.724 0.579 - 38 118 80 198 Hg -30954.310 0.458 7911.552 0.002 B- -3425.564 7.559 197 966769.179 0.491 - 36 117 81 198 Tl x -27528.746 7.545 7890.300 0.038 B- -1461.257 11.554 197 970446.673 8.100 - 34 116 82 198 Pb -26067.489 8.750 7878.969 0.044 B- -6698.003 29.283 197 972015.397 9.393 - 32 115 83 198 Bi x -19369.486 27.945 7841.189 0.141 B- -3896.134 32.932 197 979206.000 30.000 - 30 114 84 198 Po -15473.352 17.424 7817.561 0.088 B- -8758.839 18.386 197 983388.672 18.705 - 28 113 85 198 At x -6714.513 5.868 7769.373 0.030 B- -5484.155 14.647 197 992791.673 6.300 - 26 112 86 198 Rn -a -1230.358 13.420 7737.724 0.068 B- -10804.382 34.905 197 998679.156 14.406 - 24 111 87 198 Fr -a 9574.024 32.222 7679.205 0.163 B- * 198 010278.138 34.591 -0 49 124 75 199 Re x -14860# 401# 7851# 2# B- 5623# 446# 198 984047# 430# - 47 123 76 199 Os x -20484# 196# 7875# 1# B- 3915# 200# 198 978010# 210# - 45 122 77 199 Ir p-2n -24398.515 41.054 7891.206 0.206 B- 2990.167 41.003 198 973807.115 44.073 - 43 121 78 199 Pt -n -27388.682 2.159 7902.300 0.011 B- 1705.059 2.120 198 970597.038 2.317 - 41 120 79 199 Au -29093.741 0.542 7906.937 0.003 B- 452.327 0.613 198 968766.582 0.581 - 39 119 80 199 Hg -29546.068 0.526 7905.279 0.003 B- -1486.674 27.950 198 968280.989 0.564 - 37 118 81 199 Tl x -28059.394 27.945 7893.877 0.140 B- -2827.589 29.679 198 969877.000 30.000 - 35 117 82 199 Pb +a -25231.804 9.996 7875.736 0.050 B- -4434.239 14.547 198 972912.542 10.730 - 33 116 83 199 Bi -20797.566 10.568 7849.522 0.053 B- -5589.083 20.919 198 977672.893 11.345 - 31 115 84 199 Po -a -15208.483 18.060 7817.505 0.091 B- -6385.111 18.845 198 983673.021 19.387 - 29 114 85 199 At -8823.372 5.384 7781.488 0.027 B- -7323.921 37.972 198 990527.719 5.780 - 27 113 86 199 Rn -a -1499.451 37.588 7740.753 0.189 B- -8270.844 40.015 198 998390.273 40.352 - 25 112 87 199 Fr -a 6771.393 13.726 7695.259 0.069 B- * 199 007269.389 14.734 -0 48 124 76 200 Os x -18779# 298# 7868# 1# B- 2832# 357# 199 979840# 320# - 46 123 77 200 Ir x -21611# 196# 7878# 1# B- 4988# 197# 199 976800# 210# - 44 122 78 200 Pt -nn -26599.160 20.110 7899.198 0.101 B- 640.932 33.439 199 971444.625 21.588 - 42 121 79 200 Au -27240.092 26.717 7898.491 0.134 B- 2263.178 26.719 199 970756.556 28.681 - 40 120 80 200 Hg -29503.270 0.529 7905.895 0.003 B- -2456.040 5.735 199 968326.934 0.568 - 38 119 81 200 Tl - -27047.230 5.759 7889.703 0.029 B- -796.176 12.340 199 970963.602 6.182 - 36 118 82 200 Pb 4n -26251.054 10.927 7881.810 0.055 B- -5880.299 24.852 199 971818.332 11.730 - 34 117 83 200 Bi +a -20370.755 22.321 7848.497 0.112 B- -3428.994 23.573 199 978131.093 23.962 - 32 116 84 200 Po -16941.761 7.579 7827.440 0.038 B- -7953.869 25.612 199 981812.270 8.135 - 30 115 85 200 At -a -8987.892 24.465 7783.759 0.122 B- -4983.127 28.030 199 990351.100 26.264 - 28 114 86 200 Rn -a -4004.765 13.681 7754.932 0.068 B- -10137.263 33.529 199 995700.707 14.686 - 26 113 87 200 Fr -a 6132.498 30.611 7700.334 0.153 B- * 200 006583.507 32.861 -0 49 125 76 201 Os x -15239# 298# 7851# 1# B- 4657# 357# 200 983640# 320# - 47 124 77 201 Ir x -19897# 196# 7871# 1# B- 3844# 202# 200 978640# 210# - 45 123 78 201 Pt + -23740.714 50.103 7885.833 0.249 B- 2660.000 50.000 200 974513.293 53.788 - 43 122 79 201 Au -26400.714 3.218 7895.175 0.016 B- 1261.827 3.147 200 971657.665 3.454 - 41 121 80 201 Hg -27662.542 0.711 7897.560 0.004 B- -481.704 14.181 200 970303.038 0.763 - 39 120 81 201 Tl -27180.838 14.185 7891.271 0.071 B- -1909.802 18.530 200 970820.168 15.228 - 37 119 82 201 Pb -25271.036 13.747 7877.877 0.068 B- -3854.603 20.481 200 972870.425 14.758 - 35 118 83 201 Bi +a -21416.433 15.183 7854.808 0.076 B- -4895.248 15.962 200 977008.512 16.299 - 33 117 84 201 Po -16521.185 4.942 7826.561 0.025 B- -5731.747 9.561 200 982263.777 5.305 - 31 116 85 201 At +a -10789.438 8.184 7794.153 0.041 B- -6717.113 50.401 200 988417.061 8.786 - 29 115 86 201 Rn -a -4072.324 49.732 7756.842 0.247 B- -7660.902 50.554 200 995628.179 53.389 - 27 114 87 201 Fr -a 3588.577 9.080 7714.836 0.045 B- -8348.224 22.239 201 003852.496 9.747 - 25 113 88 201 Ra -a 11936.801 20.301 7669.410 0.101 B- * 201 012814.683 21.794 -0 50 126 76 202 Os x -13087# 401# 7842# 2# B- 3689# 499# 201 985950# 430# - 48 125 77 202 Ir x -16776# 298# 7856# 1# B- 5916# 299# 201 981990# 320# - 46 124 78 202 Pt x -22692.125 25.150 7881.560 0.125 B- 1660.854 34.276 201 975639.000 27.000 - 44 123 79 202 Au x -24352.979 23.287 7885.909 0.115 B- 2992.345 23.298 201 973856.000 25.000 - 42 122 80 202 Hg -27345.324 0.705 7896.850 0.003 B- -1365.108 1.636 201 970643.585 0.756 - 40 121 81 202 Tl -25980.216 1.606 7886.219 0.008 B- -39.602 4.096 201 972109.089 1.723 - 38 120 82 202 Pb -25940.614 3.796 7882.150 0.019 B- -5199.130 15.856 201 972151.604 4.075 - 36 119 83 202 Bi -20741.484 15.396 7852.539 0.076 B- -2799.868 17.666 201 977733.100 16.528 - 34 118 84 202 Po -17941.616 8.670 7834.805 0.043 B- -7350.884 29.289 201 980738.881 9.307 - 32 117 85 202 At -a -10590.732 27.977 7794.541 0.138 B- -4316.097 33.010 201 988630.380 30.034 - 30 116 86 202 Rn -a -6274.635 17.520 7769.301 0.087 B- -9370.871 18.881 201 993263.902 18.808 - 28 115 87 202 Fr -a 3096.237 7.040 7719.038 0.035 B- -5978.625 16.586 202 003323.946 7.557 - 26 114 88 202 Ra -a 9074.861 15.018 7685.568 0.074 B- * 202 009742.264 16.122 -0 51 127 76 203 Os x -7640# 401# 7816# 2# B- 7050# 566# 202 991798# 430# - 49 126 77 203 Ir x -14690# 401# 7847# 2# B- 4937# 446# 202 984230# 430# - 47 125 78 203 Pt x -19627# 196# 7867# 1# B- 3517# 196# 202 978930# 210# - 45 124 79 203 Au -23143.436 3.083 7880.864 0.015 B- 2125.829 3.451 202 975154.498 3.309 - 43 123 80 203 Hg -25269.265 1.627 7887.482 0.008 B- 492.112 1.225 202 972872.326 1.746 - 41 122 81 203 Tl -25761.377 1.166 7886.053 0.006 B- -974.820 6.461 202 972344.022 1.252 - 39 121 82 203 Pb -24786.557 6.554 7877.397 0.032 B- -3261.729 14.356 202 973390.535 7.036 - 37 120 83 203 Bi +a -21524.827 12.778 7857.475 0.063 B- -4213.939 15.433 202 976892.145 13.717 - 35 119 84 203 Po +a -17310.889 8.655 7832.863 0.043 B- -5148.332 13.666 202 981415.995 9.291 - 33 118 85 203 At -12162.557 10.576 7803.648 0.052 B- -6008.858 21.027 202 986942.957 11.353 - 31 117 86 203 Rn -a -6153.699 18.179 7770.193 0.090 B- -7030.116 19.218 202 993393.732 19.516 - 29 116 87 203 Fr 876.417 6.232 7731.708 0.031 B- -7785.309 38.630 203 000940.872 6.689 - 27 115 88 203 Ra -a 8661.726 38.124 7689.503 0.188 B- * 203 009298.745 40.928 -0 50 127 77 204 Ir x -9688# 401# 7824# 2# B- 8234# 446# 203 989600# 430# - 48 126 78 204 Pt x -17922# 196# 7860# 1# B- 2728# 280# 203 980760# 210# - 46 125 79 204 Au + -20650# 200# 7870# 1# B- 4040# 200# 203 977831# 215# - 44 124 80 204 Hg -24690.145 0.498 7885.545 0.002 B- -344.000 1.186 203 973494.037 0.534 - 42 123 81 204 Tl -24346.145 1.152 7880.023 0.006 B- 763.748 0.177 203 973863.337 1.236 - 40 122 82 204 Pb -25109.892 1.146 7879.932 0.006 B- -4463.996 9.248 203 973043.420 1.230 - 38 121 83 204 Bi +a -20645.896 9.180 7854.215 0.045 B- -2304.652 14.335 203 977835.717 9.854 - 36 120 84 204 Po -a -18341.244 11.013 7839.083 0.054 B- -6465.811 24.860 203 980309.863 11.822 - 34 119 85 204 At -11875.433 22.288 7803.552 0.109 B- -3905.240 23.498 203 987251.197 23.926 - 32 118 86 204 Rn -7970.193 7.444 7780.574 0.036 B- -8577.503 25.684 203 991443.644 7.991 - 30 117 87 204 Fr -a 607.310 24.581 7734.692 0.120 B- -5449.477 28.940 204 000651.974 26.389 - 28 116 88 204 Ra -a 6056.787 15.273 7704.144 0.075 B- * 204 006502.228 16.396 -0 51 128 77 205 Ir x -5960# 503# 7807# 2# B- 7007# 585# 204 993602# 540# - 49 127 78 205 Pt x -12966# 298# 7837# 1# B- 5803# 357# 204 986080# 320# - 47 126 79 205 Au x -18770# 196# 7861# 1# B- 3518# 196# 204 979850# 210# - 45 125 80 205 Hg -22287.740 3.654 7874.732 0.018 B- 1533.135 3.724 204 976073.125 3.923 - 43 124 81 205 Tl -23820.874 1.237 7878.394 0.006 B- -50.636 0.503 204 974427.237 1.328 - 41 123 82 205 Pb -23770.239 1.144 7874.331 0.006 B- -2705.734 5.107 204 974481.597 1.228 - 39 122 83 205 Bi -21064.504 5.111 7857.316 0.025 B- -3543.106 11.280 204 977386.323 5.487 - 37 121 84 205 Po -17521.398 10.059 7836.216 0.049 B- -4549.452 18.130 204 981190.004 10.798 - 35 120 85 205 At +a -12971.946 15.085 7810.207 0.074 B- -5262.161 15.913 204 986074.041 16.194 - 33 119 86 205 Rn -7709.786 5.080 7780.722 0.025 B- -6399.973 9.329 204 991723.204 5.453 - 31 118 87 205 Fr x -1309.813 7.824 7745.686 0.038 B- -7148.804 70.954 204 998593.858 8.399 - 29 117 88 205 Ra -a 5838.991 70.521 7706.998 0.344 B- -8267.702 86.923 205 006268.415 75.707 - 27 116 89 205 Ac -a 14106.693 50.818 7662.851 0.248 B- * 205 015144.158 54.555 -0 50 128 78 206 Pt x -9632# 298# 7822# 1# B- 4583# 422# 205 989660# 320# - 48 127 79 206 Au x -14215# 298# 7840# 1# B- 6731# 299# 205 984740# 320# - 46 126 80 206 Hg +a -20945.801 20.440 7869.172 0.099 B- 1307.566 20.410 205 977513.756 21.943 - 44 125 81 206 Tl -22253.367 1.284 7871.721 0.006 B- 1532.217 0.612 205 976110.026 1.378 - 42 124 82 206 Pb -23785.584 1.144 7875.362 0.006 B- -3757.306 7.546 205 974465.124 1.227 - 40 123 83 206 Bi - -20028.278 7.632 7853.324 0.037 B- -1839.604 8.600 205 978498.757 8.193 - 38 122 84 206 Po -a -18188.674 4.012 7840.597 0.019 B- -5758.956 15.580 205 980473.654 4.306 - 36 121 85 206 At -12429.718 15.056 7808.843 0.073 B- -3296.753 17.330 205 986656.148 16.162 - 34 120 86 206 Rn -9132.965 8.591 7789.041 0.042 B- -7890.549 29.475 205 990195.358 9.223 - 32 119 87 206 Fr -a -1242.416 28.195 7746.940 0.137 B- -4807.955 33.455 205 998666.211 30.268 - 30 118 88 206 Ra -a 3565.539 18.008 7719.802 0.087 B- -9913.913 53.608 206 003827.763 19.332 - 28 117 89 206 Ac -a 13479.452 50.493 7667.879 0.245 B- * 206 014470.787 54.206 -0 51 129 78 207 Pt x -4540# 401# 7798# 2# B- 6270# 500# 206 995126# 430# - 49 128 79 207 Au x -10810# 300# 7825# 1# B- 5677# 301# 206 988395# 322# - 47 127 80 207 Hg x -16487.444 29.808 7848.610 0.144 B- 4547.008 30.300 206 982300.000 32.000 - 45 126 81 207 Tl -21034.451 5.439 7866.797 0.026 B- 1417.595 5.402 206 977418.586 5.839 - 43 125 82 207 Pb -22452.047 1.147 7869.866 0.006 B- -2397.420 2.118 206 975896.735 1.230 - 41 124 83 207 Bi -20054.627 2.397 7854.505 0.012 B- -2908.852 6.614 206 978470.471 2.573 - 39 123 84 207 Po -17145.775 6.659 7836.673 0.032 B- -3918.358 14.075 206 981593.252 7.148 - 37 122 85 207 At +a -13227.416 12.406 7813.964 0.060 B- -4592.654 15.037 206 985799.783 13.318 - 35 121 86 207 Rn +a -8634.762 8.497 7787.998 0.041 B- -5790.421 19.458 206 990730.200 9.121 - 33 120 87 207 Fr -2844.341 17.505 7756.246 0.085 B- -6388.826 56.008 206 996946.474 18.792 - 31 119 88 207 Ra -a 3544.485 53.202 7721.602 0.257 B- -7601.748 73.276 207 003805.161 57.115 - 29 118 89 207 Ac -a 11146.233 50.387 7681.099 0.243 B- * 207 011965.973 54.092 -0 52 130 78 208 Pt x -990# 400# 7783# 2# B- 5111# 499# 207 998937# 429# - 50 129 79 208 Au x -6101# 298# 7804# 1# B- 7164# 300# 207 993450# 320# - 48 128 80 208 Hg x -13265.406 30.739 7834.191 0.148 B- 3484.726 30.795 207 985759.000 33.000 - 46 127 81 208 Tl +a -16750.132 1.854 7847.183 0.009 B- 4998.466 1.669 207 982017.992 1.990 - 44 126 82 208 Pb -21748.598 1.148 7867.453 0.006 B- -2878.375 2.013 207 976651.918 1.231 - 42 125 83 208 Bi +n -18870.223 2.304 7849.853 0.011 B- -1400.628 2.397 207 979741.981 2.473 - 40 124 84 208 Po -a -17469.596 1.737 7839.358 0.008 B- -4999.725 9.086 207 981245.616 1.864 - 38 123 85 208 At +a -12469.871 8.921 7811.560 0.043 B- -2814.279 14.269 207 986613.042 9.577 - 36 122 86 208 Rn -a -9655.591 11.138 7794.268 0.054 B- -6989.672 16.251 207 989634.295 11.957 - 34 121 87 208 Fr -2665.919 11.834 7756.903 0.057 B- -4393.774 14.881 207 997138.018 12.704 - 32 120 88 208 Ra -a 1727.856 9.023 7732.017 0.043 B- -9025.380 56.442 208 001854.929 9.686 - 30 119 89 208 Ac -a 10753.235 55.716 7684.865 0.268 B- -5930.495 65.370 208 011544.073 59.813 - 28 118 90 208 Th -a 16683.730 34.190 7652.592 0.164 B- * 208 017910.722 36.704 -0 51 130 79 209 Au x -2540# 400# 7788# 2# B- 6104# 426# 208 997273# 429# - 49 129 80 209 Hg x -8644# 149# 7813# 1# B- 5000# 149# 208 990720# 160# - 47 128 81 209 Tl +a -13644.757 6.110 7833.397 0.029 B- 3969.889 6.211 208 985351.750 6.559 - 45 127 82 209 Pb -17614.646 1.747 7848.648 0.008 B- 644.016 1.146 208 981089.898 1.875 - 43 126 83 209 Bi -18258.662 1.364 7847.987 0.007 B- -1892.570 1.564 208 980398.519 1.464 - 41 125 84 209 Po -a -16366.092 1.778 7835.188 0.009 B- -3483.478 5.287 208 982430.276 1.908 - 39 124 85 209 At -12882.613 5.102 7814.777 0.024 B- -3941.564 11.188 208 986169.944 5.477 - 37 123 86 209 Rn -8941.049 9.960 7792.175 0.048 B- -5171.477 17.713 208 990401.388 10.692 - 35 122 87 209 Fr x -3769.572 14.648 7763.688 0.070 B- -5627.791 15.730 208 995953.197 15.725 - 33 121 88 209 Ra -a 1858.219 5.747 7733.017 0.027 B- -6985.590 50.934 209 001994.879 6.169 - 31 120 89 209 Ac -a 8843.809 50.608 7695.850 0.242 B- -7523# 148# 209 009494.220 54.330 - 29 119 90 209 Th IT 16367# 140# 7656# 1# B- * 209 017571# 150# -0 52 131 79 210 Au x 2329# 401# 7766# 2# B- 7694# 446# 210 002500# 430# - 50 130 80 210 Hg x -5365# 196# 7799# 1# B- 3882# 196# 209 994240# 210# - 48 129 81 210 Tl +a -9246.969 11.604 7813.588 0.055 B- 5481.534 11.561 209 990072.970 12.456 - 46 128 82 210 Pb -14728.502 1.447 7835.965 0.007 B- 63.476 0.499 209 984188.301 1.553 - 44 127 83 210 Bi -14791.979 1.363 7832.542 0.006 B- 1161.159 0.766 209 984120.156 1.462 - 42 126 84 210 Po -15953.137 1.146 7834.346 0.005 B- -3980.960 7.610 209 982873.601 1.230 - 40 125 85 210 At -a -11972.177 7.695 7811.663 0.037 B- -2367.407 8.922 209 987147.338 8.261 - 38 124 86 210 Rn -a -9604.770 4.557 7796.665 0.022 B- -6271.565 15.824 209 989688.854 4.892 - 36 123 87 210 Fr -3333.205 15.154 7763.075 0.072 B- -3775.997 17.720 209 996421.657 16.268 - 34 122 88 210 Ra -a 442.792 9.193 7741.368 0.044 B- -8346.908 58.133 210 000475.356 9.868 - 32 121 89 210 Ac -a 8789.699 57.402 7697.896 0.273 B- -5269.747 60.436 210 009436.130 61.623 - 30 120 90 210 Th -a 14059.446 18.909 7669.076 0.090 B- * 210 015093.437 20.299 -0 51 131 80 211 Hg x -624# 196# 7778# 1# B- 5454# 200# 210 999330# 210# - 49 130 81 211 Tl x -6077.998 41.917 7799.791 0.199 B- 4414.950 41.978 210 993475.000 45.000 - 47 129 82 211 Pb -10492.948 2.261 7817.007 0.011 B- 1366.183 5.471 210 988735.356 2.426 - 45 128 83 211 Bi -11859.131 5.442 7819.774 0.026 B- 573.439 5.430 210 987268.698 5.842 - 43 127 84 211 Po -a -12432.571 1.255 7818.784 0.006 B- -785.307 2.539 210 986653.085 1.347 - 41 126 85 211 At -a -11647.264 2.729 7811.354 0.013 B- -2891.860 6.894 210 987496.147 2.929 - 39 125 86 211 Rn -a -8755.404 6.813 7793.941 0.032 B- -4615.155 13.786 210 990600.686 7.314 - 37 124 87 211 Fr -4140.249 11.991 7768.360 0.057 B- -4972.272 14.369 210 995555.259 12.872 - 35 123 88 211 Ra x 832.023 7.918 7741.087 0.038 B- -6370.191 53.564 211 000893.213 8.500 - 33 122 89 211 Ac -a 7202.214 52.976 7707.189 0.251 B- -6707.958 90.205 211 007731.894 56.871 - 31 121 90 211 Th -a 13910.171 73.010 7671.690 0.346 B- -8170# 126# 211 014933.183 78.379 - 29 120 91 211 Pa x 22080# 102# 7629# 0# B- * 211 023704# 110# -0 52 132 80 212 Hg x 2757# 298# 7763# 1# B- 4308# 359# 212 002960# 320# - 50 131 81 212 Tl +a -1551# 200# 7780# 1# B- 5998# 200# 211 998335# 215# - 48 130 82 212 Pb -7548.850 1.842 7804.319 0.009 B- 569.104 1.825 211 991895.975 1.977 - 46 129 83 212 Bi -8117.954 1.854 7803.313 0.009 B- 2251.533 1.667 211 991285.016 1.989 - 44 128 84 212 Po -10369.487 1.152 7810.243 0.005 B- -1741.266 2.107 211 988867.896 1.236 - 42 127 85 212 At -a -8628.221 2.384 7798.340 0.011 B- 31.387 3.605 211 990737.223 2.559 - 40 126 86 212 Rn -a -8659.608 3.145 7794.797 0.015 B- -5143.640 9.318 211 990703.528 3.376 - 38 125 87 212 Fr -3515.968 8.775 7766.845 0.041 B- -3317.000 14.276 211 996225.453 9.420 - 36 124 88 212 Ra -a -198.968 11.263 7747.508 0.053 B- -7476.266 52.601 211 999786.399 12.091 - 34 123 89 212 Ac -a 7277.298 51.381 7708.552 0.242 B- -4833.510 52.366 212 007812.501 55.160 - 32 122 90 212 Th -a 12110.808 10.109 7682.062 0.048 B- -9482.551 75.541 212 013001.487 10.852 - 30 121 91 212 Pa -a 21593.358 74.862 7633.643 0.353 B- * 212 023181.425 80.367 -0 53 133 80 213 Hg x 7666# 298# 7741# 1# B- 5882# 299# 213 008230# 320# - 51 132 81 213 Tl x 1783.811 27.013 7765.430 0.127 B- 4987.343 27.894 213 001915.000 29.000 - 49 131 82 213 Pb +a -3203.532 6.954 7785.172 0.033 B- 2028.103 8.371 212 996560.867 7.465 - 47 130 83 213 Bi -5231.635 5.082 7791.021 0.024 B- 1421.949 5.490 212 994383.608 5.456 - 45 129 84 213 Po -6653.584 3.053 7794.024 0.014 B- -73.989 5.465 212 992857.083 3.277 - 43 128 85 213 At -a -6579.595 4.898 7790.003 0.023 B- -883.569 5.724 212 992936.514 5.257 - 41 127 86 213 Rn -a -5696.026 3.370 7782.182 0.016 B- -2143.179 6.006 212 993885.064 3.617 - 39 126 87 213 Fr -3552.848 5.091 7768.447 0.024 B- -3898.405 11.057 212 996185.861 5.465 - 37 125 88 213 Ra 345.557 9.818 7746.472 0.046 B- -5809.134 18.156 213 000370.970 10.540 - 35 124 89 213 Ac -a 6154.692 15.272 7715.526 0.072 B- -5965.394 17.834 213 006607.333 16.395 - 33 123 90 213 Th -a 12120.086 9.217 7683.846 0.043 B- -7542.539 71.737 213 013011.447 9.895 - 31 122 91 213 Pa -a 19662.625 71.142 7644.762 0.334 B- * 213 021108.697 76.374 -0 54 134 80 214 Hg x 11178# 401# 7727# 2# B- 4713# 446# 214 012000# 430# - 52 133 81 214 Tl x 6465# 196# 7745# 1# B- 6647# 196# 214 006940# 210# - 50 132 82 214 Pb -182.769 1.975 7772.394 0.009 B- 1017.984 11.256 213 999803.788 2.120 - 48 131 83 214 Bi -1200.753 11.209 7773.495 0.052 B- 3269.293 11.165 213 998710.938 12.033 - 46 130 84 214 Po -4470.046 1.449 7785.116 0.007 B- -1090.215 4.107 213 995201.208 1.555 - 44 129 85 214 At -a -3379.831 4.298 7776.366 0.020 B- 939.911 10.014 213 996371.601 4.614 - 42 128 86 214 Rn -a -4319.742 9.187 7777.102 0.043 B- -3361.035 12.503 213 995362.566 9.862 - 40 127 87 214 Fr -a -958.707 8.634 7757.740 0.040 B- -1051.441 10.086 213 998970.785 9.268 - 38 126 88 214 Ra -a 92.734 5.250 7749.171 0.025 B- -6351.120 16.232 214 000099.554 5.636 - 36 125 89 214 Ac -a 6443.854 15.360 7715.837 0.072 B- -4251.030 18.693 214 006917.762 16.489 - 34 124 90 214 Th -a 10694.885 10.661 7692.317 0.050 B- -8790.630 76.867 214 011481.431 11.445 - 32 123 91 214 Pa -a 19485.515 76.125 7647.583 0.356 B- * 214 020918.561 81.723 -0 55 135 80 215 Hg x 16208# 401# 7705# 2# B- 6297# 499# 215 017400# 430# - 53 134 81 215 Tl x 9911# 298# 7730# 1# B- 5569# 303# 215 010640# 320# - 51 133 82 215 Pb +a 4342.244 52.448 7752.737 0.244 B- 2712.922 52.748 215 004661.590 56.304 - 49 132 83 215 Bi 1629.322 5.624 7761.717 0.026 B- 2171.028 5.530 215 001749.149 6.037 - 47 131 84 215 Po -541.706 2.121 7768.176 0.010 B- 714.049 6.819 214 999418.454 2.276 - 45 130 85 215 At -a -1255.756 6.799 7767.858 0.032 B- -87.195 10.168 214 998651.890 7.299 - 43 129 86 215 Rn -a -1168.561 7.672 7763.814 0.036 B- -1486.625 10.306 214 998745.498 8.236 - 41 128 87 215 Fr -a 318.065 7.066 7753.260 0.033 B- -2215.674 10.077 215 000341.456 7.585 - 39 127 88 215 Ra -a 2533.739 7.613 7739.316 0.035 B- -3496.877 14.551 215 002720.080 8.172 - 37 126 89 215 Ac -a 6030.615 12.406 7719.413 0.058 B- -4890.971 15.234 215 006474.132 13.318 - 35 125 90 215 Th -a 10921.586 8.840 7693.025 0.041 B- -6942.353 73.380 215 011724.805 9.490 - 33 124 91 215 Pa -a 17863.939 72.845 7657.096 0.339 B- -7059.147 114.616 215 019177.728 78.202 - 31 123 92 215 U -a 24923.087 88.490 7620.624 0.412 B- * 215 026756.035 94.997 -0 56 136 80 216 Hg x 19859# 401# 7690# 2# B- 5142# 499# 216 021320# 430# - 54 135 81 216 Tl x 14718# 298# 7710# 1# B- 7238# 357# 216 015800# 320# - 52 134 82 216 Pb x 7480# 196# 7740# 1# B- 1606# 196# 216 008030# 210# - 50 133 83 216 Bi x 5873.991 11.178 7743.499 0.052 B- 4091.571 11.324 216 006305.989 12.000 - 48 132 84 216 Po 1782.420 1.816 7758.819 0.008 B- -474.246 3.571 216 001913.506 1.949 - 46 131 85 216 At -a 2256.666 3.575 7753.002 0.017 B- 2003.799 6.836 216 002422.631 3.837 - 44 130 86 216 Rn -a 252.868 5.994 7758.657 0.028 B- -2718.082 7.126 216 000271.464 6.435 - 42 129 87 216 Fr -a 2970.950 4.173 7742.451 0.019 B- -320.128 9.548 216 003189.445 4.480 - 40 128 88 216 Ra -a 3291.077 8.737 7737.347 0.040 B- -4853.317 13.921 216 003533.117 9.379 - 38 127 89 216 Ac -a 8144.395 10.840 7711.256 0.050 B- -2153.937 16.201 216 008743.367 11.637 - 36 126 90 216 Th -a 10298.332 12.042 7697.662 0.056 B- -7500.882 54.864 216 011055.714 12.928 - 34 125 91 216 Pa -a 17799.214 53.526 7659.314 0.248 B- -5267.137 60.450 216 019108.242 57.462 - 32 124 92 216 U -a 23066.351 28.093 7631.307 0.130 B- * 216 024762.747 30.158 -0 55 136 81 217 Tl x 18313# 401# 7695# 2# B- 6073# 499# 217 019660# 430# - 53 135 82 217 Pb x 12240# 298# 7719# 1# B- 3510# 299# 217 013140# 320# - 51 134 83 217 Bi x 8729.962 17.698 7731.848 0.082 B- 2846.444 18.870 217 009372.000 19.000 - 49 133 84 217 Po +a 5883.518 6.544 7741.360 0.030 B- 1488.883 7.979 217 006316.216 7.025 - 47 132 85 217 At 4394.635 5.001 7744.616 0.023 B- 736.135 6.151 217 004717.835 5.369 - 45 131 86 217 Rn -a 3658.501 4.198 7744.403 0.019 B- -656.089 7.538 217 003927.562 4.506 - 43 130 87 217 Fr -a 4314.590 6.531 7737.775 0.030 B- -1575.067 9.588 217 004631.902 7.010 - 41 129 88 217 Ra -a 5889.656 7.202 7726.911 0.033 B- -2814.017 13.430 217 006322.806 7.731 - 39 128 89 217 Ac -a 8703.673 11.389 7710.338 0.052 B- -3502.107 15.566 217 009343.777 12.226 - 37 127 90 217 Th -a 12205.780 10.614 7690.594 0.049 B- -4862.630 19.132 217 013103.444 11.394 - 35 126 91 217 Pa -a 17068.410 15.918 7664.580 0.073 B- -5905# 73# 217 018323.692 17.089 - 33 125 92 217 U -a 22973# 71# 7634# 0# B- * 217 024663# 77# -0 56 137 81 218 Tl x 23180# 400# 7674# 2# B- 7727# 499# 218 024885# 429# - 54 136 82 218 Pb x 15453# 298# 7706# 1# B- 2237# 299# 218 016590# 320# - 52 135 83 218 Bi x 13216.037 27.013 7712.827 0.124 B- 4859.136 27.085 218 014188.000 29.000 - 50 134 84 218 Po 8356.901 1.973 7731.528 0.009 B- 258.738 11.649 218 008971.502 2.118 - 48 133 85 218 At -a 8098.162 11.604 7729.126 0.053 B- 2880.816 11.705 218 008693.735 12.456 - 46 132 86 218 Rn 5217.347 2.316 7738.752 0.011 B- -1841.770 4.942 218 005601.052 2.486 - 44 131 87 218 Fr -a 7059.117 4.757 7726.715 0.022 B- 407.947 12.039 218 007578.274 5.106 - 42 130 88 218 Ra -a 6651.170 11.176 7724.998 0.051 B- -4192.439 51.931 218 007140.325 11.997 - 40 129 89 218 Ac -a 10843.609 50.740 7702.177 0.233 B- -1523.132 51.815 218 011641.093 54.471 - 38 128 90 218 Th -a 12366.741 10.516 7691.602 0.048 B- -6317.029 21.130 218 013276.242 11.289 - 36 127 91 218 Pa -a 18683.770 18.329 7659.036 0.084 B- -3210.838 22.888 218 020057.853 19.676 - 34 126 92 218 U -a 21894.608 13.714 7640.719 0.063 B- * 218 023504.829 14.722 -0 55 137 82 219 Pb x 20279# 401# 7686# 2# B- 3996# 446# 219 021770# 430# - 53 136 83 219 Bi x 16283# 196# 7700# 1# B- 3601# 196# 219 017480# 210# - 51 135 84 219 Po x 12681.359 15.835 7713.333 0.072 B- 2285.283 16.163 219 013614.000 17.000 - 49 134 85 219 At 10396.076 3.237 7720.196 0.015 B- 1566.675 2.947 219 011160.647 3.474 - 47 133 86 219 Rn 8829.402 2.100 7723.777 0.010 B- 211.635 7.058 219 009478.753 2.254 - 45 132 87 219 Fr -a 8617.767 7.039 7721.171 0.032 B- -776.515 10.772 219 009251.553 7.556 - 43 131 88 219 Ra -a 9394.282 8.258 7714.053 0.038 B- -2175.199 51.142 219 010085.176 8.865 - 41 130 89 219 Ac -a 11569.480 50.497 7700.549 0.231 B- -2901.910 71.425 219 012420.348 54.210 - 39 129 90 219 Th -a 14471.390 50.576 7683.725 0.231 B- -4068.741 72.192 219 015535.677 54.295 - 37 128 91 219 Pa -a 18540.131 51.516 7661.574 0.235 B- -4746.439 72.333 219 019903.650 55.304 - 35 127 92 219 U -a 23286.569 50.775 7636.329 0.232 B- -6170.086 101.905 219 024999.161 54.509 - 33 126 93 219 Np -a 29456.655 88.354 7604.583 0.403 B- * 219 031623.021 94.851 -0 56 138 82 220 Pb x 23669# 401# 7672# 2# B- 2850# 499# 220 025410# 430# - 54 137 83 220 Bi x 20819# 298# 7682# 1# B- 5555# 299# 220 022350# 320# - 52 136 84 220 Po x 15263.461 17.698 7703.224 0.080 B- 887.714 22.549 220 016386.000 19.000 - 50 135 85 220 At x 14375.747 13.972 7703.703 0.064 B- 3763.670 14.090 220 015433.000 15.000 - 48 134 86 220 Rn 10612.077 1.815 7717.254 0.008 B- -870.242 4.026 220 011392.534 1.948 - 46 133 87 220 Fr -a 11482.320 4.028 7709.742 0.018 B- 1212.075 9.061 220 012326.778 4.324 - 44 132 88 220 Ra -a 10270.245 8.237 7711.696 0.037 B- -3473.437 10.141 220 011025.562 8.843 - 42 131 89 220 Ac -a 13743.682 6.129 7692.351 0.028 B- -925.417 22.941 220 014754.450 6.579 - 40 130 90 220 Th -a 14669.100 22.166 7684.589 0.101 B- -5549# 56# 220 015747.926 23.795 - 38 129 91 220 Pa -a 20218# 51# 7656# 0# B- -2715# 113# 220 021705# 55# - 36 128 92 220 U -a 22933# 101# 7640# 0# B- -7378# 220# 220 024620# 108# - 34 127 93 220 Np x 30311# 196# 7603# 1# B- * 220 032540# 210# -0 55 138 83 221 Bi x 24098# 298# 7668# 1# B- 4324# 299# 221 025870# 320# - 53 137 84 221 Po x 19773.755 19.561 7684.481 0.089 B- 2991.027 24.039 221 021228.000 21.000 - 51 136 85 221 At x 16782.727 13.972 7694.475 0.063 B- 2311.308 15.096 221 018017.000 15.000 - 49 135 86 221 Rn +a 14471.420 5.714 7701.393 0.026 B- 1194.130 7.231 221 015535.709 6.134 - 47 134 87 221 Fr 13277.290 4.886 7703.256 0.022 B- 313.479 6.386 221 014253.757 5.245 - 45 133 88 221 Ra -a 12963.811 4.630 7701.135 0.021 B- -1559.298 50.603 221 013917.224 4.970 - 43 132 89 221 Ac -a 14523.109 50.425 7690.539 0.228 B- -2417.261 51.056 221 015591.199 54.133 - 41 131 90 221 Th -a 16940.371 8.166 7676.061 0.037 B- -3435.918 51.915 221 018186.236 8.766 - 39 130 91 221 Pa -a 20376.288 51.281 7656.974 0.232 B- -4143.707 72.404 221 021874.846 55.052 - 37 129 92 221 U -a 24519.995 51.114 7634.684 0.231 B- -5330# 207# 221 026323.299 54.873 - 35 128 93 221 Np x 29850# 200# 7607# 1# B- * 221 032045# 215# -0 56 139 83 222 Bi x 28729# 300# 7649# 1# B- 6243# 303# 222 030842# 322# - 54 138 84 222 Po x 22486.265 40.054 7674.005 0.180 B- 1533.239 43.071 222 024140.000 43.000 - 52 137 85 222 At x 20953.026 15.835 7677.387 0.071 B- 4580.820 15.955 222 022494.000 17.000 - 50 136 86 222 Rn 16372.206 1.950 7694.497 0.009 B- -5.900 7.703 222 017576.286 2.093 - 48 135 87 222 Fr x 16378.105 7.452 7690.947 0.034 B- 2057.917 8.682 222 017582.620 8.000 - 46 134 88 222 Ra 14320.188 4.454 7696.692 0.020 B- -2301.285 6.637 222 015373.355 4.781 - 44 133 89 222 Ac -a 16621.474 5.174 7682.802 0.023 B- -581.637 13.228 222 017843.887 5.554 - 42 132 90 222 Th -a 17203.111 12.279 7676.658 0.055 B- -4951# 74# 222 018468.300 13.182 - 40 131 91 222 Pa -a 22155# 72# 7651# 0# B- -2118# 89# 222 023784# 78# - 38 130 92 222 U -a 24272.827 51.994 7637.764 0.234 B- -6746# 202# 222 026057.953 55.817 - 36 129 93 222 Np x 31019# 196# 7604# 1# B- * 222 033300# 210# -0 57 140 83 223 Bi x 32137# 401# 7636# 2# B- 5058# 446# 223 034500# 430# - 55 139 84 223 Po x 27079# 196# 7655# 1# B- 3651# 196# 223 029070# 210# - 53 138 85 223 At x 23428.006 13.972 7668.055 0.063 B- 3038.267 16.013 223 025151.000 15.000 - 51 137 86 223 Rn 20389.739 7.822 7678.171 0.035 B- 2007.344 8.057 223 021889.285 8.397 - 49 136 87 223 Fr 18382.394 1.932 7683.664 0.009 B- 1149.085 0.848 223 019734.313 2.073 - 47 135 88 223 Ra 17233.309 2.090 7685.309 0.009 B- -592.573 7.128 223 018500.719 2.244 - 45 134 89 223 Ac -a 17825.882 7.110 7679.143 0.032 B- -1559.948 11.563 223 019136.872 7.632 - 43 133 90 223 Th -a 19385.831 9.212 7668.640 0.041 B- -2934.845 71.639 223 020811.546 9.889 - 41 132 91 223 Pa -a 22320.676 71.063 7651.971 0.319 B- -3516.330 100.506 223 023962.232 76.289 - 39 131 92 223 U -a 25837.006 71.119 7632.694 0.319 B- -4763# 208# 223 027737.168 76.349 - 37 130 93 223 Np x 30600# 196# 7608# 1# B- * 223 032850# 210# -0 58 141 83 224 Bi x 36830# 400# 7617# 2# B- 6920# 445# 224 039539# 429# - 56 140 84 224 Po x 29910# 196# 7644# 1# B- 2199# 197# 224 032110# 210# - 54 139 85 224 At x 27711.015 22.356 7650.735 0.100 B- 5265.917 24.415 224 029749.000 24.000 - 52 138 86 224 Rn 22445.098 9.814 7670.751 0.044 B- 696.482 14.875 224 024095.804 10.536 - 50 137 87 224 Fr x 21748.616 11.178 7670.367 0.050 B- 2922.699 11.324 224 023348.100 12.000 - 48 136 88 224 Ra 18825.917 1.813 7679.922 0.008 B- -1408.219 4.087 224 020210.453 1.945 - 46 135 89 224 Ac -a 20234.135 4.089 7670.143 0.018 B- 240.401 10.823 224 021722.239 4.389 - 44 134 90 224 Th -a 19993.734 10.120 7667.724 0.045 B- -3868.544 12.546 224 021464.157 10.864 - 42 133 91 224 Pa -a 23862.278 7.587 7646.961 0.034 B- -1859.974 24.329 224 025617.210 8.145 - 40 132 92 224 U -a 25722.252 23.171 7635.165 0.103 B- -6153# 197# 224 027613.974 24.875 - 38 131 93 224 Np x 31876# 196# 7604# 1# B- * 224 034220# 210# -0 57 141 84 225 Po x 34530# 298# 7626# 1# B- 4136# 422# 225 037070# 320# - 55 140 85 225 At x 30395# 298# 7641# 1# B- 3861# 298# 225 032630# 320# - 53 139 86 225 Rn 26534.141 11.140 7654.357 0.050 B- 2713.531 16.349 225 028485.574 11.958 - 51 138 87 225 Fr 23820.610 11.967 7662.940 0.053 B- 1827.501 12.158 225 025572.478 12.847 - 49 137 88 225 Ra 21993.109 2.596 7667.586 0.012 B- 355.763 5.007 225 023610.574 2.787 - 47 136 89 225 Ac 21637.346 4.758 7665.690 0.021 B- -672.781 6.658 225 023228.647 5.107 - 45 135 90 225 Th -a 22310.127 5.093 7659.222 0.023 B- -2030.598 71.170 225 023950.907 5.467 - 43 134 91 225 Pa -a 24340.725 71.012 7646.720 0.316 B- -3039.196 71.827 225 026130.844 76.234 - 41 133 92 225 U -a 27379.921 10.909 7629.736 0.048 B- -4207.783 72.440 225 029393.555 11.711 - 39 132 93 225 Np -a 31587.704 71.622 7607.557 0.318 B- * 225 033910.797 76.889 -0 58 142 84 226 Po x 37549# 401# 7614# 2# B- 2934# 499# 226 040310# 430# - 56 141 85 226 At x 34614# 298# 7624# 1# B- 5867# 298# 226 037160# 320# - 54 140 86 226 Rn 28747.192 10.477 7646.410 0.046 B- 1226.653 12.190 226 030861.382 11.247 - 52 139 87 226 Fr 27520.539 6.230 7648.376 0.028 B- 3852.715 6.523 226 029544.515 6.688 - 50 138 88 226 Ra 23667.824 1.933 7661.962 0.009 B- -641.440 3.274 226 025408.455 2.075 - 48 137 89 226 Ac 24309.264 3.100 7655.662 0.014 B- 1111.630 4.563 226 026097.069 3.328 - 46 136 90 226 Th 23197.634 4.481 7657.119 0.020 B- -2835.642 12.165 226 024903.686 4.810 - 44 135 91 226 Pa -a 26033.276 11.420 7641.110 0.051 B- -1295.593 17.228 226 027947.872 12.259 - 42 134 92 226 U -a 27328.869 12.999 7631.916 0.058 B- -5448# 89# 226 029338.749 13.955 - 40 133 93 226 Np -a 32777# 88# 7604# 0# B- * 226 035188# 95# -0 59 143 84 227 Po x 42281# 401# 7596# 2# B- 4797# 499# 227 045390# 430# - 57 142 85 227 At x 37483# 298# 7613# 1# B- 4597# 298# 227 040240# 320# - 55 141 86 227 Rn 32885.834 14.091 7630.050 0.062 B- 3203.388 15.276 227 035304.396 15.127 - 53 140 87 227 Fr 29682.445 5.898 7640.715 0.026 B- 2504.734 6.213 227 031865.417 6.332 - 51 139 88 227 Ra -n 27177.711 1.952 7648.303 0.009 B- 1328.132 2.265 227 029176.474 2.095 - 49 138 89 227 Ac 25849.580 1.927 7650.707 0.008 B- 44.757 0.830 227 027750.666 2.068 - 47 137 90 227 Th 25804.823 2.088 7647.458 0.009 B- -1026.375 7.437 227 027702.618 2.241 - 45 136 91 227 Pa -a 26831.198 7.420 7639.490 0.033 B- -2214.264 12.146 227 028804.477 7.965 - 43 135 92 227 U -a 29045.462 9.705 7626.289 0.043 B- -3516.618 73.135 227 031181.587 10.419 - 41 134 93 227 Np -a 32562.080 72.506 7607.351 0.319 B- -4208# 123# 227 034956.832 77.838 - 39 133 94 227 Pu x 36770# 100# 7585# 0# B- * 227 039474# 107# -0 58 143 85 228 At x 41684# 401# 7597# 2# B- 6441# 401# 228 044750# 430# - 56 142 86 228 Rn 35243.465 17.677 7621.645 0.078 B- 1859.244 18.916 228 037835.418 18.977 - 54 141 87 228 Fr 33384.221 6.732 7626.368 0.030 B- 4443.953 7.021 228 035839.437 7.226 - 52 140 88 228 Ra +a 28940.268 1.996 7642.428 0.009 B- 45.540 0.634 228 031068.657 2.142 - 50 139 89 228 Ac - 28894.728 2.094 7639.196 0.009 B- 2123.743 2.645 228 031019.767 2.247 - 48 138 90 228 Th 26770.984 1.807 7645.080 0.008 B- -2152.602 4.340 228 028739.835 1.940 - 46 137 91 228 Pa -a 28923.586 4.340 7632.207 0.019 B- -298.640 14.929 228 031050.748 4.659 - 44 136 92 228 U -a 29222.226 14.354 7627.466 0.063 B- -4373.468 52.545 228 031371.351 15.409 - 42 135 93 228 Np -a 33595.694 50.572 7604.853 0.222 B- -2491.677 58.346 228 036066.462 54.291 - 40 134 94 228 Pu -a 36087.370 29.143 7590.493 0.128 B- * 228 038741.387 31.286 -0 59 144 85 229 At x 44823# 401# 7585# 2# B- 5461# 401# 229 048120# 430# - 57 143 86 229 Rn x 39362.400 13.041 7605.622 0.057 B- 3694.138 13.967 229 042257.276 14.000 - 55 142 87 229 Fr 35668.262 5.001 7618.337 0.022 B- 3106.298 16.231 229 038291.455 5.368 - 53 141 88 229 Ra x 32561.963 15.441 7628.485 0.067 B- 1872.030 19.623 229 034956.707 16.576 - 51 140 89 229 Ac x 30689.933 12.109 7633.244 0.053 B- 1104.350 12.346 229 032947.000 13.000 - 49 139 90 229 Th 29585.583 2.405 7634.650 0.011 B- -311.325 3.715 229 031761.431 2.581 - 47 138 91 229 Pa 29896.908 3.280 7629.874 0.014 B- -1313.646 6.655 229 032095.652 3.521 - 45 137 92 229 U -a 31210.554 5.938 7620.721 0.026 B- -2569.122 87.031 229 033505.909 6.374 - 43 136 93 229 Np -a 33779.675 86.848 7606.086 0.379 B- -3615.915 100.792 229 036263.974 93.235 - 41 135 94 229 Pu -a 37395.590 51.176 7586.880 0.223 B- -4754.430 101.230 229 040145.819 54.939 - 39 134 95 229 Am -a 42150.020 87.348 7562.702 0.381 B- * 229 045249.909 93.772 -0 58 144 86 230 Rn x 42048# 196# 7596# 1# B- 2561# 196# 230 045140# 210# - 56 143 87 230 Fr 39486.768 6.541 7603.704 0.028 B- 4970.462 12.198 230 042390.791 7.022 - 54 142 88 230 Ra x 34516.306 10.296 7621.914 0.045 B- 677.924 18.888 230 037054.780 11.053 - 52 141 89 230 Ac x 33838.383 15.835 7621.460 0.069 B- 2975.789 15.882 230 036327.000 17.000 - 50 140 90 230 Th 30862.593 1.210 7630.996 0.005 B- -1311.014 2.833 230 033132.358 1.299 - 48 139 91 230 Pa 32173.607 3.038 7621.895 0.013 B- 558.605 4.592 230 034539.789 3.261 - 46 138 92 230 U -a 31615.002 4.509 7620.922 0.020 B- -3621.290 51.461 230 033940.102 4.841 - 44 137 93 230 Np -a 35236.291 51.288 7601.776 0.223 B- -1698.101 53.363 230 037827.716 55.059 - 42 136 94 230 Pu -a 36934.392 14.824 7590.991 0.064 B- -5998# 134# 230 039650.703 15.913 - 40 135 95 230 Am -a 42932# 133# 7562# 1# B- * 230 046089# 143# -0 59 145 86 231 Rn x 46454# 298# 7579# 1# B- 4373# 298# 231 049870# 320# - 57 144 87 231 Fr x 42080.575 7.731 7594.500 0.033 B- 3864.089 13.749 231 045175.357 8.300 - 55 143 88 231 Ra 38216.486 11.370 7607.841 0.049 B- 2453.636 17.301 231 041027.086 12.206 - 53 142 89 231 Ac x 35762.849 13.041 7615.076 0.056 B- 1946.959 13.098 231 038393.000 14.000 - 51 141 90 231 Th 33815.891 1.218 7620.118 0.005 B- 391.487 1.460 231 036302.853 1.308 - 49 140 91 231 Pa 33424.404 1.772 7618.426 0.008 B- -381.611 2.033 231 035882.575 1.902 - 47 139 92 231 U -a 33806.015 2.670 7613.387 0.012 B- -1818.498 50.577 231 036292.252 2.866 - 45 138 93 231 Np -a 35624.513 50.547 7602.128 0.219 B- -2684.492 55.333 231 038244.490 54.264 - 43 137 94 231 Pu -a 38309.005 22.549 7587.120 0.098 B- -4101# 301# 231 041126.410 24.206 - 41 136 95 231 Am x 42410# 300# 7566# 1# B- -4860# 424# 231 045529# 322# - 39 135 96 231 Cm x 47270# 300# 7542# 1# B- * 231 050746# 322# -0 58 145 87 232 Fr x 46072.834 13.972 7579.347 0.060 B- 5575.880 16.702 232 049461.224 15.000 - 56 144 88 232 Ra 40496.953 9.151 7600.009 0.039 B- 1342.534 15.931 232 043475.270 9.823 - 54 143 89 232 Ac x 39154.419 13.041 7602.424 0.056 B- 3707.635 13.118 232 042034.000 14.000 - 52 142 90 232 Th 35446.784 1.422 7615.033 0.006 B- -499.850 7.734 232 038053.689 1.526 - 50 141 91 232 Pa + 35946.633 7.645 7609.506 0.033 B- 1337.103 7.428 232 038590.300 8.207 - 48 140 92 232 U 34609.530 1.809 7611.897 0.008 B- -2750# 100# 232 037154.860 1.942 - 46 139 93 232 Np - 37360# 100# 7597# 0# B- -1004# 102# 232 040107# 107# - 44 138 94 232 Pu -a 38363.140 17.595 7588.974 0.076 B- -4976# 300# 232 041184.526 18.888 - 42 137 95 232 Am x 43340# 300# 7564# 1# B- -2973# 362# 232 046527# 322# - 40 136 96 232 Cm -a 46312# 202# 7548# 1# B- * 232 049718# 217# -0 59 146 87 233 Fr x 48920.051 19.561 7569.239 0.084 B- 4585.991 21.369 233 052517.838 21.000 - 57 145 88 233 Ra 44334.060 8.603 7585.564 0.037 B- 3026.027 15.623 233 047594.573 9.235 - 55 144 89 233 Ac x 41308.033 13.041 7595.193 0.056 B- 2576.318 13.118 233 044346.000 14.000 - 53 143 90 233 Th 38731.715 1.425 7602.893 0.006 B- 1242.243 1.122 233 041580.208 1.529 - 51 142 91 233 Pa 37489.472 1.336 7604.866 0.006 B- 570.296 1.975 233 040246.605 1.434 - 49 141 92 233 U 36919.176 2.255 7603.956 0.010 B- -1029.415 51.005 233 039634.367 2.420 - 47 140 93 233 Np -a 37948.590 50.981 7596.181 0.219 B- -2103.179 71.642 233 040739.489 54.729 - 45 139 94 233 Pu -a 40051.769 50.351 7583.796 0.216 B- -3211# 113# 233 042997.345 54.054 - 43 138 95 233 Am -a 43263# 102# 7567# 0# B- -4031# 124# 233 046445# 109# - 41 137 96 233 Cm -a 47294.006 71.547 7545.998 0.307 B- -5567# 235# 233 050772.206 76.809 - 39 136 97 233 Bk -a 52861# 224# 7519# 1# B- * 233 056748# 240# -0 58 146 88 234 Ra x 46930.629 8.383 7576.543 0.036 B- 2089.439 16.294 234 050382.104 9.000 - 56 145 89 234 Ac x 44841.190 13.972 7582.129 0.060 B- 4228.181 14.210 234 048139.000 15.000 - 54 144 90 234 Th +a 40613.009 2.589 7596.855 0.011 B- 274.088 3.172 234 043599.860 2.779 - 52 143 91 234 Pa IT 40338.921 4.094 7594.683 0.017 B- 2193.896 4.000 234 043305.615 4.395 - 50 142 92 234 U 38145.025 1.130 7600.715 0.005 B- -1809.846 8.321 234 040950.370 1.213 - 48 141 93 234 Np - 39954.871 8.397 7589.637 0.036 B- -395.100 10.752 234 042893.320 9.014 - 46 140 94 234 Pu -a 40349.971 6.798 7584.605 0.029 B- -4111# 159# 234 043317.478 7.298 - 44 139 95 234 Am -a 44461# 159# 7564# 1# B- -2263# 159# 234 047731# 170# - 42 138 96 234 Cm -a 46724.633 17.394 7550.677 0.074 B- -6731# 143# 234 050160.959 18.673 - 40 137 97 234 Bk -a 53455# 142# 7519# 1# B- * 234 057387# 153# -0 59 147 88 235 Ra x 51130# 300# 7561# 1# B- 3773# 300# 235 054890# 322# - 57 146 89 235 Ac x 47357.155 13.972 7573.504 0.059 B- 3339.406 19.113 235 050840.000 15.000 - 55 145 90 235 Th x 44017.749 13.041 7584.385 0.055 B- 1728.853 19.113 235 047255.000 14.000 - 53 144 91 235 Pa x 42288.896 13.972 7588.413 0.059 B- 1370.050 14.017 235 045399.000 15.000 - 51 143 92 235 U 40918.846 1.117 7590.914 0.005 B- -124.262 0.852 235 043928.190 1.199 - 49 142 93 235 Np 41043.108 1.389 7587.056 0.006 B- -1139.302 20.499 235 044061.591 1.491 - 47 141 94 235 Pu -a 42182.410 20.521 7578.879 0.087 B- -2443.019 56.045 235 045284.682 22.030 - 45 140 95 235 Am -a 44625.429 52.192 7565.154 0.222 B- -3408# 208# 235 047907.371 56.030 - 43 139 96 235 Cm -a 48034# 201# 7547# 1# B- -4670# 448# 235 051567# 216# - 41 138 97 235 Bk x 52704# 401# 7524# 2# B- * 235 056580# 430# -0 58 147 89 236 Ac x 51220.992 38.191 7559.242 0.162 B- 4965.795 40.667 236 054988.000 41.000 - 56 146 90 236 Th x 46255.198 13.972 7576.968 0.059 B- 921.248 19.760 236 049657.000 15.000 - 54 145 91 236 Pa x 45333.950 13.972 7577.557 0.059 B- 2889.306 14.017 236 048668.000 15.000 - 52 144 92 236 U 42444.644 1.113 7586.484 0.005 B- -933.534 50.415 236 045566.201 1.194 - 50 143 93 236 Np IT 43378.178 50.421 7579.214 0.214 B- 476.585 50.389 236 046568.392 54.129 - 48 142 94 236 Pu 42901.593 1.811 7577.918 0.008 B- -3139# 112# 236 046056.756 1.944 - 46 141 95 236 Am -a 46041# 112# 7561# 0# B- -1814# 113# 236 049427# 120# - 44 140 96 236 Cm -a 47855.045 18.315 7550.299 0.078 B- -5687# 401# 236 051374.506 19.662 - 42 139 97 236 Bk x 53542# 401# 7523# 2# B- * 236 057480# 430# -0 59 148 89 237 Ac x 54020# 400# 7550# 2# B- 4065# 400# 237 057993# 429# - 57 147 90 237 Th x 49955.092 15.835 7563.443 0.067 B- 2427.473 20.514 237 053629.000 17.000 - 55 146 91 237 Pa x 47527.619 13.041 7570.384 0.055 B- 2137.425 13.096 237 051023.000 14.000 - 53 145 92 237 U 45390.194 1.203 7576.102 0.005 B- 518.534 0.520 237 048728.380 1.291 - 51 144 93 237 Np 44871.659 1.120 7574.989 0.005 B- -220.063 1.294 237 048171.710 1.202 - 49 143 94 237 Pu 45091.722 1.697 7570.759 0.007 B- -1478# 59# 237 048407.957 1.822 - 47 142 95 237 Am -a 46570# 59# 7561# 0# B- -2677# 93# 237 049995# 64# - 45 141 96 237 Cm -a 49247.085 70.960 7546.624 0.299 B- -3941# 235# 237 052868.923 76.178 - 43 140 97 237 Bk -a 53188# 224# 7527# 1# B- -4751# 241# 237 057100# 241# - 41 139 98 237 Cf -a 57938.921 87.287 7503.347 0.368 B- * 237 062199.993 93.706 -0 58 148 90 238 Th +a 52525# 283# 7555# 1# B- 1631# 284# 238 056388# 304# - 56 147 91 238 Pa x 50894.038 15.835 7558.344 0.067 B- 3586.255 15.906 238 054637.000 17.000 - 54 146 92 238 U 47307.783 1.493 7570.125 0.006 B- -146.874 1.201 238 050786.996 1.602 - 52 145 93 238 Np -n 47454.656 1.138 7566.221 0.005 B- 1291.443 0.457 238 050944.671 1.221 - 50 144 94 238 Pu 46163.213 1.139 7568.360 0.005 B- -2258.273 50.688 238 049558.250 1.222 - 48 143 95 238 Am -a 48421.487 50.700 7555.584 0.213 B- -1023.701 52.145 238 051982.607 54.428 - 46 142 96 238 Cm -a 49445.188 12.234 7547.996 0.051 B- -4771# 255# 238 053081.595 13.133 - 44 141 97 238 Bk -a 54216# 255# 7525# 1# B- -3061# 392# 238 058203# 274# - 42 140 98 238 Cf x 57278# 298# 7509# 1# B- * 238 061490# 320# -0 59 149 90 239 Th x 56450# 400# 7541# 2# B- 3113# 445# 239 060602# 429# - 57 148 91 239 Pa x 53337# 196# 7550# 1# B- 2765# 196# 239 057260# 210# - 55 147 92 239 U -n 50572.718 1.503 7558.561 0.006 B- 1261.661 1.493 239 054292.048 1.613 - 53 146 93 239 Np 49311.057 1.311 7560.567 0.005 B- 722.774 0.930 239 052937.599 1.407 - 51 145 94 239 Pu 48588.282 1.113 7560.318 0.005 B- -802.142 1.664 239 052161.669 1.195 - 49 144 95 239 Am -a 49390.424 1.982 7553.688 0.008 B- -1756.602 54.058 239 053022.803 2.128 - 47 143 96 239 Cm -a 51147.025 54.047 7543.065 0.226 B- -3103# 214# 239 054908.593 58.022 - 45 142 97 239 Bk -a 54250# 207# 7527# 1# B- -4019# 294# 239 058240# 222# - 43 141 98 239 Cf -a 58269# 209# 7507# 1# B- -5287# 364# 239 062554# 224# - 41 140 99 239 Es x 63556# 298# 7481# 1# B- * 239 068230# 320# -0 58 149 91 240 Pa x 56910# 200# 7538# 1# B- 4194# 200# 240 061095# 215# - 56 148 92 240 U 52715.505 2.553 7551.770 0.011 B- 399.233 17.083 240 056592.425 2.740 - 54 147 93 240 Np 52316.272 17.032 7550.173 0.071 B- 2190.891 17.015 240 056163.830 18.284 - 52 146 94 240 Pu 50125.380 1.106 7556.042 0.005 B- -1384.789 13.788 240 053811.812 1.187 - 50 145 95 240 Am +n 51510.169 13.832 7547.013 0.058 B- -214.137 13.897 240 055298.444 14.849 - 48 144 96 240 Cm 51724.306 1.906 7542.861 0.008 B- -3940# 150# 240 055528.329 2.046 - 46 143 97 240 Bk - 55664# 150# 7523# 1# B- -2327# 151# 240 059758# 161# - 44 142 98 240 Cf -a 57990.944 18.700 7510.230 0.078 B- -6208# 401# 240 062255.842 20.075 - 42 141 99 240 Es x 64199# 401# 7481# 2# B- * 240 068920# 430# -0 59 150 91 241 Pa x 59640# 300# 7528# 1# B- 3443# 358# 241 064026# 322# - 57 149 92 241 U x 56197# 196# 7539# 1# B- 1937# 208# 241 060330# 210# - 55 148 93 241 Np + 54260.175 70.719 7544.270 0.293 B- 1305.000 70.711 241 058250.697 75.920 - 53 147 94 241 Pu 52955.175 1.106 7546.439 0.005 B- 20.780 0.166 241 056849.722 1.187 - 51 146 95 241 Am 52934.395 1.114 7543.278 0.005 B- -767.434 1.168 241 056827.413 1.195 - 49 145 96 241 Cm 53701.830 1.608 7536.848 0.007 B- -2330# 200# 241 057651.288 1.726 - 47 144 97 241 Bk - 56032# 200# 7524# 1# B- -3295# 260# 241 060153# 215# - 45 143 98 241 Cf -a 59327# 166# 7507# 1# B- -4537# 280# 241 063690# 178# - 43 142 99 241 Es -a 63863# 225# 7485# 1# B- -5263# 374# 241 068560# 242# - 41 141 100 241 Fm x 69126# 298# 7460# 1# B- * 241 074210# 320# -0 58 150 92 242 U +a 58620# 201# 7532# 1# B- 1203# 283# 242 062931# 215# - 56 149 93 242 Np + 57416.932 200.004 7533.403 0.826 B- 2700.000 200.000 242 061639.615 214.713 - 54 148 94 242 Pu 54716.932 1.245 7541.327 0.005 B- -751.140 0.708 242 058741.045 1.336 - 52 147 95 242 Am -n 55468.072 1.119 7534.991 0.005 B- 664.309 0.414 242 059547.428 1.200 - 50 146 96 242 Cm 54803.764 1.142 7534.503 0.005 B- -2930# 200# 242 058834.263 1.225 - 48 145 97 242 Bk - 57734# 200# 7519# 1# B- -1653# 200# 242 061980# 215# - 46 144 98 242 Cf -a 59386.966 12.892 7509.098 0.053 B- -5414# 256# 242 063754.533 13.840 - 44 143 99 242 Es -a 64801# 256# 7483# 1# B- -3598# 475# 242 069567# 275# - 42 142 100 242 Fm x 68400# 401# 7465# 2# B- * 242 073430# 430# -0 59 151 92 243 U x 62360# 300# 7518# 1# B- 2484# 302# 243 066946# 322# - 57 150 93 243 Np IT 59876# 32# 7525# 0# B- 2121# 32# 243 064279# 34# - 55 149 94 243 Pu 57754.602 2.542 7531.008 0.010 B- 579.556 2.622 243 062002.119 2.728 - 53 148 95 243 Am 57175.046 1.388 7530.173 0.006 B- -6.952 1.569 243 061379.940 1.490 - 51 147 96 243 Cm -a 57181.998 1.496 7526.925 0.006 B- -1507.695 4.506 243 061387.403 1.606 - 49 146 97 243 Bk -a 58689.693 4.524 7517.501 0.019 B- -2300# 114# 243 063005.980 4.857 - 47 145 98 243 Cf -a 60990# 114# 7505# 0# B- -3757# 236# 243 065475# 123# - 45 144 99 243 Es -a 64747# 207# 7486# 1# B- -4640# 298# 243 069509# 222# - 43 143 100 243 Fm -a 69387# 215# 7464# 1# B- * 243 074490# 231# -0 58 151 93 244 Np x 63202# 298# 7514# 1# B- 3396# 298# 244 067850# 320# - 56 150 94 244 Pu 59806.028 2.346 7524.815 0.010 B- -73.168 2.686 244 064204.415 2.518 - 54 149 95 244 Am + 59879.196 1.492 7521.308 0.006 B- 1427.300 1.000 244 064282.964 1.601 - 52 148 96 244 Cm -a 58451.896 1.107 7523.952 0.005 B- -2261.989 14.357 244 062750.694 1.188 - 50 147 97 244 Bk -a 60713.885 14.399 7511.475 0.059 B- -764.294 14.572 244 065179.039 15.457 - 48 146 98 244 Cf 61478.179 2.618 7505.136 0.011 B- -4547# 181# 244 065999.543 2.810 - 46 145 99 244 Es -a 66026# 181# 7483# 1# B- -2940# 271# 244 070881# 195# - 44 144 100 244 Fm -a 68966# 201# 7468# 1# B- * 244 074038# 216# -0 59 152 93 245 Np x 65890# 300# 7505# 1# B- 2712# 300# 245 070736# 322# - 57 151 94 245 Pu -n 63178.179 13.620 7513.281 0.056 B- 1277.710 13.733 245 067824.568 14.621 - 55 150 95 245 Am +a 61900.469 1.887 7515.303 0.008 B- 895.889 1.549 245 066452.890 2.025 - 53 149 96 245 Cm 61004.580 1.150 7515.767 0.005 B- -809.256 1.496 245 065491.113 1.234 - 51 148 97 245 Bk -a 61813.836 1.793 7509.270 0.007 B- -1571.374 2.586 245 066359.885 1.924 - 49 147 98 245 Cf 63385.210 2.428 7499.663 0.010 B- -2981# 200# 245 068046.825 2.606 - 47 146 99 245 Es -a 66366# 200# 7484# 1# B- -3821# 279# 245 071247# 215# - 45 145 100 245 Fm -a 70187# 195# 7466# 1# B- -5085# 362# 245 075349# 209# - 43 144 101 245 Md -a 75272# 305# 7442# 1# B- * 245 080808# 328# -0 58 152 94 246 Pu 65394.801 14.985 7506.539 0.061 B- 401# 14# 246 070204.209 16.087 - 56 151 95 246 Am IT 64994# 18# 7505# 0# B- 2377# 18# 246 069774# 19# - 54 150 96 246 Cm 62616.967 1.526 7511.471 0.006 B- -1350.000 60.000 246 067222.082 1.638 - 52 149 97 246 Bk - 63966.967 60.019 7502.803 0.244 B- -123.325 60.020 246 068671.367 64.433 - 50 148 98 246 Cf 64090.292 1.515 7499.121 0.006 B- -3810# 224# 246 068803.762 1.626 - 48 147 99 246 Es -a 67901# 224# 7480# 1# B- -2288# 224# 246 072894# 240# - 46 146 100 246 Fm -a 70188.833 15.333 7467.970 0.062 B- -5926# 260# 246 075350.815 16.460 - 44 145 101 246 Md -a 76115# 259# 7441# 1# B- * 246 081713# 278# -0 59 153 94 247 Pu x 69108# 196# 7494# 1# B- 1954# 220# 247 074190# 210# - 57 152 95 247 Am + 67153# 100# 7499# 0# B- 1620# 100# 247 072092# 107# - 55 151 96 247 Cm 65533.143 3.797 7501.931 0.015 B- 43.581 6.324 247 070352.726 4.076 - 53 150 97 247 Bk -a 65489.562 5.189 7498.940 0.021 B- -614.341 16.188 247 070305.940 5.570 - 51 149 98 247 Cf +a 66103.903 15.334 7493.285 0.062 B- -2474.485 24.760 247 070965.462 16.461 - 49 148 99 247 Es +a 68578.388 19.441 7480.100 0.079 B- -3094# 116# 247 073621.932 20.870 - 47 147 100 247 Fm +a 71673# 115# 7464# 0# B- -4264# 237# 247 076944# 123# - 45 146 101 247 Md -a 75937# 207# 7444# 1# B- * 247 081521# 222# -0 58 153 95 248 Am + 70563# 200# 7487# 1# B- 3170# 200# 248 075752# 215# - 56 152 96 248 Cm 67392.755 2.358 7496.728 0.010 B- -687# 71# 248 072349.101 2.531 - 54 151 97 248 Bk IT 68080# 71# 7491# 0# B- 842# 71# 248 073087# 76# - 52 150 98 248 Cf -a 67238.012 5.121 7491.043 0.021 B- -3061# 53# 248 072182.978 5.497 - 50 149 99 248 Es -a 70299# 52# 7476# 0# B- -1599# 53# 248 075469# 56# - 48 148 100 248 Fm 71897.857 8.497 7465.944 0.034 B- -5250# 238# 248 077185.528 9.122 - 46 147 101 248 Md -a 77148# 237# 7442# 1# B- -3473# 327# 248 082822# 255# - 44 146 102 248 No -a 80621# 224# 7424# 1# B- * 248 086550# 241# -0 59 154 95 249 Am x 73104# 298# 7479# 1# B- 2353# 298# 249 078480# 320# - 57 153 96 249 Cm -n 70750.702 2.371 7485.550 0.010 B- 904.317 2.594 249 075954.006 2.545 - 55 152 97 249 Bk + 69846.384 1.249 7486.040 0.005 B- 123.600 0.400 249 074983.182 1.340 - 53 151 98 249 Cf 69722.784 1.183 7483.394 0.005 B- -1452# 30# 249 074850.491 1.270 - 51 150 99 249 Es -a 71175# 30# 7474# 0# B- -2344# 31# 249 076409# 32# - 49 149 100 249 Fm 73519.188 6.212 7461.864 0.025 B- -3713# 201# 249 078926.098 6.668 - 47 148 101 249 Md -a 77232# 201# 7444# 1# B- -4550# 344# 249 082912# 216# - 45 147 102 249 No -a 81782# 279# 7422# 1# B- * 249 087797# 300# -0 58 154 96 250 Cm -nn 72989.594 10.274 7478.938 0.041 B- 39.616 10.894 250 078357.556 11.029 - 56 153 97 250 Bk +a 72949.978 3.719 7475.967 0.015 B- 1779.587 3.386 250 078315.027 3.992 - 54 152 98 250 Cf -a 71170.391 1.538 7479.956 0.006 B- -2055# 100# 250 076404.561 1.651 - 52 151 99 250 Es - 73225# 100# 7469# 0# B- -847# 100# 250 078611# 107# - 50 150 100 250 Fm 74072.243 7.888 7462.090 0.032 B- -4558# 301# 250 079519.828 8.468 - 48 149 101 250 Md -a 78630# 301# 7441# 1# B- -2933# 362# 250 084413# 323# - 46 148 102 250 No -a 81564# 201# 7426# 1# B- * 250 087562# 215# -0 59 155 96 251 Cm + 76648.018 22.698 7466.722 0.090 B- 1420.000 20.000 251 082285.036 24.367 - 57 154 97 251 Bk + 75228.018 10.734 7469.263 0.043 B- 1093.000 10.000 251 080760.603 11.523 - 55 153 98 251 Cf -a 74135.018 3.901 7470.500 0.016 B- -377.259 7.057 251 079587.219 4.187 - 53 152 99 251 Es -a 74512.277 5.994 7465.881 0.024 B- -1441.641 16.342 251 079992.224 6.434 - 51 151 100 251 Fm +a 75953.919 15.203 7457.020 0.061 B- -3012.825 24.271 251 081539.889 16.320 - 49 150 101 251 Md +a 78966.744 18.919 7441.900 0.075 B- -3882# 116# 251 084774.291 20.310 - 47 149 102 251 No IT 82849# 114# 7423# 0# B- -4879# 319# 251 088942# 123# - 45 148 103 251 Lr x 87728# 298# 7401# 1# B- * 251 094180# 320# -0 60 156 96 252 Cm x 79056# 298# 7460# 1# B- 521# 359# 252 084870# 320# - 58 155 97 252 Bk + 78535# 200# 7459# 1# B- 2500# 200# 252 084310# 215# - 56 154 98 252 Cf -a 76034.617 2.358 7465.347 0.009 B- -1260.000 50.000 252 081626.523 2.531 - 54 153 99 252 Es - 77294.617 50.056 7457.242 0.199 B- 478.990 50.351 252 082979.189 53.736 - 52 152 100 252 Fm -a 76815.627 5.498 7456.038 0.022 B- -3695# 130# 252 082464.972 5.902 - 50 151 101 252 Md IT 80510# 130# 7438# 1# B- -2361# 131# 252 086432# 140# - 48 150 102 252 No 82871.427 9.292 7425.798 0.037 B- -5866# 238# 252 088966.141 9.975 - 46 149 103 252 Lr -a 88737# 238# 7399# 1# B- * 252 095263# 255# -0 59 156 97 253 Bk -a 80929# 359# 7451# 1# B- 1627# 359# 253 086880# 385# - 57 155 98 253 Cf -a 79301.567 4.257 7454.829 0.017 B- 291.030 4.385 253 085133.738 4.570 - 55 154 99 253 Es -a 79010.538 1.250 7452.887 0.005 B- -335.202 2.713 253 084821.305 1.341 - 53 153 100 253 Fm -a 79345.740 2.932 7448.470 0.012 B- -1827# 31# 253 085181.160 3.148 - 51 152 101 253 Md -a 81173# 31# 7438# 0# B- -3186# 32# 253 087143# 34# - 49 151 102 253 No 84358.735 6.912 7422.471 0.027 B- -4217# 202# 253 090562.831 7.420 - 47 150 103 253 Lr -a 88575# 202# 7403# 1# B- -4982# 457# 253 095089# 217# - 45 149 104 253 Rf -a 93557# 410# 7380# 2# B- * 253 100438# 440# -0 60 157 97 254 Bk x 84393# 298# 7440# 1# B- 3052# 298# 254 090600# 320# - 58 156 98 254 Cf -a 81341.401 11.462 7449.225 0.045 B- -649.193 12.113 254 087323.590 12.304 - 56 155 99 254 Es -a 81990.594 4.010 7443.589 0.016 B- 1087.800 3.202 254 088020.527 4.304 - 54 154 100 254 Fm -a 80902.794 2.414 7444.792 0.010 B- -2550# 100# 254 086852.726 2.591 - 52 153 101 254 Md - 83453# 100# 7432# 0# B- -1271# 100# 254 089590# 107# - 50 152 102 254 No 84723.347 9.658 7423.590 0.038 B- -5148# 301# 254 090954.259 10.367 - 48 151 103 254 Lr -a 89871# 301# 7400# 1# B- -3327# 414# 254 096481# 323# - 46 150 104 254 Rf -a 93199# 283# 7384# 1# B- * 254 100053# 304# -0 59 157 98 255 Cf + 84809# 200# 7438# 1# B- 720# 200# 255 091047# 215# - 57 156 99 255 Es -a 84089.274 10.817 7437.821 0.042 B- 289.620 10.247 255 090273.553 11.612 - 55 155 100 255 Fm -a 83799.654 4.291 7435.888 0.017 B- -1043.416 7.747 255 089962.633 4.607 - 53 154 101 255 Md -a 84843.070 6.553 7428.729 0.026 B- -1964.164 16.281 255 091082.787 7.035 - 51 153 102 255 No x 86807.234 14.904 7417.958 0.058 B- -3140.066 23.138 255 093191.404 16.000 - 49 152 103 255 Lr x 89947.300 17.698 7402.576 0.069 B- -4382# 116# 255 096562.404 19.000 - 47 151 104 255 Rf -a 94330# 115# 7382# 0# B- -5263# 377# 255 101267# 123# - 45 150 105 255 Db -a 99593# 359# 7359# 1# B- * 255 106918# 385# -0 60 158 98 256 Cf -a 87041# 314# 7432# 1# B- -146# 330# 256 093442# 338# - 58 157 99 256 Es + 87187# 100# 7428# 0# B- 1700# 100# 256 093599# 108# - 56 156 100 256 Fm -a 85486.817 5.600 7431.780 0.022 B- -1969# 123# 256 091773.878 6.012 - 54 155 101 256 Md IT 87456# 122# 7421# 0# B- -366# 123# 256 093888# 132# - 52 154 102 256 No -a 87822.062 7.743 7416.546 0.030 B- -3924.536 83.264 256 094280.866 8.312 - 50 153 103 256 Lr x 91746.598 82.903 7398.160 0.324 B- -2475.451 84.802 256 098494.029 89.000 - 48 152 104 256 Rf -a 94222.049 17.848 7385.434 0.070 B- -6276# 241# 256 101151.535 19.160 - 46 151 105 256 Db -a 100498# 240# 7358# 1# B- * 256 107889# 258# -0 59 158 99 257 Es -a 89403# 411# 7422# 2# B- 813# 411# 257 095979# 441# - 57 157 100 257 Fm -a 88590.033 4.486 7422.194 0.017 B- -403.020 4.715 257 095105.317 4.815 - 55 156 101 257 Md -a 88993.053 1.601 7417.582 0.006 B- -1254.202 6.661 257 095537.977 1.718 - 53 155 102 257 No -a 90247.256 6.678 7409.657 0.026 B- -2418# 45# 257 096884.419 7.169 - 51 154 103 257 Lr -a 92665# 44# 7397# 0# B- -3201# 45# 257 099480# 47# - 49 153 104 257 Rf -a 95866.427 10.817 7381.704 0.042 B- -4340# 203# 257 102916.848 11.612 - 47 152 105 257 Db -a 100207# 203# 7362# 1# B- * 257 107576# 218# -0 60 159 99 258 Es x 92702# 401# 7412# 2# B- 2276# 448# 258 099520# 430# - 58 158 100 258 Fm -a 90426# 200# 7418# 1# B- -1260# 200# 258 097077# 215# - 56 157 101 258 Md -a 91686.792 4.419 7409.675 0.017 B- 209# 100# 258 098429.825 4.743 - 54 156 102 258 No -a 91478# 100# 7407# 0# B- -3304# 143# 258 098205# 107# - 52 155 103 258 Lr -a 94782# 102# 7392# 0# B- -1559# 107# 258 101753# 109# - 50 154 104 258 Rf -a 96341.036 31.967 7382.538 0.124 B- -5456# 307# 258 103426.362 34.317 - 48 153 105 258 Db -a 101797# 305# 7358# 1# B- -3447# 513# 258 109284# 328# - 46 152 106 258 Sg -a 105244# 413# 7342# 2# B- * 258 112984# 443# -0 59 159 100 259 Fm -a 93704# 283# 7407# 1# B- 80# 346# 259 100596# 304# - 57 158 101 259 Md -a 93624# 200# 7405# 1# B- -454# 200# 259 100510# 215# - 55 157 102 259 No -a 94078.569 6.589 7399.974 0.025 B- -1773# 71# 259 100997.503 7.073 - 53 156 103 259 Lr -a 95852# 71# 7390# 0# B- -2510# 101# 259 102901# 76# - 51 155 104 259 Rf -a 98362# 72# 7377# 0# B- -3629# 90# 259 105596# 78# - 49 154 105 259 Db -a 101991.016 53.040 7360.362 0.205 B- -4529# 126# 259 109491.865 56.940 - 47 153 106 259 Sg -a 106520# 115# 7340# 0# B- * 259 114353# 123# -0 60 160 100 260 Fm -a 95766# 435# 7402# 2# B- -786# 537# 260 102809# 467# - 58 159 101 260 Md -a 96552# 316# 7396# 1# B- 940# 374# 260 103653# 340# - 56 158 102 260 No -a 95612# 200# 7397# 1# B- -2665# 235# 260 102643# 215# - 54 157 103 260 Lr -a 98277# 124# 7383# 0# B- -870# 236# 260 105504# 133# - 52 156 104 260 Rf -a 99147# 200# 7377# 1# B- -4526# 221# 260 106439# 215# - 50 155 105 260 Db -a 103673# 93# 7357# 0# B- -2875# 95# 260 111297# 100# - 48 154 106 260 Sg -a 106547.552 20.536 7342.562 0.079 B- -6776# 246# 260 114383.508 22.045 - 46 153 107 260 Bh -a 113323# 245# 7313# 1# B- * 260 121658# 263# -0 59 160 101 261 Md -a 98578# 509# 7391# 2# B- 123# 547# 261 105828# 546# - 57 159 102 261 No -a 98455# 200# 7388# 1# B- -1103# 283# 261 105696# 215# - 55 158 103 261 Lr -a 99558# 200# 7381# 1# B- -1761# 206# 261 106880# 215# - 53 157 104 261 Rf -a 101318.594 50.444 7371.384 0.193 B- -2990# 121# 261 108769.990 54.153 - 51 156 105 261 Db -a 104308# 110# 7357# 0# B- -3697# 112# 261 111980# 118# - 49 155 106 261 Sg -a 108005.043 18.494 7339.770 0.071 B- -5128# 210# 261 115948.188 19.853 - 47 154 107 261 Bh -a 113133# 209# 7317# 1# B- * 261 121454# 224# -0 60 161 101 262 Md -a 101627# 500# 7382# 2# B- 1526# 617# 262 109101# 537# - 58 160 102 262 No -a 100101# 361# 7385# 1# B- -2000# 412# 262 107463# 387# - 56 159 103 262 Lr -a 102102# 200# 7374# 1# B- -291# 300# 262 109611# 215# - 54 158 104 262 Rf -a 102393# 224# 7370# 1# B- -3861# 265# 262 109923# 240# - 52 157 105 262 Db -a 106253# 143# 7352# 1# B- -2112# 147# 262 114068# 154# - 50 156 106 262 Sg -a 108365.771 35.411 7341.185 0.135 B- -6176# 308# 262 116335.446 38.015 - 48 155 107 262 Bh -a 114541# 306# 7315# 1# B- * 262 122965# 328# -0 59 161 102 263 No -a 103129# 490# 7376# 2# B- -600# 566# 263 110714# 526# - 57 160 103 263 Lr -a 103729# 283# 7371# 1# B- -1027# 322# 263 111358# 304# - 55 159 104 263 Rf -a 104756# 153# 7364# 1# B- -2355# 227# 263 112460# 164# - 53 158 105 263 Db -a 107111# 168# 7352# 1# B- -3079# 193# 263 114988# 181# - 51 157 106 263 Sg -a 110190# 95# 7337# 0# B- -4306# 319# 263 118294# 102# - 49 156 107 263 Bh -a 114496# 305# 7318# 1# B- -5182# 329# 263 122916# 327# - 47 155 108 263 Hs -a 119678# 125# 7295# 0# B- * 263 128480# 134# -0 60 162 102 264 No -a 105011# 591# 7371# 2# B- -1366# 734# 264 112734# 634# - 58 161 103 264 Lr -a 106377# 436# 7363# 2# B- 300# 566# 264 114200# 468# - 56 160 104 264 Rf -a 106077# 361# 7361# 1# B- -3285# 431# 264 113878# 387# - 54 159 105 264 Db -a 109362# 235# 7346# 1# B- -1420# 368# 264 117405# 253# - 52 158 106 264 Sg -a 110782# 283# 7338# 1# B- -5276# 334# 264 118929# 304# - 50 157 107 264 Bh -a 116058# 177# 7315# 1# B- -3506# 180# 264 124593# 190# - 48 156 108 264 Hs -a 119563.222 28.881 7298.375 0.109 B- * 264 128356.405 31.005 -0 59 162 103 265 Lr -a 108233# 547# 7359# 2# B- -457# 655# 265 116193# 587# - 57 161 104 265 Rf -a 108690# 361# 7354# 1# B- -1793# 424# 265 116683# 387# - 55 160 105 265 Db -a 110483# 224# 7344# 1# B- -2312# 255# 265 118608# 240# - 53 159 106 265 Sg -a 112794# 123# 7333# 0# B- -3621# 264# 265 121090# 132# - 51 158 107 265 Bh -a 116415# 234# 7316# 1# B- -4485# 235# 265 124977# 251# - 49 157 108 265 Hs -a 120900.283 23.958 7296.247 0.090 B- -5778# 452# 265 129791.799 25.719 - 47 156 109 265 Mt -a 126678# 451# 7271# 2# B- * 265 135995# 484# -0 60 163 103 266 Lr -a 111622# 583# 7349# 2# B- 1546# 749# 266 119831# 626# - 58 162 104 266 Rf -a 110076# 469# 7352# 2# B- -2660# 548# 266 118172# 504# - 56 161 105 266 Db -a 112737# 283# 7339# 1# B- -881# 374# 266 121028# 304# - 54 160 106 266 Sg -a 113618# 245# 7332# 1# B- -4487# 294# 266 121973# 263# - 52 159 107 266 Bh -a 118104# 163# 7313# 1# B- -3032# 167# 266 126790# 175# - 50 158 108 266 Hs -a 121136.373 38.695 7298.273 0.145 B- -6826# 309# 266 130045.252 41.540 - 48 157 109 266 Mt -a 127962# 307# 7270# 1# B- * 266 137373# 329# -0 59 163 104 267 Rf -a 113444# 575# 7342# 2# B- -630# 707# 267 121787# 617# - 57 162 105 267 Db -a 114074# 412# 7336# 2# B- -1732# 486# 267 122464# 443# - 55 161 106 267 Sg -a 115806# 257# 7327# 1# B- -2960# 367# 267 124322# 276# - 53 160 107 267 Bh -a 118766# 263# 7313# 1# B- -3887# 279# 267 127500# 282# - 51 159 108 267 Hs -a 122653# 96# 7295# 0# B- -5138# 512# 267 131673# 103# - 49 158 109 267 Mt -a 127791# 503# 7273# 2# B- -6089# 521# 267 137189# 540# - 47 157 110 267 Ds -a 133880# 135# 7248# 1# B- * 267 143726# 145# -0 60 164 104 268 Rf -a 115476# 662# 7337# 2# B- -1586# 848# 268 123968# 711# - 58 163 105 268 Db -a 117062# 529# 7328# 2# B- 260# 707# 268 125671# 568# - 56 162 106 268 Sg -a 116802# 469# 7326# 2# B- -4005# 605# 268 125392# 504# - 54 161 107 268 Bh -a 120807# 381# 7308# 1# B- -2023# 475# 268 129691# 409# - 52 160 108 268 Hs -a 122830# 283# 7298# 1# B- -6321# 367# 268 131863# 304# - 50 159 109 268 Mt -a 129151# 233# 7271# 1# B- -4497# 381# 268 138649# 250# - 48 158 110 268 Ds -a 133648# 301# 7252# 1# B- * 268 143477# 324# -0 59 164 105 269 Db -a 119148# 624# 7323# 2# B- -614# 722# 269 127911# 669# - 57 163 106 269 Sg -a 119763# 364# 7318# 1# B- -1715# 522# 269 128570# 391# - 55 162 107 269 Bh -a 121478# 374# 7309# 1# B- -3086# 394# 269 130412# 402# - 53 161 108 269 Hs -a 124564# 124# 7294# 0# B- -4806# 480# 269 133725# 133# - 51 160 109 269 Mt -a 129370# 463# 7273# 2# B- -5465# 464# 269 138884# 497# - 49 159 110 269 Ds -a 134834.709 31.403 7250.154 0.117 B- * 269 144751.021 33.712 -0 60 165 105 270 Db -a 122307# 617# 7314# 2# B- 816# 831# 270 131302# 662# - 58 164 106 270 Sg -a 121491# 557# 7314# 2# B- -2735# 627# 270 130426# 598# - 56 163 107 270 Bh -a 124226# 287# 7301# 1# B- -886# 379# 270 133362# 308# - 54 162 108 270 Hs -a 125112# 248# 7295# 1# B- -5598# 301# 270 134314# 266# - 52 161 109 270 Mt -a 130710# 170# 7271# 1# B- -3968# 177# 270 140323# 183# - 50 160 110 270 Ds -a 134678.282 48.011 7253.775 0.178 B- * 270 144583.090 51.542 -0 59 165 106 271 Sg -a 124757# 585# 7305# 2# B- -1164# 718# 271 133932# 628# - 57 164 107 271 Bh -a 125921# 415# 7298# 2# B- -1819# 501# 271 135182# 446# - 55 163 108 271 Hs -a 127740# 280# 7288# 1# B- -3361# 433# 271 137135# 301# - 53 162 109 271 Mt -a 131101# 330# 7273# 1# B- -4847# 344# 271 140742# 354# - 51 161 110 271 Ds -a 135948# 97# 7252# 0# B- * 271 145946# 104# -0 60 166 106 272 Sg -a 126580# 727# 7301# 3# B- -2209# 901# 272 135890# 781# - 58 165 107 272 Bh -a 128789# 532# 7290# 2# B- -217# 737# 272 138261# 571# - 56 164 108 272 Hs -a 129006# 510# 7286# 2# B- -4575# 704# 272 138494# 547# - 54 163 109 272 Mt -a 133581# 485# 7267# 2# B- -2433# 637# 272 143406# 521# - 52 162 110 272 Ds -a 136015# 413# 7255# 2# B- -6758# 474# 272 146018# 443# - 50 161 111 272 Rg -a 142773# 233# 7227# 1# B- * 272 153273# 251# -0 61 167 106 273 Sg x 130018# 503# 7291# 2# B- -615# 855# 273 139580# 540# - 59 166 107 273 Bh -a 130633# 692# 7286# 3# B- -1257# 783# 273 140240# 743# - 57 165 108 273 Hs -a 131890# 367# 7279# 1# B- -2822# 561# 273 141590# 394# - 55 164 109 273 Mt -a 134713# 424# 7265# 2# B- -3643# 445# 273 144620# 455# - 53 163 110 273 Ds -a 138356# 134# 7249# 0# B- -4339# 543# 273 148531# 144# - 51 162 111 273 Rg -a 142695# 526# 7231# 2# B- * 273 153189# 565# -0 60 167 107 274 Bh -a 133682# 619# 7278# 2# B- 196# 856# 274 143513# 664# - 58 166 108 274 Hs -a 133486# 592# 7276# 2# B- -3760# 689# 274 143303# 635# - 56 165 109 274 Mt -a 137246# 354# 7259# 1# B- -1952# 526# 274 147339# 380# - 54 164 110 274 Ds -a 139197# 389# 7249# 1# B- -5416# 428# 274 149434# 418# - 52 163 111 274 Rg -a 144613# 177# 7227# 1# B- * 274 155249# 190# -0 61 168 107 275 Bh x 135691# 596# 7273# 2# B- -929# 837# 275 145670# 640# - 59 167 108 275 Hs -a 136620# 587# 7267# 2# B- -2209# 721# 275 146667# 631# - 57 166 109 275 Mt -a 138829# 418# 7256# 2# B- -2736# 586# 275 149039# 449# - 55 165 110 275 Ds -a 141565# 410# 7244# 1# B- -3731# 661# 275 151976# 441# - 53 164 111 275 Rg -a 145296# 519# 7227# 2# B- * 275 155981# 557# -0 60 168 108 276 Hs -a 138285# 754# 7264# 3# B- -3029# 923# 276 148455# 810# - 58 167 109 276 Mt -a 141315# 532# 7250# 2# B- -1227# 763# 276 151708# 571# - 56 166 110 276 Ds -a 142541# 548# 7243# 2# B- -4945# 834# 276 153024# 588# - 54 165 111 276 Rg -a 147486# 629# 7222# 2# B- -2866# 866# 276 158333# 675# - 52 164 112 276 Cn x 150352# 596# 7209# 2# B- * 276 161410# 640# -0 61 169 108 277 Hs -a 141493# 541# 7255# 2# B- -1475# 884# 277 151899# 581# - 59 168 109 277 Mt -a 142968# 699# 7247# 3# B- -2172# 798# 277 153483# 751# - 57 167 110 277 Ds -a 145140# 384# 7237# 1# B- -3197# 646# 277 155815# 412# - 55 166 111 277 Rg -a 148338# 520# 7222# 2# B- -4065# 539# 277 159247# 558# - 53 165 112 277 Cn -a 152403# 143# 7205# 1# B- * 277 163611# 153# -0 60 169 109 278 Mt -a 145736# 621# 7240# 2# B- -645# 881# 278 156454# 666# - 58 168 110 278 Ds -a 146381# 625# 7235# 2# B- -4136# 719# 278 157146# 671# - 56 167 111 278 Rg -a 150517# 357# 7218# 1# B- -2415# 565# 278 161587# 383# - 54 166 112 278 Cn -a 152932# 438# 7206# 2# B- -5957# 475# 278 164179# 470# - 52 165 113 278 Ed -a 158889# 184# 7182# 1# B- * 278 170574# 198# -0 61 170 109 279 Mt -a 147496# 667# 7237# 2# B- -1630# 896# 279 158343# 716# - 59 169 110 279 Ds -a 149126# 598# 7228# 2# B- -2649# 731# 279 160093# 642# - 57 168 111 279 Rg -a 151775# 421# 7216# 2# B- -3255# 621# 279 162937# 452# - 55 167 112 279 Cn -a 155030# 456# 7202# 2# B- -4209# 835# 279 166432# 490# - 53 166 113 279 Ed x 159239# 699# 7184# 3# B- * 279 170950# 750# -0 60 170 110 280 Ds -a 150520# 780# 7226# 3# B- -3366# 944# 280 161590# 838# - 58 169 111 280 Rg -a 153886# 532# 7212# 2# B- -1810# 789# 280 165203# 571# - 56 168 112 280 Cn -a 155696# 583# 7202# 2# B- -5444# 707# 280 167147# 626# - 54 167 113 280 Ed x 161140# 400# 7180# 1# B- * 280 172991# 429# -0 61 171 110 281 Ds -a 153431# 579# 7219# 2# B- -1866# 992# 281 164715# 622# - 59 170 111 281 Rg -a 155297# 806# 7210# 3# B- -2722# 894# 281 166718# 865# - 57 169 112 281 Cn -a 158019# 387# 7197# 1# B- -3790# 490# 281 169641# 416# - 55 168 113 281 Ed x 161810# 300# 7181# 1# B- * 281 173710# 322# -0 60 171 111 282 Rg -a 157800# 654# 7204# 2# B- -1176# 926# 282 169405# 702# - 58 170 112 282 Cn -a 158976# 656# 7197# 2# B- -4749# 748# 282 170668# 704# - 56 169 113 282 Ed -a 163725# 361# 7177# 1# B- * 282 175766# 387# -0 61 172 111 283 Rg -a 159281# 697# 7202# 2# B- -2205# 925# 283 170995# 748# - 59 171 112 283 Cn -a 161486# 608# 7191# 2# B- -3221# 748# 283 173362# 653# - 57 170 113 283 Ed -a 164707# 436# 7177# 2# B- * 283 176820# 468# -0 60 172 112 284 Cn -a 162545# 806# 7190# 3# B- -4046# 966# 284 174499# 865# - 58 171 113 284 Ed -a 166591# 534# 7173# 2# B- -2330# 846# 284 178843# 573# - 56 170 114 284 Fl -a 168921# 656# 7162# 2# B- * 284 181344# 704# -0 61 173 112 285 Cn -a 165173# 581# 7184# 2# B- -2557# 995# 285 177321# 624# - 59 172 113 285 Ed -a 167731# 807# 7173# 3# B- -3272# 897# 285 180066# 866# - 57 171 114 285 Fl -a 171003# 391# 7158# 1# B- * 285 183579# 419# -0 60 173 113 286 Ed -a 170014# 656# 7168# 2# B- -1758# 928# 286 182518# 704# - 58 172 114 286 Fl -a 171773# 657# 7159# 2# B- * 286 184406# 705# -0 61 174 113 287 Ed -a 171245# 725# 7167# 3# B- -2827# 948# 287 183840# 778# - 59 173 114 287 Fl -a 174073# 610# 7154# 2# B- -3823# 752# 287 186875# 655# - 57 172 115 287 Ef -a 177895# 439# 7138# 2# B- * 287 190978# 471# -0 60 174 114 288 Fl -a 175042# 806# 7154# 3# B- -4728# 968# 288 187916# 865# - 58 173 115 288 Ef -a 179771# 536# 7135# 2# B- * 288 192992# 576# -0 61 175 114 289 Fl -a 177564# 584# 7148# 2# B- -3102# 997# 289 190623# 626# - 59 174 115 289 Ef -a 180666# 809# 7135# 3# B- -3861# 947# 289 193953# 868# - 57 173 116 289 Lv -a 184528# 492# 7119# 2# B- * 289 198099# 529# -0 60 175 115 290 Ef -a 182894# 658# 7130# 2# B- -2304# 932# 290 196345# 706# - 58 174 116 290 Lv -a 185198# 660# 7120# 2# B- * 290 198818# 708# -0 61 176 115 291 Ef -a 183990# 784# 7130# 3# B- -3397# 995# 291 197522# 842# - 59 175 116 291 Lv -a 187387# 612# 7116# 2# B- -4413# 853# 291 201169# 658# - 57 174 117 291 Eh -a 191800# 594# 7098# 2# B- * 291 205906# 637# -0 60 176 116 292 Lv -a 188242# 806# 7116# 3# B- -5334# 1047# 292 202086# 865# - 58 175 117 292 Eh -a 193576# 669# 7095# 2# B- * 292 207812# 718# -0 61 177 116 293 Lv -a 190669# 586# 7111# 2# B- -3716# 1000# 293 204691# 629# - 59 176 117 293 Eh -a 194385# 810# 7095# 3# B- -4488# 1072# 293 208680# 870# - 57 175 118 293 Ei -a 198873# 702# 7077# 2# B- * 293 213498# 753# -0 60 177 117 294 Eh -a 196521# 660# 7092# 2# B- -2942# 936# 294 210974# 708# - 58 176 118 294 Ei -a 199463# 663# 7079# 2# B- * 294 214132# 712# -0 59 177 118 295 Ei -a 201512# 644# 7075# 2# B- * 295 216332# 692# diff --git a/openmc/data/mass_1.mas20.txt b/openmc/data/mass_1.mas20.txt new file mode 100644 index 000000000..ce12b2c4a --- /dev/null +++ b/openmc/data/mass_1.mas20.txt @@ -0,0 +1,3594 @@ +1 a0dsskgw A T O M I C M A S S A D J U S T M E N T +0 DATE 3 Mar 2021 TIME 22:41 +0 ********************* A= 0 TO 295 + * file : mass.mas20 * + ********************* + + This is one file out of a series of 3 files published in: + "The Ame2020 atomic mass evaluation (I)" by W.J.Huang, M.Wang, F.G.Kondev, G.Audi and S.Naimi + Chinese Physics C45, 030002, March 2021. + "The Ame2020 atomic mass evaluation (II)" by M.Wang, W.J.Huang, F.G.Kondev, G.Audi and S.Naimi + Chinese Physics C45, 030003, March 2021. + for files : mass.mas20 : atomic masses + rct1.mas20 : react and sep energies, part 1 + rct2.mas20 : react and sep energies, part 2 + A fourth file is the "Rounded" version of the atomic mass table (the first file) + massround.mas20 atomic masses "Rounded" version + + Values in files 1, 2 and 3 are unrounded version of the published ones + Values in file 4 are exact copy of the published ones + + col 1 : Fortran character control: 1 = page feed 0 = line feed + format : a1,i3,i5,i5,i5,1x,a3,a4,1x,f14.6,f12.6,f13.5,1x,f10.5,1x,a2,f13.5,f11.5,1x,i3,1x,f13.6,f12.6 + cc NZ N Z A el o mass unc binding unc B beta unc atomic_mass unc + Warnings : this format is not identical to that used in AME2016; + one more digit is added to the "BINDING ENERGY/A", "BETA-DECAY ENERGY" and "ATOMIC-MASS" values and their uncertainties; + # in a place of decimal point : estimated (non-experimental) value; + * in a place of value : the not calculable quantity + +....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+...10....+...11....+...12....+...13 + + + MASS LIST + for analysis + +1N-Z N Z A EL O MASS EXCESS BINDING ENERGY/A BETA-DECAY ENERGY ATOMIC MASS + (keV) (keV) (keV) (micro-u) +0 1 1 0 1 n 8071.31806 0.00044 0.0 0.0 B- 782.3470 0.0004 1 008664.91590 0.00047 + -1 0 1 1 H 7288.971064 0.000013 0.0 0.0 B- * 1 007825.031898 0.000014 +0 0 1 1 2 H 13135.722895 0.000015 1112.2831 0.0002 B- * 2 014101.777844 0.000015 +0 1 2 1 3 H 14949.81090 0.00008 2827.2654 0.0003 B- 18.59202 0.00006 3 016049.28132 0.00008 + -1 1 2 3 He 14931.21888 0.00006 2572.68044 0.00015 B- -13736# 2000# 3 016029.32197 0.00006 + -3 0 3 3 Li -pp 28667# 2000# -2267# 667# B- * 3 030775# 2147# +0 2 3 1 4 H -n 24621.129 100.000 1720.4491 25.0000 B- 22196.2131 100.0000 4 026431.867 107.354 + 0 2 2 4 He 2424.91587 0.00015 7073.9156 0.0002 B- -22898.2740 212.1320 4 002603.25413 0.00016 + -2 1 3 4 Li -p 25323.190 212.132 1153.7603 53.0330 B- * 4 027185.561 227.733 +0 3 4 1 5 H -nn 32892.447 89.443 1336.3592 17.8885 B- 21661.2131 91.6515 5 035311.492 96.020 + 1 3 2 5 He -n 11231.234 20.000 5512.1325 4.0000 B- -447.6529 53.8516 5 012057.224 21.470 + -1 2 3 5 Li -p 11678.887 50.000 5266.1325 10.0000 B- -25460# 2003# 5 012537.800 53.677 + -3 1 4 5 Be x 37139# 2003# 18# 401# B- * 5 039870# 2150# +0 4 5 1 6 H -3n 41875.725 254.127 961.6395 42.3545 B- 24283.6294 254.1268 6 044955.437 272.816 + 2 4 2 6 He 17592.095 0.053 4878.5199 0.0089 B- 3505.2147 0.0532 6 018885.889 0.057 + 0 3 3 6 Li 14086.88044 0.00144 5332.3312 0.0003 B- -4288.1534 5.4478 6 015122.88742 0.00155 + -2 2 4 6 Be - 18375.034 5.448 4487.2478 0.9080 B- -28945# 2003# 6 019726.409 5.848 + -4 1 5 6 B x 47320# 2003# -467# 334# B- * 6 050800# 2150# +0 5 6 1 7 H -nn 49135# 1004# 940# 143# B- 23062# 1004# 7 052749# 1078# + 3 5 2 7 He -n 26073.128 7.559 4123.0578 1.0799 B- 11166.0229 7.5595 7 027990.652 8.115 + 1 4 3 7 Li 14907.10463 0.00419 5606.4401 0.0006 B- -861.8930 0.0707 7 016003.43426 0.00450 + -1 3 4 7 Be 15768.998 0.071 5371.5487 0.0101 B- -11907.5551 25.1504 7 016928.714 0.076 + -3 2 5 7 B p4n 27676.553 25.150 3558.7055 3.5929 B- * 7 029712.000 27.000 +0 4 6 2 8 He 31609.683 0.089 3924.5210 0.0111 B- 10663.8784 0.1005 8 033934.388 0.095 + 2 5 3 8 Li 20945.805 0.047 5159.7124 0.0059 B- 16004.1329 0.0591 8 022486.244 0.050 + 0 4 4 8 Be -a 4941.672 0.035 7062.4356 0.0044 B- -17979.8973 1.0005 8 005305.102 0.037 + -2 3 5 8 B 22921.569 1.000 4717.1551 0.1250 B- -12142.7002 18.2704 8 024607.315 1.073 + -4 2 6 8 C 35064.269 18.243 3101.5242 2.2804 B- * 8 037643.039 19.584 +0 5 7 2 9 He 40935.826 46.816 3349.0380 5.2018 B- 15980.9213 46.8169 9 043946.414 50.259 + 3 6 3 9 Li -3n 24954.905 0.186 5037.7685 0.0207 B- 13606.4541 0.2014 9 026790.191 0.200 + 1 5 4 9 Be 11348.451 0.076 6462.6693 0.0085 B- -1068.0349 0.8994 9 012183.062 0.082 + -1 4 5 9 B - 12416.486 0.903 6257.0713 0.1003 B- -16494.4854 2.3195 9 013329.645 0.969 + -3 3 6 9 C -pp 28910.971 2.137 4337.4233 0.2374 B- * 9 031037.202 2.293 +0 6 8 2 10 He -nn 49197.147 92.848 2995.1340 9.2848 B- 16144.5191 93.7152 10 052815.306 99.676 + 4 7 3 10 Li -n 33052.628 12.721 4531.3512 1.2721 B- 20445.1411 12.7216 10 035483.453 13.656 + 2 6 4 10 Be 12607.487 0.081 6497.6306 0.0081 B- 556.8759 0.0822 10 013534.692 0.086 + 0 5 5 10 B 12050.611 0.015 6475.0835 0.0015 B- -3648.0623 0.0687 10 012936.862 0.016 + -2 4 6 10 C 15698.673 0.070 6032.0426 0.0070 B- -23101.3545 400.0000 10 016853.217 0.075 + -4 3 7 10 N -- 38800.027 400.000 3643.6724 40.0000 B- * 10 041653.540 429.417 +0 5 8 3 11 Li x 40728.259 0.615 4155.3817 0.0559 B- 20551.0898 0.6591 11 043723.581 0.660 + 3 7 4 11 Be 20177.169 0.238 5952.5402 0.0216 B- 11509.4607 0.2380 11 021661.080 0.255 + 1 6 5 11 B 8667.708 0.012 6927.7323 0.0011 B- -1981.6889 0.0608 11 009305.166 0.013 + -1 5 6 11 C 10649.397 0.060 6676.4563 0.0054 B- -13716.2469 5.0008 11 011432.597 0.064 + -3 4 7 11 N -p 24365.644 5.000 5358.4023 0.4546 B- -23373.2693 60.2459 11 026157.593 5.368 + -5 3 8 11 O -pp 47738.913 60.038 3162.4372 5.4580 B- * 11 051249.828 64.453 +0 6 9 3 12 Li -n 49009.577 30.006 3791.5999 2.5005 B- 23931.8152 30.0669 12 052613.942 32.213 + 4 8 4 12 Be 25077.761 1.909 5720.7223 0.1590 B- 11708.3636 2.3214 12 026922.082 2.048 + 2 7 5 12 B 13369.398 1.321 6631.2237 0.1101 B- 13369.3979 1.3214 12 014352.638 1.418 + 0 6 6 12 C 0.0 0.0 7680.1446 0.0002 B- -17338.0681 0.9999 12 000000.0 0.0 + -2 5 7 12 N 17338.068 1.000 6170.1100 0.0833 B- -14675.2668 12.0418 12 018613.180 1.073 + -4 4 8 12 O -pp 32013.335 12.000 4881.9755 1.0000 B- * 12 034367.726 12.882 +0 7 10 3 13 Li -nn 56980.895 70.003 3507.6307 5.3848 B- 23321.8152 70.7391 13 061171.503 75.150 + 5 9 4 13 Be -n 33659.080 10.180 5241.4359 0.7831 B- 17097.1315 10.2295 13 036134.506 10.929 + 3 8 5 13 B -nn 16561.948 1.000 6496.4194 0.0769 B- 13436.9387 1.0001 13 017779.981 1.073 + 1 7 6 13 C 3125.00933 0.00023 7469.8495 0.0002 B- -2220.4718 0.2695 13 003354.83534 0.00025 + -1 6 7 13 N -p 5345.481 0.270 7238.8634 0.0207 B- -17769.9506 9.5301 13 005738.609 0.289 + -3 5 8 13 O +3n 23115.432 9.526 5811.7636 0.7328 B- -18915# 500# 13 024815.435 10.226 + -5 4 9 13 F x 42030# 500# 4297# 38# B- * 13 045121# 537# +0 6 10 4 14 Be x 39954.502 132.245 4993.8973 9.4461 B- 16290.8166 133.9357 14 042892.920 141.970 + 4 9 5 14 B 23663.686 21.213 6101.6451 1.5152 B- 20643.7926 21.2133 14 025404.010 22.773 + 2 8 6 14 C 3019.89328 0.00375 7520.3198 0.0004 B- 156.4765 0.0037 14 003241.98862 0.00403 + 0 7 7 14 N 2863.41683 0.00022 7475.6148 0.0002 B- -5144.3643 0.0252 14 003074.00425 0.00024 + -2 6 8 14 O 8007.781 0.025 7052.2783 0.0018 B- -23956.6215 41.1187 14 008596.706 0.027 + -4 5 9 14 F -p 31964.403 41.119 5285.2091 2.9371 B- * 14 034315.196 44.142 +0 7 11 4 15 Be -n 49825.821 165.797 4540.9708 11.0532 B- 20868.4411 167.1256 15 053490.215 177.990 + 5 10 5 15 B 28957.379 21.029 5880.0438 1.4019 B- 19084.2343 21.0442 15 031087.023 22.575 + 3 9 6 15 C -n 9873.145 0.800 7100.1696 0.0533 B- 9771.7071 0.8000 15 010599.256 0.858 + 1 8 7 15 N 101.43809 0.00058 7699.4603 0.0002 B- -2754.1841 0.4902 15 000108.89827 0.00062 + -1 7 8 15 O 2855.622 0.490 7463.6915 0.0327 B- -13711.1300 14.0086 15 003065.636 0.526 + -3 6 9 15 F -p 16566.752 14.000 6497.4597 0.9333 B- -23648.6215 68.1377 15 017785.139 15.029 + -5 5 10 15 Ne -pp 40215.374 66.684 4868.7285 4.4456 B- * 15 043172.977 71.588 +0 8 12 4 16 Be -nn 57447.139 165.797 4285.2851 10.3623 B- 20335.4399 167.6075 16 061672.036 177.990 + 6 11 5 16 B 37111.699 24.566 5507.3535 1.5354 B- 23417.5656 24.8254 16 039841.045 26.373 + 4 10 6 16 C -nn 13694.133 3.578 6922.0546 0.2236 B- 8010.2260 4.2540 16 014701.255 3.840 + 2 9 7 16 N -n 5683.907 2.301 7373.7971 0.1438 B- 10420.9094 2.3014 16 006101.925 2.470 + 0 8 8 16 O -4737.00217 0.00030 7976.2072 0.0002 B- -15412.1840 5.3642 15 994914.61926 0.00032 + -2 7 9 16 F 10675.182 5.364 6964.0490 0.3353 B- -13311.5932 21.1709 16 011460.278 5.758 + -4 6 10 16 Ne -- 23986.775 20.480 6083.1777 1.2800 B- * 16 025750.860 21.986 +0 7 12 5 17 B x 43716.322 204.104 5269.6677 12.0061 B- 22684.4422 204.8410 17 046931.399 219.114 + 5 11 6 17 C 2p-n 21031.880 17.365 6558.0262 1.0215 B- 13161.8007 22.9464 17 022578.650 18.641 + 3 10 7 17 N +p 7870.079 15.000 7286.2294 0.8824 B- 8678.8430 15.0000 17 008448.876 16.103 + 1 9 8 17 O -808.76421 0.00064 7750.7291 0.0002 B- -2760.4655 0.2479 16 999131.75595 0.00069 + -1 8 9 17 F 1951.701 0.248 7542.3284 0.0146 B- -14548.7507 0.4323 17 002095.237 0.266 + -3 7 10 17 Ne 16500.452 0.354 6640.4991 0.0208 B- -18219.1277 59.6167 17 017713.962 0.380 + -5 6 11 17 Na x 34719.580 59.616 5522.7653 3.5068 B- * 17 037273.000 64.000 +0 8 13 5 18 B -n 51792.640 204.165 4976.6306 11.3425 B- 26873.3742 206.3572 18 055601.683 219.180 + 6 12 6 18 C ++ 24919.266 30.000 6426.1321 1.6667 B- 11806.0982 35.2821 18 026751.930 32.206 + 4 11 7 18 N + 13113.167 18.570 7038.5627 1.0316 B- 13895.9838 18.5695 18 014077.563 19.935 + 2 10 8 18 O -782.81634 0.00064 7767.0981 0.0002 B- -1655.9288 0.4633 17 999159.61214 0.00069 + 0 9 9 18 F 873.112 0.463 7631.6383 0.0257 B- -4444.5049 0.5888 18 000937.324 0.497 + -2 8 10 18 Ne 5317.617 0.363 7341.2577 0.0202 B- -19720.3745 93.8819 18 005708.696 0.390 + -4 7 11 18 Na 25037.992 93.881 6202.2176 5.2156 B- * 18 026879.388 100.785 +0 9 14 5 19 B x 59770.251 525.363 4719.6346 27.6507 B- 27356.4961 534.4964 19 064166.000 564.000 + 7 13 6 19 C -n 32413.754 98.389 6118.2740 5.1784 B- 16557.4995 99.7475 19 034797.594 105.625 + 5 12 7 19 N p-2n 15856.255 16.404 6948.5452 0.8634 B- 12523.3972 16.6143 19 017022.389 17.610 + 3 11 8 19 O -n 3332.858 2.637 7566.4952 0.1388 B- 4820.3029 2.6370 19 003577.969 2.830 + 1 10 9 19 F -1487.44512 0.00082 7779.0192 0.0002 B- -3239.4986 0.1601 18 998403.16207 0.00088 + -1 9 10 19 Ne +3n 1752.054 0.160 7567.3431 0.0084 B- -11177.3310 10.5364 19 001880.906 0.171 + -3 8 11 19 Na 12929.384 10.535 6937.8864 0.5545 B- -18909.0095 60.9189 19 013880.264 11.309 + -5 7 12 19 Mg -pp 31838.394 60.001 5901.4992 3.1579 B- * 19 034179.920 64.413 +0 10 15 5 20 B -n 69401.569 546.357 4405.6529 27.3178 B- 31898.0019 593.0377 20 074505.644 586.538 + 8 14 6 20 C x 37503.567 230.625 5961.4356 11.5312 B- 15737.0689 243.7459 20 040261.732 247.585 + 6 13 7 20 N x 21766.498 78.894 6709.1717 3.9447 B- 17970.3261 78.8991 20 023367.295 84.696 + 4 12 8 20 O -nn 3796.172 0.885 7568.5707 0.0442 B- 3813.6349 0.8854 20 004075.357 0.950 + 2 11 9 20 F -n -17.463 0.030 7720.1351 0.0015 B- 7024.4689 0.0297 19 999981.252 0.031 + 0 10 10 20 Ne -7041.93217 0.00154 8032.2412 0.0002 B- -13892.4207 1.1090 19 992440.17525 0.00165 + -2 9 11 20 Na 6850.489 1.109 7298.5028 0.0554 B- -10627.2054 2.1681 20 007354.301 1.190 + -4 8 12 20 Mg +t 17477.694 1.863 6728.0252 0.0931 B- * 20 018763.075 2.000 +0 11 16 5 21 B -nn 78382.887 558.664 4152.5265 26.6031 B- 32740# 817# 21 084147.485 599.750 + 9 15 6 21 C x 45643# 596# 5674# 28# B- 20411# 611# 21 049000# 640# + 7 14 7 21 N x 25231.915 134.048 6609.0159 6.3832 B- 17169.8816 134.5840 21 027087.573 143.906 + 5 13 8 21 O -3n 8062.034 12.000 7389.3747 0.5714 B- 8109.6390 12.1342 21 008654.948 12.882 + 3 12 9 21 F -nn -47.605 1.800 7738.2934 0.0857 B- 5684.1712 1.8004 20 999948.893 1.932 + 1 11 10 21 Ne -5731.776 0.038 7971.7136 0.0018 B- -3546.9190 0.0177 20 993846.685 0.041 + -1 10 11 21 Na -2184.857 0.042 7765.5581 0.0020 B- -13088.7080 0.7557 20 997654.459 0.045 + -3 9 12 21 Mg x 10903.851 0.755 7105.0317 0.0359 B- -16186# 600# 21 011705.764 0.810 + -5 8 13 21 Al x 27090# 600# 6297# 29# B- * 21 029082# 644# +0 10 16 6 22 C -nn 53611.203 231.490 5421.0778 10.5223 B- 21846.3983 311.0627 22 057553.990 248.515 + 8 15 7 22 N x 31764.805 207.779 6378.5347 9.4445 B- 22481.7725 215.4350 22 034100.918 223.060 + 6 14 8 22 O -4n 9283.032 56.921 7364.8722 2.5873 B- 6489.6562 58.2558 22 009965.744 61.107 + 4 13 9 22 F + 2793.376 12.399 7624.2954 0.5636 B- 10818.0916 12.3990 22 002998.812 13.310 + 2 12 10 22 Ne -8024.716 0.018 8080.4656 0.0008 B- -2843.3243 0.1325 21 991385.113 0.018 + 0 11 11 22 Na -5181.391 0.132 7915.6624 0.0060 B- -4781.4051 0.1631 21 994437.547 0.141 + -2 10 12 22 Mg -399.986 0.159 7662.7645 0.0072 B- -18601# 401# 21 999570.597 0.170 + -4 9 13 22 Al x 18201# 401# 6782# 18# B- -15439# 641# 22 019540# 430# + -6 8 14 22 Si x 33640# 500# 6044# 23# B- * 22 036114# 537# +0 11 17 6 23 C x 64171# 997# 5077# 43# B- 27450# 1082# 23 068890# 1070# + 9 16 7 23 N x 36720.429 420.570 6236.6721 18.2856 B- 22099.0584 437.8271 23 039421.000 451.500 + 7 15 8 23 O x 14621.371 121.712 7163.4856 5.2918 B- 11336.1072 126.1904 23 015696.686 130.663 + 5 14 9 23 F 3285.263 33.320 7622.3447 1.4487 B- 8439.3084 33.3206 23 003526.875 35.770 + 3 13 10 23 Ne -n -5154.045 0.104 7955.2561 0.0045 B- 4375.8085 0.1044 22 994466.905 0.112 + 1 12 11 23 Na -9529.85352 0.00181 8111.4936 0.0002 B- -4056.1790 0.0317 22 989769.28195 0.00194 + -1 11 12 23 Mg - -5473.675 0.032 7901.1229 0.0014 B- -12221.7457 0.3461 22 994123.768 0.034 + -3 10 13 23 Al -- 6748.071 0.345 7335.7275 0.0150 B- -17202# 500# 23 007244.351 0.370 + -5 9 14 23 Si x 23950# 500# 6554# 22# B- * 23 025711# 537# +0 10 17 7 24 N x 46938# 401# 5887# 17# B- 28438# 433# 24 050390# 430# + 8 16 8 24 O x 18500.404 164.874 7039.6855 6.8698 B- 10955.8885 191.6327 24 019861.000 177.000 + 6 15 9 24 F x 7544.516 97.670 7463.5831 4.0696 B- 13496.1583 97.6717 24 008099.370 104.853 + 4 14 10 24 Ne -nn -5951.642 0.513 7993.3252 0.0214 B- 2466.2583 0.5130 23 993610.649 0.550 + 2 13 11 24 Na -n -8417.901 0.017 8063.4882 0.0007 B- 5515.6774 0.0210 23 990963.012 0.017 + 0 12 12 24 Mg -13933.578 0.013 8260.7103 0.0006 B- -13884.7660 0.2282 23 985041.689 0.013 + -2 11 13 24 Al -48.812 0.228 7649.5806 0.0095 B- -10793.9978 19.4734 23 999947.598 0.244 + -4 10 14 24 Si -- 10745.186 19.472 7167.2329 0.8113 B- -23275# 501# 24 011535.430 20.904 + -6 9 15 24 P x 34020# 500# 6165# 21# B- * 24 036522# 537# +0 11 18 7 25 N x 55983# 503# 5613# 20# B- 28654# 529# 25 060100# 540# + 9 17 8 25 O -n 27329.030 165.084 6727.8058 6.6034 B- 15994.8633 191.1909 25 029338.919 177.225 + 7 16 9 25 F x 11334.167 96.442 7336.3065 3.8577 B- 13369.6698 100.7212 25 012167.727 103.535 + 5 15 10 25 Ne -2035.503 29.045 7839.7994 1.1618 B- 7322.3107 29.0701 24 997814.797 31.181 + 3 14 11 25 Na -nn -9357.814 1.200 8101.3979 0.0480 B- 3834.9684 1.2009 24 989953.974 1.288 + 1 13 12 25 Mg -13192.782 0.047 8223.5028 0.0019 B- -4276.8080 0.0447 24 985836.966 0.050 + -1 12 13 25 Al -8915.974 0.065 8021.1366 0.0026 B- -12743.2956 10.0002 24 990428.308 0.069 + -3 11 14 25 Si +3n 3827.322 10.000 7480.1109 0.4000 B- -16363# 400# 25 004108.798 10.735 + -5 10 15 25 P x 20190# 400# 6794# 16# B- * 25 021675# 429# +0 10 18 8 26 O -nn 34661.041 164.950 6497.4790 6.3442 B- 15986.3855 196.6301 26 037210.155 177.081 + 8 17 9 26 F 18674.655 107.027 7082.2497 4.1164 B- 18193.5414 108.6022 26 020048.065 114.898 + 6 16 10 26 Ne x 481.114 18.429 7751.9110 0.7088 B- 7341.8940 18.7585 26 000516.496 19.784 + 4 15 11 26 Na x -6860.780 3.502 8004.2013 0.1347 B- 9353.7631 3.5018 25 992634.649 3.759 + 2 14 12 26 Mg -16214.544 0.029 8333.8711 0.0011 B- -4004.4042 0.0629 25 982592.972 0.031 + 0 13 13 26 Al -12210.139 0.066 8149.7653 0.0026 B- -5069.1361 0.0849 25 986891.876 0.071 + -2 12 14 26 Si - -7141.003 0.108 7924.7083 0.0041 B- -18114# 196# 25 992333.818 0.115 + -4 11 15 26 P x 10973# 196# 7198# 8# B- -16707# 631# 26 011780# 210# + -6 10 16 26 S x 27680# 600# 6525# 23# B- * 26 029716# 644# +0 11 19 8 27 O x 44670# 500# 6185# 19# B- 19536# 514# 27 047955# 537# + 9 18 9 27 F 25133.478 120.198 6879.6662 4.4518 B- 18082.5680 150.6211 27 026981.897 129.037 + 7 17 10 27 Ne x 7050.910 90.770 7520.4151 3.3619 B- 12568.7005 90.8467 27 007569.462 97.445 + 5 16 11 27 Na ++ -5517.791 3.726 7956.9467 0.1380 B- 9068.8037 3.7266 26 994076.408 4.000 + 3 15 12 27 Mg -14586.594 0.047 8263.8525 0.0018 B- 2610.2694 0.0669 26 984340.647 0.050 + 1 14 13 27 Al -17196.864 0.047 8331.5533 0.0018 B- -4812.3583 0.0964 26 981538.408 0.050 + -1 13 14 27 Si - -12384.505 0.107 8124.3420 0.0040 B- -11725.4730 9.0013 26 986704.687 0.115 + -3 12 15 27 P -p -659.032 9.001 7661.0894 0.3334 B- -18150# 400# 26 999292.499 9.662 + -5 11 16 27 S - 17491# 400# 6960# 15# B- * 27 018777# 430# +0 12 20 8 28 O x 52080# 699# 5988# 25# B- 18676# 709# 28 055910# 750# + 10 19 9 28 F -n 33403.796 120.347 6626.8567 4.2981 B- 22104.0579 174.2886 28 035860.448 129.198 + 8 18 10 28 Ne x 11299.738 126.068 7388.3463 4.5024 B- 12288.0534 126.4833 28 012130.767 135.339 + 6 17 11 28 Na x -988.315 10.246 7799.2644 0.3659 B- 14031.6303 10.2498 27 998939.000 11.000 + 4 16 12 28 Mg x -15019.946 0.261 8272.4531 0.0093 B- 1830.7740 0.2653 27 983875.426 0.280 + 2 15 13 28 Al -n -16850.719 0.049 8309.8969 0.0018 B- 4642.0776 0.0486 27 981910.009 0.052 + 0 14 14 28 Si -21492.79711 0.00051 8447.7445 0.0002 B- -14344.9407 1.1473 27 976926.53442 0.00055 + -2 13 15 28 P -7147.856 1.147 7907.4842 0.0410 B- -11221.0593 160.0041 27 992326.460 1.231 + -4 12 16 28 S -- 4073.203 160.000 7478.7911 5.7143 B- -24197# 525# 28 004372.762 171.767 + -6 11 17 28 Cl -p 28270# 500# 6587# 18# B- * 28 030349# 537# +0 11 20 9 29 F x 40150.190 525.363 6444.0314 18.1160 B- 21750.3873 546.2212 29 043103.000 564.000 + 9 19 10 29 Ne x 18399.803 149.505 7167.0673 5.1553 B- 15719.8092 149.6847 29 019753.000 160.500 + 7 18 11 29 Na 2679.994 7.337 7682.1522 0.2530 B- 13292.3538 7.3447 29 002877.091 7.876 + 5 17 12 29 Mg -10612.360 0.345 8113.5317 0.0119 B- 7595.4023 0.4873 28 988607.163 0.369 + 3 16 13 29 Al x -18207.762 0.345 8348.4647 0.0119 B- 3687.3192 0.3447 28 980453.164 0.370 + 1 15 14 29 Si -21895.08154 0.00056 8448.6361 0.0002 B- -4942.2325 0.3589 28 976494.66434 0.00060 + -1 14 15 29 P -16952.849 0.359 8251.2368 0.0124 B- -13858.4257 13.0459 28 981800.368 0.385 + -3 13 16 29 S x -3094.423 13.041 7746.3826 0.4497 B- -17117# 189# 28 996678.000 14.000 + -5 12 17 29 Cl -p 14022# 189# 7129# 7# B- -23947# 478# 29 015053# 203# + -7 11 18 29 Ar -pp 37969# 439# 6276# 15# B- * 29 040761# 471# +0 12 21 9 30 F x 48960# 500# 6205# 17# B- 25680# 561# 30 052561# 537# + 10 20 10 30 Ne 23280.120 253.250 7034.5317 8.4417 B- 14805.4501 253.2946 30 024992.235 271.875 + 8 19 11 30 Na 8474.670 4.727 7501.9685 0.1576 B- 17356.0423 4.9011 30 009097.931 5.074 + 6 18 12 30 Mg -8881.373 1.295 8054.4250 0.0432 B- 6982.7440 2.3287 29 990465.454 1.390 + 4 17 13 30 Al -15864.116 1.936 8261.1049 0.0645 B- 8568.8459 1.9357 29 982969.171 2.077 + 2 16 14 30 Si -n -24432.962 0.022 8520.6549 0.0008 B- -4232.1065 0.0615 29 973770.137 0.023 + 0 15 15 30 P - -20200.856 0.065 8353.5064 0.0022 B- -6141.6014 0.1956 29 978313.490 0.069 + -2 14 16 30 S - -14059.254 0.206 8122.7081 0.0069 B- -18733.8020 23.8769 29 984906.770 0.221 + -4 13 17 30 Cl -p 4674.548 23.876 7472.1698 0.7959 B- -17397# 180# 30 005018.333 25.631 + -6 12 18 30 Ar -pp 22071# 179# 6866# 6# B- * 30 023694# 192# +0 13 22 9 31 F -nn 56843# 535# 6011# 17# B- 25661# 597# 31 061023# 574# + 11 21 10 31 Ne 31181.594 266.195 6813.0902 8.5869 B- 18935.5625 266.5617 31 033474.816 285.772 + 9 20 11 31 Na x 12246.031 13.972 7398.6778 0.4507 B- 15368.1833 14.3065 31 013146.654 15.000 + 7 19 12 31 Mg x -3122.152 3.074 7869.1886 0.0992 B- 11828.5569 3.8009 30 996648.232 3.300 + 5 18 13 31 Al x -14950.709 2.236 8225.5180 0.0721 B- 7998.3286 2.2360 30 983949.754 2.400 + 3 17 14 31 Si -n -22949.037 0.043 8458.2916 0.0014 B- 1491.5071 0.0434 30 975363.196 0.046 + 1 16 15 31 P -24440.54442 0.00075 8481.1677 0.0002 B- -5398.0130 0.2292 30 973761.99768 0.00080 + -1 15 16 31 S -19042.531 0.229 8281.8013 0.0074 B- -12007.9790 3.4541 30 979557.002 0.246 + -3 14 17 31 Cl -- -7034.552 3.447 7869.2101 0.1112 B- -18360# 200# 30 992448.097 3.700 + -5 13 18 31 Ar - 11325# 200# 7252# 6# B- -22935# 361# 31 012158# 215# + -7 12 19 31 K x 34260# 300# 6487# 10# B- * 31 036780# 322# +0 12 22 10 32 Ne x 36999# 503# 6671# 16# B- 18359# 504# 32 039720# 540# + 10 21 11 32 Na x 18640.152 37.260 7219.8815 1.1644 B- 19469.0523 37.4021 32 020011.024 40.000 + 8 20 12 32 Mg x -828.901 3.260 7803.8411 0.1019 B- 10270.4677 7.8787 31 999110.138 3.500 + 6 19 13 32 Al x -11099.368 7.173 8100.3449 0.2241 B- 12978.3208 7.1787 31 988084.338 7.700 + 4 18 14 32 Si x -24077.689 0.298 8481.4690 0.0093 B- 227.1872 0.3008 31 974151.538 0.320 + 2 17 15 32 P -n -24304.876 0.040 8464.1203 0.0013 B- 1710.6608 0.0400 31 973907.643 0.042 + 0 16 16 32 S -26015.53714 0.00131 8493.1301 0.0002 B- -12680.8313 0.5617 31 972071.17354 0.00141 + -2 15 17 32 Cl -13334.706 0.562 8072.4058 0.0176 B- -11134.3536 1.8568 31 985684.605 0.603 + -4 14 18 32 Ar x -2200.352 1.770 7700.0089 0.0553 B- -24190# 400# 31 997637.824 1.900 + -6 13 19 32 K x 21990# 400# 6920# 12# B- * 32 023607# 429# +0 13 23 10 33 Ne x 46130# 600# 6436# 18# B- 22350# 750# 33 049523# 644# + 11 22 11 33 Na x 23780.113 449.912 7089.9262 13.6337 B- 18817.2400 449.9195 33 025529.000 483.000 + 9 21 12 33 Mg 4962.873 2.663 7636.4382 0.0807 B- 13460.2550 7.4767 33 005327.862 2.859 + 7 20 13 33 Al x -8497.382 6.986 8020.6172 0.2117 B- 12016.9460 7.0211 32 990877.685 7.500 + 5 19 14 33 Si x -20514.328 0.699 8361.0596 0.0212 B- 5823.0223 1.2947 32 977976.964 0.750 + 3 18 15 33 P + -26337.350 1.090 8513.8073 0.0330 B- 248.5079 1.0900 32 971725.692 1.170 + 1 17 16 33 S -26585.85830 0.00134 8497.6304 0.0002 B- -5582.5182 0.3908 32 971458.90862 0.00144 + -1 16 17 33 Cl -21003.340 0.391 8304.7557 0.0118 B- -11619.0452 0.5596 32 977451.988 0.419 + -3 15 18 33 Ar x -9384.295 0.401 7928.9559 0.0121 B- -16925# 200# 32 989925.545 0.430 + -5 14 19 33 K x 7540# 200# 7392# 6# B- -23489# 447# 33 008095# 215# + -7 13 20 33 Ca x 31030# 400# 6657# 12# B- * 33 033312# 429# +0 14 24 10 34 Ne -nn 52842# 513# 6287# 15# B- 21161# 789# 34 056728# 551# + 12 23 11 34 Na x 31680.114 599.416 6886.4377 17.6299 B- 23356.7903 599.4561 34 034010.000 643.500 + 10 22 12 34 Mg x 8323.324 6.893 7550.3919 0.2027 B- 11320.9428 7.2072 34 008935.455 7.400 + 8 21 13 34 Al x -2997.619 2.105 7860.3506 0.0619 B- 16994.0653 2.2519 33 996781.924 2.259 + 6 20 14 34 Si x -19991.684 0.801 8337.1659 0.0236 B- 4557.0175 1.1395 33 978538.045 0.860 + 4 19 15 34 P x -24548.702 0.810 8448.1856 0.0238 B- 5382.9879 0.8116 33 973645.886 0.870 + 2 18 16 34 S -29931.689 0.045 8583.4986 0.0013 B- -5491.6037 0.0378 33 967867.011 0.047 + 0 17 17 34 Cl -24440.086 0.049 8398.9706 0.0014 B- -6061.7930 0.0631 33 973762.490 0.052 + -2 16 18 34 Ar -18378.293 0.078 8197.6724 0.0023 B- -17158# 196# 33 980270.092 0.083 + -4 15 19 34 K x -1220# 196# 7670# 6# B- -16110# 358# 33 998690# 210# + -6 14 20 34 Ca x 14890# 300# 7173# 9# B- * 34 015985# 322# +0 13 24 11 35 Na -n 37831# 670# 6745# 19# B- 22192# 723# 35 040614# 720# + 11 23 12 35 Mg x 15639.786 269.668 7356.2338 7.7048 B- 15863.5156 269.7679 35 016790.000 289.500 + 9 22 13 35 Al x -223.730 7.359 7787.1243 0.2103 B- 14167.7504 36.6047 34 999759.816 7.900 + 7 21 14 35 Si 2p-n -14391.480 35.857 8169.5644 1.0245 B- 10466.3291 35.9049 34 984550.111 38.494 + 5 20 15 35 P +p -24857.809 1.866 8446.2496 0.0533 B- 3988.4006 1.8667 34 973314.045 2.003 + 3 19 16 35 S -28846.210 0.040 8537.8511 0.0012 B- 167.3218 0.0257 34 969032.321 0.043 + 1 18 17 35 Cl -29013.532 0.035 8520.2790 0.0010 B- -5966.2429 0.6794 34 968852.694 0.038 + -1 17 18 35 Ar - -23047.289 0.680 8327.4621 0.0194 B- -11874.3955 0.8516 34 975257.719 0.730 + -3 16 19 35 K 4n -11172.893 0.512 7965.8409 0.0146 B- -16363# 200# 34 988005.406 0.550 + -5 15 20 35 Ca x 5190# 200# 7476# 6# B- -21910# 447# 35 005572# 215# + -7 14 21 35 Sc x 27100# 400# 6828# 11# B- * 35 029093# 429# +0 14 25 11 36 Na -n 45903# 687# 6557# 19# B- 25523# 974# 36 049279# 737# + 12 24 12 36 Mg x 20380.159 690.237 7244.4202 19.1733 B- 14429.7751 706.2429 36 021879.000 741.000 + 10 23 13 36 Al x 5950.384 149.505 7623.5154 4.1529 B- 18386.5096 165.8510 36 006388.000 160.500 + 8 22 14 36 Si x -12436.125 71.797 8112.5199 1.9944 B- 7814.9194 72.9852 35 986649.271 77.077 + 6 21 15 36 P + -20251.045 13.114 8307.8692 0.3643 B- 10413.0962 13.1124 35 978259.610 14.078 + 4 20 16 36 S -30664.141 0.188 8575.3900 0.0052 B- -1142.1329 0.1893 35 967080.692 0.201 + 2 19 17 36 Cl -29522.008 0.036 8521.9322 0.0010 B- 709.5343 0.0449 35 968306.822 0.038 + 0 18 18 36 Ar -30231.542 0.027 8519.9096 0.0008 B- -12814.3607 0.3259 35 967545.106 0.028 + -2 17 19 36 K -17417.182 0.325 8142.2233 0.0090 B- -10966.0155 40.0013 35 981301.887 0.349 + -4 16 20 36 Ca 4n -6451.166 40.000 7815.8799 1.1111 B- -22601# 303# 35 993074.388 42.941 + -6 15 21 36 Sc x 16150# 300# 7166# 8# B- * 36 017338# 322# +0 15 26 11 37 Na -nn 53134# 687# 6403# 19# B- 24923# 980# 37 057042# 737# + 13 25 12 37 Mg -n 28211.478 698.947 7055.1115 18.8905 B- 18401.9132 721.8139 37 030286.265 750.350 + 11 24 13 37 Al x 9809.564 180.244 7531.3160 4.8715 B- 16381.0765 213.1678 37 010531.000 193.500 + 9 23 14 37 Si x -6571.512 113.809 7952.9033 3.0759 B- 12424.5003 119.9691 36 992945.191 122.179 + 7 22 15 37 P p-2n -18996.012 37.948 8267.5561 1.0256 B- 7900.4135 37.9474 36 979606.942 40.738 + 5 21 16 37 S -n -26896.426 0.198 8459.9363 0.0054 B- 4865.1258 0.1965 36 971125.500 0.212 + 3 20 17 37 Cl -31761.552 0.052 8570.2816 0.0014 B- -813.8729 0.2000 36 965902.573 0.055 + 1 19 18 37 Ar - -30947.679 0.207 8527.1406 0.0056 B- -6147.4775 0.2270 36 966776.301 0.221 + -1 18 19 37 K -p -24800.201 0.094 8339.8480 0.0025 B- -11664.1314 0.6412 36 973375.890 0.100 + -3 17 20 37 Ca x -13136.070 0.634 8003.4567 0.0171 B- -16916# 300# 36 985897.849 0.680 + -5 16 21 37 Sc x 3780# 300# 7525# 8# B- -21390# 500# 37 004058# 322# + -7 15 22 37 Ti x 25170# 400# 6926# 11# B- * 37 027021# 429# +0 16 27 11 38 Na -n 61905# 715# 6216# 19# B- 27831# 875# 38 066458# 768# + 14 26 12 38 Mg x 34074# 503# 6928# 13# B- 17604# 525# 38 036580# 540# + 12 25 13 38 Al x 16470# 150# 7370# 4# B- 20640# 183# 38 017681# 161# + 10 24 14 38 Si x -4170.299 104.793 7892.8297 2.7577 B- 10451.2656 127.4736 37 995523.000 112.500 + 8 23 15 38 P x -14621.565 72.581 8147.2749 1.9100 B- 12239.6512 72.9340 37 984303.105 77.918 + 6 22 16 38 S + -26861.216 7.172 8448.7829 0.1887 B- 2936.9000 7.1714 37 971163.300 7.699 + 4 21 17 38 Cl -n -29798.116 0.098 8505.4817 0.0026 B- 4916.7109 0.2182 37 968010.408 0.105 + 2 20 18 38 Ar -34714.827 0.195 8614.2807 0.0051 B- -5914.0671 0.0448 37 962732.102 0.209 + 0 19 19 38 K -28800.760 0.195 8438.0593 0.0051 B- -6742.2563 0.0626 37 969081.114 0.209 + -2 18 20 38 Ca -22058.503 0.194 8240.0434 0.0051 B- -17809# 200# 37 976319.223 0.208 + -4 17 21 38 Sc x -4249# 200# 7751# 5# B- -15619# 361# 37 995438# 215# + -6 16 22 38 Ti x 11370# 300# 7319# 8# B- * 38 012206# 322# +0 17 28 11 39 Na -n 69977# 743# 6056# 19# B- 27201# 903# 39 075123# 797# + 15 27 12 39 Mg -n 42775# 513# 6734# 13# B- 21286# 594# 39 045921# 551# + 13 26 13 39 Al x 21490# 300# 7260# 8# B- 19169# 329# 39 023070# 322# + 11 25 14 39 Si x 2320.352 135.532 7730.9793 3.4752 B- 15094.9874 176.2324 39 002491.000 145.500 + 9 24 15 39 P x -12774.636 112.645 8097.9701 2.8883 B- 10388.0361 123.2430 38 986285.865 120.929 + 7 23 16 39 S 2p-n -23162.672 50.000 8344.2698 1.2821 B- 6637.5463 50.0300 38 975133.850 53.677 + 5 22 17 39 Cl -nn -29800.218 1.732 8494.4032 0.0444 B- 3441.9774 5.2915 38 968008.151 1.859 + 3 21 18 39 Ar + -33242.195 5.000 8562.5988 0.1282 B- 565.0000 5.0000 38 964313.037 5.367 + 1 20 19 39 K -33807.19535 0.00456 8557.0258 0.0003 B- -6524.4888 0.5962 38 963706.48482 0.00489 + -1 19 20 39 Ca -27282.707 0.596 8369.6711 0.0153 B- -13109.9804 24.0074 38 970710.811 0.640 + -3 18 21 39 Sc 2n-p -14172.726 24.000 8013.4575 0.6154 B- -16673# 202# 38 984784.953 25.765 + -5 17 22 39 Ti x 2500# 200# 7566# 5# B- -20070# 447# 39 002684# 215# + -7 16 23 39 V x 22570# 400# 7031# 10# B- * 39 024230# 429# +0 16 28 12 40 Mg x 49550# 500# 6598# 13# B- 20729# 583# 40 053194# 537# + 14 27 13 40 Al x 28820# 300# 7097# 7# B- 23154# 324# 40 030940# 322# + 12 26 14 40 Si x 5666.876 121.991 7655.8247 3.0498 B- 13806.0653 147.8912 40 006083.641 130.962 + 10 25 15 40 P x -8139.189 83.607 7981.4177 2.0902 B- 14698.6603 83.7017 39 991262.221 89.755 + 8 24 16 40 S -22837.850 3.982 8329.3255 0.0996 B- 4719.9687 32.3118 39 975482.561 4.274 + 6 23 17 40 Cl + -27557.818 32.066 8427.7660 0.8016 B- 7482.0816 32.0655 39 970415.466 34.423 + 4 22 18 40 Ar -35039.89997 0.00218 8595.2594 0.0002 B- -1504.4031 0.0559 39 962383.12204 0.00234 + 2 21 19 40 K -33535.497 0.056 8538.0907 0.0014 B- 1310.9051 0.0596 39 963998.165 0.060 + 0 20 20 40 Ca -34846.402 0.020 8551.3046 0.0006 B- -14323.0493 2.8281 39 962590.850 0.022 + -2 19 21 40 Sc - -20523.353 2.828 8173.6697 0.0707 B- -11529.9139 68.3023 39 977967.275 3.036 + -4 18 22 40 Ti -8993.439 68.244 7865.8632 1.7061 B- -21463# 308# 39 990345.146 73.262 + -6 17 23 40 V x 12470# 300# 7310# 7# B- * 40 013387# 322# +0 17 29 12 41 Mg x 58100# 500# 6425# 12# B- 23510# 640# 41 062373# 537# + 15 28 13 41 Al x 34590# 400# 6980# 10# B- 21390# 500# 41 037134# 429# + 13 27 14 41 Si x 13200# 300# 7482# 7# B- 18180# 323# 41 014171# 322# + 11 26 15 41 P x -4979.767 120.163 7906.5513 2.9308 B- 14028.8125 120.2326 40 994654.000 129.000 + 9 25 16 41 S x -19008.580 4.099 8229.6358 0.1000 B- 8298.6116 68.8456 40 979593.451 4.400 + 7 24 17 41 Cl x -27307.192 68.723 8412.9593 1.6762 B- 5760.3180 68.7243 40 970684.525 73.777 + 5 23 18 41 Ar -n -33067.510 0.347 8534.3733 0.0085 B- 2492.0392 0.3473 40 964500.570 0.372 + 3 22 19 41 K -35559.54880 0.00376 8576.0731 0.0003 B- -421.6406 0.1377 40 961825.25611 0.00403 + 1 21 20 41 Ca -35137.908 0.138 8546.7075 0.0034 B- -6495.5482 0.1553 40 962277.905 0.147 + -1 20 21 41 Sc -28642.360 0.077 8369.1979 0.0019 B- -12944.8214 27.9449 40 969251.163 0.083 + -3 19 22 41 Ti x -15697.539 27.945 8034.3889 0.6816 B- -16008# 202# 40 983148.000 30.000 + -5 18 23 41 V x 310# 200# 7625# 5# B- -20100# 447# 41 000333# 215# + -7 17 24 41 Cr x 20410# 400# 7116# 10# B- * 41 021911# 429# +0 16 29 13 42 Al x 41990# 500# 6829# 12# B- 25150# 583# 42 045078# 537# + 14 28 14 42 Si x 16840# 300# 7410# 7# B- 15748# 315# 42 018078# 322# + 12 27 15 42 P x 1091.842 95.009 7765.9122 2.2621 B- 18729.5899 95.0504 42 001172.140 101.996 + 10 26 16 42 S x -17637.748 2.794 8193.2275 0.0665 B- 7194.0221 59.6811 41 981065.100 3.000 + 8 25 17 42 Cl x -24831.770 59.616 8345.8864 1.4194 B- 9590.9082 59.8947 41 973342.000 64.000 + 6 24 18 42 Ar x -34422.678 5.775 8555.6141 0.1375 B- 599.3527 5.7763 41 963045.737 6.200 + 4 23 19 42 K -n -35022.031 0.106 8551.2571 0.0025 B- 3525.2626 0.1825 41 962402.305 0.113 + 2 22 20 42 Ca -38547.293 0.148 8616.5646 0.0035 B- -6426.2904 0.0485 41 958617.780 0.159 + 0 21 21 42 Sc -32121.003 0.154 8444.9303 0.0037 B- -7016.6496 0.2239 41 965516.686 0.165 + -2 20 22 42 Ti -25104.353 0.269 8259.2400 0.0064 B- -17485# 196# 41 973049.369 0.289 + -4 19 23 42 V x -7620# 196# 7824# 5# B- -14679# 358# 41 991820# 210# + -6 18 24 42 Cr x 7060# 300# 7456# 7# B- * 42 007579# 322# +0 17 30 13 43 Al x 48270# 600# 6712# 14# B- 23940# 721# 43 051820# 644# + 15 29 14 43 Si x 24330# 400# 7251# 9# B- 19289# 500# 43 026119# 429# + 13 28 15 43 P x 5040# 300# 7681# 7# B- 17236# 300# 43 005411# 322# + 11 27 16 43 S x -12195.461 4.970 8063.8276 0.1156 B- 11964.0500 62.0579 42 986907.635 5.335 + 9 26 17 43 Cl x -24159.510 61.859 8323.8672 1.4386 B- 7850.3002 62.0860 42 974063.700 66.407 + 7 25 18 43 Ar x -32009.811 5.310 8488.2382 0.1235 B- 4565.5836 5.3254 42 965636.056 5.700 + 5 24 19 43 K -4n -36575.394 0.410 8576.2204 0.0095 B- 1833.4783 0.4687 42 960734.701 0.440 + 3 23 20 43 Ca -38408.873 0.227 8600.6653 0.0053 B- -2220.7227 1.8650 42 958766.381 0.244 + 1 22 21 43 Sc -p -36188.150 1.863 8530.8265 0.0433 B- -6872.5591 6.0147 42 961150.425 1.999 + -1 21 22 43 Ti -29315.591 5.719 8352.8054 0.1330 B- -11399.2333 43.2287 42 968528.420 6.139 + -3 20 23 43 V x -17916.358 42.849 8069.5129 0.9965 B- -15946# 205# 42 980766.000 46.000 + -5 19 24 43 Cr x -1970# 200# 7680# 5# B- -19340# 447# 42 997885# 215# + -7 18 25 43 Mn x 17370# 400# 7213# 9# B- * 43 018647# 429# +0 16 30 14 44 Si x 29310# 500# 7156# 11# B- 18200# 640# 44 031466# 537# + 14 29 15 44 P x 11110# 400# 7552# 9# B- 20314# 400# 44 011927# 429# + 12 28 16 44 S x -9204.236 5.216 7996.0154 0.1186 B- 11274.7373 85.7253 43 990118.846 5.600 + 10 27 17 44 Cl x -20478.973 85.566 8234.4788 1.9447 B- 12194.2869 85.5811 43 978014.918 91.859 + 8 26 18 44 Ar x -32673.260 1.584 8493.8411 0.0360 B- 3108.2375 1.6381 43 964923.814 1.700 + 6 25 19 44 K x -35781.498 0.419 8546.7023 0.0095 B- 5687.2319 0.5303 43 961586.984 0.450 + 4 24 20 44 Ca -41468.730 0.325 8658.1769 0.0074 B- -3652.6948 1.7565 43 955481.489 0.348 + 2 23 21 44 Sc -p -37816.035 1.756 8557.3805 0.0399 B- -267.4488 1.8899 43 959402.818 1.884 + 0 22 22 44 Ti -a -37548.586 0.700 8533.5215 0.0159 B- -13740.5071 7.2986 43 959689.936 0.751 + -2 21 23 44 V -23808.079 7.265 8203.4567 0.1651 B- -10386.1805 51.7447 43 974440.977 7.799 + -4 20 24 44 Cr x -13421.899 51.232 7949.6265 1.1644 B- -20882# 304# 43 985591.000 55.000 + -6 19 25 44 Mn x 7460# 300# 7457# 7# B- * 44 008009# 322# +0 17 31 14 45 Si x 37090# 600# 7004# 13# B- 21130# 781# 45 039818# 644# + 15 30 15 45 P x 15960# 500# 7456# 11# B- 19301# 583# 45 017134# 537# + 13 29 16 45 S x -3340# 300# 7867# 7# B- 14922# 329# 44 996414# 322# + 11 28 17 45 Cl x -18262.544 136.163 8181.5991 3.0259 B- 11508.2568 136.1643 44 980394.353 146.177 + 9 27 18 45 Ar x -29770.801 0.512 8419.9526 0.0114 B- 6844.8422 0.7311 44 968039.731 0.550 + 7 26 19 45 K x -36615.643 0.522 8554.6747 0.0116 B- 4196.5868 0.6369 44 960691.491 0.560 + 5 25 20 45 Ca -40812.230 0.365 8630.5467 0.0081 B- 260.0910 0.7377 44 956186.270 0.392 + 3 24 21 45 Sc -41072.321 0.663 8618.9410 0.0147 B- -2062.0551 0.5086 44 955907.051 0.712 + 1 23 22 45 Ti -39010.266 0.836 8555.7321 0.0186 B- -7123.8247 0.2142 44 958120.758 0.897 + -1 22 23 45 V -31886.441 0.863 8380.0394 0.0192 B- -12371.6400 35.4073 44 965768.498 0.926 + -3 21 24 45 Cr x -19514.801 35.397 8087.7286 0.7866 B- -14535# 302# 44 979050.000 38.000 + -5 20 25 45 Mn x -4980# 300# 7747# 7# B- -19388# 412# 44 994654# 322# + -7 19 26 45 Fe -pp 14408# 283# 7299# 6# B- * 45 015467# 304# +0 16 31 15 46 P x 22840# 500# 7320# 11# B- 22200# 640# 46 024520# 537# + 14 30 16 46 S x 640# 400# 7785# 9# B- 14375# 411# 46 000687# 429# + 12 29 17 46 Cl x -13734.949 97.249 8080.7757 2.1141 B- 16036.3062 97.2766 45 985254.926 104.400 + 10 28 18 46 Ar x -29771.255 2.329 8412.3835 0.0506 B- 5642.6746 2.4394 45 968039.244 2.500 + 8 27 19 46 K x -35413.929 0.727 8518.0428 0.0158 B- 7725.6802 2.3490 45 961981.584 0.780 + 6 26 20 46 Ca -43139.610 2.234 8668.9848 0.0486 B- -1377.9665 2.3305 45 953687.726 2.398 + 4 25 21 46 Sc -n -41761.643 0.671 8622.0215 0.0146 B- 2366.6260 0.6666 45 955167.034 0.720 + 2 24 22 46 Ti -44128.269 0.090 8656.4623 0.0020 B- -7052.3723 0.0923 45 952626.356 0.097 + 0 23 23 46 V -37075.897 0.134 8486.1423 0.0029 B- -7604.3264 11.4538 45 960197.389 0.143 + -2 22 24 46 Cr -29471.570 11.453 8303.8233 0.2490 B- -17053.8226 87.3828 45 968360.969 12.295 + -4 21 25 46 Mn x -12417.748 86.629 7916.0805 1.8832 B- -13628# 312# 45 986669.000 93.000 + -6 20 26 46 Fe x 1210# 300# 7603# 7# B- * 46 001299# 322# +0 17 32 15 47 P x 28810# 600# 7209# 13# B- 21610# 721# 47 030929# 644# + 15 31 16 47 S x 7200# 400# 7652# 9# B- 16781# 447# 47 007730# 429# + 13 30 17 47 Cl x -9580# 200# 7992# 4# B- 15787# 200# 46 989715# 215# + 11 29 18 47 Ar x -25367.274 1.211 8311.4250 0.0258 B- 10344.7078 1.8490 46 972767.112 1.300 + 9 28 19 47 K x -35711.982 1.397 8514.8795 0.0297 B- 6632.6837 2.6237 46 961661.612 1.500 + 7 27 20 47 Ca -42344.665 2.221 8639.3548 0.0473 B- 1992.1770 1.1849 46 954541.134 2.384 + 5 26 21 47 Sc -44336.842 1.931 8665.0958 0.0411 B- 600.7694 1.9292 46 952402.444 2.072 + 3 25 22 47 Ti -44937.612 0.080 8661.2325 0.0017 B- -2930.5422 0.0879 46 951757.491 0.085 + 1 24 23 47 V -42007.070 0.110 8582.2348 0.0024 B- -7443.9769 5.1976 46 954903.558 0.118 + -1 23 24 47 Cr -34563.093 5.197 8407.2067 0.1106 B- -11996.7167 32.0943 46 962894.995 5.578 + -3 22 25 47 Mn x -22566.376 31.671 8135.3117 0.6738 B- -15437# 501# 46 975774.000 34.000 + -5 21 26 47 Fe x -7130# 500# 7790# 11# B- -17750# 781# 46 992346# 537# + -7 20 27 47 Co x 10620# 600# 7396# 13# B- * 47 011401# 644# +0 16 32 16 48 S x 12390# 500# 7552# 10# B- 16670# 707# 48 013301# 537# + 14 31 17 48 Cl x -4280# 500# 7883# 10# B- 18075# 500# 47 995405# 537# + 12 30 18 48 Ar x -22354.927 16.767 8243.6656 0.3493 B- 9929.5550 16.7847 47 976001.000 18.000 + 10 29 19 48 K x -32284.482 0.773 8434.2324 0.0161 B- 11940.3857 0.7734 47 965341.184 0.830 + 8 28 20 48 Ca -44224.868 0.018 8666.6916 0.0004 B- 279.2155 4.9499 47 952522.654 0.018 + 6 27 21 48 Sc -44504.083 4.950 8656.2097 0.1031 B- 3988.8685 4.9499 47 952222.903 5.313 + 4 26 22 48 Ti -48492.952 0.074 8723.0122 0.0016 B- -4014.9467 0.9691 47 947940.677 0.079 + 2 25 23 48 V -44478.005 0.972 8623.0686 0.0202 B- -1656.6918 7.3746 47 952250.900 1.043 + 0 24 24 48 Cr +nn -42821.313 7.311 8572.2553 0.1523 B- -13524.6692 9.9157 47 954029.431 7.848 + -2 23 25 48 Mn -29296.644 6.699 8274.1924 0.1396 B- -11288.0685 92.4609 47 968548.760 7.191 + -4 22 26 48 Fe x -18008.575 92.218 8022.7254 1.9212 B- -19738# 509# 47 980667.000 99.000 + -6 21 27 48 Co x 1730# 500# 7595# 10# B- -16448# 656# 48 001857# 537# + -8 20 28 48 Ni -pp 18178# 424# 7236# 9# B- * 48 019515# 455# +0 17 33 16 49 S -n 20391# 583# 7400# 12# B- 19652# 707# 49 021891# 626# + 15 32 17 49 Cl x 740# 400# 7785# 8# B- 17800# 565# 49 000794# 429# + 13 31 18 49 Ar x -17060# 400# 8132# 8# B- 12551# 400# 48 981685# 429# + 11 30 19 49 K x -29611.496 0.801 8372.2753 0.0164 B- 11688.5069 0.8205 48 968210.753 0.860 + 9 29 20 49 Ca -n -41300.003 0.178 8594.8500 0.0036 B- 5262.4445 2.2745 48 955662.625 0.190 + 7 28 21 49 Sc -46562.447 2.268 8686.2805 0.0463 B- 2001.5652 2.2684 48 950013.159 2.434 + 5 27 22 49 Ti -48564.012 0.078 8711.1625 0.0016 B- -601.8555 0.8203 48 947864.391 0.084 + 3 26 23 49 V - -47962.157 0.824 8682.9135 0.0168 B- -2629.8047 2.3487 48 948510.509 0.884 + 1 25 24 49 Cr -45332.352 2.202 8613.2777 0.0449 B- -7712.4265 0.2329 48 951333.720 2.363 + -1 24 25 49 Mn -37619.925 2.214 8439.9150 0.0452 B- -12869.1957 24.3199 48 959613.350 2.377 + -3 23 26 49 Fe x -24750.730 24.219 8161.3121 0.4943 B- -14971# 501# 48 973429.000 26.000 + -5 22 27 49 Co x -9780# 500# 7840# 10# B- -18309# 781# 48 989501# 537# + -7 21 28 49 Ni x 8530# 600# 7450# 12# B- * 49 009157# 644# +0 16 33 17 50 Cl x 7700# 400# 7651# 8# B- 20930# 640# 50 008266# 429# + 14 32 18 50 Ar x -13230# 500# 8054# 10# B- 12498# 500# 49 985797# 537# + 12 31 19 50 K x -25727.853 7.731 8288.5833 0.1546 B- 13861.3774 7.8919 49 972380.015 8.300 + 10 30 20 50 Ca x -39589.230 1.584 8550.1639 0.0317 B- 4947.8903 2.9723 49 957499.215 1.700 + 8 29 21 50 Sc -44537.120 2.515 8633.4747 0.0503 B- 6894.7470 2.5166 49 952187.437 2.700 + 6 28 22 50 Ti -51431.867 0.082 8755.7227 0.0017 B- -2208.6274 0.0579 49 944785.622 0.088 + 4 27 23 50 V -49223.240 0.093 8695.9032 0.0019 B- 1038.1240 0.0551 49 947156.681 0.099 + 2 26 24 50 Cr -50261.364 0.094 8701.0188 0.0019 B- -7634.4776 0.0672 49 946042.209 0.100 + 0 25 25 50 Mn -42626.886 0.115 8532.6823 0.0023 B- -8150.4267 8.3842 49 954238.157 0.123 + -2 24 26 50 Fe x -34476.460 8.383 8354.0268 0.1677 B- -16887.0566 126.0308 49 962988.000 9.000 + -4 23 27 50 Co x -17589.403 125.752 8000.6387 2.5150 B- -14130# 516# 49 981117.000 135.000 + -6 22 28 50 Ni x -3460# 500# 7702# 10# B- * 49 996286# 537# +0 17 34 17 51 Cl x 14290# 700# 7530# 14# B- 20780# 806# 51 015341# 751# + 15 33 18 51 Ar x -6490# 400# 7922# 8# B- 16026# 400# 50 993033# 429# + 13 32 19 51 K x -22515.457 13.041 8221.3350 0.2557 B- 13816.8529 13.0517 50 975828.664 14.000 + 11 31 20 51 Ca x -36332.310 0.522 8476.9135 0.0102 B- 6918.0432 2.5686 50 960995.663 0.560 + 9 30 21 51 Sc -43250.353 2.515 8597.2213 0.0493 B- 6482.6122 2.5612 50 953568.838 2.700 + 7 29 22 51 Ti -49732.965 0.484 8708.9912 0.0095 B- 2470.1402 0.4820 50 946609.468 0.519 + 5 28 23 51 V -52203.105 0.097 8742.0852 0.0019 B- -752.3907 0.1494 50 943957.664 0.104 + 3 27 24 51 Cr -51450.715 0.167 8711.9923 0.0033 B- -3207.4893 0.3256 50 944765.388 0.178 + 1 26 25 51 Mn -48243.225 0.304 8633.7602 0.0060 B- -8054.0400 1.4309 50 948208.770 0.326 + -1 25 26 51 Fe x -40189.185 1.398 8460.4977 0.0274 B- -12847.0389 48.4579 50 956855.137 1.501 + -3 24 27 51 Co x -27342.146 48.438 8193.2549 0.9498 B- -15692# 503# 50 970647.000 52.000 + -5 23 28 51 Ni x -11650# 500# 7870# 10# B- * 50 987493# 537# +0 18 35 17 52 Cl x 22360# 700# 7386# 13# B- 23739# 922# 52 024004# 751# + 16 34 18 52 Ar x -1380# 600# 7827# 12# B- 15758# 601# 51 998519# 644# + 14 33 19 52 K x -17137.628 33.534 8115.0303 0.6449 B- 17128.6431 33.5405 51 981602.000 36.000 + 12 32 20 52 Ca x -34266.272 0.671 8429.3821 0.0129 B- 6257.2889 3.1463 51 963213.646 0.720 + 10 31 21 52 Sc -40523.560 3.074 8534.6695 0.0591 B- 8954.1372 4.1223 51 956496.170 3.300 + 8 30 22 52 Ti -49477.698 2.747 8691.8193 0.0528 B- 1965.3340 2.7510 51 946883.509 2.948 + 6 29 23 52 V -n -51443.032 0.159 8714.5690 0.0031 B- 3976.4763 0.1601 51 944773.636 0.170 + 4 28 24 52 Cr -55419.508 0.112 8775.9946 0.0022 B- -4708.1214 0.0633 51 940504.714 0.120 + 2 27 25 52 Mn - -50711.387 0.129 8670.4087 0.0025 B- -2379.2912 0.1534 51 945559.090 0.138 + 0 26 26 52 Fe -- -48332.095 0.179 8609.6079 0.0035 B- -13988.1167 5.2831 51 948113.364 0.192 + -2 25 27 52 Co -34343.979 5.282 8325.5606 0.1016 B- -11784.1230 83.0710 51 963130.224 5.669 + -4 24 28 52 Ni x -22559.856 82.903 8083.8977 1.5943 B- -20680# 606# 51 975781.000 89.000 + -6 23 29 52 Cu x -1880# 600# 7671# 12# B- * 51 997982# 644# +0 17 35 18 53 Ar x 6791# 699# 7677# 13# B- 19086# 708# 53 007290# 750# + 15 34 19 53 K x -12295.722 111.779 8022.8488 2.1090 B- 17091.9853 120.0471 52 986800.000 120.000 + 13 33 20 53 Ca x -29387.707 43.780 8330.5778 0.8260 B- 9381.8471 47.2223 52 968451.000 47.000 + 11 32 21 53 Sc -38769.555 17.698 8492.8325 0.3339 B- 8111.8785 17.9325 52 958379.173 19.000 + 9 31 22 53 Ti x -46881.433 2.888 8631.1256 0.0545 B- 4970.2419 4.2386 52 949670.714 3.100 + 7 30 23 53 V +p -51851.675 3.103 8710.1425 0.0585 B- 3435.9426 3.1017 52 944334.940 3.331 + 5 29 24 53 Cr -55287.618 0.116 8760.2103 0.0022 B- -597.2679 0.3430 52 940646.304 0.124 + 3 28 25 53 Mn -54690.350 0.346 8734.1798 0.0065 B- -3742.8664 1.6971 52 941287.497 0.371 + 1 27 26 53 Fe -50947.483 1.669 8648.7985 0.0315 B- -8288.1073 0.4431 52 945305.629 1.792 + -1 26 27 53 Co -42659.376 1.727 8477.6578 0.0326 B- -13028.5485 25.2096 52 954203.278 1.854 + -3 25 28 53 Ni x -29630.827 25.150 8217.0749 0.4745 B- -16491# 501# 52 968190.000 27.000 + -5 24 29 53 Cu x -13140# 500# 7891# 9# B- * 52 985894# 537# +0 18 36 18 54 Ar x 12560# 800# 7578# 15# B- 17710# 894# 54 013484# 859# + 16 35 19 54 K x -5150# 400# 7891# 7# B- 20010# 403# 53 994471# 429# + 14 34 20 54 Ca x -25160.587 48.438 8247.4967 0.8970 B- 9277.3463 50.4129 53 972989.000 52.000 + 12 33 21 54 Sc x -34437.934 13.973 8404.8115 0.2588 B- 11305.8789 21.1188 53 963029.359 15.000 + 10 32 22 54 Ti x -45743.812 15.835 8599.6917 0.2932 B- 4154.4548 19.3840 53 950892.000 17.000 + 8 31 23 54 V -49898.267 11.180 8662.1382 0.2070 B- 7037.1118 11.1794 53 946432.009 12.001 + 6 30 24 54 Cr -56935.379 0.132 8777.9672 0.0025 B- -1377.1325 1.0051 53 938877.359 0.142 + 4 29 25 54 Mn -p -55558.247 1.007 8737.9768 0.0186 B- 696.3688 1.0587 53 940355.772 1.080 + 2 28 26 54 Fe -56254.615 0.343 8736.3846 0.0064 B- -8244.5478 0.0893 53 939608.189 0.368 + 0 27 27 54 Co -48010.068 0.355 8569.2199 0.0066 B- -8731.7558 4.6710 53 948459.075 0.380 + -2 26 28 54 Ni x -39278.312 4.657 8393.0328 0.0862 B- -18038# 400# 53 957833.000 5.000 + -4 25 29 54 Cu x -21240# 400# 8045# 7# B- -15538# 454# 53 977198# 429# + -6 24 30 54 Zn -pp -5702# 217# 7742# 4# B- * 53 993879# 232# +0 17 36 19 55 K x 470# 500# 7792# 9# B- 19121# 525# 55 000505# 537# + 15 35 20 55 Ca x -18650.375 160.217 8125.9260 2.9130 B- 12191.7329 171.9435 54 979978.000 172.000 + 13 34 21 55 Sc x -30842.108 62.411 8333.3694 1.1347 B- 10990.3608 68.7671 54 966889.637 67.000 + 11 33 22 55 Ti x -41832.469 28.876 8518.9696 0.5250 B- 7292.6673 39.5419 54 955091.000 31.000 + 9 32 23 55 V x -49125.136 27.013 8637.3391 0.4912 B- 5985.1877 27.0143 54 947262.000 29.000 + 7 31 24 55 Cr -n -55110.324 0.228 8731.9362 0.0042 B- 2602.2183 0.3219 54 940836.637 0.245 + 5 30 25 55 Mn -57712.542 0.260 8765.0247 0.0047 B- -231.1204 0.1786 54 938043.040 0.279 + 3 29 26 55 Fe -57481.422 0.308 8746.5981 0.0056 B- -3451.4254 0.3241 54 938291.158 0.330 + 1 28 27 55 Co -54029.996 0.405 8669.6204 0.0074 B- -8694.0350 0.5775 54 941996.416 0.434 + -1 27 28 55 Ni - -45335.961 0.705 8497.3225 0.0128 B- -13700.5585 155.5611 54 951329.846 0.757 + -3 26 29 55 Cu x -31635.403 155.560 8233.9970 2.8284 B- -17366# 429# 54 966038.000 167.000 + -5 25 30 55 Zn x -14270# 400# 7904# 7# B- * 54 984681# 429# +0 18 37 19 56 K x 7980# 600# 7663# 11# B- 21491# 650# 56 008567# 644# + 16 36 20 56 Ca x -13510.390 249.640 8033.1654 4.4579 B- 12005.4580 360.2029 55 985496.000 268.000 + 14 35 21 56 Sc x -25515.848 259.665 8233.5781 4.6369 B- 13907.1470 278.3271 55 972607.611 278.761 + 12 34 22 56 Ti -39422.995 100.201 8467.9495 1.7893 B- 6760.4051 188.1842 55 957677.675 107.569 + 10 33 23 56 V -46183.401 175.884 8574.7006 3.1408 B- 9101.7270 175.8854 55 950420.082 188.819 + 8 32 24 56 Cr ++ -55285.128 0.578 8723.2609 0.0103 B- 1626.5384 0.5524 55 940648.977 0.620 + 6 31 25 56 Mn -n -56911.666 0.293 8738.3358 0.0052 B- 3695.4973 0.2065 55 938902.816 0.314 + 4 30 26 56 Fe -60607.163 0.268 8790.3563 0.0048 B- -4566.6455 0.4104 55 934935.537 0.287 + 2 29 27 56 Co -56040.518 0.475 8694.8386 0.0085 B- -2132.8689 0.3735 55 939838.032 0.510 + 0 28 28 56 Ni -53907.649 0.399 8642.7811 0.0071 B- -15277.9163 6.4070 55 942127.761 0.428 + -2 27 29 56 Cu x -38629.733 6.395 8355.9907 0.1142 B- -13240# 400# 55 958529.278 6.864 + -4 26 30 56 Zn x -25390# 400# 8106# 7# B- -21550# 640# 55 972743# 429# + -6 25 31 56 Ga x -3840# 500# 7707# 9# B- * 55 995878# 537# +0 19 38 19 57 K x 14130# 600# 7563# 11# B- 20689# 721# 57 015169# 644# + 17 37 20 57 Ca x -6560# 400# 7912# 7# B- 14820# 438# 56 992958# 429# + 15 36 21 57 Sc x -21379.653 179.778 8158.1666 3.1540 B- 13022.1957 273.3249 56 977048.000 193.000 + 13 35 22 57 Ti x -34401.848 205.879 8372.9008 3.6119 B- 10033.2148 222.6466 56 963068.098 221.020 + 11 34 23 57 V x -44435.063 84.766 8535.1967 1.4871 B- 8089.9214 84.7864 56 952297.000 91.000 + 9 33 24 57 Cr x -52524.985 1.863 8663.3998 0.0327 B- 4961.2946 2.3948 56 943612.112 2.000 + 7 32 25 57 Mn -57486.279 1.505 8736.7146 0.0264 B- 2695.7375 1.5219 56 938285.944 1.615 + 5 31 26 57 Fe -60182.017 0.268 8770.2829 0.0047 B- -836.3589 0.4493 56 935391.950 0.287 + 3 30 27 57 Co -59345.658 0.516 8741.8845 0.0090 B- -3261.6970 0.6417 56 936289.819 0.553 + 1 29 28 57 Ni -56083.961 0.566 8670.9364 0.0099 B- -8774.9466 0.4393 56 939791.394 0.608 + -1 28 29 57 Cu -47309.014 0.501 8503.2646 0.0088 B- -14759# 200# 56 949211.686 0.537 + -3 27 30 57 Zn x -32550# 200# 8231# 4# B- -17140# 447# 56 965056# 215# + -5 26 31 57 Ga x -15410# 400# 7916# 7# B- * 56 983457# 429# +0 20 39 19 58 K x 21930# 700# 7437# 12# B- 23461# 860# 58 023543# 751# + 18 38 20 58 Ca x -1530# 500# 7828# 9# B- 13949# 535# 57 998357# 537# + 16 37 21 58 Sc x -15479.569 190.025 8054.9436 3.2763 B- 15438.0995 264.0509 57 983382.000 204.000 + 14 36 22 58 Ti x -30917.668 183.340 8307.6290 3.1610 B- 9512.9152 206.8675 57 966808.519 196.823 + 12 35 23 58 V x -40430.584 95.816 8458.1560 1.6520 B- 11561.2240 95.8625 57 956595.985 102.862 + 10 34 24 58 Cr x -51991.808 2.981 8643.9987 0.0514 B- 3835.7607 4.0227 57 944184.501 3.200 + 8 33 25 58 Mn x -55827.568 2.701 8696.6438 0.0466 B- 6327.7027 2.7198 57 940066.643 2.900 + 6 32 26 58 Fe -62155.271 0.316 8792.2534 0.0055 B- -2307.9785 1.1389 57 933273.575 0.339 + 4 31 27 58 Co -59847.292 1.153 8738.9719 0.0199 B- 381.5789 1.1071 57 935751.292 1.237 + 2 30 28 58 Ni -60228.871 0.349 8732.0621 0.0060 B- -8561.0204 0.4425 57 935341.650 0.374 + 0 29 29 58 Cu -51667.851 0.564 8570.9696 0.0097 B- -9368.9796 50.0020 57 944532.283 0.604 + -2 28 30 58 Zn -- -42298.871 50.001 8395.9467 0.8621 B- -18759# 304# 57 954590.296 53.678 + -4 27 31 58 Ga x -23540# 300# 8059# 5# B- -15960# 583# 57 974729# 322# + -6 26 32 58 Ge x -7580# 500# 7770# 9# B- * 57 991863# 537# +0 21 40 19 59 K x 28750# 800# 7332# 14# B- 22940# 1000# 59 030864# 859# + 19 39 20 59 Ca x 5810# 600# 7708# 10# B- 16639# 650# 59 006237# 644# + 17 38 21 59 Sc x -10829.550 249.640 7976.4073 4.2312 B- 15050# 390# 58 988374.000 268.000 + 15 37 22 59 Ti x -25880# 300# 8218# 5# B- 11731# 330# 58 972217# 322# + 13 36 23 59 V x -37610.617 137.400 8403.8034 2.3288 B- 10505.3137 137.4021 58 959623.343 147.505 + 11 35 24 59 Cr x -48115.931 0.671 8568.5995 0.0114 B- 7409.3977 2.4234 58 948345.426 0.720 + 9 34 25 59 Mn x -55525.328 2.329 8680.9224 0.0395 B- 5139.6290 2.3520 58 940391.111 2.500 + 7 33 26 59 Fe -60664.957 0.330 8754.7746 0.0056 B- 1564.8804 0.3690 58 934873.492 0.354 + 5 32 27 59 Co -62229.838 0.397 8768.0379 0.0067 B- -1073.0050 0.1944 58 933193.524 0.426 + 3 31 28 59 Ni -61156.833 0.351 8736.5912 0.0060 B- -4798.3786 0.3973 58 934345.442 0.376 + 1 30 29 59 Cu -56358.454 0.528 8642.0027 0.0090 B- -9142.7760 0.6018 58 939496.713 0.566 + -1 29 30 59 Zn -47215.678 0.759 8473.7802 0.0129 B- -13456# 170# 58 949311.886 0.814 + -3 28 31 59 Ga x -33760# 170# 8232# 3# B- -17390# 434# 58 963757# 183# + -5 27 32 59 Ge x -16370# 400# 7924# 7# B- * 58 982426# 429# +0 20 40 20 60 Ca x 11000# 700# 7627# 12# B- 15550# 860# 60 011809# 751# + 18 39 21 60 Sc x -4550# 500# 7873# 8# B- 17549# 555# 59 995115# 537# + 16 38 22 60 Ti x -22099.698 240.325 8152.7858 4.0054 B- 10987.7040 301.4311 59 976275.000 258.000 + 14 37 23 60 V x -33087.402 181.946 8322.8751 3.0324 B- 13821.0986 181.9496 59 964479.215 195.327 + 12 36 24 60 Cr x -46908.500 1.118 8540.1876 0.0186 B- 6059.4457 2.5831 59 949641.656 1.200 + 10 35 25 60 Mn x -52967.946 2.329 8628.1392 0.0388 B- 8445.2283 4.1261 59 943136.574 2.500 + 8 34 26 60 Fe -nn -61413.174 3.406 8755.8539 0.0568 B- 237.2633 3.4106 59 934070.249 3.656 + 6 33 27 60 Co -n -61650.437 0.403 8746.7692 0.0067 B- 2822.8058 0.2124 59 933815.536 0.433 + 4 32 28 60 Ni -64473.243 0.353 8780.7769 0.0059 B- -6127.9810 1.5735 59 930785.129 0.378 + 2 31 29 60 Cu - -58345.262 1.613 8665.6047 0.0269 B- -4170.7922 1.6286 59 937363.787 1.731 + 0 30 30 60 Zn -54174.470 0.548 8583.0524 0.0091 B- -14584# 200# 59 941841.317 0.588 + -2 29 31 60 Ga x -39590# 200# 8327# 3# B- -12060# 361# 59 957498# 215# + -4 28 32 60 Ge x -27530# 300# 8113# 5# B- -21890# 500# 59 970445# 322# + -6 27 33 60 As x -5640# 400# 7735# 7# B- * 59 993945# 429# +0 21 41 20 61 Ca x 19010# 800# 7503# 13# B- 18510# 1000# 61 020408# 859# + 19 40 21 61 Sc x 500# 600# 7794# 10# B- 16870# 671# 61 000537# 644# + 17 39 22 61 Ti x -16370# 300# 8058# 5# B- 13807# 381# 60 982426# 322# + 15 38 23 61 V x -30177.121 234.920 8271.0417 3.8511 B- 12319.3807 234.9272 60 967603.529 252.196 + 13 37 24 61 Cr x -42496.502 1.863 8460.1734 0.0305 B- 9245.6277 2.9822 60 954378.130 2.000 + 11 36 25 61 Mn x -51742.130 2.329 8598.9157 0.0382 B- 7178.3730 3.4965 60 944452.541 2.500 + 9 35 26 61 Fe x -58920.503 2.608 8703.7686 0.0428 B- 3977.6759 2.7399 60 936746.241 2.800 + 7 34 27 61 Co p2n -62898.179 0.839 8756.1510 0.0138 B- 1323.8504 0.7899 60 932476.031 0.901 + 5 33 28 61 Ni -64222.029 0.355 8765.0281 0.0058 B- -2237.9663 0.9617 60 931054.819 0.381 + 3 32 29 61 Cu p2n -61984.063 0.951 8715.5148 0.0156 B- -5635.1565 15.9028 60 933457.375 1.020 + 1 31 30 61 Zn -56348.906 15.899 8610.3098 0.2606 B- -9214.2438 37.6786 60 939506.964 17.068 + -1 30 31 61 Ga -47134.662 37.994 8446.4313 0.6228 B- -13345# 302# 60 949398.861 40.787 + -3 29 32 61 Ge x -33790# 300# 8215# 5# B- -16590# 424# 60 963725# 322# + -5 28 33 61 As x -17200# 300# 7930# 5# B- * 60 981535# 322# +0 20 41 21 62 Sc x 7310# 600# 7688# 10# B- 19510# 721# 62 007848# 644# + 18 40 22 62 Ti x -12200# 400# 7990# 6# B- 13013# 479# 61 986903# 429# + 16 39 23 62 V x -25213.164 264.287 8187.7565 4.2627 B- 15639.4478 264.3094 61 972932.556 283.723 + 14 38 24 62 Cr x -40852.611 3.447 8427.3871 0.0556 B- 7671.3532 7.3947 61 956142.920 3.700 + 12 37 25 62 Mn IT -48523.965 6.542 8538.5002 0.1055 B- 10354.0920 7.1142 61 947907.384 7.023 + 10 36 26 62 Fe x -58878.057 2.794 8692.8831 0.0451 B- 2546.3427 18.7834 61 936791.809 3.000 + 8 35 27 62 Co + -61424.399 18.574 8721.3347 0.2996 B- 5322.0404 18.5695 61 934058.198 19.940 + 6 34 28 62 Ni -66746.440 0.425 8794.5555 0.0069 B- -3958.8965 0.4751 61 928344.753 0.455 + 4 33 29 62 Cu - -62787.543 0.637 8718.0839 0.0103 B- -1619.4548 0.6507 61 932594.803 0.683 + 2 32 30 62 Zn -61168.088 0.615 8679.3451 0.0099 B- -9181.0666 0.3763 61 934333.359 0.660 + 0 31 31 62 Ga -51987.022 0.637 8518.6449 0.0103 B- -9847# 140# 61 944189.639 0.684 + -2 30 32 62 Ge x -42140# 140# 8347# 2# B- -17720# 331# 61 954761# 150# + -4 29 33 62 As x -24420# 300# 8049# 5# B- * 61 973784# 322# +0 21 42 21 63 Sc x 13070# 700# 7603# 11# B- 18930# 860# 63 014031# 751# + 19 41 22 63 Ti x -5860# 500# 7891# 8# B- 15880# 605# 62 993709# 537# + 17 40 23 63 V x -21740.141 339.995 8130.7809 5.3968 B- 14438.1586 347.6720 62 976661.000 365.000 + 15 39 24 63 Cr x -36178.299 72.657 8347.5398 1.1533 B- 10708.7611 72.7520 62 961161.000 78.000 + 13 38 25 63 Mn x -46887.061 3.726 8505.1020 0.0591 B- 8748.5685 5.6915 62 949664.672 4.000 + 11 37 26 63 Fe -55635.629 4.302 8631.5499 0.0683 B- 6215.9238 19.0668 62 940272.698 4.618 + 9 36 27 63 Co -61851.553 18.575 8717.7972 0.2948 B- 3661.3385 18.5704 62 933599.630 19.941 + 7 35 28 63 Ni -65512.891 0.426 8763.4955 0.0068 B- 66.9768 0.0149 62 929669.021 0.457 + 5 34 29 63 Cu -65579.868 0.426 8752.1404 0.0068 B- -3366.4392 1.5450 62 929597.119 0.457 + 3 33 30 63 Zn -62213.429 1.560 8686.2866 0.0248 B- -5666.3294 2.0330 62 933211.140 1.674 + 1 32 31 63 Ga x -56547.100 1.304 8583.9267 0.0207 B- -9625.8787 37.2826 62 939294.194 1.400 + -1 31 32 63 Ge x -46921.221 37.260 8418.7167 0.5914 B- -13421# 204# 62 949628.000 40.000 + -3 30 33 63 As x -33500# 200# 8193# 3# B- -16650# 539# 62 964036# 215# + -5 29 34 63 Se x -16850# 500# 7917# 8# B- * 62 981911# 537# +0 20 42 22 64 Ti x -1480# 600# 7826# 9# B- 14840# 721# 63 998411# 644# + 18 41 23 64 V x -16320# 400# 8045# 6# B- 17320# 500# 63 982480# 429# + 16 40 24 64 Cr x -33639.978 299.941 8303.5626 4.6866 B- 9349.0622 299.9620 63 963886.000 322.000 + 14 39 25 64 Mn x -42989.040 3.540 8437.4175 0.0553 B- 11980.5117 6.1402 63 953849.369 3.800 + 12 38 26 64 Fe x -54969.552 5.017 8612.3888 0.0784 B- 4822.8898 20.6249 63 940987.761 5.386 + 10 37 27 64 Co + -59792.442 20.005 8675.5223 0.3126 B- 7306.5921 20.0000 63 935810.176 21.476 + 8 36 28 64 Ni -67099.034 0.463 8777.4637 0.0072 B- -1674.6156 0.2055 63 927966.228 0.497 + 6 35 29 64 Cu -65424.418 0.427 8739.0736 0.0067 B- 579.5996 0.6447 63 929764.001 0.458 + 4 34 30 64 Zn -66004.018 0.644 8735.9057 0.0101 B- -7171.1912 1.4825 63 929141.776 0.690 + 2 33 31 64 Ga -58832.827 1.429 8611.6317 0.0223 B- -4517.3237 3.9905 63 936840.366 1.533 + 0 32 32 64 Ge x -54315.503 3.726 8528.8243 0.0582 B- -14783# 203# 63 941689.912 4.000 + -2 31 33 64 As -p -39532# 203# 8286# 3# B- -12673# 540# 63 957560# 218# + -4 30 34 64 Se x -26860# 500# 8075# 8# B- * 63 971165# 537# +0 21 43 22 65 Ti x 5210# 700# 7726# 11# B- 17320# 860# 65 005593# 751# + 19 42 23 65 V x -12110# 500# 7981# 8# B- 16200# 539# 64 986999# 537# + 17 41 24 65 Cr x -28310# 200# 8218# 3# B- 12657# 200# 64 969608# 215# + 15 40 25 65 Mn x -40967.344 3.726 8400.6822 0.0573 B- 10250.5576 6.3257 64 956019.749 4.000 + 13 39 26 65 Fe x -51217.902 5.112 8546.3470 0.0786 B- 7967.3036 5.5198 64 945015.323 5.487 + 11 38 27 65 Co x -59185.205 2.083 8656.8848 0.0320 B- 5940.5911 2.1379 64 936462.071 2.235 + 9 37 28 65 Ni -n -65125.796 0.483 8736.2424 0.0074 B- 2137.8808 0.6997 64 930084.585 0.518 + 7 36 29 65 Cu -67263.677 0.643 8757.0967 0.0099 B- -1351.6527 0.3557 64 927789.476 0.690 + 5 35 30 65 Zn -65912.024 0.646 8724.2660 0.0099 B- -3254.5380 0.6305 64 929240.534 0.693 + 3 34 31 65 Ga -62657.486 0.791 8662.1601 0.0122 B- -6179.2631 2.3046 64 932734.424 0.849 + 1 33 32 65 Ge -56478.223 2.165 8555.0584 0.0333 B- -9541.1670 84.7936 64 939368.136 2.323 + -1 32 33 65 As x -46937.056 84.766 8396.2351 1.3041 B- -13917# 312# 64 949611.000 91.000 + -3 31 34 65 Se x -33020# 300# 8170# 5# B- -16529# 583# 64 964552# 322# + -5 30 35 65 Br x -16490# 500# 7904# 8# B- * 64 982297# 537# +0 20 43 23 66 V x -6300# 500# 7894# 8# B- 18840# 583# 65 993237# 537# + 18 42 24 66 Cr x -25140# 300# 8168# 5# B- 11610# 300# 65 973011# 322# + 16 41 25 66 Mn x -36750.392 11.178 8331.7986 0.1694 B- 13317.4543 11.9056 65 960546.833 12.000 + 14 40 26 66 Fe x -50067.847 4.099 8521.7245 0.0621 B- 6340.6944 14.5611 65 946249.958 4.400 + 12 39 27 66 Co x -56408.541 13.972 8605.9419 0.2117 B- 9597.7522 14.0421 65 939442.943 15.000 + 10 38 28 66 Ni x -66006.293 1.397 8739.5086 0.0212 B- 251.9958 1.5405 65 929139.333 1.500 + 8 37 29 66 Cu -66258.289 0.649 8731.4730 0.0098 B- 2640.9396 0.9255 65 928868.804 0.696 + 6 36 30 66 Zn -68899.229 0.744 8759.6335 0.0113 B- -5175.5000 0.8000 65 926033.639 0.798 + 4 35 31 66 Ga - -63723.729 1.092 8669.3631 0.0166 B- -2116.6879 2.6376 65 931589.766 1.172 + 2 34 32 66 Ge x -61607.041 2.401 8625.4383 0.0364 B- -9581.9570 6.1685 65 933862.124 2.577 + 0 33 33 66 As x -52025.084 5.682 8468.4034 0.0861 B- -10365# 200# 65 944148.778 6.100 + -2 32 34 66 Se x -41660# 200# 8300# 3# B- -18091# 447# 65 955276# 215# + -4 31 35 66 Br x -23570# 400# 8014# 6# B- * 65 974697# 429# +0 21 44 23 67 V x -1744# 600# 7829# 9# B- 17526# 721# 66 998128# 644# + 19 43 24 67 Cr x -19270# 400# 8079# 6# B- 14311# 447# 66 979313# 429# + 17 42 25 67 Mn x -33580# 200# 8281# 3# B- 12128# 200# 66 963950# 215# + 15 41 26 67 Fe x -45708.416 3.819 8449.9359 0.0570 B- 9613.3678 7.4900 66 950930.000 4.100 + 13 40 27 67 Co x -55321.783 6.443 8581.7422 0.0962 B- 8420.9047 7.0607 66 940609.625 6.917 + 11 39 28 67 Ni x -63742.688 2.888 8695.7505 0.0431 B- 3576.8654 3.0223 66 931569.413 3.100 + 9 38 29 67 Cu -67319.553 0.892 8737.4597 0.0133 B- 560.8226 0.8296 66 927729.490 0.957 + 7 37 30 67 Zn -67880.376 0.755 8734.1534 0.0113 B- -1001.2201 1.1196 66 927127.422 0.810 + 5 36 31 67 Ga -66879.156 1.176 8707.5330 0.0176 B- -4205.4380 4.4066 66 928202.276 1.262 + 3 35 32 67 Ge -62673.718 4.319 8633.0884 0.0645 B- -6086.4858 4.3418 66 932716.999 4.636 + 1 34 33 67 As -56587.232 0.443 8530.5685 0.0066 B- -10006.9381 67.0690 66 939251.110 0.475 + -1 33 34 67 Se x -46580.294 67.068 8369.5344 1.0010 B- -14051# 307# 66 949994.000 72.000 + -3 32 35 67 Br x -32530# 300# 8148# 4# B- -16978# 520# 66 965078# 322# + -5 31 36 67 Kr -pp -15552# 424# 7883# 6# B- * 66 983305# 455# +0 20 44 24 68 Cr x -15690# 500# 8026# 7# B- 13230# 583# 67 983156# 537# + 18 43 25 68 Mn x -28920# 300# 8209# 4# B- 14977# 356# 67 968953# 322# + 16 42 26 68 Fe x -43897# 193# 8418# 3# B- 7746# 193# 67 952875# 207# + 14 41 27 68 Co -51642.591 3.859 8520.1301 0.0567 B- 11821.2318 4.8760 67 944559.401 4.142 + 12 40 28 68 Ni x -63463.822 2.981 8682.4667 0.0438 B- 2103.2205 3.3753 67 931868.787 3.200 + 10 39 29 68 Cu x -65567.043 1.584 8701.8913 0.0233 B- 4440.1115 1.7645 67 929610.887 1.700 + 8 38 30 68 Zn -70007.154 0.778 8755.6820 0.0115 B- -2921.1000 1.2000 67 924844.232 0.835 + 6 37 31 68 Ga - -67086.054 1.430 8701.2195 0.0210 B- -107.2555 2.3594 67 927980.161 1.535 + 4 36 32 68 Ge x -66978.799 1.876 8688.1371 0.0276 B- -8084.2715 2.6320 67 928095.305 2.014 + 2 35 33 68 As -58894.527 1.846 8557.7457 0.0271 B- -4705.0786 1.9112 67 936774.127 1.981 + 0 34 34 68 Se x -54189.449 0.496 8477.0482 0.0073 B- -15398# 259# 67 941825.236 0.532 + -2 33 35 68 Br -p -38791# 259# 8239# 4# B- -13165# 563# 67 958356# 278# + -4 32 36 68 Kr x -25626# 500# 8034# 7# B- * 67 972489# 537# +0 21 45 24 69 Cr x -9630# 500# 7939# 7# B- 15730# 640# 68 989662# 537# + 19 44 25 69 Mn x -25360# 400# 8155# 6# B- 13839# 447# 68 972775# 429# + 17 43 26 69 Fe x -39199# 200# 8345# 3# B- 11186# 218# 68 957918# 215# + 15 42 27 69 Co x -50385.447 85.697 8495.4062 1.2420 B- 9593.2084 85.7784 68 945909.000 92.000 + 13 41 28 69 Ni x -59978.656 3.726 8623.0998 0.0540 B- 5757.5650 3.9793 68 935610.267 4.000 + 11 40 29 69 Cu x -65736.221 1.397 8695.2044 0.0203 B- 2681.6854 1.6075 68 929429.267 1.500 + 9 39 30 69 Zn -n -68417.906 0.795 8722.7311 0.0115 B- 909.9134 1.4234 68 926550.360 0.853 + 7 38 31 69 Ga -69327.820 1.197 8724.5798 0.0174 B- -2227.1455 0.5500 68 925573.528 1.285 + 5 37 32 69 Ge -67100.674 1.318 8680.9640 0.0191 B- -3988.4927 31.9822 68 927964.467 1.414 + 3 36 33 69 As -63112.181 31.999 8611.8214 0.4638 B- -6677.4672 32.0215 68 932246.289 34.352 + 1 35 34 69 Se -56434.714 1.490 8503.7082 0.0216 B- -10175.2364 42.0293 68 939414.845 1.599 + -1 34 35 69 Br -p -46259.478 42.003 8344.9026 0.6087 B- -14119# 303# 68 950338.410 45.091 + -3 33 36 69 Kr x -32140# 300# 8129# 4# B- * 68 965496# 322# +0 22 46 24 70 Cr x -5640# 600# 7884# 9# B- 14810# 781# 69 993945# 644# + 20 45 25 70 Mn x -20450# 500# 8084# 7# B- 16440# 583# 69 978046# 537# + 18 44 26 70 Fe x -36890# 300# 8308# 4# B- 9635# 300# 69 960397# 322# + 16 43 27 70 Co x -46524.963 10.992 8434.1980 0.1570 B- 12688.9049 11.1987 69 950053.400 11.800 + 14 42 28 70 Ni x -59213.868 2.144 8604.2917 0.0306 B- 3762.5123 2.4011 69 936431.300 2.301 + 12 41 29 70 Cu x -62976.381 1.082 8646.8655 0.0155 B- 6588.3675 2.2018 69 932392.078 1.161 + 10 40 30 70 Zn -69564.748 1.918 8729.8086 0.0274 B- -654.5979 1.5737 69 925319.175 2.058 + 8 39 31 70 Ga -68910.150 1.201 8709.2808 0.0172 B- 1651.8861 1.4520 69 926021.914 1.289 + 6 38 32 70 Ge -70562.036 0.820 8721.7028 0.0117 B- -6228.0630 1.6200 69 924248.542 0.880 + 4 37 33 70 As x -64333.973 1.397 8621.5541 0.0200 B- -2404.0737 2.1118 69 930934.642 1.500 + 2 36 34 70 Se x -61929.900 1.584 8576.0338 0.0226 B- -10504.2727 14.9878 69 933515.521 1.700 + 0 35 35 70 Br x -51425.627 14.904 8414.7964 0.2129 B- -10325# 201# 69 944792.321 16.000 + -2 34 36 70 Kr x -41100# 200# 8256# 3# B- * 69 955877# 215# +0 21 46 25 71 Mn x -16620# 500# 8030# 7# B- 15310# 640# 70 982158# 537# + 19 45 26 71 Fe x -31930# 400# 8235# 6# B- 12440# 613# 70 965722# 429# + 17 44 27 71 Co x -44369.930 465.030 8398.7344 6.5497 B- 11036.3053 465.0353 70 952366.923 499.230 + 15 43 28 71 Ni x -55406.236 2.237 8543.1564 0.0315 B- 7304.8989 2.6879 70 940518.962 2.401 + 13 42 29 71 Cu x -62711.134 1.490 8635.0233 0.0210 B- 4617.6517 3.0437 70 932676.831 1.600 + 11 41 30 71 Zn -67328.786 2.654 8689.0417 0.0374 B- 2810.3405 2.7748 70 927719.578 2.849 + 9 40 31 71 Ga -70139.127 0.811 8717.6050 0.0114 B- -232.4698 0.0934 70 924702.554 0.870 + 7 39 32 71 Ge -69906.657 0.815 8703.3118 0.0115 B- -2013.4000 4.0825 70 924952.120 0.874 + 5 38 33 71 As - -67893.257 4.163 8663.9350 0.0586 B- -4746.7420 5.0140 70 927113.594 4.469 + 3 37 34 71 Se x -63146.515 2.794 8586.0606 0.0394 B- -6644.0883 6.0820 70 932209.431 3.000 + 1 36 35 71 Br -56502.426 5.402 8481.4629 0.0761 B- -10175.2155 128.8452 70 939342.153 5.799 + -1 35 36 71 Kr -46327.211 128.769 8327.1310 1.8136 B- -14037# 420# 70 950265.695 138.238 + -3 34 37 71 Rb x -32290# 400# 8118# 6# B- * 70 965335# 429# +0 22 47 25 72 Mn x -11170# 600# 7955# 8# B- 18080# 781# 71 988009# 644# + 20 46 26 72 Fe x -29250# 500# 8195# 7# B- 11050# 583# 71 968599# 537# + 18 45 27 72 Co x -40300# 300# 8338# 4# B- 13926# 300# 71 956736# 322# + 16 44 28 72 Ni x -54226.068 2.237 8520.2118 0.0311 B- 5556.9381 2.6374 71 941785.924 2.401 + 14 43 29 72 Cu x -59783.006 1.397 8586.5256 0.0194 B- 8362.4883 2.5578 71 935820.306 1.500 + 12 42 30 72 Zn x -68145.495 2.142 8691.8053 0.0298 B- 442.7892 2.2934 71 926842.806 2.300 + 10 41 31 72 Ga -68588.284 0.818 8687.0893 0.0114 B- 3997.6263 0.8217 71 926367.452 0.878 + 8 40 32 72 Ge -72585.910 0.076 8731.7459 0.0011 B- -4356.1019 4.0825 71 922075.824 0.081 + 6 39 33 72 As - -68229.808 4.083 8660.3786 0.0567 B- -361.6194 4.5276 71 926752.291 4.383 + 4 38 34 72 Se x -67868.189 1.956 8644.4902 0.0272 B- -8806.4384 2.2083 71 927140.506 2.100 + 2 37 35 72 Br x -59061.750 1.025 8511.3126 0.0142 B- -5121.1683 8.0761 71 936594.606 1.100 + 0 36 36 72 Kr x -53940.582 8.011 8429.3193 0.1113 B- -15611# 500# 71 942092.406 8.600 + -2 35 37 72 Rb x -38330# 500# 8202# 7# B- * 71 958851# 537# +0 23 48 25 73 Mn x -6700# 600# 7895# 8# B- 17289# 781# 72 992807# 644# + 21 47 26 73 Fe x -23990# 500# 8121# 7# B- 13980# 583# 72 974246# 537# + 19 46 27 73 Co x -37970# 300# 8302# 4# B- 12139# 300# 72 959238# 322# + 17 45 28 73 Ni x -50108.159 2.423 8457.6529 0.0332 B- 8879.2856 3.1038 72 946206.681 2.601 + 15 44 29 73 Cu -58987.445 1.942 8568.5699 0.0266 B- 6605.9659 2.6910 72 936674.376 2.084 + 13 43 30 73 Zn x -65593.411 1.863 8648.3455 0.0255 B- 4105.9329 2.5064 72 929582.580 2.000 + 11 42 31 73 Ga x -69699.343 1.677 8693.8740 0.0230 B- 1598.1889 1.6777 72 925174.680 1.800 + 9 41 32 73 Ge -71297.532 0.057 8705.0500 0.0008 B- -344.7759 3.8528 72 923458.954 0.061 + 7 40 33 73 As -70952.757 3.853 8689.6099 0.0528 B- -2725.3604 7.3993 72 923829.086 4.136 + 5 39 34 73 Se -68227.396 7.424 8641.5591 0.1017 B- -4581.6095 10.0278 72 926754.881 7.969 + 3 38 35 73 Br -63645.787 6.741 8568.0803 0.0923 B- -7094.0287 9.4187 72 931673.441 7.237 + 1 37 36 73 Kr x -56551.758 6.578 8460.1847 0.0901 B- -10540.1468 41.3212 72 939289.193 7.061 + -1 36 37 73 Rb -p -46011.611 40.794 8305.0821 0.5588 B- -14061# 403# 72 950604.506 43.794 + -3 35 38 73 Sr x -31950# 401# 8102# 5# B- * 72 965700# 430# +0 22 48 26 74 Fe x -20660# 500# 8076# 7# B- 12881# 640# 73 977821# 537# + 20 47 27 74 Co x -33540# 400# 8239# 5# B- 15160# 447# 73 963993# 429# + 18 46 28 74 Ni x -48700# 200# 8433# 3# B- 7306# 200# 73 947718# 215# + 16 45 29 74 Cu x -56006.213 6.148 8521.5633 0.0831 B- 9750.5077 6.6424 73 939874.860 6.600 + 14 44 30 74 Zn x -65756.720 2.515 8642.7547 0.0340 B- 2292.9057 3.9102 73 929407.260 2.700 + 12 43 31 74 Ga x -68049.626 2.994 8663.1676 0.0405 B- 5372.8249 2.9941 73 926945.725 3.214 + 10 42 32 74 Ge -73422.451 0.013 8725.2011 0.0003 B- -2562.3871 1.6931 73 921177.760 0.013 + 8 41 33 74 As -70860.064 1.693 8680.0020 0.0229 B- 1353.1467 1.6931 73 923928.596 1.817 + 6 40 34 74 Se -72213.210 0.015 8687.7155 0.0003 B- -6925.0492 5.8354 73 922475.933 0.015 + 4 39 35 74 Br -65288.161 5.835 8583.5615 0.0789 B- -2956.3173 6.1730 73 929910.279 6.264 + 2 38 36 74 Kr -62331.844 2.013 8533.0390 0.0272 B- -10415.8280 3.4240 73 933084.016 2.161 + 0 37 37 74 Rb -51916.016 3.027 8381.7123 0.0409 B- -11089# 100# 73 944265.867 3.249 + -2 36 38 74 Sr x -40827# 100# 8221# 1# B- * 73 956170# 107# +0 23 49 26 75 Fe x -14700# 600# 7996# 8# B- 15861# 721# 74 984219# 644# + 21 48 27 75 Co x -30560# 400# 8197# 5# B- 13680# 447# 74 967192# 429# + 19 47 28 75 Ni x -44240# 200# 8369# 3# B- 10230# 200# 74 952506# 215# + 17 46 29 75 Cu -54470.219 0.718 8495.0801 0.0096 B- 8088.6967 2.0837 74 941523.817 0.770 + 15 45 30 75 Zn x -62558.916 1.956 8592.4981 0.0261 B- 5901.7231 2.0679 74 932840.244 2.100 + 13 44 31 75 Ga x -68460.639 0.671 8660.7565 0.0089 B- 3396.3337 0.6727 74 926504.484 0.720 + 11 43 32 75 Ge -n -71856.973 0.052 8695.6096 0.0007 B- 1177.2301 0.8851 74 922858.370 0.055 + 9 42 33 75 As -73034.203 0.884 8700.8748 0.0118 B- -864.7139 0.8816 74 921594.562 0.948 + 7 41 34 75 Se -72169.489 0.073 8678.9139 0.0010 B- -3062.4694 4.2855 74 922522.870 0.078 + 5 40 35 75 Br x -69107.020 4.285 8627.6497 0.0571 B- -4783.3880 9.1671 74 925810.566 4.600 + 3 39 36 75 Kr x -64323.632 8.104 8553.4399 0.1081 B- -7104.9299 8.1895 74 930945.744 8.700 + 1 38 37 75 Rb x -57218.702 1.180 8448.2762 0.0157 B- -10600.0000 220.0000 74 938573.200 1.266 + -1 37 38 75 Sr - -46618.702 220.003 8296.5116 2.9334 B- -14799# 372# 74 949952.767 236.183 + -3 36 39 75 Y x -31820# 300# 8089# 4# B- * 74 965840# 322# +0 24 50 26 76 Fe x -10590# 600# 7943# 8# B- 15070# 781# 75 988631# 644# + 22 49 27 76 Co x -25660# 500# 8131# 7# B- 16530# 583# 75 972453# 537# + 20 48 28 76 Ni x -42190# 300# 8338# 4# B- 8791# 300# 75 954707# 322# + 18 47 29 76 Cu x -50981.627 0.913 8443.6018 0.0120 B- 11321.3964 1.7183 75 945268.974 0.980 + 16 46 30 76 Zn -62303.024 1.456 8582.2735 0.0192 B- 3993.6241 2.4384 75 933114.956 1.562 + 14 45 31 76 Ga x -66296.648 1.956 8624.5272 0.0257 B- 6916.2501 1.9562 75 928827.624 2.100 + 12 44 32 76 Ge -73212.898 0.018 8705.2364 0.0003 B- -921.5145 0.8864 75 921402.725 0.019 + 10 43 33 76 As -n -72291.384 0.886 8682.8172 0.0117 B- 2960.5756 0.8864 75 922392.011 0.951 + 8 42 34 76 Se -75251.959 0.016 8711.4781 0.0003 B- -4962.8810 9.3218 75 919213.702 0.017 + 6 41 35 76 Br - -70289.078 9.322 8635.8830 0.1227 B- -1275.3724 10.1490 75 924541.574 10.007 + 4 40 36 76 Kr -69013.706 4.013 8608.8077 0.0528 B- -8534.6172 4.1214 75 925910.743 4.308 + 2 39 37 76 Rb x -60479.089 0.938 8486.2161 0.0123 B- -6231.4432 34.4780 75 935073.031 1.006 + 0 38 38 76 Sr x -54247.645 34.465 8393.9294 0.4535 B- -15998# 302# 75 941762.760 37.000 + -2 37 39 76 Y x -38250# 300# 8173# 4# B- * 75 958937# 322# +0 23 50 27 77 Co x -21910# 600# 8082# 8# B- 15440# 721# 76 976479# 644# + 21 49 28 77 Ni x -37350# 400# 8272# 5# B- 11513# 400# 76 959903# 429# + 19 48 29 77 Cu x -48862.828 1.211 8411.2501 0.0157 B- 9926.3750 2.3148 76 947543.599 1.300 + 17 47 30 77 Zn -58789.203 1.973 8530.0037 0.0256 B- 7203.1495 3.1237 76 936887.197 2.117 + 15 46 31 77 Ga x -65992.352 2.422 8613.3907 0.0315 B- 5220.5176 2.4225 76 929154.299 2.600 + 13 45 32 77 Ge -n -71212.870 0.053 8671.0293 0.0007 B- 2703.4642 1.6926 76 923549.843 0.056 + 11 44 33 77 As -73916.334 1.692 8695.9789 0.0220 B- 683.1627 1.6920 76 920647.555 1.816 + 9 43 34 77 Se -74599.497 0.062 8694.6908 0.0008 B- -1364.6792 2.8099 76 919914.150 0.067 + 7 42 35 77 Br - -73234.818 2.811 8666.8073 0.0365 B- -3065.3663 3.4244 76 921379.193 3.017 + 5 41 36 77 Kr x -70169.451 1.956 8616.8370 0.0254 B- -5338.9516 2.3510 76 924669.999 2.100 + 3 40 37 77 Rb x -64830.500 1.304 8537.3396 0.0169 B- -7027.0566 8.0244 76 930401.599 1.400 + 1 39 38 77 Sr x -57803.443 7.918 8435.9188 0.1028 B- -11365# 203# 76 937945.454 8.500 + -1 38 39 77 Y -p -46439# 203# 8278# 3# B- -14839# 448# 76 950146# 218# + -3 37 40 77 Zr x -31600# 400# 8075# 5# B- * 76 966076# 429# +0 24 51 27 78 Co x -15320# 700# 7997# 9# B- 19560# 806# 77 983553# 751# + 22 50 28 78 Ni x -34880# 400# 8238# 5# B- 9910# 400# 77 962555# 429# + 20 49 29 78 Cu -44789.474 13.332 8354.6695 0.1709 B- 12693.7680 13.4727 77 951916.524 14.312 + 18 48 30 78 Zn -57483.242 1.944 8507.3800 0.0249 B- 6220.8433 2.2088 77 938289.204 2.086 + 16 47 31 78 Ga -63704.085 1.051 8577.1043 0.0135 B- 8157.9729 3.6884 77 931610.854 1.127 + 14 46 32 78 Ge -nn -71862.058 3.536 8671.6636 0.0453 B- 954.9114 10.3987 77 922852.911 3.795 + 12 45 33 78 As +pn -72816.970 9.779 8673.8760 0.1254 B- 4208.9819 9.7801 77 921827.771 10.498 + 10 44 34 78 Se -77025.952 0.179 8717.8072 0.0023 B- -3573.7836 3.5750 77 917309.244 0.191 + 8 43 35 78 Br - -73452.168 3.580 8661.9594 0.0459 B- 726.1153 3.5845 77 921145.858 3.842 + 6 42 36 78 Kr -74178.283 0.307 8661.2385 0.0039 B- -7242.8560 3.2520 77 920366.341 0.329 + 4 41 37 78 Rb x -66935.427 3.237 8558.3512 0.0415 B- -3761.4779 8.1248 77 928141.866 3.475 + 2 40 38 78 Sr x -63173.949 7.452 8500.0971 0.0955 B- -11001# 298# 77 932179.979 8.000 + 0 39 39 78 Y x -52173# 298# 8349# 4# B- -11323# 499# 77 943990# 320# + -2 38 40 78 Zr x -40850# 400# 8194# 5# B- * 77 956146# 429# +0 23 51 28 79 Ni x -28160# 500# 8150# 6# B- 14248# 511# 78 969769# 537# + 21 50 29 79 Cu x -42408.039 104.979 8320.9380 1.3289 B- 11024.2629 105.0030 78 954473.100 112.700 + 19 49 30 79 Zn -53432.302 2.225 8450.5825 0.0282 B- 9116.0536 2.5295 78 942638.067 2.388 + 17 48 31 79 Ga -62548.355 1.208 8556.0725 0.0153 B- 6978.8242 37.1467 78 932851.582 1.296 + 15 47 32 79 Ge -69527.180 37.161 8634.5089 0.4704 B- 4108.9014 37.4361 78 925359.506 39.893 + 13 46 33 79 As -73636.081 5.325 8676.6172 0.0674 B- 2281.3849 5.3284 78 920948.419 5.716 + 11 45 34 79 Se -n -75917.466 0.223 8695.5923 0.0028 B- 150.6016 1.0186 78 918499.252 0.238 + 9 44 35 79 Br -76068.067 1.001 8687.5956 0.0127 B- -1625.7778 3.3333 78 918337.574 1.074 + 7 43 36 79 Kr - -74442.290 3.480 8657.1130 0.0441 B- -3639.5114 3.9423 78 920082.919 3.736 + 5 42 37 79 Rb -70802.778 1.943 8601.1401 0.0246 B- -5323.1140 7.5630 78 923990.095 2.085 + 3 41 38 79 Sr -65479.664 7.421 8523.8558 0.0939 B- -7676.7291 80.4515 78 929704.692 7.967 + 1 40 39 79 Y x -57802.935 80.108 8416.7788 1.0140 B- -11033# 310# 78 937946.000 86.000 + -1 39 40 79 Zr x -46770# 300# 8267# 4# B- -15120# 583# 78 949790# 322# + -3 38 41 79 Nb x -31650# 500# 8066# 6# B- * 78 966022# 537# +0 24 52 28 80 Ni x -23240# 600# 8088# 7# B- 13440# 671# 79 975051# 644# + 22 51 29 80 Cu x -36679# 300# 8246# 4# B- 14969# 300# 79 960623# 322# + 20 50 30 80 Zn -51648.619 2.585 8423.5457 0.0323 B- 7575.0553 3.8774 79 944552.929 2.774 + 18 49 31 80 Ga x -59223.675 2.891 8508.4545 0.0361 B- 10311.6397 3.5409 79 936420.773 3.103 + 16 48 32 80 Ge x -69535.314 2.054 8627.5707 0.0257 B- 2679.2869 3.9156 79 925350.773 2.205 + 14 47 33 80 As x -72214.601 3.333 8651.2824 0.0417 B- 5544.8861 3.4412 79 922474.440 3.578 + 12 46 34 80 Se -77759.487 0.947 8710.8142 0.0118 B- -1870.4623 0.3095 79 916521.761 1.016 + 10 45 35 80 Br -75889.025 0.993 8677.6541 0.0124 B- 2004.4299 1.1413 79 918529.784 1.065 + 8 44 36 80 Kr -77893.455 0.695 8692.9301 0.0087 B- -5717.9785 1.9883 79 916377.940 0.745 + 6 43 37 80 Rb x -72175.476 1.863 8611.6760 0.0233 B- -1864.0090 3.9331 79 922516.442 2.000 + 4 42 38 80 Sr x -70311.467 3.464 8578.5966 0.0433 B- -9163.3050 7.1389 79 924517.538 3.718 + 2 41 39 80 Y x -61148.162 6.242 8454.2759 0.0780 B- -6388# 300# 79 934354.750 6.701 + 0 40 40 80 Zr x -54760# 300# 8365# 4# B- -16339# 500# 79 941213# 322# + -2 39 41 80 Nb x -38420# 400# 8151# 5# B- * 79 958754# 429# +0 25 53 28 81 Ni x -16090# 700# 8000# 9# B- 15820# 761# 80 982727# 751# + 23 52 29 81 Cu x -31910# 300# 8185# 4# B- 14289# 300# 80 965743# 322# + 21 51 30 81 Zn x -46199.669 5.030 8351.9262 0.0621 B- 11428.2924 5.9960 80 950402.617 5.400 + 19 50 31 81 Ga x -57627.962 3.264 8483.3576 0.0403 B- 8663.7335 3.8508 80 938133.841 3.503 + 17 49 32 81 Ge x -66291.695 2.055 8580.6587 0.0254 B- 6241.6189 3.3436 80 928832.941 2.205 + 15 48 33 81 As -72533.314 2.644 8648.0571 0.0326 B- 3855.7050 2.8072 80 922132.288 2.838 + 13 47 34 81 Se -76389.019 0.977 8685.9998 0.0121 B- 1588.0317 1.3787 80 917993.019 1.049 + 11 46 35 81 Br -77977.051 0.978 8695.9465 0.0121 B- -280.8517 0.4713 80 916288.197 1.049 + 9 45 36 81 Kr -77696.199 1.074 8682.8206 0.0133 B- -2239.4954 5.0188 80 916589.703 1.152 + 7 44 37 81 Rb -75456.704 4.904 8645.5139 0.0605 B- -3928.5695 5.8170 80 918993.900 5.265 + 5 43 38 81 Sr x -71528.134 3.128 8587.3545 0.0386 B- -5815.2156 6.2451 80 923211.393 3.358 + 3 42 39 81 Y x -65712.919 5.405 8505.9031 0.0667 B- -8188.5003 92.3762 80 929454.283 5.802 + 1 41 40 81 Zr x -57524.418 92.218 8395.1519 1.1385 B- -11164# 410# 80 938245.000 99.000 + -1 40 41 81 Nb x -46360# 400# 8248# 5# B- -14900# 640# 80 950230# 429# + -3 39 42 81 Mo x -31460# 500# 8054# 6# B- * 80 966226# 537# +0 26 54 28 82 Ni x -10720# 800# 7935# 10# B- 15010# 894# 81 988492# 859# + 24 53 29 82 Cu x -25730# 400# 8108# 5# B- 16584# 400# 81 972378# 429# + 22 52 30 82 Zn x -42313.960 3.074 8301.1175 0.0375 B- 10616.7652 3.9162 81 954574.097 3.300 + 20 51 31 82 Ga x -52930.725 2.426 8421.0494 0.0296 B- 12484.3497 3.2960 81 943176.531 2.604 + 18 50 32 82 Ge x -65415.075 2.240 8563.7567 0.0273 B- 4690.3523 4.3452 81 929774.031 2.405 + 16 49 33 82 As x -70105.427 3.729 8611.4153 0.0455 B- 7488.4677 3.7579 81 924738.731 4.003 + 14 48 34 82 Se -77593.895 0.466 8693.1973 0.0057 B- -95.2184 1.0767 81 916699.531 0.500 + 12 47 35 82 Br -77498.677 0.971 8682.4953 0.0118 B- 3093.1185 0.9714 81 916801.752 1.042 + 10 46 36 82 Kr -80591.79509 0.00551 8710.6754 0.0003 B- -4403.9824 3.0088 81 913481.15368 0.00591 + 8 45 37 82 Rb IT -76187.813 3.009 8647.4275 0.0367 B- -177.7503 6.7048 81 918209.023 3.230 + 6 44 38 82 Sr -76010.062 5.992 8635.7190 0.0731 B- -7945.9650 8.1324 81 918399.845 6.432 + 4 43 39 82 Y x -68064.097 5.499 8529.2762 0.0671 B- -4450.0341 5.7221 81 926930.189 5.902 + 2 42 40 82 Zr x -63614.063 1.584 8465.4666 0.0193 B- -11804# 300# 81 931707.497 1.700 + 0 41 41 82 Nb x -51810# 300# 8312# 4# B- -11440# 500# 81 944380# 322# + -2 40 42 82 Mo x -40370# 400# 8163# 5# B- * 81 956661# 429# +0 25 54 29 83 Cu x -20390# 500# 8044# 6# B- 15900# 583# 82 978110# 537# + 23 53 30 83 Zn x -36290# 300# 8226# 4# B- 12967# 300# 82 961041# 322# + 21 52 31 83 Ga x -49257.129 2.612 8372.5756 0.0315 B- 11719.3136 3.5592 82 947120.300 2.804 + 19 51 32 83 Ge x -60976.442 2.427 8504.3462 0.0292 B- 8692.8893 3.6979 82 934539.100 2.604 + 17 50 33 83 As x -69669.331 2.799 8599.6540 0.0337 B- 5671.2117 4.1290 82 925206.900 3.004 + 15 49 34 83 Se -n -75340.543 3.036 8658.5560 0.0366 B- 3673.1780 4.8392 82 919118.604 3.259 + 13 48 35 83 Br -79013.721 3.795 8693.3852 0.0457 B- 976.9222 3.7947 82 915175.285 4.073 + 11 47 36 83 Kr -79990.643 0.009 8695.7295 0.0003 B- -920.0039 2.3288 82 914126.516 0.009 + 9 46 37 83 Rb -79070.639 2.329 8675.2193 0.0281 B- -2273.0239 6.4245 82 915114.181 2.500 + 7 45 38 83 Sr -76797.616 6.834 8638.4076 0.0823 B- -4591.9435 19.8444 82 917554.372 7.336 + 5 44 39 83 Y x -72205.672 18.631 8573.6571 0.2245 B- -6294.0125 19.7074 82 922484.026 20.000 + 3 43 40 83 Zr x -65911.659 6.430 8488.3997 0.0775 B- -8298.7493 162.2075 82 929240.926 6.902 + 1 42 41 83 Nb x -57612.910 162.080 8378.9889 1.9528 B- -11273# 432# 82 938150.000 174.000 + -1 41 42 83 Mo x -46340# 401# 8234# 5# B- -15020# 641# 82 950252# 430# + -3 40 43 83 Tc x -31320# 500# 8043# 6# B- * 82 966377# 537# +0 26 55 29 84 Cu x -13720# 500# 7965# 6# B- 18110# 640# 83 985271# 537# + 24 54 30 84 Zn x -31830# 400# 8171# 5# B- 12264# 401# 83 965829# 429# + 22 53 31 84 Ga x -44094.136 29.808 8307.5250 0.3549 B- 14054.2989 29.9760 83 952663.000 32.000 + 20 52 32 84 Ge x -58148.435 3.171 8465.5244 0.0377 B- 7705.1329 4.4789 83 937575.090 3.403 + 18 51 33 84 As x -65853.568 3.171 8547.9385 0.0377 B- 10094.1624 3.7219 83 929303.290 3.403 + 16 50 34 84 Se -75947.731 1.961 8658.7935 0.0233 B- 1835.3638 25.7652 83 918466.761 2.105 + 14 49 35 84 Br -77783.094 25.730 8671.3294 0.3063 B- 4656.2510 25.7300 83 916496.417 27.622 + 12 48 36 84 Kr -82439.34527 0.00382 8717.4473 0.0003 B- -2680.3708 2.1940 83 911497.72708 0.00410 + 10 47 37 84 Rb -79758.975 2.194 8676.2244 0.0261 B- 890.6058 2.3356 83 914375.223 2.355 + 8 46 38 84 Sr -80649.580 1.243 8677.5132 0.0148 B- -6755.1411 4.4114 83 913419.118 1.334 + 6 45 39 84 Y -73894.439 4.299 8587.7812 0.0512 B- -2472.7471 6.9767 83 920671.060 4.615 + 4 44 40 84 Zr x -71421.692 5.499 8549.0301 0.0655 B- -10227.8497 5.5133 83 923325.663 5.903 + 2 43 41 84 Nb x -61193.842 0.401 8417.9563 0.0048 B- -7024# 298# 83 934305.711 0.430 + 0 42 42 84 Mo x -54170# 298# 8325# 4# B- -16470# 499# 83 941846# 320# + -2 41 43 84 Tc x -37700# 400# 8120# 5# B- * 83 959527# 429# +0 25 55 30 85 Zn x -25100# 500# 8090# 6# B- 14644# 502# 84 973054# 537# + 23 54 31 85 Ga x -39744.059 37.260 8253.5687 0.4384 B- 13379.3679 37.4459 84 957333.000 40.000 + 21 53 32 85 Ge x -53123.427 3.729 8401.7689 0.0439 B- 10065.7253 4.8303 84 942969.658 4.003 + 19 52 33 85 As x -63189.152 3.078 8510.9851 0.0362 B- 9224.4929 4.0313 84 932163.658 3.304 + 17 51 34 85 Se +3p -72413.645 2.613 8610.3045 0.0307 B- 6161.8335 4.0313 84 922260.758 2.804 + 15 50 35 85 Br +n2p -78575.478 3.078 8673.5926 0.0362 B- 2904.8622 3.6705 84 915645.758 3.304 + 13 49 36 85 Kr + -81480.341 2.000 8698.5633 0.0235 B- 687.0000 2.0000 84 912527.260 2.147 + 11 48 37 85 Rb -82167.34065 0.00500 8697.4416 0.0003 B- -1064.0510 2.8132 84 911789.73604 0.00537 + 9 47 38 85 Sr -81103.290 2.813 8675.7193 0.0331 B- -3261.1584 19.1729 84 912932.041 3.020 + 7 46 39 85 Y x -77842.131 18.965 8628.1486 0.2231 B- -4666.9352 20.0257 84 916433.039 20.360 + 5 45 40 85 Zr x -73175.196 6.430 8564.0394 0.0756 B- -6895.5120 7.6250 84 921443.199 6.902 + 3 44 41 85 Nb x -66279.684 4.099 8473.7117 0.0482 B- -8769.9238 16.3572 84 928845.836 4.400 + 1 43 42 85 Mo x -57509.760 15.835 8361.3320 0.1863 B- -11660# 400# 84 938260.736 17.000 + -1 42 43 85 Tc x -45850# 400# 8215# 5# B- -15220# 640# 84 950778# 429# + -3 41 44 85 Ru x -30630# 500# 8027# 6# B- * 84 967117# 537# +0 26 56 30 86 Zn x -20062# 500# 8032# 6# B- 13699# 640# 85 978463# 537# + 24 55 31 86 Ga x -33760# 400# 8182# 5# B- 15640# 593# 85 963757# 429# + 22 54 32 86 Ge x -49399.927 437.802 8354.6300 5.0907 B- 9562.2229 437.8158 85 946967.000 470.000 + 20 53 33 86 As x -58962.150 3.450 8456.7215 0.0401 B- 11541.0256 4.2666 85 936701.532 3.703 + 18 52 34 86 Se x -70503.175 2.520 8581.8224 0.0293 B- 5129.0860 3.9717 85 924311.732 2.705 + 16 51 35 86 Br +pp -75632.261 3.078 8632.3659 0.0358 B- 7633.4147 3.0779 85 918805.432 3.304 + 14 50 36 86 Kr -83265.67593 0.00372 8712.0295 0.0003 B- -518.6734 0.2000 85 910610.62468 0.00399 + 12 49 37 86 Rb -n -82747.003 0.200 8696.9014 0.0023 B- 1776.0972 0.2001 85 911167.443 0.214 + 10 48 38 86 Sr -84523.09977 0.00524 8708.4566 0.0003 B- -5240.0000 14.1421 85 909260.72473 0.00563 + 8 47 39 86 Y - -79283.100 14.142 8638.4293 0.1644 B- -1314.0763 14.5847 85 914886.095 15.182 + 6 46 40 86 Zr -77969.023 3.566 8614.0523 0.0415 B- -8834.9627 6.5521 85 916296.814 3.827 + 4 45 41 86 Nb x -69134.061 5.499 8502.2231 0.0639 B- -5023.1337 6.2316 85 925781.536 5.903 + 2 44 42 86 Mo x -64110.927 2.932 8434.7175 0.0341 B- -12541# 300# 85 931174.092 3.147 + 0 43 43 86 Tc x -51570# 300# 8280# 3# B- -11800# 500# 85 944637# 322# + -2 42 44 86 Ru x -39770# 400# 8133# 5# B- * 85 957305# 429# +0 25 56 31 87 Ga x -28870# 500# 8124# 6# B- 14720# 583# 86 969007# 537# + 23 55 32 87 Ge x -43590# 300# 8285# 3# B- 12028# 300# 86 953204# 322# + 21 54 33 87 As x -55617.914 2.985 8413.8521 0.0343 B- 10808.2192 3.7260 86 940291.716 3.204 + 19 53 34 87 Se x -66426.133 2.241 8529.0920 0.0258 B- 7465.5526 3.8766 86 928688.616 2.405 + 17 52 35 87 Br 2p-n -73891.685 3.171 8605.9105 0.0364 B- 6817.8455 3.1805 86 920674.016 3.404 + 15 51 36 87 Kr -n -80709.531 0.246 8675.2840 0.0028 B- 3888.2706 0.2463 86 913354.759 0.264 + 13 50 37 87 Rb -84597.802 0.006 8710.9843 0.0003 B- 282.2749 0.0063 86 909180.529 0.006 + 11 49 38 87 Sr -84880.07643 0.00513 8705.2363 0.0003 B- -1861.6894 1.1278 86 908877.49454 0.00550 + 9 48 39 87 Y - -83018.387 1.128 8674.8451 0.0130 B- -3671.2405 4.2962 86 910876.100 1.210 + 7 47 40 87 Zr -79347.147 4.146 8623.6545 0.0477 B- -5472.6536 7.9633 86 914817.338 4.450 + 5 46 41 87 Nb x -73874.493 6.802 8551.7579 0.0782 B- -6989.6757 7.3781 86 920692.473 7.302 + 3 45 42 87 Mo -66884.817 2.857 8462.4243 0.0328 B- -9194.7656 5.0729 86 928196.198 3.067 + 1 44 43 87 Tc x -57690.052 4.192 8347.7449 0.0482 B- -11960# 400# 86 938067.185 4.500 + -1 43 44 87 Ru x -45730# 400# 8201# 5# B- * 86 950907# 429# +0 26 57 31 88 Ga x -22390# 500# 8050# 6# B- 17129# 640# 87 975963# 537# + 24 56 32 88 Ge x -39520# 400# 8236# 5# B- 10930# 447# 87 957574# 429# + 22 55 33 88 As x -50450# 200# 8351# 2# B- 13434# 200# 87 945840# 215# + 20 54 34 88 Se x -63884.203 3.357 8495.0045 0.0382 B- 6831.7640 4.6125 87 931417.490 3.604 + 18 53 35 88 Br ++ -70715.967 3.171 8563.7479 0.0360 B- 8975.3282 4.1059 87 924083.290 3.404 + 16 52 36 88 Kr x -79691.295 2.608 8656.8499 0.0296 B- 2917.7090 2.6130 87 914447.879 2.800 + 14 51 37 88 Rb -82609.004 0.159 8681.1154 0.0018 B- 5312.6243 0.1590 87 911315.590 0.170 + 12 50 38 88 Sr -87921.62876 0.00561 8732.5958 0.0003 B- -3622.6000 1.5000 87 905612.253 0.006 + 10 49 39 88 Y - -84299.029 1.500 8682.5396 0.0170 B- -670.1549 5.6076 87 909501.274 1.610 + 8 48 40 88 Zr -83628.874 5.403 8666.0339 0.0614 B- -7457.3187 57.8921 87 910220.715 5.800 + 6 47 41 88 Nb -76171.555 57.808 8572.4013 0.6569 B- -3485.0021 57.9345 87 918226.476 62.059 + 4 46 42 88 Mo x -72686.553 3.819 8523.9087 0.0434 B- -11016.2515 5.6021 87 921967.779 4.100 + 2 45 43 88 Tc x -61670.301 4.099 8389.8338 0.0466 B- -7331# 300# 87 933794.211 4.400 + 0 44 44 88 Ru x -54340# 300# 8298# 3# B- -17479# 500# 87 941664# 322# + -2 43 45 88 Rh x -36860# 400# 8090# 5# B- * 87 960429# 429# +0 25 57 32 89 Ge x -33040# 400# 8161# 4# B- 13490# 500# 88 964530# 429# + 23 56 33 89 As x -46530# 300# 8304# 3# B- 12462# 300# 88 950048# 322# + 21 55 34 89 Se x -58992.398 3.729 8435.2799 0.0419 B- 9281.8730 4.9510 88 936669.058 4.003 + 19 54 35 89 Br x -68274.271 3.264 8530.7802 0.0367 B- 8261.5231 3.9045 88 926704.558 3.504 + 17 53 36 89 Kr x -76535.795 2.142 8614.8158 0.0241 B- 5176.6042 5.8342 88 917835.449 2.300 + 15 52 37 89 Rb -81712.399 5.427 8664.1895 0.0610 B- 4496.6278 5.4265 88 912278.136 5.825 + 13 51 38 89 Sr -86209.026 0.092 8705.9230 0.0011 B- 1502.1757 0.3510 88 907450.808 0.098 + 11 50 39 89 Y -87711.202 0.339 8714.0110 0.0038 B- -2833.2285 2.7652 88 905838.156 0.363 + 9 49 40 89 Zr -84877.974 2.780 8673.3865 0.0312 B- -4252.2191 23.7199 88 908879.751 2.983 + 7 48 41 89 Nb -80625.755 23.630 8616.8184 0.2655 B- -5610.8105 23.9513 88 913444.696 25.367 + 5 47 42 89 Mo x -75014.944 3.912 8544.9851 0.0440 B- -7620.0875 5.4673 88 919468.149 4.200 + 3 46 43 89 Tc x -67394.857 3.819 8450.5758 0.0429 B- -9025.4327 24.5181 88 927648.649 4.100 + 1 45 44 89 Ru x -58369.424 24.219 8340.3760 0.2721 B- -12719# 361# 88 937337.849 26.000 + -1 44 45 89 Rh -p -45651# 361# 8189# 4# B- * 88 950992# 387# +0 26 58 32 90 Ge x -28470# 500# 8109# 6# B- 12520# 640# 89 969436# 537# + 24 57 33 90 As x -40990# 400# 8240# 4# B- 14810# 518# 89 955995# 429# + 22 56 34 90 Se x -55800.223 329.749 8395.7672 3.6639 B- 8200.0834 329.7660 89 940096.000 354.000 + 20 55 35 90 Br x -64000.306 3.357 8478.1865 0.0373 B- 10958.9533 3.8396 89 931292.848 3.604 + 18 54 36 90 Kr x -74959.259 1.863 8591.2599 0.0207 B- 4406.3133 6.7158 89 919527.929 2.000 + 16 53 37 90 Rb -79365.573 6.452 8631.5262 0.0717 B- 6585.3721 6.4806 89 914797.557 6.926 + 14 52 38 90 Sr -85950.945 1.449 8696.0043 0.0161 B- 545.9674 1.4060 89 907727.870 1.555 + 12 51 39 90 Y -86496.912 0.354 8693.3778 0.0039 B- 2275.6350 0.3726 89 907141.749 0.379 + 10 50 40 90 Zr -88772.547 0.118 8709.9699 0.0013 B- -6111.0165 3.3163 89 904698.755 0.126 + 8 49 41 90 Nb -82661.531 3.317 8633.3770 0.0369 B- -2489.0165 3.3163 89 911259.201 3.561 + 6 48 42 90 Mo -80172.514 3.463 8597.0285 0.0385 B- -9447.8181 3.6110 89 913931.270 3.717 + 4 47 43 90 Tc x -70724.696 1.025 8483.3600 0.0114 B- -5840.8951 3.8685 89 924073.919 1.100 + 2 46 44 90 Ru -64883.801 3.730 8409.7684 0.0414 B- -13250# 200# 89 930344.378 4.004 + 0 45 45 90 Rh - -51634# 200# 8254# 2# B- -11924# 447# 89 944569# 215# + -2 44 46 90 Pd x -39710# 400# 8113# 4# B- * 89 957370# 429# +0 25 58 33 91 As x -36500# 400# 8189# 4# B- 14080# 589# 90 960816# 429# + 23 57 34 91 Se x -50580.130 433.145 8334.8382 4.7598 B- 10527.1716 433.1593 90 945700.000 465.000 + 21 56 35 91 Br -n2p -61107.301 3.543 8441.9242 0.0389 B- 9866.6724 4.1898 90 934398.617 3.804 + 19 55 36 91 Kr x -70973.974 2.236 8541.7519 0.0246 B- 6771.0748 8.1153 90 923806.309 2.400 + 17 54 37 91 Rb -77745.049 7.801 8607.5621 0.0857 B- 5906.9010 8.8732 90 916537.261 8.375 + 15 53 38 91 Sr -83651.950 5.453 8663.8759 0.0599 B- 2699.3714 5.2468 90 910195.942 5.853 + 13 52 39 91 Y -86351.321 1.843 8684.9421 0.0203 B- 1544.2710 1.8403 90 907298.048 1.978 + 11 51 40 91 Zr -87895.592 0.095 8693.3149 0.0011 B- -1257.5644 2.9243 90 905640.205 0.101 + 9 50 41 91 Nb -86638.028 2.926 8670.8983 0.0322 B- -4429.1934 6.7439 90 906990.256 3.140 + 7 49 42 91 Mo -82208.834 6.238 8613.6286 0.0686 B- -6222.1768 6.6706 90 911745.190 6.696 + 5 48 43 91 Tc -75986.657 2.363 8536.6558 0.0260 B- -7746.8246 3.2422 90 918424.972 2.536 + 3 47 44 91 Ru -68239.833 2.221 8442.9287 0.0244 B- -9670# 298# 90 926741.530 2.384 + 1 46 45 91 Rh x -58570# 298# 8328# 3# B- -12400# 300# 90 937123# 320# + -1 45 46 91 Pd - -46170# 423# 8183# 5# B- * 90 950435# 454# +0 26 59 33 92 As x -30380# 500# 8121# 5# B- 16344# 640# 91 967386# 537# + 24 58 34 92 Se x -46724# 400# 8290# 4# B- 9509# 400# 91 949840# 429# + 22 57 35 92 Br x -56232.812 6.709 8384.9123 0.0729 B- 12536.5161 7.2322 91 939631.595 7.202 + 20 56 36 92 Kr x -68769.329 2.701 8512.6750 0.0294 B- 6003.1210 6.6924 91 926173.092 2.900 + 18 55 37 92 Rb -74772.450 6.123 8569.4225 0.0666 B- 8094.9212 6.4187 91 919728.477 6.573 + 16 54 38 92 Sr -82867.371 3.423 8648.9070 0.0372 B- 1949.1237 9.3841 91 911038.222 3.675 + 14 53 39 92 Y -84816.494 9.127 8661.5894 0.0992 B- 3642.5294 9.1271 91 908945.752 9.798 + 12 52 40 92 Zr -88459.024 0.094 8692.6783 0.0011 B- -2005.7335 1.7823 91 905035.336 0.101 + 10 51 41 92 Nb -86453.290 1.784 8662.3731 0.0194 B- 355.2968 1.7911 91 907188.580 1.915 + 8 50 42 92 Mo -86808.587 0.157 8657.7312 0.0017 B- -7882.8841 3.1063 91 906807.153 0.168 + 6 49 43 92 Tc -78925.703 3.102 8563.5440 0.0337 B- -4624.4922 4.1246 91 915269.777 3.330 + 4 48 44 92 Ru -74301.211 2.718 8504.7740 0.0295 B- -11302.1155 5.1531 91 920234.373 2.917 + 2 47 45 92 Rh x -62999.095 4.378 8373.4211 0.0476 B- -8220.0000 345.0000 91 932367.692 4.700 + 0 46 46 92 Pd - -54779.095 345.028 8275.5695 3.7503 B- -17249# 528# 91 941192.225 370.402 + -2 45 47 92 Ag x -37530# 400# 8080# 4# B- * 91 959710# 429# +0 25 59 34 93 Se x -40860# 400# 8225# 4# B- 12030# 588# 92 956135# 429# + 23 58 35 93 Br x -52890.235 430.816 8345.5986 4.6324 B- 11245.7673 430.8234 92 943220.000 462.500 + 21 57 36 93 Kr x -64136.002 2.515 8458.1085 0.0270 B- 8483.8977 8.2243 92 931147.172 2.700 + 19 56 37 93 Rb -72619.900 7.830 8540.9209 0.0842 B- 7465.9434 8.8761 92 922039.334 8.406 + 17 55 38 93 Sr -80085.844 7.554 8612.7875 0.0812 B- 4141.3118 11.6972 92 914024.314 8.109 + 15 54 39 93 Y -84227.155 10.488 8648.9054 0.1128 B- 2894.8723 10.4830 92 909578.434 11.259 + 13 53 40 93 Zr -87122.028 0.456 8671.6207 0.0049 B- 90.8123 1.4838 92 906470.661 0.489 + 11 52 41 93 Nb -87212.840 1.490 8664.1849 0.0160 B- -405.7609 1.5012 92 906373.170 1.599 + 9 51 42 93 Mo -n -86807.079 0.181 8651.4095 0.0020 B- -3200.9629 1.0040 92 906808.772 0.193 + 7 50 43 93 Tc -p -83606.116 1.012 8608.5782 0.0109 B- -6389.3929 2.2995 92 910245.147 1.086 + 5 49 44 93 Ru -77216.723 2.065 8531.4627 0.0222 B- -8204.9136 3.3425 92 917104.442 2.216 + 3 48 45 93 Rh -69011.810 2.629 8434.8255 0.0283 B- -10030.0000 370.0000 92 925912.778 2.821 + 1 47 46 93 Pd - -58981.810 370.009 8318.5637 3.9786 B- -12582# 545# 92 936680.426 397.221 + -1 46 47 93 Ag x -46400# 401# 8175# 4# B- * 92 950188# 430# +0 26 60 34 94 Se x -36803# 500# 8180# 5# B- 10846# 539# 93 960490# 537# + 24 59 35 94 Br x -47650# 200# 8287# 2# B- 13698# 201# 93 948846# 215# + 22 58 36 94 Kr x -61347.780 12.109 8424.3318 0.1288 B- 7215.0114 12.2782 93 934140.452 13.000 + 20 57 37 94 Rb -68562.791 2.029 8492.7644 0.0216 B- 10282.9297 2.6230 93 926394.819 2.177 + 18 56 38 94 Sr -78845.721 1.663 8593.8344 0.0177 B- 3505.7517 6.4220 93 915355.641 1.785 + 16 55 39 94 Y -82351.473 6.380 8622.8068 0.0679 B- 4917.8589 6.3799 93 911592.062 6.849 + 14 54 40 94 Zr -87269.332 0.164 8666.8016 0.0018 B- -900.2684 1.5000 93 906312.523 0.175 + 12 53 41 94 Nb -86369.063 1.491 8648.9014 0.0159 B- 2045.0163 1.4937 93 907279.001 1.600 + 10 52 42 94 Mo -88414.079 0.141 8662.3341 0.0015 B- -4255.7476 4.0687 93 905083.586 0.151 + 8 51 43 94 Tc - -84158.332 4.071 8608.7373 0.0433 B- -1574.7296 5.1433 93 909652.319 4.370 + 6 50 44 94 Ru -82583.602 3.143 8583.6620 0.0334 B- -9675.9789 4.6150 93 911342.860 3.374 + 4 49 45 94 Rh -72907.623 3.379 8472.4033 0.0359 B- -6805.3428 5.4588 93 921730.450 3.627 + 2 48 46 94 Pd x -66102.281 4.287 8391.6832 0.0456 B- -13700# 400# 93 929036.286 4.602 + 0 47 47 94 Ag - -52402# 400# 8238# 4# B- -11962# 640# 93 943744# 429# + -2 46 48 94 Cd x -40440# 500# 8102# 5# B- * 93 956586# 537# +0 27 61 34 95 Se x -30460# 500# 8112# 5# B- 13390# 583# 94 967300# 537# + 25 60 35 95 Br x -43850# 300# 8245# 3# B- 12309# 301# 94 952925# 322# + 23 59 36 95 Kr x -56158.920 18.630 8365.9963 0.1961 B- 9731.3868 27.5124 94 939710.922 20.000 + 21 58 37 95 Rb -65890.307 20.245 8460.1967 0.2131 B- 9226.9772 20.2036 94 929263.849 21.733 + 19 57 38 95 Sr -75117.284 5.810 8549.0875 0.0612 B- 6090.6528 7.2395 94 919358.282 6.237 + 17 56 39 95 Y -81207.937 6.779 8604.9644 0.0714 B- 4452.0031 6.7718 94 912819.697 7.277 + 15 55 40 95 Zr -85659.940 0.869 8643.5924 0.0092 B- 1126.3312 0.9854 94 908040.276 0.933 + 13 54 41 95 Nb -86786.272 0.508 8647.2133 0.0054 B- 925.6009 0.4938 94 906831.110 0.545 + 11 53 42 95 Mo -87711.872 0.123 8648.7212 0.0013 B- -1690.5175 5.0782 94 905837.436 0.132 + 9 52 43 95 Tc -86021.355 5.080 8622.6911 0.0535 B- -2563.5961 10.5310 94 907652.281 5.453 + 7 51 44 95 Ru -83457.759 9.502 8587.4706 0.1000 B- -5117.1423 10.2656 94 910404.415 10.200 + 5 50 45 95 Rh -78340.616 3.886 8525.3707 0.0409 B- -8374.7035 4.9281 94 915897.893 4.171 + 3 49 46 95 Pd x -69965.913 3.031 8428.9807 0.0319 B- -10060# 400# 94 924888.506 3.253 + 1 48 47 95 Ag - -59906# 400# 8315# 4# B- -12850# 400# 94 935688# 429# + -1 47 48 95 Cd - -47056# 566# 8171# 6# B- * 94 949483# 607# +0 26 61 35 96 Br x -38210# 300# 8184# 3# B- 14872# 301# 95 958980# 322# + 24 60 36 96 Kr -53081.682 19.277 8330.8721 0.2008 B- 8272.6693 19.5669 95 943014.473 20.695 + 22 59 37 96 Rb -61354.351 3.353 8408.8963 0.0349 B- 11563.8970 9.1062 95 934133.398 3.599 + 20 58 38 96 Sr -72918.248 8.466 8521.2041 0.0882 B- 5411.7380 9.7257 95 921719.045 9.089 + 18 57 39 96 Y -78329.986 6.075 8569.4269 0.0633 B- 7108.8741 6.0740 95 915909.305 6.521 + 16 56 40 96 Zr -85438.860 0.114 8635.3283 0.0012 B- 163.9704 0.1000 95 908277.615 0.122 + 14 55 41 96 Nb -85602.830 0.147 8628.8868 0.0015 B- 3192.0590 0.1070 95 908101.586 0.157 + 12 54 42 96 Mo -88794.889 0.120 8653.9880 0.0013 B- -2973.2411 5.1450 95 904674.770 0.128 + 10 53 43 96 Tc - -85821.648 5.146 8614.8673 0.0536 B- 258.7369 5.1464 95 907866.675 5.524 + 8 52 44 96 Ru -86080.385 0.170 8609.4130 0.0018 B- -6392.6529 10.0000 95 907588.910 0.182 + 6 51 45 96 Rh - -79687.732 10.001 8534.6735 0.1042 B- -3504.3127 10.8442 95 914451.705 10.737 + 4 50 46 96 Pd x -76183.420 4.194 8490.0207 0.0437 B- -11671.7741 90.1814 95 918213.739 4.502 + 2 49 47 96 Ag ep -64511.645 90.084 8360.2903 0.9384 B- -8940# 400# 95 930743.903 96.708 + 0 48 48 96 Cd - -55572# 410# 8259# 4# B- -17482# 647# 95 940341# 440# + -2 47 49 96 In x -38090# 500# 8069# 5# B- * 95 959109# 537# +0 27 62 35 97 Br x -34000# 400# 8140# 4# B- 13423# 420# 96 963499# 429# + 25 61 36 97 Kr x -47423.499 130.409 8269.8645 1.3444 B- 11095.6460 130.4232 96 949088.782 140.000 + 23 60 37 97 Rb -58519.145 1.912 8376.1872 0.0197 B- 10061.5295 3.8872 96 937177.117 2.052 + 21 59 38 97 Sr -68580.674 3.385 8471.8489 0.0349 B- 7534.7807 7.5131 96 926375.621 3.633 + 19 58 39 97 Y + -76115.455 6.708 8541.4616 0.0692 B- 6821.2382 6.7068 96 918286.702 7.201 + 17 57 40 97 Zr -82936.693 0.121 8603.7182 0.0013 B- 2666.1038 4.2435 96 910963.802 0.130 + 15 56 41 97 Nb -85602.797 4.244 8623.1384 0.0438 B- 1941.9038 4.2435 96 908101.622 4.556 + 13 55 42 97 Mo -87544.700 0.165 8635.0926 0.0017 B- -320.2640 4.1169 96 906016.903 0.176 + 11 54 43 97 Tc -87224.436 4.118 8623.7254 0.0425 B- -1103.8722 4.9563 96 906360.720 4.420 + 9 53 44 97 Ru -n -86120.564 2.763 8604.2799 0.0285 B- -3523.0000 35.3553 96 907545.776 2.965 + 7 52 45 97 Rh - -82597.564 35.463 8559.8949 0.3656 B- -4791.7118 35.7924 96 911327.872 38.071 + 5 51 46 97 Pd x -77805.852 4.844 8502.4303 0.0499 B- -6901.8255 12.9558 96 916471.985 5.200 + 3 50 47 97 Ag x -70904.027 12.016 8423.2121 0.1239 B- -10170.0000 420.0000 96 923881.400 12.900 + 1 49 48 97 Cd - -60734.027 420.172 8310.3013 4.3317 B- -13344# 580# 96 934799.343 451.073 + -1 48 49 97 In x -47390# 401# 8165# 4# B- * 96 949125# 430# +0 28 63 35 98 Br x -28050# 400# 8078# 4# B- 16070# 500# 97 969887# 429# + 26 62 36 98 Kr x -44120# 300# 8234# 3# B- 10249# 300# 97 952635# 322# + 24 61 37 98 Rb -54369.152 16.083 8330.7294 0.1641 B- 12053.2361 16.4029 97 941632.317 17.265 + 22 60 38 98 Sr -66422.389 3.226 8445.7385 0.0329 B- 5866.3591 8.5504 97 928692.636 3.463 + 20 59 39 98 Y p-2n -72288.748 7.919 8497.6162 0.0808 B- 8993.0098 11.5755 97 922394.841 8.501 + 18 58 40 98 Zr -81281.757 8.445 8581.3984 0.0862 B- 2242.8547 9.8134 97 912740.448 9.065 + 16 57 41 98 Nb -pn -83524.612 5.001 8596.3016 0.0510 B- 4591.3681 5.0032 97 910332.645 5.369 + 14 56 42 98 Mo -88115.980 0.174 8635.1691 0.0018 B- -1683.7664 3.3768 97 905403.609 0.186 + 12 55 43 98 Tc -86432.214 3.380 8610.0047 0.0345 B- 1792.6575 7.1568 97 907211.206 3.628 + 10 54 44 98 Ru -88224.871 6.463 8620.3140 0.0659 B- -5049.6529 10.0000 97 905286.709 6.937 + 8 53 45 98 Rh - -83175.219 11.906 8560.8038 0.1215 B- -1854.2331 12.8161 97 910707.734 12.782 + 6 52 46 98 Pd -81320.985 4.742 8533.8999 0.0484 B- -8254.5607 33.0975 97 912698.335 5.090 + 4 51 47 98 Ag -73066.425 32.907 8441.6866 0.3358 B- -5430.0000 40.0000 97 921559.970 35.327 + 2 50 48 98 Cd - -67636.425 51.797 8378.2953 0.5285 B- -13730# 300# 97 927389.315 55.605 + 0 49 49 98 In - -53906# 304# 8230# 3# B- * 97 942129# 327# +0 27 63 36 99 Kr x -38400# 400# 8175# 4# B- 12721# 400# 98 958776# 429# + 25 62 37 99 Rb x -51121.150 4.031 8295.3010 0.0407 B- 11397.3767 6.2201 98 945119.190 4.327 + 23 61 38 99 Sr -62518.527 4.737 8402.5235 0.0479 B- 8125.2037 8.1353 98 932883.604 5.085 + 21 60 39 99 Y x -70643.730 6.615 8476.6938 0.0668 B- 6972.9398 12.4082 98 924160.839 7.101 + 19 59 40 99 Zr -77616.670 10.499 8539.2250 0.1061 B- 4718.6736 15.9474 98 916675.081 11.271 + 17 58 41 99 Nb +p -82335.344 12.004 8578.9859 0.1213 B- 3634.7623 12.0059 98 911609.377 12.886 + 15 57 42 99 Mo -85970.106 0.229 8607.7982 0.0023 B- 1357.7631 0.8905 98 907707.299 0.245 + 13 56 43 99 Tc -87327.869 0.908 8613.6105 0.0092 B- 297.5156 0.9453 98 906249.681 0.974 + 11 55 44 99 Ru -87625.385 0.343 8608.7132 0.0035 B- -2040.8632 19.4529 98 905930.284 0.368 + 9 54 45 99 Rh -85584.522 19.451 8580.1959 0.1965 B- -3401.6603 18.9153 98 908121.241 20.881 + 7 53 46 99 Pd -82182.861 5.107 8537.9332 0.0516 B- -5470.3785 8.0829 98 911773.073 5.482 + 5 52 47 99 Ag x -76712.483 6.265 8474.7744 0.0633 B- -6781.3511 6.4622 98 917645.766 6.725 + 3 51 48 99 Cd x -69931.132 1.584 8398.3734 0.0160 B- -8555# 298# 98 924925.845 1.700 + 1 50 49 99 In x -61376# 298# 8304# 3# B- -13400# 500# 98 934110# 320# + -1 49 50 99 Sn - -47976# 582# 8161# 6# B- * 98 948495# 625# +0 28 64 36 100 Kr x -34470# 400# 8134# 4# B- 11796# 400# 99 962995# 429# + 26 63 37 100 Rb -46265.884 13.124 8244.5085 0.1312 B- 13551.6204 14.8355 99 950331.532 14.089 + 24 62 38 100 Sr -59817.505 6.918 8372.2012 0.0692 B- 7503.7365 13.1453 99 935783.270 7.426 + 22 61 39 100 Y x -67321.241 11.179 8439.4151 0.1118 B- 9051.4949 13.8293 99 927727.678 12.000 + 20 60 40 100 Zr -76372.736 8.143 8522.1066 0.0814 B- 3418.5098 11.3976 99 918010.499 8.742 + 18 59 41 100 Nb IT -79791.246 7.976 8548.4683 0.0798 B- 6401.7829 7.9817 99 914340.578 8.562 + 16 58 42 100 Mo -86193.029 0.301 8604.6626 0.0030 B- -172.0776 1.3704 99 907467.982 0.322 + 14 57 43 100 Tc -n -86020.951 1.351 8595.1184 0.0135 B- 3206.4401 1.3760 99 907652.715 1.450 + 12 56 44 100 Ru -89227.391 0.342 8619.3593 0.0034 B- -3636.2612 18.1231 99 904210.460 0.367 + 10 55 45 100 Rh -85591.130 18.125 8575.1732 0.1813 B- -378.4577 25.2879 99 908114.147 19.458 + 8 54 46 100 Pd -85212.672 17.637 8563.5652 0.1764 B- -7074.7030 18.3319 99 908520.438 18.934 + 6 53 47 100 Ag x -78137.969 5.000 8484.9947 0.0500 B- -3943.3740 5.2735 99 916115.443 5.367 + 4 52 48 100 Cd x -74194.595 1.677 8437.7375 0.0168 B- -10016.4492 2.7945 99 920348.829 1.800 + 2 51 49 100 In x -64178.146 2.236 8329.7495 0.0224 B- -7030.0000 240.0000 99 931101.929 2.400 + 0 50 50 100 Sn - -57148.146 240.010 8251.6260 2.4001 B- * 99 938648.944 257.661 +0 29 65 36 101 Kr x -28580# 500# 8075# 5# B- 13987# 501# 100 969318# 537# + 27 64 37 101 Rb x -42567.417 20.493 8206.1753 0.2029 B- 12757.4969 22.1781 100 954302.000 22.000 + 25 63 38 101 Sr x -55324.914 8.480 8324.7411 0.0840 B- 9729.8721 11.0473 100 940606.264 9.103 + 23 62 39 101 Y x -65054.787 7.080 8413.3305 0.0701 B- 8106.2003 10.9331 100 930160.817 7.601 + 21 61 40 101 Zr -73160.987 8.332 8485.8439 0.0825 B- 5730.5011 9.1366 100 921458.454 8.944 + 19 60 41 101 Nb x -78891.488 3.749 8534.8355 0.0371 B- 4628.4637 3.7378 100 915306.508 4.024 + 17 59 42 101 Mo -n -83519.952 0.308 8572.9159 0.0031 B- 2824.6411 24.0018 100 910337.648 0.331 + 15 58 43 101 Tc + -86344.593 24.004 8593.1366 0.2377 B- 1613.5200 24.0000 100 907305.271 25.768 + 13 57 44 101 Ru -87958.113 0.413 8601.3660 0.0041 B- -545.6846 5.8518 100 905573.086 0.443 + 11 56 45 101 Rh -87412.428 5.841 8588.2172 0.0578 B- -1980.2833 3.9027 100 906158.903 6.270 + 9 55 46 101 Pd -85432.145 4.588 8560.8644 0.0454 B- -4097.7606 6.6679 100 908284.824 4.925 + 7 54 47 101 Ag x -81334.384 4.838 8512.5465 0.0479 B- -5497.9186 5.0625 100 912683.951 5.193 + 5 53 48 101 Cd x -75836.466 1.490 8450.3657 0.0148 B- -7291.5642 11.7569 100 918586.209 1.600 + 3 52 49 101 In x -68544.901 11.662 8370.4260 0.1155 B- -8239.2770 300.2313 100 926414.025 12.519 + 1 51 50 101 Sn ep -60305.624 300.005 8281.1030 2.9703 B- * 100 935259.252 322.068 +0 28 65 37 102 Rb x -37252.312 82.903 8152.7443 0.8128 B- 14906.9991 106.6347 101 960008.000 89.000 + 26 64 38 102 Sr x -52159.311 67.068 8291.2213 0.6575 B- 9013.3301 67.1916 101 944004.679 72.000 + 24 63 39 102 Y x -61172.641 4.081 8371.9172 0.0400 B- 10408.7856 9.6618 101 934328.471 4.381 + 22 62 40 102 Zr -71581.427 8.758 8466.2940 0.0859 B- 4716.8380 9.0530 101 923154.181 9.401 + 20 61 41 102 Nb -76298.265 2.511 8504.8675 0.0246 B- 7262.6008 8.6750 101 918090.447 2.695 + 18 60 42 102 Mo -83560.866 8.305 8568.3994 0.0814 B- 1012.0557 12.3682 101 910293.725 8.916 + 16 59 43 102 Tc -84572.921 9.166 8570.6514 0.0899 B- 4533.5134 9.1646 101 909207.239 9.840 + 14 58 44 102 Ru -89106.435 0.416 8607.4275 0.0041 B- -2323.1187 6.3960 101 904340.312 0.446 + 12 57 45 102 Rh - -86783.316 6.410 8576.9818 0.0628 B- 1119.6470 6.3962 101 906834.282 6.880 + 10 56 46 102 Pd -87902.963 0.419 8580.2887 0.0041 B- -5656.2615 8.1816 101 905632.292 0.449 + 8 55 47 102 Ag + -82246.702 8.171 8517.1650 0.0801 B- -2587.0000 8.0000 101 911704.538 8.771 + 6 54 48 102 Cd -79659.702 1.662 8484.1322 0.0163 B- -8964.8059 4.8654 101 914481.797 1.784 + 4 53 49 102 In -70694.896 4.573 8388.5719 0.0448 B- -5760.0000 100.0000 101 924105.911 4.909 + 2 52 50 102 Sn - -64934.896 100.105 8324.4313 0.9814 B- -13835# 412# 101 930289.525 107.466 + 0 51 51 102 Sb x -51100# 400# 8181# 4# B- * 101 945142# 429# +0 29 66 37 103 Rb x -33160# 400# 8112# 4# B- 14120# 447# 102 964401# 429# + 27 65 38 103 Sr x -47280# 200# 8242# 2# B- 11177# 201# 102 949243# 215# + 25 64 39 103 Y x -58457.034 11.206 8342.6336 0.1088 B- 9351.9600 14.5130 102 937243.796 12.029 + 23 63 40 103 Zr x -67808.993 9.223 8425.8337 0.0895 B- 7219.6740 10.0270 102 927204.054 9.900 + 21 62 41 103 Nb x -75028.667 3.935 8488.3320 0.0382 B- 5925.6639 10.0270 102 919453.416 4.224 + 19 61 42 103 Mo x -80954.331 9.223 8538.2672 0.0895 B- 3649.5889 13.4648 102 913091.954 9.900 + 17 60 43 103 Tc +p -84603.920 9.810 8566.1045 0.0952 B- 2663.2474 9.8086 102 909173.960 10.531 + 15 59 44 103 Ru -87267.168 0.441 8584.3656 0.0043 B- 764.5378 2.2598 102 906314.846 0.473 + 13 58 45 103 Rh -88031.705 2.301 8584.1927 0.0223 B- -574.7252 2.3928 102 905494.081 2.470 + 11 57 46 103 Pd -n -87456.980 0.878 8571.0173 0.0085 B- -2654.2778 4.1916 102 906111.074 0.942 + 9 56 47 103 Ag x -84802.702 4.099 8537.6520 0.0398 B- -4151.0761 4.4806 102 908960.558 4.400 + 7 55 48 103 Cd -80651.626 1.811 8489.7547 0.0176 B- -6019.2293 9.1242 102 913416.922 1.943 + 5 54 49 103 In -74632.397 8.980 8423.7199 0.0872 B- -7540# 100# 102 919878.830 9.640 + 3 53 50 103 Sn - -67092# 100# 8343# 1# B- -10422# 316# 102 927973# 108# + 1 52 51 103 Sb x -56670# 300# 8234# 3# B- * 102 939162# 322# +0 30 67 37 104 Rb x -27450# 500# 8057# 5# B- 16310# 583# 103 970531# 537# + 28 66 38 104 Sr x -43760# 300# 8206# 3# B- 10320# 361# 103 953022# 322# + 26 65 39 104 Y x -54080# 200# 8298# 2# B- 11638# 200# 103 941943# 215# + 24 64 40 104 Zr x -65717.660 9.316 8402.3159 0.0896 B- 6093.3367 9.4851 103 929449.193 10.000 + 22 63 41 104 Nb x -71810.997 1.784 8453.3832 0.0172 B- 8532.7512 9.0879 103 922907.728 1.915 + 20 62 42 104 Mo -80343.748 8.911 8527.9063 0.0857 B- 2155.2212 24.1665 103 913747.443 9.566 + 18 61 43 104 Tc -82498.969 24.886 8541.1070 0.2393 B- 5596.7945 24.9370 103 911433.718 26.716 + 16 60 44 104 Ru -88095.763 2.498 8587.3998 0.0240 B- -1136.4195 3.3643 103 905425.312 2.682 + 14 59 45 104 Rh -n -86959.344 2.303 8568.9501 0.0221 B- 2435.7789 2.6595 103 906645.309 2.471 + 12 58 46 104 Pd +n -89395.123 1.336 8584.8485 0.0129 B- -4278.6529 4.0000 103 904030.393 1.434 + 10 57 47 104 Ag - -85116.470 4.217 8536.1850 0.0406 B- -1148.0787 4.5370 103 908623.715 4.527 + 8 56 48 104 Cd -83968.391 1.673 8517.6232 0.0161 B- -7785.7166 6.0127 103 909856.228 1.795 + 6 55 49 104 In x -76182.675 5.775 8435.2380 0.0555 B- -4555.6174 8.1461 103 918214.538 6.200 + 4 54 50 104 Sn -71627.057 5.745 8383.9114 0.0552 B- -12332# 102# 103 923105.195 6.167 + 2 53 51 104 Sb +a -59295# 101# 8258# 1# B- -9668# 333# 103 936344# 109# + 0 52 52 104 Te -a -49626.831 317.609 8157.3256 3.0539 B- * 103 946723.408 340.967 +0 29 67 38 105 Sr x -38190# 500# 8152# 5# B- 12380# 640# 104 959001# 537# + 27 66 39 105 Y x -50570# 400# 8262# 4# B- 10888# 400# 104 945711# 429# + 25 65 40 105 Zr x -61458.274 12.110 8358.5980 0.1153 B- 8457.2728 12.7625 104 934021.832 13.000 + 23 64 41 105 Nb x -69915.547 4.028 8431.6925 0.0384 B- 7415.2411 9.9106 104 924942.577 4.324 + 21 63 42 105 Mo -77330.788 9.055 8494.8630 0.0862 B- 4955.5157 35.0307 104 916981.989 9.721 + 19 62 43 105 Tc -82286.303 35.263 8534.6074 0.3358 B- 3648.2396 35.2787 104 911662.024 37.856 + 17 61 44 105 Ru -85934.543 2.499 8561.9016 0.0238 B- 1916.7271 2.8508 104 907745.478 2.683 + 15 60 45 105 Rh -87851.270 2.502 8572.7053 0.0238 B- 566.6347 2.3459 104 905687.787 2.685 + 13 59 46 105 Pd -88417.905 1.138 8570.6509 0.0108 B- -1347.0564 4.6695 104 905079.479 1.222 + 11 58 47 105 Ag -87070.848 4.544 8550.3708 0.0433 B- -2736.9989 4.3618 104 906525.604 4.877 + 9 57 48 105 Cd -84333.849 1.392 8516.8532 0.0133 B- -4693.2673 10.3405 104 909463.893 1.494 + 7 56 49 105 In x -79640.582 10.246 8464.7045 0.0976 B- -6302.5807 10.9891 104 914502.322 11.000 + 5 55 50 105 Sn -73338.001 3.971 8397.2290 0.0378 B- -9322.5103 22.1849 104 921268.421 4.263 + 3 54 51 105 Sb +a -64015.491 21.827 8300.9923 0.2079 B- -11203.9825 300.8126 104 931276.547 23.431 + 1 53 52 105 Te -a -52811.509 300.020 8186.8368 2.8573 B- * 104 943304.516 322.084 +0 30 68 38 106 Sr x -34300# 600# 8114# 6# B- 11490# 781# 105 963177# 644# + 28 67 39 106 Y x -45790# 500# 8215# 5# B- 12959# 539# 105 950842# 537# + 26 66 40 106 Zr x -58749# 200# 8330# 2# B- 7453# 200# 105 936930# 215# + 24 65 41 106 Nb -66202.678 1.416 8393.2657 0.0134 B- 9925.3249 9.2388 105 928928.505 1.520 + 22 64 42 106 Mo x -76128.003 9.130 8479.5202 0.0861 B- 3648.2494 15.2778 105 918273.231 9.801 + 20 63 43 106 Tc + -79776.253 12.250 8506.5570 0.1156 B- 6547.0000 11.0000 105 914356.674 13.150 + 18 62 44 106 Ru -86323.253 5.391 8560.9406 0.0509 B- 39.4038 0.2121 105 907328.181 5.787 + 16 61 45 106 Rh -86362.656 5.390 8553.9317 0.0508 B- 3544.8865 5.3348 105 907285.879 5.786 + 14 60 46 106 Pd -89907.543 1.106 8579.9934 0.0104 B- -2965.1434 2.8172 105 903480.287 1.186 + 12 59 47 106 Ag -86942.399 3.016 8544.6397 0.0285 B- 189.7534 2.8190 105 906663.499 3.237 + 10 58 48 106 Cd -87132.153 1.104 8539.0492 0.0104 B- -6524.0031 12.1765 105 906459.791 1.184 + 8 57 49 106 In - -80608.150 12.226 8470.1213 0.1153 B- -3254.4521 13.2439 105 913463.596 13.125 + 6 56 50 106 Sn -77353.698 5.091 8432.0383 0.0480 B- -10880.3964 9.0249 105 916957.394 5.465 + 4 55 51 106 Sb x -66473.301 7.452 8322.0124 0.0703 B- -8253.5423 100.8163 105 928637.979 8.000 + 2 54 52 106 Te -a -58219.759 100.541 8236.7682 0.9485 B- -14920# 412# 105 937498.521 107.934 + 0 53 53 106 I x -43300# 400# 8089# 4# B- * 105 953516# 429# +0 31 69 38 107 Sr x -28250# 700# 8057# 7# B- 13720# 860# 106 969672# 751# + 29 68 39 107 Y x -41970# 500# 8178# 5# B- 12050# 583# 106 954943# 537# + 27 67 40 107 Zr x -54020# 300# 8284# 3# B- 9704# 300# 106 942007# 322# + 25 66 41 107 Nb x -63723.805 8.023 8367.0898 0.0750 B- 8821.1703 12.2239 106 931589.685 8.612 + 23 65 42 107 Mo x -72544.975 9.223 8442.2190 0.0862 B- 6204.9921 12.6599 106 922119.770 9.901 + 21 64 43 107 Tc x -78749.967 8.673 8492.8979 0.0811 B- 5112.5985 11.7243 106 915458.437 9.310 + 19 63 44 107 Ru -nn -83862.565 8.673 8533.3676 0.0811 B- 3001.1457 14.8473 106 909969.837 9.310 + 17 62 45 107 Rh +p -86863.711 12.051 8554.1040 0.1126 B- 1508.9427 12.1108 106 906747.975 12.937 + 15 61 46 107 Pd -88372.654 1.201 8560.8946 0.0112 B- 34.0458 2.3174 106 905128.058 1.289 + 13 60 47 107 Ag -88406.700 2.382 8553.9012 0.0223 B- -1416.3741 2.5654 106 905091.509 2.556 + 11 59 48 107 Cd -86990.325 1.660 8533.3524 0.0155 B- -3423.6586 9.5800 106 906612.049 1.782 + 9 58 49 107 In -83566.667 9.654 8494.0439 0.0902 B- -5054.4281 11.0175 106 910287.497 10.363 + 7 57 50 107 Sn x -78512.239 5.310 8439.4946 0.0496 B- -7858.9903 6.7377 106 915713.649 5.700 + 5 56 51 107 Sb -70653.248 4.148 8358.7344 0.0388 B- -9996# 101# 106 924150.621 4.452 + 3 55 52 107 Te -a -60657# 101# 8258# 1# B- -11227# 316# 106 934882# 108# + 1 54 53 107 I x -49430# 300# 8146# 3# B- * 106 946935# 322# +0 30 69 39 108 Y x -36780# 600# 8129# 6# B- 14170# 721# 107 960515# 644# + 28 68 40 108 Zr x -50950# 400# 8253# 4# B- 8595# 400# 107 945303# 429# + 26 67 41 108 Nb x -59545.198 8.239 8325.6604 0.0763 B- 11204.0998 12.3668 107 936075.604 8.844 + 24 66 42 108 Mo x -70749.297 9.223 8422.1581 0.0854 B- 5173.5330 12.7262 107 924047.508 9.901 + 22 65 43 108 Tc x -75922.831 8.769 8462.8172 0.0812 B- 7738.5736 11.7903 107 918493.493 9.413 + 20 64 44 108 Ru -3n -83661.404 8.680 8527.2267 0.0804 B- 1369.7517 16.4699 107 910185.793 9.318 + 18 63 45 108 Rh x -85031.156 13.997 8532.6657 0.1296 B- 4493.0596 14.0405 107 908715.304 15.026 + 16 62 46 108 Pd -89524.215 1.108 8567.0241 0.0103 B- -1917.4238 2.6323 107 903891.806 1.189 + 14 61 47 108 Ag -n -87606.792 2.388 8542.0262 0.0221 B- 1645.6311 2.6386 107 905950.245 2.563 + 12 60 48 108 Cd -89252.423 1.123 8550.0196 0.0104 B- -5132.5944 8.5845 107 904183.588 1.205 + 10 59 49 108 In -84119.828 8.641 8495.2516 0.0800 B- -2049.8794 9.8365 107 909693.654 9.276 + 8 58 50 108 Sn -82069.949 5.382 8469.0273 0.0498 B- -9624.6079 7.6925 107 911894.290 5.778 + 6 57 51 108 Sb x -72445.341 5.496 8372.6666 0.0509 B- -6663.6646 7.7125 107 922226.731 5.900 + 4 56 52 108 Te -65781.676 5.411 8303.7221 0.0501 B- -13011# 101# 107 929380.469 5.808 + 2 55 53 108 I -p -52771# 101# 8176# 1# B- -10139# 393# 107 943348# 109# + 0 54 54 108 Xe -a -42632.357 379.497 8074.8886 3.5139 B- * 107 954232.285 407.406 +0 31 70 39 109 Y x -32480# 700# 8089# 6# B- 13250# 860# 108 965131# 751# + 29 69 40 109 Zr x -45730# 500# 8204# 5# B- 10960# 660# 108 950907# 537# + 27 68 41 109 Nb x -56689.800 430.816 8297.1307 3.9524 B- 9969.4851 430.9610 108 939141.000 462.500 + 25 67 42 109 Mo x -66659.285 11.179 8381.4163 0.1026 B- 7623.5438 14.7805 108 928438.318 12.000 + 23 66 43 109 Tc x -74282.828 9.669 8444.1796 0.0887 B- 6455.6267 12.6574 108 920254.107 10.380 + 21 65 44 109 Ru -4n -80738.455 8.954 8496.2280 0.0821 B- 4260.7958 9.8229 108 913323.707 9.612 + 19 64 45 109 Rh -84999.251 4.040 8528.1404 0.0371 B- 2607.2327 4.1874 108 908749.555 4.336 + 17 63 46 109 Pd -87606.484 1.114 8544.8825 0.0102 B- 1112.9469 1.4024 108 905950.576 1.195 + 15 62 47 109 Ag -88719.431 1.287 8547.9155 0.0118 B- -215.1002 1.7795 108 904755.778 1.381 + 13 61 48 109 Cd -88504.330 1.536 8538.7646 0.0141 B- -2014.8047 4.0662 108 904986.697 1.649 + 11 60 49 109 In -86489.526 3.969 8513.1027 0.0364 B- -3859.3453 8.8866 108 907149.679 4.261 + 9 59 50 109 Sn -82630.180 7.949 8470.5183 0.0729 B- -6379.1940 8.8074 108 911292.857 8.533 + 7 58 51 109 Sb -76250.986 5.265 8404.8161 0.0483 B- -8535.5871 6.8502 108 918141.203 5.652 + 5 57 52 109 Te -67715.399 4.382 8319.3305 0.0402 B- -10042.8941 8.0301 108 927304.532 4.704 + 3 56 53 109 I -p -57672.505 6.729 8220.0164 0.0617 B- -11502.9589 300.1831 108 938086.022 7.223 + 1 55 54 109 Xe -a -46169.546 300.108 8107.3071 2.7533 B- * 108 950434.955 322.178 +0 30 70 40 110 Zr x -42220# 500# 8171# 5# B- 10090# 976# 109 954675# 537# + 28 69 41 110 Nb x -52309.914 838.345 8255.2607 7.6213 B- 12225.9002 838.6945 109 943843.000 900.000 + 26 68 42 110 Mo x -64535.814 24.219 8359.2930 0.2202 B- 6498.7491 26.0147 109 930717.956 26.000 + 24 67 43 110 Tc x -71034.564 9.497 8411.2603 0.0863 B- 9038.0654 12.5086 109 923741.263 10.195 + 22 66 44 110 Ru -80072.629 8.924 8486.3123 0.0811 B- 2756.0638 19.4044 109 914038.501 9.580 + 20 65 45 110 Rh -82828.693 17.805 8504.2551 0.1619 B- 5502.2116 17.7967 109 911079.745 19.114 + 18 64 46 110 Pd -88330.904 0.612 8547.1630 0.0056 B- -873.5982 1.3777 109 905172.878 0.657 + 16 63 47 110 Ag -87457.306 1.286 8532.1089 0.0117 B- 2890.6633 1.2771 109 906110.724 1.380 + 14 62 48 110 Cd -90347.969 0.380 8551.2755 0.0035 B- -3878.0000 11.5470 109 903007.470 0.407 + 12 61 49 110 In - -86469.969 11.553 8508.9087 0.1050 B- -627.9769 17.9802 109 907170.674 12.402 + 10 60 50 110 Sn x -85841.993 13.777 8496.0875 0.1252 B- -8392.2480 15.0117 109 907844.835 14.790 + 8 59 51 110 Sb x -77449.745 5.962 8412.6821 0.0542 B- -5219.9240 8.8753 109 916854.283 6.400 + 6 58 52 110 Te -72229.821 6.575 8358.1160 0.0598 B- -11761.9766 62.2875 109 922458.102 7.058 + 4 57 53 110 I -a -60467.844 61.940 8244.0767 0.5631 B- -8545.2075 118.4700 109 935085.102 66.494 + 2 56 54 110 Xe -a -51922.636 100.988 8159.2808 0.9181 B- * 109 944258.759 108.415 +0 31 71 40 111 Zr x -36480# 600# 8118# 5# B- 12480# 671# 110 960837# 644# + 29 70 41 111 Nb x -48960# 300# 8223# 3# B- 10980# 300# 110 947439# 322# + 27 69 42 111 Mo + -59939.813 12.578 8315.2932 0.1133 B- 9084.8620 6.7999 110 935651.966 13.503 + 25 68 43 111 Tc x -69024.675 10.582 8390.0906 0.0953 B- 7760.6500 13.8477 110 925898.966 11.359 + 23 67 44 111 Ru x -76785.325 9.682 8452.9582 0.0872 B- 5518.5456 11.8621 110 917567.566 10.394 + 21 66 45 111 Rh -82303.871 6.853 8495.6267 0.0617 B- 3682.0153 6.8899 110 911643.164 7.356 + 19 65 46 111 Pd -n -85985.886 0.731 8521.7498 0.0066 B- 2229.5607 1.5721 110 907690.358 0.785 + 17 64 47 111 Ag + -88215.447 1.459 8534.7878 0.0131 B- 1036.8000 1.4142 110 905296.827 1.565 + 15 63 48 111 Cd -89252.247 0.357 8537.0801 0.0032 B- -860.1972 3.4170 110 904183.776 0.383 + 13 62 49 111 In -88392.050 3.424 8522.2824 0.0308 B- -2453.4692 6.3368 110 905107.236 3.675 + 11 61 50 111 Sn +n -85938.581 5.336 8493.1310 0.0481 B- -5101.8340 10.3337 110 907741.143 5.728 + 9 60 51 111 Sb x -80836.747 8.849 8440.1203 0.0797 B- -7249.2597 10.9370 110 913218.187 9.500 + 7 59 52 111 Te x -73587.487 6.427 8367.7635 0.0579 B- -8633.6922 7.9943 110 921000.587 6.900 + 5 58 53 111 I -64953.795 4.754 8282.9343 0.0428 B- -10434# 116# 110 930269.236 5.103 + 3 57 54 111 Xe -a -54520# 115# 8182# 1# B- -11620# 231# 110 941470# 124# + 1 56 55 111 Cs x -42900# 200# 8070# 2# B- * 110 953945# 215# +0 32 72 40 112 Zr x -32420# 700# 8081# 6# B- 11650# 761# 111 965196# 751# + 30 71 41 112 Nb x -44070# 300# 8178# 3# B- 13410# 361# 111 952689# 322# + 28 70 42 112 Mo x -57480# 200# 8291# 2# B- 7779# 200# 111 938293# 215# + 26 69 43 112 Tc x -65258.932 5.515 8353.6217 0.0492 B- 10371.9409 11.0602 111 929941.658 5.920 + 24 68 44 112 Ru x -75630.873 9.600 8439.2431 0.0857 B- 4100.1790 45.1185 111 918806.922 10.305 + 22 67 45 112 Rh -79731.052 44.085 8468.8666 0.3936 B- 6589.9874 43.9269 111 914405.199 47.327 + 20 66 46 112 Pd -86321.039 6.546 8520.7205 0.0584 B- 262.6897 6.9799 111 907330.557 7.027 + 18 65 47 112 Ag x -86583.729 2.422 8516.0807 0.0216 B- 3991.1283 2.4348 111 907048.548 2.600 + 16 64 48 112 Cd -90574.857 0.250 8544.7306 0.0022 B- -2584.7306 4.2434 111 902763.896 0.268 + 14 63 49 112 In -87990.127 4.251 8514.6674 0.0380 B- 664.9224 4.2434 111 905538.718 4.563 + 12 62 50 112 Sn -88655.049 0.294 8513.6189 0.0026 B- -7056.0760 17.8317 111 904824.894 0.315 + 10 61 51 112 Sb x -81598.973 17.829 8443.6330 0.1592 B- -4031.4550 19.7019 111 912399.903 19.140 + 8 60 52 112 Te x -77567.518 8.383 8400.6527 0.0749 B- -10504.1795 13.2390 111 916727.848 9.000 + 6 59 53 112 I x -67063.339 10.246 8299.8801 0.0915 B- -7036.9910 13.1754 111 928004.548 11.000 + 4 58 54 112 Xe -a -60026.348 8.283 8230.0646 0.0740 B- -13612# 116# 111 935559.068 8.891 + 2 57 55 112 Cs -p -46415# 116# 8102# 1# B- * 111 950172# 124# +0 33 73 40 113 Zr x -26340# 300# 8027# 3# B- 13870# 500# 112 971723# 322# + 31 72 41 113 Nb x -40210# 400# 8143# 4# B- 12440# 500# 112 956833# 429# + 29 71 42 113 Mo x -52650# 300# 8246# 3# B- 10162# 300# 112 943478# 322# + 27 70 43 113 Tc x -62811.549 3.353 8329.4652 0.0297 B- 9056.2674 38.4285 112 932569.032 3.600 + 25 69 44 113 Ru -71867.816 38.282 8402.6857 0.3388 B- 6899.1276 38.9406 112 922846.729 41.097 + 23 68 45 113 Rh x -78766.944 7.132 8456.8165 0.0631 B- 4823.5559 9.8809 112 915440.212 7.656 + 21 67 46 113 Pd x -83590.500 6.947 8492.5795 0.0615 B- 3436.3252 18.0341 112 910261.912 7.458 + 19 66 47 113 Ag + -87026.825 16.643 8516.0660 0.1473 B- 2016.4615 16.6410 112 906572.865 17.866 + 17 65 48 113 Cd -89043.286 0.245 8526.9874 0.0022 B- 323.8370 0.2653 112 904408.105 0.262 + 15 64 49 113 In -89367.123 0.188 8522.9297 0.0017 B- -1038.9941 1.5733 112 904060.451 0.202 + 13 63 50 113 Sn -88328.129 1.575 8506.8117 0.0139 B- -3911.1637 17.1206 112 905175.857 1.690 + 11 62 51 113 Sb - -84416.966 17.193 8465.2762 0.1521 B- -6069.9281 32.8102 112 909374.664 18.457 + 9 61 52 113 Te x -78347.037 27.945 8404.6366 0.2473 B- -7227.5210 29.0704 112 915891.000 30.000 + 7 60 53 113 I x -71119.517 8.011 8333.7528 0.0709 B- -8915.8902 10.5334 112 923650.062 8.600 + 5 59 54 113 Xe -62203.626 6.840 8247.9277 0.0605 B- -10439.0876 10.9702 112 933221.663 7.342 + 3 58 55 113 Cs -p -51764.539 8.577 8148.6230 0.0759 B- -12055# 300# 112 944428.484 9.207 + 1 57 56 113 Ba x -39710# 300# 8035# 3# B- * 112 957370# 322# +0 32 73 41 114 Nb x -34960# 500# 8097# 4# B- 14720# 583# 113 962469# 537# + 30 72 42 114 Mo x -49680# 300# 8219# 3# B- 8920# 527# 113 946666# 322# + 28 71 43 114 Tc x -58600.294 433.145 8290.2599 3.7995 B- 11620.9190 433.1594 113 937090.000 465.000 + 26 70 44 114 Ru x -70221.213 3.556 8385.3351 0.0312 B- 5489.0622 71.6432 113 924614.430 3.817 + 24 69 45 114 Rh -75710.275 71.561 8426.6221 0.6277 B- 7780.0712 71.8915 113 918721.680 76.824 + 22 68 46 114 Pd x -83490.346 6.948 8488.0056 0.0610 B- 1440.4642 8.3133 113 910369.430 7.459 + 20 67 47 114 Ag x -84930.811 4.564 8493.7786 0.0400 B- 5084.1233 4.5727 113 908823.029 4.900 + 18 66 48 114 Cd -90014.934 0.276 8531.5135 0.0024 B- -1445.1268 0.3817 113 903364.998 0.296 + 16 65 49 114 In -88569.807 0.301 8511.9742 0.0027 B- 1989.9281 0.3018 113 904916.405 0.323 + 14 64 50 114 Sn -90559.735 0.029 8522.5671 0.0004 B- -6063.1189 19.7724 113 902780.130 0.031 + 12 63 51 114 Sb -84496.616 19.772 8462.5191 0.1734 B- -2606.9398 31.4275 113 909289.155 21.226 + 10 62 52 114 Te x -81889.676 24.428 8432.7885 0.2143 B- -9250.7417 31.5883 113 912087.820 26.224 + 8 61 53 114 I x -72638.935 20.027 8344.7790 0.1757 B- -5553.0360 22.9354 113 922018.900 21.500 + 6 60 54 114 Xe x -67085.899 11.178 8289.2054 0.0981 B- -12399.9706 85.7989 113 927980.329 12.000 + 4 59 55 114 Cs -a -54685.928 85.068 8173.5711 0.7462 B- -8780.4915 133.3375 113 941292.244 91.323 + 2 58 56 114 Ba -a -45905.437 102.676 8089.6865 0.9007 B- * 113 950718.489 110.227 +0 33 74 41 115 Nb x -30880# 500# 8061# 4# B- 13670# 640# 114 966849# 537# + 31 73 42 115 Mo x -44550# 400# 8173# 3# B- 11247# 445# 114 952174# 429# + 29 72 43 115 Tc x -55796# 196# 8264# 2# B- 10309# 197# 114 940100# 210# + 27 71 44 115 Ru x -66105.296 25.166 8346.8140 0.2188 B- 8123.9327 26.1788 114 929033.049 27.016 + 25 70 45 115 Rh x -74229.228 7.319 8410.6538 0.0636 B- 6196.5938 15.3503 114 920311.649 7.857 + 23 69 46 115 Pd -80425.822 13.547 8457.7342 0.1178 B- 4556.7647 21.6496 114 913659.333 14.543 + 21 68 47 115 Ag -84982.587 18.268 8490.5553 0.1589 B- 3101.8930 18.2744 114 908767.445 19.611 + 19 67 48 115 Cd -88084.480 0.651 8510.7252 0.0057 B- 1451.8768 0.6514 114 905437.426 0.699 + 17 66 49 115 In -89536.357 0.012 8516.5472 0.0003 B- 497.4892 0.0097 114 903878.772 0.012 + 15 65 50 115 Sn -90033.846 0.015 8514.0702 0.0003 B- -3030.4336 16.0253 114 903344.695 0.016 + 13 64 51 115 Sb x -87003.412 16.025 8480.9156 0.1394 B- -4940.6447 32.2137 114 906598.000 17.203 + 11 63 52 115 Te x -82062.767 27.945 8431.1504 0.2430 B- -5724.9628 40.1840 114 911902.000 30.000 + 9 62 53 115 I x -76337.805 28.876 8374.5651 0.2511 B- -7681.0475 31.3126 114 918048.000 31.000 + 7 61 54 115 Xe x -68656.757 12.109 8300.9704 0.1053 B- -8957# 103# 114 926293.943 13.000 + 5 60 55 115 Cs x -59699# 102# 8216# 1# B- -10779# 225# 114 935910# 110# + 3 59 56 115 Ba x -48920# 200# 8116# 2# B- * 114 947482# 215# +0 34 75 41 116 Nb x -25230# 300# 8012# 3# B- 15980# 583# 115 972914# 322# + 32 74 42 116 Mo x -41210# 500# 8143# 4# B- 10003# 582# 115 955759# 537# + 30 73 43 116 Tc x -51214# 298# 8223# 3# B- 12855# 298# 115 945020# 320# + 28 72 44 116 Ru x -64068.917 3.726 8326.8840 0.0321 B- 6666.8252 73.9257 115 931219.191 4.000 + 26 71 45 116 Rh -70735.742 73.832 8377.6123 0.6365 B- 9095.2839 74.1690 115 924062.060 79.261 + 24 70 46 116 Pd x -79831.026 7.135 8449.2755 0.0615 B- 2711.6378 7.8446 115 914297.872 7.659 + 22 69 47 116 Ag x -82542.664 3.260 8465.9073 0.0281 B- 6169.8248 3.2642 115 911386.809 3.500 + 20 68 48 116 Cd -88712.489 0.160 8512.3511 0.0014 B- -462.7305 0.2720 115 904763.230 0.172 + 18 67 49 116 In -n -88249.758 0.220 8501.6177 0.0019 B- 3276.2204 0.2397 115 905259.992 0.236 + 16 66 50 116 Sn -91525.979 0.096 8523.1166 0.0009 B- -4703.9591 5.1540 115 901742.825 0.103 + 14 65 51 116 Sb -86822.020 5.154 8475.8208 0.0444 B- -1558.2272 24.7485 115 906792.732 5.533 + 12 64 52 116 Te -85263.793 24.206 8455.6435 0.2087 B- -7843.1388 75.3230 115 908465.558 25.986 + 10 63 53 116 I -77420.654 75.037 8381.2858 0.6469 B- -4373.7764 75.8444 115 916885.513 80.555 + 8 62 54 116 Xe -73046.877 13.017 8336.8365 0.1122 B- -11004# 101# 115 921580.955 13.974 + 6 61 55 116 Cs ea -62043# 100# 8235# 1# B- -7663# 224# 115 933395# 108# + 4 60 56 116 Ba x -54380# 200# 8162# 2# B- -14330# 379# 115 941621# 215# + 2 59 57 116 La -a -40050# 321# 8032# 3# B- * 115 957005# 345# +0 33 75 42 117 Mo x -35689# 500# 8096# 4# B- 12450# 640# 116 961686# 537# + 31 74 43 117 Tc x -48140# 400# 8195# 3# B- 11350# 589# 116 948320# 429# + 29 73 44 117 Ru x -59489.871 433.145 8285.5625 3.7021 B- 9406.8875 433.2361 116 936135.000 465.000 + 27 72 45 117 Rh x -68896.758 8.895 8359.2766 0.0760 B- 7527.1313 11.4108 116 926036.291 9.548 + 25 71 46 117 Pd -76423.890 7.255 8416.9243 0.0620 B- 5758.0284 14.7674 116 917955.584 7.788 + 23 70 47 117 Ag -82181.918 13.572 8459.4515 0.1160 B- 4236.4790 13.6099 116 911774.086 14.570 + 21 69 48 117 Cd -n -86418.397 1.013 8488.9740 0.0087 B- 2524.6381 4.9829 116 907226.039 1.087 + 19 68 49 117 In -88943.035 4.881 8503.8653 0.0417 B- 1454.7073 4.8567 116 904515.729 5.239 + 17 67 50 117 Sn -90397.742 0.483 8509.6120 0.0041 B- -1758.1788 8.4449 116 902954.036 0.518 + 15 66 51 117 Sb -88639.564 8.437 8487.8981 0.0721 B- -3544.0634 13.0785 116 904841.519 9.057 + 13 65 52 117 Te -85095.500 13.455 8450.9203 0.1150 B- -4656.9321 28.1284 116 908646.227 14.444 + 11 64 53 117 I -80438.568 25.558 8404.4307 0.2184 B- -6253.2213 27.5845 116 913645.649 27.437 + 9 63 54 117 Xe x -74185.347 10.378 8344.2976 0.0887 B- -7692.2462 63.2672 116 920358.758 11.141 + 7 62 55 117 Cs x -66493.101 62.410 8271.8652 0.5334 B- -9035.1943 258.0009 116 928616.723 67.000 + 5 61 56 117 Ba ep -57457.906 250.339 8187.9546 2.1396 B- -11187# 321# 116 938316.403 268.749 + 3 60 57 117 La -p -46271# 200# 8086# 2# B- * 116 950326# 215# +0 34 76 42 118 Mo x -32370# 500# 8067# 4# B- 10920# 640# 117 965249# 537# + 32 75 43 118 Tc x -43290# 400# 8153# 3# B- 13710# 447# 117 953526# 429# + 30 74 44 118 Ru x -57000# 200# 8263# 2# B- 7887# 202# 117 938808# 215# + 28 73 45 118 Rh x -64886.840 24.236 8322.8539 0.2054 B- 10501.5182 24.3424 117 930341.116 26.018 + 26 72 46 118 Pd -75388.358 2.494 8405.2197 0.0211 B- 4165.4444 3.5419 117 919067.273 2.677 + 24 71 47 118 Ag x -79553.802 2.515 8433.8900 0.0213 B- 7147.8469 20.1582 117 914595.484 2.700 + 22 70 48 118 Cd -nn -86701.649 20.001 8487.8350 0.1695 B- 526.5277 21.4501 117 906921.956 21.471 + 20 69 49 118 In -87228.177 7.752 8485.6670 0.0657 B- 4424.6664 7.7396 117 906356.705 8.322 + 18 68 50 118 Sn -91652.843 0.499 8516.5341 0.0042 B- -3656.6393 2.9745 117 901606.630 0.536 + 16 67 51 118 Sb - -87996.204 3.016 8478.9156 0.0256 B- -305.4459 18.5521 117 905532.194 3.237 + 14 66 52 118 Te +nn -87690.758 18.306 8469.6970 0.1551 B- -6719.7015 26.9364 117 905860.104 19.652 + 12 65 53 118 I x -80971.056 19.760 8406.1203 0.1675 B- -2891.9893 22.3197 117 913074.000 21.213 + 10 64 54 118 Xe x -78079.067 10.378 8374.9819 0.0880 B- -9669.6905 16.4423 117 916178.678 11.141 + 8 63 55 118 Cs IT -68409.377 12.753 8286.4053 0.1081 B- -6210# 201# 117 926559.517 13.690 + 6 62 56 118 Ba x -62200# 200# 8227# 2# B- -12580# 361# 117 933226# 215# + 4 61 57 118 La x -49620# 300# 8114# 3# B- * 117 946731# 322# +0 35 77 42 119 Mo x -26580# 300# 8019# 3# B- 13590# 583# 118 971465# 322# + 33 76 43 119 Tc x -40170# 500# 8126# 4# B- 11910# 583# 118 956876# 537# + 31 75 44 119 Ru x -52080# 300# 8220# 3# B- 10743# 300# 118 944090# 322# + 29 74 45 119 Rh x -62822.802 9.315 8303.3953 0.0783 B- 8584.4751 12.4416 118 932556.951 10.000 + 27 73 46 119 Pd x -71407.277 8.248 8368.9594 0.0693 B- 7238.4816 16.8566 118 923341.138 8.854 + 25 72 47 119 Ag -78645.759 14.703 8423.2126 0.1236 B- 5331.1799 35.9259 118 915570.309 15.783 + 23 71 48 119 Cd -83976.939 37.695 8461.4381 0.3168 B- 3721.7197 38.0880 118 909847.052 40.467 + 21 70 49 119 In -87698.658 7.310 8486.1387 0.0614 B- 2366.3263 7.3381 118 905851.622 7.847 + 19 69 50 119 Sn -90064.985 0.725 8499.4494 0.0061 B- -589.4452 6.9937 118 903311.266 0.778 + 17 68 51 119 Sb -89475.539 6.998 8487.9218 0.0588 B- -2293.0000 2.0000 118 903944.062 7.512 + 15 67 52 119 Te - -87182.539 7.278 8462.0785 0.0612 B- -3404.8080 22.8941 118 906405.699 7.813 + 13 66 53 119 I x -83777.731 21.706 8426.8924 0.1824 B- -4983.2433 24.0598 118 910060.910 23.302 + 11 65 54 119 Xe -78794.488 10.378 8378.4420 0.0872 B- -6489.4269 17.3790 118 915410.641 11.141 + 9 64 55 119 Cs IT -72305.061 13.940 8317.3347 0.1171 B- -7714.9651 200.7537 118 922377.327 14.965 + 7 63 56 119 Ba ep -64590.096 200.269 8245.9287 1.6829 B- -9570# 361# 118 930659.683 214.997 + 5 62 57 119 La x -55020# 300# 8159# 3# B- -11199# 583# 118 940934# 322# + 3 61 58 119 Ce x -43820# 500# 8058# 4# B- * 118 952957# 537# +0 34 77 43 120 Tc x -35000# 500# 8083# 4# B- 14720# 640# 119 962426# 537# + 32 76 44 120 Ru x -49720# 400# 8199# 3# B- 8899# 447# 119 946623# 429# + 30 75 45 120 Rh x -58620# 200# 8266# 2# B- 11660# 200# 119 937069# 215# + 28 74 46 120 Pd -70279.604 2.296 8357.0817 0.0191 B- 5371.9076 5.0261 119 924551.745 2.464 + 26 73 47 120 Ag x -75651.512 4.471 8395.3281 0.0373 B- 8305.8535 5.8202 119 918784.765 4.800 + 24 72 48 120 Cd x -83957.365 3.726 8458.0240 0.0311 B- 1770.3754 40.1837 119 909868.065 4.000 + 22 71 49 120 In + -85727.741 40.011 8466.2575 0.3334 B- 5370.0000 40.0000 119 907967.489 42.953 + 20 70 50 120 Sn -91097.741 0.920 8504.4880 0.0077 B- -2680.6076 7.1399 119 902202.557 0.987 + 18 69 51 120 Sb - -88417.133 7.199 8475.6300 0.0600 B- 945.0271 7.3530 119 905080.308 7.728 + 16 68 52 120 Te -89362.160 1.751 8476.9857 0.0146 B- -5615.0000 15.0000 119 904065.779 1.880 + 14 67 53 120 I - -83747.160 15.102 8423.6745 0.1258 B- -1574.7260 19.1760 119 910093.729 16.212 + 12 66 54 120 Xe x -82172.434 11.817 8404.0322 0.0985 B- -8283.7857 15.4611 119 911784.267 12.686 + 10 65 55 120 Cs IT -73888.649 9.970 8328.4811 0.0831 B- -5000.0000 300.0000 119 920677.277 10.702 + 8 64 56 120 Ba - -68888.649 300.166 8280.2949 2.5014 B- -11319# 424# 119 926044.997 322.241 + 6 63 57 120 La x -57570# 300# 8179# 2# B- -7840# 583# 119 938196# 322# + 4 62 58 120 Ce x -49730# 500# 8108# 4# B- * 119 946613# 537# +0 35 78 43 121 Tc x -31540# 500# 8054# 4# B- 13080# 640# 120 966140# 537# + 33 77 44 121 Ru x -44620# 400# 8156# 3# B- 11630# 737# 120 952098# 429# + 31 76 45 121 Rh x -56250.134 619.444 8245.2397 5.1194 B- 9932.2030 619.4527 120 939613.000 665.000 + 29 75 46 121 Pd x -66182.337 3.353 8320.8584 0.0277 B- 8220.4934 12.5652 120 928950.342 3.600 + 27 74 47 121 Ag x -74402.831 12.109 8382.3306 0.1001 B- 6671.0057 12.2642 120 920125.279 13.000 + 25 73 48 121 Cd x -81073.837 1.942 8430.9972 0.0161 B- 4760.7564 27.4876 120 912963.660 2.085 + 23 72 49 121 In +p -85834.593 27.419 8463.8767 0.2266 B- 3362.0331 27.4098 120 907852.778 29.435 + 21 71 50 121 Sn -89196.626 0.978 8485.1964 0.0081 B- 402.5306 2.5239 120 904243.488 1.050 + 19 70 51 121 Sb -89599.157 2.506 8482.0574 0.0207 B- -1056.0462 25.7587 120 903811.353 2.690 + 17 69 52 121 Te -88543.111 25.835 8466.8641 0.2135 B- -2297.4615 25.9856 120 904945.065 27.734 + 15 68 53 121 I -86245.649 4.723 8441.4111 0.0390 B- -3764.6525 11.2790 120 907411.492 5.070 + 13 67 54 121 Xe -82480.997 10.243 8403.8326 0.0847 B- -5378.6549 13.9791 120 911453.012 10.995 + 11 66 55 121 Cs -77102.342 14.290 8352.9152 0.1181 B- -6357.4948 141.1765 120 917227.235 15.340 + 9 65 56 121 Ba - -70744.847 141.898 8293.9083 1.1727 B- -8555# 332# 120 924052.286 152.333 + 7 64 57 121 La x -62190# 300# 8217# 2# B- -9500# 500# 120 933236# 322# + 5 63 58 121 Ce x -52690# 401# 8132# 3# B- -11139# 641# 120 943435# 430# + 3 62 59 121 Pr -p -41551# 500# 8033# 4# B- * 120 955393# 537# +0 36 79 43 122 Tc x -26305# 300# 8011# 2# B- 15475# 583# 121 971760# 322# + 34 78 44 122 Ru x -41780# 500# 8132# 4# B- 10099# 583# 121 955147# 537# + 32 77 45 122 Rh x -51880# 300# 8208# 2# B- 12737# 301# 121 944305# 322# + 30 76 46 122 Pd x -64616.169 19.561 8305.9755 0.1603 B- 6489.9492 42.9094 121 930631.693 21.000 + 28 75 47 122 Ag x -71106.118 38.191 8352.7591 0.3130 B- 9506.2662 38.2604 121 923664.446 41.000 + 26 74 48 122 Cd -80612.384 2.299 8424.2667 0.0188 B- 2958.9765 50.1126 121 913459.050 2.468 + 24 73 49 122 In + -83571.361 50.060 8442.1079 0.4103 B- 6368.5921 50.0000 121 910282.458 53.741 + 22 72 50 122 Sn -89939.953 2.448 8487.8968 0.0201 B- -1605.7483 3.2135 121 903445.494 2.627 + 20 71 51 122 Sb -88334.205 2.503 8468.3222 0.0205 B- 1979.0772 2.1265 121 905169.335 2.687 + 18 70 52 122 Te -90313.282 1.357 8478.1315 0.0111 B- -4234.0000 5.0000 121 903044.708 1.456 + 16 69 53 122 I - -86079.282 5.181 8437.0139 0.0425 B- -724.2937 12.2596 121 907590.094 5.561 + 14 68 54 122 Xe x -85354.988 11.111 8424.6644 0.0911 B- -7210.2195 35.4720 121 908367.655 11.928 + 12 67 55 122 Cs -78144.769 33.687 8359.1515 0.2761 B- -3535.8170 43.7690 121 916108.144 36.164 + 10 66 56 122 Ba x -74608.952 27.945 8323.7567 0.2291 B- -10066# 299# 121 919904.000 30.000 + 8 65 57 122 La x -64543# 298# 8235# 2# B- -6669# 499# 121 930710# 320# + 6 64 58 122 Ce x -57874# 401# 8174# 3# B- -13094# 641# 121 937870# 430# + 4 63 59 122 Pr x -44780# 500# 8060# 4# B- * 121 951927# 537# +0 35 79 44 123 Ru x -36550# 500# 8089# 4# B- 12640# 640# 122 960762# 537# + 33 78 45 123 Rh x -49190# 400# 8185# 3# B- 11239# 885# 122 947192# 429# + 31 77 46 123 Pd x -60429.748 789.441 8270.0318 6.4182 B- 9138.8323 790.1142 122 935126.000 847.500 + 29 76 47 123 Ag x -69568.581 32.602 8337.9707 0.2651 B- 7845.6026 32.7136 122 925315.060 35.000 + 27 75 48 123 Cd -77414.183 2.696 8395.3955 0.0219 B- 6014.8503 19.8980 122 916892.460 2.894 + 25 74 49 123 In -83429.034 19.832 8437.9362 0.1612 B- 4385.6489 19.8392 122 910435.252 21.290 + 23 73 50 123 Sn -87814.683 2.479 8467.2313 0.0202 B- 1408.2079 2.4203 122 905727.065 2.661 + 21 72 51 123 Sb -89222.890 1.356 8472.3196 0.0110 B- -51.9128 0.0661 122 904215.292 1.456 + 19 71 52 123 Te -89170.978 1.355 8465.5370 0.0110 B- -1228.3898 3.4448 122 904271.022 1.454 + 17 70 53 123 I -87942.588 3.686 8449.1896 0.0300 B- -2694.3302 9.6829 122 905589.753 3.956 + 15 69 54 123 Xe -85248.258 9.534 8420.9239 0.0775 B- -4204.6012 15.4121 122 908482.235 10.234 + 13 68 55 123 Cs x -81043.657 12.109 8380.3796 0.0985 B- -5388.6934 17.1253 122 912996.060 13.000 + 11 67 56 123 Ba x -75654.963 12.109 8330.2086 0.0985 B- -7004# 196# 122 918781.060 13.000 + 9 66 57 123 La x -68651# 196# 8267# 2# B- -8365# 357# 122 926300# 210# + 7 65 58 123 Ce x -60286# 298# 8193# 2# B- -10056# 499# 122 935280# 320# + 5 64 59 123 Pr x -50230# 400# 8104# 3# B- * 122 946076# 429# +0 36 80 44 124 Ru x -33590# 600# 8065# 5# B- 11120# 721# 123 963940# 644# + 34 79 45 124 Rh x -44710# 400# 8148# 3# B- 13690# 500# 123 952002# 429# + 32 78 46 124 Pd x -58400# 300# 8252# 2# B- 7830# 391# 123 937305# 322# + 30 77 47 124 Ag x -66229.951 251.503 8308.8958 2.0283 B- 10469.4858 251.5169 123 928899.227 270.000 + 28 76 48 124 Cd -76699.436 2.609 8387.0179 0.0210 B- 4168.3420 30.5355 123 917659.772 2.800 + 26 75 49 124 In -80867.778 30.561 8414.3243 0.2465 B- 7363.6970 30.5668 123 913184.873 32.808 + 24 74 50 124 Sn -88231.475 1.314 8467.3997 0.0106 B- -612.4067 0.4101 123 905279.619 1.410 + 22 73 51 124 Sb -n -87619.069 1.358 8456.1517 0.0110 B- 2905.0730 0.1317 123 905937.065 1.457 + 20 72 52 124 Te -90524.142 1.352 8473.2705 0.0109 B- -3159.5870 1.8593 123 902818.341 1.451 + 18 71 53 124 I - -87364.555 2.299 8441.4807 0.0185 B- 302.8501 1.8639 123 906210.297 2.467 + 16 70 54 124 Xe -87667.405 1.358 8437.6138 0.0110 B- -5926.3445 9.2512 123 905885.174 1.457 + 14 69 55 124 Cs x -81741.060 9.151 8383.5114 0.0738 B- -2651.2748 15.4894 123 912247.366 9.823 + 12 68 56 124 Ba x -79089.786 12.497 8355.8209 0.1008 B- -8831.1685 58.0305 123 915093.627 13.416 + 10 67 57 124 La x -70258.617 56.669 8278.2926 0.4570 B- -5343# 303# 123 924574.275 60.836 + 8 66 58 124 Ce x -64916# 298# 8229# 2# B- -11765# 499# 123 930310# 320# + 6 65 59 124 Pr x -53151# 401# 8128# 3# B- -8321# 641# 123 942940# 430# + 4 64 60 124 Nd x -44830# 500# 8054# 4# B- * 123 951873# 537# +0 37 81 44 125 Ru x -28370# 300# 8023# 2# B- 13460# 583# 124 969544# 322# + 35 80 45 125 Rh x -41830# 500# 8124# 4# B- 12130# 640# 124 955094# 537# + 33 79 46 125 Pd x -53960# 400# 8215# 3# B- 10560# 589# 124 942072# 429# + 31 78 47 125 Ag x -64519.939 433.145 8293.3151 3.4652 B- 8828.1511 433.1544 124 930735.000 465.000 + 29 77 48 125 Cd x -73348.090 2.888 8357.6815 0.0231 B- 7064.2177 3.3869 124 921257.590 3.100 + 27 76 49 125 In x -80412.308 1.770 8407.9365 0.0142 B- 5481.3495 2.2131 124 913673.841 1.900 + 25 75 50 125 Sn -n -85893.657 1.329 8445.5285 0.0106 B- 2361.4366 2.1661 124 907789.370 1.426 + 23 74 51 125 Sb + -88255.094 2.515 8458.1612 0.0201 B- 766.7000 2.1213 124 905254.264 2.700 + 21 73 52 125 Te -89021.794 1.352 8458.0361 0.0108 B- -185.7700 0.0600 124 904431.178 1.451 + 19 72 53 125 I - -88836.024 1.353 8450.2911 0.0108 B- -1636.6632 0.4259 124 904630.610 1.452 + 17 71 54 125 Xe -87199.361 1.415 8430.9390 0.0113 B- -3109.6184 7.7879 124 906387.640 1.518 + 15 70 55 125 Cs -84089.742 7.736 8399.8033 0.0619 B- -4420.7663 13.4415 124 909725.953 8.304 + 13 69 56 125 Ba -79668.976 10.992 8358.1784 0.0879 B- -5909.4836 27.6308 124 914471.840 11.800 + 11 68 57 125 La -73759.492 25.997 8304.6438 0.2080 B- -7102# 197# 124 920815.931 27.909 + 9 67 58 125 Ce x -66658# 196# 8242# 2# B- -8587# 358# 124 928440# 210# + 7 66 59 125 Pr x -58070# 300# 8167# 2# B- -10001# 500# 124 937659# 322# + 5 65 60 125 Nd x -48070# 400# 8080# 3# B- * 124 948395# 429# +0 36 81 45 126 Rh x -37200# 500# 8087# 4# B- 14590# 640# 125 960064# 537# + 34 80 46 126 Pd x -51790# 400# 8197# 3# B- 8930# 447# 125 944401# 429# + 32 79 47 126 Ag x -60720# 200# 8261# 2# B- 11535# 200# 125 934814# 215# + 30 78 48 126 Cd -72255.727 2.304 8346.7393 0.0183 B- 5553.6500 4.7831 125 922430.290 2.473 + 28 77 49 126 In x -77809.377 4.192 8384.6067 0.0333 B- 8205.7585 11.4802 125 916468.202 4.500 + 26 76 50 126 Sn -nn -86015.135 10.688 8443.5227 0.0848 B- 378.0000 30.0000 125 907658.958 11.473 + 24 75 51 126 Sb - -86393.135 31.847 8440.3136 0.2528 B- 3671.0321 31.8223 125 907253.158 34.189 + 22 74 52 126 Te -90064.168 1.354 8463.2397 0.0107 B- -2153.6712 3.6717 125 903312.144 1.453 + 20 73 53 126 I -87910.496 3.778 8439.9379 0.0300 B- 1235.8904 3.7779 125 905624.205 4.055 + 18 72 54 126 Xe -89146.38687 0.00562 8443.5375 0.0003 B- -4795.7039 10.3587 125 904297.422 0.006 + 16 71 55 126 Cs -84350.683 10.359 8399.2673 0.0822 B- -1680.7697 16.2322 125 909445.821 11.120 + 14 70 56 126 Ba x -82669.913 12.497 8379.7187 0.0992 B- -7696.4376 91.3663 125 911250.202 13.416 + 12 69 57 126 La x -74973.476 90.508 8312.4268 0.7183 B- -4152.9106 94.7235 125 919512.667 97.163 + 10 68 58 126 Ce x -70820.565 27.945 8273.2581 0.2218 B- -10497# 198# 125 923971.000 30.000 + 8 67 59 126 Pr x -60324# 196# 8184# 2# B- -6943# 358# 125 935240# 210# + 6 66 60 126 Nd x -53380# 300# 8122# 2# B- -13631# 583# 125 942694# 322# + 4 65 61 126 Pm x -39750# 500# 8008# 4# B- * 125 957327# 537# +0 37 82 45 127 Rh x -33730# 600# 8060# 5# B- 13490# 781# 126 963789# 644# + 35 81 46 127 Pd x -47220# 500# 8160# 4# B- 11429# 539# 126 949307# 537# + 33 80 47 127 Ag x -58650# 200# 8244# 2# B- 10092# 200# 126 937037# 215# + 31 79 48 127 Cd x -68741.199 6.200 8316.8971 0.0488 B- 8138.6978 11.7675 126 926203.291 6.656 + 29 78 49 127 In -76879.897 10.001 8374.8212 0.0788 B- 6589.6810 12.0260 126 917466.040 10.736 + 27 77 50 127 Sn -83469.578 9.226 8420.5482 0.0726 B- 3228.7160 10.1668 126 910391.726 9.904 + 25 76 51 127 Sb -86698.294 5.083 8439.8110 0.0400 B- 1582.2030 4.9102 126 906925.557 5.457 + 23 75 52 127 Te -88280.497 1.365 8446.1090 0.0108 B- 702.7199 3.5652 126 905226.993 1.465 + 21 74 53 127 I -88983.217 3.621 8445.4820 0.0285 B- -662.3336 2.0442 126 904472.592 3.887 + 19 73 54 127 Xe -88320.883 4.088 8434.1066 0.0322 B- -2080.8562 6.4115 126 905183.636 4.388 + 17 72 55 127 Cs -86240.027 5.578 8411.5617 0.0439 B- -3422.0719 12.6525 126 907417.527 5.987 + 15 71 56 127 Ba -82817.955 11.357 8378.4560 0.0894 B- -4921.8386 27.7403 126 911091.272 12.192 + 13 70 57 127 La -77896.116 26.000 8333.5412 0.2047 B- -5916.7727 38.8567 126 916375.083 27.912 + 11 69 58 127 Ce x -71979.344 28.876 8280.7922 0.2274 B- -7436# 198# 126 922727.000 31.000 + 9 68 59 127 Pr x -64543# 196# 8216# 2# B- -8633# 358# 126 930710# 210# + 7 67 60 127 Nd x -55910# 300# 8142# 2# B- -10600# 500# 126 939978# 322# + 5 66 61 127 Pm x -45310# 400# 8052# 3# B- * 126 951358# 429# +0 38 83 45 128 Rh x -27340# 300# 8010# 2# B- 17050# 583# 127 970649# 322# + 36 82 46 128 Pd x -44390# 500# 8137# 4# B- 10320# 583# 127 952345# 537# + 34 81 47 128 Ag x -54710# 300# 8211# 2# B- 12528# 300# 127 941266# 322# + 32 80 48 128 Cd -67238.245 6.432 8303.2367 0.0503 B- 6951.8716 6.5665 127 927816.778 6.905 + 30 79 49 128 In x -74190.117 1.322 8351.4361 0.0103 B- 9171.3131 17.7194 127 920353.637 1.419 + 28 78 50 128 Sn -83361.430 17.682 8416.9749 0.1381 B- 1268.4219 13.3175 127 910507.828 18.982 + 26 77 51 128 Sb IT -84629.852 18.788 8420.7724 0.1468 B- 4363.9419 18.7862 127 909146.121 20.169 + 24 76 52 128 Te -88993.794 0.706 8448.7536 0.0055 B- -1255.7634 3.6807 127 904461.237 0.758 + 22 75 53 128 I -87738.030 3.621 8432.8309 0.0283 B- 2122.5041 3.6211 127 905809.355 3.887 + 20 74 54 128 Xe -89860.53427 0.00520 8443.3008 0.0003 B- -3928.7617 5.3762 127 903530.75341 0.00558 + 18 73 55 128 Cs -85931.773 5.376 8406.4953 0.0420 B- -562.6171 5.6122 127 907748.452 5.771 + 16 72 56 128 Ba -85369.156 1.610 8395.9878 0.0126 B- -6743.7167 54.4716 127 908352.446 1.728 + 14 71 57 128 La x -78625.439 54.448 8337.1904 0.4254 B- -3091.5136 61.2003 127 915592.123 58.452 + 12 70 58 128 Ce x -75533.925 27.945 8306.9259 0.2183 B- -9203.1617 40.8585 127 918911.000 30.000 + 10 69 59 128 Pr x -66330.764 29.808 8228.9141 0.2329 B- -5800# 202# 127 928791.000 32.000 + 8 68 60 128 Nd x -60530# 200# 8177# 2# B- -12311# 361# 127 935018# 215# + 6 67 61 128 Pm x -48220# 300# 8075# 2# B- -9070# 583# 127 948234# 322# + 4 66 62 128 Sm x -39150# 500# 7998# 4# B- * 127 957971# 537# +0 37 83 46 129 Pd x -37880# 600# 8086# 5# B- 13990# 721# 128 959334# 644# + 35 82 47 129 Ag x -51870# 400# 8188# 3# B- 11252# 400# 128 944315# 429# + 33 81 48 129 Cd x -63122.142 5.310 8269.5311 0.0412 B- 9712.7471 5.6637 128 932235.597 5.700 + 31 80 49 129 In -72834.889 1.971 8338.7590 0.0153 B- 7755.7081 17.2376 128 921808.534 2.116 + 29 79 50 129 Sn -80590.597 17.270 8392.8161 0.1339 B- 4038.7874 27.3634 128 913482.440 18.540 + 27 78 51 129 Sb + -84629.384 21.225 8418.0598 0.1645 B- 2375.5000 21.2132 128 909146.623 22.786 + 25 77 52 129 Te -87004.884 0.711 8430.4098 0.0055 B- 1502.2919 3.1358 128 906596.419 0.763 + 23 76 53 129 I -88507.176 3.153 8435.9908 0.0244 B- 188.8936 3.1534 128 904983.643 3.385 + 21 75 54 129 Xe -88696.06975 0.00505 8431.3904 0.0003 B- -1197.0197 4.5532 128 904780.85742 0.00542 + 19 74 55 129 Cs -87499.050 4.553 8416.0465 0.0353 B- -2438.1843 10.5627 128 906065.910 4.888 + 17 73 56 129 Ba -85060.866 10.504 8391.0811 0.0814 B- -3737.3247 21.6280 128 908683.409 11.276 + 15 72 57 129 La -81323.541 21.343 8356.0449 0.1655 B- -5036.0370 35.1633 128 912695.592 22.913 + 13 71 58 129 Ce x -76287.504 27.945 8310.9411 0.2166 B- -6513.9383 40.8585 128 918102.000 30.000 + 11 70 59 129 Pr x -69773.566 29.808 8254.3808 0.2311 B- -7399# 204# 128 925095.000 32.000 + 9 69 60 129 Nd ep -62375# 202# 8191# 2# B- -9195# 362# 128 933038# 217# + 7 68 61 129 Pm x -53180# 300# 8114# 2# B- -10850# 583# 128 942909# 322# + 5 67 62 129 Sm x -42330# 500# 8023# 4# B- * 128 954557# 537# +0 38 84 46 130 Pd x -32730# 300# 8046# 2# B- 13168# 520# 129 964863# 322# + 36 83 47 130 Ag -nn -45898# 424# 8142# 3# B- 15220# 425# 129 950727# 455# + 34 82 48 130 Cd x -61117.597 22.356 8252.5868 0.1720 B- 8788.9322 22.4274 129 934387.563 24.000 + 32 81 49 130 In -69906.530 1.790 8314.1760 0.0138 B- 10225.6870 2.5905 129 924952.257 1.921 + 30 80 50 130 Sn -80132.217 1.873 8386.8170 0.0144 B- 2153.4702 14.1129 129 913974.531 2.010 + 28 79 51 130 Sb -82285.687 14.212 8397.3641 0.1093 B- 5067.2728 14.2124 129 911662.686 15.257 + 26 78 52 130 Te -87352.960 0.011 8430.3251 0.0003 B- -416.7716 3.1537 129 906222.745 0.011 + 24 77 53 130 I -n -86936.188 3.154 8421.1011 0.0243 B- 2944.2864 3.1537 129 906670.168 3.385 + 22 76 54 130 Xe -89880.474 0.009 8437.7314 0.0003 B- -2980.7199 8.3567 129 903509.346 0.010 + 20 75 55 130 Cs -86899.754 8.357 8408.7848 0.0643 B- 357.0219 8.3617 129 906709.281 8.971 + 18 74 56 130 Ba -87256.776 0.287 8405.5130 0.0022 B- -5629.4021 25.9477 129 906326.002 0.308 + 16 73 57 130 La x -81627.374 25.946 8356.1919 0.1996 B- -2204.4611 38.1328 129 912369.413 27.854 + 14 72 58 130 Ce x -79422.913 27.945 8333.2164 0.2150 B- -8247.4488 70.0853 129 914736.000 30.000 + 12 71 59 130 Pr x -71175.464 64.273 8263.7565 0.4944 B- -4579.2250 70.0853 129 923590.000 69.000 + 10 70 60 130 Nd x -66596.239 27.945 8222.5136 0.2150 B- -11127# 202# 129 928506.000 30.000 + 8 69 61 130 Pm x -55470# 200# 8131# 2# B- -7770# 447# 129 940451# 215# + 6 68 62 130 Sm x -47700# 400# 8065# 3# B- -14187# 671# 129 948792# 429# + 4 67 63 130 Eu -p -33513# 539# 7950# 4# B- * 129 964022# 578# +0 39 85 46 131 Pd x -25740# 300# 7993# 2# B- 15010# 583# 130 972367# 322# + 37 84 47 131 Ag x -40750# 500# 8102# 4# B- 14462# 501# 130 956253# 537# + 35 83 48 131 Cd -55211.760 19.238 8206.1204 0.1469 B- 12812.6089 19.3644 130 940727.740 20.653 + 33 82 49 131 In -68024.369 2.205 8297.9544 0.0168 B- 9240.2095 4.2397 130 926972.839 2.367 + 31 81 50 131 Sn -77264.579 3.621 8362.5183 0.0276 B- 4716.8328 3.9621 130 917053.067 3.887 + 29 80 51 131 Sb -81981.412 2.084 8392.5525 0.0159 B- 3229.6099 2.0845 130 911989.339 2.236 + 27 79 52 131 Te -n -85211.022 0.061 8411.2339 0.0005 B- 2231.7057 0.6077 130 908522.210 0.065 + 25 78 53 131 I + -87442.727 0.605 8422.2977 0.0046 B- 970.8477 0.6046 130 906126.375 0.649 + 23 77 54 131 Xe -88413.57492 0.00512 8423.7367 0.0003 B- -358.0009 0.1771 130 905084.12808 0.00549 + 21 76 55 131 Cs +nn -88055.574 0.177 8415.0317 0.0014 B- -1376.6158 0.4515 130 905468.457 0.190 + 19 75 56 131 Ba -n -86678.958 0.415 8398.5511 0.0032 B- -2909.6936 27.9479 130 906946.315 0.445 + 17 74 57 131 La x -83769.265 27.945 8370.3676 0.2133 B- -4060.8167 43.0918 130 910070.000 30.000 + 15 73 58 131 Ce -79708.448 32.802 8333.3969 0.2504 B- -5407.7842 55.4462 130 914429.465 35.214 + 13 72 59 131 Pr -74300.664 46.995 8286.1439 0.3587 B- -6532.6235 53.0809 130 920234.960 50.451 + 11 71 60 131 Nd -67768.040 27.517 8230.3045 0.2101 B- -7998# 202# 130 927248.020 29.541 + 9 70 61 131 Pm x -59770# 200# 8163# 2# B- -9490# 447# 130 935834# 215# + 7 69 62 131 Sm x -50280# 400# 8085# 3# B- -10816# 565# 130 946022# 429# + 5 68 63 131 Eu -p -39464# 400# 7996# 3# B- * 130 957634# 429# +0 38 85 47 132 Ag x -34400# 500# 8053# 4# B- 16065# 504# 131 963070# 537# + 36 84 48 132 Cd x -50465.429 60.068 8169.1421 0.4551 B- 11946.1243 84.9236 131 945823.136 64.485 + 34 83 49 132 In + -62411.554 60.033 8253.7162 0.4548 B- 14135.0000 60.0000 131 932998.444 64.447 + 32 82 50 132 Sn -76546.554 1.976 8354.8726 0.0150 B- 3088.7280 3.1606 131 917823.898 2.121 + 30 81 51 132 Sb -79635.282 2.467 8372.3452 0.0187 B- 5552.9155 4.2708 131 914508.013 2.648 + 28 80 52 132 Te -85188.197 3.486 8408.4859 0.0264 B- 515.3046 3.4830 131 908546.713 3.742 + 26 79 53 132 I -85703.502 4.065 8406.4628 0.0308 B- 3575.4729 4.0654 131 907993.511 4.364 + 24 78 54 132 Xe -89278.97451 0.00507 8427.6229 0.0003 B- -2126.2813 1.0359 131 904155.08346 0.00544 + 22 77 55 132 Cs -87152.693 1.036 8405.5878 0.0079 B- 1282.2099 1.4773 131 906437.740 1.112 + 20 76 56 132 Ba -88434.903 1.053 8409.3747 0.0080 B- -4711.3256 36.3537 131 905061.231 1.130 + 18 75 57 132 La -83723.578 36.359 8367.7559 0.2754 B- -1254.8898 41.7025 131 910119.047 39.032 + 16 74 58 132 Ce -82468.688 20.407 8352.3223 0.1546 B- -7241.2240 35.3594 131 911466.226 21.907 + 14 73 59 132 Pr x -75227.464 28.876 8291.5377 0.2188 B- -3801.6487 37.6795 131 919240.000 31.000 + 12 72 60 132 Nd x -71425.815 24.205 8256.8104 0.1834 B- -9798# 151# 131 923321.237 25.985 + 10 71 61 132 Pm x -61628# 149# 8177# 1# B- -6488# 335# 131 933840# 160# + 8 70 62 132 Sm x -55140# 300# 8122# 2# B- -12939# 500# 131 940805# 322# + 6 69 63 132 Eu x -42200# 400# 8018# 3# B- * 131 954696# 429# +0 39 86 47 133 Ag x -29080# 500# 8013# 4# B- 15059# 539# 132 968781# 537# + 37 85 48 133 Cd x -44140# 200# 8121# 2# B- 13550# 283# 132 952614# 215# + 35 84 49 133 In x -57690# 200# 8217# 2# B- 13184# 200# 132 938067# 215# + 33 83 50 133 Sn -70873.890 1.904 8310.0890 0.0143 B- 8049.6228 3.6617 132 923913.753 2.043 + 31 82 51 133 Sb -78923.513 3.128 8364.7302 0.0235 B- 4013.6198 3.5179 132 915272.128 3.357 + 29 81 52 133 Te -82937.133 2.066 8389.0255 0.0155 B- 2920.1690 6.2531 132 910963.330 2.218 + 27 80 53 133 I -85857.302 5.902 8405.0993 0.0444 B- 1786.2812 6.3712 132 907828.400 6.335 + 25 79 54 133 Xe + -87643.583 2.400 8412.6477 0.0180 B- 427.3600 2.4000 132 905910.748 2.576 + 23 78 55 133 Cs -88070.943 0.008 8409.9786 0.0003 B- -517.4310 0.9920 132 905451.958 0.008 + 21 77 56 133 Ba -87553.512 0.992 8400.2059 0.0075 B- -2059.1203 27.9624 132 906007.443 1.065 + 19 76 57 133 La x -85494.392 27.945 8378.8415 0.2101 B- -3076.1685 32.3786 132 908218.000 30.000 + 17 75 58 133 Ce x -82418.223 16.354 8349.8301 0.1230 B- -4480.6319 20.5826 132 911520.402 17.557 + 15 74 59 133 Pr x -77937.591 12.497 8310.2588 0.0940 B- -5605.2112 48.2223 132 916330.558 13.416 + 13 73 60 133 Nd x -72332.380 46.575 8262.2320 0.3502 B- -6924.7272 68.5519 132 922348.000 50.000 + 11 72 61 133 Pm x -65407.653 50.301 8204.2841 0.3782 B- -8177# 302# 132 929782.000 54.000 + 9 71 62 133 Sm x -57231# 298# 8137# 2# B- -9995# 422# 132 938560# 320# + 7 70 63 133 Eu x -47236# 298# 8056# 2# B- -11176# 582# 132 949290# 320# + 5 69 64 133 Gd x -36060# 500# 7966# 4# B- * 132 961288# 537# +0 38 86 48 134 Cd x -39460# 300# 8086# 2# B- 12510# 361# 133 957638# 322# + 36 85 49 134 In x -51970# 200# 8173# 1# B- 14464# 200# 133 944208# 215# + 34 84 50 134 Sn x -66433.759 3.167 8275.1719 0.0236 B- 7585.2453 4.4136 133 928680.430 3.400 + 32 83 51 134 Sb x -74019.004 3.074 8325.9398 0.0229 B- 8514.7483 4.1221 133 920537.334 3.300 + 30 82 52 134 Te -82533.752 2.746 8383.6442 0.0205 B- 1509.6875 4.9335 133 911396.376 2.948 + 28 81 53 134 I -84043.440 4.857 8389.0722 0.0362 B- 4082.3946 4.8567 133 909775.660 5.213 + 26 80 54 134 Xe -88125.83443 0.00577 8413.6994 0.0003 B- -1234.6691 0.0160 133 905393.030 0.006 + 24 79 55 134 Cs -86891.165 0.016 8398.6470 0.0003 B- 2058.8368 0.2508 133 906718.501 0.017 + 22 78 56 134 Ba -88950.002 0.251 8408.1731 0.0019 B- -3731.3434 19.9312 133 904508.249 0.269 + 20 77 57 134 La x -85218.659 19.930 8374.4888 0.1487 B- -385.7605 28.5098 133 908514.011 21.395 + 18 76 58 134 Ce x -84832.898 20.387 8365.7716 0.1521 B- -6304.8987 28.7814 133 908928.142 21.886 + 16 75 59 134 Pr x -78528.000 20.316 8312.8817 0.1516 B- -2881.5569 23.5032 133 915696.729 21.810 + 14 74 60 134 Nd x -75646.443 11.817 8285.5391 0.0882 B- -8882.5343 43.5512 133 918790.207 12.686 + 12 73 61 134 Pm x -66763.908 41.917 8213.4131 0.3128 B- -5388# 200# 133 928326.000 45.000 + 10 72 62 134 Sm x -61376# 196# 8167# 1# B- -11576# 358# 133 934110# 210# + 8 71 63 134 Eu x -49800# 300# 8075# 2# B- -8271# 500# 133 946537# 322# + 6 70 64 134 Gd x -41530# 400# 8008# 3# B- * 133 955416# 429# +0 39 87 48 135 Cd x -32820# 400# 8036# 3# B- 14290# 500# 134 964766# 429# + 37 86 49 135 In x -47110# 300# 8136# 2# B- 13522# 300# 134 949425# 322# + 35 85 50 135 Sn x -60632.252 3.074 8230.6877 0.0228 B- 9058.0800 4.0522 134 934908.603 3.300 + 33 84 51 135 Sb -69690.332 2.640 8291.9894 0.0196 B- 8038.4581 3.1524 134 925184.354 2.834 + 31 83 52 135 Te -77728.790 1.722 8345.7384 0.0128 B- 6050.3894 2.6850 134 916554.715 1.848 + 29 82 53 135 I -83779.180 2.060 8384.7609 0.0153 B- 2634.1851 3.8284 134 910059.355 2.211 + 27 81 54 135 Xe -86413.365 3.668 8398.4783 0.0272 B- 1168.5917 3.6623 134 907231.441 3.938 + 25 80 55 135 Cs -87581.956 0.364 8401.3393 0.0027 B- 268.6983 0.2862 134 905976.907 0.390 + 23 79 56 135 Ba -87850.655 0.245 8397.5345 0.0018 B- -1207.1973 9.4299 134 905688.447 0.263 + 21 78 57 135 La -86643.458 9.432 8382.7972 0.0699 B- -2027.1499 4.6101 134 906984.427 10.126 + 19 77 58 135 Ce -84616.308 10.266 8361.9861 0.0760 B- -3680.4357 15.6540 134 909160.662 11.021 + 17 76 59 135 Pr x -80935.872 11.817 8328.9284 0.0875 B- -4722.2522 22.4837 134 913111.772 12.686 + 15 75 60 135 Nd x -76213.620 19.128 8288.1536 0.1417 B- -6151.2907 85.0809 134 918181.318 20.534 + 13 74 61 135 Pm x -70062.329 82.903 8236.7933 0.6141 B- -7205.1069 175.4501 134 924785.000 89.000 + 11 73 62 135 Sm x -62857.222 154.628 8177.6270 1.1454 B- -8709# 249# 134 932520.000 166.000 + 9 72 63 135 Eu x -54148# 196# 8107# 1# B- -9898# 445# 134 941870# 210# + 7 71 64 135 Gd x -44250# 400# 8028# 3# B- -11197# 565# 134 952496# 429# + 5 70 65 135 Tb -p -33053# 400# 7939# 3# B- * 134 964516# 429# +0 38 87 49 136 In x -40970# 300# 8091# 2# B- 15200# 361# 135 956017# 322# + 36 86 50 136 Sn x -56170# 200# 8197# 1# B- 8337# 200# 135 939699# 215# + 34 85 51 136 Sb -64506.890 5.830 8252.2533 0.0429 B- 9918.3897 6.2599 135 930749.009 6.258 + 32 84 52 136 Te -74425.279 2.281 8319.4301 0.0168 B- 5119.9455 14.1880 135 920101.180 2.448 + 30 83 53 136 I -79545.225 14.188 8351.3242 0.1043 B- 6883.9455 14.1880 135 914604.693 15.231 + 28 82 54 136 Xe -86429.170 0.007 8396.1889 0.0003 B- -90.3151 1.8730 135 907214.474 0.007 + 26 81 55 136 Cs + -86338.855 1.873 8389.7723 0.0138 B- 2548.2241 1.8570 135 907311.431 2.010 + 24 80 56 136 Ba -88887.079 0.245 8402.7566 0.0018 B- -2849.5915 53.1715 135 904575.800 0.262 + 22 79 57 136 La x -86037.488 53.171 8376.0512 0.3910 B- 471.0621 53.1720 135 907634.962 57.081 + 20 78 58 136 Ce -86508.550 0.324 8373.7624 0.0024 B- -5168.1290 11.4561 135 907129.256 0.348 + 18 77 59 136 Pr -81340.421 11.455 8330.0089 0.0842 B- -2141.1234 16.4578 135 912677.470 12.296 + 16 76 60 136 Nd x -79199.297 11.817 8308.5127 0.0869 B- -8029.3747 70.0764 135 914976.061 12.686 + 14 75 61 136 Pm x -71169.923 69.073 8243.7207 0.5079 B- -4359.0237 70.1942 135 923595.949 74.152 + 12 74 62 136 Sm x -66810.899 12.497 8205.9165 0.0919 B- -10567# 196# 135 928275.553 13.416 + 10 73 63 136 Eu x -56244# 196# 8122# 1# B- -7154# 357# 135 939620# 210# + 8 72 64 136 Gd x -49090# 298# 8064# 2# B- -13190# 582# 135 947300# 320# + 6 71 65 136 Tb x -35900# 500# 7961# 4# B- * 135 961460# 537# +0 39 88 49 137 In x -35830# 400# 8053# 3# B- 14320# 500# 136 961535# 429# + 37 87 50 137 Sn x -50150# 300# 8152# 2# B- 9911# 304# 136 946162# 322# + 35 86 51 137 Sb x -60060.392 52.164 8218.4764 0.3808 B- 9243.3698 52.2059 136 935522.519 56.000 + 33 85 52 137 Te -69303.762 2.100 8280.2357 0.0153 B- 7052.5063 8.6426 136 925599.354 2.254 + 31 84 53 137 I p-2n -76356.268 8.383 8326.0033 0.0612 B- 6027.1455 8.3841 136 918028.178 9.000 + 29 83 54 137 Xe -n -82383.414 0.104 8364.2865 0.0008 B- 4162.3582 0.3193 136 911557.771 0.111 + 27 82 55 137 Cs + -86545.772 0.302 8388.9581 0.0022 B- 1175.6285 0.1723 136 907089.296 0.324 + 25 81 56 137 Ba -87721.401 0.248 8391.8288 0.0018 B- -580.5356 1.6231 136 905827.207 0.266 + 23 80 57 137 La + -87140.865 1.640 8381.8807 0.0120 B- -1222.1000 1.6000 136 906450.438 1.760 + 21 79 58 137 Ce -85918.765 0.360 8367.2497 0.0026 B- -2716.9515 8.1328 136 907762.416 0.386 + 19 78 59 137 Pr -83201.814 8.135 8341.7074 0.0594 B- -3617.8447 14.2706 136 910679.183 8.733 + 17 77 60 137 Nd -79583.969 11.725 8309.5892 0.0856 B- -5511.1108 17.5366 136 914563.099 12.586 + 15 76 61 137 Pm x -74072.858 13.041 8263.6516 0.0952 B- -6081.2029 31.4460 136 920479.519 14.000 + 13 75 62 137 Sm -67991.655 28.614 8213.5527 0.2089 B- -7845.7518 28.9474 136 927007.959 30.718 + 11 74 63 137 Eu x -60145.904 4.378 8150.5738 0.0320 B- -8932# 298# 136 935430.719 4.700 + 9 73 64 137 Gd x -51214# 298# 8080# 2# B- -10246# 499# 136 945020# 320# + 7 72 65 137 Tb x -40967# 401# 7999# 3# B- * 136 956020# 430# +0 38 88 50 138 Sn x -45510# 400# 8118# 3# B- 9140# 500# 137 951143# 429# + 36 87 51 138 Sb x -54650# 300# 8178# 2# B- 11046# 300# 137 941331# 322# + 34 86 52 138 Te -65695.995 3.787 8252.5786 0.0274 B- 6283.9149 7.0625 137 929472.452 4.065 + 32 85 53 138 I x -71979.910 5.962 8292.4450 0.0432 B- 7992.3346 6.5881 137 922726.392 6.400 + 30 84 54 138 Xe -79972.244 2.804 8344.6913 0.0203 B- 2914.7839 9.5780 137 914146.268 3.010 + 28 83 55 138 Cs -82887.028 9.158 8360.1437 0.0664 B- 5374.7776 9.1584 137 911017.119 9.831 + 26 82 56 138 Ba -88261.806 0.249 8393.4222 0.0018 B- -1748.3977 0.3384 137 905247.059 0.267 + 24 81 57 138 La -86513.408 0.416 8375.0835 0.0030 B- 1052.4585 0.4018 137 907124.041 0.446 + 22 80 58 138 Ce -87565.867 0.499 8377.0408 0.0036 B- -4437.0000 10.0000 137 905994.180 0.536 + 20 79 59 138 Pr - -83128.867 10.012 8339.2195 0.0726 B- -1111.6847 15.3256 137 910757.495 10.748 + 18 78 60 138 Nd -82017.182 11.603 8325.4946 0.0841 B- -7102.8119 16.0995 137 911950.938 12.456 + 16 77 61 138 Pm -74914.370 11.603 8268.3558 0.0841 B- -3416.5976 16.5613 137 919576.119 12.456 + 14 76 62 138 Sm x -71497.772 11.817 8237.9286 0.0856 B- -9748.0968 30.3408 137 923243.988 12.686 + 12 75 63 138 Eu x -61749.676 27.945 8161.6211 0.2025 B- -6090# 202# 137 933709.000 30.000 + 10 74 64 138 Gd x -55660# 200# 8112# 1# B- -12059# 361# 137 940247# 215# + 8 73 65 138 Tb x -43600# 300# 8019# 2# B- -8669# 586# 137 953193# 322# + 6 72 66 138 Dy x -34931# 503# 7950# 4# B- * 137 962500# 540# +0 39 89 50 139 Sn x -39310# 400# 8073# 3# B- 10740# 565# 138 957799# 429# + 37 88 51 139 Sb x -50050# 400# 8144# 3# B- 10155# 400# 138 946269# 429# + 35 87 52 139 Te x -60205.080 3.540 8211.7716 0.0255 B- 8265.8835 5.3454 138 935367.191 3.800 + 33 86 53 139 I x -68470.964 4.005 8265.6100 0.0288 B- 7173.6224 4.5424 138 926493.400 4.300 + 31 85 54 139 Xe x -75644.586 2.142 8311.5904 0.0154 B- 5056.5023 3.7960 138 918792.200 2.300 + 29 84 55 139 Cs + -80701.088 3.134 8342.3397 0.0225 B- 4212.8293 3.1235 138 913363.822 3.364 + 27 83 56 139 Ba -n -84913.918 0.253 8367.0194 0.0018 B- 2308.4632 0.6571 138 908841.164 0.271 + 25 82 57 139 La -87222.381 0.607 8377.9987 0.0044 B- -264.6396 1.9989 138 906362.927 0.651 + 23 81 58 139 Ce -86957.741 2.089 8370.4664 0.0150 B- -2129.0890 2.9962 138 906647.029 2.242 + 21 80 59 139 Pr -84828.652 3.649 8349.5208 0.0263 B- -2811.7226 27.6166 138 908932.700 3.917 + 19 79 60 139 Nd -82016.930 27.521 8323.6642 0.1980 B- -4515.9014 25.8700 138 911951.208 29.545 + 17 78 61 139 Pm -77501.028 13.588 8285.5473 0.0978 B- -5120.7993 17.4098 138 916799.228 14.587 + 15 77 62 139 Sm x -72380.229 10.884 8243.0786 0.0783 B- -6982.1777 17.0705 138 922296.631 11.684 + 13 76 63 139 Eu x -65398.051 13.151 8187.2187 0.0946 B- -7767# 196# 138 929792.307 14.117 + 11 75 64 139 Gd x -57632# 196# 8126# 1# B- -9501# 357# 138 938130# 210# + 9 74 65 139 Tb x -48130# 298# 8052# 2# B- -10430# 582# 138 948330# 320# + 7 73 66 139 Dy x -37700# 500# 7971# 4# B- * 138 959527# 537# +0 40 90 50 140 Sn x -34490# 300# 8038# 2# B- 9900# 671# 139 962973# 322# + 38 89 51 140 Sb x -44390# 600# 8103# 4# B- 11977# 600# 139 952345# 644# + 36 88 52 140 Te -56367.449 14.377 8183.3567 0.1027 B- 7238.7734 18.7976 139 939487.057 15.434 + 34 87 53 140 I x -63606.223 12.109 8229.4740 0.0865 B- 9380.2388 12.3313 139 931715.914 13.000 + 32 86 54 140 Xe x -72986.461 2.329 8290.8875 0.0166 B- 4063.2768 8.5232 139 921645.814 2.500 + 30 85 55 140 Cs -77049.738 8.199 8314.3227 0.0586 B- 6218.1669 9.8671 139 917283.707 8.801 + 28 84 56 140 Ba -83267.905 7.900 8353.1500 0.0564 B- 1044.1542 7.9051 139 910608.231 8.480 + 26 83 57 140 La -84312.059 0.607 8355.0201 0.0043 B- 3762.1676 1.3364 139 909487.285 0.651 + 24 82 58 140 Ce -88074.227 1.313 8376.3045 0.0094 B- -3388.0000 6.0000 139 905448.433 1.409 + 22 81 59 140 Pr - -84686.227 6.142 8346.5163 0.0439 B- -428.9806 6.9536 139 909085.600 6.593 + 20 80 60 140 Nd x -84257.246 3.260 8337.8640 0.0233 B- -6045.2000 24.0000 139 909546.130 3.500 + 18 79 61 140 Pm - -78212.046 24.220 8289.0958 0.1730 B- -2756.1010 27.2546 139 916035.918 26.001 + 16 78 62 140 Sm x -75455.945 12.497 8263.8211 0.0893 B- -8470.0000 50.0000 139 918994.714 13.416 + 14 77 63 140 Eu - -66985.945 51.538 8197.7330 0.3681 B- -5203.6675 58.6268 139 928087.633 55.328 + 12 76 64 140 Gd x -61782.278 27.945 8154.9757 0.1996 B- -11300.0000 800.0000 139 933674.000 30.000 + 10 75 65 140 Tb - -50482.278 800.488 8068.6732 5.7178 B- -7652# 895# 139 945805.048 859.359 + 8 74 66 140 Dy x -42830# 401# 8008# 3# B- -13513# 641# 139 954020# 430# + 6 73 67 140 Ho -p -29317# 500# 7906# 4# B- * 139 968526# 537# +0 39 90 51 141 Sb x -39540# 500# 8069# 4# B- 11129# 640# 140 957552# 537# + 37 89 52 141 Te x -50670# 400# 8142# 3# B- 9257# 400# 140 945604# 429# + 35 88 53 141 I x -59926.666 15.835 8202.2562 0.1123 B- 8270.6430 16.0965 140 935666.081 17.000 + 33 87 54 141 Xe x -68197.309 2.888 8255.3647 0.0205 B- 6280.0423 9.6378 140 926787.181 3.100 + 31 86 55 141 Cs -74477.351 9.195 8294.3554 0.0652 B- 5255.1410 9.6174 140 920045.279 9.871 + 29 85 56 141 Ba -79732.492 5.318 8326.0774 0.0377 B- 3197.3515 6.5510 140 914403.653 5.709 + 27 84 57 141 La -82929.844 4.127 8343.2050 0.0293 B- 2501.2141 3.9279 140 910971.155 4.430 + 25 83 58 141 Ce -85431.058 1.315 8355.3956 0.0093 B- 583.4758 1.1784 140 908285.991 1.411 + 23 82 59 141 Pr -86014.533 1.498 8353.9852 0.0106 B- -1823.0137 2.8090 140 907659.604 1.607 + 21 81 60 141 Nd - -84191.520 3.183 8335.5074 0.0226 B- -3668.5879 14.3304 140 909616.690 3.417 + 19 80 61 141 Pm x -80522.932 13.972 8303.9405 0.0991 B- -4588.9724 16.3730 140 913555.081 15.000 + 17 79 62 141 Sm -75933.959 8.535 8265.8460 0.0605 B- -6008.3127 14.2829 140 918481.545 9.162 + 15 78 63 141 Eu -69925.647 12.639 8217.6853 0.0896 B- -6701.4161 23.4562 140 924931.734 13.568 + 13 77 64 141 Gd x -63224.231 19.760 8164.6090 0.1401 B- -8683.3880 107.0975 140 932126.000 21.213 + 11 76 65 141 Tb x -54540.843 105.259 8097.4761 0.7465 B- -9158# 316# 140 941448.000 113.000 + 9 75 66 141 Dy x -45382# 298# 8027# 2# B- -11018# 499# 140 951280# 320# + 7 74 67 141 Ho -p -34364# 401# 7943# 3# B- * 140 963108# 430# +0 40 91 51 142 Sb x -33610# 300# 8027# 2# B- 12939# 583# 141 963918# 322# + 38 90 52 142 Te x -46550# 500# 8113# 4# B- 8253# 500# 141 950027# 537# + 36 89 53 142 I x -54802.969 4.937 8165.2517 0.0348 B- 10426.6792 5.6276 141 941166.595 5.300 + 34 88 54 142 Xe x -65229.648 2.701 8233.1695 0.0190 B- 5284.9078 7.5655 141 929973.095 2.900 + 32 87 55 142 Cs -70514.556 7.067 8264.8777 0.0498 B- 7327.7007 8.3627 141 924299.514 7.586 + 30 86 56 142 Ba -77842.257 5.920 8310.9718 0.0417 B- 2181.6932 8.3754 141 916432.904 6.355 + 28 85 57 142 La -80023.950 6.286 8320.8263 0.0443 B- 4508.9455 5.8446 141 914090.760 6.748 + 26 84 58 142 Ce -84532.896 2.443 8347.0700 0.0172 B- -746.5288 2.4868 141 909250.208 2.623 + 24 83 59 142 Pr -83786.367 1.498 8336.3032 0.0106 B- 2163.6885 1.3656 141 910051.640 1.607 + 22 82 60 142 Nd -85950.055 1.256 8346.0310 0.0088 B- -4808.5196 23.6216 141 907728.824 1.348 + 20 81 61 142 Pm -81141.536 23.596 8306.6587 0.1662 B- -2159.6062 23.6524 141 912890.982 25.330 + 18 80 62 142 Sm -78981.930 1.866 8285.9407 0.0131 B- -7673.0000 30.0000 141 915209.415 2.002 + 16 79 63 142 Eu - -71308.930 30.058 8226.3960 0.2117 B- -4349.4074 41.0414 141 923446.719 32.268 + 14 78 64 142 Gd x -66959.522 27.945 8190.2569 0.1968 B- -10400.0000 700.0000 141 928116.000 30.000 + 12 77 65 142 Tb - -56559.522 700.558 8111.5080 4.9335 B- -6440# 200# 141 939280.858 752.079 + 10 76 66 142 Dy - -50120# 729# 8061# 5# B- -12869# 831# 141 946194# 782# + 8 75 67 142 Ho x -37250# 401# 7965# 3# B- -9321# 641# 141 960010# 430# + 6 74 68 142 Er x -27930# 500# 7893# 4# B- * 141 970016# 537# +0 39 91 52 143 Te x -40530# 500# 8070# 3# B- 10259# 539# 142 956489# 537# + 37 90 53 143 I x -50790# 200# 8137# 1# B- 9413# 200# 142 945475# 215# + 35 89 54 143 Xe x -60202.882 4.657 8196.8855 0.0326 B- 7472.6365 8.8908 142 935369.550 5.000 + 33 88 55 143 Cs -67675.519 7.573 8243.6707 0.0530 B- 6261.6865 9.7303 142 927347.346 8.130 + 31 87 56 143 Ba -73937.205 6.756 8281.9878 0.0472 B- 4234.2623 9.9682 142 920625.149 7.253 + 29 86 57 143 La -78171.467 7.329 8306.1271 0.0513 B- 3434.9108 7.5812 142 916079.482 7.868 + 27 85 58 143 Ce -81606.378 2.442 8324.6765 0.0171 B- 1461.8214 1.8649 142 912391.953 2.621 + 25 84 59 143 Pr -83068.200 1.816 8329.4280 0.0127 B- 934.1107 1.3673 142 910822.624 1.949 + 23 83 60 143 Nd -84002.310 1.255 8330.4893 0.0088 B- -1041.6463 2.6830 142 909819.815 1.347 + 21 82 61 143 Pm -82960.664 2.944 8317.7341 0.0206 B- -3443.5291 3.5604 142 910938.068 3.160 + 19 81 62 143 Sm -79517.135 2.750 8288.1825 0.0192 B- -5275.8240 11.3245 142 914634.848 2.951 + 17 80 63 143 Eu x -74241.311 10.986 8245.8177 0.0768 B- -6010.0000 200.0000 142 920298.678 11.793 + 15 79 64 143 Gd - -68231.311 200.301 8198.3188 1.4007 B- -7812.1185 206.7497 142 926750.678 215.032 + 13 78 65 143 Tb x -60419.192 51.232 8138.2176 0.3583 B- -8250.2433 52.8659 142 935137.332 55.000 + 11 77 66 143 Dy x -52168.949 13.041 8075.0527 0.0912 B- -10121# 298# 142 943994.332 14.000 + 9 76 67 143 Ho x -42048# 298# 7999# 2# B- -10887# 499# 142 954860# 320# + 7 75 68 143 Er x -31160# 400# 7917# 3# B- * 142 966548# 429# +0 40 92 52 144 Te x -36220# 300# 8040# 2# B- 9110# 500# 143 961116# 322# + 38 91 53 144 I x -45330# 400# 8098# 3# B- 11542# 400# 143 951336# 429# + 36 90 54 144 Xe x -56872.301 5.310 8172.8845 0.0369 B- 6399.0606 20.8203 143 938945.076 5.700 + 34 89 55 144 Cs -63271.362 20.132 8211.8894 0.1398 B- 8495.7679 20.4163 143 932075.402 21.612 + 32 88 56 144 Ba -71767.130 7.136 8265.4549 0.0496 B- 3082.5300 14.7744 143 922954.821 7.661 + 30 87 57 144 La x -74849.660 12.937 8281.4283 0.0898 B- 5582.2823 13.2432 143 919645.589 13.888 + 28 86 58 144 Ce + -80431.942 2.833 8314.7612 0.0197 B- 318.6462 0.8321 143 913652.763 3.041 + 26 85 59 144 Pr + -80750.588 2.708 8311.5411 0.0188 B- 2997.4400 2.4000 143 913310.682 2.907 + 24 84 60 144 Nd -83748.028 1.255 8326.9237 0.0087 B- -2331.9117 2.6464 143 910092.798 1.346 + 22 83 61 144 Pm -81416.116 2.912 8305.2969 0.0202 B- 549.5096 2.6679 143 912596.208 3.126 + 20 82 62 144 Sm -81965.626 1.459 8303.6800 0.0101 B- -6346.4515 10.8092 143 912006.285 1.566 + 18 81 63 144 Eu -75619.175 10.787 8254.1744 0.0749 B- -3859.6633 29.9546 143 918819.481 11.580 + 16 80 64 144 Gd x -71759.511 27.945 8221.9382 0.1941 B- -9391.3235 39.5199 143 922963.000 30.000 + 14 79 65 144 Tb x -62368.188 27.945 8151.2877 0.1941 B- -5798.0965 28.8506 143 933045.000 30.000 + 12 78 66 144 Dy x -56570.091 7.173 8105.5902 0.0498 B- -11960.5706 11.1039 143 939269.512 7.700 + 10 77 67 144 Ho x -44609.521 8.477 8017.0977 0.0589 B- -8002# 196# 143 952109.712 9.100 + 8 76 68 144 Er x -36608# 196# 7956# 1# B- -14448# 445# 143 960700# 210# + 6 75 69 144 Tm -p -22159# 400# 7850# 3# B- * 143 976211# 429# +0 41 93 52 145 Te x -30010# 300# 7998# 2# B- 11120# 583# 144 967783# 322# + 39 92 53 145 I x -41130# 500# 8069# 3# B- 10363# 500# 144 955845# 537# + 37 91 54 145 Xe x -51493.337 11.178 8135.0877 0.0771 B- 8561.0867 14.3929 144 944719.631 12.000 + 35 90 55 145 Cs -60054.424 9.067 8188.7342 0.0625 B- 7461.7591 12.4121 144 935528.927 9.733 + 33 89 56 145 Ba x -67516.183 8.477 8234.7991 0.0585 B- 5319.1425 14.9122 144 927518.400 9.100 + 31 88 57 145 La -72835.325 12.269 8266.0873 0.0846 B- 4231.7331 35.2977 144 921808.065 13.170 + 29 87 58 145 Ce -77067.059 33.900 8289.8762 0.2338 B- 2558.9318 33.6347 144 917265.113 36.393 + 27 86 59 145 Pr -79625.990 7.149 8302.1285 0.0493 B- 1806.0140 7.0370 144 914517.987 7.674 + 25 85 60 145 Nd -81432.004 1.271 8309.1883 0.0088 B- -164.4982 2.5361 144 912579.151 1.364 + 23 84 61 145 Pm -81267.506 2.805 8302.6583 0.0193 B- -616.0990 2.5390 144 912755.748 3.011 + 21 83 62 145 Sm -80651.407 1.485 8293.0139 0.0102 B- -2659.8832 2.7224 144 913417.157 1.594 + 19 82 63 145 Eu -77991.524 3.060 8269.2744 0.0211 B- -5064.8984 19.9521 144 916272.659 3.285 + 17 81 64 145 Gd -72926.626 19.716 8228.9485 0.1360 B- -6526.9329 109.7144 144 921710.051 21.165 + 15 80 65 145 Tb -66399.693 110.896 8178.5397 0.7648 B- -8157.0853 111.0872 144 928717.001 119.051 + 13 79 66 145 Dy x -58242.607 6.520 8116.8884 0.0450 B- -9122.4943 9.9019 144 937473.992 7.000 + 11 78 67 145 Ho x -49120.113 7.452 8048.5792 0.0514 B- -9880# 200# 144 947267.392 8.000 + 9 77 68 145 Er x -39240# 200# 7975# 1# B- -11657# 280# 144 957874# 215# + 7 76 69 145 Tm -p -27583# 196# 7889# 1# B- * 144 970389# 210# +0 40 93 53 146 I x -35540# 300# 8031# 2# B- 12415# 301# 145 961846# 322# + 38 92 54 146 Xe x -47954.950 24.219 8110.4154 0.1659 B- 7355.4298 24.3911 145 948518.245 26.000 + 36 91 55 146 Cs x -55310.380 2.893 8155.4365 0.0198 B- 9555.8882 3.3918 145 940621.867 3.106 + 34 90 56 146 Ba x -64866.269 1.770 8215.5293 0.0121 B- 4354.9052 2.4366 145 930363.200 1.900 + 32 89 57 146 La -69221.174 1.675 8239.9988 0.0115 B- 6404.6947 14.7146 145 925688.017 1.797 + 30 88 58 146 Ce -75625.868 14.665 8278.5081 0.1004 B- 1047.6178 32.4842 145 918812.294 15.743 + 28 87 59 146 Pr -76673.486 34.356 8280.3250 0.2353 B- 4252.4300 34.3686 145 917687.630 36.882 + 26 86 60 146 Nd -80925.916 1.273 8304.0927 0.0087 B- -1471.5560 4.1194 145 913122.459 1.366 + 24 85 61 146 Pm + -79454.360 4.275 8288.6550 0.0293 B- 1542.0000 3.0000 145 914702.240 4.589 + 22 84 62 146 Sm -80996.360 3.045 8293.8581 0.0209 B- -3878.7573 5.8685 145 913046.835 3.269 + 20 83 63 146 Eu -77117.603 6.009 8261.9327 0.0412 B- -1031.7798 7.0750 145 917210.852 6.451 + 18 82 64 146 Gd -76085.823 4.076 8249.5072 0.0279 B- -8322.1791 44.7488 145 918318.513 4.376 + 16 81 65 146 Tb -67763.644 44.860 8187.1474 0.3073 B- -5208.7165 45.1580 145 927252.739 48.159 + 14 80 66 146 Dy -62554.928 6.695 8146.1128 0.0459 B- -11316.7007 9.3917 145 932844.526 7.187 + 12 79 67 146 Ho -51238.227 6.587 8063.2426 0.0451 B- -6916.2074 9.3987 145 944993.503 7.071 + 10 78 68 146 Er -44322.019 6.705 8010.5127 0.0459 B- -13267# 200# 145 952418.357 7.197 + 8 77 69 146 Tm -p -31055# 200# 7914# 1# B- * 145 966661# 215# +0 41 94 53 147 I x -31200# 300# 8001# 2# B- 11199# 361# 146 966505# 322# + 39 93 54 147 Xe x -42400# 200# 8072# 1# B- 9520# 200# 146 954482# 215# + 37 92 55 147 Cs x -51920.073 8.383 8131.8010 0.0570 B- 8343.9631 21.4535 146 944261.512 9.000 + 35 91 56 147 Ba x -60264.036 19.748 8183.2405 0.1343 B- 6414.3615 22.4660 146 935303.900 21.200 + 33 90 57 147 La x -66678.397 10.712 8221.5536 0.0729 B- 5335.5046 13.7248 146 928417.800 11.500 + 31 89 58 147 Ce -72013.902 8.580 8252.5274 0.0584 B- 3430.1913 15.5317 146 922689.900 9.211 + 29 88 59 147 Pr -75444.093 15.855 8270.5400 0.1079 B- 2702.7013 15.8571 146 919007.438 17.020 + 27 87 60 147 Nd -78146.794 1.275 8283.6036 0.0087 B- 895.1896 0.5664 146 916105.969 1.368 + 25 86 61 147 Pm -79041.984 1.288 8284.3712 0.0088 B- 224.0638 0.2940 146 915144.944 1.382 + 23 85 62 147 Sm -79266.048 1.262 8280.5734 0.0086 B- -1721.4367 2.2832 146 914904.401 1.354 + 21 84 63 147 Eu -77544.611 2.569 8263.5409 0.0175 B- -2187.6833 2.5273 146 916752.440 2.758 + 19 83 64 147 Gd -75356.928 1.887 8243.3366 0.0128 B- -4614.2543 8.1414 146 919101.014 2.025 + 17 82 65 147 Tb -70742.674 8.096 8206.6250 0.0551 B- -6546.6266 11.9939 146 924054.620 8.691 + 15 81 66 147 Dy x -64196.047 8.849 8156.7680 0.0602 B- -8438.9460 10.1644 146 931082.712 9.500 + 13 80 67 147 Ho -55757.101 5.001 8094.0381 0.0340 B- -9149.2869 38.5173 146 940142.293 5.368 + 11 79 68 147 Er x -46607.814 38.191 8026.4760 0.2598 B- -10633.4071 38.7987 146 949964.456 41.000 + 9 78 69 147 Tm -35974.407 6.839 7948.8178 0.0465 B- * 146 961379.887 7.341 +0 40 94 54 148 Xe x -38650# 300# 8047# 2# B- 8261# 300# 147 958508# 322# + 38 93 55 148 Cs x -46910.950 13.041 8097.5469 0.0881 B- 10633.9614 13.1258 147 949639.026 14.000 + 36 92 56 148 Ba x -57544.911 1.490 8164.1118 0.0101 B- 5163.8307 19.5252 147 938223.000 1.600 + 34 91 57 148 La x -62708.742 19.468 8193.7165 0.1315 B- 7689.6824 22.4573 147 932679.400 20.900 + 32 90 58 148 Ce -70398.424 11.195 8240.3876 0.0756 B- 2137.0282 12.5663 147 924424.186 12.017 + 30 89 59 148 Pr -72535.452 15.041 8249.5409 0.1016 B- 4872.6133 15.0858 147 922129.992 16.147 + 28 88 60 148 Nd -77408.066 2.053 8277.1778 0.0139 B- -542.1891 5.8755 147 916899.027 2.203 + 26 87 61 148 Pm +p -76865.877 5.690 8268.2283 0.0384 B- 2470.1898 5.6409 147 917481.091 6.108 + 24 86 62 148 Sm -79336.067 1.246 8279.6326 0.0084 B- -3038.5844 9.9657 147 914829.233 1.337 + 22 85 63 148 Eu -76297.482 9.961 8253.8155 0.0673 B- -28.0630 9.9633 147 918091.288 10.693 + 20 84 64 148 Gd -76269.419 1.460 8248.3398 0.0099 B- -5732.4723 12.5208 147 918121.414 1.566 + 18 83 65 148 Tb -70536.947 12.463 8204.3207 0.0842 B- -2677.5501 9.5961 147 924275.476 13.379 + 16 82 66 148 Dy -67859.397 8.724 8180.9430 0.0589 B- -9868.2304 84.2872 147 927149.944 9.365 + 14 81 67 148 Ho x -57991.166 83.834 8108.9797 0.5664 B- -6512.1694 84.4583 147 937743.925 90.000 + 12 80 68 148 Er x -51478.997 10.246 8059.6924 0.0692 B- -12713.9630 14.4906 147 944735.026 11.000 + 10 79 69 148 Tm x -38765.034 10.246 7968.5011 0.0692 B- -8535# 400# 147 958384.026 11.000 + 8 78 70 148 Yb x -30230# 400# 7906# 3# B- * 147 967547# 429# +0 41 95 54 149 Xe x -33000# 300# 8009# 2# B- 10300# 500# 148 964573# 322# + 39 94 55 149 Cs x -43300# 400# 8073# 3# B- 9531# 400# 148 953516# 429# + 37 93 56 149 Ba x -52830.620 2.515 8131.8495 0.0169 B- 7389.3010 200.2781 148 943284.000 2.700 + 35 92 57 149 La + -60219.921 200.262 8176.1915 1.3440 B- 6450.0000 200.0000 148 935351.259 214.990 + 33 91 58 149 Ce x -66669.921 10.246 8214.2294 0.0688 B- 4369.4525 14.2296 148 928426.900 11.000 + 31 90 59 149 Pr x -71039.373 9.874 8238.3040 0.0663 B- 3336.1617 10.0853 148 923736.100 10.600 + 29 89 60 149 Nd -n -74375.535 2.054 8255.4437 0.0138 B- 1688.8697 2.4588 148 920154.583 2.205 + 27 88 61 149 Pm -76064.404 2.184 8261.5277 0.0147 B- 1071.4936 1.8747 148 918341.507 2.344 + 25 87 62 149 Sm -77135.898 1.157 8263.4683 0.0078 B- -694.5812 3.7881 148 917191.211 1.241 + 23 86 63 149 Eu -76441.317 3.903 8253.5560 0.0262 B- -1314.1437 4.1361 148 917936.875 4.190 + 21 85 64 149 Gd -75127.173 3.310 8239.4856 0.0222 B- -3638.5336 4.3388 148 919347.666 3.553 + 19 84 65 149 Tb -71488.639 3.629 8209.8153 0.0244 B- -3794.6493 9.1335 148 923253.792 3.895 + 17 83 66 149 Dy -67693.990 9.183 8179.0972 0.0616 B- -6048.1366 12.7928 148 927327.516 9.858 + 15 82 67 149 Ho -61645.854 11.985 8133.2550 0.0804 B- -7904.2328 30.4066 148 933820.457 12.866 + 13 81 68 149 Er x -53741.621 27.945 8074.9558 0.1875 B- -9801# 202# 148 942306.000 30.000 + 11 80 69 149 Tm x -43940# 200# 8004# 1# B- -10611# 361# 148 952828# 215# + 9 79 70 149 Yb x -33330# 300# 7927# 2# B- * 148 964219# 322# +0 42 96 54 150 Xe x -28990# 300# 7983# 2# B- 9180# 500# 149 968878# 322# + 40 95 55 150 Cs x -38170# 400# 8039# 3# B- 11720# 400# 149 959023# 429# + 38 94 56 150 Ba x -49889.799 5.682 8111.8405 0.0379 B- 6421.3477 6.2138 149 946441.100 6.100 + 36 93 57 150 La x -56311.147 2.515 8149.4339 0.0168 B- 8535.7155 11.9641 149 939547.500 2.700 + 34 92 58 150 Ce -64846.863 11.697 8201.1230 0.0780 B- 3453.6462 14.2913 149 930384.032 12.556 + 32 91 59 150 Pr -68300.509 9.015 8218.9316 0.0601 B- 5379.4422 9.0682 149 926676.391 9.677 + 30 90 60 150 Nd -73679.951 1.129 8249.5789 0.0075 B- -82.6155 20.0010 149 920901.322 1.211 + 28 89 61 150 Pm + -73597.336 20.031 8243.8125 0.1335 B- 3454.0000 20.0000 149 920990.014 21.504 + 26 88 62 150 Sm -77051.336 1.112 8261.6235 0.0074 B- -2258.9662 6.1803 149 917281.993 1.193 + 24 87 63 150 Eu -74792.369 6.231 8241.3481 0.0415 B- 971.6815 3.5428 149 919707.092 6.688 + 22 86 64 150 Gd -75764.051 6.055 8242.6103 0.0404 B- -4658.2621 8.3784 149 918663.949 6.500 + 20 85 65 150 Tb -71105.789 7.371 8206.3396 0.0491 B- -1796.1707 8.3886 149 923664.799 7.912 + 18 84 66 150 Dy -69309.618 4.319 8189.1495 0.0288 B- -7363.7264 14.4629 149 925593.068 4.636 + 16 83 67 150 Ho -61945.892 14.168 8134.8423 0.0945 B- -4114.5689 13.5910 149 933498.353 15.209 + 14 82 68 150 Er -57831.323 17.194 8102.1962 0.1146 B- -11340# 196# 149 937915.524 18.458 + 12 81 69 150 Tm x -46491# 196# 8021# 1# B- -7661# 358# 149 950090# 210# + 10 80 70 150 Yb x -38830# 300# 7965# 2# B- -14059# 424# 149 958314# 322# + 8 79 71 150 Lu -p -24771# 300# 7866# 2# B- * 149 973407# 322# +0 41 96 55 151 Cs x -34280# 500# 8013# 3# B- 10660# 640# 150 963199# 537# + 39 95 56 151 Ba x -44940# 400# 8079# 3# B- 8370# 591# 150 951755# 429# + 37 94 57 151 La x -53310.339 435.473 8129.0436 2.8839 B- 7914.7191 435.8330 150 942769.000 467.500 + 35 93 58 151 Ce x -61225.058 17.698 8176.2779 0.1172 B- 5554.6233 21.1885 150 934272.200 19.000 + 33 92 59 151 Pr -66779.681 11.650 8207.8824 0.0772 B- 4163.5021 11.6789 150 928309.066 12.506 + 31 91 60 151 Nd -70943.183 1.133 8230.2741 0.0075 B- 2443.0767 4.4734 150 923839.363 1.215 + 29 90 61 151 Pm -73386.260 4.611 8241.2723 0.0305 B- 1190.2198 4.4757 150 921216.613 4.949 + 27 89 62 151 Sm -74576.480 1.110 8243.9735 0.0074 B- 76.6182 0.5375 150 919938.859 1.191 + 25 88 63 151 Eu -74653.098 1.166 8239.2998 0.0077 B- -464.1779 2.7791 150 919856.606 1.251 + 23 87 64 151 Gd -74188.920 2.993 8231.0446 0.0198 B- -2565.3796 3.7615 150 920354.922 3.212 + 21 86 65 151 Tb -71623.541 4.094 8208.8743 0.0271 B- -2871.1525 4.9455 150 923108.970 4.395 + 19 85 66 151 Dy -a -68752.388 3.247 8184.6789 0.0215 B- -5129.6421 8.7507 150 926191.279 3.486 + 17 84 67 151 Ho -a -63622.746 8.298 8145.5267 0.0550 B- -5356.4558 18.4420 150 931698.176 8.908 + 15 83 68 151 Er x -58266.290 16.470 8104.8723 0.1091 B- -7494.6768 25.4292 150 937448.567 17.681 + 13 82 69 151 Tm -50771.613 19.375 8050.0576 0.1283 B- -9229.2615 300.1329 150 945494.433 20.799 + 11 81 70 151 Yb ep -41542.352 300.492 7983.7556 1.9900 B- -11242# 425# 150 955402.453 322.591 + 9 80 71 151 Lu -p -30300# 300# 7904# 2# B- * 150 967471# 322# +0 42 97 55 152 Cs x -29130# 500# 7980# 3# B- 12480# 640# 151 968728# 537# + 40 96 56 152 Ba x -41610# 400# 8057# 3# B- 7680# 500# 151 955330# 429# + 38 95 57 152 La x -49290# 300# 8102# 2# B- 9690# 361# 151 947085# 322# + 36 94 58 152 Ce x -58980# 200# 8161# 1# B- 4778# 201# 151 936682# 215# + 34 93 59 152 Pr x -63758.070 18.537 8187.1049 0.1220 B- 6391.5934 30.7035 151 931552.900 19.900 + 32 92 60 152 Nd -70149.663 24.476 8224.0078 0.1610 B- 1104.8050 18.5011 151 924691.242 26.276 + 30 91 61 152 Pm -71254.468 25.904 8226.1293 0.1704 B- 3508.5089 25.8859 151 923505.185 27.809 + 28 90 62 152 Sm -74762.977 1.016 8244.0645 0.0067 B- -1874.4774 0.6857 151 919738.646 1.090 + 26 89 63 152 Eu -72888.500 1.166 8226.5854 0.0077 B- 1818.8037 0.7002 151 921750.980 1.252 + 24 88 64 152 Gd -74707.304 1.007 8233.4042 0.0066 B- -3990.0000 40.0000 151 919798.414 1.081 + 22 87 65 152 Tb - -70717.304 40.013 8202.0072 0.2632 B- -599.3405 40.2575 151 924081.855 42.955 + 20 86 66 152 Dy -a -70117.963 4.593 8192.9171 0.0302 B- -6513.3275 13.3176 151 924725.274 4.930 + 18 85 67 152 Ho -63604.636 12.528 8144.9193 0.0824 B- -3104.4174 9.8150 151 931717.618 13.449 + 16 84 68 152 Er -60500.218 8.830 8119.3485 0.0581 B- -8779.9397 54.7434 151 935050.347 9.478 + 14 83 69 152 Tm -51720.279 54.027 8056.4387 0.3554 B- -5449.8923 139.6200 151 944476.000 58.000 + 12 82 70 152 Yb -46270.386 149.708 8015.4371 0.9849 B- -12848# 246# 151 950326.699 160.718 + 10 81 71 152 Lu x -33422# 196# 7926# 1# B- * 151 964120# 210# +0 41 97 56 153 Ba x -36470# 400# 8023# 3# B- 9590# 500# 152 960848# 429# + 39 96 57 153 La x -46060# 300# 8081# 2# B- 8850# 361# 152 950553# 322# + 37 95 58 153 Ce x -54910# 200# 8134# 1# B- 6659# 201# 152 941052# 215# + 35 94 59 153 Pr -61568.490 11.882 8172.0371 0.0777 B- 5761.8901 12.1896 152 933903.511 12.755 + 33 93 60 153 Nd -67330.380 2.747 8204.5832 0.0180 B- 3317.6236 9.3521 152 927717.868 2.949 + 31 92 61 153 Pm -70648.003 9.063 8221.1536 0.0592 B- 1912.0559 9.0829 152 924156.252 9.729 + 29 91 62 153 Sm -n -72560.059 1.025 8228.5373 0.0067 B- 807.4073 0.7063 152 922103.576 1.100 + 27 90 63 153 Eu -73367.466 1.171 8228.7011 0.0077 B- -484.5225 0.7150 152 921236.789 1.257 + 25 89 64 153 Gd -72882.944 1.002 8220.4209 0.0066 B- -1569.3340 3.8444 152 921756.945 1.075 + 23 88 65 153 Tb -71313.610 3.947 8205.0504 0.0258 B- -2170.4134 1.9335 152 923441.694 4.237 + 21 87 66 153 Dy -69143.197 4.001 8185.7514 0.0262 B- -4131.1229 6.1571 152 925771.729 4.295 + 19 86 67 153 Ho -a -65012.074 5.066 8153.6372 0.0331 B- -4545.3918 9.8899 152 930206.671 5.438 + 17 85 68 153 Er -60466.682 9.285 8118.8154 0.0607 B- -6494.0723 12.8812 152 935086.350 9.967 + 15 84 69 153 Tm -53972.610 11.979 8071.2571 0.0783 B- -6813# 201# 152 942058.023 12.860 + 13 83 70 153 Yb x -47160# 200# 8022# 1# B- -8784# 250# 152 949372# 215# + 11 82 71 153 Lu +a -38375.462 150.017 7959.0882 0.9805 B- -11075# 335# 152 958802.248 161.050 + 9 81 72 153 Hf x -27300# 300# 7882# 2# B- * 152 970692# 322# +0 42 98 56 154 Ba x -32920# 500# 8001# 3# B- 8610# 583# 153 964659# 537# + 40 97 57 154 La x -41530# 300# 8051# 2# B- 10690# 361# 153 955416# 322# + 38 96 58 154 Ce x -52220# 200# 8116# 1# B- 5640# 224# 153 943940# 215# + 36 95 59 154 Pr + -57859.602 100.005 8147.2994 0.6494 B- 7720.0000 100.0000 153 937885.165 107.360 + 34 94 60 154 Nd x -65579.602 1.025 8192.3491 0.0067 B- 2687.0000 25.0000 153 929597.404 1.100 + 32 93 61 154 Pm - -68266.602 25.021 8204.7170 0.1625 B- 4188.9614 25.0550 153 926712.791 26.861 + 30 92 62 154 Sm -72455.564 1.305 8226.8379 0.0085 B- -717.1969 1.1019 153 922215.756 1.400 + 28 91 63 154 Eu -71738.367 1.188 8217.1006 0.0077 B- 1967.9913 0.7535 153 922985.699 1.275 + 26 90 64 154 Gd -73706.358 0.994 8224.7996 0.0065 B- -3549.6514 45.2983 153 920872.974 1.066 + 24 89 65 154 Tb - -70156.707 45.309 8196.6697 0.2942 B- 237.3080 45.9008 153 924683.681 48.641 + 22 88 66 154 Dy -70394.015 7.431 8193.1305 0.0483 B- -5754.6363 10.1785 153 924428.920 7.977 + 20 87 67 154 Ho -a -64639.378 8.216 8150.6825 0.0534 B- -2034.4045 9.4621 153 930606.776 8.820 + 18 86 68 154 Er -62604.974 4.961 8132.3919 0.0322 B- -8177.8316 14.9113 153 932790.799 5.325 + 16 85 69 154 Tm -a -54427.142 14.412 8074.2090 0.0936 B- -4495.0495 13.9528 153 941570.062 15.471 + 14 84 70 154 Yb -49932.093 17.281 8039.9402 0.1122 B- -10265# 201# 153 946395.696 18.551 + 12 83 71 154 Lu +a -39667# 201# 7968# 1# B- -6937# 361# 153 957416# 216# + 10 82 72 154 Hf x -32730# 300# 7918# 2# B- * 153 964863# 322# +0 41 98 57 155 La x -37930# 400# 8028# 3# B- 9850# 500# 154 959280# 429# + 39 97 58 155 Ce x -47780# 300# 8087# 2# B- 7635# 300# 154 948706# 322# + 37 96 59 155 Pr -55415.335 17.198 8131.0398 0.1110 B- 6868.4609 19.4725 154 940509.193 18.462 + 35 95 60 155 Nd -62283.796 9.154 8170.3050 0.0591 B- 4656.2095 10.2781 154 933135.598 9.826 + 33 94 61 155 Pm -66940.006 4.719 8195.2977 0.0304 B- 3251.1999 4.9024 154 928136.951 5.065 + 31 93 62 155 Sm -n -70191.206 1.332 8211.2258 0.0086 B- 1627.1314 1.2016 154 924646.645 1.429 + 29 92 63 155 Eu -71818.337 1.252 8216.6760 0.0081 B- 251.9612 0.8682 154 922899.847 1.343 + 27 91 64 155 Gd -72070.298 0.983 8213.2541 0.0063 B- -819.8588 9.7884 154 922629.356 1.055 + 25 90 65 155 Tb + -71250.439 9.830 8202.9173 0.0634 B- -2094.5000 1.8974 154 923509.511 10.552 + 23 89 66 155 Dy -69155.939 9.645 8184.3570 0.0622 B- -3116.1405 16.5887 154 925758.049 10.354 + 21 88 67 155 Ho -66039.799 17.470 8159.2055 0.1127 B- -3830.6268 18.4730 154 929103.363 18.754 + 19 87 68 155 Er -a -62209.172 6.074 8129.4444 0.0392 B- -5583.2509 11.5109 154 933215.710 6.520 + 17 86 69 155 Tm -a -56625.921 9.921 8088.3760 0.0640 B- -6123.3072 19.3388 154 939209.576 10.651 + 15 85 70 155 Yb -a -50502.614 16.600 8043.8234 0.1071 B- -7957.5578 25.4153 154 945783.216 17.820 + 13 84 71 155 Lu -42545.056 19.245 7987.4369 0.1242 B- -8235# 301# 154 954326.005 20.660 + 11 83 72 155 Hf x -34310# 300# 7929# 2# B- -10322# 424# 154 963167# 322# + 9 82 73 155 Ta -p -23988# 300# 7858# 2# B- * 154 974248# 322# +0 42 99 57 156 La x -33050# 400# 7997# 3# B- 11769# 500# 155 964519# 429# + 40 98 58 156 Ce x -44820# 300# 8068# 2# B- 6630# 300# 155 951884# 322# + 38 97 59 156 Pr x -51449.307 1.025 8105.2337 0.0066 B- 8752.8229 1.6585 155 944766.900 1.100 + 36 96 60 156 Nd x -60202.130 1.304 8156.3265 0.0084 B- 3964.7175 1.7642 155 935370.358 1.400 + 34 95 61 156 Pm -64166.847 1.188 8176.7263 0.0076 B- 5193.8878 8.6044 155 931114.059 1.275 + 32 94 62 156 Sm -69360.735 8.522 8205.0054 0.0546 B- 722.1090 7.9025 155 925538.191 9.148 + 30 93 63 156 Eu -70082.844 3.532 8204.6192 0.0226 B- 2452.4891 3.4083 155 924762.976 3.791 + 28 92 64 156 Gd -72535.333 0.983 8215.3253 0.0063 B- -2444.3230 3.6774 155 922130.120 1.054 + 26 91 65 156 Tb -70091.010 3.768 8194.6415 0.0242 B- 438.3762 3.6789 155 924754.209 4.044 + 24 90 66 156 Dy -70529.386 0.988 8192.4366 0.0063 B- -4990.9836 38.4111 155 924283.593 1.060 + 22 89 67 156 Ho - -65538.403 38.424 8155.4280 0.2463 B- -1326.7201 45.6391 155 929641.634 41.249 + 20 88 68 156 Er -64211.683 24.629 8141.9084 0.1579 B- -7377.2657 26.7099 155 931065.926 26.440 + 18 87 69 156 Tm -56834.417 14.279 8089.6032 0.0915 B- -3568.8794 12.5484 155 938985.746 15.328 + 16 86 70 156 Yb -53265.538 9.308 8061.7107 0.0597 B- -9565.9880 54.9162 155 942817.096 9.992 + 14 85 71 156 Lu -a -43699.550 54.122 7995.3752 0.3469 B- -5880.0352 139.6908 155 953086.606 58.102 + 12 84 72 156 Hf -37819.514 149.740 7952.6676 0.9599 B- -11819# 335# 155 959399.083 160.752 + 10 83 73 156 Ta -p -26001# 300# 7872# 2# B- * 155 972087# 322# +0 43 100 57 157 La x -29070# 300# 7972# 2# B- 10860# 500# 156 968792# 322# + 41 99 58 157 Ce x -39930# 400# 8037# 3# B- 8504# 400# 156 957133# 429# + 39 98 59 157 Pr x -48434.806 3.167 8085.8170 0.0202 B- 8059.3109 3.8207 156 948003.100 3.400 + 37 97 60 157 Nd -56494.117 2.137 8132.1671 0.0136 B- 5802.9994 7.3246 156 939351.074 2.294 + 35 96 61 157 Pm -62297.116 7.006 8164.1458 0.0446 B- 4380.5376 8.2650 156 933121.298 7.521 + 33 95 62 157 Sm -66677.654 4.434 8187.0642 0.0282 B- 2781.4807 6.1191 156 928418.598 4.759 + 31 94 63 157 Eu -69459.134 4.234 8199.7975 0.0270 B- 1364.7614 4.1973 156 925432.556 4.545 + 29 93 64 157 Gd -70823.896 0.977 8203.5072 0.0062 B- -60.0473 0.2972 156 923967.424 1.048 + 27 92 65 157 Tb -70763.848 1.018 8198.1416 0.0065 B- -1339.1791 5.1297 156 924031.888 1.092 + 25 91 66 157 Dy -69424.669 5.154 8184.6287 0.0328 B- -2591.8068 23.7839 156 925469.555 5.532 + 23 90 67 157 Ho -66832.862 23.469 8163.1373 0.1495 B- -3419.2146 33.6675 156 928251.974 25.194 + 21 89 68 157 Er -63413.648 26.505 8136.3757 0.1688 B- -4704.3690 38.5152 156 931922.652 28.454 + 19 88 69 157 Tm x -58709.279 27.945 8101.4285 0.1780 B- -5289.3667 29.9971 156 936973.000 30.000 + 17 87 70 157 Yb -53419.912 10.905 8062.7551 0.0695 B- -6980.0942 14.2406 156 942651.368 11.706 + 15 86 71 157 Lu -46439.818 12.074 8013.3128 0.0769 B- -7585# 201# 156 950144.807 12.961 + 13 85 72 157 Hf -a -38855# 200# 7960# 1# B- -9259# 250# 156 958288# 215# + 11 84 73 157 Ta IT -29595.948 150.052 7896.0608 0.9557 B- -9906# 427# 156 968227.445 161.087 + 9 83 74 157 W x -19690# 400# 7828# 3# B- * 156 978862# 429# +0 42 100 58 158 Ce x -36540# 400# 8015# 3# B- 7610# 500# 157 960773# 429# + 40 99 59 158 Pr x -44150# 300# 8059# 2# B- 9685# 300# 157 952603# 322# + 38 98 60 158 Nd x -53835.123 1.304 8114.9529 0.0083 B- 5271.0196 1.5776 157 942205.620 1.400 + 36 97 61 158 Pm -59106.143 0.888 8143.3622 0.0056 B- 6145.7062 4.8634 157 936546.948 0.953 + 34 96 62 158 Sm -65251.849 4.782 8177.3075 0.0303 B- 2018.6123 5.1146 157 929949.262 5.133 + 32 95 63 158 Eu -67270.461 2.032 8185.1320 0.0129 B- 3419.5081 2.2547 157 927782.192 2.181 + 30 94 64 158 Gd -70689.969 0.976 8201.8229 0.0062 B- -1219.0862 0.9799 157 924111.200 1.048 + 28 93 65 158 Tb -69470.883 1.268 8189.1556 0.0080 B- 936.2686 2.4750 157 925419.942 1.360 + 26 92 66 158 Dy -70407.152 2.337 8190.1298 0.0148 B- -4219.7555 27.0048 157 924414.817 2.509 + 24 91 67 158 Ho - -66187.396 27.106 8158.4709 0.1716 B- -883.5812 37.0236 157 928944.910 29.099 + 22 90 68 158 Er -65303.815 25.219 8147.9270 0.1596 B- -6600.6151 31.3411 157 929893.474 27.074 + 20 89 69 158 Tm -58703.200 25.219 8101.1994 0.1596 B- -2693.5796 26.4499 157 936979.525 27.074 + 18 88 70 158 Yb -56009.620 7.973 8079.1999 0.0505 B- -8797.4201 16.8655 157 939871.202 8.559 + 16 87 71 158 Lu -a -47212.200 15.125 8018.5685 0.0957 B- -5109.8010 14.9373 157 949315.620 16.236 + 14 86 72 158 Hf -42102.399 17.494 7981.2764 0.1107 B- -10984# 201# 157 954801.217 18.780 + 12 85 73 158 Ta +a -31118# 201# 7907# 1# B- -7426# 361# 157 966593# 215# + 10 84 74 158 W -a -23693# 300# 7855# 2# B- * 157 974565# 322# +0 43 101 58 159 Ce x -31340# 500# 7983# 3# B- 9430# 640# 158 966355# 537# + 41 100 59 159 Pr x -40770# 400# 8037# 3# B- 8954# 401# 158 956232# 429# + 39 99 60 159 Nd x -49724.007 29.808 8088.8224 0.1875 B- 6830.3441 31.4529 158 946619.085 32.000 + 37 98 61 159 Pm -56554.351 10.039 8126.8601 0.0631 B- 5653.4982 11.6438 158 939286.409 10.777 + 35 97 62 159 Sm -62207.849 5.934 8157.4963 0.0373 B- 3835.5363 7.3211 158 933217.130 6.370 + 33 96 63 159 Eu -66043.386 4.320 8176.6987 0.0272 B- 2518.4717 4.3657 158 929099.512 4.637 + 31 95 64 159 Gd -68561.857 0.980 8187.6177 0.0062 B- 970.7242 0.7495 158 926395.822 1.051 + 29 94 65 159 Tb -69532.582 1.103 8188.8025 0.0069 B- -365.3613 1.1573 158 925353.707 1.184 + 27 93 66 159 Dy -69167.220 1.439 8181.5842 0.0091 B- -1837.6000 2.6833 158 925745.938 1.544 + 25 92 67 159 Ho - -67329.620 3.045 8165.1066 0.0192 B- -2768.5000 2.0000 158 927718.683 3.268 + 23 91 68 159 Er - -64561.120 3.643 8142.7742 0.0229 B- -3990.7162 28.1813 158 930690.790 3.910 + 21 90 69 159 Tm x -60570.404 27.945 8112.7549 0.1758 B- -4736.8869 33.0155 158 934975.000 30.000 + 19 89 70 159 Yb x -55833.517 17.582 8078.0428 0.1106 B- -6124.9081 41.5648 158 940060.257 18.874 + 17 88 71 159 Lu x -49708.609 37.663 8034.6009 0.2369 B- -6856.0030 41.2456 158 946635.615 40.433 + 15 87 72 159 Hf -a -42852.606 16.813 7986.5610 0.1057 B- -8413.4492 25.8909 158 953995.837 18.049 + 13 86 73 159 Ta IT -34439.157 19.689 7928.7258 0.1238 B- -9005# 301# 158 963028.046 21.137 + 11 85 74 159 W -a -25434# 300# 7867# 2# B- -10629# 427# 158 972696# 322# + 9 84 75 159 Re IT -14805# 305# 7795# 2# B- * 158 984106# 327# +0 42 101 59 160 Pr x -36200# 400# 8009# 2# B- 10525# 402# 159 961138# 429# + 40 100 60 160 Nd x -46724.515 46.575 8069.9662 0.2911 B- 6170.1238 46.6198 159 949839.172 50.000 + 38 99 61 160 Pm x -52894.639 2.049 8103.6398 0.0128 B- 7338.5338 2.8330 159 943215.272 2.200 + 36 98 62 160 Sm x -60233.172 1.956 8144.6159 0.0122 B- 3260.2763 2.1547 159 935337.032 2.100 + 34 97 63 160 Eu x -63493.449 0.904 8160.1030 0.0057 B- 4448.6112 1.4417 159 931836.982 0.970 + 32 96 64 160 Gd -67942.060 1.123 8183.0171 0.0070 B- -105.5863 1.0207 159 927061.202 1.206 + 30 95 65 160 Tb -67836.474 1.110 8177.4676 0.0069 B- 1835.9516 1.1011 159 927174.553 1.191 + 28 94 66 160 Dy -69672.425 0.700 8184.0526 0.0044 B- -3290.0000 15.0000 159 925203.578 0.751 + 26 93 67 160 Ho - -66382.425 15.016 8158.6004 0.0939 B- -318.2488 28.5197 159 928735.538 16.120 + 24 92 68 160 Er -66064.176 24.246 8151.7217 0.1515 B- -5763.1395 39.1333 159 929077.193 26.029 + 22 91 69 160 Tm -60301.037 32.686 8110.8124 0.2043 B- -2137.8101 33.1447 159 935264.177 35.089 + 20 90 70 160 Yb x -58163.227 5.496 8092.5614 0.0343 B- -7893.2846 57.0863 159 937559.210 5.900 + 18 89 71 160 Lu x -50269.942 56.821 8038.3387 0.3551 B- -4331.1951 57.6165 159 946033.000 61.000 + 16 88 72 160 Hf -45938.747 9.540 8006.3791 0.0596 B- -10115.0475 55.1472 159 950682.728 10.241 + 14 87 73 160 Ta -a -35823.700 54.316 7938.2704 0.3395 B- -6494.6267 139.8413 159 961541.678 58.310 + 12 86 74 160 W -29329.073 149.810 7892.7893 0.9363 B- -12451# 335# 159 968513.946 160.828 + 10 85 75 160 Re -a -16878# 300# 7810# 2# B- * 159 981880# 322# +0 43 102 59 161 Pr x -32490# 500# 7986# 3# B- 9741# 640# 160 965121# 537# + 41 101 60 161 Nd x -42230# 400# 8042# 2# B- 7856# 400# 160 954664# 429# + 39 100 61 161 Pm x -50086.589 9.035 8085.9977 0.0561 B- 6585.4546 11.3187 160 946229.837 9.700 + 37 99 62 161 Sm -56672.043 6.817 8122.0418 0.0423 B- 5119.5577 12.4147 160 939160.062 7.318 + 35 98 63 161 Eu -61791.601 10.400 8148.9810 0.0646 B- 3714.5406 10.5074 160 933663.991 11.164 + 33 97 64 161 Gd -n -65506.142 1.504 8167.1934 0.0093 B- 1955.6357 1.4402 160 929676.267 1.614 + 31 96 65 161 Tb -67461.778 1.218 8174.4809 0.0076 B- 593.7166 1.2010 160 927576.806 1.308 + 29 95 66 161 Dy -68055.494 0.697 8173.3093 0.0043 B- -859.2003 2.1368 160 926939.425 0.748 + 27 94 67 161 Ho -67196.294 2.151 8163.1134 0.0134 B- -1994.9954 9.0041 160 927861.815 2.309 + 25 93 68 161 Er +n -65201.298 8.774 8145.8628 0.0545 B- -3302.5839 29.2899 160 930003.530 9.419 + 23 92 69 161 Tm x -61898.715 27.945 8120.4906 0.1736 B- -4064.4665 31.7640 160 933549.000 30.000 + 21 91 70 161 Yb x -57834.248 15.101 8090.3861 0.0938 B- -5271.8989 31.7640 160 937912.384 16.211 + 19 90 71 161 Lu x -52562.349 27.945 8052.7821 0.1736 B- -6246.5319 36.4805 160 943572.000 30.000 + 17 89 72 161 Hf -46315.817 23.450 8009.1245 0.1457 B- -7537.2421 33.7278 160 950277.927 25.174 + 15 88 73 161 Ta +a -38778.575 24.381 7957.4500 0.1514 B- -8272# 202# 160 958369.489 26.174 + 13 87 74 161 W -a -30507# 200# 7901# 1# B- -9664# 250# 160 967249# 215# + 11 86 75 161 Re -20842.820 149.905 7836.3292 0.9311 B- -10647# 427# 160 977624.313 160.930 + 9 85 76 161 Os -a -10196# 400# 7765# 2# B- * 160 989054# 429# +0 42 102 60 162 Nd x -39010# 400# 8022# 2# B- 7030# 500# 161 958121# 429# + 40 101 61 162 Pm x -46040# 300# 8061# 2# B- 8339# 300# 161 950574# 322# + 38 100 62 162 Sm -54379.053 3.523 8107.5745 0.0218 B- 4343.8905 3.7605 161 941621.687 3.782 + 36 99 63 162 Eu -58722.944 1.314 8129.5593 0.0081 B- 5557.7761 4.1748 161 936958.329 1.410 + 34 98 64 162 Gd -nn -64280.720 3.963 8159.0373 0.0245 B- 1598.8278 4.4611 161 930991.812 4.254 + 32 97 65 162 Tb x -65879.548 2.049 8164.0773 0.0127 B- 2301.6217 2.1640 161 929275.400 2.200 + 30 96 66 162 Dy -68181.169 0.695 8173.4555 0.0043 B- -2140.6068 3.0926 161 926804.507 0.746 + 28 95 67 162 Ho -66040.563 3.102 8155.4126 0.0192 B- 293.6478 3.1069 161 929102.543 3.330 + 26 94 68 162 Er -66334.210 0.756 8152.3959 0.0047 B- -4856.7282 26.0475 161 928787.299 0.811 + 24 93 69 162 Tm - -61477.482 26.058 8117.5868 0.1609 B- -1656.3190 30.1127 161 934001.211 27.974 + 22 92 70 162 Yb x -59821.163 15.103 8102.5333 0.0932 B- -6989.4042 76.5406 161 935779.342 16.213 + 20 91 71 162 Lu x -52831.759 75.036 8054.5596 0.4632 B- -3663.3333 75.5679 161 943282.776 80.554 + 18 90 72 162 Hf -49168.426 8.952 8027.1171 0.0553 B- -9387.0211 63.8938 161 947215.526 9.610 + 16 89 73 162 Ta -a -39781.405 63.322 7964.3432 0.3909 B- -5782.1880 63.3235 161 957292.907 67.979 + 14 88 74 162 W -33999.217 17.657 7923.8214 0.1090 B- -11546# 201# 161 963500.341 18.955 + 12 87 75 162 Re +a -22453# 201# 7848# 1# B- -7953# 361# 161 975896# 215# + 10 86 76 162 Os -a -14500# 300# 7794# 2# B- * 161 984434# 322# +0 43 103 60 163 Nd x -34080# 500# 7992# 3# B- 8880# 640# 162 963414# 537# + 41 102 61 163 Pm x -42960# 400# 8042# 2# B- 7640# 400# 162 953881# 429# + 39 101 62 163 Sm x -50599.612 7.359 8084.1653 0.0451 B- 5974.2073 7.4141 162 945679.085 7.900 + 37 100 63 163 Eu x -56573.819 0.904 8116.0172 0.0056 B- 4814.7720 1.2046 162 939265.510 0.970 + 35 99 64 163 Gd -61388.591 0.797 8140.7560 0.0049 B- 3207.1628 4.1374 162 934096.640 0.855 + 33 98 65 163 Tb +p -64595.754 4.060 8155.6322 0.0249 B- 1785.1041 4.0006 162 930653.609 4.358 + 31 97 66 163 Dy -66380.858 0.693 8161.7840 0.0043 B- -2.8309 0.0222 162 928737.221 0.744 + 29 96 67 163 Ho -66378.027 0.693 8156.9670 0.0043 B- -1210.6141 4.5755 162 928740.260 0.744 + 27 95 68 163 Er -65167.413 4.628 8144.7403 0.0284 B- -2439.0000 3.0000 162 930039.908 4.967 + 25 94 69 163 Tm - -62728.413 5.515 8124.9774 0.0338 B- -3434.5345 16.0687 162 932658.282 5.920 + 23 93 70 163 Yb x -59293.878 15.105 8099.1069 0.0927 B- -4502.4636 31.7657 162 936345.406 16.215 + 21 92 71 163 Lu x -54791.415 27.945 8066.6848 0.1714 B- -5522.0944 37.9611 162 941179.000 30.000 + 19 91 72 163 Hf -49269.320 25.693 8028.0072 0.1576 B- -6734.6864 45.9217 162 947107.211 27.582 + 17 90 73 163 Ta -a -42534.634 38.061 7981.8905 0.2335 B- -7626.1952 69.7301 162 954337.194 40.860 + 15 89 74 163 W -a -34908.439 58.426 7930.3043 0.3584 B- -8906.1859 61.2953 162 962524.251 62.722 + 13 88 75 163 Re +a -26002.253 18.534 7870.8655 0.1137 B- -9666# 301# 162 972085.434 19.897 + 11 87 76 163 Os -a -16336# 300# 7807# 2# B- -11026# 500# 162 982462# 322# + 9 86 77 163 Ir x -5310# 400# 7734# 2# B- * 162 994299# 429# +0 42 103 61 164 Pm x -38360# 400# 8014# 2# B- 9565# 400# 163 958819# 429# + 40 102 62 164 Sm x -47925.314 4.099 8067.7803 0.0250 B- 5306.8315 4.5907 163 948550.061 4.400 + 38 101 63 164 Eu -53232.146 2.068 8095.3686 0.0126 B- 6461.5416 2.2969 163 942852.943 2.219 + 36 100 64 164 Gd -59693.688 1.000 8129.9978 0.0061 B- 2411.2959 2.1143 163 935916.193 1.073 + 34 99 65 164 Tb x -62104.983 1.863 8139.9304 0.0114 B- 3862.6653 1.9884 163 933327.561 2.000 + 32 98 66 164 Dy -65967.649 0.695 8158.7129 0.0042 B- -987.1315 1.3710 163 929180.819 0.746 + 30 97 67 164 Ho -64980.517 1.390 8147.9234 0.0085 B- 962.0559 1.3756 163 930240.548 1.492 + 28 96 68 164 Er -65942.573 0.704 8149.0191 0.0043 B- -4033.6302 25.0113 163 929207.739 0.755 + 26 95 69 164 Tm -61908.943 25.006 8119.6534 0.1525 B- -896.7722 29.2135 163 933538.019 26.845 + 24 94 70 164 Yb x -61012.171 15.106 8109.4149 0.0921 B- -6369.7952 31.7666 163 934500.743 16.217 + 22 93 71 164 Lu x -54642.376 27.945 8065.8043 0.1704 B- -2824.0194 32.1083 163 941339.000 30.000 + 20 92 72 164 Hf -51818.356 15.812 8043.8142 0.0964 B- -8535.5511 32.1083 163 944370.709 16.975 + 18 91 73 164 Ta x -43282.805 27.945 7986.9978 0.1704 B- -5047.2500 29.5717 163 953534.000 30.000 + 16 90 74 164 W -38235.555 9.673 7951.4515 0.0590 B- -10763.1138 55.4055 163 958952.445 10.384 + 14 89 75 164 Re -a -27472.441 54.555 7881.0523 0.3326 B- -7047.7180 140.0330 163 970507.122 58.566 + 12 88 76 164 Os -20424.723 149.903 7833.3080 0.9140 B- -12941# 350# 163 978073.158 160.927 + 10 87 77 164 Ir -a -7483# 316# 7750# 2# B- * 163 991966# 339# +0 43 104 61 165 Pm x -34670# 500# 7992# 3# B- 8840# 640# 164 962780# 537# + 41 103 62 165 Sm x -43510# 400# 8041# 2# B- 7219# 400# 164 953290# 429# + 39 102 63 165 Eu -50729.103 5.213 8080.0529 0.0316 B- 5796.6788 5.3733 164 945540.070 5.596 + 37 101 64 165 Gd -56525.782 1.304 8110.4428 0.0079 B- 4063.0674 2.0189 164 939317.080 1.400 + 35 100 65 165 Tb -60588.849 1.541 8130.3259 0.0093 B- 3023.4392 1.6915 164 934955.198 1.654 + 33 99 66 165 Dy -n -63612.289 0.697 8143.9083 0.0042 B- 1285.7287 0.7502 164 931709.402 0.748 + 31 98 67 165 Ho -64898.017 0.786 8146.9591 0.0048 B- -376.6648 0.9575 164 930329.116 0.844 + 29 97 68 165 Er -64521.353 0.918 8139.9348 0.0056 B- -1591.3282 1.4891 164 930733.482 0.985 + 27 96 69 165 Tm -62930.024 1.658 8125.5489 0.0101 B- -2634.6364 26.5907 164 932441.843 1.779 + 25 95 70 165 Yb -60295.388 26.539 8104.8399 0.1608 B- -3853.1403 35.4324 164 935270.241 28.490 + 23 94 71 165 Lu -56442.248 26.539 8076.7460 0.1608 B- -4806.7350 38.5387 164 939406.758 28.490 + 21 93 72 165 Hf x -51635.513 27.945 8042.8728 0.1694 B- -5787.6410 31.0668 164 944567.000 30.000 + 19 92 73 165 Ta -45847.872 13.573 8003.0547 0.0823 B- -6986.5555 29.1133 164 950780.287 14.571 + 17 91 74 165 W -38861.316 25.756 7955.9704 0.1561 B- -8201.9627 34.9116 164 958280.663 27.649 + 15 90 75 165 Re +a -30659.353 23.593 7901.5201 0.1430 B- -8913# 202# 164 967085.831 25.328 + 13 89 76 165 Os -a -21747# 200# 7843# 1# B- -10151# 255# 164 976654# 215# + 11 88 77 165 Ir IT -11595# 158# 7776# 1# B- -11277# 430# 164 987552# 170# + 9 87 78 165 Pt -a -318# 400# 7703# 2# B- * 164 999658# 429# +0 42 104 62 166 Sm x -40450# 400# 8023# 2# B- 6299# 412# 165 956575# 429# + 40 103 63 166 Eu + -46749# 100# 8056# 1# B- 7622# 100# 165 949813# 107# + 38 102 64 166 Gd x -54370.926 1.584 8097.2260 0.0095 B- 3437.8515 2.1558 165 941630.413 1.700 + 36 101 65 166 Tb -57808.778 1.463 8113.2230 0.0088 B- 4775.6930 1.6690 165 937939.727 1.570 + 34 100 66 166 Dy -n -62584.471 0.804 8137.2793 0.0048 B- 485.8684 0.8502 165 932812.810 0.862 + 32 99 67 166 Ho -63070.339 0.786 8135.4933 0.0047 B- 1853.8057 0.7792 165 932291.209 0.844 + 30 98 68 166 Er -64924.145 0.334 8141.9479 0.0020 B- -3037.6667 11.5470 165 930301.067 0.358 + 28 97 69 166 Tm - -61886.478 11.552 8118.9357 0.0696 B- -292.7714 13.5069 165 933562.136 12.401 + 26 96 70 166 Yb +nn -61593.706 7.001 8112.4591 0.0422 B- -5572.7197 30.6189 165 933876.439 7.515 + 24 95 71 166 Lu x -56020.987 29.808 8074.1756 0.1796 B- -2161.9978 40.8585 165 939859.000 32.000 + 22 94 72 166 Hf x -53858.989 27.945 8056.4386 0.1683 B- -7761.2089 39.5199 165 942180.000 30.000 + 20 93 73 166 Ta x -46097.780 27.945 8004.9714 0.1683 B- -4210.3092 29.5036 165 950512.000 30.000 + 18 92 74 166 W -41887.471 9.463 7974.8951 0.0570 B- -10050.1358 88.7072 165 955031.952 10.159 + 16 91 75 166 Re -a -31837.335 88.242 7909.6392 0.5316 B- -6405.8090 88.3046 165 965821.216 94.731 + 14 90 76 166 Os -25431.526 17.966 7866.3371 0.1082 B- -12126# 201# 165 972698.135 19.287 + 12 89 77 166 Ir -p -13306# 201# 7789# 1# B- -8523# 361# 165 985716# 215# + 10 88 78 166 Pt -a -4783# 300# 7733# 2# B- * 165 994866# 322# +0 43 105 62 167 Sm x -35330# 500# 7992# 3# B- 8440# 640# 166 962072# 537# + 41 104 63 167 Eu x -43770# 400# 8038# 2# B- 7006# 400# 166 953011# 429# + 39 103 64 167 Gd -50775.732 5.213 8075.5428 0.0312 B- 5107.3505 5.5584 166 945490.012 5.596 + 37 102 65 167 Tb -55883.082 1.929 8101.4410 0.0116 B- 4028.3686 4.4459 166 940007.046 2.071 + 35 101 66 167 Dy x -59911.451 4.005 8120.8782 0.0240 B- 2368.0076 6.5549 166 935682.415 4.300 + 33 100 67 167 Ho p2n -62279.459 5.189 8130.3732 0.0311 B- 1009.7971 5.1890 166 933140.254 5.570 + 31 99 68 167 Er -63289.256 0.286 8131.7352 0.0017 B- -746.1392 1.2633 166 932056.192 0.306 + 29 98 69 167 Tm -62543.117 1.258 8122.5826 0.0075 B- -1953.2162 3.7968 166 932857.206 1.350 + 27 97 70 167 Yb -60589.900 3.960 8106.2020 0.0237 B- -3063.6190 37.4696 166 934954.069 4.251 + 25 96 71 167 Lu x -57526.281 37.260 8083.1722 0.2231 B- -4058.5198 46.5747 166 938243.000 40.000 + 23 95 72 167 Hf x -53467.761 27.945 8054.1850 0.1673 B- -5116.6971 39.5199 166 942600.000 30.000 + 21 94 73 167 Ta x -48351.064 27.945 8018.8614 0.1673 B- -6257.8523 33.6262 166 948093.000 30.000 + 19 93 74 167 W -42093.212 18.703 7976.7045 0.1120 B- -7259# 44# 166 954811.080 20.078 + 17 92 75 167 Re +a -34834# 40# 7929# 0# B- -8335# 90# 166 962604# 43# + 15 91 76 167 Os -a -26498.860 80.892 7873.9557 0.4844 B- -9426.4121 82.9464 166 971552.304 86.841 + 13 90 77 167 Ir -17072.448 18.346 7812.8254 0.1099 B- -10319# 307# 166 981671.973 19.694 + 11 89 78 167 Pt -a -6753# 306# 7746# 2# B- * 166 992750# 329# +0 44 106 62 168 Sm x -31640# 300# 7971# 2# B- 7610# 500# 167 966033# 322# + 42 105 63 168 Eu x -39250# 400# 8012# 2# B- 8899# 500# 167 957863# 429# + 40 104 64 168 Gd x -48150# 300# 8060# 2# B- 4631# 300# 167 948309# 322# + 38 103 65 168 Tb x -52781.181 4.192 8082.7980 0.0250 B- 5777.2167 140.0696 167 943337.074 4.500 + 36 102 66 168 Dy +pp -58558.398 140.007 8112.5293 0.8334 B- 1500.8333 143.1849 167 937134.977 150.303 + 34 101 67 168 Ho + -60059.231 30.001 8116.8061 0.1786 B- 2930.0000 30.0000 167 935523.766 32.207 + 32 100 68 168 Er -62989.231 0.262 8129.5897 0.0016 B- -1676.8526 1.6858 167 932378.282 0.280 + 30 99 69 168 Tm -61312.379 1.677 8114.9516 0.0100 B- 267.4880 1.6782 167 934178.457 1.800 + 28 98 70 168 Yb -61579.867 0.093 8111.8870 0.0006 B- -4507.0351 37.9735 167 933891.297 0.100 + 26 97 71 168 Lu -57072.832 37.973 8080.4026 0.2260 B- -1712.2740 47.1476 167 938729.798 40.766 + 24 96 72 168 Hf x -55360.557 27.945 8065.5536 0.1663 B- -6966.6444 39.5199 167 940568.000 30.000 + 22 95 73 168 Ta x -48393.913 27.945 8019.4287 0.1663 B- -3500.9828 30.9307 167 948047.000 30.000 + 20 94 74 168 W -44892.930 13.259 7993.9327 0.0789 B- -9098.0411 33.5515 167 951805.459 14.233 + 18 93 75 168 Re -a -35794.889 30.821 7935.1208 0.1835 B- -5799.8944 32.3727 167 961572.607 33.087 + 16 92 76 168 Os -29994.995 9.903 7895.9408 0.0589 B- -11328.7644 56.0975 167 967799.050 10.631 + 14 91 77 168 Ir -a -18666.230 55.216 7823.8509 0.3287 B- -7656.1526 140.3258 167 979960.978 59.277 + 12 90 78 168 Pt -a -11010.078 149.934 7773.6217 0.8925 B- -13540# 427# 167 988180.196 160.960 + 10 89 79 168 Au x 2530# 400# 7688# 2# B- * 168 002716# 429# +0 43 106 63 169 Eu x -35660# 500# 7991# 3# B- 8230# 640# 168 961717# 537# + 41 105 64 169 Gd x -43890# 400# 8035# 2# B- 6590# 500# 168 952882# 429# + 39 104 65 169 Tb x -50480# 300# 8069# 2# B- 5116# 425# 168 945807# 322# + 37 103 66 169 Dy + -55596.010 300.669 8094.7566 1.7791 B- 3200.0000 300.0000 168 940315.231 322.781 + 35 102 67 169 Ho +p -58796.010 20.048 8109.0622 0.1186 B- 2125.1534 20.0483 168 936879.890 21.522 + 33 101 68 169 Er -n -60921.163 0.304 8117.0078 0.0018 B- 353.4910 0.7729 168 934598.444 0.326 + 31 100 69 169 Tm -61274.654 0.738 8114.4702 0.0044 B- -899.1270 0.7563 168 934218.956 0.792 + 29 99 70 169 Yb -n -60375.527 0.178 8104.5206 0.0011 B- -2293.0000 3.0000 168 935184.208 0.191 + 27 98 71 169 Lu - -58082.527 3.005 8086.3233 0.0178 B- -3365.6321 28.1060 168 937645.845 3.226 + 25 97 72 169 Hf x -54716.895 27.945 8061.7791 0.1654 B- -4426.4600 39.5199 168 941259.000 30.000 + 23 96 73 169 Ta x -50290.435 27.945 8030.9577 0.1654 B- -5372.5686 31.9246 168 946011.000 30.000 + 21 95 74 169 W -44917.866 15.436 7994.5381 0.0913 B- -6508.6195 19.1703 168 951778.689 16.571 + 19 94 75 169 Re +a -38409.247 11.369 7951.3963 0.0673 B- -7686.2626 28.3218 168 958765.979 12.204 + 17 93 76 169 Os -a -30722.984 25.940 7901.2862 0.1535 B- -8629.5684 34.8557 168 967017.521 27.847 + 15 92 77 169 Ir +a -22093.416 23.307 7845.5944 0.1379 B- -9629# 202# 168 976281.743 25.020 + 13 91 78 169 Pt -a -12464# 200# 7784# 1# B- -10676# 359# 168 986619# 215# + 11 90 79 169 Au x -1788# 298# 7716# 2# B- * 168 998080# 320# +0 44 107 63 170 Eu x -30860# 500# 7963# 3# B- 9989# 707# 169 966870# 537# + 42 106 64 170 Gd x -40850# 500# 8017# 3# B- 5860# 583# 169 956146# 537# + 40 105 65 170 Tb x -46710# 300# 8047# 2# B- 7000# 361# 169 949855# 322# + 38 104 66 170 Dy x -53710# 200# 8084# 1# B- 2528# 206# 169 942340# 215# + 36 103 67 170 Ho + -56237.514 50.019 8093.7902 0.2942 B- 3870.0000 50.0000 169 939626.548 53.697 + 34 102 68 170 Er -60107.514 1.387 8111.9529 0.0082 B- -312.1997 1.7852 169 935471.933 1.488 + 32 101 69 170 Tm -59795.314 0.732 8105.5144 0.0043 B- 968.6148 0.7319 169 935807.093 0.785 + 30 100 70 170 Yb -60763.929 0.010 8106.6101 0.0003 B- -3457.6950 16.8430 169 934767.242 0.011 + 28 99 71 170 Lu - -57306.234 16.843 8081.6686 0.0991 B- -1052.3734 32.6282 169 938479.230 18.081 + 26 98 72 170 Hf x -56253.860 27.945 8070.8762 0.1644 B- -6116.1903 39.5199 169 939609.000 30.000 + 24 97 73 170 Ta x -50137.670 27.945 8030.2965 0.1644 B- -2846.8656 30.9035 169 946175.000 30.000 + 22 96 74 170 W -47290.804 13.195 8008.9482 0.0776 B- -8386.8083 17.4557 169 949231.235 14.165 + 20 95 75 170 Re -38903.996 11.427 7955.0120 0.0672 B- -4978.3046 15.0274 169 958234.844 12.267 + 18 94 76 170 Os -33925.692 9.759 7921.1258 0.0574 B- -10743# 102# 169 963579.273 10.476 + 16 93 77 170 Ir -a -23182# 101# 7853# 1# B- -6883# 102# 169 975113# 109# + 14 92 78 170 Pt -16299.202 18.246 7808.2365 0.1073 B- -12596# 202# 169 982502.087 19.588 + 12 91 79 170 Au -p -3703# 201# 7730# 1# B- -9119# 362# 169 996024# 216# + 10 90 80 170 Hg -a 5415# 302# 7671# 2# B- * 170 005814# 324# +0 43 107 64 171 Gd x -36210# 500# 7990# 3# B- 7560# 640# 170 961127# 537# + 41 106 65 171 Tb x -43770# 400# 8030# 2# B- 6240# 447# 170 953011# 429# + 39 105 66 171 Dy x -50010# 200# 8062# 1# B- 4508# 633# 170 946312# 215# + 37 104 67 171 Ho + -54517.822 600.002 8083.6021 3.5088 B- 3200.0000 600.0000 170 941472.713 644.128 + 35 103 68 171 Er -57717.822 1.408 8097.7404 0.0082 B- 1492.4490 1.0788 170 938037.372 1.511 + 33 102 69 171 Tm -59210.271 0.972 8101.8931 0.0057 B- 96.5468 0.9715 170 936435.162 1.043 + 31 101 70 171 Yb -59306.818 0.013 8097.8826 0.0003 B- -1478.3526 1.8621 170 936331.515 0.013 + 29 100 71 171 Lu -57828.465 1.862 8084.6621 0.0109 B- -2397.1144 28.9363 170 937918.591 1.999 + 27 99 72 171 Hf x -55431.351 28.876 8066.0687 0.1689 B- -3711.0725 40.1840 170 940492.000 31.000 + 25 98 73 171 Ta x -51720.279 27.945 8039.7914 0.1634 B- -4634.1832 39.5199 170 944476.000 30.000 + 23 97 74 171 W x -47086.095 27.945 8008.1158 0.1634 B- -5835.8106 39.5199 170 949451.000 30.000 + 21 96 75 171 Re x -41250.285 27.945 7969.4131 0.1634 B- -6953.0469 33.3748 170 955716.000 30.000 + 19 95 76 171 Os -34297.238 18.247 7924.1769 0.1067 B- -7885.2079 42.5749 170 963180.402 19.589 + 17 94 77 171 Ir -a -26412.030 38.466 7873.4895 0.2249 B- -8945.4613 89.6251 170 971645.520 41.295 + 15 93 78 171 Pt -a -17466.569 80.951 7816.6017 0.4734 B- -9904.2655 83.5586 170 981248.868 86.904 + 13 92 79 171 Au -p -7562.303 20.713 7754.1069 0.1211 B- -10901# 307# 170 991881.533 22.236 + 11 91 80 171 Hg -a 3339# 307# 7686# 2# B- * 171 003585# 329# +0 44 108 64 172 Gd x -32970# 300# 7972# 2# B- 6720# 583# 171 964605# 322# + 42 107 65 172 Tb x -39690# 500# 8006# 3# B- 8070# 583# 171 957391# 537# + 40 106 66 172 Dy x -47760# 300# 8049# 2# B- 3724# 358# 171 948728# 322# + 38 105 67 172 Ho x -51484# 196# 8066# 1# B- 4999# 196# 171 944730# 210# + 36 104 68 172 Er -56482.578 3.962 8090.4052 0.0230 B- 890.9756 4.5418 171 939363.461 4.253 + 34 103 69 172 Tm -57373.554 5.481 8091.0367 0.0319 B- 1881.9024 5.4814 171 938406.959 5.884 + 32 102 70 172 Yb -59255.456 0.014 8097.4295 0.0003 B- -2519.3805 2.3360 171 936386.654 0.014 + 30 101 71 172 Lu -56736.076 2.336 8078.2334 0.0136 B- -333.8443 24.5396 171 939091.320 2.507 + 28 100 72 172 Hf x -56402.232 24.428 8071.7439 0.1420 B- -5072.2490 37.1167 171 939449.716 26.224 + 26 99 73 172 Ta x -51329.983 27.945 8037.7056 0.1625 B- -2232.7914 39.5199 171 944895.000 30.000 + 24 98 74 172 W x -49097.191 27.945 8020.1757 0.1625 B- -7530.3525 45.2323 171 947292.000 30.000 + 22 97 75 172 Re -41566.839 35.568 7971.8460 0.2068 B- -4323.1979 37.7890 171 955376.165 38.183 + 20 96 76 172 Os -37243.641 12.766 7942.1626 0.0742 B- -9864.2673 34.8263 171 960017.309 13.704 + 18 95 77 172 Ir -a -27379.373 32.402 7880.2637 0.1884 B- -6272.7035 34.0232 171 970607.035 34.785 + 16 94 78 172 Pt -21106.670 10.376 7839.2460 0.0603 B- -11788.6592 57.1082 171 977341.059 11.139 + 14 93 79 172 Au -a -9318.011 56.158 7766.1587 0.3265 B- -8256.6495 140.8350 171 989996.704 60.287 + 12 92 80 172 Hg -a -1061.361 150.062 7713.6064 0.8725 B- * 171 998860.581 161.098 +0 43 108 65 173 Tb x -36510# 500# 7988# 3# B- 7230# 640# 172 960805# 537# + 41 107 66 173 Dy x -43740# 400# 8026# 2# B- 5610# 499# 172 953043# 429# + 39 106 67 173 Ho x -49351# 298# 8054# 2# B- 4304# 357# 172 947020# 320# + 37 105 68 173 Er x -53654# 196# 8074# 1# B- 2602# 196# 172 942400# 210# + 35 104 69 173 Tm p2n -56256.067 4.400 8084.4633 0.0254 B- 1295.1669 4.4000 172 939606.630 4.723 + 33 103 70 173 Yb -57551.234 0.011 8087.4276 0.0003 B- -670.2201 1.5674 172 938216.211 0.012 + 31 102 71 173 Lu -56881.014 1.567 8079.0312 0.0091 B- -1469.2244 27.9887 172 938935.722 1.682 + 29 101 72 173 Hf x -55411.790 27.945 8066.0164 0.1615 B- -3015.2464 39.5199 172 940513.000 30.000 + 27 100 73 173 Ta x -52396.543 27.945 8044.0650 0.1615 B- -3669.1553 39.5199 172 943750.000 30.000 + 25 99 74 173 W x -48727.388 27.945 8018.3337 0.1615 B- -5173.5182 39.5199 172 947689.000 30.000 + 23 98 75 173 Re x -43553.870 27.945 7983.9068 0.1615 B- -6115.6196 31.6968 172 953243.000 30.000 + 21 97 76 173 Os -37438.250 14.959 7944.0341 0.0865 B- -7169.7944 18.2998 172 959808.387 16.059 + 19 96 77 173 Ir -30268.456 10.542 7898.0680 0.0609 B- -8331.6974 64.3014 172 967505.477 11.316 + 17 95 78 173 Pt -a -21936.758 63.431 7845.3856 0.3667 B- -9104.7415 67.3903 172 976449.922 68.096 + 15 94 79 173 Au +a -12832.017 22.783 7788.2348 0.1317 B- -10171# 202# 172 986224.263 24.458 + 13 93 80 173 Hg -a -2661# 201# 7725# 1# B- * 172 997143# 215# +0 44 109 65 174 Tb x -31970# 500# 7963# 3# B- 9160# 707# 173 965679# 537# + 42 108 66 174 Dy x -41130# 500# 8011# 3# B- 4739# 583# 173 955845# 537# + 40 107 67 174 Ho x -45870# 300# 8034# 2# B- 6080# 423# 173 950757# 322# + 38 106 68 174 Er x -51949# 298# 8064# 2# B- 1915# 301# 173 944230# 320# + 36 105 69 174 Tm + -53864.521 44.721 8070.6432 0.2570 B- 3080.0000 44.7214 173 942174.061 48.010 + 34 104 70 174 Yb -56944.521 0.011 8083.8481 0.0003 B- -1374.2287 1.5675 173 938867.545 0.011 + 32 103 71 174 Lu -55570.292 1.567 8071.4540 0.0090 B- 274.2911 2.1686 173 940342.840 1.682 + 30 102 72 174 Hf -55844.583 2.259 8068.5341 0.0130 B- -4103.8117 28.0360 173 940048.377 2.425 + 28 101 73 174 Ta x -51740.771 27.945 8040.4528 0.1606 B- -1513.6779 39.5199 173 944454.000 30.000 + 26 100 74 174 W x -50227.093 27.945 8027.2572 0.1606 B- -6553.9925 39.5199 173 946079.000 30.000 + 24 99 75 174 Re x -43673.101 27.945 7985.0944 0.1606 B- -3677.7177 29.7667 173 953115.000 30.000 + 22 98 76 174 Os -39995.383 10.254 7959.4618 0.0589 B- -9209.4466 15.2008 173 957063.192 11.008 + 20 97 77 174 Ir +a -30785.937 11.221 7902.0377 0.0645 B- -5468.3293 15.2578 173 966949.939 12.046 + 18 96 78 174 Pt -a -25317.608 10.338 7866.1143 0.0594 B- -11259# 102# 173 972820.431 11.098 + 16 95 79 174 Au -a -14058# 102# 7797# 1# B- -7417# 102# 173 984908# 109# + 14 94 80 174 Hg -a -6641.017 19.211 7749.7851 0.1104 B- * 173 992870.575 20.623 +0 43 109 66 175 Dy x -36730# 500# 7986# 3# B- 6570# 640# 174 960569# 537# + 41 108 67 175 Ho x -43300# 400# 8019# 2# B- 5352# 566# 174 953516# 429# + 39 107 68 175 Er x -48652# 401# 8045# 2# B- 3659# 404# 174 947770# 430# + 37 106 69 175 Tm + -52310.556 50.000 8061.7673 0.2857 B- 2385.0000 50.0000 174 943842.310 53.677 + 35 105 70 175 Yb -54695.556 0.071 8070.9253 0.0005 B- 470.1219 1.2068 174 941281.907 0.076 + 33 104 71 175 Lu -55165.678 1.207 8069.1412 0.0069 B- -683.9154 1.9516 174 940777.211 1.295 + 31 103 72 175 Hf -54481.763 2.283 8060.7625 0.0130 B- -2073.1103 28.0379 174 941511.424 2.450 + 29 102 73 175 Ta x -52408.653 27.945 8044.4456 0.1597 B- -2775.8524 39.5199 174 943737.000 30.000 + 27 101 74 175 W x -49632.800 27.945 8024.1130 0.1597 B- -4344.4885 39.5199 174 946717.000 30.000 + 25 100 75 175 Re x -45288.312 27.945 7994.8168 0.1597 B- -5182.9513 30.3243 174 951381.000 30.000 + 23 99 76 175 Os -40105.360 11.775 7960.7294 0.0673 B- -6710.8496 17.0887 174 956945.126 12.640 + 21 98 77 175 Ir -33394.511 12.384 7917.9112 0.0708 B- -7685.8265 22.3572 174 964149.519 13.295 + 19 97 78 175 Pt -25708.684 18.614 7869.5216 0.1064 B- -8304.9980 42.8203 174 972400.593 19.982 + 17 96 79 175 Au -a -17403.686 38.563 7817.5939 0.2204 B- -9434.2436 89.7876 174 981316.375 41.399 + 15 95 80 175 Hg -a -7969.443 81.085 7759.2134 0.4633 B- * 174 991444.451 87.047 +0 44 110 66 176 Dy x -33610# 500# 7969# 3# B- 5780# 707# 175 963918# 537# + 42 109 67 176 Ho x -39390# 500# 7997# 3# B- 7241# 641# 175 957713# 537# + 40 108 68 176 Er x -46631# 401# 8034# 2# B- 2741# 413# 175 949940# 430# + 38 107 69 176 Tm + -49371.322 100.000 8045.1214 0.5682 B- 4120.0000 100.0000 175 946997.707 107.354 + 36 106 70 176 Yb -53491.322 0.014 8064.0853 0.0003 B- -108.9895 1.2124 175 942574.706 0.015 + 34 105 71 176 Lu -53382.333 1.212 8059.0209 0.0069 B- 1194.0947 0.8744 175 942691.711 1.301 + 32 104 72 176 Hf -54576.428 1.482 8061.3604 0.0084 B- -3211.0484 30.7750 175 941409.797 1.591 + 30 103 73 176 Ta x -51365.379 30.739 8038.6706 0.1747 B- -723.7709 41.5430 175 944857.000 33.000 + 28 102 74 176 W x -50641.608 27.945 8030.1131 0.1588 B- -5578.7182 39.5199 175 945634.000 30.000 + 26 101 75 176 Re x -45062.890 27.945 7993.9707 0.1588 B- -2931.7058 30.0134 175 951623.000 30.000 + 24 100 76 176 Os -42131.184 10.949 7972.8681 0.0622 B- -8249.2618 13.6110 175 954770.315 11.754 + 22 99 77 176 Ir -33881.923 8.085 7921.5522 0.0459 B- -4948.0041 15.0657 175 963626.261 8.679 + 20 98 78 176 Pt -28933.918 12.712 7888.9934 0.0722 B- -10412.9516 35.5363 175 968938.162 13.647 + 18 97 79 176 Au -a -18520.967 33.185 7825.3837 0.1885 B- -6736.3283 34.9978 175 980116.925 35.625 + 16 96 80 176 Hg -11784.639 11.118 7782.6640 0.0632 B- -12369.3668 83.7993 175 987348.670 11.936 + 14 95 81 176 Tl -p 584.728 83.058 7707.9383 0.4719 B- * 176 000627.731 89.166 +0 43 110 67 177 Ho x -36280# 500# 7980# 3# B- 6578# 709# 176 961052# 537# + 41 109 68 177 Er x -42858# 503# 8013# 3# B- 4711# 541# 176 953990# 540# + 39 108 69 177 Tm x -47570# 200# 8035# 1# B- 3417# 200# 176 948932# 215# + 37 107 70 177 Yb -n -50986.404 0.220 8049.9741 0.0013 B- 1397.4983 1.2406 176 945263.846 0.236 + 35 106 71 177 Lu -52383.903 1.221 8053.4495 0.0069 B- 496.8425 0.7921 176 943763.570 1.310 + 33 105 72 177 Hf -52880.745 1.410 8051.8365 0.0080 B- -1166.0000 3.0000 176 943230.187 1.514 + 31 104 73 177 Ta - -51714.745 3.315 8040.8289 0.0187 B- -2013.0144 28.1408 176 944481.940 3.558 + 29 103 74 177 W x -49701.731 27.945 8025.0359 0.1579 B- -3432.5558 39.5199 176 946643.000 30.000 + 27 102 75 177 Re x -46269.175 27.945 8001.2229 0.1579 B- -4312.7271 31.5349 176 950328.000 30.000 + 25 101 76 177 Os +a -41956.448 14.613 7972.4371 0.0826 B- -5909.0234 24.5763 176 954957.902 15.687 + 23 100 77 177 Ir x -36047.425 19.760 7934.6328 0.1116 B- -6676.9880 24.8010 176 961301.500 21.213 + 21 99 78 177 Pt -29370.437 14.988 7892.4896 0.0847 B- -7824.7003 17.9991 176 968469.541 16.090 + 19 98 79 177 Au -21545.736 9.968 7843.8623 0.0563 B- -8769.9135 85.3061 176 976869.701 10.700 + 17 97 80 177 Hg -a -12775.823 84.722 7789.8947 0.4787 B- -9435.7198 87.4322 176 986284.590 90.952 + 15 96 81 177 Tl IT -3340.103 21.628 7732.1655 0.1222 B- * 176 996414.252 23.218 +0 44 111 67 178 Ho x -32130# 500# 7957# 3# B- 8130# 778# 177 965507# 537# + 42 110 68 178 Er x -40260# 596# 7999# 3# B- 3980# 667# 177 956779# 640# + 40 109 69 178 Tm x -44240# 300# 8017# 2# B- 5437# 300# 177 952506# 322# + 38 108 70 178 Yb -49677.139 6.588 8042.7386 0.0370 B- 660.7415 6.9617 177 946669.400 7.072 + 36 107 71 178 Lu -50337.881 2.251 8042.0554 0.0127 B- 2097.4851 2.0569 177 945960.065 2.416 + 34 106 72 178 Hf -52435.366 1.415 8049.4438 0.0080 B- -1837# 52# 177 943708.322 1.519 + 32 105 73 178 Ta IT -50598# 52# 8035# 0# B- -191# 50# 177 945680# 56# + 30 104 74 178 W - -50407.066 15.199 8029.2584 0.0854 B- -4753.6082 31.8106 177 945885.791 16.316 + 28 103 75 178 Re x -45653.457 27.945 7998.1576 0.1570 B- -2109.2143 31.0925 177 950989.000 30.000 + 26 102 76 178 Os -43544.243 13.632 7981.9128 0.0766 B- -7289.9295 23.2390 177 953253.334 14.634 + 24 101 77 178 Ir -36254.314 18.821 7936.5630 0.1057 B- -4256.8282 21.3752 177 961079.395 20.204 + 22 100 78 178 Pt -31997.486 10.133 7908.2530 0.0569 B- -9694.4567 14.4108 177 965649.288 10.878 + 20 99 79 178 Au x -22303.029 10.246 7849.3946 0.0576 B- -5987.6832 14.8566 177 976056.714 11.000 + 18 98 80 178 Hg -a -16315.346 10.758 7811.3607 0.0604 B- -11702# 103# 177 982484.756 11.548 + 16 97 81 178 Tl -a -4613# 102# 7741# 1# B- -8187# 103# 177 995047# 110# + 14 96 82 178 Pb -a 3573.371 23.184 7690.8359 0.1302 B- * 178 003836.171 24.889 +0 43 111 68 179 Er x -36080# 500# 7976# 3# B- 5821# 640# 178 961267# 537# + 41 110 69 179 Tm x -41900# 400# 8004# 2# B- 4739# 447# 178 955018# 429# + 39 109 70 179 Yb x -46640# 200# 8026# 1# B- 2419# 200# 178 949930# 215# + 37 108 71 179 Lu -49059.013 5.150 8035.0744 0.0288 B- 1404.0231 5.0672 178 947332.985 5.528 + 35 107 72 179 Hf -50463.036 1.416 8038.5474 0.0079 B- -105.5801 0.4088 178 945825.705 1.520 + 33 106 73 179 Ta -50357.456 1.466 8033.5869 0.0082 B- -1062.2093 14.5197 178 945939.050 1.574 + 31 105 74 179 W -49295.247 14.573 8023.2821 0.0814 B- -2710.9347 26.8021 178 947079.378 15.644 + 29 104 75 179 Re -46584.312 24.639 8003.7666 0.1376 B- -3564.1747 29.1116 178 949989.686 26.450 + 27 103 76 179 Os -43020.137 15.505 7979.4844 0.0866 B- -4938.4182 18.3271 178 953815.985 16.645 + 25 102 77 179 Ir -38081.719 9.771 7947.5248 0.0546 B- -5813.5920 12.6133 178 959117.594 10.489 + 23 101 78 179 Pt -32268.127 7.977 7910.6759 0.0446 B- -7279.5556 14.1567 178 965358.742 8.563 + 21 100 79 179 Au -24988.572 11.696 7865.6374 0.0653 B- -8055.6480 30.4559 178 973173.666 12.555 + 19 99 80 179 Hg -16932.924 28.121 7816.2631 0.1571 B- -8663.2918 47.7998 178 981821.759 30.188 + 17 98 81 179 Tl -a -8269.632 38.653 7763.4942 0.2159 B- -10321.2401 89.9571 178 991122.185 41.495 + 15 97 82 179 Pb -a 2051.608 81.229 7701.4630 0.4538 B- * 179 002202.492 87.203 +0 44 112 68 180 Er x -33180# 500# 7960# 3# B- 4990# 640# 179 964380# 537# + 42 111 69 180 Tm x -38170# 400# 7983# 2# B- 6550# 500# 179 959023# 429# + 40 110 70 180 Yb x -44720# 300# 8016# 2# B- 1956# 308# 179 951991# 322# + 38 109 71 180 Lu + -46676.476 70.725 8022.0394 0.3929 B- 3103.0000 70.7107 179 949890.744 75.926 + 36 108 72 180 Hf -49779.476 1.421 8034.9319 0.0079 B- -845.8453 2.3472 179 946559.537 1.525 + 34 107 73 180 Ta +n -48933.631 2.068 8025.8864 0.0115 B- 702.6122 2.3590 179 947467.589 2.219 + 32 106 74 180 W -49636.243 1.439 8025.4434 0.0080 B- -3798.8793 21.4404 179 946713.304 1.545 + 30 105 75 180 Re x -45837.364 21.392 7999.9922 0.1188 B- -1481.1659 26.5482 179 950791.568 22.965 + 28 104 76 180 Os -44356.198 15.722 7987.4171 0.0873 B- -6378.6679 26.8021 179 952381.665 16.878 + 26 103 77 180 Ir x -37977.530 21.706 7947.6337 0.1206 B- -3547.6546 23.9205 179 959229.446 23.302 + 24 102 78 180 Pt -34429.875 10.051 7923.5781 0.0558 B- -8804.2290 11.1207 179 963038.010 10.790 + 22 101 79 180 Au -25625.646 4.759 7870.3194 0.0264 B- -5375.1330 13.5105 179 972489.738 5.108 + 20 100 80 180 Hg -20250.513 12.645 7836.1111 0.0702 B- -10860.0750 71.0509 179 978260.180 13.574 + 18 99 81 180 Tl -a -9390.438 69.917 7771.4310 0.3884 B- -7449.3696 71.0069 179 989918.950 75.058 + 16 98 82 180 Pb -a -1941.069 12.395 7725.6993 0.0689 B- * 179 997916.177 13.306 +0 43 112 69 181 Tm x -35440# 500# 7969# 3# B- 5649# 582# 180 961954# 537# + 41 111 70 181 Yb x -41088# 298# 7996# 2# B- 3709# 324# 180 955890# 320# + 39 110 71 181 Lu x -44797.414 125.752 8011.9301 0.6948 B- 2605.5435 125.7598 180 951908.000 135.000 + 37 109 72 181 Hf -n -47402.958 1.423 8022.0030 0.0079 B- 1036.1061 1.9298 180 949110.834 1.527 + 35 108 73 181 Ta -48439.064 1.576 8023.4050 0.0087 B- -205.1193 1.9495 180 947998.528 1.692 + 33 107 74 181 W -n -48233.945 1.448 8017.9494 0.0080 B- -1716.5331 12.6289 180 948218.733 1.554 + 31 106 75 181 Re 4n -46517.412 12.549 8004.1434 0.0693 B- -2967.4438 28.2755 180 950061.507 13.471 + 29 105 76 181 Os -43549.968 25.338 7983.4263 0.1400 B- -4086.9327 25.8756 180 953247.188 27.201 + 27 104 77 181 Ir +a -39463.035 5.245 7956.5242 0.0290 B- -5081.5379 14.6597 180 957634.691 5.631 + 25 103 78 181 Pt -34381.497 13.689 7924.1271 0.0756 B- -6510.3575 24.2164 180 963089.946 14.695 + 23 102 79 181 Au -a -27871.140 19.976 7883.8359 0.1104 B- -7210.0126 25.2123 180 970079.102 21.445 + 21 101 80 181 Hg -20661.127 15.382 7839.6792 0.0850 B- -7862.3780 17.8730 180 977819.368 16.513 + 19 100 81 181 Tl -12798.749 9.102 7791.9183 0.0503 B- -9688.1182 85.5227 180 986259.978 9.771 + 17 99 82 181 Pb -a -3110.631 85.037 7734.0704 0.4698 B- * 180 996660.600 91.290 +0 44 113 69 182 Tm x -31490# 500# 7948# 3# B- 7410# 640# 181 966194# 537# + 42 112 70 182 Yb x -38900# 400# 7984# 2# B- 2870# 447# 181 958239# 429# + 40 111 71 182 Lu x -41770# 200# 7996# 1# B- 4280# 200# 181 955158# 215# + 38 110 72 182 Hf -nn -46049.636 6.166 8014.8381 0.0339 B- 381.0486 6.3027 181 950563.684 6.619 + 36 109 73 182 Ta -46430.685 1.578 8012.6332 0.0087 B- 1815.4592 1.5276 181 950154.612 1.693 + 34 108 74 182 W -48246.144 0.745 8018.3096 0.0041 B- -2800.0000 101.9804 181 948205.636 0.799 + 32 107 75 182 Re IT -45446.144 101.983 7998.6264 0.5603 B- -837.0348 104.2757 181 951211.560 109.483 + 30 106 76 182 Os -44609.109 21.745 7989.7287 0.1195 B- -5557.4266 30.2074 181 952110.154 23.344 + 28 105 77 182 Ir -39051.682 20.967 7954.8948 0.1152 B- -2883.2620 24.7202 181 958076.296 22.509 + 26 104 78 182 Pt -36168.420 13.095 7934.7541 0.0719 B- -7864.4447 22.8812 181 961171.605 14.057 + 24 103 79 182 Au -28303.976 18.764 7887.2442 0.1031 B- -4727.0905 21.1645 181 969614.433 20.143 + 22 102 80 182 Hg -23576.885 9.790 7856.9726 0.0538 B- -10249.6721 15.4687 181 974689.173 10.510 + 20 101 81 182 Tl -a -13327.213 11.976 7796.3571 0.0658 B- -6502.6567 17.0151 181 985692.649 12.856 + 18 100 82 182 Pb -a -6824.556 12.086 7756.3296 0.0664 B- * 181 992673.537 12.975 +0 43 113 70 183 Yb x -35000# 400# 7963# 2# B- 4716# 408# 182 962426# 429# + 41 112 71 183 Lu x -39716.114 80.108 7984.8125 0.4378 B- 3567.4325 85.5564 182 957363.000 86.000 + 39 111 72 183 Hf + -43283.547 30.042 8000.0315 0.1642 B- 2010.0000 30.0000 182 953533.203 32.251 + 37 110 73 183 Ta -n -45293.547 1.590 8006.7400 0.0087 B- 1072.1161 1.5405 182 951375.380 1.707 + 35 109 74 183 W -46365.663 0.743 8008.3234 0.0041 B- -556.0000 8.0000 182 950224.416 0.798 + 33 108 75 183 Re - -45809.663 8.034 8001.0101 0.0439 B- -2145.9028 50.4129 182 950821.306 8.625 + 31 107 76 183 Os -43663.760 49.769 7985.0087 0.2720 B- -3461.6215 52.8061 182 953125.028 53.428 + 29 106 77 183 Ir -40202.138 24.672 7961.8176 0.1348 B- -4428.9417 28.4743 182 956841.231 26.486 + 27 105 78 183 Pt -35773.197 14.216 7933.3406 0.0777 B- -5581.7092 17.0554 182 961595.895 15.261 + 25 104 79 183 Au -30191.488 9.423 7898.5644 0.0515 B- -6386.8322 11.7891 182 967588.106 10.116 + 23 103 80 183 Hg -23804.655 7.084 7859.3885 0.0387 B- -7217.3941 11.7158 182 974444.652 7.604 + 21 102 81 183 Tl -16587.261 9.331 7815.6741 0.0510 B- -9007.2534 30.4442 182 982192.843 10.017 + 19 101 82 183 Pb -a -7580.008 28.979 7762.1790 0.1584 B- * 182 991862.527 31.110 +0 44 114 70 184 Yb x -32600# 503# 7951# 3# B- 3700# 541# 183 965002# 540# + 42 113 71 184 Lu x -36300# 200# 7967# 1# B- 5199# 204# 183 961030# 215# + 40 112 72 184 Hf + -41499.453 39.706 7990.7228 0.2158 B- 1340.0000 30.0000 183 955448.507 42.625 + 38 111 73 184 Ta + -42839.453 26.010 7993.7535 0.1414 B- 2866.0000 26.0000 183 954009.958 27.923 + 36 110 74 184 W -45705.453 0.738 8005.0777 0.0040 B- -1485.6333 4.1971 183 950933.180 0.792 + 34 109 75 184 Re -44219.819 4.276 7992.7517 0.0232 B- 32.7460 4.1387 183 952528.073 4.590 + 32 108 76 184 Os -44252.565 0.829 7988.6778 0.0045 B- -4641.7101 27.9571 183 952492.919 0.890 + 30 107 77 184 Ir x -39610.855 27.945 7959.1992 0.1519 B- -2278.3688 31.5957 183 957476.000 30.000 + 28 106 78 184 Pt -37332.486 14.744 7942.5649 0.0801 B- -7013.7724 26.7122 183 959921.929 15.828 + 26 105 79 184 Au -a -30318.714 22.275 7900.1947 0.1211 B- -3973.9269 24.2296 183 967451.523 23.912 + 24 104 80 184 Hg -26344.787 9.535 7874.3454 0.0518 B- -9461.4321 13.8254 183 971717.709 10.235 + 22 103 81 184 Tl -16883.355 10.012 7818.6727 0.0544 B- -5831.7688 16.2517 183 981874.973 10.747 + 20 102 82 184 Pb -11051.586 12.802 7782.7264 0.0696 B- -12306# 123# 183 988135.634 13.743 + 18 101 83 184 Bi -a 1254# 122# 7712# 1# B- * 184 001347# 131# +0 45 115 70 185 Yb x -28480# 500# 7929# 3# B- 5480# 583# 184 969425# 537# + 43 114 71 185 Lu x -33960# 300# 7955# 2# B- 4359# 307# 184 963542# 322# + 41 113 72 185 Hf x -38319.804 64.273 7973.9711 0.3474 B- 3074.5667 65.8147 184 958862.000 69.000 + 39 112 73 185 Ta + -41394.371 14.161 7986.3615 0.0765 B- 1993.5000 14.1421 184 955561.317 15.202 + 37 111 74 185 W -43387.871 0.739 7992.9083 0.0040 B- 431.1764 0.6616 184 953421.206 0.793 + 35 110 75 185 Re -43819.047 0.820 7991.0101 0.0044 B- -1013.1393 0.4190 184 952958.320 0.879 + 33 109 76 185 Os -42805.908 0.832 7981.3047 0.0045 B- -2470.3505 27.9572 184 954045.969 0.893 + 31 108 77 185 Ir x -40335.558 27.945 7963.7226 0.1511 B- -3647.4137 38.0554 184 956698.000 30.000 + 29 107 78 185 Pt -36688.144 25.832 7939.7779 0.1396 B- -4829.9942 25.9635 184 960613.659 27.731 + 27 106 79 185 Au x -31858.150 2.608 7909.4410 0.0141 B- -5674.4989 13.8859 184 965798.871 2.800 + 25 105 80 185 Hg -26183.651 13.639 7874.5391 0.0737 B- -6425.9062 24.7674 184 971890.696 14.641 + 23 104 81 185 Tl IT -19757.745 20.674 7835.5756 0.1118 B- -8216.5333 26.2493 184 978789.189 22.194 + 21 103 82 185 Pb -a -11541.211 16.175 7786.9330 0.0874 B- -9305# 83# 184 987610.000 17.364 + 19 102 83 185 Bi IT -2236# 81# 7732# 0# B- * 184 997600# 87# +0 44 115 71 186 Lu x -30320# 400# 7936# 2# B- 6104# 403# 185 967450# 429# + 42 114 72 186 Hf x -36424.214 51.232 7964.3032 0.2754 B- 2183.3883 78.9063 185 960897.000 55.000 + 40 113 73 186 Ta + -38607.602 60.012 7971.8357 0.3226 B- 3901.0000 60.0000 185 958553.036 64.425 + 38 112 74 186 W -42508.602 1.213 7988.6026 0.0065 B- -581.2819 1.2386 185 954365.140 1.302 + 36 111 75 186 Re -41927.320 0.820 7981.2713 0.0044 B- 1072.7114 0.8337 185 954989.172 0.880 + 34 110 76 186 Os -43000.032 0.761 7982.8324 0.0041 B- -3827.6813 16.5430 185 953837.569 0.816 + 32 109 77 186 Ir x -39172.350 16.526 7958.0473 0.0888 B- -1307.9030 27.3122 185 957946.754 17.740 + 30 108 78 186 Pt -37864.447 21.745 7946.8094 0.1169 B- -6149.5913 30.2074 185 959350.845 23.344 + 28 107 79 186 Au -31714.856 20.967 7909.5409 0.1127 B- -3175.7972 23.9866 185 965952.703 22.509 + 26 106 80 186 Hg -28539.059 11.650 7888.2605 0.0626 B- -8656.1190 23.7974 185 969362.061 12.507 + 24 105 81 186 Tl -19882.940 20.751 7837.5161 0.1116 B- -5202.0427 23.4877 185 978654.787 22.276 + 22 104 82 186 Pb -a -14680.897 11.004 7805.3420 0.0592 B- -11535.3999 20.2118 185 984239.409 11.813 + 20 103 83 186 Bi -a -3145.497 16.954 7739.1175 0.0911 B- -7247.0279 24.9305 185 996623.169 18.200 + 18 102 84 186 Po -a 4101.531 18.278 7695.9488 0.0983 B- * 186 004403.174 19.622 +0 45 116 71 187 Lu x -27770# 400# 7923# 2# B- 5230# 447# 186 970188# 429# + 43 115 72 187 Hf x -33000# 200# 7947# 1# B- 3896# 208# 186 964573# 215# + 41 114 73 187 Ta x -36895.550 55.890 7963.2123 0.2989 B- 3008.4937 55.9028 186 960391.000 60.000 + 39 113 74 187 W -39904.044 1.213 7975.1168 0.0065 B- 1312.5048 1.1219 186 957161.249 1.302 + 37 112 75 187 Re -41216.548 0.737 7977.9519 0.0039 B- 2.4667 0.0016 186 955752.217 0.791 + 35 111 76 187 Os -41219.015 0.737 7973.7814 0.0039 B- -1669.6385 27.9545 186 955749.569 0.791 + 33 110 77 187 Ir x -39549.377 27.945 7960.6692 0.1494 B- -2864.0151 36.8802 186 957542.000 30.000 + 31 109 78 187 Pt -36685.361 24.067 7941.1699 0.1287 B- -3656.5811 27.4478 186 960616.646 25.837 + 29 108 79 187 Au -33028.780 22.499 7917.4323 0.1203 B- -4910.2713 25.9171 186 964542.147 24.153 + 27 107 80 187 Hg -28118.509 12.864 7886.9905 0.0688 B- -5673.9170 15.1746 186 969813.540 13.810 + 25 106 81 187 Tl -22444.592 8.048 7852.4650 0.0430 B- -7457.6370 9.5248 186 975904.740 8.640 + 23 105 82 187 Pb -14986.955 5.094 7808.4010 0.0272 B- -8603.6798 11.2268 186 983910.842 5.468 + 21 104 83 187 Bi -a -6383.275 10.005 7758.2083 0.0535 B- -9207.0832 34.1302 186 993147.272 10.740 + 19 103 84 187 Po -a 2823.808 32.631 7704.7889 0.1745 B- * 187 003031.482 35.030 +0 46 117 71 188 Lu x -23820# 400# 7903# 2# B- 7009# 500# 187 974428# 429# + 44 116 72 188 Hf x -30830# 300# 7936# 2# B- 3080# 361# 187 966903# 322# + 42 115 73 188 Ta x -33910# 200# 7948# 1# B- 4758# 200# 187 963596# 215# + 40 114 74 188 W + -38667.880 3.089 7969.0532 0.0164 B- 349.0000 3.0000 187 958488.325 3.316 + 38 113 75 188 Re -n -39016.880 0.738 7966.7481 0.0039 B- 2120.4209 0.1520 187 958113.658 0.792 + 36 112 76 188 Os -41137.301 0.734 7973.8656 0.0039 B- -2792.3457 9.4164 187 955837.292 0.788 + 34 111 77 188 Ir -38344.955 9.423 7954.8512 0.0501 B- -523.9860 8.6863 187 958834.999 10.116 + 32 110 78 188 Pt -37820.970 5.305 7947.9027 0.0282 B- -5449.6549 5.9528 187 959397.521 5.694 + 30 109 79 188 Au x -32371.315 2.701 7914.7537 0.0144 B- -2172.9634 7.3046 187 965247.966 2.900 + 28 108 80 188 Hg -30198.351 6.787 7899.0340 0.0361 B- -7861.9485 30.6643 187 967580.738 7.285 + 26 107 81 188 Tl x -22336.403 29.904 7853.0537 0.1591 B- -4525.3784 31.5712 187 976020.886 32.103 + 24 106 82 188 Pb -a -17811.024 10.124 7824.8211 0.0539 B- -10616.2241 15.0824 187 980879.079 10.868 + 22 105 83 188 Bi -a -7194.800 11.179 7764.1904 0.0595 B- -6650.4226 22.8861 187 992276.064 12.001 + 20 104 84 188 Po -a -544.378 19.970 7724.6544 0.1062 B- * 187 999415.586 21.438 +0 45 117 72 189 Hf x -27150# 300# 7917# 2# B- 4809# 361# 188 970853# 322# + 43 116 73 189 Ta x -31960# 200# 7938# 1# B- 3850# 283# 188 965690# 215# + 41 115 74 189 W + -35809# 200# 7954# 1# B- 2170# 200# 188 961557# 215# + 39 114 75 189 Re +p -37979.097 8.191 7961.8105 0.0433 B- 1007.7049 8.1671 188 959227.764 8.793 + 37 113 76 189 Os -38986.802 0.666 7963.0029 0.0035 B- -537.1494 12.5630 188 958145.949 0.715 + 35 112 77 189 Ir -38449.652 12.576 7956.0214 0.0665 B- -1980.2470 13.6363 188 958722.602 13.500 + 33 111 78 189 Pt -36469.405 10.090 7941.4045 0.0534 B- -2887.4471 22.4737 188 960848.485 10.832 + 31 110 79 189 Au x -33581.958 20.081 7921.9876 0.1063 B- -3955.5800 37.4009 188 963948.286 21.558 + 29 109 80 189 Hg -29626.378 31.553 7896.9192 0.1669 B- -5010.2727 32.6434 188 968194.776 33.873 + 27 108 81 189 Tl -24616.105 8.368 7866.2704 0.0443 B- -6772.0862 16.3636 188 973573.525 8.983 + 25 107 82 189 Pb -17844.019 14.062 7826.2999 0.0744 B- -7779.3555 25.1498 188 980843.658 15.096 + 23 106 83 189 Bi -a -10064.664 20.851 7780.9999 0.1103 B- -8642.6682 30.3542 188 989195.139 22.384 + 21 105 84 189 Po -a -1421.996 22.059 7731.1321 0.1167 B- * 188 998473.425 23.681 +0 46 118 72 190 Hf x -24800# 400# 7905# 2# B- 3920# 447# 189 973376# 429# + 44 117 73 190 Ta x -28720# 200# 7922# 1# B- 5649# 203# 189 969168# 215# + 42 116 74 190 W -34368.832 35.391 7947.5031 0.1863 B- 1214.1824 35.5545 189 963103.542 37.993 + 40 115 75 190 Re -35583.015 4.870 7949.7759 0.0256 B- 3124.8105 4.7864 189 961800.064 5.227 + 38 114 76 190 Os -38707.825 0.650 7962.1047 0.0034 B- -1954.2108 1.2131 189 958445.442 0.697 + 36 113 77 190 Ir +n -36753.614 1.370 7947.7017 0.0072 B- 552.8893 1.2822 189 960543.374 1.470 + 34 112 78 190 Pt -37306.504 0.657 7946.4941 0.0035 B- -4472.9637 3.5086 189 959949.823 0.705 + 32 111 79 190 Au x -32833.540 3.447 7918.8345 0.0181 B- -1462.9150 16.2760 189 964751.746 3.700 + 30 110 80 190 Hg -31370.625 15.907 7907.0174 0.0837 B- -7004.3892 17.4819 189 966322.250 17.076 + 28 109 81 190 Tl +a -24366.236 7.252 7866.0345 0.0382 B- -3949.6288 14.4634 189 973841.771 7.784 + 26 108 82 190 Pb -a -20416.607 12.514 7841.1294 0.0659 B- -9820.7014 24.4226 189 978081.872 13.434 + 24 107 83 190 Bi -a -10595.906 20.973 7785.3239 0.1104 B- -6033.1975 24.7615 189 988624.828 22.515 + 22 106 84 190 Po -a -4562.708 13.163 7749.4526 0.0693 B- * 189 995101.731 14.131 +0 45 118 73 191 Ta x -26520# 300# 7911# 2# B- 4657# 303# 190 971530# 322# + 43 117 74 191 W x -31176.176 41.917 7931.4359 0.2195 B- 3174.2318 43.1556 190 966531.000 45.000 + 41 116 75 191 Re +p -34350.408 10.264 7943.9588 0.0537 B- 2044.8311 10.2443 190 963123.322 11.019 + 39 115 76 191 Os -36395.239 0.659 7950.5687 0.0035 B- 313.5873 1.1410 190 960928.105 0.707 + 37 114 77 191 Ir -36708.826 1.310 7948.1144 0.0069 B- -1010.4903 3.6360 190 960591.455 1.406 + 35 113 78 191 Pt -35698.336 4.127 7938.7279 0.0216 B- -1900.4257 6.4260 190 961676.261 4.430 + 33 112 79 191 Au -33797.910 4.926 7924.6819 0.0258 B- -3206.0616 22.7103 190 963716.452 5.288 + 31 111 80 191 Hg -30591.849 22.280 7903.8002 0.1167 B- -4308.8981 23.4609 190 967158.301 23.918 + 29 110 81 191 Tl +a -26282.951 7.349 7877.1445 0.0385 B- -5991.7073 9.8864 190 971784.093 7.889 + 27 109 82 191 Pb -20291.243 6.613 7841.6782 0.0346 B- -7051.8922 9.9895 190 978216.455 7.099 + 25 108 83 191 Bi -13239.351 7.487 7800.6613 0.0392 B- -8170.6205 10.3201 190 985786.972 8.037 + 23 107 84 191 Po -5068.731 7.103 7753.7871 0.0372 B- -8932.6440 17.5997 190 994558.494 7.624 + 21 106 85 191 At -a 3863.913 16.103 7702.9233 0.0843 B- * 191 004148.081 17.287 +0 46 119 73 192 Ta x -23100# 400# 7894# 2# B- 6520# 447# 191 975201# 429# + 44 118 74 192 W x -29620# 200# 7924# 1# B- 1969# 212# 191 968202# 215# + 42 117 75 192 Re x -31588.828 70.794 7930.2389 0.3687 B- 4293.4750 70.8314 191 966088.000 76.000 + 40 116 76 192 Os -35882.303 2.314 7948.5260 0.0121 B- -1046.6722 2.3962 191 961478.765 2.484 + 38 115 77 192 Ir -34835.631 1.314 7938.9999 0.0068 B- 1452.8946 2.2739 191 962602.414 1.410 + 36 114 78 192 Pt -36288.525 2.570 7942.4923 0.0134 B- -3516.3415 15.6174 191 961042.667 2.758 + 34 113 79 192 Au - -32772.184 15.827 7920.1033 0.0824 B- -760.7028 22.1777 191 964817.615 16.991 + 32 112 80 192 Hg x -32011.481 15.537 7912.0666 0.0809 B- -6139.2324 35.2767 191 965634.263 16.679 + 30 111 81 192 Tl x -25872.249 31.671 7876.0167 0.1650 B- -3320.4029 32.1843 191 972225.000 34.000 + 28 110 82 192 Pb -22551.846 5.726 7854.6482 0.0298 B- -9017.3089 30.6518 191 975789.598 6.147 + 26 109 83 192 Bi -a -13534.537 30.112 7803.6084 0.1568 B- -5468.0534 31.9348 191 985470.077 32.326 + 24 108 84 192 Po -a -8066.483 10.634 7771.0542 0.0554 B- -10992.2252 29.8328 191 991340.274 11.416 + 22 107 85 192 At -a 2925.742 27.873 7709.7283 0.1452 B- * 192 003140.912 29.922 +0 47 120 73 193 Ta x -20810# 400# 7883# 2# B- 5380# 447# 192 977660# 429# + 45 119 74 193 W x -26190# 200# 7907# 1# B- 4042# 204# 192 971884# 215# + 43 118 75 193 Re x -30231.641 39.123 7923.9378 0.2027 B- 3162.7597 39.1915 192 967545.000 42.000 + 41 117 76 193 Os -33394.401 2.320 7936.2716 0.0120 B- 1141.9038 2.4000 192 964149.637 2.490 + 39 116 77 193 Ir -34536.305 1.327 7938.1346 0.0069 B- -56.6276 0.2997 192 962923.753 1.425 + 37 115 78 193 Pt -34479.677 1.359 7933.7875 0.0070 B- -1074.8477 8.7676 192 962984.546 1.458 + 35 114 79 193 Au -33404.829 8.674 7924.1648 0.0449 B- -2342.6641 14.3702 192 964138.442 9.311 + 33 113 80 193 Hg -31062.165 15.505 7907.9730 0.0803 B- -3584.9466 16.8938 192 966653.395 16.645 + 31 112 81 193 Tl x -27477.218 6.707 7885.3445 0.0348 B- -5247.9637 12.2808 192 970501.994 7.200 + 29 111 82 193 Pb -22229.255 10.288 7854.0994 0.0533 B- -6344.6913 12.7761 192 976135.914 11.044 + 27 110 83 193 Bi -15884.563 7.576 7817.1718 0.0393 B- -7559.2614 16.3874 192 982947.220 8.132 + 25 109 84 193 Po -a -8325.302 14.531 7773.9510 0.0753 B- -8257.9789 26.0594 192 991062.421 15.599 + 23 108 85 193 At -a -67.323 21.632 7727.1099 0.1121 B- -9110.2435 33.1444 192 999927.725 23.222 + 21 107 86 193 Rn -a 9042.920 25.112 7675.8530 0.1301 B- * 193 009707.973 26.958 +0 48 121 73 194 Ta x -17130# 500# 7865# 3# B- 7280# 583# 193 981610# 537# + 46 120 74 194 W x -24410# 300# 7899# 2# B- 2850# 361# 193 973795# 322# + 44 119 75 194 Re x -27260# 200# 7909# 1# B- 5175# 200# 193 970735# 215# + 42 118 76 194 Os + -32435.176 2.403 7932.0232 0.0124 B- 96.6000 2.0000 193 965179.407 2.579 + 40 117 77 194 Ir -n -32531.776 1.332 7928.4885 0.0069 B- 2228.3252 1.2569 193 965075.703 1.429 + 38 116 78 194 Pt -34760.101 0.496 7935.9420 0.0026 B- -2548.1518 2.1174 193 962683.498 0.532 + 36 115 79 194 Au +3n -32211.950 2.118 7918.7744 0.0109 B- -27.9978 3.5809 193 965419.051 2.273 + 34 114 80 194 Hg x -32183.952 2.888 7914.5974 0.0149 B- -5246.4542 14.2677 193 965449.108 3.100 + 32 113 81 194 Tl x -26937.498 13.972 7883.5211 0.0720 B- -2729.6315 22.3433 193 971081.408 15.000 + 30 112 82 194 Pb -24207.866 17.435 7865.4181 0.0899 B- -8184.8462 18.2094 193 974011.788 18.717 + 28 111 83 194 Bi +a -16023.020 5.252 7819.1955 0.0271 B- -5018.4029 13.9386 193 982798.581 5.638 + 26 110 84 194 Po -a -11004.617 12.911 7789.2947 0.0666 B- -10288.1273 26.8153 193 988186.058 13.860 + 24 109 85 194 At -a -716.490 23.502 7732.2304 0.1211 B- -6441.1134 28.8079 193 999230.816 25.230 + 22 108 86 194 Rn -a 5724.624 16.659 7694.9961 0.0859 B- * 194 006145.636 17.884 +0 47 121 74 195 W x -20740# 300# 7881# 2# B- 4820# 424# 194 977735# 322# + 45 120 75 195 Re x -25560# 300# 7901# 2# B- 3951# 305# 194 972560# 322# + 43 119 76 195 Os x -29511.596 55.890 7917.7449 0.2866 B- 2180.7220 55.9055 194 968318.000 60.000 + 41 118 77 195 Ir -n -31692.318 1.333 7924.9160 0.0068 B- 1101.5601 1.2637 194 965976.898 1.431 + 39 117 78 195 Pt -32793.878 0.503 7926.5530 0.0026 B- -226.8175 0.9998 194 964794.325 0.540 + 37 116 79 195 Au -32567.061 1.119 7921.3778 0.0057 B- -1553.7190 23.1562 194 965037.823 1.201 + 35 115 80 195 Hg -31013.342 23.142 7909.3980 0.1187 B- -2858.0499 25.6707 194 966705.809 24.843 + 33 114 81 195 Tl -28155.292 11.126 7890.7293 0.0571 B- -4417.2524 12.2333 194 969774.052 11.944 + 31 113 82 195 Pb -23738.039 5.088 7864.0647 0.0261 B- -5712.4729 7.3370 194 974516.167 5.461 + 29 112 83 195 Bi -18025.567 5.287 7830.7579 0.0271 B- -6908.9121 8.0284 194 980648.759 5.675 + 27 111 84 195 Po -11116.655 6.042 7791.3155 0.0310 B- -7646.3554 11.3199 194 988065.781 6.486 + 25 110 85 195 At -a -3470.299 9.573 7748.0914 0.0491 B- -8520.5842 52.5650 194 996274.480 10.276 + 23 109 86 195 Rn -a 5050.285 51.686 7700.3841 0.2651 B- * 195 005421.703 55.487 +0 48 122 74 196 W x -18740# 400# 7872# 2# B- 3620# 500# 195 979882# 429# + 46 121 75 196 Re x -22360# 300# 7886# 2# B- 5918# 303# 195 975996# 322# + 44 120 76 196 Os +pp -28277.123 40.055 7912.2301 0.2044 B- 1158.3989 55.4951 195 969643.261 43.000 + 42 119 77 196 Ir + -29435.522 38.414 7914.1487 0.1960 B- 3209.0164 38.4111 195 968399.669 41.239 + 40 118 78 196 Pt -32644.538 0.510 7926.5297 0.0026 B- -1505.8204 2.9605 195 964954.648 0.547 + 38 117 79 196 Au -31138.718 2.962 7914.8553 0.0151 B- 687.2263 3.1176 195 966571.213 3.179 + 36 116 80 196 Hg -31825.944 2.946 7914.3700 0.0150 B- -4329.3455 12.4627 195 965833.445 3.163 + 34 115 81 196 Tl x -27496.598 12.109 7888.2900 0.0618 B- -2148.3639 14.3556 195 970481.189 13.000 + 32 114 82 196 Pb -25348.234 7.710 7873.3374 0.0393 B- -7339.2020 25.6160 195 972787.552 8.277 + 30 113 83 196 Bi x -18009.032 24.428 7831.9009 0.1246 B- -4540.3012 25.0142 195 980666.509 26.224 + 28 112 84 196 Po -13468.731 5.383 7804.7445 0.0275 B- -9555.5564 30.7105 195 985540.722 5.778 + 26 111 85 196 At -a -3913.175 30.235 7752.0001 0.1543 B- -5888.3439 33.3417 195 995799.034 32.458 + 24 110 86 196 Rn -a 1975.169 14.054 7717.9660 0.0717 B- * 196 002120.431 15.087 +0 49 123 74 197 W x -14870# 400# 7853# 2# B- 5480# 500# 196 984036# 429# + 47 122 75 197 Re x -20350# 300# 7877# 2# B- 4729# 361# 196 978153# 322# + 45 121 76 197 Os x -25080# 200# 7897# 1# B- 3185# 201# 196 973076# 215# + 43 120 77 197 Ir +p -28264.123 20.110 7909.0003 0.1021 B- 2155.6519 20.1061 196 969657.217 21.588 + 41 119 78 197 Pt -30419.775 0.536 7915.9714 0.0027 B- 719.9769 0.5022 196 967343.030 0.575 + 39 118 79 197 Au -31139.751 0.542 7915.6548 0.0028 B- -599.5206 3.2022 196 966570.103 0.581 + 37 117 80 197 Hg -30540.231 3.207 7908.6402 0.0163 B- -2186.0092 13.9478 196 967213.715 3.442 + 35 116 81 197 Tl +a -28354.222 13.575 7893.5725 0.0689 B- -3608.8367 14.3969 196 969560.492 14.573 + 33 115 82 197 Pb -24745.385 4.804 7871.2822 0.0244 B- -5058.1894 9.6190 196 973434.737 5.157 + 31 114 83 197 Bi +a -19687.196 8.333 7841.6348 0.0423 B- -6294.1172 12.9103 196 978864.927 8.946 + 29 113 84 197 Po -13393.078 9.861 7805.7136 0.0501 B- -7037.8235 12.6871 196 985621.939 10.585 + 27 112 85 197 At -6355.255 7.983 7766.0174 0.0405 B- -7865.6231 18.0538 196 993177.353 8.570 + 25 111 86 197 Rn -a 1510.368 16.193 7722.1190 0.0822 B- -8743.5996 58.7110 197 001621.446 17.383 + 23 110 87 197 Fr -a 10253.968 56.434 7673.7640 0.2865 B- * 197 011008.086 60.584 +0 48 123 75 198 Re x -16990# 400# 7861# 2# B- 6610# 447# 197 981760# 429# + 46 122 76 198 Os x -23600# 200# 7890# 1# B- 2110# 283# 197 974664# 215# + 44 121 77 198 Ir x -25710# 200# 7897# 1# B- 4194# 200# 197 972399# 215# + 42 120 78 198 Pt -29904.018 2.100 7914.1512 0.0106 B- -323.2251 2.0595 197 967896.718 2.254 + 40 119 79 198 Au -29580.793 0.540 7908.5675 0.0027 B- 1373.5226 0.4905 197 968243.714 0.579 + 38 118 80 198 Hg -30954.315 0.458 7911.5532 0.0023 B- -3425.5625 7.5590 197 966769.177 0.491 + 36 117 81 198 Tl x -27528.753 7.545 7890.3011 0.0381 B- -1461.3103 11.5537 197 970446.669 8.100 + 34 116 82 198 Pb -26067.443 8.750 7878.9695 0.0442 B- -6693.5916 28.9259 197 972015.450 9.393 + 32 115 83 198 Bi -19373.851 27.571 7841.2123 0.1392 B- -3900.5727 32.6152 197 979201.316 29.598 + 30 114 84 198 Po -15473.278 17.424 7817.5611 0.0880 B- -8764.5316 18.1013 197 983388.753 18.705 + 28 113 85 198 At -6708.747 4.904 7769.3446 0.0248 B- -5478.4271 14.2879 197 992797.864 5.265 + 26 112 86 198 Rn -a -1230.320 13.420 7737.7245 0.0678 B- -10808.0177 33.8991 197 998679.197 14.406 + 24 111 87 198 Fr -a 9577.698 31.130 7679.1873 0.1572 B- * 198 010282.081 33.419 +0 49 124 75 199 Re x -14730# 400# 7850# 2# B- 5541# 447# 198 984187# 429# + 47 123 76 199 Os x -20270# 200# 7874# 1# B- 4128# 204# 198 978239# 215# + 45 122 77 199 Ir p-2n -24398.534 41.054 7891.2066 0.2063 B- 2990.1656 41.0030 198 973807.097 44.073 + 43 121 78 199 Pt -n -27388.700 2.159 7902.3011 0.0109 B- 1705.0525 2.1201 198 970597.022 2.317 + 41 120 79 199 Au -29093.752 0.542 7906.9379 0.0027 B- 452.3142 0.6126 198 968766.573 0.581 + 39 119 80 199 Hg -29546.066 0.526 7905.2794 0.0027 B- -1486.6695 27.9498 198 968280.994 0.564 + 37 118 81 199 Tl x -28059.397 27.945 7893.8773 0.1404 B- -2827.6624 28.7653 198 969877.000 30.000 + 35 117 82 199 Pb +a -25231.734 6.821 7875.7366 0.0343 B- -4434.1181 12.6179 198 972912.620 7.322 + 33 116 83 199 Bi -20797.616 10.615 7849.5232 0.0533 B- -5558.7875 11.9224 198 977672.841 11.395 + 31 115 84 199 Po -a -15238.829 5.429 7817.6582 0.0273 B- -6415.4515 7.6464 198 983640.445 5.828 + 29 114 85 199 At -8823.377 5.384 7781.4883 0.0271 B- -7263.5308 9.0686 198 990527.715 5.780 + 27 113 86 199 Rn -a -1559.846 7.297 7741.0568 0.0367 B- -8331.2349 15.5446 198 998325.436 7.833 + 25 112 87 199 Fr -a 6771.388 13.726 7695.2599 0.0690 B- * 199 007269.384 14.734 +0 48 124 76 200 Os x -18550# 300# 7867# 1# B- 3020# 358# 199 980086# 322# + 46 123 77 200 Ir x -21570# 196# 7878# 1# B- 5030# 197# 199 976844# 210# + 44 122 78 200 Pt -nn -26599.178 20.110 7899.1986 0.1006 B- 640.9158 33.4386 199 971444.609 21.588 + 42 121 79 200 Au -27240.094 26.717 7898.4915 0.1336 B- 2263.1737 26.7188 199 970756.558 28.681 + 40 120 80 200 Hg -29503.267 0.530 7905.8956 0.0027 B- -2456.0403 5.7346 199 968326.941 0.568 + 38 119 81 200 Tl - -27047.227 5.759 7889.7037 0.0288 B- -796.3695 11.5360 199 970963.608 6.182 + 36 118 82 200 Pb -26250.858 10.008 7881.8101 0.0500 B- -5880.2841 24.8094 199 971818.546 10.744 + 34 117 83 200 Bi +a -20370.574 22.701 7848.4969 0.1135 B- -3428.8901 23.9327 199 978131.290 24.370 + 32 116 84 200 Po -16941.683 7.579 7827.4407 0.0379 B- -7953.7897 25.6119 199 981812.355 8.136 + 30 115 85 200 At -a -8987.894 24.465 7783.7601 0.1223 B- -4987.4394 25.1411 199 990351.099 26.264 + 28 114 86 200 Rn -a -4000.454 5.792 7754.9111 0.0290 B- -10134.0327 31.0688 199 995705.335 6.217 + 26 113 87 200 Fr -a 6133.578 30.524 7700.3292 0.1526 B- * 200 006584.666 32.769 +0 49 125 76 201 Os x -14840# 300# 7849# 1# B- 5000# 361# 200 984069# 322# + 47 124 77 201 Ir x -19840# 200# 7870# 1# B- 3901# 206# 200 978701# 215# + 45 123 78 201 Pt + -23740.705 50.103 7885.8337 0.2493 B- 2660.0000 50.0000 200 974513.305 53.788 + 43 122 79 201 Au -26400.705 3.218 7895.1752 0.0160 B- 1261.8237 3.1471 200 971657.678 3.455 + 41 121 80 201 Hg -27662.529 0.712 7897.5607 0.0036 B- -481.7508 14.1815 200 970303.054 0.763 + 39 120 81 201 Tl -27180.778 14.185 7891.2717 0.0706 B- -1909.7458 18.5299 200 970820.235 15.228 + 37 119 82 201 Pb -25271.033 13.747 7877.8782 0.0684 B- -3842.0269 18.3637 200 972870.431 14.758 + 35 118 83 201 Bi +a -21429.006 12.177 7854.8713 0.0606 B- -4907.8397 13.1377 200 976995.017 13.072 + 33 117 84 201 Po -16521.166 4.942 7826.5619 0.0246 B- -5731.7247 9.5606 200 982263.799 5.305 + 31 116 85 201 At +a -10789.441 8.184 7794.1536 0.0407 B- -6682.0288 13.0163 200 988417.058 8.786 + 29 115 86 201 Rn -a -4107.413 10.121 7757.0174 0.0504 B- -7695.9856 13.5972 200 995590.511 10.865 + 27 114 87 201 Fr -a 3588.573 9.080 7714.8367 0.0452 B- -8348.2439 22.2391 201 003852.491 9.747 + 25 113 88 201 Ra -a 11936.817 20.301 7669.4108 0.1010 B- * 201 012814.699 21.794 +0 50 126 76 202 Os x -12530# 400# 7839# 2# B- 4110# 500# 201 986548# 429# + 48 125 77 202 Ir x -16640# 300# 7855# 1# B- 6052# 301# 201 982136# 322# + 46 124 78 202 Pt x -22692.128 25.150 7881.5609 0.1245 B- 1660.8540 34.2759 201 975639.000 27.000 + 44 123 79 202 Au x -24352.982 23.287 7885.9100 0.1153 B- 2992.3278 23.2980 201 973856.000 25.000 + 42 122 80 202 Hg -27345.310 0.705 7896.8505 0.0035 B- -1364.8906 1.8348 201 970643.604 0.757 + 40 121 81 202 Tl -25980.419 1.838 7886.2206 0.0091 B- -39.8110 4.1863 201 972108.874 1.972 + 38 120 82 202 Pb -25940.608 3.796 7882.1505 0.0188 B- -5189.7539 14.5070 201 972151.613 4.075 + 36 119 83 202 Bi -20750.854 14.002 7852.5857 0.0693 B- -2809.2850 16.4660 201 977723.042 15.032 + 34 118 84 202 Po -17941.569 8.670 7834.8053 0.0429 B- -7346.4628 28.9311 201 980738.934 9.307 + 32 117 85 202 At -10595.106 27.601 7794.5637 0.1366 B- -4320.5458 32.6924 201 988625.686 29.631 + 30 116 86 202 Rn -a -6274.561 17.520 7769.3018 0.0867 B- -9376.0984 18.5296 201 993263.982 18.808 + 28 115 87 202 Fr -a 3101.538 6.033 7719.0125 0.0299 B- -5973.3620 16.1841 202 003329.637 6.476 + 26 114 88 202 Ra -a 9074.900 15.018 7685.5684 0.0743 B- * 202 009742.305 16.122 +0 51 127 76 203 Os x -7270# 400# 7814# 2# B- 7100# 565# 202 992195# 429# + 49 126 77 203 Ir x -14370# 400# 7845# 2# B- 5140# 447# 202 984573# 429# + 47 125 78 203 Pt x -19510# 200# 7867# 1# B- 3633# 200# 202 979055# 215# + 45 124 79 203 Au -23143.444 3.083 7880.8650 0.0152 B- 2125.7592 3.4514 202 975154.492 3.309 + 43 123 80 203 Hg -25269.203 1.630 7887.4828 0.0080 B- 492.1062 1.2247 202 972872.396 1.750 + 41 122 81 203 Tl -25761.309 1.171 7886.0530 0.0058 B- -974.8265 6.4609 202 972344.098 1.257 + 39 121 82 203 Pb -24786.483 6.554 7877.3970 0.0323 B- -3261.5896 14.3559 202 973390.617 7.036 + 37 120 83 203 Bi +a -21524.893 12.778 7857.4762 0.0629 B- -4214.0744 13.5942 202 976892.077 13.717 + 35 119 84 203 Po -17310.819 4.640 7832.8632 0.0229 B- -5148.2116 11.5921 202 981416.072 4.981 + 33 118 85 203 At -12162.607 10.623 7803.6487 0.0523 B- -5978.5623 12.1098 202 986942.904 11.404 + 31 117 86 203 Rn -a -6184.045 5.815 7770.3437 0.0286 B- -7060.4572 8.5231 202 993361.155 6.242 + 29 116 87 203 Fr 876.412 6.232 7731.7092 0.0307 B- -7724.9182 11.5191 203 000940.867 6.689 + 27 115 88 203 Ra -a 8601.331 9.688 7689.8015 0.0477 B- * 203 009233.907 10.400 +0 50 127 77 204 Ir x -9570# 400# 7823# 2# B- 8050# 447# 203 989726# 429# + 48 126 78 204 Pt x -17620# 200# 7859# 1# B- 2770# 283# 203 981084# 215# + 46 125 79 204 Au + -20390# 200# 7868# 1# B- 4300# 200# 203 978110# 215# + 44 124 80 204 Hg -24690.148 0.498 7885.5455 0.0025 B- -344.0781 1.1876 203 973494.037 0.534 + 42 123 81 204 Tl -24346.070 1.154 7880.0238 0.0057 B- 763.7453 0.1768 203 973863.420 1.238 + 40 122 82 204 Pb -25109.815 1.147 7879.9326 0.0056 B- -4463.8883 9.2480 203 973043.506 1.231 + 38 121 83 204 Bi +a -20645.927 9.180 7854.2157 0.0450 B- -2304.8814 13.6253 203 977835.687 9.854 + 36 120 84 204 Po -18341.045 10.071 7839.0823 0.0494 B- -6465.7939 24.8047 203 980310.078 10.811 + 34 119 85 204 At -11875.252 22.668 7803.5522 0.1111 B- -3905.1360 23.8592 203 987251.393 24.335 + 32 118 86 204 Rn -7970.115 7.444 7780.5743 0.0365 B- -8577.4239 25.6840 203 991443.729 7.991 + 30 117 87 204 Fr -a 607.308 24.581 7734.6931 0.1205 B- -5453.7889 26.1514 204 000651.972 26.389 + 28 116 88 204 Ra -a 6061.097 8.924 7704.1238 0.0437 B- * 204 006506.855 9.580 +0 51 128 77 205 Ir x -5600# 500# 7805# 2# B- 7220# 583# 204 993988# 537# + 49 127 78 205 Pt x -12820# 300# 7836# 1# B- 5750# 361# 204 986237# 322# + 47 126 79 205 Au x -18570# 200# 7860# 1# B- 3717# 200# 204 980064# 215# + 45 125 80 205 Hg -22287.719 3.655 7874.7325 0.0178 B- 1533.0836 3.7238 204 976073.151 3.923 + 43 124 81 205 Tl -23820.802 1.239 7878.3946 0.0060 B- -50.6402 0.5033 204 974427.318 1.330 + 41 123 82 205 Pb -23770.162 1.145 7874.3313 0.0056 B- -2704.5927 4.8196 204 974481.682 1.228 + 39 122 83 205 Bi -21065.569 4.808 7857.3218 0.0235 B- -3544.1710 11.1458 204 977385.182 5.161 + 37 121 84 205 Po -17521.398 10.059 7836.2168 0.0491 B- -4536.8793 15.6996 204 981190.006 10.798 + 35 120 85 205 At +a -12984.519 12.055 7810.2694 0.0588 B- -5274.7547 13.0777 204 986060.546 12.941 + 33 119 86 205 Rn -7709.764 5.080 7780.7226 0.0248 B- -6399.9479 9.3288 204 991723.228 5.453 + 31 118 87 205 Fr x -1309.816 7.824 7745.6870 0.0382 B- -7113.6693 24.0784 204 998593.854 8.399 + 29 117 88 205 Ra -a 5803.853 22.772 7707.1698 0.1111 B- -8302.8357 63.5402 205 006230.692 24.446 + 27 116 89 205 Ac -a 14106.689 59.320 7662.8519 0.2894 B- * 205 015144.152 63.682 +0 50 128 78 206 Pt x -9240# 300# 7820# 1# B- 4950# 424# 205 990080# 322# + 48 127 79 206 Au x -14190# 300# 7840# 1# B- 6755# 301# 205 984766# 322# + 46 126 80 206 Hg +a -20945.728 20.441 7869.1723 0.0992 B- 1307.5659 20.4100 205 977513.837 21.943 + 44 125 81 206 Tl -22253.293 1.286 7871.7219 0.0062 B- 1532.2128 0.6117 205 976110.108 1.380 + 42 124 82 206 Pb -23785.506 1.144 7875.3620 0.0056 B- -3757.3057 7.5461 205 974465.210 1.228 + 40 123 83 206 Bi - -20028.201 7.632 7853.3249 0.0371 B- -1839.5323 8.6005 205 978498.843 8.193 + 38 122 84 206 Po -a -18188.668 4.012 7840.5973 0.0195 B- -5749.2803 14.1099 205 980473.662 4.306 + 36 121 85 206 At -12439.388 13.529 7808.8904 0.0657 B- -3306.4697 16.0227 205 986645.768 14.523 + 34 120 86 206 Rn -9132.918 8.591 7789.0417 0.0417 B- -7886.0592 29.1075 205 990195.409 9.223 + 32 119 87 206 Fr -1246.859 27.811 7746.9621 0.1350 B- -4812.4721 33.1318 205 998661.441 29.856 + 30 118 88 206 Ra -a 3565.613 18.008 7719.8028 0.0874 B- -9919.1406 67.5328 206 003827.842 19.332 + 28 117 89 206 Ac -a 13484.754 65.088 7667.8538 0.3160 B- * 206 014476.477 69.874 +0 51 129 78 207 Pt x -4140# 400# 7797# 2# B- 6501# 500# 206 995556# 429# + 49 128 79 207 Au x -10640# 300# 7824# 1# B- 5847# 301# 206 988577# 322# + 47 127 80 207 Hg x -16487.446 29.808 7848.6112 0.1440 B- 4546.9906 30.3000 206 982300.000 32.000 + 45 126 81 207 Tl -21034.436 5.439 7866.7979 0.0263 B- 1417.5323 5.4024 206 977418.605 5.839 + 43 125 82 207 Pb -22451.968 1.147 7869.8664 0.0055 B- -2397.4140 2.1175 206 975896.821 1.231 + 41 124 83 207 Bi -20054.554 2.397 7854.5053 0.0116 B- -2908.8541 6.6140 206 978470.551 2.573 + 39 123 84 207 Po -17145.700 6.659 7836.6734 0.0322 B- -3918.2186 14.0754 206 981593.334 7.148 + 37 122 85 207 At +a -13227.482 12.406 7813.9653 0.0599 B- -4592.7400 13.2815 206 985799.715 13.318 + 35 121 86 207 Rn -8634.742 4.742 7787.9987 0.0229 B- -5785.7211 18.1857 206 990730.224 5.090 + 33 120 87 207 Fr -2849.021 17.557 7756.2689 0.0848 B- -6363.0084 60.8726 206 996941.450 18.847 + 31 119 88 207 Ra -a 3513.988 58.286 7721.7503 0.2816 B- -7632.2404 81.0004 207 003772.420 62.572 + 29 118 89 207 Ac -a 11146.228 56.248 7681.1001 0.2717 B- * 207 011965.967 60.384 +0 52 130 78 208 Pt x -500# 400# 7780# 2# B- 5410# 500# 207 999463# 429# + 50 129 79 208 Au x -5910# 300# 7803# 1# B- 7355# 302# 207 993655# 322# + 48 128 80 208 Hg x -13265.408 30.739 7834.1914 0.1478 B- 3484.7131 30.7951 207 985759.000 33.000 + 46 127 81 208 Tl +a -16750.121 1.854 7847.1835 0.0089 B- 4998.3984 1.6693 207 982018.006 1.989 + 44 126 82 208 Pb -21748.519 1.148 7867.4530 0.0055 B- -2878.3680 2.0127 207 976652.005 1.232 + 42 125 83 208 Bi +n -18870.151 2.305 7849.8534 0.0111 B- -1400.9438 2.3787 207 979742.060 2.474 + 40 124 84 208 Po -17469.207 1.672 7839.3568 0.0080 B- -4999.3061 9.0736 207 981246.035 1.795 + 38 123 85 208 At +a -12469.901 8.921 7811.5604 0.0429 B- -2814.5118 13.5215 207 986613.011 9.577 + 36 122 86 208 Rn -9655.389 10.163 7794.2678 0.0489 B- -6990.4614 15.4656 207 989634.513 10.910 + 34 121 87 208 Fr -2664.928 11.657 7756.8985 0.0560 B- -4392.8615 14.7413 207 997139.082 12.514 + 32 120 88 208 Ra -a 1727.934 9.023 7732.0177 0.0434 B- -9032.9208 65.1111 208 001855.012 9.686 + 30 119 89 208 Ac -a 10760.854 64.483 7684.8289 0.3100 B- -5927.1868 71.9264 208 011552.251 69.225 + 28 118 90 208 Th -a 16688.041 31.865 7652.5716 0.1532 B- * 208 017915.348 34.208 +0 51 130 79 209 Au x -2230# 400# 7786# 2# B- 6380# 427# 208 997606# 429# + 49 129 80 209 Hg x -8610# 150# 7813# 1# B- 5035# 150# 208 990757# 161# + 47 128 81 209 Tl +a -13644.793 6.110 7833.3979 0.0292 B- 3969.7809 6.2115 208 985351.713 6.559 + 45 127 82 209 Pb -17614.574 1.747 7848.6488 0.0084 B- 644.0152 1.1462 208 981089.978 1.875 + 43 126 83 209 Bi -18258.589 1.365 7847.9869 0.0065 B- -1892.5741 1.5635 208 980398.599 1.465 + 41 125 84 209 Po -a -16366.015 1.778 7835.1882 0.0085 B- -3482.2417 4.9599 208 982430.361 1.909 + 39 124 85 209 At -12883.773 4.745 7814.7835 0.0227 B- -3942.7237 11.0298 208 986168.701 5.094 + 37 123 86 209 Rn -8941.049 9.960 7792.1755 0.0477 B- -5158.9051 15.2153 208 990401.389 10.692 + 35 122 87 209 Fr -3782.144 11.503 7763.7485 0.0550 B- -5640.3845 12.8549 208 995939.701 12.349 + 33 121 88 209 Ra -a 1858.240 5.747 7733.0177 0.0275 B- -6986.6464 56.1409 209 001994.902 6.169 + 31 120 89 209 Ac -a 8844.887 55.846 7695.8455 0.2672 B- -7550# 117# 209 009495.375 59.953 + 29 119 90 209 Th IT 16395# 103# 7656# 0# B- * 209 017601# 111# +0 52 131 79 210 Au x 2680# 400# 7764# 2# B- 7980# 447# 210 002877# 429# + 50 130 80 210 Hg x -5300# 200# 7799# 1# B- 3947# 201# 209 994310# 215# + 48 129 81 210 Tl +a -9246.996 11.603 7813.5890 0.0553 B- 5481.4334 11.5610 209 990072.942 12.456 + 46 128 82 210 Pb -14728.429 1.448 7835.9656 0.0069 B- 63.4758 0.4992 209 984188.381 1.554 + 44 127 83 210 Bi -14791.905 1.364 7832.5424 0.0065 B- 1161.1549 0.7662 209 984120.237 1.463 + 42 126 84 210 Po -15953.060 1.146 7834.3462 0.0055 B- -3980.9605 7.6101 209 982873.686 1.230 + 40 125 85 210 At -a -11972.099 7.695 7811.6638 0.0366 B- -2367.3352 8.9225 209 987147.423 8.261 + 38 124 86 210 Rn -a -9604.764 4.557 7796.6653 0.0217 B- -6261.2558 14.1720 209 989688.862 4.892 + 36 123 87 210 Fr -3343.508 13.420 7763.1243 0.0639 B- -3786.3467 16.2633 209 996410.596 14.407 + 34 122 88 210 Ra -a 442.839 9.193 7741.3687 0.0438 B- -8321.2403 62.8832 210 000475.406 9.868 + 32 121 89 210 Ac 8764.079 62.208 7698.0182 0.2962 B- -5295.4420 65.0180 210 009408.625 66.782 + 30 120 90 210 Th -a 14059.521 18.909 7669.0764 0.0900 B- * 210 015093.515 20.299 +0 51 131 80 211 Hg x -390# 200# 7777# 1# B- 5688# 205# 210 999581# 215# + 49 130 81 211 Tl x -6077.999 41.917 7799.7915 0.1987 B- 4415.0129 41.9781 210 993475.000 45.000 + 47 129 82 211 Pb -10493.012 2.260 7817.0079 0.0107 B- 1366.1041 5.4713 210 988735.288 2.426 + 45 128 83 211 Bi -11859.116 5.442 7819.7745 0.0258 B- 573.3763 5.4297 210 987268.715 5.842 + 43 127 84 211 Po -a -12432.492 1.255 7818.7842 0.0060 B- -785.3012 2.5385 210 986653.171 1.347 + 41 126 85 211 At -a -11647.191 2.729 7811.3545 0.0129 B- -2891.8615 6.8937 210 987496.226 2.929 + 39 125 86 211 Rn -a -8755.330 6.813 7793.9412 0.0323 B- -4615.0152 13.7862 210 990600.767 7.314 + 37 124 87 211 Fr -4140.314 11.991 7768.3613 0.0568 B- -4972.1844 12.9786 210 995555.189 12.872 + 35 123 88 211 Ra 831.870 4.966 7741.0887 0.0235 B- -6311.6152 53.9818 211 000893.049 5.331 + 33 122 89 211 Ac 7143.485 53.753 7707.4680 0.2548 B- -6732.9111 101.4758 211 007668.846 57.706 + 31 121 90 211 Th -a 13876.396 86.070 7671.8506 0.4079 B- -8175.8296 110.6091 211 014896.923 92.399 + 29 120 91 211 Pa -a 22052.226 69.472 7629.3948 0.3293 B- * 211 023674.036 74.581 +0 52 132 80 212 Hg x 3020# 300# 7762# 1# B- 4571# 361# 212 003242# 322# + 50 131 81 212 Tl +a -1551# 200# 7780# 1# B- 5998# 200# 211 998335# 215# + 48 130 82 212 Pb -7548.929 1.840 7804.3203 0.0087 B- 569.0133 1.8246 211 991895.891 1.975 + 46 129 83 212 Bi -8117.943 1.853 7803.3140 0.0087 B- 2251.4656 1.6671 211 991285.030 1.989 + 44 128 84 212 Po -10369.408 1.153 7810.2438 0.0054 B- -1741.2596 2.1066 211 988867.982 1.237 + 42 127 85 212 At -a -8628.149 2.385 7798.3400 0.0113 B- 31.0705 3.5927 211 990737.301 2.559 + 40 126 86 212 Rn -a -8659.219 3.110 7794.7963 0.0147 B- -5143.2210 9.3064 211 990703.946 3.338 + 38 125 87 212 Fr -3515.998 8.775 7766.8455 0.0414 B- -3317.2355 13.4939 211 996225.420 9.419 + 36 124 88 212 Ra -198.763 10.254 7747.5078 0.0484 B- -7498.3626 24.1666 211 999786.619 11.007 + 34 123 89 212 Ac 7299.600 21.883 7708.4479 0.1032 B- -4811.2864 24.1055 212 007836.442 23.492 + 32 122 90 212 Th -a 12110.886 10.109 7682.0628 0.0477 B- -9485.6366 88.1858 212 013001.570 10.852 + 30 121 91 212 Pa -a 21596.523 87.604 7633.6289 0.4132 B- * 212 023184.819 94.047 +0 53 133 80 213 Hg x 8200# 300# 7739# 1# B- 6416# 301# 213 008803# 322# + 51 132 81 213 Tl x 1783.811 27.013 7765.4311 0.1268 B- 4987.4088 27.8941 213 001915.000 29.000 + 49 131 82 213 Pb +a -3203.598 6.954 7785.1732 0.0326 B- 2028.0730 8.3708 212 996560.796 7.465 + 47 130 83 213 Bi -5231.671 5.082 7791.0217 0.0239 B- 1421.8481 5.4898 212 994383.570 5.455 + 45 129 84 213 Po -6653.519 3.053 7794.0240 0.0143 B- -73.9972 5.4646 212 992857.154 3.277 + 43 128 85 213 At -a -6579.522 4.898 7790.0036 0.0230 B- -883.5727 5.7243 212 992936.593 5.258 + 41 127 86 213 Rn -a -5695.949 3.370 7782.1824 0.0158 B- -2141.7493 5.6996 212 993885.147 3.618 + 39 126 87 213 Fr -3554.199 4.707 7768.4543 0.0221 B- -3899.7568 10.8862 212 996184.410 5.053 + 37 125 88 213 Ra 345.557 9.818 7746.4726 0.0461 B- -5795.4721 15.2463 213 000370.971 10.540 + 35 124 89 213 Ac 6141.029 11.665 7715.5908 0.0548 B- -5979.0781 14.8635 213 006592.665 12.522 + 33 123 90 213 Th -a 12120.108 9.217 7683.8470 0.0433 B- -7534.0866 57.9078 213 013011.470 9.895 + 31 122 91 213 Pa -a 19654.194 57.170 7644.8027 0.2684 B- * 213 021099.644 61.374 +0 54 134 80 214 Hg x 11770# 400# 7724# 2# B- 5306# 445# 214 012636# 429# + 52 133 81 214 Tl x 6465# 196# 7745# 1# B- 6648# 196# 214 006940# 210# + 50 132 82 214 Pb -183.019 1.969 7772.3955 0.0092 B- 1017.7611 11.2559 213 999803.521 2.114 + 48 131 83 214 Bi -1200.780 11.209 7773.4955 0.0524 B- 3269.1925 11.1649 213 998710.909 12.033 + 46 130 84 214 Po -4469.972 1.449 7785.1163 0.0068 B- -1090.8208 3.7750 213 995201.287 1.556 + 44 129 85 214 At -3379.151 3.982 7776.3632 0.0186 B- 940.5125 9.8827 213 996372.331 4.274 + 42 128 86 214 Rn -a -4319.664 9.187 7777.1023 0.0429 B- -3361.3369 12.4238 213 995362.650 9.862 + 40 127 87 214 Fr -a -958.327 8.519 7757.7393 0.0398 B- -1051.0675 9.9879 213 998971.193 9.145 + 38 126 88 214 Ra -a 92.740 5.250 7749.1719 0.0245 B- -6340.5313 14.5317 214 000099.560 5.636 + 36 125 89 214 Ac 6433.272 13.551 7715.8874 0.0633 B- -4261.6599 17.2389 214 006906.400 14.547 + 34 124 90 214 Th -a 10694.932 10.661 7692.3173 0.0498 B- -8764.9630 81.9051 214 011481.480 11.445 + 32 123 91 214 Pa -a 19459.895 81.208 7647.7037 0.3795 B- * 214 020891.055 87.180 +0 55 135 80 215 Hg x 17110# 400# 7701# 2# B- 7079# 500# 215 018368# 429# + 53 134 81 215 Tl x 10030# 300# 7730# 1# B- 5688# 305# 215 010768# 322# + 51 133 82 215 Pb +a 4342.245 52.685 7752.7381 0.2450 B- 2712.9729 52.9848 215 004661.591 56.560 + 49 132 83 215 Bi 1629.272 5.624 7761.7177 0.0262 B- 2171.0426 5.5297 215 001749.095 6.037 + 47 131 84 215 Po -541.771 2.120 7768.1768 0.0099 B- 714.8128 6.6491 214 999418.385 2.276 + 45 130 85 215 At -a -1256.583 6.629 7767.8627 0.0308 B- -87.5935 8.9062 214 998651.002 7.116 + 43 129 86 215 Rn -a -1168.990 6.090 7763.8164 0.0283 B- -1487.1274 9.1890 214 998745.037 6.538 + 41 128 87 215 Fr -a 318.137 7.066 7753.2607 0.0329 B- -2213.8573 9.7691 215 000341.534 7.585 + 39 127 88 215 Ra -a 2531.995 7.201 7739.3249 0.0335 B- -3498.5554 14.3395 215 002718.208 7.730 + 37 126 89 215 Ac -a 6030.550 12.406 7719.4137 0.0577 B- -4890.8833 13.9296 215 006474.061 13.318 + 35 125 90 215 Th -a 10921.434 6.335 7693.0266 0.0295 B- -6883.1037 82.6932 215 011724.640 6.800 + 33 124 91 215 Pa -a 17804.537 82.450 7657.3733 0.3835 B- -7084.7747 132.8246 215 019113.955 88.513 + 31 123 92 215 U -a 24889.312 104.136 7620.7821 0.4844 B- * 215 026719.774 111.794 +0 56 136 80 216 Hg x 20920# 400# 7685# 2# B- 6050# 500# 216 022459# 429# + 54 135 81 216 Tl x 14870# 300# 7709# 1# B- 7361# 361# 216 015964# 322# + 52 134 82 216 Pb x 7510# 200# 7740# 1# B- 1636# 201# 216 008062# 215# + 50 133 83 216 Bi x 5873.988 11.178 7743.4996 0.0518 B- 4091.6520 11.3243 216 006305.985 12.000 + 48 132 84 216 Po 1782.336 1.815 7758.8205 0.0084 B- -474.3423 3.5713 216 001913.416 1.948 + 46 131 85 216 At -a 2256.678 3.575 7753.0024 0.0166 B- 2003.3657 6.6383 216 002422.643 3.837 + 44 130 86 216 Rn -a 253.312 5.768 7758.6553 0.0267 B- -2717.7096 6.9366 216 000271.942 6.192 + 42 129 87 216 Fr -a 2971.022 4.174 7742.4513 0.0193 B- -320.4441 8.8904 216 003189.523 4.480 + 40 128 88 216 Ra -a 3291.466 8.004 7737.3458 0.0371 B- -4858.2701 12.2147 216 003533.534 8.592 + 38 127 89 216 Ac 8149.736 9.230 7711.2319 0.0427 B- -2148.8006 14.4375 216 008749.101 9.908 + 36 126 90 216 Th -a 10298.537 11.104 7697.6617 0.0514 B- -7525.2616 27.0327 216 011055.933 11.920 + 34 125 91 216 Pa -a 17823.799 24.647 7659.2006 0.1141 B- -5242.6308 37.3721 216 019134.633 26.459 + 32 124 92 216 U -a 23066.429 28.093 7631.3072 0.1301 B- * 216 024762.829 30.158 +0 55 136 81 217 Tl x 18660# 400# 7693# 2# B- 6399# 500# 217 020032# 429# + 53 135 82 217 Pb x 12260# 300# 7719# 1# B- 3530# 300# 217 013162# 322# + 51 134 83 217 Bi x 8729.963 17.698 7731.8491 0.0816 B- 2846.5103 18.8695 217 009372.000 19.000 + 49 133 84 217 Po +a 5883.452 6.544 7741.3614 0.0302 B- 1488.8543 7.9791 217 006316.145 7.025 + 47 132 85 217 At 4394.598 5.001 7744.6172 0.0230 B- 736.0320 6.1505 217 004717.794 5.368 + 45 131 86 217 Rn -a 3658.566 4.198 7744.4037 0.0193 B- -656.0967 7.5383 217 003927.632 4.506 + 43 130 87 217 Fr -a 4314.663 6.531 7737.7750 0.0301 B- -1574.8729 9.4723 217 004631.980 7.011 + 41 129 88 217 Ra -a 5889.536 7.047 7726.9122 0.0325 B- -2812.7853 13.2129 217 006322.676 7.564 + 39 128 89 217 Ac -a 8702.321 11.223 7710.3448 0.0517 B- -3503.4590 15.4454 217 009342.325 12.048 + 37 127 90 217 Th -a 12205.780 10.614 7690.5945 0.0489 B- -4848.9680 16.3966 217 013103.443 11.394 + 35 126 91 217 Pa -a 17054.748 12.498 7664.6438 0.0576 B- -5916# 81# 217 018309.024 13.417 + 33 125 92 217 U -a 22971# 81# 7634# 0# B- * 217 024660# 86# +0 56 137 81 218 Tl x 23710# 400# 7672# 2# B- 8081# 500# 218 025454# 429# + 54 136 82 218 Pb x 15630# 300# 7705# 1# B- 2414# 301# 218 016779# 322# + 52 135 83 218 Bi x 13216.038 27.013 7712.8280 0.1239 B- 4859.3866 27.0849 218 014188.000 29.000 + 50 134 84 218 Po 8356.652 1.967 7731.5300 0.0090 B- 256.4334 11.5490 218 008971.234 2.112 + 48 133 85 218 At -a 8100.218 11.503 7729.1175 0.0528 B- 2882.8048 11.6054 218 008695.941 12.349 + 46 132 86 218 Rn 5217.413 2.316 7738.7527 0.0106 B- -1842.0267 4.4418 218 005601.123 2.486 + 44 131 87 218 Fr -a 7059.440 4.235 7726.7143 0.0194 B- 413.8838 10.5603 218 007578.620 4.546 + 42 130 88 218 Ra -a 6645.556 9.807 7725.0241 0.0450 B- -4205.2887 58.4224 218 007134.297 10.528 + 40 129 89 218 Ac -a 10850.845 57.616 7702.1450 0.2643 B- -1515.9019 58.5648 218 011648.860 61.853 + 38 128 90 218 Th -a 12366.747 10.516 7691.6026 0.0482 B- -6282.8212 20.7132 218 013276.248 11.289 + 36 127 91 218 Pa -a 18649.568 17.846 7659.1935 0.0819 B- -3245.0869 22.5042 218 020021.133 19.158 + 34 126 92 218 U -a 21894.655 13.714 7640.7191 0.0629 B- * 218 023504.877 14.722 +0 55 137 82 219 Pb x 20620# 400# 7684# 2# B- 4300# 447# 219 022136# 429# + 53 136 83 219 Bi x 16320# 200# 7700# 1# B- 3638# 201# 219 017520# 215# + 51 135 84 219 Po x 12681.361 15.835 7713.3340 0.0723 B- 2285.3395 16.1628 219 013614.000 17.000 + 49 134 85 219 At 10396.021 3.237 7720.1970 0.0148 B- 1566.6838 2.9473 219 011160.587 3.474 + 47 133 86 219 Rn 8829.337 2.100 7723.7784 0.0096 B- 212.3984 6.8938 219 009478.683 2.254 + 45 132 87 219 Fr -a 8616.939 6.874 7721.1759 0.0314 B- -776.9137 9.5906 219 009250.664 7.380 + 43 131 88 219 Ra -a 9393.853 6.814 7714.0560 0.0311 B- -2175.7005 51.9016 219 010084.715 7.315 + 41 130 89 219 Ac -a 11569.553 51.477 7700.5489 0.2351 B- -2893.2268 76.3627 219 012420.425 55.263 + 39 129 90 219 Th -a 14462.780 56.460 7683.7655 0.2578 B- -4120.4434 89.7010 219 015526.432 60.611 + 37 128 91 219 Pa -a 18583.223 69.705 7661.3783 0.3183 B- -4712.7298 70.9693 219 019949.909 74.831 + 35 127 92 219 U -a 23295.953 13.338 7636.2867 0.0609 B- -6140.9976 92.9309 219 025009.233 14.319 + 33 126 93 219 Np -a 29436.951 91.969 7604.6732 0.4199 B- * 219 031601.865 98.732 +0 56 138 82 220 Pb x 24130# 400# 7670# 2# B- 3171# 500# 220 025905# 429# + 54 137 83 220 Bi x 20960# 300# 7681# 1# B- 5696# 300# 220 022501# 322# + 52 136 84 220 Po x 15263.462 17.698 7703.2244 0.0804 B- 887.7139 22.5491 220 016386.000 19.000 + 50 135 85 220 At x 14375.748 13.972 7703.7033 0.0635 B- 3763.7550 14.0896 220 015433.000 15.000 + 48 134 86 220 Rn 10611.994 1.814 7717.2552 0.0082 B- -870.3384 4.0256 220 011392.443 1.947 + 46 133 87 220 Fr -a 11482.332 4.028 7709.7430 0.0183 B- 1210.2406 8.4809 220 012326.789 4.324 + 44 132 88 220 Ra -a 10272.091 7.595 7711.6879 0.0345 B- -3471.6640 9.6266 220 011027.542 8.153 + 42 131 89 220 Ac -a 13743.755 6.129 7692.3515 0.0279 B- -945.7825 14.9144 220 014754.527 6.579 + 40 130 90 220 Th -a 14689.538 13.687 7684.4964 0.0622 B- -5588.8595 20.0508 220 015769.866 14.693 + 38 129 91 220 Pa -a 20278.397 14.655 7655.5364 0.0666 B- -2735# 102# 220 021769.753 15.732 + 36 128 92 220 U -a 23013# 101# 7640# 0# B- -7462# 105# 220 024706# 108# + 34 127 93 220 Np -a 30475.022 30.718 7602.0758 0.1396 B- * 220 032716.280 32.977 +0 55 138 83 221 Bi x 24200# 300# 7668# 1# B- 4426# 301# 221 025980# 322# + 53 137 84 221 Po x 19773.757 19.561 7684.4814 0.0885 B- 2991.0276 24.0390 221 021228.000 21.000 + 51 136 85 221 At x 16782.729 13.972 7694.4754 0.0632 B- 2311.3750 15.0957 221 018017.000 15.000 + 49 135 86 221 Rn +a 14471.354 5.714 7701.3941 0.0259 B- 1194.1032 7.2312 221 015535.637 6.134 + 47 134 87 221 Fr 13277.251 4.886 7703.2572 0.0221 B- 313.3741 6.3858 221 014253.714 5.245 + 45 133 88 221 Ra -a 12963.877 4.630 7701.1352 0.0210 B- -1567.1715 57.0591 221 013917.293 4.970 + 43 132 89 221 Ac -a 14531.048 56.901 7690.5039 0.2575 B- -2408.8773 57.4376 221 015599.721 61.086 + 41 131 90 221 Th -a 16939.926 7.994 7676.0640 0.0362 B- -3435.0112 59.9069 221 018185.757 8.582 + 39 130 91 221 Pa -a 20374.937 59.380 7656.9809 0.2687 B- -4145.0590 93.4311 221 021873.393 63.746 + 37 129 92 221 U -a 24519.996 72.135 7634.6849 0.3264 B- -5390# 213# 221 026323.297 77.440 + 35 128 93 221 Np x 29910# 200# 7607# 1# B- -6019# 361# 221 032110# 215# + 33 127 94 221 Pu x 35930# 300# 7576# 1# B- * 221 038572# 322# +0 56 139 83 222 Bi x 28950# 300# 7648# 1# B- 6464# 303# 222 031079# 322# + 54 138 84 222 Po x 22486.268 40.054 7674.0054 0.1804 B- 1533.2393 43.0709 222 024140.000 43.000 + 52 137 85 222 At x 20953.028 15.835 7677.3878 0.0713 B- 4581.0714 15.9542 222 022494.000 17.000 + 50 136 86 222 Rn 16371.957 1.944 7694.4991 0.0088 B- -6.1461 7.7013 222 017576.017 2.086 + 48 135 87 222 Fr x 16378.103 7.452 7690.9474 0.0336 B- 2057.8980 8.6816 222 017582.615 8.000 + 46 134 88 222 Ra 14320.205 4.454 7696.6931 0.0201 B- -2301.5922 6.2737 222 015373.371 4.781 + 44 133 89 222 Ac -a 16621.797 4.699 7682.8015 0.0212 B- -581.2415 11.1289 222 017844.232 5.044 + 42 132 90 222 Th -a 17203.039 10.216 7676.6592 0.0460 B- -4861.3220 87.1915 222 018468.220 10.966 + 40 131 91 222 Pa -a 22064.361 86.606 7651.2373 0.3901 B- -2208.4729 101.0129 222 023687.064 92.975 + 38 130 92 222 U -a 24272.834 51.994 7637.7651 0.2342 B- -7001.8072 64.4300 222 026057.957 55.817 + 36 129 93 222 Np -a 31274.641 38.051 7602.7013 0.1714 B- -3785# 302# 222 033574.706 40.849 + 34 128 94 222 Pu x 35060# 300# 7582# 1# B- * 222 037638# 322# +0 57 140 83 223 Bi x 32240# 400# 7636# 2# B- 5161# 445# 223 034611# 429# + 55 139 84 223 Po x 27079# 196# 7655# 1# B- 3651# 196# 223 029070# 210# + 53 138 85 223 At x 23428.008 13.972 7668.0557 0.0627 B- 3038.2698 16.0129 223 025151.000 15.000 + 51 137 86 223 Rn 20389.738 7.822 7678.1720 0.0351 B- 2007.4091 8.0568 223 021889.283 8.397 + 49 136 87 223 Fr 18382.329 1.931 7683.6655 0.0087 B- 1149.0844 0.8476 223 019734.241 2.073 + 47 135 88 223 Ra 17233.245 2.090 7685.3101 0.0094 B- -591.8099 6.9657 223 018500.648 2.243 + 45 134 89 223 Ac -a 17825.055 6.947 7679.1479 0.0312 B- -1560.3471 10.4712 223 019135.982 7.457 + 43 133 90 223 Th -a 19385.402 7.943 7668.6426 0.0356 B- -2952.2124 76.0305 223 020811.083 8.527 + 41 132 91 223 Pa -a 22337.614 75.632 7651.8957 0.3392 B- -3707.6637 95.9225 223 023980.414 81.193 + 39 131 92 223 U -a 26045.278 59.054 7631.7611 0.2648 B- -4613.3046 101.7520 223 027960.754 63.396 + 37 130 93 223 Np -a 30658.583 82.863 7607.5654 0.3716 B- -5462# 311# 223 032913.340 88.956 + 35 129 94 223 Pu x 36121# 300# 7580# 1# B- -6579# 424# 223 038777# 322# + 33 128 95 223 Am x 42700# 300# 7547# 1# B- * 223 045840# 322# +0 58 141 83 224 Bi x 37070# 400# 7616# 2# B- 7159# 445# 224 039796# 429# + 56 140 84 224 Po x 29910# 196# 7644# 1# B- 2199# 197# 224 032110# 210# + 54 139 85 224 At x 27711.018 22.356 7650.7354 0.0998 B- 5265.9197 24.4153 224 029749.000 24.000 + 52 138 86 224 Rn 22445.098 9.814 7670.7514 0.0438 B- 696.4840 14.8750 224 024095.803 10.536 + 50 137 87 224 Fr x 21748.614 11.178 7670.3680 0.0499 B- 2922.7819 11.3237 224 023348.096 12.000 + 48 136 88 224 Ra 18825.832 1.811 7679.9236 0.0081 B- -1408.3152 4.0869 224 020210.361 1.944 + 46 135 89 224 Ac -a 20234.148 4.089 7670.1438 0.0183 B- 238.5672 10.3428 224 021722.249 4.389 + 44 134 90 224 Th -a 19995.581 9.604 7667.7162 0.0429 B- -3866.7705 12.1339 224 021466.137 10.310 + 42 133 91 224 Pa -a 23862.351 7.587 7646.9612 0.0339 B- -1880.3393 16.9711 224 025617.286 8.145 + 40 132 92 224 U -a 25742.690 15.261 7635.0742 0.0681 B- -6289.5572 32.7036 224 027635.913 16.383 + 38 131 93 224 Np 32032.248 28.925 7603.5032 0.1291 B- -3248# 301# 224 034388.030 31.052 + 36 130 94 224 Pu x 35280# 300# 7586# 1# B- -7980# 500# 224 037875# 322# + 34 129 95 224 Am x 43260# 400# 7546# 2# B- * 224 046442# 429# +0 57 141 84 225 Po x 34580# 300# 7626# 1# B- 4280# 424# 225 037123# 322# + 55 140 85 225 At x 30300# 300# 7641# 1# B- 3765# 300# 225 032528# 322# + 53 139 86 225 Rn 26534.143 11.140 7654.3581 0.0495 B- 2713.5412 16.3492 225 028485.572 11.958 + 51 138 87 225 Fr 23820.602 11.967 7662.9412 0.0532 B- 1827.5584 12.1574 225 025572.466 12.847 + 49 137 88 225 Ra 21993.044 2.596 7667.5866 0.0115 B- 355.7386 5.0067 225 023610.502 2.786 + 47 136 89 225 Ac 21637.305 4.758 7665.6906 0.0211 B- -672.8878 6.6576 225 023228.601 5.107 + 45 135 90 225 Th -a 22310.193 5.093 7659.2229 0.0226 B- -2046.4473 82.0038 225 023950.975 5.467 + 43 134 91 225 Pa -a 24356.640 81.867 7646.6504 0.3639 B- -3015.3610 82.4514 225 026147.927 87.887 + 41 133 92 225 U -a 27372.001 9.934 7629.7717 0.0442 B- -4246.0969 92.1491 225 029385.050 10.664 + 39 132 93 225 Np -a 31618.098 91.618 7607.4231 0.4072 B- -4682# 314# 225 033943.422 98.355 + 37 131 94 225 Pu x 36300# 300# 7583# 1# B- -6090# 500# 225 038970# 322# + 35 130 95 225 Am x 42390# 400# 7553# 2# B- * 225 045508# 429# +0 58 142 84 226 Po x 37549# 401# 7614# 2# B- 2889# 500# 226 040310# 430# + 56 141 85 226 At x 34660# 300# 7624# 1# B- 5913# 300# 226 037209# 322# + 54 140 86 226 Rn 28747.194 10.477 7646.4108 0.0464 B- 1226.6542 12.1895 226 030861.380 11.247 + 52 139 87 226 Fr 27520.539 6.230 7648.3768 0.0276 B- 3852.9638 6.5215 226 029544.512 6.688 + 50 138 88 226 Ra 23667.576 1.927 7661.9636 0.0085 B- -641.6252 3.2730 226 025408.186 2.068 + 48 137 89 226 Ac 24309.201 3.100 7655.6628 0.0137 B- 1111.5517 4.5626 226 026096.999 3.327 + 46 136 90 226 Th 23197.649 4.481 7657.1195 0.0198 B- -2835.9504 11.9702 226 024903.699 4.810 + 44 135 91 226 Pa -a 26033.600 11.213 7641.1093 0.0496 B- -1295.1978 15.6747 226 027948.217 12.037 + 42 134 92 226 U -a 27328.797 11.071 7631.9166 0.0490 B- -5488.0792 102.6485 226 029338.669 11.884 + 40 133 93 226 Np -a 32816.877 102.063 7604.1714 0.4516 B- -2813# 225# 226 035230.364 109.568 + 38 132 94 226 Pu x 35630# 200# 7588# 1# B- -7340# 361# 226 038250# 215# + 36 131 95 226 Am x 42970# 300# 7552# 1# B- * 226 046130# 322# +0 59 143 84 227 Po x 42281# 401# 7596# 2# B- 4850# 500# 227 045390# 430# + 57 142 85 227 At x 37430# 300# 7613# 1# B- 4544# 300# 227 040183# 322# + 55 141 86 227 Rn 32885.835 14.091 7630.0508 0.0621 B- 3203.3894 15.2755 227 035304.393 15.127 + 53 140 87 227 Fr 29682.445 5.898 7640.7162 0.0260 B- 2504.9813 6.2112 227 031865.413 6.332 + 51 139 88 227 Ra -n 27177.464 1.946 7648.3048 0.0086 B- 1327.9489 2.2622 227 029176.205 2.089 + 49 138 89 227 Ac 25849.515 1.926 7650.7084 0.0085 B- 44.7559 0.8297 227 027750.594 2.068 + 47 137 90 227 Th 25804.759 2.088 7647.4591 0.0092 B- -1025.6117 7.2815 227 027702.546 2.241 + 45 136 91 227 Pa -a 26830.371 7.263 7639.4945 0.0320 B- -2214.6629 11.1118 227 028803.586 7.797 + 43 135 92 227 U -a 29045.034 8.510 7626.2918 0.0375 B- -3533.9848 77.4417 227 031181.124 9.136 + 41 134 93 227 Np -a 32579.018 76.989 7607.2771 0.3392 B- -4191# 126# 227 034975.012 82.651 + 39 133 94 227 Pu x 36770# 100# 7585# 0# B- -5410# 224# 227 039474# 107# + 37 132 95 227 Am x 42180# 200# 7558# 1# B- * 227 045282# 215# +0 58 143 85 228 At x 41880# 400# 7596# 2# B- 6637# 400# 228 044960# 429# + 56 142 86 228 Rn 35243.466 17.677 7621.6457 0.0775 B- 1859.2451 18.9157 228 037835.415 18.977 + 54 141 87 228 Fr 33384.221 6.732 7626.3689 0.0295 B- 4444.0270 7.0210 228 035839.433 7.226 + 52 140 88 228 Ra +a 28940.194 1.995 7642.4289 0.0088 B- 45.5402 0.6344 228 031068.574 2.141 + 50 139 89 228 Ac - 28894.654 2.093 7639.1973 0.0092 B- 2123.7545 2.6446 228 031019.685 2.247 + 48 138 90 228 Th 26770.899 1.806 7645.0807 0.0079 B- -2152.6993 4.3399 228 028739.741 1.938 + 46 137 91 228 Pa -a 28923.599 4.340 7632.2076 0.0190 B- -296.4020 14.0858 228 031050.758 4.659 + 44 136 92 228 U -a 29220.001 13.474 7627.4763 0.0591 B- -4605# 101# 228 031368.959 14.465 + 42 135 93 228 Np -a 33825# 100# 7604# 0# B- -2283# 103# 228 036313# 108# + 40 134 94 228 Pu -a 36107.809 23.352 7590.4039 0.1024 B- -6742# 202# 228 038763.325 25.069 + 38 133 95 228 Am x 42850# 200# 7557# 1# B- * 228 046001# 215# +0 59 144 85 229 At x 44890# 400# 7585# 2# B- 5527# 400# 229 048191# 429# + 57 143 86 229 Rn x 39362.400 13.041 7605.6227 0.0569 B- 3694.1465 13.9670 229 042257.272 14.000 + 55 142 87 229 Fr 35668.253 5.001 7618.3380 0.0218 B- 3106.2907 16.2305 229 038291.443 5.368 + 53 141 88 229 Ra x 32561.963 15.441 7628.4862 0.0674 B- 1872.0266 19.6229 229 034956.703 16.576 + 51 140 89 229 Ac x 30689.936 12.109 7633.2446 0.0529 B- 1104.4191 12.3458 229 032947.000 13.000 + 49 139 90 229 Th 29585.517 2.404 7634.6510 0.0105 B- -311.3310 3.7152 229 031761.357 2.581 + 47 138 91 229 Pa 29896.848 3.280 7629.8752 0.0143 B- -1313.7716 6.6554 229 032095.585 3.521 + 45 137 92 229 U -a 31210.620 5.938 7620.7218 0.0259 B- -2590.7577 101.3342 229 033505.976 6.374 + 43 136 93 229 Np -a 33801.378 101.177 7605.9921 0.4418 B- -3593.5462 117.9433 229 036287.269 108.618 + 41 135 94 229 Pu -a 37394.924 60.633 7586.8834 0.2648 B- -4785.4899 122.4147 229 040145.099 65.092 + 39 134 95 229 Am -a 42180.414 106.348 7562.5697 0.4644 B- * 229 045282.534 114.169 +0 58 144 86 230 Rn x 42170# 200# 7595# 1# B- 2683# 200# 230 045271# 215# + 56 143 87 230 Fr 39486.769 6.541 7603.7052 0.0284 B- 4970.4627 12.1984 230 042390.787 7.022 + 54 142 88 230 Ra x 34516.306 10.296 7621.9144 0.0448 B- 677.9196 18.8884 230 037054.776 11.053 + 52 141 89 230 Ac x 33838.386 15.835 7621.4604 0.0689 B- 2975.8745 15.8815 230 036327.000 17.000 + 50 140 90 230 Th 30862.512 1.209 7630.9974 0.0053 B- -1311.0313 2.8334 230 033132.267 1.297 + 48 139 91 230 Pa 32173.543 3.038 7621.8958 0.0132 B- 558.5262 4.5919 230 034539.717 3.261 + 46 138 92 230 U -a 31615.017 4.509 7620.9227 0.0196 B- -3621.5986 55.1683 230 033940.114 4.841 + 44 137 93 230 Np -a 35236.615 55.007 7601.7751 0.2392 B- -1695.5543 56.8505 230 037828.060 59.051 + 42 136 94 230 Pu -a 36932.170 14.451 7591.0016 0.0628 B- -5940# 144# 230 039648.313 15.514 + 40 135 95 230 Am -a 42872# 143# 7562# 1# B- * 230 046025# 153# +0 59 145 86 231 Rn x 46550# 300# 7579# 1# B- 4469# 300# 231 049973# 322# + 57 144 87 231 Fr x 42080.575 7.731 7594.5009 0.0335 B- 3864.0868 13.7495 231 045175.353 8.300 + 55 143 88 231 Ra 38216.488 11.370 7607.8418 0.0492 B- 2453.6351 17.3014 231 041027.085 12.206 + 53 142 89 231 Ac x 35762.853 13.041 7615.0768 0.0565 B- 1947.0425 13.0976 231 038393.000 14.000 + 51 141 90 231 Th 33815.811 1.217 7620.1188 0.0053 B- 391.4727 1.4598 231 036302.764 1.306 + 49 140 91 231 Pa 33424.338 1.771 7618.4267 0.0077 B- -381.6138 2.0325 231 035882.500 1.901 + 47 139 92 231 U -a 33805.952 2.670 7613.3879 0.0116 B- -1817.7347 51.1839 231 036292.180 2.866 + 45 138 93 231 Np -a 35623.686 51.154 7602.1321 0.2214 B- -2684.8905 55.6931 231 038243.598 54.916 + 43 137 94 231 Pu -a 38308.577 22.061 7587.1224 0.0955 B- -4101# 301# 231 041125.946 23.683 + 41 136 95 231 Am x 42410# 300# 7566# 1# B- -4860# 424# 231 045529# 322# + 39 135 96 231 Cm x 47270# 300# 7542# 1# B- * 231 050746# 322# +0 58 145 87 232 Fr x 46072.834 13.972 7579.3481 0.0602 B- 5575.8791 16.7023 232 049461.219 15.000 + 56 144 88 232 Ra 40496.955 9.151 7600.0099 0.0394 B- 1342.5322 15.9313 232 043475.267 9.823 + 54 143 89 232 Ac x 39154.423 13.041 7602.4245 0.0562 B- 3707.7131 13.1181 232 042034.000 14.000 + 52 142 90 232 Th 35446.710 1.421 7615.0338 0.0061 B- -499.8388 7.7338 232 038053.606 1.525 + 50 141 91 232 Pa + 35946.549 7.645 7609.5072 0.0330 B- 1337.1034 7.4278 232 038590.205 8.206 + 48 140 92 232 U 34609.445 1.808 7611.8984 0.0078 B- -2750# 100# 232 037154.765 1.941 + 46 139 93 232 Np - 37359# 100# 7597# 0# B- -1001# 101# 232 040107# 107# + 44 138 94 232 Pu -a 38360.915 16.885 7588.9839 0.0728 B- -5059# 300# 232 041182.133 18.126 + 42 137 95 232 Am x 43420# 300# 7564# 1# B- -2913# 361# 232 046613# 322# + 40 136 96 232 Cm -a 46333# 201# 7548# 1# B- * 232 049740# 216# +0 59 146 87 233 Fr x 48920.052 19.561 7569.2398 0.0840 B- 4585.9906 21.3694 233 052517.833 21.000 + 57 145 88 233 Ra 44334.062 8.603 7585.5644 0.0369 B- 3026.0244 15.6228 233 047594.570 9.235 + 55 144 89 233 Ac x 41308.037 13.041 7595.1939 0.0560 B- 2576.3950 13.1184 233 044346.000 14.000 + 53 143 90 233 Th 38731.642 1.424 7602.8937 0.0061 B- 1242.2320 1.1224 233 041580.126 1.528 + 51 142 91 233 Pa 37489.410 1.336 7604.8675 0.0057 B- 570.2993 1.9750 233 040246.535 1.433 + 49 141 92 233 U 36919.111 2.254 7603.9574 0.0097 B- -1029.4197 51.0050 233 039634.294 2.420 + 47 140 93 233 Np -a 37948.531 50.981 7596.1816 0.2188 B- -2103.3047 74.3811 233 040739.421 54.729 + 45 139 94 233 Pu -a 40051.836 54.178 7583.7968 0.2325 B- -3233# 126# 233 042997.411 58.162 + 43 138 95 233 Am -a 43285# 114# 7567# 0# B- -4008# 140# 233 046468# 123# + 41 137 96 233 Cm -a 47293.340 81.095 7546.0020 0.3480 B- -5478# 247# 233 050771.485 87.059 + 39 136 97 233 Bk -a 52771# 233# 7519# 1# B- * 233 056652# 250# +0 58 146 88 234 Ra x 46930.629 8.383 7576.5439 0.0358 B- 2089.4348 16.2945 234 050382.100 9.000 + 56 145 89 234 Ac x 44841.195 13.972 7582.1297 0.0597 B- 4228.2364 14.2103 234 048139.000 15.000 + 54 144 90 234 Th +a 40612.958 2.589 7596.8557 0.0111 B- 274.0882 3.1716 234 043599.801 2.779 + 52 143 91 234 Pa IT 40338.870 4.094 7594.6837 0.0175 B- 2193.9105 3.9998 234 043305.555 4.395 + 50 142 92 234 U 38144.959 1.129 7600.7160 0.0048 B- -1809.8462 8.3205 234 040950.296 1.212 + 48 141 93 234 Np - 39954.806 8.397 7589.6382 0.0359 B- -395.1807 10.7522 234 042893.245 9.014 + 46 140 94 234 Pu -a 40349.986 6.798 7584.6061 0.0291 B- -4112# 160# 234 043317.489 7.298 + 44 139 95 234 Am -a 44462# 160# 7564# 1# B- -2261# 161# 234 047731# 172# + 42 138 96 234 Cm -a 46722.411 17.078 7550.6868 0.0730 B- -6673# 154# 234 050158.568 18.333 + 40 137 97 234 Bk -a 53395# 153# 7519# 1# B- * 234 057322# 164# +0 59 147 88 235 Ra x 51130# 300# 7561# 1# B- 3773# 300# 235 054890# 322# + 57 146 89 235 Ac x 47357.160 13.972 7573.5051 0.0595 B- 3339.4064 19.1127 235 050840.000 15.000 + 55 145 90 235 Th x 44017.754 13.041 7584.3862 0.0555 B- 1728.8531 19.1127 235 047255.000 14.000 + 53 144 91 235 Pa x 42288.901 13.972 7588.4139 0.0595 B- 1370.1184 14.0169 235 045399.000 15.000 + 51 143 92 235 U 40918.782 1.116 7590.9151 0.0048 B- -124.2619 0.8524 235 043928.117 1.198 + 49 142 93 235 Np 41043.044 1.388 7587.0571 0.0059 B- -1139.3021 20.4992 235 044061.518 1.490 + 47 141 94 235 Pu -a 42182.346 20.521 7578.8799 0.0873 B- -2442.2558 56.5932 235 045284.609 22.030 + 45 140 95 235 Am -a 44624.602 52.780 7565.1582 0.2246 B- -3389# 115# 235 047906.478 56.661 + 43 139 96 235 Cm -a 48013# 102# 7547# 0# B- -4757# 413# 235 051545# 110# + 41 138 97 235 Bk x 52770# 401# 7524# 2# B- * 235 056651# 430# +0 58 147 89 236 Ac x 51220.998 38.191 7559.2423 0.1618 B- 4965.7951 40.6669 236 054988.000 41.000 + 56 146 90 236 Th x 46255.203 13.972 7576.9688 0.0592 B- 921.2477 19.7600 236 049657.000 15.000 + 54 145 91 236 Pa x 45333.955 13.972 7577.5573 0.0592 B- 2889.3730 14.0166 236 048668.000 15.000 + 52 144 92 236 U 42444.582 1.112 7586.4854 0.0047 B- -933.5116 50.4152 236 045566.130 1.193 + 50 143 93 236 Np IT 43378.094 50.421 7579.2148 0.2136 B- 476.5854 50.3887 236 046568.296 54.129 + 48 142 94 236 Pu 42901.508 1.810 7577.9192 0.0077 B- -3139# 119# 236 046056.661 1.942 + 46 141 95 236 Am -a 46041# 119# 7561# 1# B- -1812# 120# 236 049427# 127# + 44 140 96 236 Cm -a 47852.820 17.635 7550.3090 0.0747 B- -5689# 361# 236 051372.112 18.931 + 42 139 97 236 Bk -a 53542# 361# 7523# 2# B- * 236 057479# 387# +0 59 148 89 237 Ac x 54020# 400# 7550# 2# B- 4065# 400# 237 057993# 429# + 57 147 90 237 Th x 49955.097 15.835 7563.4433 0.0668 B- 2427.4736 20.5140 237 053629.000 17.000 + 55 146 91 237 Pa x 47527.624 13.041 7570.3847 0.0550 B- 2137.4905 13.0962 237 051023.000 14.000 + 53 145 92 237 U 45390.133 1.202 7576.1026 0.0051 B- 518.5338 0.5200 237 048728.309 1.290 + 51 144 93 237 Np 44871.599 1.120 7574.9895 0.0047 B- -220.0630 1.2944 237 048171.640 1.201 + 49 143 94 237 Pu 45091.662 1.697 7570.7599 0.0072 B- -1478# 59# 237 048407.888 1.821 + 47 142 95 237 Am -a 46570# 59# 7561# 0# B- -2677# 95# 237 049995# 64# + 45 141 96 237 Cm -a 49247.151 74.399 7546.6241 0.3139 B- -3963# 242# 237 052868.988 79.870 + 43 140 97 237 Bk -a 53210# 230# 7527# 1# B- -4728# 250# 237 057123# 247# + 41 139 98 237 Cf -a 57938.255 97.347 7503.3507 0.4107 B- * 237 062199.272 104.506 +0 58 148 90 238 Th +a 52525# 283# 7555# 1# B- 1631# 284# 238 056388# 304# + 56 147 91 238 Pa x 50894.043 15.835 7558.3449 0.0665 B- 3586.3111 15.9056 238 054637.000 17.000 + 54 146 92 238 U 47307.732 1.492 7570.1262 0.0063 B- -146.8652 1.2006 238 050786.936 1.601 + 52 145 93 238 Np -n 47454.597 1.137 7566.2220 0.0048 B- 1291.4491 0.4573 238 050944.603 1.220 + 50 144 94 238 Pu 46163.148 1.138 7568.3611 0.0048 B- -2258.2731 58.9005 238 049558.175 1.221 + 48 143 95 238 Am -a 48421.421 58.911 7555.5853 0.2475 B- -1023.7818 60.1587 238 051982.531 63.243 + 46 142 96 238 Cm -a 49445.203 12.234 7547.9966 0.0514 B- -4771# 256# 238 053081.606 13.133 + 44 141 97 238 Bk -a 54216# 256# 7525# 1# B- -3061# 393# 238 058204# 275# + 42 140 98 238 Cf x 57278# 298# 7509# 1# B- * 238 061490# 320# +0 59 149 90 239 Th x 56500# 400# 7540# 2# B- 3162# 445# 239 060655# 429# + 57 148 91 239 Pa x 53337# 196# 7550# 1# B- 2765# 196# 239 057260# 210# + 55 147 92 239 U -n 50572.668 1.502 7558.5624 0.0063 B- 1261.6634 1.4935 239 054291.989 1.612 + 53 146 93 239 Np 49311.005 1.310 7560.5680 0.0055 B- 722.7849 0.9304 239 052937.538 1.406 + 51 145 94 239 Pu 48588.220 1.112 7560.3187 0.0047 B- -802.1402 1.6635 239 052161.596 1.194 + 49 144 95 239 Am -a 49390.360 1.982 7553.6891 0.0083 B- -1756.6021 150.0740 239 053022.729 2.127 + 47 143 96 239 Cm -a 51146.962 150.070 7543.0659 0.6279 B- -3103# 256# 239 054908.519 161.107 + 45 142 97 239 Bk -a 54250# 207# 7527# 1# B- -3952# 239# 239 058239# 222# + 43 141 98 239 Cf -a 58202# 120# 7507# 1# B- -5429# 323# 239 062482# 129# + 41 140 99 239 Es x 63630# 300# 7481# 1# B- * 239 068310# 322# +0 58 149 91 240 Pa x 57010# 200# 7537# 1# B- 4295# 200# 240 061203# 215# + 56 148 92 240 U 52715.497 2.553 7551.7705 0.0106 B- 399.2685 17.0830 240 056592.411 2.740 + 54 147 93 240 Np 52316.229 17.032 7550.1743 0.0710 B- 2190.9095 17.0151 240 056163.778 18.284 + 52 146 94 240 Pu 50125.319 1.105 7556.0433 0.0046 B- -1384.7902 13.7882 240 053811.740 1.186 + 50 145 95 240 Am +n 51510.110 13.832 7547.0136 0.0576 B- -214.1127 13.8967 240 055298.374 14.849 + 48 144 96 240 Cm 51724.222 1.905 7542.8617 0.0079 B- -3940# 150# 240 055528.233 2.045 + 46 143 97 240 Bk - 55664# 150# 7523# 1# B- -2324# 151# 240 059758# 161# + 44 142 98 240 Cf -a 57988.719 18.034 7510.2400 0.0751 B- -6237# 366# 240 062253.447 19.360 + 42 141 99 240 Es -a 64225# 366# 7481# 2# B- * 240 068949# 393# +0 59 150 91 241 Pa x 59740# 300# 7528# 1# B- 3543# 358# 241 064134# 322# + 57 149 92 241 U x 56197# 196# 7539# 1# B- 1882# 220# 241 060330# 210# + 55 148 93 241 Np + 54315.115 100.006 7544.0426 0.4150 B- 1360.0000 100.0000 241 058309.671 107.360 + 53 147 94 241 Pu 52955.115 1.105 7546.4395 0.0046 B- 20.7799 0.1658 241 056849.651 1.186 + 51 146 95 241 Am 52934.335 1.113 7543.2795 0.0046 B- -767.4346 1.1685 241 056827.343 1.195 + 49 145 96 241 Cm 53701.770 1.607 7536.8488 0.0067 B- -2279# 165# 241 057651.218 1.725 + 47 144 97 241 Bk +a 55981# 165# 7524# 1# B- -3346# 235# 241 060098# 178# + 45 143 98 241 Cf -a 59327# 167# 7507# 1# B- -4567# 285# 241 063690# 180# + 43 142 99 241 Es -a 63893# 231# 7485# 1# B- -5327# 379# 241 068592# 248# + 41 141 100 241 Fm x 69220# 300# 7459# 1# B- * 241 074311# 322# +0 58 150 92 242 U +a 58620# 201# 7532# 1# B- 1203# 283# 242 062931# 215# + 56 149 93 242 Np + 57416.876 200.004 7533.4042 0.8265 B- 2700.0000 200.0000 242 061639.548 214.712 + 54 148 94 242 Pu 54716.876 1.245 7541.3284 0.0052 B- -751.1373 0.7080 242 058740.979 1.336 + 52 147 95 242 Am -n 55468.014 1.118 7534.9917 0.0046 B- 664.3145 0.4143 242 059547.358 1.199 + 50 146 96 242 Cm 54803.699 1.141 7534.5040 0.0047 B- -2948# 135# 242 058834.187 1.224 + 48 145 97 242 Bk IT 57752# 135# 7519# 1# B- -1635# 135# 242 061999# 144# + 46 144 98 242 Cf -a 59386.982 12.892 7509.0991 0.0533 B- -5414# 257# 242 063754.544 13.840 + 44 143 99 242 Es -a 64801# 257# 7483# 1# B- -3598# 476# 242 069567# 276# + 42 142 100 242 Fm x 68400# 401# 7465# 2# B- * 242 073430# 430# +0 59 151 92 243 U x 62480# 300# 7518# 1# B- 2674# 302# 243 067075# 322# + 57 150 93 243 Np IT 59806# 32# 7526# 0# B- 2051# 32# 243 064204# 34# + 55 149 94 243 Pu 57754.561 2.542 7531.0087 0.0105 B- 579.5559 2.6216 243 062002.068 2.728 + 53 148 95 243 Am 57175.005 1.388 7530.1742 0.0057 B- -6.9302 1.5692 243 061379.889 1.490 + 51 147 96 243 Cm -a 57181.936 1.496 7526.9261 0.0062 B- -1507.6936 4.5065 243 061387.329 1.605 + 49 146 97 243 Bk -a 58689.629 4.524 7517.5021 0.0186 B- -2300# 181# 243 063005.905 4.856 + 47 145 98 243 Cf -a 60990# 181# 7505# 1# B- -3757# 275# 243 065475# 194# + 45 144 99 243 Es -a 64747# 207# 7486# 1# B- -4569# 245# 243 069508# 222# + 43 143 100 243 Fm -a 69316# 130# 7464# 1# B- * 243 074414# 140# +0 58 151 93 244 Np x 63240# 100# 7514# 0# B- 3434# 100# 244 067891# 107# + 56 150 94 244 Pu 59806.021 2.346 7524.8154 0.0096 B- -73.1143 2.6856 244 064204.401 2.518 + 54 149 95 244 Am + 59879.135 1.491 7521.3095 0.0061 B- 1427.3000 1.0000 244 064282.892 1.600 + 52 148 96 244 Cm -a 58451.835 1.106 7523.9527 0.0045 B- -2261.9902 14.3567 244 062750.622 1.187 + 50 147 97 244 Bk -a 60713.825 14.399 7511.4759 0.0590 B- -764.2709 14.5724 244 065178.969 15.457 + 48 146 98 244 Cf 61478.096 2.617 7505.1373 0.0107 B- -4547# 181# 244 065999.447 2.809 + 46 145 99 244 Es -a 66026# 181# 7483# 1# B- -2938# 271# 244 070881# 195# + 44 144 100 244 Fm -a 68964# 201# 7468# 1# B- -6634# 425# 244 074036# 216# + 42 143 101 244 Md -a 75597# 374# 7438# 2# B- * 244 081157# 402# +0 59 152 93 245 Np x 65850# 200# 7506# 1# B- 2672# 201# 245 070693# 215# + 57 151 94 245 Pu -n 63178.173 13.620 7513.2822 0.0556 B- 1277.7559 13.7334 245 067824.554 14.621 + 55 150 95 245 Am +a 61900.417 1.886 7515.3043 0.0077 B- 895.8929 1.5491 245 066452.827 2.024 + 53 149 96 245 Cm 61004.524 1.149 7515.7677 0.0047 B- -809.2519 1.4964 245 065491.047 1.233 + 51 148 97 245 Bk -a 61813.776 1.792 7509.2714 0.0073 B- -1571.3755 2.5861 245 066359.814 1.923 + 49 147 98 245 Cf 63385.151 2.428 7499.6644 0.0099 B- -2930# 165# 245 068046.755 2.606 + 47 146 99 245 Es IT 66315# 165# 7485# 1# B- -3877# 256# 245 071192# 178# + 45 145 100 245 Fm -a 70192# 195# 7465# 1# B- -5133# 325# 245 075354# 210# + 43 144 101 245 Md -a 75325# 260# 7441# 1# B- * 245 080864# 279# +0 58 152 94 246 Pu 65394.772 14.985 7506.5401 0.0609 B- 401# 14# 246 070204.172 16.087 + 56 151 95 246 Am IT 64994# 18# 7505# 0# B- 2377# 18# 246 069774# 19# + 54 150 96 246 Cm 62616.912 1.525 7511.4716 0.0062 B- -1350.0000 60.0000 246 067222.016 1.637 + 52 149 97 246 Bk - 63966.912 60.019 7502.8035 0.2440 B- -123.3159 60.0198 246 068671.300 64.433 + 50 148 98 246 Cf 64090.228 1.514 7499.1220 0.0062 B- -3728.5741 89.9373 246 068803.685 1.625 + 48 147 99 246 Es 67818.802 89.925 7480.7849 0.3655 B- -2372.3848 90.9577 246 072806.474 96.538 + 46 146 100 246 Fm -a 70191.187 13.670 7467.9608 0.0556 B- -5924# 260# 246 075353.334 14.675 + 44 145 101 246 Md -a 76115# 260# 7441# 1# B- * 246 081713# 279# +0 59 153 94 247 Pu x 69210# 200# 7493# 1# B- 2057# 224# 247 074300# 215# + 57 152 95 247 Am + 67153# 100# 7499# 0# B- 1620# 100# 247 072092# 107# + 55 151 96 247 Cm 65533.105 3.797 7501.9318 0.0154 B- 43.5841 6.3245 247 070352.678 4.076 + 53 150 97 247 Bk -a 65489.521 5.189 7498.9408 0.0210 B- -619.8711 15.2376 247 070305.889 5.570 + 51 149 98 247 Cf +a 66109.392 14.327 7493.2638 0.0580 B- -2469.0006 24.1495 247 070971.348 15.380 + 49 148 99 247 Es +a 68578.393 19.441 7480.1005 0.0787 B- -3094# 182# 247 073621.929 20.870 + 47 147 100 247 Fm +a 71672# 181# 7464# 1# B- -4263# 275# 247 076944# 194# + 45 146 101 247 Md -a 75936# 207# 7444# 1# B- * 247 081520# 223# +0 58 153 95 248 Am + 70563# 200# 7487# 1# B- 3170# 200# 248 075752# 215# + 56 152 96 248 Cm 67392.748 2.358 7496.7291 0.0095 B- -738.3049 50.0026 248 072349.086 2.531 + 54 151 97 248 Bk +a 68131.053 50.058 7490.5975 0.2018 B- 893.1015 50.3143 248 073141.689 53.739 + 52 150 98 248 Cf -a 67237.951 5.121 7491.0440 0.0207 B- -3061# 53# 248 072182.905 5.497 + 50 149 99 248 Es -a 70299# 52# 7476# 0# B- -1599# 53# 248 075469# 56# + 48 148 100 248 Fm 71897.793 8.497 7465.9451 0.0343 B- -5050# 184# 248 077185.451 9.122 + 46 147 101 248 Md -a 76948# 184# 7442# 1# B- -3741# 290# 248 082607# 198# + 44 146 102 248 No -a 80689# 224# 7424# 1# B- * 248 086623# 241# +0 59 154 95 249 Am x 73104# 298# 7479# 1# B- 2353# 298# 249 078480# 320# + 57 153 96 249 Cm -n 70750.696 2.371 7485.5510 0.0095 B- 904.3630 2.5934 249 075953.992 2.545 + 55 152 97 249 Bk + 69846.333 1.248 7486.0410 0.0050 B- 123.6000 0.4000 249 074983.118 1.339 + 53 151 98 249 Cf 69722.733 1.182 7483.3954 0.0048 B- -1452# 30# 249 074850.428 1.269 + 51 150 99 249 Es -a 71175# 30# 7474# 0# B- -2344# 31# 249 076409# 32# + 49 149 100 249 Fm 73519.143 6.212 7461.8649 0.0249 B- -3661.8091 164.5418 249 078926.042 6.668 + 47 148 101 249 Md 77180.952 164.425 7444.0169 0.6603 B- -4606# 324# 249 082857.155 176.516 + 45 147 102 249 No -a 81787# 279# 7422# 1# B- * 249 087802# 300# +0 58 154 96 250 Cm -nn 72989.588 10.274 7478.9385 0.0411 B- 37.5820 10.6414 250 078357.541 11.029 + 56 153 97 250 Bk +a 72952.006 2.898 7475.9594 0.0116 B- 1781.6696 2.4561 250 078317.195 3.110 + 54 152 98 250 Cf -a 71170.336 1.538 7479.9567 0.0062 B- -2055# 100# 250 076404.494 1.650 + 52 151 99 250 Es - 73225# 100# 7469# 0# B- -847# 100# 250 078611# 107# + 50 150 100 250 Fm 74072.193 7.888 7462.0905 0.0316 B- -4326.9476 91.2615 250 079519.765 8.468 + 48 149 101 250 Md 78399.140 90.920 7441.6533 0.3637 B- -3167# 220# 250 084164.934 97.606 + 46 148 102 250 No -a 81566# 200# 7426# 1# B- * 250 087565# 215# +0 59 155 96 251 Cm + 76647.981 22.698 7466.7233 0.0904 B- 1420.0000 20.0000 251 082284.988 24.367 + 57 154 97 251 Bk + 75227.981 10.734 7469.2637 0.0428 B- 1093.0000 10.0000 251 080760.555 11.523 + 55 153 98 251 Cf -a 74134.981 3.901 7470.5014 0.0155 B- -376.5660 6.4677 251 079587.171 4.187 + 53 152 99 251 Es -a 74511.547 5.288 7465.8842 0.0211 B- -1447.2610 15.2387 251 079991.431 5.676 + 51 151 100 251 Fm 75958.808 14.292 7457.0013 0.0569 B- -3007.9406 23.7108 251 081545.130 15.342 + 49 150 101 251 Md +a 78966.749 18.919 7441.9005 0.0754 B- -3882# 182# 251 084774.287 20.310 + 47 149 102 251 No IT 82849# 181# 7423# 1# B- -4981# 270# 251 088942# 194# + 45 148 103 251 Lr x 87830# 200# 7400# 1# B- * 251 094289# 215# +0 60 156 96 252 Cm x 79056# 298# 7460# 1# B- 521# 359# 252 084870# 320# + 58 155 97 252 Bk + 78535# 200# 7459# 1# B- 2500# 200# 252 084310# 215# + 56 154 98 252 Cf -a 76034.610 2.358 7465.3474 0.0094 B- -1260.0000 50.0000 252 081626.507 2.531 + 54 153 99 252 Es - 77294.610 50.056 7457.2428 0.1986 B- 477.9998 50.3220 252 082979.173 53.736 + 52 152 100 252 Fm -a 76816.611 5.221 7456.0351 0.0207 B- -3650.5075 91.4356 252 082466.019 5.604 + 50 151 101 252 Md x 80467.118 91.286 7438.4444 0.3622 B- -2404.2523 91.7581 252 086385.000 98.000 + 48 150 102 252 No 82871.370 9.292 7425.7992 0.0369 B- -5666# 185# 252 088966.070 9.975 + 46 149 103 252 Lr -a 88537# 185# 7400# 1# B- * 252 095048# 198# +0 59 156 97 253 Bk -a 80929# 359# 7451# 1# B- 1627# 359# 253 086880# 385# + 57 155 98 253 Cf -a 79301.562 4.257 7454.8297 0.0168 B- 291.0753 4.3850 253 085133.723 4.570 + 55 154 99 253 Es -a 79010.486 1.249 7452.8879 0.0049 B- -335.0623 1.0782 253 084821.241 1.341 + 53 153 100 253 Fm -a 79345.549 1.549 7448.4712 0.0061 B- -1827# 31# 253 085180.945 1.662 + 51 152 101 253 Md -a 81173# 31# 7438# 0# B- -3186# 32# 253 087143# 34# + 49 151 102 253 No 84358.696 6.912 7422.4719 0.0273 B- -4164.7752 164.6791 253 090562.780 7.420 + 47 150 103 253 Lr 88523.471 164.534 7402.9180 0.6503 B- -5118# 442# 253 095033.850 176.634 + 45 149 104 253 Rf -a 93642# 410# 7380# 2# B- * 253 100528# 440# +0 60 157 97 254 Bk x 84393# 298# 7440# 1# B- 3052# 298# 254 090600# 320# + 58 156 98 254 Cf -a 81341.395 11.462 7449.2259 0.0451 B- -652.7561 11.8014 254 087323.575 12.304 + 56 155 99 254 Es -a 81994.151 2.936 7443.5759 0.0116 B- 1091.6300 2.2858 254 088024.337 3.152 + 54 154 100 254 Fm -a 80902.521 1.843 7444.7936 0.0073 B- -2550# 100# 254 086852.424 1.978 + 52 153 101 254 Md - 83453# 100# 7432# 0# B- -1271# 100# 254 089590# 107# + 50 152 102 254 No 84723.312 9.658 7423.5909 0.0380 B- -4922.5753 91.8208 254 090954.211 10.367 + 48 151 103 254 Lr -a 89645.887 91.312 7401.1306 0.3595 B- -3555# 298# 254 096238.813 98.026 + 46 150 104 254 Rf -a 93201# 283# 7384# 1# B- * 254 100055# 304# +0 59 157 98 255 Cf + 84809# 200# 7438# 1# B- 720# 200# 255 091046# 215# + 57 156 99 255 Es -a 84089.237 10.817 7437.8216 0.0424 B- 288.7717 10.1024 255 090273.504 11.612 + 55 155 100 255 Fm -a 83800.465 3.934 7435.8860 0.0154 B- -1041.6037 6.7172 255 089963.495 4.223 + 53 154 101 255 Md -a 84842.069 5.567 7428.7333 0.0218 B- -1969.8648 15.1096 255 091081.702 5.976 + 51 153 102 255 No 86811.934 14.047 7417.9403 0.0551 B- -3135.3716 22.5952 255 093196.439 15.079 + 49 152 103 255 Lr x 89947.305 17.698 7402.5767 0.0694 B- -4382# 182# 255 096562.399 19.000 + 47 151 104 255 Rf -a 94329# 181# 7382# 1# B- -5265# 336# 255 101267# 194# + 45 150 105 255 Db -a 99595# 283# 7359# 1# B- * 255 106919# 304# +0 60 158 98 256 Cf -a 87041# 314# 7432# 1# B- -144# 330# 256 093442# 338# + 58 157 99 256 Es + 87185# 100# 7428# 0# B- 1700# 100# 256 093597# 107# + 56 156 100 256 Fm -a 85484.796 3.020 7431.7888 0.0118 B- -1971# 124# 256 091771.699 3.241 + 54 155 101 256 Md IT 87456# 124# 7421# 0# B- -367# 124# 256 093888# 133# + 52 154 102 256 No -a 87823.046 7.548 7416.5429 0.0295 B- -3923.5573 83.2459 256 094281.912 8.103 + 50 153 103 256 Lr x 91746.603 82.903 7398.1605 0.3238 B- -2475.3893 84.8025 256 098494.024 89.000 + 48 152 104 256 Rf -a 94221.992 17.848 7385.4349 0.0697 B- -6076# 188# 256 101151.464 19.160 + 46 151 105 256 Db -a 100298# 187# 7359# 1# B- * 256 107674# 201# +0 59 158 99 257 Es -a 89403# 411# 7422# 2# B- 813# 411# 257 095979# 441# + 57 157 100 257 Fm -a 88590.137 4.350 7422.1942 0.0169 B- -402.3347 4.5748 257 095105.419 4.669 + 55 156 101 257 Md -a 88992.472 1.569 7417.5845 0.0061 B- -1254.5923 6.1695 257 095537.343 1.683 + 53 155 102 257 No -a 90247.064 6.197 7409.6587 0.0241 B- -2418# 45# 257 096884.203 6.652 + 51 154 103 257 Lr -a 92665# 44# 7397# 0# B- -3201# 45# 257 099480# 47# + 49 153 104 257 Rf -a 95866.389 10.817 7381.7053 0.0421 B- -4287.8969 164.9888 257 102916.796 11.612 + 47 152 105 257 Db 100154.285 164.634 7361.9767 0.6406 B- * 257 107520.042 176.741 +0 60 159 99 258 Es x 92702# 401# 7412# 2# B- 2276# 448# 258 099520# 430# + 58 158 100 258 Fm -a 90426# 200# 7418# 1# B- -1264# 200# 258 097077# 215# + 56 157 101 258 Md -a 91690.350 3.474 7409.6615 0.0135 B- 213# 100# 258 098433.634 3.729 + 54 156 102 258 No -a 91477# 100# 7407# 0# B- -3304# 143# 258 098205# 107# + 52 155 103 258 Lr -a 94782# 102# 7392# 0# B- -1562# 103# 258 101753# 109# + 50 154 104 258 Rf -a 96344.338 16.104 7382.5257 0.0624 B- -5163.3651 93.2584 258 103429.895 17.288 + 48 153 105 258 Db -a 101507.703 91.857 7359.4803 0.3560 B- -3788# 423# 258 108972.995 98.613 + 46 152 106 258 Sg -a 105296# 413# 7342# 2# B- * 258 113040# 443# +0 59 159 100 259 Fm -a 93704# 283# 7407# 1# B- 140# 300# 259 100596# 304# + 57 158 101 259 Md -a 93564# 101# 7405# 0# B- -515# 101# 259 100445# 108# + 55 157 102 259 No -a 94079.381 6.362 7399.9714 0.0246 B- -1771# 71# 259 100998.364 6.829 + 53 156 103 259 Lr -a 95851# 71# 7390# 0# B- -2516# 101# 259 102900# 76# + 51 155 104 259 Rf -a 98367# 72# 7377# 0# B- -3624# 92# 259 105601# 78# + 49 154 105 259 Db -a 101991.021 56.685 7360.3626 0.2189 B- -4528# 190# 259 109491.859 60.854 + 47 153 106 259 Sg -a 106519# 181# 7340# 1# B- * 259 114353# 194# +0 60 160 100 260 Fm -a 95766# 435# 7402# 2# B- -784# 537# 260 102809# 467# + 58 159 101 260 Md -a 96550# 316# 7396# 1# B- 940# 374# 260 103650# 339# + 56 158 102 260 No -a 95610# 200# 7397# 1# B- -2667# 236# 260 102641# 215# + 54 157 103 260 Lr -a 98277# 125# 7383# 0# B- -871# 236# 260 105504# 134# + 52 156 104 260 Rf -a 99148# 200# 7377# 1# B- -4525# 221# 260 106440# 215# + 50 155 105 260 Db -a 103673# 93# 7357# 0# B- -2875# 95# 260 111297# 100# + 48 154 106 260 Sg -a 106547.495 20.536 7342.5632 0.0790 B- -6576# 197# 260 114383.435 22.045 + 46 153 107 260 Bh -a 113123# 196# 7314# 1# B- * 260 121443# 211# +0 59 160 101 261 Md -a 98578# 509# 7391# 2# B- 123# 547# 261 105828# 546# + 57 159 102 261 No -a 98455# 200# 7388# 1# B- -1102# 283# 261 105696# 215# + 55 158 103 261 Lr -a 99557# 200# 7381# 1# B- -1761# 211# 261 106879# 215# + 53 157 104 261 Rf -a 101318.233 65.663 7371.3858 0.2516 B- -2990# 128# 261 108769.591 70.492 + 51 156 105 261 Db -a 104308# 110# 7357# 0# B- -3697# 112# 261 111979# 118# + 49 155 106 261 Sg -a 108005.004 18.494 7339.7710 0.0709 B- -5074.4052 180.7519 261 115948.135 19.853 + 47 154 107 261 Bh -a 113079.410 179.803 7317.3313 0.6889 B- * 261 121395.733 193.026 +0 60 161 101 262 Md -a 101667# 448# 7382# 2# B- 1566# 575# 262 109144# 481# + 58 160 102 262 No -a 100101# 361# 7385# 1# B- -2004# 412# 262 107463# 387# + 56 159 103 262 Lr -a 102105# 200# 7374# 1# B- -287# 300# 262 109615# 215# + 54 158 104 262 Rf -a 102392# 224# 7370# 1# B- -3861# 265# 262 109923# 240# + 52 157 105 262 Db -a 106253# 143# 7352# 1# B- -2116# 145# 262 114067# 154# + 50 156 106 262 Sg -a 108369.072 22.167 7341.1736 0.0846 B- -5883.0463 95.6774 262 116338.978 23.797 + 48 155 107 262 Bh -a 114252.119 93.074 7315.7331 0.3552 B- * 262 122654.688 99.919 +0 59 161 102 263 No -a 103129# 490# 7376# 2# B- -540# 539# 263 110714# 526# + 57 160 103 263 Lr -a 103669# 224# 7371# 1# B- -1087# 271# 263 111293# 240# + 55 159 104 263 Rf -a 104757# 153# 7364# 1# B- -2353# 227# 263 112461# 164# + 53 158 105 263 Db -a 107110# 168# 7352# 1# B- -3085# 193# 263 114987# 180# + 51 157 106 263 Sg -a 110195# 95# 7337# 0# B- -4301# 320# 263 118299# 101# + 49 156 107 263 Bh -a 114496# 305# 7318# 1# B- -5182# 363# 263 122916# 328# + 47 155 108 263 Hs -a 119678# 197# 7295# 1# B- * 263 128479# 212# +0 60 162 102 264 No -a 105011# 591# 7371# 2# B- -1364# 734# 264 112734# 634# + 58 161 103 264 Lr -a 106375# 436# 7363# 2# B- 300# 566# 264 114198# 468# + 56 160 104 264 Rf -a 106075# 361# 7361# 1# B- -3187# 431# 264 113876# 387# + 54 159 105 264 Db -a 109262# 236# 7346# 1# B- -1521# 368# 264 117297# 253# + 52 158 106 264 Sg -a 110783# 283# 7338# 1# B- -5175# 334# 264 118930# 304# + 50 157 107 264 Bh -a 115958# 177# 7315# 1# B- -3605# 180# 264 124486# 190# + 48 156 108 264 Hs -a 119563.165 28.881 7298.3762 0.1094 B- * 264 128356.330 31.005 +0 59 162 103 265 Lr -a 108233# 547# 7359# 2# B- -457# 655# 265 116193# 587# + 57 161 104 265 Rf -a 108690# 361# 7354# 1# B- -1692# 424# 265 116683# 387# + 55 160 105 265 Db -a 110382# 224# 7345# 1# B- -2412# 263# 265 118500# 240# + 53 159 106 265 Sg -a 112794# 139# 7333# 1# B- -3601# 277# 265 121089# 149# + 51 158 107 265 Bh -a 116395# 239# 7316# 1# B- -4505# 240# 265 124955# 257# + 49 157 108 265 Hs -a 120900.245 23.958 7296.2474 0.0904 B- -5724# 439# 265 129791.744 25.719 + 47 156 109 265 Mt -a 126624# 439# 7272# 2# B- * 265 135937# 471# +0 60 163 103 266 Lr -a 111662# 539# 7349# 2# B- 1526# 679# 266 119874# 579# + 58 162 104 266 Rf -a 110136# 412# 7351# 2# B- -2604# 500# 266 118236# 443# + 56 161 105 266 Db -a 112740# 283# 7339# 1# B- -877# 374# 266 121032# 304# + 54 160 106 266 Sg -a 113617# 245# 7332# 1# B- -4487# 294# 266 121973# 263# + 52 159 107 266 Bh -a 118104# 163# 7313# 1# B- -3036# 165# 266 126790# 175# + 50 158 108 266 Hs -a 121139.675 27.106 7298.2611 0.1019 B- -6533.0066 100.2087 266 130048.783 29.099 + 48 157 109 266 Mt -a 127672.681 96.473 7270.7598 0.3627 B- * 266 137062.253 103.568 +0 59 163 104 267 Rf -a 113444# 575# 7342# 2# B- -570# 686# 267 121787# 617# + 57 162 105 267 Db -a 114014# 374# 7337# 1# B- -1792# 457# 267 122399# 402# + 55 161 106 267 Sg -a 115806# 261# 7327# 1# B- -2958# 371# 267 124323# 281# + 53 160 107 267 Bh -a 118765# 263# 7313# 1# B- -3893# 279# 267 127499# 282# + 51 159 108 267 Hs -a 122658# 95# 7295# 0# B- -5133# 512# 267 131678# 102# + 49 158 109 267 Mt -a 127791# 503# 7273# 2# B- -6089# 543# 267 137189# 540# + 47 157 110 267 Ds -a 133880# 204# 7248# 1# B- * 267 143726# 219# +0 60 164 104 268 Rf -a 115476# 662# 7337# 2# B- -1584# 848# 268 123968# 711# + 58 163 105 268 Db -a 117060# 529# 7328# 2# B- 260# 707# 268 125669# 568# + 56 162 106 268 Sg -a 116800# 469# 7326# 2# B- -3907# 605# 268 125389# 504# + 54 161 107 268 Bh -a 120707# 382# 7309# 1# B- -2261# 486# 268 129584# 410# + 52 160 108 268 Hs -a 122968# 300# 7297# 1# B- -6183# 380# 268 132011# 322# + 50 159 109 268 Mt -a 129151# 233# 7271# 1# B- -4497# 381# 268 138649# 250# + 48 158 110 268 Ds -a 133648# 301# 7252# 1# B- * 268 143477# 324# +0 59 164 105 269 Db -a 119148# 624# 7323# 2# B- -544# 724# 269 127911# 669# + 57 163 106 269 Sg -a 119692# 368# 7318# 1# B- -1785# 525# 269 128495# 395# + 55 162 107 269 Bh -a 121477# 374# 7309# 1# B- -3016# 396# 269 130411# 402# + 53 161 108 269 Hs -a 124493# 131# 7294# 0# B- -4807# 338# 269 133649# 141# + 51 160 109 269 Mt -a 129300# 312# 7274# 1# B- -5535# 313# 269 138809# 335# + 49 159 110 269 Ds -a 134834.671 31.403 7250.1551 0.1167 B- * 269 144750.965 33.712 +0 60 165 105 270 Db -a 122397# 575# 7314# 2# B- 966# 735# 270 131399# 617# + 58 164 106 270 Sg -a 121431# 458# 7314# 2# B- -2799# 547# 270 130362# 492# + 56 163 107 270 Bh -a 124230# 299# 7301# 1# B- -882# 388# 270 133366# 320# + 54 162 108 270 Hs -a 125112# 248# 7295# 1# B- -5597# 313# 270 134313# 266# + 52 161 109 270 Mt -a 130709# 191# 7271# 1# B- -3973# 195# 270 140322# 205# + 50 160 110 270 Ds -a 134681.584 39.275 7253.7634 0.1455 B- * 270 144586.620 42.163 +0 59 165 106 271 Sg -a 124617# 591# 7305# 2# B- -1242# 705# 271 133782# 634# + 57 164 107 271 Bh -a 125859# 384# 7298# 1# B- -1832# 473# 271 135115# 412# + 55 163 108 271 Hs -a 127691# 276# 7288# 1# B- -3409# 430# 271 137082# 296# + 53 162 109 271 Mt -a 131100# 330# 7273# 1# B- -4853# 344# 271 140741# 354# + 51 161 110 271 Ds -a 135952# 97# 7252# 0# B- * 271 145951# 104# +0 60 166 106 272 Sg -a 126520# 692# 7301# 3# B- -2267# 873# 272 135825# 743# + 58 165 107 272 Bh -a 128787# 532# 7290# 2# B- -217# 737# 272 138259# 571# + 56 164 108 272 Hs -a 129004# 510# 7286# 2# B- -4477# 704# 272 138492# 547# + 54 163 109 272 Mt -a 133481# 485# 7267# 2# B- -2601# 645# 272 143298# 521# + 52 162 110 272 Ds -a 136083# 424# 7255# 2# B- -6690# 484# 272 146091# 456# + 50 161 111 272 Rg -a 142773# 233# 7227# 1# B- * 272 153273# 251# +0 61 167 106 273 Sg x 129920# 400# 7292# 1# B- -763# 767# 273 139475# 429# + 59 166 107 273 Bh -a 130683# 655# 7286# 2# B- -1084# 754# 273 140294# 703# + 57 165 108 273 Hs -a 131767# 374# 7279# 1# B- -3015# 565# 273 141458# 401# + 55 164 109 273 Mt -a 134782# 424# 7265# 2# B- -3503# 447# 273 144695# 455# + 53 163 110 273 Ds -a 138285# 142# 7250# 1# B- -4600# 424# 273 148455# 152# + 51 162 111 273 Rg -a 142885# 400# 7230# 1# B- * 273 153393# 429# +0 60 167 107 274 Bh -a 133762# 578# 7278# 2# B- 356# 744# 274 143599# 620# + 58 166 108 274 Hs -a 133406# 469# 7276# 2# B- -3843# 602# 274 143217# 504# + 56 165 109 274 Mt -a 137249# 377# 7259# 1# B- -1948# 542# 274 147343# 404# + 54 164 110 274 Ds -a 139197# 389# 7249# 1# B- -5415# 442# 274 149434# 418# + 52 163 111 274 Rg -a 144612# 209# 7227# 1# B- * 274 155247# 225# +0 61 168 107 275 Bh x 135780# 600# 7273# 2# B- -712# 844# 275 145766# 644# + 59 167 108 275 Hs -a 136492# 593# 7268# 2# B- -2275# 709# 275 146530# 637# + 57 166 109 275 Mt -a 138767# 387# 7257# 1# B- -2899# 516# 275 148972# 416# + 55 165 110 275 Ds -a 141666# 340# 7243# 1# B- -3729# 561# 275 152085# 366# + 53 164 111 275 Rg -a 145395# 446# 7227# 2# B- * 275 156088# 479# +0 62 169 107 276 Bh x 138950# 600# 7265# 2# B- 765# 937# 276 149169# 644# + 60 168 108 276 Hs -a 138185# 720# 7265# 3# B- -3127# 895# 276 148348# 773# + 58 167 109 276 Mt -a 141312# 532# 7250# 2# B- -1227# 764# 276 151705# 571# + 56 166 110 276 Ds -a 142539# 548# 7243# 2# B- -4847# 834# 276 153022# 588# + 54 165 111 276 Rg -a 147386# 629# 7223# 2# B- -2974# 804# 276 158226# 675# + 52 164 112 276 Cn x 150360# 500# 7209# 2# B- * 276 161418# 537# +0 63 170 107 277 Bh x 141100# 600# 7260# 2# B- -275# 748# 277 151477# 644# + 61 169 108 277 Hs -a 141375# 447# 7256# 2# B- -1633# 799# 277 151772# 480# + 59 168 109 277 Mt -a 143008# 662# 7247# 2# B- -2084# 770# 277 153525# 711# + 57 167 110 277 Ds -a 145092# 392# 7237# 1# B- -3315# 611# 277 155763# 421# + 55 166 111 277 Rg -a 148407# 469# 7222# 2# B- -3925# 493# 277 159322# 504# + 53 165 112 277 Cn -a 152332# 153# 7205# 1# B- * 277 163535# 165# +0 64 171 107 278 Bh x 144370# 400# 7251# 1# B- 1150# 500# 278 154988# 429# + 62 170 108 278 Hs x 143220# 300# 7252# 1# B- -2547# 652# 278 153753# 322# + 60 169 109 278 Mt -a 145767# 579# 7240# 2# B- -484# 771# 278 156487# 621# + 58 168 110 278 Ds -a 146251# 510# 7236# 2# B- -4270# 641# 278 157007# 548# + 56 167 111 278 Rg -a 150521# 389# 7218# 1# B- -2321# 585# 278 161590# 417# + 54 166 112 278 Cn -a 152842# 438# 7206# 2# B- -6188# 491# 278 164083# 470# + 52 165 113 278 Nh -a 159030# 224# 7181# 1# B- * 278 170725# 240# +0 63 171 108 279 Hs x 146500# 600# 7243# 2# B- -1085# 900# 279 157274# 644# + 61 170 109 279 Mt -a 147585# 671# 7237# 2# B- -1439# 903# 279 158439# 720# + 59 169 110 279 Ds -a 149024# 605# 7229# 2# B- -2697# 737# 279 159984# 649# + 57 168 111 279 Rg -a 151721# 422# 7216# 2# B- -3299# 578# 279 162880# 453# + 55 167 112 279 Cn -a 155021# 395# 7202# 1# B- -4439# 718# 279 166422# 424# + 53 166 113 279 Nh x 159460# 600# 7183# 2# B- * 279 171187# 644# +0 64 172 108 280 Hs x 148420# 600# 7239# 2# B- -2090# 848# 280 159335# 644# + 62 171 109 280 Mt x 150510# 600# 7229# 2# B- 190# 958# 280 161579# 644# + 60 170 110 280 Ds -a 150320# 748# 7227# 3# B- -3566# 918# 280 161375# 803# + 58 169 111 280 Rg -a 153886# 532# 7212# 2# B- -1768# 789# 280 165204# 571# + 56 168 112 280 Cn -a 155654# 583# 7202# 2# B- -5585# 707# 280 167102# 626# + 54 167 113 280 Nh x 161240# 400# 7180# 1# B- * 280 173098# 429# +0 63 172 109 281 Mt x 152400# 600# 7225# 2# B- -873# 776# 281 163608# 644# + 61 171 110 281 Ds -a 153273# 493# 7220# 2# B- -2060# 918# 281 164545# 529# + 59 170 111 281 Rg -a 155333# 774# 7209# 3# B- -2614# 870# 281 166757# 831# + 57 169 112 281 Cn -a 157947# 397# 7197# 1# B- -3863# 498# 281 169563# 427# + 55 168 113 281 Nh x 161810# 300# 7181# 1# B- * 281 173710# 322# +0 64 173 109 282 Mt -a 155455# 447# 7218# 2# B- 665# 538# 282 166888# 480# + 62 172 110 282 Ds x 154790# 300# 7217# 1# B- -2952# 660# 282 166174# 322# + 60 171 111 282 Rg -a 157742# 588# 7204# 2# B- -1084# 804# 282 169343# 631# + 58 170 112 282 Cn -a 158826# 548# 7197# 2# B- -4903# 678# 282 170507# 588# + 56 169 113 282 Nh -a 163729# 400# 7177# 1# B- * 282 175770# 430# +0 63 173 110 283 Ds x 157830# 500# 7210# 2# B- -1550# 843# 283 169437# 537# + 61 172 111 283 Rg -a 159380# 678# 7201# 2# B- -1957# 916# 283 171101# 728# + 59 171 112 283 Cn -a 161337# 615# 7192# 2# B- -3226# 754# 283 173202# 660# + 57 170 113 283 Nh -a 164563# 437# 7177# 2# B- * 283 176666# 469# +0 64 174 110 284 Ds x 159460# 500# 7207# 2# B- -2510# 707# 284 171187# 537# + 62 173 111 284 Rg x 161970# 500# 7195# 2# B- -445# 912# 284 173882# 537# + 60 172 112 284 Cn -a 162415# 762# 7191# 3# B- -4176# 931# 284 174360# 819# + 58 171 113 284 Nh -a 166591# 533# 7173# 2# B- -2188# 845# 284 178843# 573# + 56 170 114 284 Fl -a 168779# 656# 7163# 2# B- * 284 181192# 704# +0 63 174 111 285 Rg x 163730# 600# 7192# 2# B- -1357# 785# 285 175771# 644# + 61 173 112 285 Cn -a 165086# 507# 7185# 2# B- -2682# 926# 285 177227# 544# + 59 172 113 285 Nh -a 167768# 775# 7172# 3# B- -3164# 874# 285 180106# 832# + 57 171 114 285 Fl -a 170932# 404# 7159# 1# B- * 285 183503# 433# +0 64 175 111 286 Rg -a 166510# 458# 7185# 2# B- 61# 836# 286 178756# 492# + 62 174 112 286 Cn x 166450# 700# 7183# 2# B- -3507# 915# 286 178691# 751# + 60 173 113 286 Nh -a 169957# 590# 7168# 2# B- -1649# 806# 286 182456# 634# + 58 172 114 286 Fl -a 171606# 549# 7159# 2# B- * 286 184226# 590# +0 63 175 112 287 Cn x 169370# 700# 7176# 2# B- -2085# 995# 287 181826# 751# + 61 174 113 287 Nh -a 171455# 707# 7166# 2# B- -2474# 939# 287 184064# 759# + 59 173 114 287 Fl -a 173929# 617# 7155# 2# B- -3819# 759# 287 186720# 663# + 57 172 115 287 Mc -a 177748# 443# 7139# 2# B- * 287 190820# 475# +0 64 176 112 288 Cn x 170930# 700# 7174# 2# B- -3039# 989# 288 183501# 751# + 62 175 113 288 Nh x 173970# 700# 7160# 2# B- -947# 1035# 288 186764# 751# + 60 174 114 288 Fl -a 174917# 763# 7154# 3# B- -4749# 932# 288 187781# 819# + 58 173 115 288 Mc -a 179666# 536# 7135# 2# B- * 288 192879# 575# +0 63 176 113 289 Nh x 175550# 500# 7158# 2# B- -1915# 715# 289 188461# 537# + 61 175 114 289 Fl -a 177465# 511# 7149# 2# B- -3217# 929# 289 190517# 548# + 59 174 115 289 Mc -a 180683# 776# 7135# 3# B- -3774# 925# 289 193971# 834# + 57 173 116 289 Lv -a 184457# 503# 7119# 2# B- * 289 198023# 540# +0 64 177 113 290 Nh -a 178315# 469# 7152# 2# B- -416# 843# 290 191429# 503# + 62 176 114 290 Fl -a 178731# 700# 7147# 2# B- -4061# 917# 290 191875# 752# + 60 175 115 290 Mc -a 182792# 592# 7131# 2# B- -2236# 809# 290 196235# 635# + 58 174 116 290 Lv -a 185028# 552# 7120# 2# B- * 290 198635# 593# +0 63 177 114 291 Fl x 181500# 700# 7141# 2# B- -2680# 1015# 291 194848# 751# + 61 176 115 291 Mc -a 184180# 735# 7129# 3# B- -3064# 964# 291 197725# 789# + 59 175 116 291 Lv -a 187244# 623# 7116# 2# B- -4409# 863# 291 201014# 669# + 57 174 117 291 Ts -a 191653# 597# 7098# 2# B- * 291 205748# 640# +0 62 177 115 292 Mc x 186600# 700# 7124# 2# B- -1533# 1035# 292 200323# 751# + 60 176 116 292 Lv -a 188133# 763# 7116# 3# B- -5488# 1014# 292 201969# 819# + 58 175 117 292 Ts -a 193621# 669# 7095# 2# B- * 292 207861# 718# +0 61 177 116 293 Lv -a 190568# 515# 7111# 2# B- -3860# 933# 293 204583# 553# + 59 176 117 293 Ts -a 194428# 778# 7095# 3# B- -4374# 1053# 293 208727# 835# + 57 175 118 293 Og -a 198802# 709# 7078# 2# B- * 293 213423# 761# +0 60 177 117 294 Ts -a 196397# 593# 7092# 2# B- -2923# 811# 294 210840# 637# + 58 176 118 294 Og -a 199320# 553# 7079# 2# B- * 294 213979# 594# +0 59 177 118 295 Og -a 201369# 655# 7076# 2# B- * 295 216178# 703# diff --git a/setup.py b/setup.py index e11c50d56..a9e863da2 100755 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ kwargs = { # Data files and libraries 'package_data': { 'openmc.lib': ['libopenmc.{}'.format(suffix)], - 'openmc.data': ['mass16.txt', 'BREMX.DAT', 'half_life.json', '*.h5'], + 'openmc.data': ['mass_1.mas20.txt', 'BREMX.DAT', 'half_life.json', '*.h5'], 'openmc.data.effective_dose': ['*.txt'] }, From f5f42a4c80536ee39c154a518fad0acc375d3956 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 26 Oct 2022 13:37:09 -0400 Subject: [PATCH 1212/2654] Update openmc/geometry.py Co-authored-by: Patrick Shriwise --- openmc/geometry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 08608a5cd..379a2bb4e 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -448,16 +448,16 @@ class Geometry: """ # check if redundant surfaces have not been calculated yet if self._redundant_surface_map is None: - tally = defaultdict(list) + redundancies = defaultdict(list) for surf in self.get_all_surfaces().values(): coeffs = tuple(round(surf._coefficients[k], self.surface_precision) for k in surf._coeff_keys) key = (surf._type,) + coeffs - tally[key].append(surf) + redundancies[key].append(surf) self._redundant_surface_map = {replace.id: keep - for keep, *redundant in tally.values() + for keep, *redundant in redundancies.values() for replace in redundant} return self._redundant_surface_map From 5d177a5ace4e640a76f5941b76468f3c604e938c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 26 Oct 2022 20:21:06 +0100 Subject: [PATCH 1213/2654] Apply suggestions from code review by @paulromano Co-authored-by: Paul Romano --- openmc/source.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/source.py b/openmc/source.py index 05954da77..7be7b838a 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -364,8 +364,8 @@ class SourceParticle: """ def __init__( self, - r: Tuple[float, float, float] = (0., 0., 0.), - u: Tuple[float, float, float] = (0., 0., 1.), + r: typing.Iterable[float] = (0., 0., 0.), + u: typing.Iterable[float] = (0., 0., 1.), E: float = 1.0e6, time: float = 0.0, wgt: float = 1.0, @@ -401,7 +401,7 @@ class SourceParticle: def write_source_file( - source_particles: 'typing.Iterable[openmc.SourceParticle]', + source_particles: typing.Iterable[SourceParticle], filename: PathLike, **kwargs ): """Write a source file using a collection of source particles From 84b055e15bf1bc08697129f154f33a55e4252086 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 26 Oct 2022 20:24:23 +0100 Subject: [PATCH 1214/2654] reordered imports to avoid circular imports --- openmc/__init__.py | 4 ++-- openmc/source.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/__init__.py b/openmc/__init__.py index ca21bf17b..9615024f2 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -10,11 +10,11 @@ from openmc.material import * from openmc.plots import * from openmc.region import * from openmc.volume import * -from openmc.source import * from openmc.weight_windows import * -from openmc.settings import * from openmc.surface import * from openmc.universe import * +from openmc.source import * +from openmc.settings import * from openmc.lattice import * from openmc.filter import * from openmc.filter_expansion import * diff --git a/openmc/source.py b/openmc/source.py index 7be7b838a..fd5b737e5 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -84,7 +84,7 @@ class Source: parameters: Optional[str] = None, strength: float = 1.0, particle: str = 'neutron', - domains: Optional[Union[openmc.Cell, openmc.Material, 'openmc.Universe']] = None + domains: Optional[Union[openmc.Cell, openmc.Material, openmc.Universe]] = None ): self._space = None self._angle = None @@ -257,7 +257,7 @@ class Source: return element @classmethod - def from_xml_element(cls, elem: ET.Element) -> 'openmc.Source': + def from_xml_element(cls, elem: ET.Element) -> openmc.Source: """Generate source from an XML element Parameters From 2af754baa9982585b3dc860be081e00b30d57c36 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 26 Oct 2022 20:32:44 +0100 Subject: [PATCH 1215/2654] forward ref for openmc.source --- openmc/source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/source.py b/openmc/source.py index fd5b737e5..ee5cc4875 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -257,7 +257,7 @@ class Source: return element @classmethod - def from_xml_element(cls, elem: ET.Element) -> openmc.Source: + def from_xml_element(cls, elem: ET.Element) -> 'openmc.Source': """Generate source from an XML element Parameters From 9ff159a4db2b2a72861f45aa96358cce425c72dd Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 26 Oct 2022 21:08:12 +0100 Subject: [PATCH 1216/2654] updated to new AME format --- openmc/data/data.py | 12 ++++++------ tests/unit_tests/test_data_misc.py | 10 ++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 361aa6457..fcdafede7 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -223,19 +223,19 @@ def atomic_mass(isotope): """ if not _ATOMIC_MASS: - # Load data from AME2016 file + # Load data from AME2020 file, Note format change to AME2016 mass_file = os.path.join(os.path.dirname(__file__), 'mass_1.mas20.txt') with open(mass_file, 'r') as ame: - # Read lines in file starting at line 40 - for line in itertools.islice(ame, 39, None): + # Read lines in file starting at line 37 + for line in itertools.islice(ame, 36, None): name = f'{line[20:22].strip()}{int(line[16:19])}' - mass = float(line[96:99]) + 1e-6*float( - line[100:106] + '.' + line[107:112]) + mass = float(line[106:109]) + 1e-6*float( + line[110:116] + '.' + line[117:123]) _ATOMIC_MASS[name.lower()] = mass # For isotopes found in some libraries that represent all natural # isotopes of their element (e.g. C0), calculate the atomic mass as - # the sum of the atomic mass times the natural abudance of the isotopes + # the sum of the atomic mass times the natural abundance of the isotopes # that make up the element. for element in ['C', 'Zn', 'Pt', 'Os', 'Tl']: isotope_zero = element.lower() + '0' diff --git a/tests/unit_tests/test_data_misc.py b/tests/unit_tests/test_data_misc.py index c3f7e3cff..37e024fe2 100644 --- a/tests/unit_tests/test_data_misc.py +++ b/tests/unit_tests/test_data_misc.py @@ -76,15 +76,17 @@ def test_thin(): def test_atomic_mass(): - assert openmc.data.atomic_mass('H1') == 1.00782503224 - assert openmc.data.atomic_mass('U235') == 235.04392819 + assert openmc.data.atomic_mass('H1') == 1.007825031898 + assert openmc.data.atomic_mass('U235') == 235.043928117 + assert openmc.data.atomic_mass('Li6') == 6.01512288742 + assert openmc.data.atomic_mass('Pb220') == 220.025905 with pytest.raises(KeyError): openmc.data.atomic_mass('U100') def test_atomic_weight(): - assert openmc.data.atomic_weight('C') == 12.011115164864455 - assert openmc.data.atomic_weight('carbon') == 12.011115164864455 + assert openmc.data.atomic_weight('C') == 12.011115164865895 + assert openmc.data.atomic_weight('carbon') == 12.011115164865895 with pytest.raises(ValueError): openmc.data.atomic_weight('Qt') From df9f7ec8147e41e05960efc996a846c872c087a3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 27 Oct 2022 08:51:32 -0500 Subject: [PATCH 1217/2654] Make sure Chain.reduce preserves information in the .sources attribute --- openmc/deplete/chain.py | 1 + tests/unit_tests/test_deplete_chain.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index ce376a181..33ac8a342 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -1025,6 +1025,7 @@ class Chain: new_nuclide = Nuclide(previous.name) new_nuclide.half_life = previous.half_life new_nuclide.decay_energy = previous.decay_energy + new_nuclide.sources = previous.sources.copy() if hasattr(previous, '_fpy'): new_nuclide._fpy = previous._fpy diff --git a/tests/unit_tests/test_deplete_chain.py b/tests/unit_tests/test_deplete_chain.py index 32c3e2809..e4e023135 100644 --- a/tests/unit_tests/test_deplete_chain.py +++ b/tests/unit_tests/test_deplete_chain.py @@ -500,6 +500,7 @@ def test_reduce(gnd_simple_chain, endf_chain): assert u5_round0.n_decay_modes == ref_U5.n_decay_modes assert u5_round0.half_life == ref_U5.half_life assert u5_round0.decay_energy == ref_U5.decay_energy + assert u5_round0.sources == ref_U5.sources for newmode, refmode in zip(u5_round0.decay_modes, ref_U5.decay_modes): assert newmode.target is None assert newmode.type == refmode.type @@ -522,6 +523,7 @@ def test_reduce(gnd_simple_chain, endf_chain): assert bareI5.n_decay_modes == ref_iodine.n_decay_modes assert bareI5.half_life == ref_iodine.half_life assert bareI5.decay_energy == ref_iodine.decay_energy + assert bareI5.sources == ref_iodine.sources for newmode, refmode in zip(bareI5.decay_modes, ref_iodine.decay_modes): assert newmode.target is None assert newmode.type == refmode.type From 459b0f1fcf0c864fcb1c3037df831c97c15bdd65 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 27 Oct 2022 16:17:49 +0100 Subject: [PATCH 1218/2654] avoid union namespace overwrite --- openmc/source.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/source.py b/openmc/source.py index ee5cc4875..a5907344e 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -3,7 +3,7 @@ from enum import Enum from numbers import Real import warnings import typing # imported separately as py3.8 requires typing.Iterable -from typing import Optional, Union, Tuple +from typing import Optional from xml.etree import ElementTree as ET import numpy as np @@ -84,7 +84,7 @@ class Source: parameters: Optional[str] = None, strength: float = 1.0, particle: str = 'neutron', - domains: Optional[Union[openmc.Cell, openmc.Material, openmc.Universe]] = None + domains: Optional[typing.Union[openmc.Cell, openmc.Material, openmc.Universe]] = None ): self._space = None self._angle = None From 3623408bc54baad55d8429a178dd408fc89e1115 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 27 Oct 2022 17:38:27 +0100 Subject: [PATCH 1219/2654] avoid namespace overwrite of union --- openmc/checkvalue.py | 4 ++-- openmc/deplete/results.py | 7 ++++--- openmc/material.py | 4 ++-- openmc/settings.py | 9 +++++---- openmc/source.py | 1 + 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/openmc/checkvalue.py b/openmc/checkvalue.py index c5d80b2fc..840306486 100644 --- a/openmc/checkvalue.py +++ b/openmc/checkvalue.py @@ -1,12 +1,12 @@ import copy import os -from typing import Union +import typing # required to prevent typing.Union namespace overwriting Union from collections.abc import Iterable import numpy as np # Type for arguments that accept file paths -PathLike = Union[str, os.PathLike] +PathLike = typing.Union[str, os.PathLike] def check_type(name, value, expected_type, expected_iter_type=None, *, none_ok=False): diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index d9aa52b79..9552a6ba6 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -1,7 +1,8 @@ import numbers import bisect import math -from typing import Iterable, Optional, Tuple, Union +import typing # required to prevent typing.Union namespace overwriting Union +from typing import Iterable, Optional, Tuple from warnings import warn import h5py @@ -95,7 +96,7 @@ class Results(list): def get_atoms( self, - mat: Union[Material, str], + mat: typing.Union[Material, str], nuc: str, nuc_units: str = "atoms", time_units: str = "s" @@ -165,7 +166,7 @@ class Results(list): def get_reaction_rate( self, - mat: Union[Material, str], + mat: typing.Union[Material, str], nuc: str, rx: str ) -> Tuple[np.ndarray, np.ndarray]: diff --git a/openmc/material.py b/openmc/material.py index 1979b3958..10ade8bfe 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -6,7 +6,7 @@ from pathlib import Path import re import typing # imported separately as py3.8 requires typing.Iterable import warnings -from typing import Optional, Union +from typing import Optional from xml.etree import ElementTree as ET import h5py @@ -968,7 +968,7 @@ class Material(IDManagerMixin): Returns ------- - Union[dict, float] + typing.Union[dict, float] If by_nuclide is True then a dictionary whose keys are nuclide names and values are activity is returned. Otherwise the activity of the material is returned as a float. diff --git a/openmc/settings.py b/openmc/settings.py index ad5a9b28a..45658f812 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -6,7 +6,8 @@ import itertools from math import ceil from numbers import Integral, Real from pathlib import Path -from typing import Optional, Union +import typing # required to prevent typing.Union namespace overwriting Union +from typing import Optional from xml.etree import ElementTree as ET import openmc.checkvalue as cv @@ -582,7 +583,7 @@ class Settings: self._max_order = max_order @source.setter - def source(self, source: Union[Source, typing.Iterable[Source]]): + def source(self, source: typing.Union[Source, typing.Iterable[Source]]): if not isinstance(source, MutableSequence): source = [source] self._source = cv.CheckedList(Source, 'source distributions', source) @@ -843,7 +844,7 @@ class Settings: @volume_calculations.setter def volume_calculations( - self, vol_calcs: Union[VolumeCalculation, typing.Iterable[VolumeCalculation]] + self, vol_calcs: typing.Union[VolumeCalculation, typing.Iterable[VolumeCalculation]] ): if not isinstance(vol_calcs, MutableSequence): vol_calcs = [vol_calcs] @@ -889,7 +890,7 @@ class Settings: self._write_initial_source = value @weight_windows.setter - def weight_windows(self, value: Union[WeightWindows, typing.Iterable[WeightWindows]]): + def weight_windows(self, value: typing.Union[WeightWindows, typing.Iterable[WeightWindows]]): if not isinstance(value, MutableSequence): value = [value] self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows', value) diff --git a/openmc/source.py b/openmc/source.py index a5907344e..d886e9891 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -3,6 +3,7 @@ from enum import Enum from numbers import Real import warnings import typing # imported separately as py3.8 requires typing.Iterable +# also required to prevent typing.Union namespace overwriting Union from typing import Optional from xml.etree import ElementTree as ET From 5c589b7a6cd86d34d5eaef63e53abb63646f4092 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 27 Oct 2022 11:11:56 -0500 Subject: [PATCH 1220/2654] Adding __eq__ method and roundtrip test for wws --- openmc/weight_windows.py | 31 ++++++++- tests/unit_tests/weightwindows/test.py | 92 ++++++++++++++++---------- 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 3a9bfff6d..5b43331c0 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -159,6 +159,35 @@ class WeightWindows(IDManagerMixin): string += '{: <16}=\t{}\n'.format('\tWeight Cutoff', self._weight_cutoff) return string + def __eq__(self, other): + # ensure that `other` is a WeightWindows object + if not isinstance(other, WeightWindows): + return False + + # TODO: add ability to check mesh equality + + # check a few more attributes directly + attrs = ('particle_type', + 'survival_ratio', + 'max_lower_bound_ratio', + 'max_split', + 'weight_cutoff') + for attr in attrs: + if getattr(self, attr) != getattr(other, attr): + return False + + # save most expensive checks for last + if not np.array_equal(self.energy_bounds, other.energy_bounds): + return False + + if not np.array_equal(self.lower_ww_bounds, other.lower_ww_bounds): + return False + + if not np.array_equal(self.upper_ww_bounds, other.upper_ww_bounds): + return False + + return True + @property def mesh(self): return self._mesh @@ -341,7 +370,7 @@ class WeightWindows(IDManagerMixin): particle_type = get_text(elem, 'particle_type') survival_ratio = float(get_text(elem, 'survival_ratio')) - ww_shape = (len(e_bounds) - 1,) + mesh.dimension[::-1] + ww_shape = (len(e_bounds) - 1,) + tuple(mesh.dimension[::-1]) lower_ww_bounds = np.array(lower_ww_bounds).reshape(ww_shape).T upper_ww_bounds = np.array(upper_ww_bounds).reshape(ww_shape).T diff --git a/tests/unit_tests/weightwindows/test.py b/tests/unit_tests/weightwindows/test.py index 51e2fdc62..18a738561 100644 --- a/tests/unit_tests/weightwindows/test.py +++ b/tests/unit_tests/weightwindows/test.py @@ -10,6 +10,45 @@ from openmc.stats import Discrete, Point from tests import cdtemp + +@pytest.fixture +def wws(): + + # weight windows + + # load pre-generated weight windows + # (created using the same tally as above) + ww_n_lower_bnds = np.loadtxt('ww_n.txt') + ww_p_lower_bnds = np.loadtxt('ww_p.txt') + + # create a mesh matching the one used + # to generate the weight windows + ww_mesh = openmc.RegularMesh() + ww_mesh.lower_left = (-240, -240, -240) + ww_mesh.upper_right = (240, 240, 240) + ww_mesh.dimension = (5, 6, 7) + + # energy bounds matching those of the + # generated weight windows + e_bnds = [0.0, 0.5, 2E7] + + ww_n = openmc.WeightWindows(ww_mesh, + ww_n_lower_bnds, + None, + 10.0, + e_bnds, + survival_ratio=1.01) + + ww_p = openmc.WeightWindows(ww_mesh, + ww_p_lower_bnds, + None, + 10.0, + e_bnds, + survival_ratio=1.01) + + return [ww_n, ww_p] + + @pytest.fixture def model(): openmc.reset_auto_ids() @@ -80,7 +119,7 @@ def model(): return model -def test_weightwindows(model): +def test_weightwindows(model, wws): ww_files = ('ww_n.txt', 'ww_p.txt') cwd = Path(__file__).parent.absolute() @@ -92,39 +131,7 @@ def test_weightwindows(model): analog_sp = model.run() os.rename(analog_sp, 'statepoint.analog.h5') - # weight windows - - # load pre-generated weight windows - # (created using the same tally as above) - ww_n_lower_bnds = np.loadtxt('ww_n.txt') - ww_p_lower_bnds = np.loadtxt('ww_p.txt') - - # create a mesh matching the one used - # to generate the weight windows - ww_mesh = openmc.RegularMesh() - ww_mesh.lower_left = (-240, -240, -240) - ww_mesh.upper_right = (240, 240, 240) - ww_mesh.dimension = (5, 6, 7) - - # energy bounds matching those of the - # generated weight windows - e_bnds = [0.0, 0.5, 2E7] - - ww_n = openmc.WeightWindows(ww_mesh, - ww_n_lower_bnds, - None, - 10.0, - e_bnds, - survival_ratio=1.01) - - ww_p = openmc.WeightWindows(ww_mesh, - ww_p_lower_bnds, - None, - 10.0, - e_bnds, - survival_ratio=1.01) - - model.settings.weight_windows = [ww_n, ww_p] + model.settings.weight_windows = wws # check that string form of the class can be created for ww in model.settings.weight_windows: @@ -211,3 +218,20 @@ def test_lower_ww_bounds_shape(): energy_bounds=(1, 1e40) ) assert ww.lower_ww_bounds.shape == (2, 3, 4, 1) + + +def test_roundtrip(model, wws): + model.settings.weight_windows = wws + + # write the model with weight windows to XML + model.export_to_xml() + + # ensure that they can be read successfully from XML and that they match the input values + model_read = openmc.Model.from_xml() + + zipped_wws = zip(model.settings.weight_windows, + model_read.settings.weight_windows) + + # ensure the lower bounds read in from the XML match those of the + for ww_out, ww_in in zipped_wws: + assert(ww_out == ww_in) From 53ec17eb77877c02579ef768c7556410a118129f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 27 Oct 2022 11:41:12 -0500 Subject: [PATCH 1221/2654] fix comment --- openmc/weight_windows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 5b43331c0..44de64041 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -166,7 +166,7 @@ class WeightWindows(IDManagerMixin): # TODO: add ability to check mesh equality - # check a few more attributes directly + # check several attributes directly attrs = ('particle_type', 'survival_ratio', 'max_lower_bound_ratio', From 80563f1b8cf01f8cb74c5607d08ed47268c1e1b7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 27 Oct 2022 14:43:14 -0500 Subject: [PATCH 1222/2654] Absolute file paths on system --- tests/unit_tests/weightwindows/test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/weightwindows/test.py b/tests/unit_tests/weightwindows/test.py index 18a738561..d73a52f45 100644 --- a/tests/unit_tests/weightwindows/test.py +++ b/tests/unit_tests/weightwindows/test.py @@ -16,10 +16,15 @@ def wws(): # weight windows + + ww_files = ('ww_n.txt', 'ww_p.txt') + cwd = Path(__file__).parent.absolute() + ww_n_file, ww_p_file = [cwd / Path(f) for f in ww_files] + # load pre-generated weight windows # (created using the same tally as above) - ww_n_lower_bnds = np.loadtxt('ww_n.txt') - ww_p_lower_bnds = np.loadtxt('ww_p.txt') + ww_n_lower_bnds = np.loadtxt(ww_n_file) + ww_p_lower_bnds = np.loadtxt(ww_p_file) # create a mesh matching the one used # to generate the weight windows From 43033b656c03ac96e40f9effc5b4b8d9e17602d1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 27 Oct 2022 14:47:16 -0500 Subject: [PATCH 1223/2654] Returning a tuple for RegularMesh.dimension --- openmc/mesh.py | 2 +- openmc/weight_windows.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d4db5011b..72b021066 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -324,7 +324,7 @@ class RegularMesh(StructuredMesh): @property def dimension(self): - return self._dimension + return tuple(self._dimension) @property def n_dimension(self): diff --git a/openmc/weight_windows.py b/openmc/weight_windows.py index 44de64041..cf5a62cc1 100644 --- a/openmc/weight_windows.py +++ b/openmc/weight_windows.py @@ -370,7 +370,7 @@ class WeightWindows(IDManagerMixin): particle_type = get_text(elem, 'particle_type') survival_ratio = float(get_text(elem, 'survival_ratio')) - ww_shape = (len(e_bounds) - 1,) + tuple(mesh.dimension[::-1]) + ww_shape = (len(e_bounds) - 1,) + mesh.dimension[::-1] lower_ww_bounds = np.array(lower_ww_bounds).reshape(ww_shape).T upper_ww_bounds = np.array(upper_ww_bounds).reshape(ww_shape).T From b00404be7c5a9c1e69f660c0fea7107e63afd518 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 28 Oct 2022 04:34:35 +0000 Subject: [PATCH 1224/2654] Updating dimension type to tuple in a couple of test checks --- tests/regression_tests/dagmc/legacy/test.py | 1 + tests/unit_tests/test_settings.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index dacbc19ee..91734a219 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -55,6 +55,7 @@ def model(): return model + def test_dagmc(model): harness = PyAPITestHarness('statepoint.5.h5', model) harness.main() diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 7678711a4..3603b57c1 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -89,7 +89,7 @@ def test_export_to_xml(run_in_tmpdir): assert isinstance(s.entropy_mesh, openmc.RegularMesh) assert s.entropy_mesh.lower_left == [-10., -10., -10.] assert s.entropy_mesh.upper_right == [10., 10., 10.] - assert s.entropy_mesh.dimension == [5, 5, 5] + assert s.entropy_mesh.dimension == (5, 5, 5) assert s.trigger_active assert s.trigger_max_batches == 10000 assert s.trigger_batch_interval == 50 @@ -102,7 +102,7 @@ def test_export_to_xml(run_in_tmpdir): assert isinstance(s.ufs_mesh, openmc.RegularMesh) assert s.ufs_mesh.lower_left == [-10., -10., -10.] assert s.ufs_mesh.upper_right == [10., 10., 10.] - assert s.ufs_mesh.dimension == [5, 5, 5] + assert s.ufs_mesh.dimension == (5, 5, 5) assert s.resonance_scattering == {'enable': True, 'method': 'rvs', 'energy_min': 1.0, 'energy_max': 1000.0, 'nuclides': ['U235', 'U238', 'Pu239']} From 7eb1a7bbd093d3398095a32a9359fca70a6d3563 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 28 Oct 2022 22:07:46 +0100 Subject: [PATCH 1225/2654] updated reference micro xs values --- .../microxs/test_reference.csv | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/regression_tests/microxs/test_reference.csv b/tests/regression_tests/microxs/test_reference.csv index 787ce74c3..00f4783e6 100644 --- a/tests/regression_tests/microxs/test_reference.csv +++ b/tests/regression_tests/microxs/test_reference.csv @@ -1,13 +1,13 @@ nuclide,"(n,gamma)",fission -U234,22.231989822002465,0.49620744663749855 -U235,10.479008971197121,48.41787337164604 -U238,0.8673334105437324,0.10467880588762352 -U236,8.65171044607122,0.31948392400019293 -O16,7.497851000107524e-05,0.0 -O17,0.0004079227797153371,0.0 -I135,6.842395323713927,0.0 -Xe135,227463.86426990604,0.0 -Xe136,0.02317896034753588,0.0 -Cs135,2.1721665580713623,0.0 -Gd157,12786.09939237018,0.0 -Gd156,3.4006085445846983,0.0 +U234,22.231989815372202,0.49620744658634824 +U235,10.479008966651142,48.417873345870724 +U238,0.8673334103130558,0.1046788058833928 +U236,8.651710443768728,0.3194839239606777 +O16,7.497850998328519e-05,0.0 +O17,0.0004079227795364271,0.0 +I135,6.842395320017149,0.0 +Xe135,227463.8640052883,0.0 +Xe136,0.023178960335476638,0.0 +Cs135,2.1721665579658485,0.0 +Gd157,12786.099387172428,0.0 +Gd156,3.4006085435237843,0.0 From 10b11c02a81fcbe24196668307d55b8f1f9b5ce4 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 28 Oct 2022 22:25:36 +0100 Subject: [PATCH 1226/2654] f strings and pep8 --- .../deplete_no_transport/test.py | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 384653ff7..a36541748 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -8,6 +8,7 @@ import openmc import openmc.deplete from openmc.deplete import IndependentOperator, MicroXS + @pytest.fixture(scope="module") def fuel(): fuel = openmc.Material(name="uo2") @@ -25,16 +26,18 @@ def micro_xs(): micro_xs_file = Path(__file__).parents[2] / 'micro_xs_simple.csv' return MicroXS.from_csv(micro_xs_file) + @pytest.fixture(scope="module") def chain_file(): return Path(__file__).parents[2] / 'chain_simple.xml' + @pytest.mark.parametrize("multiproc, from_nuclides, normalization_mode, power, flux", [ - (True, True,'source-rate', None, 1164719970082145.0), + (True, True, 'source-rate', None, 1164719970082145.0), (False, True, 'source-rate', None, 1164719970082145.0), (True, True, 'fission-q', 174, None), (False, True, 'fission-q', 174, None), - (True, False,'source-rate', None, 1164719970082145.0), + (True, False, 'source-rate', None, 1164719970082145.0), (False, False, 'source-rate', None, 1164719970082145.0), (True, False, 'fission-q', 174, None), (False, False, 'fission-q', 174, None)]) @@ -90,13 +93,14 @@ def test_against_self(run_in_tmpdir, _assert_atoms_equal(res_test, res_ref, tol) _assert_reaction_rates_equal(res_test, res_ref, tol) + @pytest.mark.parametrize("multiproc, dt, time_units, time_type, atom_tol, rx_tol ", [ (True, 360, 's', 'minutes', 2.0e-3, 3.0e-2), (False, 360, 's', 'minutes', 2.0e-3, 3.0e-2), (True, 4, 'h', 'hours', 2.0e-3, 6.0e-2), - (False,4, 'h', 'hours', 2.0e-3, 6.0e-2), + (False, 4, 'h', 'hours', 2.0e-3, 6.0e-2), (True, 5, 'd', 'days', 2.0e-3, 5.0e-2), - (False,5, 'd', 'days', 2.0e-3, 5.0e-2), + (False, 5, 'd', 'days', 2.0e-3, 5.0e-2), (True, 100, 'd', 'months', 4.0e-3, 9.0e-2), (False, 100, 'd', 'months', 4.0e-3, 9.0e-2)]) def test_against_coupled(run_in_tmpdir, @@ -136,6 +140,7 @@ def test_against_coupled(run_in_tmpdir, _assert_atoms_equal(res_test, res_ref, atom_tol) _assert_reaction_rates_equal(res_test, res_ref, rx_tol) + def _create_operator(from_nuclides, fuel, micro_xs, @@ -160,20 +165,22 @@ def _create_operator(from_nuclides, return op + def _assert_same_mats(res_ref, res_test): for mat in res_ref[0].index_mat: - assert mat in res_test[0].index_mat, \ - "Material {} not in new results.".format(mat) + assert mat in res_test[0].index_mat, \ + f"Material {mat} not in new results." for nuc in res_ref[0].index_nuc: assert nuc in res_test[0].index_nuc, \ - "Nuclide {} not in new results.".format(nuc) + f"Nuclide {nuc} not in new results." for mat in res_test[0].index_mat: assert mat in res_ref[0].index_mat, \ - "Material {} not in old results.".format(mat) + f"Material {mat} not in old results." for nuc in res_test[0].index_nuc: assert nuc in res_ref[0].index_nuc, \ - "Nuclide {} not in old results.".format(nuc) + f"Nuclide {nuc} not in old results." + def _assert_atoms_equal(res_ref, res_test, tol): for mat in res_test[0].index_mat: @@ -193,6 +200,7 @@ def _assert_atoms_equal(res_ref, res_test, tol): assert correct, "Discrepancy in mat {} and nuc {}\n{}\n{}".format( mat, nuc, y_old, y_test) + def _assert_reaction_rates_equal(res_ref, res_test, tol): for reactions in res_test[0].rates: for mat in reactions.index_mat: From 21ec8baea4abb52ebefabfa06858dcb158fdb773 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 28 Oct 2022 22:26:14 +0100 Subject: [PATCH 1227/2654] updated reference depletion results --- .../test_reference_fission_q.h5 | Bin 36312 -> 36312 bytes .../test_reference_source_rate.h5 | Bin 36312 -> 36312 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 b/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 index 826c5f3b012fb4b1fb26be4193ac451bd232e2a1..4ae9d3660534b651edb9ee20529ff90a02888d20 100644 GIT binary patch delta 411 zcmcaHo9V`ErVT&3>t)tftX!vl(RqtWik|L*l!z zv5MX0OogU;hugN3=hYvO_@ijYvS`;{=VLB*yJNmBFuM5M_Q>wzlV|rB);r9qvzO24 zU-MYxl+)T@5`E0yCOI84Dd2q{a@gtCd>?@|Kct)*9ps*9+Bi8yPqbMewI{@>{gcsr zkmm%&^wSK0p3_@#=n%+r_a|QdJP*lp=bBPKUPbbp@rLazmPnqPP$L+9_8*e(W*<{N zFNx&43-N4Q@{xS^R#x2px3ICDk>rj1R-or9!lYNp06iytbF-5N&~sdWlFyq1J@-Ms U%8v2>u+WyuUw~o(Ruq}dpq;Lwk~Ue1CB1Z+TxNk_2u=MHR5&*Q1Ied z)1eEO+3jKcMUGX|OyZ{4!uXq5?E-#W`U~d=m>*IV%{vO$zdil;{HzFeI6wXAdWrAC z#wvDtrjAYZ4!3Q&oTna;_@ij|Y~kg-&c|HrzOf1~G`jfQmMi1&xj^#V4_>>2I) z*E|+E~zqL2C8B&QE-1-$P=4m(L&`UtG~A>|~gCjUg!#>r`3l8}tl#wUDw5~k7+qkoMDko_f@$>Ge@MP-m|%Ne z63KT*%ayj|Bl*rwSkL~qu(93ZCqMFAfu8&O%V3oZ&~tn@&p3GiJr}vO;k-G}bMAMh T+A;p0Jg-N5^4?x?7LXqSVn&fT diff --git a/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 b/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 index f5161d37067f6b7ffe333e41270959a75f7ebfda..1572fbd765b9823ab98b9e6719df7f05242f6b9c 100644 GIT binary patch delta 151 zcmcaHo9V`ErVT&3g=N-OtX!vl(RqtWike94akPRgqq7nQ+8#Z6!**2M{M+Inw2hixs9{I@&dQDhBMgst; C*hG5( delta 178 zcmcaHo9V`ErVT&3g>PmhuUw~o(Ruq}dpq;Lwk~Ue1159#s4^~{Y}ljExN>r0k2qua z Date: Sun, 30 Oct 2022 03:28:14 +0000 Subject: [PATCH 1228/2654] undo formatting change of settings file --- openmc/settings.py | 715 +++++++++++++++++++++------------------------ 1 file changed, 340 insertions(+), 375 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index e6561ffb9..f13b233de 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -17,14 +17,14 @@ from openmc.checkvalue import PathLike class RunMode(Enum): - EIGENVALUE = "eigenvalue" - FIXED_SOURCE = "fixed source" - PLOT = "plot" - VOLUME = "volume" - PARTICLE_RESTART = "particle restart" + EIGENVALUE = 'eigenvalue' + FIXED_SOURCE = 'fixed source' + PLOT = 'plot' + VOLUME = 'volume' + PARTICLE_RESTART = 'particle restart' -_RES_SCAT_METHODS = ["dbrc", "rvs"] +_RES_SCAT_METHODS = ['dbrc', 'rvs'] class Settings: @@ -190,7 +190,7 @@ class Settings: temperature within which cross sections may be used. If the method is 'interpolation', 'tolerance' indicates the range of temperatures outside of the available cross section temperatures where cross sections will - evaluate to the nearer bound. The value for 'range' should be a pair a + evaluate to the nearer bound. The value for 'range' should be a pair of minimum and maximum temperatures which are used to indicate that cross sections be loaded at all temperatures within the range. 'multipole' is a boolean indicating whether or not the windowed multipole method should @@ -245,7 +245,7 @@ class Settings: self._max_order = None # Source subelement - self._source = cv.CheckedList(Source, "source distributions") + self._source = cv.CheckedList(Source, 'source distributions') self._confidence_intervals = None self._electron_treatment = None @@ -290,8 +290,7 @@ class Settings: self._resonance_scattering = {} self._volume_calculations = cv.CheckedList( - VolumeCalculation, "volume calculations" - ) + VolumeCalculation, 'volume calculations') self._create_fission_neutrons = None self._delayed_photon_scaling = None @@ -301,7 +300,7 @@ class Settings: self._event_based = None self._max_particles_in_flight = None self._write_initial_source = None - self._weight_windows = cv.CheckedList(WeightWindows, "weight windows") + self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows') self._weight_windows_on = None self._max_splits = None self._max_tracks = None @@ -499,109 +498,103 @@ class Settings: @run_mode.setter def run_mode(self, run_mode: str): - cv.check_value("run mode", run_mode, {x.value for x in RunMode}) + cv.check_value('run mode', run_mode, {x.value for x in RunMode}) for mode in RunMode: if mode.value == run_mode: self._run_mode = mode @batches.setter def batches(self, batches: int): - cv.check_type("batches", batches, Integral) - cv.check_greater_than("batches", batches, 0) + cv.check_type('batches', batches, Integral) + cv.check_greater_than('batches', batches, 0) self._batches = batches @generations_per_batch.setter def generations_per_batch(self, generations_per_batch: int): - cv.check_type("generations per patch", generations_per_batch, Integral) - cv.check_greater_than("generations per batch", generations_per_batch, 0) + cv.check_type('generations per patch', generations_per_batch, Integral) + cv.check_greater_than('generations per batch', generations_per_batch, 0) self._generations_per_batch = generations_per_batch @inactive.setter def inactive(self, inactive: int): - cv.check_type("inactive batches", inactive, Integral) - cv.check_greater_than("inactive batches", inactive, 0, True) + cv.check_type('inactive batches', inactive, Integral) + cv.check_greater_than('inactive batches', inactive, 0, True) self._inactive = inactive @max_lost_particles.setter def max_lost_particles(self, max_lost_particles: int): - cv.check_type("max_lost_particles", max_lost_particles, Integral) - cv.check_greater_than("max_lost_particles", max_lost_particles, 0) + cv.check_type('max_lost_particles', max_lost_particles, Integral) + cv.check_greater_than('max_lost_particles', max_lost_particles, 0) self._max_lost_particles = max_lost_particles @rel_max_lost_particles.setter def rel_max_lost_particles(self, rel_max_lost_particles: float): - cv.check_type("rel_max_lost_particles", rel_max_lost_particles, Real) - cv.check_greater_than("rel_max_lost_particles", rel_max_lost_particles, 0) - cv.check_less_than("rel_max_lost_particles", rel_max_lost_particles, 1) + cv.check_type('rel_max_lost_particles', rel_max_lost_particles, Real) + cv.check_greater_than('rel_max_lost_particles', rel_max_lost_particles, 0) + cv.check_less_than('rel_max_lost_particles', rel_max_lost_particles, 1) self._rel_max_lost_particles = rel_max_lost_particles @particles.setter def particles(self, particles: int): - cv.check_type("particles", particles, Integral) - cv.check_greater_than("particles", particles, 0) + cv.check_type('particles', particles, Integral) + cv.check_greater_than('particles', particles, 0) self._particles = particles @keff_trigger.setter def keff_trigger(self, keff_trigger: dict): if not isinstance(keff_trigger, dict): - msg = ( - f'Unable to set a trigger on keff from "{keff_trigger}" ' - "which is not a Python dictionary" - ) + msg = f'Unable to set a trigger on keff from "{keff_trigger}" ' \ + 'which is not a Python dictionary' raise ValueError(msg) - elif "type" not in keff_trigger: - msg = ( - f'Unable to set a trigger on keff from "{keff_trigger}" ' - 'which does not have a "type" key' - ) + elif 'type' not in keff_trigger: + msg = f'Unable to set a trigger on keff from "{keff_trigger}" ' \ + 'which does not have a "type" key' raise ValueError(msg) - elif keff_trigger["type"] not in ["variance", "std_dev", "rel_err"]: - msg = "Unable to set a trigger on keff with " 'type "{0}"'.format( - keff_trigger["type"] - ) + elif keff_trigger['type'] not in ['variance', 'std_dev', 'rel_err']: + msg = 'Unable to set a trigger on keff with ' \ + 'type "{0}"'.format(keff_trigger['type']) raise ValueError(msg) - elif "threshold" not in keff_trigger: - msg = ( - f'Unable to set a trigger on keff from "{keff_trigger}" ' - 'which does not have a "threshold" key' - ) + elif 'threshold' not in keff_trigger: + msg = f'Unable to set a trigger on keff from "{keff_trigger}" ' \ + 'which does not have a "threshold" key' raise ValueError(msg) - elif not isinstance(keff_trigger["threshold"], Real): - msg = "Unable to set a trigger on keff with " 'threshold "{0}"'.format( - keff_trigger["threshold"] - ) + elif not isinstance(keff_trigger['threshold'], Real): + msg = 'Unable to set a trigger on keff with ' \ + 'threshold "{0}"'.format(keff_trigger['threshold']) raise ValueError(msg) self._keff_trigger = keff_trigger @energy_mode.setter def energy_mode(self, energy_mode: str): - cv.check_value("energy mode", energy_mode, ["continuous-energy", "multi-group"]) + cv.check_value('energy mode', energy_mode, + ['continuous-energy', 'multi-group']) self._energy_mode = energy_mode @max_order.setter def max_order(self, max_order: Optional[int]): if max_order is not None: - cv.check_type("maximum scattering order", max_order, Integral) - cv.check_greater_than("maximum scattering order", max_order, 0, True) + cv.check_type('maximum scattering order', max_order, Integral) + cv.check_greater_than('maximum scattering order', max_order, 0, + True) self._max_order = max_order @source.setter def source(self, source: Union[Source, typing.Iterable[Source]]): if not isinstance(source, MutableSequence): source = [source] - self._source = cv.CheckedList(Source, "source distributions", source) + self._source = cv.CheckedList(Source, 'source distributions', source) @output.setter def output(self, output: dict): - cv.check_type("output", output, Mapping) + cv.check_type('output', output, Mapping) for key, value in output.items(): - cv.check_value("output key", key, ("summary", "tallies", "path")) - if key in ("summary", "tallies"): + cv.check_value('output key', key, ('summary', 'tallies', 'path')) + if key in ('summary', 'tallies'): cv.check_type(f"output['{key}']", value, bool) else: cv.check_type("output['path']", value, str) @@ -609,257 +602,245 @@ class Settings: @verbosity.setter def verbosity(self, verbosity: int): - cv.check_type("verbosity", verbosity, Integral) - cv.check_greater_than("verbosity", verbosity, 1, True) - cv.check_less_than("verbosity", verbosity, 10, True) + cv.check_type('verbosity', verbosity, Integral) + cv.check_greater_than('verbosity', verbosity, 1, True) + cv.check_less_than('verbosity', verbosity, 10, True) self._verbosity = verbosity @sourcepoint.setter def sourcepoint(self, sourcepoint: dict): - cv.check_type("sourcepoint options", sourcepoint, Mapping) + cv.check_type('sourcepoint options', sourcepoint, Mapping) for key, value in sourcepoint.items(): - if key == "batches": - cv.check_type("sourcepoint batches", value, Iterable, Integral) + if key == 'batches': + cv.check_type('sourcepoint batches', value, Iterable, Integral) for batch in value: - cv.check_greater_than("sourcepoint batch", batch, 0) - elif key == "separate": - cv.check_type("sourcepoint separate", value, bool) - elif key == "write": - cv.check_type("sourcepoint write", value, bool) - elif key == "overwrite": - cv.check_type("sourcepoint overwrite", value, bool) + cv.check_greater_than('sourcepoint batch', batch, 0) + elif key == 'separate': + cv.check_type('sourcepoint separate', value, bool) + elif key == 'write': + cv.check_type('sourcepoint write', value, bool) + elif key == 'overwrite': + cv.check_type('sourcepoint overwrite', value, bool) else: - raise ValueError( - f"Unknown key '{key}' encountered when " - "setting sourcepoint options." - ) + raise ValueError(f"Unknown key '{key}' encountered when " + "setting sourcepoint options.") self._sourcepoint = sourcepoint @statepoint.setter def statepoint(self, statepoint: dict): - cv.check_type("statepoint options", statepoint, Mapping) + cv.check_type('statepoint options', statepoint, Mapping) for key, value in statepoint.items(): - if key == "batches": - cv.check_type("statepoint batches", value, Iterable, Integral) + if key == 'batches': + cv.check_type('statepoint batches', value, Iterable, Integral) for batch in value: - cv.check_greater_than("statepoint batch", batch, 0) + cv.check_greater_than('statepoint batch', batch, 0) else: - raise ValueError( - f"Unknown key '{key}' encountered when " - "setting statepoint options." - ) + raise ValueError(f"Unknown key '{key}' encountered when " + "setting statepoint options.") self._statepoint = statepoint @surf_source_read.setter def surf_source_read(self, surf_source_read: dict): - cv.check_type("surface source reading options", surf_source_read, Mapping) + cv.check_type('surface source reading options', surf_source_read, Mapping) for key, value in surf_source_read.items(): - cv.check_value("surface source reading key", key, ("path")) - if key == "path": - cv.check_type("path to surface source file", value, str) + cv.check_value('surface source reading key', key, + ('path')) + if key == 'path': + cv.check_type('path to surface source file', value, str) self._surf_source_read = surf_source_read @surf_source_write.setter def surf_source_write(self, surf_source_write: dict): - cv.check_type("surface source writing options", surf_source_write, Mapping) + cv.check_type('surface source writing options', surf_source_write, Mapping) for key, value in surf_source_write.items(): - cv.check_value( - "surface source writing key", key, ("surface_ids", "max_particles") - ) - if key == "surface_ids": - cv.check_type( - "surface ids for source banking", value, Iterable, Integral - ) + cv.check_value('surface source writing key', key, + ('surface_ids', 'max_particles')) + if key == 'surface_ids': + cv.check_type('surface ids for source banking', value, + Iterable, Integral) for surf_id in value: - cv.check_greater_than("surface id for source banking", surf_id, 0) - elif key == "max_particles": - cv.check_type( - "maximum particle banks on surfaces per process", value, Integral - ) - cv.check_greater_than( - "maximum particle banks on surfaces per process", value, 0 - ) + cv.check_greater_than('surface id for source banking', + surf_id, 0) + elif key == 'max_particles': + cv.check_type('maximum particle banks on surfaces per process', + value, Integral) + cv.check_greater_than('maximum particle banks on surfaces per process', + value, 0) self._surf_source_write = surf_source_write @confidence_intervals.setter def confidence_intervals(self, confidence_intervals: bool): - cv.check_type("confidence interval", confidence_intervals, bool) + cv.check_type('confidence interval', confidence_intervals, bool) self._confidence_intervals = confidence_intervals @electron_treatment.setter def electron_treatment(self, electron_treatment: str): - cv.check_value("electron treatment", electron_treatment, ["led", "ttb"]) + cv.check_value('electron treatment', electron_treatment, ['led', 'ttb']) self._electron_treatment = electron_treatment @photon_transport.setter def photon_transport(self, photon_transport: bool): - cv.check_type("photon transport", photon_transport, bool) + cv.check_type('photon transport', photon_transport, bool) self._photon_transport = photon_transport @ptables.setter def ptables(self, ptables: bool): - cv.check_type("probability tables", ptables, bool) + cv.check_type('probability tables', ptables, bool) self._ptables = ptables @seed.setter def seed(self, seed: int): - cv.check_type("random number generator seed", seed, Integral) - cv.check_greater_than("random number generator seed", seed, 0) + cv.check_type('random number generator seed', seed, Integral) + cv.check_greater_than('random number generator seed', seed, 0) self._seed = seed @survival_biasing.setter def survival_biasing(self, survival_biasing: bool): - cv.check_type("survival biasing", survival_biasing, bool) + cv.check_type('survival biasing', survival_biasing, bool) self._survival_biasing = survival_biasing @cutoff.setter def cutoff(self, cutoff: dict): if not isinstance(cutoff, Mapping): - msg = ( - f'Unable to set cutoff from "{cutoff}" which is not a ' - "Python dictionary" - ) + msg = f'Unable to set cutoff from "{cutoff}" which is not a '\ + 'Python dictionary' raise ValueError(msg) for key in cutoff: - if key == "weight": - cv.check_type("weight cutoff", cutoff[key], Real) - cv.check_greater_than("weight cutoff", cutoff[key], 0.0) - elif key == "weight_avg": - cv.check_type("average survival weight", cutoff[key], Real) - cv.check_greater_than("average survival weight", cutoff[key], 0.0) - elif key in [ - "energy_neutron", - "energy_photon", - "energy_electron", - "energy_positron", - ]: - cv.check_type("energy cutoff", cutoff[key], Real) - cv.check_greater_than("energy cutoff", cutoff[key], 0.0) + if key == 'weight': + cv.check_type('weight cutoff', cutoff[key], Real) + cv.check_greater_than('weight cutoff', cutoff[key], 0.0) + elif key == 'weight_avg': + cv.check_type('average survival weight', cutoff[key], Real) + cv.check_greater_than('average survival weight', + cutoff[key], 0.0) + elif key in ['energy_neutron', 'energy_photon', 'energy_electron', + 'energy_positron']: + cv.check_type('energy cutoff', cutoff[key], Real) + cv.check_greater_than('energy cutoff', cutoff[key], 0.0) else: - msg = ( - f'Unable to set cutoff to "{key}" which is unsupported ' "by OpenMC" - ) + msg = f'Unable to set cutoff to "{key}" which is unsupported ' \ + 'by OpenMC' self._cutoff = cutoff @entropy_mesh.setter def entropy_mesh(self, entropy: RegularMesh): - cv.check_type("entropy mesh", entropy, RegularMesh) + cv.check_type('entropy mesh', entropy, RegularMesh) self._entropy_mesh = entropy @trigger_active.setter def trigger_active(self, trigger_active: bool): - cv.check_type("trigger active", trigger_active, bool) + cv.check_type('trigger active', trigger_active, bool) self._trigger_active = trigger_active @trigger_max_batches.setter def trigger_max_batches(self, trigger_max_batches: int): - cv.check_type("trigger maximum batches", trigger_max_batches, Integral) - cv.check_greater_than("trigger maximum batches", trigger_max_batches, 0) + cv.check_type('trigger maximum batches', trigger_max_batches, Integral) + cv.check_greater_than('trigger maximum batches', trigger_max_batches, 0) self._trigger_max_batches = trigger_max_batches @trigger_batch_interval.setter def trigger_batch_interval(self, trigger_batch_interval: int): - cv.check_type("trigger batch interval", trigger_batch_interval, Integral) - cv.check_greater_than("trigger batch interval", trigger_batch_interval, 0) + cv.check_type('trigger batch interval', trigger_batch_interval, Integral) + cv.check_greater_than('trigger batch interval', trigger_batch_interval, 0) self._trigger_batch_interval = trigger_batch_interval @no_reduce.setter def no_reduce(self, no_reduce: bool): - cv.check_type("no reduction option", no_reduce, bool) + cv.check_type('no reduction option', no_reduce, bool) self._no_reduce = no_reduce @tabular_legendre.setter def tabular_legendre(self, tabular_legendre: dict): - cv.check_type("tabular_legendre settings", tabular_legendre, Mapping) + cv.check_type('tabular_legendre settings', tabular_legendre, Mapping) for key, value in tabular_legendre.items(): - cv.check_value("tabular_legendre key", key, ["enable", "num_points"]) - if key == "enable": - cv.check_type("enable tabular_legendre", value, bool) - elif key == "num_points": - cv.check_type("num_points tabular_legendre", value, Integral) - cv.check_greater_than("num_points tabular_legendre", value, 0) + cv.check_value('tabular_legendre key', key, + ['enable', 'num_points']) + if key == 'enable': + cv.check_type('enable tabular_legendre', value, bool) + elif key == 'num_points': + cv.check_type('num_points tabular_legendre', value, Integral) + cv.check_greater_than('num_points tabular_legendre', value, 0) self._tabular_legendre = tabular_legendre @temperature.setter def temperature(self, temperature: dict): - cv.check_type("temperature settings", temperature, Mapping) + cv.check_type('temperature settings', temperature, Mapping) for key, value in temperature.items(): - cv.check_value( - "temperature key", - key, - ["default", "method", "tolerance", "multipole", "range"], - ) - if key == "default": - cv.check_type("default temperature", value, Real) - elif key == "method": - cv.check_value( - "temperature method", value, ["nearest", "interpolation"] - ) - elif key == "tolerance": - cv.check_type("temperature tolerance", value, Real) - elif key == "multipole": - cv.check_type("temperature multipole", value, bool) - elif key == "range": - cv.check_length("temperature range", value, 2) + cv.check_value('temperature key', key, + ['default', 'method', 'tolerance', 'multipole', + 'range']) + if key == 'default': + cv.check_type('default temperature', value, Real) + elif key == 'method': + cv.check_value('temperature method', value, + ['nearest', 'interpolation']) + elif key == 'tolerance': + cv.check_type('temperature tolerance', value, Real) + elif key == 'multipole': + cv.check_type('temperature multipole', value, bool) + elif key == 'range': + cv.check_length('temperature range', value, 2) for T in value: - cv.check_type("temperature", T, Real) + cv.check_type('temperature', T, Real) self._temperature = temperature @trace.setter def trace(self, trace: Iterable): - cv.check_type("trace", trace, Iterable, Integral) - cv.check_length("trace", trace, 3) - cv.check_greater_than("trace batch", trace[0], 0) - cv.check_greater_than("trace generation", trace[1], 0) - cv.check_greater_than("trace particle", trace[2], 0) + cv.check_type('trace', trace, Iterable, Integral) + cv.check_length('trace', trace, 3) + cv.check_greater_than('trace batch', trace[0], 0) + cv.check_greater_than('trace generation', trace[1], 0) + cv.check_greater_than('trace particle', trace[2], 0) self._trace = trace @track.setter def track(self, track: typing.Iterable[typing.Iterable[int]]): - cv.check_type("track", track, Iterable) + cv.check_type('track', track, Iterable) for t in track: if len(t) != 3: msg = f'Unable to set the track to "{t}" since its length is not 3' raise ValueError(msg) - cv.check_greater_than("track batch", t[0], 0) - cv.check_greater_than("track generation", t[1], 0) - cv.check_greater_than("track particle", t[2], 0) - cv.check_type("track batch", t[0], Integral) - cv.check_type("track generation", t[1], Integral) - cv.check_type("track particle", t[2], Integral) + cv.check_greater_than('track batch', t[0], 0) + cv.check_greater_than('track generation', t[1], 0) + cv.check_greater_than('track particle', t[2], 0) + cv.check_type('track batch', t[0], Integral) + cv.check_type('track generation', t[1], Integral) + cv.check_type('track particle', t[2], Integral) self._track = track @ufs_mesh.setter def ufs_mesh(self, ufs_mesh: RegularMesh): - cv.check_type("UFS mesh", ufs_mesh, RegularMesh) - cv.check_length("UFS mesh dimension", ufs_mesh.dimension, 3) - cv.check_length("UFS mesh lower-left corner", ufs_mesh.lower_left, 3) - cv.check_length("UFS mesh upper-right corner", ufs_mesh.upper_right, 3) + cv.check_type('UFS mesh', ufs_mesh, RegularMesh) + cv.check_length('UFS mesh dimension', ufs_mesh.dimension, 3) + cv.check_length('UFS mesh lower-left corner', ufs_mesh.lower_left, 3) + cv.check_length('UFS mesh upper-right corner', ufs_mesh.upper_right, 3) self._ufs_mesh = ufs_mesh @resonance_scattering.setter def resonance_scattering(self, res: dict): - cv.check_type("resonance scattering settings", res, Mapping) - keys = ("enable", "method", "energy_min", "energy_max", "nuclides") + cv.check_type('resonance scattering settings', res, Mapping) + keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides') for key, value in res.items(): - cv.check_value("resonance scattering dictionary key", key, keys) - if key == "enable": - cv.check_type("resonance scattering enable", value, bool) - elif key == "method": - cv.check_value("resonance scattering method", value, _RES_SCAT_METHODS) - elif key == "energy_min": - name = "resonance scattering minimum energy" + cv.check_value('resonance scattering dictionary key', key, keys) + if key == 'enable': + cv.check_type('resonance scattering enable', value, bool) + elif key == 'method': + cv.check_value('resonance scattering method', value, + _RES_SCAT_METHODS) + elif key == 'energy_min': + name = 'resonance scattering minimum energy' cv.check_type(name, value, Real) cv.check_greater_than(name, value, 0) - elif key == "energy_max": - name = "resonance scattering minimum energy" + elif key == 'energy_max': + name = 'resonance scattering minimum energy' cv.check_type(name, value, Real) cv.check_greater_than(name, value, 0) - elif key == "nuclides": - cv.check_type("resonance scattering nuclides", value, Iterable, str) + elif key == 'nuclides': + cv.check_type('resonance scattering nuclides', value, + Iterable, str) self._resonance_scattering = res @volume_calculations.setter @@ -869,69 +850,67 @@ class Settings: if not isinstance(vol_calcs, MutableSequence): vol_calcs = [vol_calcs] self._volume_calculations = cv.CheckedList( - VolumeCalculation, "stochastic volume calculations", vol_calcs - ) + VolumeCalculation, 'stochastic volume calculations', vol_calcs) @create_fission_neutrons.setter def create_fission_neutrons(self, create_fission_neutrons: bool): - cv.check_type("Whether create fission neutrons", create_fission_neutrons, bool) + cv.check_type('Whether create fission neutrons', + create_fission_neutrons, bool) self._create_fission_neutrons = create_fission_neutrons @delayed_photon_scaling.setter def delayed_photon_scaling(self, value: bool): - cv.check_type("delayed photon scaling", value, bool) + cv.check_type('delayed photon scaling', value, bool) self._delayed_photon_scaling = value @event_based.setter def event_based(self, value: bool): - cv.check_type("event based", value, bool) + cv.check_type('event based', value, bool) self._event_based = value @max_particles_in_flight.setter def max_particles_in_flight(self, value: int): - cv.check_type("max particles in flight", value, Integral) - cv.check_greater_than("max particles in flight", value, 0) + cv.check_type('max particles in flight', value, Integral) + cv.check_greater_than('max particles in flight', value, 0) self._max_particles_in_flight = value @material_cell_offsets.setter def material_cell_offsets(self, value: bool): - cv.check_type("material cell offsets", value, bool) + cv.check_type('material cell offsets', value, bool) self._material_cell_offsets = value @log_grid_bins.setter def log_grid_bins(self, log_grid_bins: int): - cv.check_type("log grid bins", log_grid_bins, Real) - cv.check_greater_than("log grid bins", log_grid_bins, 0) + cv.check_type('log grid bins', log_grid_bins, Real) + cv.check_greater_than('log grid bins', log_grid_bins, 0) self._log_grid_bins = log_grid_bins @write_initial_source.setter def write_initial_source(self, value: bool): - cv.check_type("write initial source", value, bool) + cv.check_type('write initial source', value, bool) self._write_initial_source = value @weight_windows.setter - def weight_windows( - self, value: Union[WeightWindows, typing.Iterable[WeightWindows]] - ): + def weight_windows(self, value: Union[WeightWindows, typing.Iterable[WeightWindows]]): if not isinstance(value, MutableSequence): value = [value] - self._weight_windows = cv.CheckedList(WeightWindows, "weight windows", value) + self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows', value) @weight_windows_on.setter def weight_windows_on(self, value): - cv.check_type("weight windows on", value, bool) + cv.check_type('weight windows on', value, bool) self._weight_windows_on = value @max_splits.setter def max_splits(self, value: int): - cv.check_type("maximum particle splits", value, Integral) - cv.check_greater_than("max particle splits", value, 0) + cv.check_type('maximum particle splits', value, Integral) + cv.check_greater_than('max particle splits', value, 0) self._max_splits = value @max_tracks.setter def max_tracks(self, value: int): - cv.check_type("maximum particle tracks", value, Integral) - cv.check_greater_than("maximum particle tracks", value, 0, True) + cv.check_type('maximum particle tracks', value, Integral) + cv.check_greater_than('maximum particle tracks', value, 0, True) self._max_tracks = value def _create_run_mode_subelement(self, root): @@ -998,7 +977,7 @@ class Settings: element = ET.SubElement(root, "output") for key, value in sorted(self._output.items()): subelement = ET.SubElement(element, key) - if key in ("summary", "tallies"): + if key in ('summary', 'tallies'): subelement.text = str(value).lower() else: subelement.text = value @@ -1011,49 +990,50 @@ class Settings: def _create_statepoint_subelement(self, root): if self._statepoint: element = ET.SubElement(root, "state_point") - if "batches" in self._statepoint: + if 'batches' in self._statepoint: subelement = ET.SubElement(element, "batches") - subelement.text = " ".join(str(x) for x in self._statepoint["batches"]) + subelement.text = ' '.join( + str(x) for x in self._statepoint['batches']) def _create_sourcepoint_subelement(self, root): if self._sourcepoint: element = ET.SubElement(root, "source_point") - if "batches" in self._sourcepoint: + if 'batches' in self._sourcepoint: subelement = ET.SubElement(element, "batches") - subelement.text = " ".join(str(x) for x in self._sourcepoint["batches"]) + subelement.text = ' '.join( + str(x) for x in self._sourcepoint['batches']) - if "separate" in self._sourcepoint: + if 'separate' in self._sourcepoint: subelement = ET.SubElement(element, "separate") - subelement.text = str(self._sourcepoint["separate"]).lower() + subelement.text = str(self._sourcepoint['separate']).lower() - if "write" in self._sourcepoint: + if 'write' in self._sourcepoint: subelement = ET.SubElement(element, "write") - subelement.text = str(self._sourcepoint["write"]).lower() + subelement.text = str(self._sourcepoint['write']).lower() # Overwrite latest subelement - if "overwrite" in self._sourcepoint: + if 'overwrite' in self._sourcepoint: subelement = ET.SubElement(element, "overwrite_latest") - subelement.text = str(self._sourcepoint["overwrite"]).lower() + subelement.text = str(self._sourcepoint['overwrite']).lower() def _create_surf_source_read_subelement(self, root): if self._surf_source_read: element = ET.SubElement(root, "surf_source_read") - if "path" in self._surf_source_read: + if 'path' in self._surf_source_read: subelement = ET.SubElement(element, "path") - subelement.text = self._surf_source_read["path"] + subelement.text = self._surf_source_read['path'] def _create_surf_source_write_subelement(self, root): if self._surf_source_write: element = ET.SubElement(root, "surf_source_write") - if "surface_ids" in self._surf_source_write: + if 'surface_ids' in self._surf_source_write: subelement = ET.SubElement(element, "surface_ids") - subelement.text = " ".join( - str(x) for x in self._surf_source_write["surface_ids"] - ) - if "max_particles" in self._surf_source_write: + subelement.text = ' '.join( + str(x) for x in self._surf_source_write['surface_ids']) + if 'max_particles' in self._surf_source_write: subelement = ET.SubElement(element, "max_particles") - subelement.text = str(self._surf_source_write["max_particles"]) + subelement.text = str(self._surf_source_write['max_particles']) def _create_confidence_intervals(self, root): if self._confidence_intervals is not None: @@ -1097,14 +1077,12 @@ class Settings: # use default heuristic for entropy mesh if not set by user if self.entropy_mesh.dimension is None: if self.particles is None: - raise RuntimeError( - "Number of particles must be set in order to " - "use entropy mesh dimension heuristic" - ) + raise RuntimeError("Number of particles must be set in order to " \ + "use entropy mesh dimension heuristic") else: - n = ceil((self.particles / 20.0) ** (1.0 / 3.0)) + n = ceil((self.particles / 20.0)**(1.0 / 3.0)) d = len(self.entropy_mesh.lower_left) - self.entropy_mesh.dimension = (n,) * d + self.entropy_mesh.dimension = (n,)*d # See if a element already exists -- if not, add it path = f"./mesh[@id='{self.entropy_mesh.id}']" @@ -1137,10 +1115,10 @@ class Settings: if self.tabular_legendre: element = ET.SubElement(root, "tabular_legendre") subelement = ET.SubElement(element, "enable") - subelement.text = str(self._tabular_legendre["enable"]).lower() - if "num_points" in self._tabular_legendre: + subelement.text = str(self._tabular_legendre['enable']).lower() + if 'num_points' in self._tabular_legendre: subelement = ET.SubElement(element, "num_points") - subelement.text = str(self._tabular_legendre["num_points"]) + subelement.text = str(self._tabular_legendre['num_points']) def _create_temperature_subelements(self, root): if self.temperature: @@ -1148,20 +1126,20 @@ class Settings: element = ET.SubElement(root, f"temperature_{key}") if isinstance(value, bool): element.text = str(value).lower() - elif key == "range": - element.text = " ".join(str(T) for T in value) + elif key == 'range': + element.text = ' '.join(str(T) for T in value) else: element.text = str(value) def _create_trace_subelement(self, root): if self._trace is not None: element = ET.SubElement(root, "trace") - element.text = " ".join(map(str, self._trace)) + element.text = ' '.join(map(str, self._trace)) def _create_track_subelement(self, root): if self._track is not None: element = ET.SubElement(root, "track") - element.text = " ".join(map(str, itertools.chain(*self._track))) + element.text = ' '.join(map(str, itertools.chain(*self._track))) def _create_ufs_mesh_subelement(self, root): if self.ufs_mesh is not None: @@ -1176,22 +1154,22 @@ class Settings: def _create_resonance_scattering_subelement(self, root): res = self.resonance_scattering if res: - elem = ET.SubElement(root, "resonance_scattering") - if "enable" in res: - subelem = ET.SubElement(elem, "enable") - subelem.text = str(res["enable"]).lower() - if "method" in res: - subelem = ET.SubElement(elem, "method") - subelem.text = res["method"] - if "energy_min" in res: - subelem = ET.SubElement(elem, "energy_min") - subelem.text = str(res["energy_min"]) - if "energy_max" in res: - subelem = ET.SubElement(elem, "energy_max") - subelem.text = str(res["energy_max"]) - if "nuclides" in res: - subelem = ET.SubElement(elem, "nuclides") - subelem.text = " ".join(res["nuclides"]) + elem = ET.SubElement(root, 'resonance_scattering') + if 'enable' in res: + subelem = ET.SubElement(elem, 'enable') + subelem.text = str(res['enable']).lower() + if 'method' in res: + subelem = ET.SubElement(elem, 'method') + subelem.text = res['method'] + if 'energy_min' in res: + subelem = ET.SubElement(elem, 'energy_min') + subelem.text = str(res['energy_min']) + if 'energy_max' in res: + subelem = ET.SubElement(elem, 'energy_max') + subelem.text = str(res['energy_max']) + if 'nuclides' in res: + subelem = ET.SubElement(elem, 'nuclides') + subelem.text = ' '.join(res['nuclides']) def _create_create_fission_neutrons_subelement(self, root): if self._create_fission_neutrons is not None: @@ -1253,7 +1231,7 @@ class Settings: elem.text = str(self._max_tracks) def _eigenvalue_from_xml_element(self, root): - elem = root.find("eigenvalue") + elem = root.find('eigenvalue') if elem is not None: self._run_mode_from_xml_element(elem) self._particles_from_xml_element(elem) @@ -1264,168 +1242,161 @@ class Settings: self._generations_per_batch_from_xml_element(elem) def _run_mode_from_xml_element(self, root): - text = get_text(root, "run_mode") + text = get_text(root, 'run_mode') if text is not None: self.run_mode = text def _particles_from_xml_element(self, root): - text = get_text(root, "particles") + text = get_text(root, 'particles') if text is not None: self.particles = int(text) def _batches_from_xml_element(self, root): - text = get_text(root, "batches") + text = get_text(root, 'batches') if text is not None: self.batches = int(text) def _inactive_from_xml_element(self, root): - text = get_text(root, "inactive") + text = get_text(root, 'inactive') if text is not None: self.inactive = int(text) def _max_lost_particles_from_xml_element(self, root): - text = get_text(root, "max_lost_particles") + text = get_text(root, 'max_lost_particles') if text is not None: self.max_lost_particles = int(text) def _rel_max_lost_particles_from_xml_element(self, root): - text = get_text(root, "rel_max_lost_particles") + text = get_text(root, 'rel_max_lost_particles') if text is not None: self.rel_max_lost_particles = float(text) def _generations_per_batch_from_xml_element(self, root): - text = get_text(root, "generations_per_batch") + text = get_text(root, 'generations_per_batch') if text is not None: self.generations_per_batch = int(text) def _keff_trigger_from_xml_element(self, root): - elem = root.find("keff_trigger") + elem = root.find('keff_trigger') if elem is not None: - trigger = get_text(elem, "type") - threshold = float(get_text(elem, "threshold")) - self.keff_trigger = {"type": trigger, "threshold": threshold} + trigger = get_text(elem, 'type') + threshold = float(get_text(elem, 'threshold')) + self.keff_trigger = {'type': trigger, 'threshold': threshold} def _source_from_xml_element(self, root): - for elem in root.findall("source"): + for elem in root.findall('source'): self.source.append(Source.from_xml_element(elem)) def _volume_calcs_from_xml_element(self, root): volume_elems = root.findall("volume_calc") if volume_elems: - self.volume_calculations = [ - VolumeCalculation.from_xml_element(elem) for elem in volume_elems - ] + self.volume_calculations = [VolumeCalculation.from_xml_element(elem) + for elem in volume_elems] def _output_from_xml_element(self, root): - elem = root.find("output") + elem = root.find('output') if elem is not None: self.output = {} - for key in ("summary", "tallies", "path"): + for key in ('summary', 'tallies', 'path'): value = get_text(elem, key) if value is not None: - if key in ("summary", "tallies"): - value = value in ("true", "1") + if key in ('summary', 'tallies'): + value = value in ('true', '1') self.output[key] = value def _statepoint_from_xml_element(self, root): - elem = root.find("state_point") + elem = root.find('state_point') if elem is not None: - text = get_text(elem, "batches") + text = get_text(elem, 'batches') if text is not None: - self.statepoint["batches"] = [int(x) for x in text.split()] + self.statepoint['batches'] = [int(x) for x in text.split()] def _sourcepoint_from_xml_element(self, root): - elem = root.find("source_point") + elem = root.find('source_point') if elem is not None: - for key in ("separate", "write", "overwrite_latest", "batches"): + for key in ('separate', 'write', 'overwrite_latest', 'batches'): value = get_text(elem, key) if value is not None: - if key in ("separate", "write"): - value = value in ("true", "1") - elif key == "overwrite_latest": - value = value in ("true", "1") - key = "overwrite" + if key in ('separate', 'write'): + value = value in ('true', '1') + elif key == 'overwrite_latest': + value = value in ('true', '1') + key = 'overwrite' else: value = [int(x) for x in value.split()] self.sourcepoint[key] = value def _surf_source_read_from_xml_element(self, root): - elem = root.find("surf_source_read") + elem = root.find('surf_source_read') if elem is not None: - value = get_text(elem, "path") + value = get_text(elem, 'path') if value is not None: - self.surf_source_read["path"] = value + self.surf_source_read['path'] = value def _surf_source_write_from_xml_element(self, root): - elem = root.find("surf_source_write") + elem = root.find('surf_source_write') if elem is not None: - for key in ("surface_ids", "max_particles"): + for key in ('surface_ids', 'max_particles'): value = get_text(elem, key) if value is not None: - if key == "surface_ids": + if key == 'surface_ids': value = [int(x) for x in value.split()] - elif key in ("max_particles"): + elif key in ('max_particles'): value = int(value) self.surf_source_write[key] = value def _confidence_intervals_from_xml_element(self, root): - text = get_text(root, "confidence_intervals") + text = get_text(root, 'confidence_intervals') if text is not None: - self.confidence_intervals = text in ("true", "1") + self.confidence_intervals = text in ('true', '1') def _electron_treatment_from_xml_element(self, root): - text = get_text(root, "electron_treatment") + text = get_text(root, 'electron_treatment') if text is not None: self.electron_treatment = text def _energy_mode_from_xml_element(self, root): - text = get_text(root, "energy_mode") + text = get_text(root, 'energy_mode') if text is not None: self.energy_mode = text def _max_order_from_xml_element(self, root): - text = get_text(root, "max_order") + text = get_text(root, 'max_order') if text is not None: self.max_order = int(text) def _photon_transport_from_xml_element(self, root): - text = get_text(root, "photon_transport") + text = get_text(root, 'photon_transport') if text is not None: - self.photon_transport = text in ("true", "1") + self.photon_transport = text in ('true', '1') def _ptables_from_xml_element(self, root): - text = get_text(root, "ptables") + text = get_text(root, 'ptables') if text is not None: - self.ptables = text in ("true", "1") + self.ptables = text in ('true', '1') def _seed_from_xml_element(self, root): - text = get_text(root, "seed") + text = get_text(root, 'seed') if text is not None: self.seed = int(text) def _survival_biasing_from_xml_element(self, root): - text = get_text(root, "survival_biasing") + text = get_text(root, 'survival_biasing') if text is not None: - self.survival_biasing = text in ("true", "1") + self.survival_biasing = text in ('true', '1') def _cutoff_from_xml_element(self, root): - elem = root.find("cutoff") + elem = root.find('cutoff') if elem is not None: self.cutoff = {} - for key in ( - "energy_neutron", - "energy_photon", - "energy_electron", - "energy_positron", - "weight", - "weight_avg", - ): + for key in ('energy_neutron', 'energy_photon', 'energy_electron', + 'energy_positron', 'weight', 'weight_avg'): value = get_text(elem, key) if value is not None: self.cutoff[key] = float(value) def _entropy_mesh_from_xml_element(self, root): - text = get_text(root, "entropy_mesh") + text = get_text(root, 'entropy_mesh') if text is not None: path = f"./mesh[@id='{int(text)}']" elem = root.find(path) @@ -1433,65 +1404,65 @@ class Settings: self.entropy_mesh = RegularMesh.from_xml_element(elem) def _trigger_from_xml_element(self, root): - elem = root.find("trigger") + elem = root.find('trigger') if elem is not None: - self.trigger_active = get_text(elem, "active") in ("true", "1") - text = get_text(elem, "max_batches") + self.trigger_active = get_text(elem, 'active') in ('true', '1') + text = get_text(elem, 'max_batches') if text is not None: self.trigger_max_batches = int(text) - text = get_text(elem, "batch_interval") + text = get_text(elem, 'batch_interval') if text is not None: self.trigger_batch_interval = int(text) def _no_reduce_from_xml_element(self, root): - text = get_text(root, "no_reduce") + text = get_text(root, 'no_reduce') if text is not None: - self.no_reduce = text in ("true", "1") + self.no_reduce = text in ('true', '1') def _verbosity_from_xml_element(self, root): - text = get_text(root, "verbosity") + text = get_text(root, 'verbosity') if text is not None: self.verbosity = int(text) def _tabular_legendre_from_xml_element(self, root): - elem = root.find("tabular_legendre") + elem = root.find('tabular_legendre') if elem is not None: - text = get_text(elem, "enable") - self.tabular_legendre["enable"] = text in ("true", "1") - text = get_text(elem, "num_points") + text = get_text(elem, 'enable') + self.tabular_legendre['enable'] = text in ('true', '1') + text = get_text(elem, 'num_points') if text is not None: - self.tabular_legendre["num_points"] = int(text) + self.tabular_legendre['num_points'] = int(text) def _temperature_from_xml_element(self, root): - text = get_text(root, "temperature_default") + text = get_text(root, 'temperature_default') if text is not None: - self.temperature["default"] = float(text) - text = get_text(root, "temperature_tolerance") + self.temperature['default'] = float(text) + text = get_text(root, 'temperature_tolerance') if text is not None: - self.temperature["tolerance"] = float(text) - text = get_text(root, "temperature_method") + self.temperature['tolerance'] = float(text) + text = get_text(root, 'temperature_method') if text is not None: - self.temperature["method"] = text - text = get_text(root, "temperature_range") + self.temperature['method'] = text + text = get_text(root, 'temperature_range') if text is not None: - self.temperature["range"] = [float(x) for x in text.split()] - text = get_text(root, "temperature_multipole") + self.temperature['range'] = [float(x) for x in text.split()] + text = get_text(root, 'temperature_multipole') if text is not None: - self.temperature["multipole"] = text in ("true", "1") + self.temperature['multipole'] = text in ('true', '1') def _trace_from_xml_element(self, root): - text = get_text(root, "trace") + text = get_text(root, 'trace') if text is not None: self.trace = [int(x) for x in text.split()] def _track_from_xml_element(self, root): - text = get_text(root, "track") + text = get_text(root, 'track') if text is not None: values = [int(x) for x in text.split()] self.track = list(zip(values[::3], values[1::3], values[2::3])) def _ufs_mesh_from_xml_element(self, root): - text = get_text(root, "ufs_mesh") + text = get_text(root, 'ufs_mesh') if text is not None: path = f"./mesh[@id='{int(text)}']" elem = root.find(path) @@ -1499,82 +1470,80 @@ class Settings: self.ufs_mesh = RegularMesh.from_xml_element(elem) def _resonance_scattering_from_xml_element(self, root): - elem = root.find("resonance_scattering") + elem = root.find('resonance_scattering') if elem is not None: - keys = ("enable", "method", "energy_min", "energy_max", "nuclides") + keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides') for key in keys: value = get_text(elem, key) if value is not None: - if key == "enable": - value = value in ("true", "1") - elif key in ("energy_min", "energy_max"): + if key == 'enable': + value = value in ('true', '1') + elif key in ('energy_min', 'energy_max'): value = float(value) - elif key == "nuclides": + elif key == 'nuclides': value = value.split() self.resonance_scattering[key] = value def _create_fission_neutrons_from_xml_element(self, root): - text = get_text(root, "create_fission_neutrons") + text = get_text(root, 'create_fission_neutrons') if text is not None: - self.create_fission_neutrons = text in ("true", "1") + self.create_fission_neutrons = text in ('true', '1') def _delayed_photon_scaling_from_xml_element(self, root): - text = get_text(root, "delayed_photon_scaling") + text = get_text(root, 'delayed_photon_scaling') if text is not None: - self.delayed_photon_scaling = text in ("true", "1") + self.delayed_photon_scaling = text in ('true', '1') def _event_based_from_xml_element(self, root): - text = get_text(root, "event_based") + text = get_text(root, 'event_based') if text is not None: - self.event_based = text in ("true", "1") + self.event_based = text in ('true', '1') def _max_particles_in_flight_from_xml_element(self, root): - text = get_text(root, "max_particles_in_flight") + text = get_text(root, 'max_particles_in_flight') if text is not None: self.max_particles_in_flight = int(text) def _material_cell_offsets_from_xml_element(self, root): - text = get_text(root, "material_cell_offsets") + text = get_text(root, 'material_cell_offsets') if text is not None: - self.material_cell_offsets = text in ("true", "1") + self.material_cell_offsets = text in ('true', '1') def _log_grid_bins_from_xml_element(self, root): - text = get_text(root, "log_grid_bins") + text = get_text(root, 'log_grid_bins') if text is not None: self.log_grid_bins = int(text) def _write_initial_source_from_xml_element(self, root): - text = get_text(root, "write_initial_source") + text = get_text(root, 'write_initial_source') if text is not None: - self.write_initial_source = text in ("true", "1") + self.write_initial_source = text in ('true', '1') def _weight_windows_from_xml_element(self, root): - for elem in root.findall("weight_windows"): + for elem in root.findall('weight_windows'): ww = WeightWindows.from_xml_element(elem, root) self.weight_windows.append(ww) - text = get_text(root, "weight_windows_on") + text = get_text(root, 'weight_windows_on') if text is not None: - self.weight_windows_on = text in ("true", "1") + self.weight_windows_on = text in ('true', '1') def _max_splits_from_xml_element(self, root): - text = get_text(root, "max_splits") + text = get_text(root, 'max_splits') if text is not None: self.max_splits = int(text) def _max_tracks_from_xml_element(self, root): - text = get_text(root, "max_tracks") + text = get_text(root, 'max_tracks') if text is not None: self.max_tracks = int(text) - def export_to_xml(self, path: PathLike = "settings.xml"): + def export_to_xml(self, path: PathLike = 'settings.xml'): """Export simulation settings to an XML file. - Parameters ---------- path : str Path to file to write. Defaults to 'settings.xml'. - """ # Reset xml element tree @@ -1631,29 +1600,25 @@ class Settings: # Check if path is a directory p = Path(path) if p.is_dir(): - p /= "settings.xml" + p /= 'settings.xml' # Write the XML Tree to the settings.xml file reorder_attributes(root_element) # TODO: Remove when support is Python 3.8+ tree = ET.ElementTree(root_element) - tree.write(str(p), xml_declaration=True, encoding="utf-8") + tree.write(str(p), xml_declaration=True, encoding='utf-8') @classmethod - def from_xml(cls, path: PathLike = "settings.xml"): + def from_xml(cls, path: PathLike = 'settings.xml'): """Generate settings from XML file - .. versionadded:: 0.13.0 - Parameters ---------- path : str, optional Path to settings XML file - Returns ------- openmc.Settings Settings object - """ tree = ET.parse(path) root = tree.getroot() @@ -1707,4 +1672,4 @@ class Settings: # TODO: Get volume calculations - return settings + return settings \ No newline at end of file From f6a7b61c4a64f18165608c4114570e6ca8b061ec Mon Sep 17 00:00:00 2001 From: josh Date: Sun, 30 Oct 2022 03:31:26 +0000 Subject: [PATCH 1229/2654] address a few more formatting issues --- openmc/settings.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index f13b233de..e48c0d3ad 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1540,10 +1540,12 @@ class Settings: def export_to_xml(self, path: PathLike = 'settings.xml'): """Export simulation settings to an XML file. + Parameters ---------- path : str Path to file to write. Defaults to 'settings.xml'. + """ # Reset xml element tree @@ -1610,15 +1612,19 @@ class Settings: @classmethod def from_xml(cls, path: PathLike = 'settings.xml'): """Generate settings from XML file + .. versionadded:: 0.13.0 + Parameters ---------- path : str, optional Path to settings XML file + Returns ------- openmc.Settings Settings object + """ tree = ET.parse(path) root = tree.getroot() @@ -1672,4 +1678,4 @@ class Settings: # TODO: Get volume calculations - return settings \ No newline at end of file + return settings From 375af321d89fa5b4af812d73b496639090269a38 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 1 Nov 2022 15:49:22 +0000 Subject: [PATCH 1230/2654] corrected types from code review by @paulromano Co-authored-by: Paul Romano --- openmc/source.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/source.py b/openmc/source.py index d886e9891..9293a5953 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -4,7 +4,7 @@ from numbers import Real import warnings import typing # imported separately as py3.8 requires typing.Iterable # also required to prevent typing.Union namespace overwriting Union -from typing import Optional +from typing import Optional, Sequence from xml.etree import ElementTree as ET import numpy as np @@ -77,7 +77,7 @@ class Source: def __init__( self, space: Optional[openmc.stats.Spatial] = None, - angle: Optional[openmc.stats.Spatial] = None, + angle: Optional[openmc.stats.UnitSphere] = None, energy: Optional[openmc.stats.Univariate] = None, time: Optional[openmc.stats.Univariate] = None, filename: Optional[str] = None, @@ -85,7 +85,7 @@ class Source: parameters: Optional[str] = None, strength: float = 1.0, particle: str = 'neutron', - domains: Optional[typing.Union[openmc.Cell, openmc.Material, openmc.Universe]] = None + domains: Optional[Sequence[typing.Union[openmc.Cell, openmc.Material, openmc.Universe]]] = None ): self._space = None self._angle = None From 81b88cc018b17156bf08213a0e1348517ec8d428 Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 2 Nov 2022 02:23:37 +0000 Subject: [PATCH 1231/2654] Clean up comparisons and lump test cross sections --- src/nuclide.cpp | 6 ++--- src/thermal.cpp | 6 +++-- tests/unit_tests/test_temp_interp.py | 35 ++++++++++------------------ 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/nuclide.cpp b/src/nuclide.cpp index 4c1706509..134e2d6b9 100644 --- a/src/nuclide.cpp +++ b/src/nuclide.cpp @@ -171,14 +171,14 @@ Nuclide::Nuclide(hid_t group, const vector& temperature) if (!found_pair) { // If no pairs found, check if the desired temperature falls just // outside of data - if (T_desired - temps_available.front() <= - -settings::temperature_tolerance) { + if (std::abs(T_desired - temps_available.front()) <= + settings::temperature_tolerance) { if (!contains(temps_to_read, temps_available.front())) { temps_to_read.push_back(std::round(temps_available.front())); } break; } - if (T_desired - temps_available.back() <= + if (std::abs(T_desired - temps_available.back()) <= settings::temperature_tolerance) { if (!contains(temps_to_read, temps_available.back())) { temps_to_read.push_back(std::round(temps_available.back())); diff --git a/src/thermal.cpp b/src/thermal.cpp index 66e1fb009..b54f07b36 100644 --- a/src/thermal.cpp +++ b/src/thermal.cpp @@ -119,11 +119,13 @@ ThermalScattering::ThermalScattering( if (!found) { // If no pairs found, check if the desired temperature falls within // bounds' tolerance - if (T - temps_available[0] <= -settings::temperature_tolerance) { + if (std::abs(T - temps_available[0]) <= + settings::temperature_tolerance) { temps_to_read.push_back(std::round(temps_available[0])); break; } - if (T - temps_available[n - 1] <= settings::temperature_tolerance) { + if (std::abs(T - temps_available[n - 1]) <= + settings::temperature_tolerance) { temps_to_read.push_back(std::round(temps_available[n - 1])); break; } diff --git a/tests/unit_tests/test_temp_interp.py b/tests/unit_tests/test_temp_interp.py index c64ebe46a..a28aafb6f 100644 --- a/tests/unit_tests/test_temp_interp.py +++ b/tests/unit_tests/test_temp_interp.py @@ -10,7 +10,7 @@ import pytest def make_fake_cross_section(): - """Create fake U235 nuclide + """Create fake U235 nuclide with a fake thermal scattering library attached This nuclide is designed to have k_inf=1 at 300 K, k_inf=2 at 600 K, and k_inf=1 at 900 K. The absorption cross section is also constant with @@ -81,16 +81,9 @@ def make_fake_cross_section(): # Export HDF5 file u235_fake.export_to_hdf5('U235_fake.h5', 'w') - lib = openmc.data.DataLibrary() - lib.register_file('U235_fake.h5') - lib.export_to_xml('cross_sections_fake.xml') - - -def fake_thermal_scattering(): - """Create a fake thermal scattering library for U-235 at 294K and 600K - """ - fake_tsl = openmc.data.ThermalScattering("c_U_fake", 1.9968, 4.9, [0.0253]) - fake_tsl.nuclides = ['U235'] + # Create a fake thermal scattering library attached to the fake U235 data + c_U_fake = openmc.data.ThermalScattering("c_U_fake", 1.9968, 4.9, [0.0253]) + c_U_fake.nuclides = ['U235'] # Create elastic reaction bragg_edges = [0.00370672, 0.00494229] @@ -110,7 +103,7 @@ def fake_thermal_scattering(): '294K': openmc.data.MixedElasticAE(coherent_dist, incoherent_dist_294), '600K': openmc.data.MixedElasticAE(coherent_dist, incoherent_dist_600) } - fake_tsl.elastic = openmc.data.ThermalScatteringReaction(elastic_xs, elastic_dist) + c_U_fake.elastic = openmc.data.ThermalScatteringReaction(elastic_xs, elastic_dist) # Create inelastic reaction inelastic_xs = { @@ -135,19 +128,16 @@ def fake_thermal_scattering(): breakpoints, interpolation, energy, energy_out, mu) inelastic_dist = {'294K': dist, '600K': dist} inelastic = openmc.data.ThermalScatteringReaction(inelastic_xs, inelastic_dist) - fake_tsl.inelastic = inelastic + c_U_fake.inelastic = inelastic - return fake_tsl - - -def edit_fake_cross_sections(): - """Edit the test cross sections xml to include fake thermal scattering data - """ - lib = openmc.data.DataLibrary.from_xml("cross_sections_fake.xml") - c_U_fake = fake_thermal_scattering() + # Export HDF5 file c_U_fake.export_to_hdf5("c_U_fake.h5") + + # Create a data library of the fake nuclide and its thermal scattering data + lib = openmc.data.DataLibrary() + lib.register_file('U235_fake.h5') lib.register_file("c_U_fake.h5") - lib.export_to_xml("cross_sections_fake.xml") + lib.export_to_xml('cross_sections_fake.xml') @pytest.fixture(scope='module') @@ -223,7 +213,6 @@ def test_interpolation(model, method, temperature, fission_expected, tolerance): def test_temperature_interpolation_tolerance(model): """Test applying global and cell temperatures with thermal scattering libraries """ - edit_fake_cross_sections() model.materials[0].add_s_alpha_beta("c_U_fake") # Default k-effective, using the thermal scattering data's minimum available temperature From 235195b12522824e5f887875c4d5fa9024057a4f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 2 Nov 2022 12:20:50 +0000 Subject: [PATCH 1232/2654] Changed comment to reference 2020 atomic data version. Co-authored-by: Paul Romano --- openmc/data/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index fcdafede7..55bfb4f09 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -223,7 +223,7 @@ def atomic_mass(isotope): """ if not _ATOMIC_MASS: - # Load data from AME2020 file, Note format change to AME2016 + # Load data from AME2020 file mass_file = os.path.join(os.path.dirname(__file__), 'mass_1.mas20.txt') with open(mass_file, 'r') as ame: # Read lines in file starting at line 37 From fd516c1c4cca06889e6bcfae664017984a0d64ef Mon Sep 17 00:00:00 2001 From: Hunter Belanger Date: Thu, 3 Nov 2022 18:55:06 +0100 Subject: [PATCH 1233/2654] Doctors the incoherent inelastic TSL data when in continuous format. --- openmc/data/thermal.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index 7e66b6319..44010a0b0 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -670,12 +670,41 @@ class ThermalScattering(EqualityMixin): mu_i = [] for j in range(n_energy_out[i]): mu = ace.xss[idx + 4:idx + 4 + n_mu] + # The equiprobable angles produced by NJOY are not always + # sorted. This is problematic when the smearing algorithm + # is applied when sampling the angles. We sort the angles + # here, because they are equiprobable, so the order + # doesn't mater. + mu.sort() p_mu = 1. / n_mu * np.ones(n_mu) mu_ij = Discrete(mu, p_mu) mu_ij.c = np.cumsum(p_mu) mu_i.append(mu_ij) idx += 3 + n_mu + # Check if the CDF for the outgoing energy distribution starts + # at 0. For NJOY and FRENDY evaluations, this is never the case, + # and can very rarely lead to negative energies when sampling + # the outgoing energy. From Eq. 7.6 of the ENDF manual, we can + # add the outgoing energy 0 eV, which has a PDF of 0 (and of + # course, a CDF of 0 as well). + if eout_i.c[0] > 0.: + eout_i.x = np.insert(eout_i.x, 0, 0.) + eout_i.p = np.insert(eout_i.p, 0, 0.) + eout_i.c = np.insert(eout_i.c, 0, 0.) + + # For this added outgoing energy (of 0 eV) we add a set of + # isotropic discrete angles. + dmu = 2. / n_mu + mu = np.linsace(-1. + 0.5*dmu, 1. - 0.5*dmu, n_mu) + p_mu = 1. / n_mu * np.ones(n_mu) + mu_0 = Discrete(mu, p_mu) + mu_0.c = np.cumsum(p_mu) + mu_i.insert(0, mu_0) + # We don't worry about renormalizing the outgoing energy PDF/CDF + # after this manipulation, because it never seems to be + # normalized to begin with (at least with NJOY). + energy_out.append(eout_i) mu_out.append(mu_i) From 6cb7a178e8018a2376a3488320239d2c5f2862e6 Mon Sep 17 00:00:00 2001 From: Hunter Belanger Date: Thu, 3 Nov 2022 19:09:28 +0100 Subject: [PATCH 1234/2654] Fix spelling error. --- openmc/data/thermal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index 44010a0b0..12e666cdc 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -696,7 +696,7 @@ class ThermalScattering(EqualityMixin): # For this added outgoing energy (of 0 eV) we add a set of # isotropic discrete angles. dmu = 2. / n_mu - mu = np.linsace(-1. + 0.5*dmu, 1. - 0.5*dmu, n_mu) + mu = np.linspace(-1. + 0.5*dmu, 1. - 0.5*dmu, n_mu) p_mu = 1. / n_mu * np.ones(n_mu) mu_0 = Discrete(mu, p_mu) mu_0.c = np.cumsum(p_mu) From 647c9d185ea5d7a7be652da9fe22ebd5363f3ea5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Nov 2022 13:26:13 -0500 Subject: [PATCH 1235/2654] Update include/openmc/cell.h --- include/openmc/cell.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 248c2b23d..39acaf067 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -58,7 +58,7 @@ public: //---------------------------------------------------------------------------- // Constructors Region() {} - explicit Region(std::string region_expressioni, int32_t cell_id); + explicit Region(std::string region_spec, int32_t cell_id); //---------------------------------------------------------------------------- // Methods From 89fafb4fdff9fd00ebad6161beef36189308054c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 26 Oct 2022 13:20:53 +0000 Subject: [PATCH 1236/2654] Improving missing material error for DAGMC material by ID --- src/dagmc.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 0e04869fd..b06db792e 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -486,13 +486,20 @@ void DAGUniverse::legacy_assign_material( // if no material was set using a name, assign by id if (!mat_found_by_name) { + bool found_by_id = true; try { auto id = std::stoi(mat_string); + if (model::material_map.find(id) == model::material_map.end()) + found_by_id = false; c->material_.emplace_back(id); } catch (const std::invalid_argument&) { + found_by_id = false; + } + + // report failure for failed int conversion or missing material + if (!found_by_id) fatal_error(fmt::format( "No material '{}' found for volume (cell) {}", mat_string, c->id_)); - } } if (settings::verbosity >= 10) { From 075ff0304c8acc6b5907387ba919b44f4737aa2e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 26 Oct 2022 14:10:16 +0000 Subject: [PATCH 1237/2654] Adding tests for expected error messages --- tests/regression_tests/dagmc/legacy/test.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index 91734a219..706b52bea 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -11,6 +11,7 @@ pytestmark = pytest.mark.skipif( @pytest.fixture def model(): + openmc.reset_auto_ids() model = openmc.model.Model() @@ -56,6 +57,24 @@ def model(): return model +def test_missing_material_id(model): + # remove the last material, which is identified by ID in the DAGMC file + model.materials = model.materials[:-1] + with pytest.raises(RuntimeError) as exec_info: + model.run() + exp_error_msg = "Material with ID '41' not found for volume (cell) 3" + assert exp_error_msg in str(exec_info.value) + + +def test_missing_material_name(model): + # remove the first material, which is identified by name in the DAGMC file + model.materials = model.materials[1:] + with pytest.raises(RuntimeError) as exec_info: + model.run() + exp_error_msg = "No material 'no-void fuel' found for volume (cell) 1" + assert exp_error_msg in str(exec_info.value) + + def test_dagmc(model): harness = PyAPITestHarness('statepoint.5.h5', model) harness.main() From 7266fcc5edc11816f2ea010dfb896dc1af0a0e50 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 26 Oct 2022 22:06:28 +0000 Subject: [PATCH 1238/2654] Making error messages consistent --- src/dagmc.cpp | 5 +++-- tests/regression_tests/dagmc/legacy/test.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index b06db792e..129291891 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -498,8 +498,9 @@ void DAGUniverse::legacy_assign_material( // report failure for failed int conversion or missing material if (!found_by_id) - fatal_error(fmt::format( - "No material '{}' found for volume (cell) {}", mat_string, c->id_)); + fatal_error( + fmt::format("Material with name/ID '{}' not found for volume (cell) {}", + mat_string, c->id_)); } if (settings::verbosity >= 10) { diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index 706b52bea..502775148 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -62,7 +62,7 @@ def test_missing_material_id(model): model.materials = model.materials[:-1] with pytest.raises(RuntimeError) as exec_info: model.run() - exp_error_msg = "Material with ID '41' not found for volume (cell) 3" + exp_error_msg = "Material with name/ID '41' not found for volume (cell) 3" assert exp_error_msg in str(exec_info.value) @@ -71,7 +71,7 @@ def test_missing_material_name(model): model.materials = model.materials[1:] with pytest.raises(RuntimeError) as exec_info: model.run() - exp_error_msg = "No material 'no-void fuel' found for volume (cell) 1" + exp_error_msg = "Material with name/ID 'no-void fuel' not found for volume (cell) 1" assert exp_error_msg in str(exec_info.value) From 6a0d5043030cffd791b0500e6eecdf11be3fb02b Mon Sep 17 00:00:00 2001 From: Hunter Belanger Date: Sat, 5 Nov 2022 13:05:47 +0100 Subject: [PATCH 1239/2654] Fix wording of comments --- openmc/data/thermal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index 12e666cdc..e6213e5f0 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -674,7 +674,7 @@ class ThermalScattering(EqualityMixin): # sorted. This is problematic when the smearing algorithm # is applied when sampling the angles. We sort the angles # here, because they are equiprobable, so the order - # doesn't mater. + # doesn't matter. mu.sort() p_mu = 1. / n_mu * np.ones(n_mu) mu_ij = Discrete(mu, p_mu) @@ -686,7 +686,7 @@ class ThermalScattering(EqualityMixin): # at 0. For NJOY and FRENDY evaluations, this is never the case, # and can very rarely lead to negative energies when sampling # the outgoing energy. From Eq. 7.6 of the ENDF manual, we can - # add the outgoing energy 0 eV, which has a PDF of 0 (and of + # add an outgoing energy 0 eV that has a PDF of 0 (and of # course, a CDF of 0 as well). if eout_i.c[0] > 0.: eout_i.x = np.insert(eout_i.x, 0, 0.) From b469b3a16981269ca7202c070058587f78c2a542 Mon Sep 17 00:00:00 2001 From: myerspat Date: Sat, 5 Nov 2022 13:50:27 -0400 Subject: [PATCH 1240/2654] Added alias sampling to discrete distribution --- include/openmc/distribution.h | 4 +++ src/distribution.cpp | 58 ++++++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index d3fe958ca..de1664275 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -52,6 +52,10 @@ public: private: vector x_; //!< Possible outcomes vector p_; //!< Probability of each outcome + + //! Alies method tables + vector prob_; + vector alias_; //! Normalize distribution so that probabilities sum to unity void normalize(); diff --git a/src/distribution.cpp b/src/distribution.cpp index 6bf51df6a..29cf4014a 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -36,20 +36,62 @@ Discrete::Discrete(const double* x, const double* p, int n) : x_ {x, x + n}, p_ {p, p + n} { normalize(); + + // Vectors for large and small probabilities based on 1/n + vector large; + vector small; + + // Set and allocate memory + prob_ = p_; + alias_.reserve(n); + + // Fill large and small vectors based on 1/n + for (int i = 0; i < n; i++) { + prob_[i] *= n; + if (prob_[i] > 1.0) { + large.push_back(i); + } else { + small.push_back(i); + } + } + + while (!large.empty() && !small.empty()) { + int j = small.back(); + int k = large.back(); + + // Update probability and alias based on Vose's algorithm + prob_[k] += prob_[j] - 1; + alias_[j] = k; + + // Remove last vector element and or move large index to small vector + if (prob_[k] < 1) { + small.push_back(k); + large.pop_back(); + } else { + small.pop_back(); + } + } } double Discrete::sample(uint64_t* seed) const { - int n = x_.size(); + int n = prob_.size(); if (n > 1) { - double xi = prn(seed); - double c = 0.0; - for (int i = 0; i < n; ++i) { - c += p_[i]; - if (xi < c) - return x_[i]; + int u = prn(seed) * n; + if (prn(seed) < prob_[u]) { + return x_[u]; + } else { + return x_[alias_[u]]; } - throw std::runtime_error {"Error when sampling probability mass function."}; + + // double xi = prn(seed); + // double c = 0.0; + // for (int i = 0; i < n; ++i) { + // c += p_[i]; + // if (xi < c) + // return x_[i]; + // } + // throw std::runtime_error {"Error when sampling probability mass function."}; } else { return x_[0]; } From 20718f512184c6700281da67522fe6b74793bae9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 5 Nov 2022 20:32:44 -0500 Subject: [PATCH 1241/2654] Adding enumerator for filter types. --- include/openmc/tallies/filter.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/openmc/tallies/filter.h b/include/openmc/tallies/filter.h index 2eecfe0e4..810ff371d 100644 --- a/include/openmc/tallies/filter.h +++ b/include/openmc/tallies/filter.h @@ -17,6 +17,33 @@ namespace openmc { +enum class FilterType { + AZIMUTHAL = 0, + CELLBORN, + CELLFROM, + CELL, + CELL_INSTANCE, + COLLISION, + DELAYEDGROUP, + DISTRIBCELL, + ENERGYFUNC, + ENERGY, + LEGENDRE, + MATCH, + MATERIAL, + MESH, + MESHSURFACE, + MU, + PARTICLE, + POLAR, + SPH_HARM, + SPTL_LEGENDRE, + SURFACE, + TIME, + UNIVERSE, + ZERNIKE, +}; + //============================================================================== //! Modifies tally score events. //============================================================================== From 06fbf3fe014a1296dbc69ae8f8950fb945594039 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 5 Nov 2022 21:14:59 -0500 Subject: [PATCH 1242/2654] Switch to use of FilterType enum for comparisons --- include/openmc/tallies/filter.h | 18 ++++++++++-------- include/openmc/tallies/filter_azimuthal.h | 3 ++- include/openmc/tallies/filter_cell.h | 3 ++- include/openmc/tallies/filter_cell_instance.h | 3 ++- include/openmc/tallies/filter_cellborn.h | 3 ++- include/openmc/tallies/filter_cellfrom.h | 3 ++- include/openmc/tallies/filter_collision.h | 3 ++- include/openmc/tallies/filter_delayedgroup.h | 3 ++- include/openmc/tallies/filter_distribcell.h | 3 ++- include/openmc/tallies/filter_energy.h | 6 ++++-- include/openmc/tallies/filter_energyfunc.h | 3 ++- include/openmc/tallies/filter_legendre.h | 3 ++- include/openmc/tallies/filter_material.h | 3 ++- include/openmc/tallies/filter_mesh.h | 3 ++- include/openmc/tallies/filter_meshsurface.h | 3 ++- include/openmc/tallies/filter_mu.h | 3 ++- include/openmc/tallies/filter_particle.h | 3 ++- include/openmc/tallies/filter_polar.h | 3 ++- include/openmc/tallies/filter_sph_harm.h | 3 ++- include/openmc/tallies/filter_sptl_legendre.h | 3 ++- include/openmc/tallies/filter_surface.h | 3 ++- include/openmc/tallies/filter_time.h | 3 ++- include/openmc/tallies/filter_universe.h | 3 ++- include/openmc/tallies/filter_zernike.h | 6 ++++-- src/state_point.cpp | 2 +- src/tallies/filter.cpp | 2 +- src/tallies/filter_cell.cpp | 2 +- src/tallies/filter_mesh.cpp | 8 +++++--- src/tallies/tally.cpp | 12 +++++++----- 29 files changed, 75 insertions(+), 44 deletions(-) diff --git a/include/openmc/tallies/filter.h b/include/openmc/tallies/filter.h index 810ff371d..104a55e47 100644 --- a/include/openmc/tallies/filter.h +++ b/include/openmc/tallies/filter.h @@ -24,24 +24,25 @@ enum class FilterType { CELL, CELL_INSTANCE, COLLISION, - DELAYEDGROUP, + DELAYED_GROUP, DISTRIBCELL, - ENERGYFUNC, + ENERGY_FUNCTION, ENERGY, + ENERGY_OUT, LEGENDRE, - MATCH, MATERIAL, MESH, - MESHSURFACE, + MESH_SURFACE, MU, PARTICLE, POLAR, - SPH_HARM, - SPTL_LEGENDRE, + SPHERICAL_HARMONICS, + SPATIAL_LEGENDRE, SURFACE, TIME, UNIVERSE, ZERNIKE, + ZERNIKE_RADIAL }; //============================================================================== @@ -85,7 +86,8 @@ public: //---------------------------------------------------------------------------- // Methods - virtual std::string type() const = 0; + virtual std::string type_str() const = 0; + virtual FilterType type() const = 0; //! Matches a tally event to a set of filter bins and weights. //! @@ -99,7 +101,7 @@ public: //! Writes data describing this filter to an HDF5 statepoint group. virtual void to_statepoint(hid_t filter_group) const { - write_dataset(filter_group, "type", type()); + write_dataset(filter_group, "type", type_str()); write_dataset(filter_group, "n_bins", n_bins_); } diff --git a/include/openmc/tallies/filter_azimuthal.h b/include/openmc/tallies/filter_azimuthal.h index 2272b500a..37e1ef073 100644 --- a/include/openmc/tallies/filter_azimuthal.h +++ b/include/openmc/tallies/filter_azimuthal.h @@ -24,7 +24,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "azimuthal"; } + std::string type_str() const override { return "azimuthal"; } + FilterType type() const override { return FilterType::AZIMUTHAL; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_cell.h b/include/openmc/tallies/filter_cell.h index 46d89811d..b7ea01ce6 100644 --- a/include/openmc/tallies/filter_cell.h +++ b/include/openmc/tallies/filter_cell.h @@ -25,7 +25,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "cell"; } + std::string type_str() const override { return "cell"; } + FilterType type() const override { return FilterType::CELL; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_cell_instance.h b/include/openmc/tallies/filter_cell_instance.h index 4de3fcd29..f500f4889 100644 --- a/include/openmc/tallies/filter_cell_instance.h +++ b/include/openmc/tallies/filter_cell_instance.h @@ -28,7 +28,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "cellinstance"; } + std::string type_str() const override { return "cellinstance"; } + FilterType type() const override { return FilterType::CELL_INSTANCE; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_cellborn.h b/include/openmc/tallies/filter_cellborn.h index 282854020..17102d971 100644 --- a/include/openmc/tallies/filter_cellborn.h +++ b/include/openmc/tallies/filter_cellborn.h @@ -16,7 +16,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "cellborn"; } + std::string type_str() const override { return "cellborn"; } + FilterType type() const override { return FilterType::CELLBORN; } void get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match) const override; diff --git a/include/openmc/tallies/filter_cellfrom.h b/include/openmc/tallies/filter_cellfrom.h index 47abd0353..61ff50b05 100644 --- a/include/openmc/tallies/filter_cellfrom.h +++ b/include/openmc/tallies/filter_cellfrom.h @@ -16,7 +16,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "cellfrom"; } + std::string type_str() const override { return "cellfrom"; } + FilterType type() const override { return FilterType::CELLFROM; } void get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match) const override; diff --git a/include/openmc/tallies/filter_collision.h b/include/openmc/tallies/filter_collision.h index 3724b06cf..d2dab70ca 100644 --- a/include/openmc/tallies/filter_collision.h +++ b/include/openmc/tallies/filter_collision.h @@ -23,7 +23,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "collision"; } + std::string type_str() const override { return "collision"; } + FilterType type() const override { return FilterType::COLLISION; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_delayedgroup.h b/include/openmc/tallies/filter_delayedgroup.h index 72ffa1db5..71919b2ec 100644 --- a/include/openmc/tallies/filter_delayedgroup.h +++ b/include/openmc/tallies/filter_delayedgroup.h @@ -25,7 +25,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "delayedgroup"; } + std::string type_str() const override { return "delayedgroup"; } + FilterType type() const override { return FilterType::DELAYED_GROUP; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_distribcell.h b/include/openmc/tallies/filter_distribcell.h index d72ae022f..b5cdcce84 100644 --- a/include/openmc/tallies/filter_distribcell.h +++ b/include/openmc/tallies/filter_distribcell.h @@ -21,7 +21,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "distribcell"; } + std::string type_str() const override { return "distribcell"; } + FilterType type() const override { return FilterType::DISTRIBCELL; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_energy.h b/include/openmc/tallies/filter_energy.h index 000aaa28b..e35e01a6d 100644 --- a/include/openmc/tallies/filter_energy.h +++ b/include/openmc/tallies/filter_energy.h @@ -22,7 +22,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "energy"; } + std::string type_str() const override { return "energy"; } + FilterType type() const override { return FilterType::ENERGY; } void from_xml(pugi::xml_node node) override; @@ -63,7 +64,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "energyout"; } + std::string type_str() const override { return "energyout"; } + FilterType type() const override { return FilterType::ENERGY_OUT; } void get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match) const override; diff --git a/include/openmc/tallies/filter_energyfunc.h b/include/openmc/tallies/filter_energyfunc.h index 373fee8dd..d77ef0fa8 100644 --- a/include/openmc/tallies/filter_energyfunc.h +++ b/include/openmc/tallies/filter_energyfunc.h @@ -24,7 +24,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "energyfunction"; } + std::string type_str() const override { return "energyfunction"; } + FilterType type() const override { return FilterType::ENERGY_FUNCTION; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_legendre.h b/include/openmc/tallies/filter_legendre.h index b1fac37c8..839fd77bf 100644 --- a/include/openmc/tallies/filter_legendre.h +++ b/include/openmc/tallies/filter_legendre.h @@ -21,7 +21,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "legendre"; } + std::string type_str() const override { return "legendre"; } + FilterType type() const override { return FilterType::LEGENDRE; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_material.h b/include/openmc/tallies/filter_material.h index f58fc9938..5da556d5e 100644 --- a/include/openmc/tallies/filter_material.h +++ b/include/openmc/tallies/filter_material.h @@ -25,7 +25,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "material"; } + std::string type_str() const override { return "material"; } + FilterType type() const override { return FilterType::MATERIAL; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_mesh.h b/include/openmc/tallies/filter_mesh.h index ef055b1a2..e3bcd7c20 100644 --- a/include/openmc/tallies/filter_mesh.h +++ b/include/openmc/tallies/filter_mesh.h @@ -24,7 +24,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "mesh"; } + std::string type_str() const override { return "mesh"; } + FilterType type() const override { return FilterType::MESH; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_meshsurface.h b/include/openmc/tallies/filter_meshsurface.h index 28f4e265f..195995c69 100644 --- a/include/openmc/tallies/filter_meshsurface.h +++ b/include/openmc/tallies/filter_meshsurface.h @@ -10,7 +10,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "meshsurface"; } + std::string type_str() const override { return "meshsurface"; } + FilterType type() const override { return FilterType::MESH_SURFACE; } void get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match) const override; diff --git a/include/openmc/tallies/filter_mu.h b/include/openmc/tallies/filter_mu.h index 5299f6dd4..942ee60c2 100644 --- a/include/openmc/tallies/filter_mu.h +++ b/include/openmc/tallies/filter_mu.h @@ -23,7 +23,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "mu"; } + std::string type_str() const override { return "mu"; } + FilterType type() const override { return FilterType::MU; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_particle.h b/include/openmc/tallies/filter_particle.h index cd4c5d413..a181d5cee 100644 --- a/include/openmc/tallies/filter_particle.h +++ b/include/openmc/tallies/filter_particle.h @@ -21,7 +21,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "particle"; } + std::string type_str() const override { return "particle"; } + FilterType type() const override { return FilterType::PARTICLE; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_polar.h b/include/openmc/tallies/filter_polar.h index e06aca1e0..78bb25aa4 100644 --- a/include/openmc/tallies/filter_polar.h +++ b/include/openmc/tallies/filter_polar.h @@ -24,7 +24,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "polar"; } + std::string type_str() const override { return "polar"; } + FilterType type() const override { return FilterType::POLAR; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_sph_harm.h b/include/openmc/tallies/filter_sph_harm.h index 5f5bf84f2..5d4a4bd99 100644 --- a/include/openmc/tallies/filter_sph_harm.h +++ b/include/openmc/tallies/filter_sph_harm.h @@ -25,7 +25,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "sphericalharmonics"; } + std::string type_str() const override { return "sphericalharmonics"; } + FilterType type() const override { return FilterType::SPHERICAL_HARMONICS; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_sptl_legendre.h b/include/openmc/tallies/filter_sptl_legendre.h index d6ac24668..b6c380e9b 100644 --- a/include/openmc/tallies/filter_sptl_legendre.h +++ b/include/openmc/tallies/filter_sptl_legendre.h @@ -23,7 +23,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "spatiallegendre"; } + std::string type_str() const override { return "spatiallegendre"; } + FilterType type() const override { return FilterType::SPATIAL_LEGENDRE; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_surface.h b/include/openmc/tallies/filter_surface.h index 358963fde..3537f1cc7 100644 --- a/include/openmc/tallies/filter_surface.h +++ b/include/openmc/tallies/filter_surface.h @@ -25,7 +25,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "surface"; } + std::string type_str() const override { return "surface"; } + FilterType type() const override { return FilterType::SURFACE; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_time.h b/include/openmc/tallies/filter_time.h index c66481c57..105ef9880 100644 --- a/include/openmc/tallies/filter_time.h +++ b/include/openmc/tallies/filter_time.h @@ -22,7 +22,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "time"; } + std::string type_str() const override { return "time"; } + FilterType type() const override { return FilterType::TIME; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_universe.h b/include/openmc/tallies/filter_universe.h index fde0b6397..d4894353b 100644 --- a/include/openmc/tallies/filter_universe.h +++ b/include/openmc/tallies/filter_universe.h @@ -25,7 +25,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "universe"; } + std::string type_str() const override { return "universe"; } + FilterType type() const override { return FilterType::UNIVERSE; } void from_xml(pugi::xml_node node) override; diff --git a/include/openmc/tallies/filter_zernike.h b/include/openmc/tallies/filter_zernike.h index 72c47e654..b6d9c91e6 100644 --- a/include/openmc/tallies/filter_zernike.h +++ b/include/openmc/tallies/filter_zernike.h @@ -21,7 +21,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "zernike"; } + std::string type_str() const override { return "zernike"; } + FilterType type() const override { return FilterType::ZERNIKE; } void from_xml(pugi::xml_node node) override; @@ -72,7 +73,8 @@ public: //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "zernikeradial"; } + std::string type_str() const override { return "zernikeradial"; } + FilterType type() const override { return FilterType::ZERNIKE_RADIAL; } void get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match) const override; diff --git a/src/state_point.cpp b/src/state_point.cpp index 470dd7718..4170421be 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -804,7 +804,7 @@ void write_unstructured_mesh_results() vector tally_scores; for (auto filter_idx : tally->filters()) { auto& filter = model::tally_filters[filter_idx]; - if (filter->type() != "mesh") + if (filter->type() != FilterType::MESH) continue; // check if the filter uses an unstructured mesh diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index a1e5c709f..a121299fe 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -232,7 +232,7 @@ extern "C" int openmc_filter_get_type(int32_t index, char* type) if (int err = verify_filter(index)) return err; - std::strcpy(type, model::tally_filters[index]->type().c_str()); + std::strcpy(type, model::tally_filters[index]->type_str().c_str()); return 0; } diff --git a/src/tallies/filter_cell.cpp b/src/tallies/filter_cell.cpp index 9ccae6b48..794d2ae08 100644 --- a/src/tallies/filter_cell.cpp +++ b/src/tallies/filter_cell.cpp @@ -80,7 +80,7 @@ extern "C" int openmc_cell_filter_get_bins( return err; const auto& filt = model::tally_filters[index].get(); - if (filt->type() != "cell") { + if (filt->type() != FilterType::CELL) { set_errmsg("Tried to get cells from a non-cell filter."); return OPENMC_E_INVALID_TYPE; } diff --git a/src/tallies/filter_mesh.cpp b/src/tallies/filter_mesh.cpp index 3f895b4f8..deb143346 100644 --- a/src/tallies/filter_mesh.cpp +++ b/src/tallies/filter_mesh.cpp @@ -16,7 +16,7 @@ void MeshFilter::from_xml(pugi::xml_node node) auto bins_ = get_node_array(node, "bins"); if (bins_.size() != 1) { fatal_error( - "Only one mesh can be specified per " + type() + " mesh filter."); + "Only one mesh can be specified per " + type_str() + " mesh filter."); } auto id = bins_[0]; @@ -158,7 +158,8 @@ extern "C" int openmc_mesh_filter_get_translation( // Check the filter type const auto& filter = model::tally_filters[index]; - if (filter->type() != "mesh" && filter->type() != "meshsurface") { + if (filter->type() != FilterType::MESH && + filter->type() != FilterType::MESH_SURFACE) { set_errmsg("Tried to get a translation from a non-mesh-based filter."); return OPENMC_E_INVALID_TYPE; } @@ -182,7 +183,8 @@ extern "C" int openmc_mesh_filter_set_translation( const auto& filter = model::tally_filters[index]; // Check the filter type - if (filter->type() != "mesh" && filter->type() != "meshsurface") { + if (filter->type() != FilterType::MESH && + filter->type() != FilterType::MESH_SURFACE) { set_errmsg("Tried to set mesh on a non-mesh-based filter."); return OPENMC_E_INVALID_TYPE; } diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 11d5b245f..51194684a 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -140,16 +140,18 @@ Tally::Tally(pugi::xml_node node) particle_filter_index = i_filter; // Change the tally estimator if a filter demands it - std::string filt_type = f->type(); - if (filt_type == "energyout" || filt_type == "legendre") { + FilterType filt_type = f->type(); + if (filt_type == FilterType::ENERGY_OUT || + filt_type == FilterType::LEGENDRE) { estimator_ = TallyEstimator::ANALOG; - } else if (filt_type == "sphericalharmonics") { + } else if (filt_type == FilterType::SPHERICAL_HARMONICS) { auto sf = dynamic_cast(f); if (sf->cosine() == SphericalHarmonicsCosine::scatter) { estimator_ = TallyEstimator::ANALOG; } - } else if (filt_type == "spatiallegendre" || filt_type == "zernike" || - filt_type == "zernikeradial") { + } else if (filt_type == FilterType::SPATIAL_LEGENDRE || + filt_type == FilterType::ZERNIKE || + filt_type == FilterType::ZERNIKE_RADIAL) { estimator_ = TallyEstimator::COLLISION; } } From 8d58588341417f3cfbce48f0cfaf3ca780332ab7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 5 Nov 2022 21:19:00 -0500 Subject: [PATCH 1243/2654] Changing CellBorn filter name to match other class names --- include/openmc/tallies/filter_cellborn.h | 2 +- src/tallies/filter.cpp | 2 +- src/tallies/filter_cellborn.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/openmc/tallies/filter_cellborn.h b/include/openmc/tallies/filter_cellborn.h index 17102d971..417aedece 100644 --- a/include/openmc/tallies/filter_cellborn.h +++ b/include/openmc/tallies/filter_cellborn.h @@ -11,7 +11,7 @@ namespace openmc { //! Specifies which cell the particle was born in. //============================================================================== -class CellbornFilter : public CellFilter { +class CellBornFilter : public CellFilter { public: //---------------------------------------------------------------------------- // Methods diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index a121299fe..c00d4fd43 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -115,7 +115,7 @@ Filter* Filter::create(const std::string& type, int32_t id) } else if (type == "cell") { return Filter::create(id); } else if (type == "cellborn") { - return Filter::create(id); + return Filter::create(id); } else if (type == "cellfrom") { return Filter::create(id); } else if (type == "cellinstance") { diff --git a/src/tallies/filter_cellborn.cpp b/src/tallies/filter_cellborn.cpp index d0d25c9a0..ad8363e7b 100644 --- a/src/tallies/filter_cellborn.cpp +++ b/src/tallies/filter_cellborn.cpp @@ -4,7 +4,7 @@ namespace openmc { -void CellbornFilter::get_all_bins( +void CellBornFilter::get_all_bins( const Particle& p, TallyEstimator estimator, FilterMatch& match) const { auto search = map_.find(p.cell_born()); @@ -14,7 +14,7 @@ void CellbornFilter::get_all_bins( } } -std::string CellbornFilter::text_label(int bin) const +std::string CellBornFilter::text_label(int bin) const { return "Birth Cell " + std::to_string(model::cells[cells_[bin]]->id_); } From 1abb728b4fc3f7190c105aa3ce7cd91504b4cb8d Mon Sep 17 00:00:00 2001 From: myerspat Date: Tue, 8 Nov 2022 19:42:16 -0500 Subject: [PATCH 1244/2654] bug fixing Discrete constructor --- src/distribution.cpp | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index 29cf4014a..55b6c53b7 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -59,23 +59,24 @@ Discrete::Discrete(const double* x, const double* p, int n) int j = small.back(); int k = large.back(); + // Remove last element of small + small.pop_back(); + // Update probability and alias based on Vose's algorithm prob_[k] += prob_[j] - 1; alias_[j] = k; // Remove last vector element and or move large index to small vector - if (prob_[k] < 1) { + if (prob_[k] < 1.0) { small.push_back(k); large.pop_back(); - } else { - small.pop_back(); } } } double Discrete::sample(uint64_t* seed) const { - int n = prob_.size(); + int n = x_.size(); if (n > 1) { int u = prn(seed) * n; if (prn(seed) < prob_[u]) { @@ -83,17 +84,8 @@ double Discrete::sample(uint64_t* seed) const } else { return x_[alias_[u]]; } - - // double xi = prn(seed); - // double c = 0.0; - // for (int i = 0; i < n; ++i) { - // c += p_[i]; - // if (xi < c) - // return x_[i]; - // } - // throw std::runtime_error {"Error when sampling probability mass function."}; } else { - return x_[0]; + return x_.size(); } } From 1110038939b8d72d36e9ac7e202f6a6899bfe708 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 8 Nov 2022 21:04:15 -0500 Subject: [PATCH 1245/2654] remove get_redundant_surfaces and cache --- openmc/geometry.py | 62 +++++++++++++------------------ openmc/model/model.py | 3 ++ tests/unit_tests/test_geometry.py | 9 ++--- 3 files changed, 32 insertions(+), 42 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 379a2bb4e..3b6933362 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -37,7 +37,6 @@ class Geometry: def __init__(self, root=None): self._root_universe = None self._offsets = {} - self._redundant_surface_map = None self.merge_surfaces = False self.surface_precision = 10 if root is not None: @@ -430,38 +429,6 @@ class Geometry: surfaces = cell.region.get_surfaces(surfaces) return surfaces - def get_redundant_surfaces(self): - """Return all of the topologically redundant surface IDs. - - Uses surface_precision attribute of Geometry instance for rounding and - comparing surface coefficients. - - .. versionadded:: 0.12 - - Returns - ------- - dict - Dictionary whose keys are the ID of a redundant surface and whose - values are the topologically equivalent :class:`openmc.Surface` - that should replace it. - - """ - # check if redundant surfaces have not been calculated yet - if self._redundant_surface_map is None: - redundancies = defaultdict(list) - for surf in self.get_all_surfaces().values(): - coeffs = tuple(round(surf._coefficients[k], - self.surface_precision) - for k in surf._coeff_keys) - key = (surf._type,) + coeffs - redundancies[key].append(surf) - - self._redundant_surface_map = {replace.id: keep - for keep, *redundant in redundancies.values() - for replace in redundant} - - return self._redundant_surface_map - def _get_domains_by_name(self, name, case_sensitive, matching, domain_type): if not case_sensitive: name = name.lower() @@ -609,10 +576,33 @@ class Geometry: return self._get_domains_by_name(name, case_sensitive, matching, 'lattice') def remove_redundant_surfaces(self): - """Remove redundant surfaces from the geometry.""" + """Remove and return all of the redundant surfaces. + Uses surface_precision attribute of Geometry instance for rounding and + comparing surface coefficients. + + .. versionadded:: 0.12 + + Returns + ------- + redundant_surfaces + Dictionary whose keys are the ID of a redundant surface and whose + values are the topologically equivalent :class:`openmc.Surface` + that should replace it. + + """ # Get redundant surfaces - redundant_surfaces = self.get_redundant_surfaces() + redundancies = defaultdict(list) + for surf in self.get_all_surfaces().values(): + coeffs = tuple(round(surf._coefficients[k], + self.surface_precision) + for k in surf._coeff_keys) + key = (surf._type,) + coeffs + redundancies[key].append(surf) + + redundant_surfaces = {replace.id: keep + for keep, *redundant in redundancies.values() + for replace in redundant} if redundant_surfaces: # Iterate through all cells contained in the geometry @@ -621,7 +611,7 @@ class Geometry: if cell.region: cell.region.remove_redundant_surfaces(redundant_surfaces) - self._redundant_surface_map = None + return redundant_surfaces def determine_paths(self, instances_only=False): """Determine paths through CSG tree for cells and materials. diff --git a/openmc/model/model.py b/openmc/model/model.py index 7126987cb..98136b2d5 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -422,6 +422,9 @@ class Model: warnings.warn("remove_surfs kwarg will be deprecated soon, please " "set the Geometry.merge_surfaces attribute instead.") self.geometry.merge_surfaces = True + # Can be used to modify tallies in case any surfaces are redundant + redundant_surfaces = self.geometry.remove_redundant_surfaces() + self.geometry.export_to_xml(d) # If a materials collection was specified, export it. Otherwise, look diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py index 6a092126e..9db112fd2 100644 --- a/tests/unit_tests/test_geometry.py +++ b/tests/unit_tests/test_geometry.py @@ -302,7 +302,7 @@ def test_rotation_matrix(): assert geom.find((0.0, -0.5, 0.0))[-1] == c1 assert geom.find((0.0, -1.5, 0.0))[-1] == c2 -def test_remove_redundant_surfaces(run_in_tmpdir): +def test_remove_redundant_surfaces(): """Test ability to remove redundant surfaces""" m1 = openmc.Material() @@ -344,11 +344,8 @@ def test_remove_redundant_surfaces(run_in_tmpdir): materials=openmc.Materials([m1, m2, m3])) # There should be 6 redundant surfaces in this geometry - n_redundant_surfs = len(geom.get_redundant_surfaces().keys()) + n_redundant_surfs = len(geom.remove_redundant_surfaces().keys()) assert n_redundant_surfs == 6 - # Remove redundant surfaces on export - model.export_to_xml() - geom = openmc.Geometry.from_xml() # There should be 0 remaining redundant surfaces - n_redundant_surfs = len(geom.get_redundant_surfaces().keys()) + n_redundant_surfs = len(geom.remove_redundant_surfaces().keys()) assert n_redundant_surfs == 0 From 21a14f6eebb44c88834bd8f2c71881bfab75608a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 9 Nov 2022 16:23:48 -0600 Subject: [PATCH 1246/2654] Add suggestion from @paulromano Co-authored-by: Paul Romano --- include/openmc/tallies/filter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/tallies/filter.h b/include/openmc/tallies/filter.h index 104a55e47..47b4c8a94 100644 --- a/include/openmc/tallies/filter.h +++ b/include/openmc/tallies/filter.h @@ -18,7 +18,7 @@ namespace openmc { enum class FilterType { - AZIMUTHAL = 0, + AZIMUTHAL, CELLBORN, CELLFROM, CELL, From 67e18c0db6e02fb7c40d01669277da64a6067d44 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 9 Nov 2022 16:34:46 -0600 Subject: [PATCH 1247/2654] Updating documentation for CellBornFilter --- docs/source/pythonapi/base.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index 076b02722..72d2534ea 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -120,7 +120,7 @@ Constructing Tallies openmc.MaterialFilter openmc.CellFilter openmc.CellFromFilter - openmc.CellbornFilter + openmc.CellBornFilter openmc.CellInstanceFilter openmc.CollisionFilter openmc.SurfaceFilter From aaaff621354be10ea474012e649c94752896e8bf Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 9 Nov 2022 16:35:19 -0600 Subject: [PATCH 1248/2654] Using new CellBornFilter class name in the tallies reg test --- tests/regression_tests/tallies/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index 3e1c6e7ba..6b4baabce 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -40,7 +40,7 @@ def test_tallies(): cellborn_tally = Tally() cellborn_tally.filters = [ - CellbornFilter((model.geometry.get_all_cells()[10], + CellBornFilter((model.geometry.get_all_cells()[10], model.geometry.get_all_cells()[21], 22, 23))] # Test both Cell objects and ids cellborn_tally.scores = ['total'] From 5e7f3f7efd6c5351ad6f644dc2b79938619f9c9a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 9 Nov 2022 17:34:05 -0600 Subject: [PATCH 1249/2654] Adding alias for CellbornFilter in the Python API --- openmc/filter.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index d6571cd5a..07c4fd959 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -533,7 +533,7 @@ class CellFromFilter(WithIDFilter): expected_type = Cell -class CellbornFilter(WithIDFilter): +class CellBornFilter(WithIDFilter): """Bins tally events based on which cell the particle was born in. Parameters @@ -557,6 +557,14 @@ class CellbornFilter(WithIDFilter): expected_type = Cell +# Temporary alias for CellbornFilter +def CellbornFilter(*args, **kwargs): + warnings.warn('The name of "CellbornFilter" has changed to ' + '"CellBornFilter". "CellbornFilter" will be ' + 'removed in the future.') + return CellBornFilter(*args, **kwargs) + + class CellInstanceFilter(Filter): """Bins tally events based on which cell instance a particle is in. From d765d3224f7995abe8742423d4f864dfa56121eb Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 10 Nov 2022 09:02:31 -0600 Subject: [PATCH 1250/2654] Update openmc/filter.py Co-authored-by: Paul Romano --- openmc/filter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index 07c4fd959..99b005351 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -561,7 +561,7 @@ class CellBornFilter(WithIDFilter): def CellbornFilter(*args, **kwargs): warnings.warn('The name of "CellbornFilter" has changed to ' '"CellBornFilter". "CellbornFilter" will be ' - 'removed in the future.') + 'removed in the future.', FutureWarning) return CellBornFilter(*args, **kwargs) From e64bf6a7ffb1b33f732e804bf10ff376d2cba700 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Thu, 10 Nov 2022 12:31:45 -0300 Subject: [PATCH 1251/2654] Add installation instructions for NCrystal --- docs/source/usersguide/install.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 74be9ba0b..9e5ba1ffd 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -271,6 +271,16 @@ Prerequisites cmake -DOPENMC_USE_DAGMC=on -DCMAKE_PREFIX_PATH=/path/to/dagmc/installation .. + * NCrystal_ library for defining materials with enhanced thermal neutron transport + + Adding this option allows the creation of materials from NCrystal, which + replaces the scattering kernel treatment of ACE files with a modular, on-the-fly approach. + To use it `install `_ and + `initialize `_ + NCrystal and turn on the option in the CMake configuration step: + + cmake -DOPENMC_USE_NCRYSTAL=on .. + * libMesh_ mesh library framework for numerical simulations of partial differential equations This optional dependency enables support for unstructured mesh tally @@ -294,6 +304,7 @@ Prerequisites .. _MOAB: https://bitbucket.org/fathomteam/moab .. _libMesh: https://libmesh.github.io/ .. _libpng: http://www.libpng.org/pub/png/libpng.html +.. _NCrystal: https://github.com/mctools/ncrystal Obtaining the Source -------------------- @@ -362,6 +373,12 @@ OPENMC_USE_DAGMC should also be defined as `DAGMC_ROOT` in the CMake configuration command. (Default: off) +OPENMC_USE_NCRYSTAL + Turns on support for NCrystal materials. NCrystal must be + `installed `_ and + `initialized `_. + (Default: off) + OPENMC_USE_LIBMESH Enables the use of unstructured mesh tallies with libMesh_. (Default: off) From 1f3c5ed6bc4b29259d300a0d9b0fac0decf0eff6 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Thu, 10 Nov 2022 13:04:47 -0300 Subject: [PATCH 1252/2654] Add use instructions and examples for NCrystal --- docs/source/usersguide/materials.rst | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index 8b43f1a2a..ab5a8c5af 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -101,6 +101,42 @@ you would need to add hydrogen and oxygen to a material and then assign the .. _usersguide_naming: +------------------ +Adding NCrystal materials +------------------ + +Additional support for thermal scattering can be added by using NCrystal_. +The :meth:`Material.from_ncrystal` class method generates a material object from +an `NCrystal configuration string `_. +Temperature, material composition and density are passed from the configuration string +and the `NCMAT file `_ +that define the material, e.g: + +:: + + mat = openmc.Material.from_ncrystal('Al_sg225.ncmat') + +defines a material containing polycrystalline alumnium, + +:: + + mat = openmc.Material.from_ncrystal(""""Ge_sg227.ncmat;dcutoff=0.5;mos=40arcsec; + dir1=@crys_hkl:5,1,1@lab:0,0,1; + dir2=@crys_hkl:0,-1,1@lab:0,1,0""") + +defines an oriented germanium single crystal with 40 arcsec mosaicity. + +NCrystal only handles low energy neutron interactions. Other interaction are +provided by standard ACE files. NCrystal_ comes with a `predefined library +https://github.com/mctools/ncrystal/wiki/Data-library`_ but more materials can +be added by creating NCMAT files or on-the-fly in the configuration string. + +.. warning:: Currently, NCrystal_ materials cannot be modified after created. + Density, temperature and composition should be defined in the + configuration string or the NCMAT file. + +.. _NCrystal: https://github.com/mctools/ncrystal + ------------------ Naming Conventions ------------------ @@ -222,3 +258,4 @@ been generated, you can tell OpenMC to use this file either by setting materials.cross_sections = '/path/to/cross_sections.xml' .. _MCNP: https://mcnp.lanl.gov/ + From f6152d82505492c2a2fb14b4b1b7f56c7df29912 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 13 Oct 2022 16:28:20 -0400 Subject: [PATCH 1253/2654] working on other basis options --- openmc/model/surface_composite.py | 286 +++++++++++++++++++++++++++++- 1 file changed, 285 insertions(+), 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 4c76c7786..b8f952f19 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -1,7 +1,9 @@ from abc import ABC, abstractmethod from copy import copy -from math import sqrt, pi, sin, cos +from math import sqrt, pi, sin, cos, isclose import numpy as np +from scipy.spatial import ConvexHull, Delaunay +from matplotlib.path import Path import openmc from openmc.checkvalue import check_greater_than, check_value @@ -621,3 +623,285 @@ class ZConeOneSided(CompositeSurface): __neg__ = XConeOneSided.__neg__ __pos__ = XConeOneSided.__pos__ + + +class Polygon(CompositeSurface): + """Create a polygon composite surface from connected points. + + Parameters + ---------- + points : np.ndarray (Nx2) + Points defining the vertices of the polygon. + basis : str, {'rz', 'xy', 'yz', 'xz'}, optional + 2D basis set for the polygon. + + Attributes + ---------- + """ + _basis_surface_map = {} + _basis_surface_map['xy'] = 2*(openmc.XPlane, openmc.YPlane) + _basis_surface_map['yz'] = 2*(openmc.YPlane, openmc.ZPlane) + _basis_surface_map['xz'] = 2*(openmc.XPlane, openmc.ZPlane) + + def __init__(self, points, basis='rz'): + # If the last point is the same as the first remove it and order the + # vertices in a counter-clockwise sense. + if np.allclose(points[0, :], points[-1, :]): + points = points[:-1, :] + self._points = self.make_ccw(np.asarray(points, dtype=float)) + self._basis = basis + + # Create a triangulation and convex hull of the points. The + # Polygon region will be primarily defined by the intersection + # of the convex hull with the intersection of the complements of the + # simplices outside the polygon, but inside the convex hull. + self._tri = Delaunay(self._points, qhull_options='QJ') + self._convex_hull = ConvexHull(self._points) + self._convex_hull_surfs = self.get_convex_hull_surfs() + + # Get centroids of all the simplices and determine if they are inside + # the polygon defined by input vertices or not. If they are not, they + # are added to the convex_subsets + centroids = np.mean(self._points[self._tri.simplices], axis=1) + path = Path(self._points) + in_polygon = np.array([path.contains_point(c) for c in centroids]) + self._in_polygon = in_polygon + # Loop through simplices that aren't in the polygon and add them to the + # surfaces that need to be removed + self._surfs_to_remove = [] + for simplex in self._tri.simplices[~in_polygon, :]: + qhull = ConvexHull(self._points[simplex, :]) + idx = self.get_ordered_simplex_indices(qhull) + eqns = qhull.equations[idx, :] + self._surfs_to_remove.append(self.get_convex_hull_surfs(eqns)) + + # Set surface names as required by CompositeSurface protocol + surfnames = [] + for i, (surf, _) in enumerate(self._convex_hull_surfs): + setattr(self, f'hull_surf_{i}', surf) + surfnames.append(f'hull_surf_{i}') + + i = 0 + for surfs_ops in self._surfs_to_remove: + for surf, _ in surfs_ops: + setattr(self, f'aux_surf_{i}', surf) + surfnames.append(f'aux_surf_{i}') + i += 1 + + self._surfnames = tuple(surfnames) + + def __neg__(self): + # inside convex surface and outside all convex surfaces formed from + # concave points + return self.region + + def __pos__(self): + # outside convex hull or inside one of the convex shapes formed from + # concave points + return ~self.region + + @property + def _surface_names(self): + return self._surfnames + + @property + def points(self): + return self._points + + @property + def basis(self): + return self._basis + + @property + def tangents(self): + return np.diff(self._points, axis=0, append=[self._points[0, :]]) + + @property + def normals(self): + rotation = np.array([[0, 1], [-1, 0]]) + tangents = self.tangents + tangents /= np.linalg.norm(tangents, axis=-1, keepdims=True) + return rotation.dot(tangents.T).T + + @property + def hull_points(self): + return self._points[self._convex_hull.vertices] + + @property + def hull_tangents(self): + pts = self._points[self._convex_hull.vertices] + return np.diff(pts, axis=0, append=[pts[0, :]]) + + @property + def hull_equations(self): + idx = self.get_ordered_simplex_indices() + return self._convex_hull.equations[idx, :] + + @property + def convex_hull_surfs(self): + return self._convex_hull_surfs + + @property + def hull_region(self): + surfs_ops = self.convex_hull_surfs + regions = [getattr(surf, op)() for surf, op in surfs_ops] + return openmc.Intersection(regions) + + @property + def region(self): + hull_reg = self.hull_region + surfs_ops_sets = self._surfs_to_remove + complements = [] + for surfs_ops in surfs_ops_sets: + regions = [getattr(surf, op)() for surf, op in surfs_ops] + complements.append(~openmc.Intersection(regions)) + return hull_reg & openmc.Intersection(complements) + + def offset(self, distance): + """Offset this polygon by a set distance + + Parameters + ---------- + distance : float + The distance to offset the polygon by. Positive is outward + (expanding) and negative is inward (shrinking). + + + Returns + ------- + offset_polygon : openmc.model.Polygon + """ + points = self.points + normals = self.normals + normals = np.insert(normals, 0, normals[-1, :], axis=0) + ndotv1 = np.sum(normals[:-1, :]*(points + distance*normals[:-1, :]), + axis=-1, keepdims=True) + ndotv2 = np.sum(normals[1:, :]*(points + distance*normals[1:, :]), + axis=-1, keepdims=True) + + new_points = np.empty_like(points) + denom = normals[:-1, 0]*normals[1:, 1] - normals[:-1, 1]*normals[1:, 0] + new_points[:, 0] = normals[1:, 1]*ndotv1.T - normals[:-1, 1]*ndotv2.T + new_points[:, 1] = -normals[1:, 0]*ndotv1.T + normals[:-1, 0]*ndotv2.T + new_points /= denom[:, None] + + return type(self)(new_points, basis=self.basis) + + def get_ordered_simplex_indices(self, qhull=None): + """Return simplex indices in same order as ConvexHull.vertices + + Parameters + ---------- + qhull : scipy.spatial.ConvexHull, optional + A ConvexHull object. + + Returns + ------- + idxlist : np.array of ordered simplex indices + """ + qhull = self._convex_hull if qhull is None else qhull + idxlist = [] + verts = qhull.vertices + nverts = len(verts) + simplices = qhull.simplices + for i in range(nverts): + next_i = (i + 1) % nverts + tmp_verts = [verts[i], verts[next_i]] + for j, simplex in enumerate(simplices): + if all(idx in simplex for idx in tmp_verts): + idxlist.append(j) + return np.array(idxlist) + + def get_convex_hull_surfs(self, hull_equations=None): + """Generate a list of surfaces given by a set of linear equations + + Parameters + ---------- + hull_equations : np.ndarray, optional + An Nx3 array where N is the number of facets (or sides) that represent + the equations and each row is given by (nx, ny, c) where (nx, ny) is + the unit vector normal to the facet and c is a constant such that the + surface described by the equation is n dot x + c = 0. + + Returns + ------- + surfs_ops : list of (surface, operator) tuples + + """ + hull_equations = self.hull_equations if hull_equations is None else \ + hull_equations + # Collect surface/operator pairs such that the intersection of the + # regions defined by these pairs is the inside of the polygon. + surfs_ops = [] + # hull facet equation: dx*x + dy*y + c = 0 + for dx, dy, c in hull_equations: + # default to negative halfspace operator for inside the polygon + op = '__neg__' + # Check if the facet is horizontal + if isclose(dx, 0): + if self.basis in ('xz', 'yz', 'rz'): + surf = openmc.ZPlane(z0=-c/dy) + else: + surf = openmc.YPlane(y0=-c/dy) + # if (0, 1).(dx, dy) < 0 we want positive halfspace instead + if dy < 0: + op = '__pos__' + # Check if the facet is vertical + elif isclose(dy, 0): + if self.basis in ('xy', 'xz'): + surf = openmc.XPlane(x0=-c/dx) + elif self.basis == 'yz': + surf = openmc.YPlane(y0=-c/dx) + else: + surf = openmc.ZCylinder(r=-c/dx) + # if (1, 0).(dx, dy) < 0 we want positive halfspace instead + if dx < 0: + op = '__pos__' + # Otherwise the facet is at an angle + else: + y0 = -c/dy + r2 = dy**2 / dx**2 + # Check if the *slope* of the facet is positive + if dy / dx < 0: + if self.basis == 'rz': + surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=True) + else: + raise NotImplementedError + # if (1, -1).(dx, dy) < 0 we want positive halfspace instead + if dx - dy < 0: + op = '__pos__' + else: + if self.basis == 'rz': + surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=False) + else: + raise NotImplementedError + # if (1, 1).(dx, dy) < 0 we want positive halfspace instead + if dx + dy < 0: + op = '__pos__' + + surfs_ops.append((surf, op)) + + return surfs_ops + + def make_ccw(self, verts): + """Determine whether the vertices are ordered counter-clockwise + + Parameters + ---------- + verts : np.ndarray (Nx2) + An Nx2 array of coordinate pairs describing the vertices. + + + Returns + ------- + bool : True if vertices are in counter-clockwise order. False otherwise. + + """ + vector = np.empty(verts.shape[0]) + vector[:-1] = (verts[1:, 0] - verts[:-1, 0])*(verts[1:, 1] + verts[:-1, 1]) + vector[-1] = (verts[0, 0] - verts[-1, 0])*(verts[0, 1] + verts[-1, 1]) + + if np.sum(vector) < 0: + return verts + + return verts[::-1, :] From aa7aab1768b28a8d87ef4a7b762a04598f145155 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Fri, 14 Oct 2022 15:38:27 -0400 Subject: [PATCH 1254/2654] method to break polygon into convex sets complete --- openmc/model/surface_composite.py | 311 +++++++++++++++++------------- 1 file changed, 181 insertions(+), 130 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index b8f952f19..71f95c01c 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -638,17 +638,13 @@ class Polygon(CompositeSurface): Attributes ---------- """ - _basis_surface_map = {} - _basis_surface_map['xy'] = 2*(openmc.XPlane, openmc.YPlane) - _basis_surface_map['yz'] = 2*(openmc.YPlane, openmc.ZPlane) - _basis_surface_map['xz'] = 2*(openmc.XPlane, openmc.ZPlane) def __init__(self, points, basis='rz'): # If the last point is the same as the first remove it and order the # vertices in a counter-clockwise sense. if np.allclose(points[0, :], points[-1, :]): points = points[:-1, :] - self._points = self.make_ccw(np.asarray(points, dtype=float)) + self._points = make_ccw(np.asarray(points, dtype=float)) self._basis = basis # Create a triangulation and convex hull of the points. The @@ -656,8 +652,6 @@ class Polygon(CompositeSurface): # of the convex hull with the intersection of the complements of the # simplices outside the polygon, but inside the convex hull. self._tri = Delaunay(self._points, qhull_options='QJ') - self._convex_hull = ConvexHull(self._points) - self._convex_hull_surfs = self.get_convex_hull_surfs() # Get centroids of all the simplices and determine if they are inside # the polygon defined by input vertices or not. If they are not, they @@ -666,26 +660,35 @@ class Polygon(CompositeSurface): path = Path(self._points) in_polygon = np.array([path.contains_point(c) for c in centroids]) self._in_polygon = in_polygon - # Loop through simplices that aren't in the polygon and add them to the - # surfaces that need to be removed - self._surfs_to_remove = [] - for simplex in self._tri.simplices[~in_polygon, :]: - qhull = ConvexHull(self._points[simplex, :]) - idx = self.get_ordered_simplex_indices(qhull) - eqns = qhull.equations[idx, :] - self._surfs_to_remove.append(self.get_convex_hull_surfs(eqns)) + + # ndict maps simplex indices to a list of their neighbors inside the + # polygon + ndict = {} + for i, nlist in enumerate(self._tri.neighbors): + if not in_polygon[i]: + continue + ndict[i] = [n for n in nlist if in_polygon[n] and n >=0] + #for key, value in ndict.items(): + # print(key, ' : ', value) + + groups = group_wrapper(self._tri, ndict) + self._groups = groups + for g in groups: + print(g) + + self._surfsets = [] + for pts in get_ordered_points(self._tri, groups): + qhull = ConvexHull(pts) + surf_ops = get_convex_hull_surfs(qhull) + self._surfsets.append(surf_ops) # Set surface names as required by CompositeSurface protocol surfnames = [] - for i, (surf, _) in enumerate(self._convex_hull_surfs): - setattr(self, f'hull_surf_{i}', surf) - surfnames.append(f'hull_surf_{i}') - i = 0 - for surfs_ops in self._surfs_to_remove: + for surfs_ops in self._surfsets: for surf, _ in surfs_ops: - setattr(self, f'aux_surf_{i}', surf) - surfnames.append(f'aux_surf_{i}') + setattr(self, f'surface_{i}', surf) + surfnames.append(f'surface_{i}') i += 1 self._surfnames = tuple(surfnames) @@ -747,15 +750,18 @@ class Polygon(CompositeSurface): regions = [getattr(surf, op)() for surf, op in surfs_ops] return openmc.Intersection(regions) + @property + def regions(self): + regions = [] + for surfs_ops in self._surfsets: + reg = openmc.Intersection([getattr(surf, op)() for surf, op in + surfs_ops]) + regions.append(reg) + return regions + @property def region(self): - hull_reg = self.hull_region - surfs_ops_sets = self._surfs_to_remove - complements = [] - for surfs_ops in surfs_ops_sets: - regions = [getattr(surf, op)() for surf, op in surfs_ops] - complements.append(~openmc.Intersection(regions)) - return hull_reg & openmc.Intersection(complements) + return openmc.Union(self.regions) def offset(self, distance): """Offset this polygon by a set distance @@ -787,121 +793,166 @@ class Polygon(CompositeSurface): return type(self)(new_points, basis=self.basis) - def get_ordered_simplex_indices(self, qhull=None): - """Return simplex indices in same order as ConvexHull.vertices +def get_ordered_simplex_indices(qhull): + """Return simplex indices in same order as ConvexHull.vertices - Parameters - ---------- - qhull : scipy.spatial.ConvexHull, optional - A ConvexHull object. + Parameters + ---------- + qhull : scipy.spatial.ConvexHull, optional + A ConvexHull object. - Returns - ------- - idxlist : np.array of ordered simplex indices - """ - qhull = self._convex_hull if qhull is None else qhull - idxlist = [] - verts = qhull.vertices - nverts = len(verts) - simplices = qhull.simplices - for i in range(nverts): - next_i = (i + 1) % nverts - tmp_verts = [verts[i], verts[next_i]] - for j, simplex in enumerate(simplices): - if all(idx in simplex for idx in tmp_verts): - idxlist.append(j) - return np.array(idxlist) + Returns + ------- + idxlist : np.array of ordered simplex indices + """ + idxlist = [] + verts = qhull.vertices + nverts = len(verts) + simplices = qhull.simplices + for i in range(nverts): + next_i = (i + 1) % nverts + tmp_verts = [verts[i], verts[next_i]] + for j, simplex in enumerate(simplices): + if all(idx in simplex for idx in tmp_verts): + idxlist.append(j) + return np.array(idxlist) - def get_convex_hull_surfs(self, hull_equations=None): - """Generate a list of surfaces given by a set of linear equations +def get_convex_hull_surfs(qhull, basis='rz'): + """Generate a list of surfaces given by a set of linear equations - Parameters - ---------- - hull_equations : np.ndarray, optional - An Nx3 array where N is the number of facets (or sides) that represent - the equations and each row is given by (nx, ny, c) where (nx, ny) is - the unit vector normal to the facet and c is a constant such that the - surface described by the equation is n dot x + c = 0. + Parameters + ---------- + hull_equations : np.ndarray, optional + An Nx3 array where N is the number of facets (or sides) that represent + the equations and each row is given by (nx, ny, c) where (nx, ny) is + the unit vector normal to the facet and c is a constant such that the + surface described by the equation is n dot x + c = 0. - Returns - ------- - surfs_ops : list of (surface, operator) tuples + Returns + ------- + surfs_ops : list of (surface, operator) tuples - """ - hull_equations = self.hull_equations if hull_equations is None else \ - hull_equations - # Collect surface/operator pairs such that the intersection of the - # regions defined by these pairs is the inside of the polygon. - surfs_ops = [] - # hull facet equation: dx*x + dy*y + c = 0 - for dx, dy, c in hull_equations: - # default to negative halfspace operator for inside the polygon - op = '__neg__' - # Check if the facet is horizontal - if isclose(dx, 0): - if self.basis in ('xz', 'yz', 'rz'): - surf = openmc.ZPlane(z0=-c/dy) - else: - surf = openmc.YPlane(y0=-c/dy) - # if (0, 1).(dx, dy) < 0 we want positive halfspace instead - if dy < 0: - op = '__pos__' - # Check if the facet is vertical - elif isclose(dy, 0): - if self.basis in ('xy', 'xz'): - surf = openmc.XPlane(x0=-c/dx) - elif self.basis == 'yz': - surf = openmc.YPlane(y0=-c/dx) - else: - surf = openmc.ZCylinder(r=-c/dx) - # if (1, 0).(dx, dy) < 0 we want positive halfspace instead - if dx < 0: - op = '__pos__' - # Otherwise the facet is at an angle + """ + idx = get_ordered_simplex_indices(qhull) + hull_equations = qhull.equations[idx, :] + # Collect surface/operator pairs such that the intersection of the + # regions defined by these pairs is the inside of the polygon. + surfs_ops = [] + # hull facet equation: dx*x + dy*y + c = 0 + for dx, dy, c in hull_equations: + # default to negative halfspace operator for inside the polygon + op = '__neg__' + # Check if the facet is horizontal + if isclose(dx, 0): + if basis in ('xz', 'yz', 'rz'): + surf = openmc.ZPlane(z0=-c/dy) else: - y0 = -c/dy - r2 = dy**2 / dx**2 - # Check if the *slope* of the facet is positive - if dy / dx < 0: - if self.basis == 'rz': - surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=True) - else: - raise NotImplementedError - # if (1, -1).(dx, dy) < 0 we want positive halfspace instead - if dx - dy < 0: - op = '__pos__' + surf = openmc.YPlane(y0=-c/dy) + # if (0, 1).(dx, dy) < 0 we want positive halfspace instead + if dy < 0: + op = '__pos__' + # Check if the facet is vertical + elif isclose(dy, 0): + if basis in ('xy', 'xz'): + surf = openmc.XPlane(x0=-c/dx) + elif basis == 'yz': + surf = openmc.YPlane(y0=-c/dx) + else: + surf = openmc.ZCylinder(r=-c/dx) + # if (1, 0).(dx, dy) < 0 we want positive halfspace instead + if dx < 0: + op = '__pos__' + # Otherwise the facet is at an angle + else: + y0 = -c/dy + r2 = dy**2 / dx**2 + # Check if the *slope* of the facet is positive + if dy / dx < 0: + if basis == 'rz': + surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=True) else: - if self.basis == 'rz': - surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=False) - else: - raise NotImplementedError - # if (1, 1).(dx, dy) < 0 we want positive halfspace instead - if dx + dy < 0: - op = '__pos__' + raise NotImplementedError + # if (1, -1).(dx, dy) < 0 we want positive halfspace instead + if dx - dy < 0: + op = '__pos__' + else: + if basis == 'rz': + surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=False) + else: + raise NotImplementedError + # if (1, 1).(dx, dy) < 0 we want positive halfspace instead + if dx + dy < 0: + op = '__pos__' - surfs_ops.append((surf, op)) + surfs_ops.append((surf, op)) - return surfs_ops + return surfs_ops - def make_ccw(self, verts): - """Determine whether the vertices are ordered counter-clockwise +def make_ccw(verts): + """Determine whether the vertices are ordered counter-clockwise - Parameters - ---------- - verts : np.ndarray (Nx2) - An Nx2 array of coordinate pairs describing the vertices. + Parameters + ---------- + verts : np.ndarray (Nx2) + An Nx2 array of coordinate pairs describing the vertices. - Returns - ------- - bool : True if vertices are in counter-clockwise order. False otherwise. + Returns + ------- + bool : True if vertices are in counter-clockwise order. False otherwise. - """ - vector = np.empty(verts.shape[0]) - vector[:-1] = (verts[1:, 0] - verts[:-1, 0])*(verts[1:, 1] + verts[:-1, 1]) - vector[-1] = (verts[0, 0] - verts[-1, 0])*(verts[0, 1] + verts[-1, 1]) + """ + vector = np.empty(verts.shape[0]) + vector[:-1] = (verts[1:, 0] - verts[:-1, 0])*(verts[1:, 1] + verts[:-1, 1]) + vector[-1] = (verts[0, 0] - verts[-1, 0])*(verts[0, 1] + verts[-1, 1]) - if np.sum(vector) < 0: - return verts + if np.sum(vector) < 0: + return verts - return verts[::-1, :] + return verts[::-1, :] + + +def get_ordered_points(tri, groups): + points = [] + for g in groups: + idx = np.unique(tri.simplices[g, :]) + qhull = ConvexHull(tri.points[idx, :]) + points.append(qhull.points[qhull.vertices, :]) + return points + +def group_wrapper(tri, simp_dict): + groups = [] + while simp_dict: + groups.append(group_simplices(tri, simp_dict)) + return groups + +def group_simplices(tri, simp_dict, group=None): + """Generate a list of convex subsets""" + # If dictionary is empty there's nothing left to do + if not simp_dict: + return group + # If group is empty grab the next simplex in the dictionary and recurse + if group is None: + sidx = next(iter(simp_dict)) + return group_simplices(tri, simp_dict, group=[sidx]) + # Otherwise use the last simplex in the group + else: + # Remove current simplex from dictionary since it is in a group + sidx = group[-1] + neighbors = simp_dict.pop(sidx, []) + # For each neighbor check if it is part of the same convex + # hull as the rest of the group. If yes, recurse. If no, continue on. + for n in neighbors: + if n in group or simp_dict.get(n, None) is None: + continue + test_group = group + [n] + #print('group :', group) + #print('test_group :', test_group) + test_point_idx = np.unique(tri.simplices[test_group, :]) + test_points = tri.points[test_point_idx] + if is_convex(test_points): + group = group_simplices(tri, simp_dict, group=test_group) + return group + +def is_convex(points): + return len(points) == len(ConvexHull(points).vertices) From f6f2ed7b171c763d089550fec7ad7c80bef7c876 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sat, 15 Oct 2022 17:56:54 -0400 Subject: [PATCH 1255/2654] got other basis sets working --- openmc/model/surface_composite.py | 75 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 71f95c01c..b0c83b205 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -626,17 +626,21 @@ class ZConeOneSided(CompositeSurface): class Polygon(CompositeSurface): - """Create a polygon composite surface from connected points. + """Create a polygon composite surface from a path of closed points. Parameters ---------- - points : np.ndarray (Nx2) - Points defining the vertices of the polygon. + points : np.ndarray + An Nx2 array of points defining the vertices of the polygon. basis : str, {'rz', 'xy', 'yz', 'xz'}, optional 2D basis set for the polygon. Attributes ---------- + points : np.ndarray + An Nx2 array of points defining the vertices of the polygon. + basis : str, {'rz', 'xy', 'yz', 'xz'} + 2D basis set for the polygon. """ def __init__(self, points, basis='rz'): @@ -644,24 +648,24 @@ class Polygon(CompositeSurface): # vertices in a counter-clockwise sense. if np.allclose(points[0, :], points[-1, :]): points = points[:-1, :] + + # TODO check if path is self intersecting, throw error if yes self._points = make_ccw(np.asarray(points, dtype=float)) + check_value('basis', basis, ('xy', 'yz', 'xz', 'rz')) self._basis = basis - # Create a triangulation and convex hull of the points. The - # Polygon region will be primarily defined by the intersection - # of the convex hull with the intersection of the complements of the - # simplices outside the polygon, but inside the convex hull. + # Create a triangulation of the points. self._tri = Delaunay(self._points, qhull_options='QJ') # Get centroids of all the simplices and determine if they are inside - # the polygon defined by input vertices or not. If they are not, they - # are added to the convex_subsets + # the polygon defined by input vertices or not. centroids = np.mean(self._points[self._tri.simplices], axis=1) path = Path(self._points) in_polygon = np.array([path.contains_point(c) for c in centroids]) self._in_polygon = in_polygon - # ndict maps simplex indices to a list of their neighbors inside the + # Build a map with keys of simplex indices inside the polygon whose + # values are lists of that simplex's neighbors inside the # polygon ndict = {} for i, nlist in enumerate(self._tri.neighbors): @@ -679,7 +683,7 @@ class Polygon(CompositeSurface): self._surfsets = [] for pts in get_ordered_points(self._tri, groups): qhull = ConvexHull(pts) - surf_ops = get_convex_hull_surfs(qhull) + surf_ops = get_convex_hull_surfs(qhull, basis=self.basis) self._surfsets.append(surf_ops) # Set surface names as required by CompositeSurface protocol @@ -809,9 +813,8 @@ def get_ordered_simplex_indices(qhull): verts = qhull.vertices nverts = len(verts) simplices = qhull.simplices - for i in range(nverts): - next_i = (i + 1) % nverts - tmp_verts = [verts[i], verts[next_i]] + for i, vert in enumerate(verts): + tmp_verts = [vert, verts[(i + 1) % nverts]] for j, simplex in enumerate(simplices): if all(idx in simplex for idx in tmp_verts): idxlist.append(j) @@ -835,13 +838,12 @@ def get_convex_hull_surfs(qhull, basis='rz'): """ idx = get_ordered_simplex_indices(qhull) hull_equations = qhull.equations[idx, :] + check_value('basis', basis, ('xy', 'yz', 'xz', 'rz')) # Collect surface/operator pairs such that the intersection of the # regions defined by these pairs is the inside of the polygon. surfs_ops = [] # hull facet equation: dx*x + dy*y + c = 0 for dx, dy, c in hull_equations: - # default to negative halfspace operator for inside the polygon - op = '__neg__' # Check if the facet is horizontal if isclose(dx, 0): if basis in ('xz', 'yz', 'rz'): @@ -849,8 +851,7 @@ def get_convex_hull_surfs(qhull, basis='rz'): else: surf = openmc.YPlane(y0=-c/dy) # if (0, 1).(dx, dy) < 0 we want positive halfspace instead - if dy < 0: - op = '__pos__' + op = '__pos__' if dy < 0 else '__neg__' # Check if the facet is vertical elif isclose(dy, 0): if basis in ('xy', 'xz'): @@ -860,29 +861,29 @@ def get_convex_hull_surfs(qhull, basis='rz'): else: surf = openmc.ZCylinder(r=-c/dx) # if (1, 0).(dx, dy) < 0 we want positive halfspace instead - if dx < 0: - op = '__pos__' + op = '__pos__' if dx < 0 else '__neg__' # Otherwise the facet is at an angle else: - y0 = -c/dy - r2 = dy**2 / dx**2 - # Check if the *slope* of the facet is positive - if dy / dx < 0: - if basis == 'rz': - surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=True) - else: - raise NotImplementedError - # if (1, -1).(dx, dy) < 0 we want positive halfspace instead - if dx - dy < 0: - op = '__pos__' + op = '__neg__' + if basis == 'xy': + surf = openmc.Plane(a=dx, b=dy, d=-c) + elif basis == 'yz': + surf = openmc.Plane(b=dx, c=dy, d=-c) + elif basis == 'xz': + surf = openmc.Plane(a=dx, c=dy, d=-c) else: - if basis == 'rz': - surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=False) - else: - raise NotImplementedError - # if (1, 1).(dx, dy) < 0 we want positive halfspace instead - if dx + dy < 0: + y0 = -c/dy + r2 = dy**2 / dx**2 + # Check if the *slope* of the facet is positive. If dy/dx < 0 + # then we want up to be True for the one-sided cones. + up = dy / dx < 0 + surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=up) + # if (1, -1).(dx, dy) < 0 for up cones we want positive halfspace + # if (1, 1).(dx, dy) < 0 for down cones we want positive halfspace + if (up and dx - dy < 0) or (not up and dx + dy < 0): op = '__pos__' + else: + op = '__neg__' surfs_ops.append((surf, op)) From 3fe2bf4cb650dab3c4ab76da258d587923520c41 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sat, 15 Oct 2022 18:22:47 -0400 Subject: [PATCH 1256/2654] cleaning up unnecessary methods --- openmc/model/surface_composite.py | 66 +++++++------------------------ 1 file changed, 15 insertions(+), 51 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index b0c83b205..72c625ba9 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -660,26 +660,24 @@ class Polygon(CompositeSurface): # Get centroids of all the simplices and determine if they are inside # the polygon defined by input vertices or not. centroids = np.mean(self._points[self._tri.simplices], axis=1) - path = Path(self._points) - in_polygon = np.array([path.contains_point(c) for c in centroids]) + in_polygon = Path(self._points).contains_points(centroids) self._in_polygon = in_polygon # Build a map with keys of simplex indices inside the polygon whose - # values are lists of that simplex's neighbors inside the + # values are lists of that simplex's neighbors also inside the # polygon ndict = {} for i, nlist in enumerate(self._tri.neighbors): if not in_polygon[i]: continue ndict[i] = [n for n in nlist if in_polygon[n] and n >=0] - #for key, value in ndict.items(): - # print(key, ' : ', value) + # Get the groups of simplices forming convex polygons whose union + # comprises the full input polygon. groups = group_wrapper(self._tri, ndict) self._groups = groups - for g in groups: - print(g) + # Get the sets of surface, operator pairs defining the polygon self._surfsets = [] for pts in get_ordered_points(self._tri, groups): qhull = ConvexHull(pts) @@ -698,14 +696,10 @@ class Polygon(CompositeSurface): self._surfnames = tuple(surfnames) def __neg__(self): - # inside convex surface and outside all convex surfaces formed from - # concave points - return self.region + return self._region def __pos__(self): - # outside convex hull or inside one of the convex shapes formed from - # concave points - return ~self.region + return ~self._region @property def _surface_names(self): @@ -720,52 +714,22 @@ class Polygon(CompositeSurface): return self._basis @property - def tangents(self): - return np.diff(self._points, axis=0, append=[self._points[0, :]]) - - @property - def normals(self): + def _normals(self): rotation = np.array([[0, 1], [-1, 0]]) - tangents = self.tangents + tangents = np.diff(self._points, axis=0, append=[self._points[0, :]]) tangents /= np.linalg.norm(tangents, axis=-1, keepdims=True) return rotation.dot(tangents.T).T @property - def hull_points(self): - return self._points[self._convex_hull.vertices] - - @property - def hull_tangents(self): - pts = self._points[self._convex_hull.vertices] - return np.diff(pts, axis=0, append=[pts[0, :]]) - - @property - def hull_equations(self): - idx = self.get_ordered_simplex_indices() - return self._convex_hull.equations[idx, :] - - @property - def convex_hull_surfs(self): - return self._convex_hull_surfs - - @property - def hull_region(self): - surfs_ops = self.convex_hull_surfs - regions = [getattr(surf, op)() for surf, op in surfs_ops] - return openmc.Intersection(regions) - - @property - def regions(self): + def _regions(self): regions = [] for surfs_ops in self._surfsets: - reg = openmc.Intersection([getattr(surf, op)() for surf, op in - surfs_ops]) - regions.append(reg) - return regions + regions.append([getattr(surf, op)() for surf, op in surfs_ops]) + return [openmc.Intersection(regs) for regs in regions] @property - def region(self): - return openmc.Union(self.regions) + def _region(self): + return openmc.Union(self._regions) def offset(self, distance): """Offset this polygon by a set distance @@ -782,7 +746,7 @@ class Polygon(CompositeSurface): offset_polygon : openmc.model.Polygon """ points = self.points - normals = self.normals + normals = self._normals normals = np.insert(normals, 0, normals[-1, :], axis=0) ndotv1 = np.sum(normals[:-1, :]*(points + distance*normals[:-1, :]), axis=-1, keepdims=True) From a26dcc65b728b297d2e1cf09b1069784ad78902f Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sun, 16 Oct 2022 21:38:29 -0400 Subject: [PATCH 1257/2654] cleaning up/consolidating functions --- openmc/model/surface_composite.py | 181 ++++++++++++++++-------------- 1 file changed, 95 insertions(+), 86 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 72c625ba9..2036950f5 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -657,38 +657,17 @@ class Polygon(CompositeSurface): # Create a triangulation of the points. self._tri = Delaunay(self._points, qhull_options='QJ') - # Get centroids of all the simplices and determine if they are inside - # the polygon defined by input vertices or not. - centroids = np.mean(self._points[self._tri.simplices], axis=1) - in_polygon = Path(self._points).contains_points(centroids) - self._in_polygon = in_polygon + # Decompose the polygon into groups of simplices forming convex subsets + self._groups = self._decompose_polygon_into_convex_sets() - # Build a map with keys of simplex indices inside the polygon whose - # values are lists of that simplex's neighbors also inside the - # polygon - ndict = {} - for i, nlist in enumerate(self._tri.neighbors): - if not in_polygon[i]: - continue - ndict[i] = [n for n in nlist if in_polygon[n] and n >=0] - - # Get the groups of simplices forming convex polygons whose union - # comprises the full input polygon. - groups = group_wrapper(self._tri, ndict) - self._groups = groups - - # Get the sets of surface, operator pairs defining the polygon - self._surfsets = [] - for pts in get_ordered_points(self._tri, groups): - qhull = ConvexHull(pts) - surf_ops = get_convex_hull_surfs(qhull, basis=self.basis) - self._surfsets.append(surf_ops) + # Get the sets of (surface, operator) pairs defining the polygon + self._surfsets = self._get_surfsets() # Set surface names as required by CompositeSurface protocol surfnames = [] i = 0 - for surfs_ops in self._surfsets: - for surf, _ in surfs_ops: + for surfset in self._surfsets: + for surf, op in surfset: setattr(self, f'surface_{i}', surf) surfnames.append(f'surface_{i}') i += 1 @@ -715,6 +694,7 @@ class Polygon(CompositeSurface): @property def _normals(self): + """Generate the outward normal unit vectors for the polygon.""" rotation = np.array([[0, 1], [-1, 0]]) tangents = np.diff(self._points, axis=0, append=[self._points[0, :]]) tangents /= np.linalg.norm(tangents, axis=-1, keepdims=True) @@ -722,6 +702,7 @@ class Polygon(CompositeSurface): @property def _regions(self): + """Generate a list of regions whose union represents the polygon.""" regions = [] for surfs_ops in self._surfsets: regions.append([getattr(surf, op)() for surf, op in surfs_ops]) @@ -731,6 +712,57 @@ class Polygon(CompositeSurface): def _region(self): return openmc.Union(self._regions) + def _decompose_polygon_into_convex_sets(self): + """Decompose the Polygon into a set of convex polygons. + + Returns + ------- + list of sets of simplices + """ + + # Get centroids of all the simplices and determine if they are inside + # the polygon defined by input vertices or not. + centroids = np.mean(self._points[self._tri.simplices], axis=1) + in_polygon = Path(self._points).contains_points(centroids) + self._in_polygon = in_polygon + + # Build a map with keys of simplex indices inside the polygon whose + # values are lists of that simplex's neighbors also inside the + # polygon + neighbor_map = {} + for i, nlist in enumerate(self._tri.neighbors): + if not in_polygon[i]: + continue + neighbor_map[i] = [n for n in nlist if in_polygon[n] and n >=0] + + # Get the groups of simplices forming convex polygons whose union + # comprises the full input polygon. While there are still simplices + # left in the neighbor map, group them together into convex sets. + groups = [] + while neighbor_map: + groups.append(group_simplices(self._tri, neighbor_map)) + + return groups + + def _get_surfsets(self): + """Generate lists of surface, operator pairs for the sub-polygons. + + Returns + ------- + surfsets : a list of lists of surface, operator pairs + """ + + surfsets = [] + for g in self._groups: + # Find all the unique points in the convex group of simplices, + # generate the convex hull and find the resulting surfaces and + # unary operators that represent this convex subset of the polygon. + idx = np.unique(self._tri.simplices[g, :]) + qhull = ConvexHull(self._tri.points[idx, :]) + surf_ops = get_convex_hull_surfs(qhull, basis=self.basis) + surfsets.append(surf_ops) + return surfsets + def offset(self, distance): """Offset this polygon by a set distance @@ -745,6 +777,8 @@ class Polygon(CompositeSurface): ------- offset_polygon : openmc.model.Polygon """ + # Get the points of the polygon and outward normals such that + # normals[i] corresponds to the edge between points[i-1] and points[i] points = self.points normals = self._normals normals = np.insert(normals, 0, normals[-1, :], axis=0) @@ -761,53 +795,28 @@ class Polygon(CompositeSurface): return type(self)(new_points, basis=self.basis) -def get_ordered_simplex_indices(qhull): - """Return simplex indices in same order as ConvexHull.vertices - - Parameters - ---------- - qhull : scipy.spatial.ConvexHull, optional - A ConvexHull object. - - Returns - ------- - idxlist : np.array of ordered simplex indices - """ - idxlist = [] - verts = qhull.vertices - nverts = len(verts) - simplices = qhull.simplices - for i, vert in enumerate(verts): - tmp_verts = [vert, verts[(i + 1) % nverts]] - for j, simplex in enumerate(simplices): - if all(idx in simplex for idx in tmp_verts): - idxlist.append(j) - return np.array(idxlist) def get_convex_hull_surfs(qhull, basis='rz'): """Generate a list of surfaces given by a set of linear equations Parameters ---------- - hull_equations : np.ndarray, optional - An Nx3 array where N is the number of facets (or sides) that represent - the equations and each row is given by (nx, ny, c) where (nx, ny) is - the unit vector normal to the facet and c is a constant such that the - surface described by the equation is n dot x + c = 0. + qhull : scipy.spatial.ConvexHull + A ConvexHull object representing the sub-region of the polygon. + basis : str, {'rz', 'xy', 'yz', 'xz'}, optional + 2D basis set for the polygon. Returns ------- surfs_ops : list of (surface, operator) tuples """ - idx = get_ordered_simplex_indices(qhull) - hull_equations = qhull.equations[idx, :] check_value('basis', basis, ('xy', 'yz', 'xz', 'rz')) # Collect surface/operator pairs such that the intersection of the # regions defined by these pairs is the inside of the polygon. surfs_ops = [] # hull facet equation: dx*x + dy*y + c = 0 - for dx, dy, c in hull_equations: + for dx, dy, c in qhull.equations: # Check if the facet is horizontal if isclose(dx, 0): if basis in ('xz', 'yz', 'rz'): @@ -853,6 +862,7 @@ def get_convex_hull_surfs(qhull, basis='rz'): return surfs_ops + def make_ccw(verts): """Determine whether the vertices are ordered counter-clockwise @@ -877,47 +887,46 @@ def make_ccw(verts): return verts[::-1, :] -def get_ordered_points(tri, groups): - points = [] - for g in groups: - idx = np.unique(tri.simplices[g, :]) - qhull = ConvexHull(tri.points[idx, :]) - points.append(qhull.points[qhull.vertices, :]) - return points +def group_simplices(tri, neighbor_map, group=None): + """Generate a list of convex groups of simplices. -def group_wrapper(tri, simp_dict): - groups = [] - while simp_dict: - groups.append(group_simplices(tri, simp_dict)) - return groups + Parameters + ---------- + tri : scipy.spatial.Delaunay + A Delaunay triangulation of points generated from the polygon. + neighbor_map : dict + A map whose keys are simplex indices for simplices inside the polygon + and whose values are a list of simplex indices that neighbor this + simplex and are also inside the polygon. + group : list + A list of simplex indices that comprise the current convex group. -def group_simplices(tri, simp_dict, group=None): - """Generate a list of convex subsets""" - # If dictionary is empty there's nothing left to do - if not simp_dict: + Returns + ------- + group : list + The list of simplex indices that comprise the complete convex group. + """ + # If neighbor_map is empty there's nothing left to do + if not neighbor_map: return group - # If group is empty grab the next simplex in the dictionary and recurse + # If group is empty, grab the next simplex in the dictionary and recurse if group is None: - sidx = next(iter(simp_dict)) - return group_simplices(tri, simp_dict, group=[sidx]) + sidx = next(iter(neighbor_map)) + return group_simplices(tri, neighbor_map, group=[sidx]) # Otherwise use the last simplex in the group else: - # Remove current simplex from dictionary since it is in a group sidx = group[-1] - neighbors = simp_dict.pop(sidx, []) + # Remove current simplex from dictionary since it is in a group + neighbors = neighbor_map.pop(sidx, []) # For each neighbor check if it is part of the same convex # hull as the rest of the group. If yes, recurse. If no, continue on. for n in neighbors: - if n in group or simp_dict.get(n, None) is None: + if n in group or neighbor_map.get(n, None) is None: continue test_group = group + [n] - #print('group :', group) - #print('test_group :', test_group) test_point_idx = np.unique(tri.simplices[test_group, :]) test_points = tri.points[test_point_idx] - if is_convex(test_points): - group = group_simplices(tri, simp_dict, group=test_group) + # If test_points are convex keep adding to this group + if len(test_points) == len(ConvexHull(test_points).vertices): + group = group_simplices(tri, neighbor_map, group=test_group) return group - -def is_convex(points): - return len(points) == len(ConvexHull(points).vertices) From bf58a46a9cc79e6d52cb84f3fbc9ba6ddc93077c Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 18 Oct 2022 14:56:26 -0400 Subject: [PATCH 1258/2654] cleaning up and moving all methods to instance methods rather than module --- openmc/model/surface_composite.py | 319 ++++++++++----------- tests/unit_tests/test_surface_composite.py | 4 + 2 files changed, 151 insertions(+), 172 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 2036950f5..258a7bae7 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -6,7 +6,8 @@ from scipy.spatial import ConvexHull, Delaunay from matplotlib.path import Path import openmc -from openmc.checkvalue import check_greater_than, check_value +from openmc.checkvalue import (check_greater_than, check_value, + check_iterable_type, check_length) class CompositeSurface(ABC): @@ -641,27 +642,34 @@ class Polygon(CompositeSurface): An Nx2 array of points defining the vertices of the polygon. basis : str, {'rz', 'xy', 'yz', 'xz'} 2D basis set for the polygon. + regions : list of openmc.Region + A list of openmc.Region objects, one for each of the convex polygons + formed during the decomposition of the input polygon. + region : openmc.Union + The union of all the regions comprising the polygon. """ def __init__(self, points, basis='rz'): - # If the last point is the same as the first remove it and order the - # vertices in a counter-clockwise sense. - if np.allclose(points[0, :], points[-1, :]): - points = points[:-1, :] - - # TODO check if path is self intersecting, throw error if yes - self._points = make_ccw(np.asarray(points, dtype=float)) check_value('basis', basis, ('xy', 'yz', 'xz', 'rz')) self._basis = basis + points = np.asarray(points, dtype=float) + check_iterable_type('points', points, float, min_depth=2, max_depth=2) + check_length('points', points[0, :], 2, 2) + + # If the last point is the same as the first, remove it and make sure + # there are still at least 3 points for a valid polygon. + if np.allclose(points[0, :], points[-1, :]): + points = points[:-1, :] + check_length('points', points, 3) + + self._points = points # Create a triangulation of the points. self._tri = Delaunay(self._points, qhull_options='QJ') # Decompose the polygon into groups of simplices forming convex subsets - self._groups = self._decompose_polygon_into_convex_sets() - - # Get the sets of (surface, operator) pairs defining the polygon - self._surfsets = self._get_surfsets() + # and get the sets of (surface, operator) pairs defining the polygon + self._surfsets = self._decompose_polygon_into_convex_sets() # Set surface names as required by CompositeSurface protocol surfnames = [] @@ -671,9 +679,17 @@ class Polygon(CompositeSurface): setattr(self, f'surface_{i}', surf) surfnames.append(f'surface_{i}') i += 1 - self._surfnames = tuple(surfnames) + # Generate a list of regions whose union represents the polygon. + regions = [] + for surfs_ops in self._surfsets: + regions.append([getattr(surf, op)() for surf, op in surfs_ops]) + self._regions = [openmc.Intersection(regs) for regs in regions] + + # Create the union of all the convex subsets + self._region = openmc.Union(self._regions) + def __neg__(self): return self._region @@ -701,23 +717,125 @@ class Polygon(CompositeSurface): return rotation.dot(tangents.T).T @property - def _regions(self): - """Generate a list of regions whose union represents the polygon.""" - regions = [] - for surfs_ops in self._surfsets: - regions.append([getattr(surf, op)() for surf, op in surfs_ops]) - return [openmc.Intersection(regs) for regs in regions] + def regions(self): + return self._regions @property - def _region(self): - return openmc.Union(self._regions) + def region(self): + return self._region + + def _group_simplices(self, neighbor_map, group=None): + """Generate a convex grouping of simplices. + + Parameters + ---------- + neighbor_map : dict + A map whose keys are simplex indices for simplices inside the polygon + and whose values are a list of simplex indices that neighbor this + simplex and are also inside the polygon. + group : list + A list of simplex indices that comprise the current convex group. + + Returns + ------- + group : list + The list of simplex indices that comprise the complete convex group. + """ + # If neighbor_map is empty there's nothing left to do + if not neighbor_map: + return group + # If group is empty, grab the next simplex in the dictionary and recurse + if group is None: + sidx = next(iter(neighbor_map)) + return self._group_simplices(neighbor_map, group=[sidx]) + # Otherwise use the last simplex in the group + else: + sidx = group[-1] + # Remove current simplex from dictionary since it is in a group + neighbors = neighbor_map.pop(sidx, []) + # For each neighbor check if it is part of the same convex + # hull as the rest of the group. If yes, recurse. If no, continue on. + for n in neighbors: + if n in group or neighbor_map.get(n, None) is None: + continue + test_group = group + [n] + test_point_idx = np.unique(self._tri.simplices[test_group, :]) + test_points = self._tri.points[test_point_idx] + # If test_points are convex keep adding to this group + if len(test_points) == len(ConvexHull(test_points).vertices): + group = self._group_simplices(neighbor_map, group=test_group) + return group + + def _get_convex_hull_surfs(self, qhull): + """Generate a list of surfaces given by a set of linear equations + + Parameters + ---------- + qhull : scipy.spatial.ConvexHull + A ConvexHull object representing the sub-region of the polygon. + + Returns + ------- + surfs_ops : list of (surface, operator) tuples + + """ + basis = self.basis + # Collect surface/operator pairs such that the intersection of the + # regions defined by these pairs is the inside of the polygon. + surfs_ops = [] + # hull facet equation: dx*x + dy*y + c = 0 + for dx, dy, c in qhull.equations: + # Check if the facet is horizontal + if isclose(dx, 0): + if basis in ('xz', 'yz', 'rz'): + surf = openmc.ZPlane(z0=-c/dy) + else: + surf = openmc.YPlane(y0=-c/dy) + # if (0, 1).(dx, dy) < 0 we want positive halfspace instead + op = '__pos__' if dy < 0 else '__neg__' + # Check if the facet is vertical + elif isclose(dy, 0): + if basis in ('xy', 'xz'): + surf = openmc.XPlane(x0=-c/dx) + elif basis == 'yz': + surf = openmc.YPlane(y0=-c/dx) + else: + surf = openmc.ZCylinder(r=-c/dx) + # if (1, 0).(dx, dy) < 0 we want positive halfspace instead + op = '__pos__' if dx < 0 else '__neg__' + # Otherwise the facet is at an angle + else: + op = '__neg__' + if basis == 'xy': + surf = openmc.Plane(a=dx, b=dy, d=-c) + elif basis == 'yz': + surf = openmc.Plane(b=dx, c=dy, d=-c) + elif basis == 'xz': + surf = openmc.Plane(a=dx, c=dy, d=-c) + else: + y0 = -c/dy + r2 = dy**2 / dx**2 + # Check if the *slope* of the facet is positive. If dy/dx < 0 + # then we want up to be True for the one-sided cones. + up = dy / dx < 0 + surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=up) + # if (1, -1).(dx, dy) < 0 for up cones we want positive halfspace + # if (1, 1).(dx, dy) < 0 for down cones we want positive halfspace + if (up and dx - dy < 0) or (not up and dx + dy < 0): + op = '__pos__' + else: + op = '__neg__' + + surfs_ops.append((surf, op)) + + return surfs_ops def _decompose_polygon_into_convex_sets(self): """Decompose the Polygon into a set of convex polygons. Returns ------- - list of sets of simplices + surfsets : a list of lists of surface, operator pairs """ # Get centroids of all the simplices and determine if they are inside @@ -740,26 +858,19 @@ class Polygon(CompositeSurface): # left in the neighbor map, group them together into convex sets. groups = [] while neighbor_map: - groups.append(group_simplices(self._tri, neighbor_map)) - - return groups - - def _get_surfsets(self): - """Generate lists of surface, operator pairs for the sub-polygons. - - Returns - ------- - surfsets : a list of lists of surface, operator pairs - """ + groups.append(self._group_simplices(neighbor_map)) + self._groups = groups + # Generate lists of (surface, operator) pairs for each convex + # sub-region. surfsets = [] - for g in self._groups: + for group in groups: # Find all the unique points in the convex group of simplices, # generate the convex hull and find the resulting surfaces and # unary operators that represent this convex subset of the polygon. - idx = np.unique(self._tri.simplices[g, :]) + idx = np.unique(self._tri.simplices[group, :]) qhull = ConvexHull(self._tri.points[idx, :]) - surf_ops = get_convex_hull_surfs(qhull, basis=self.basis) + surf_ops = self._get_convex_hull_surfs(qhull) surfsets.append(surf_ops) return surfsets @@ -794,139 +905,3 @@ class Polygon(CompositeSurface): new_points /= denom[:, None] return type(self)(new_points, basis=self.basis) - - -def get_convex_hull_surfs(qhull, basis='rz'): - """Generate a list of surfaces given by a set of linear equations - - Parameters - ---------- - qhull : scipy.spatial.ConvexHull - A ConvexHull object representing the sub-region of the polygon. - basis : str, {'rz', 'xy', 'yz', 'xz'}, optional - 2D basis set for the polygon. - - Returns - ------- - surfs_ops : list of (surface, operator) tuples - - """ - check_value('basis', basis, ('xy', 'yz', 'xz', 'rz')) - # Collect surface/operator pairs such that the intersection of the - # regions defined by these pairs is the inside of the polygon. - surfs_ops = [] - # hull facet equation: dx*x + dy*y + c = 0 - for dx, dy, c in qhull.equations: - # Check if the facet is horizontal - if isclose(dx, 0): - if basis in ('xz', 'yz', 'rz'): - surf = openmc.ZPlane(z0=-c/dy) - else: - surf = openmc.YPlane(y0=-c/dy) - # if (0, 1).(dx, dy) < 0 we want positive halfspace instead - op = '__pos__' if dy < 0 else '__neg__' - # Check if the facet is vertical - elif isclose(dy, 0): - if basis in ('xy', 'xz'): - surf = openmc.XPlane(x0=-c/dx) - elif basis == 'yz': - surf = openmc.YPlane(y0=-c/dx) - else: - surf = openmc.ZCylinder(r=-c/dx) - # if (1, 0).(dx, dy) < 0 we want positive halfspace instead - op = '__pos__' if dx < 0 else '__neg__' - # Otherwise the facet is at an angle - else: - op = '__neg__' - if basis == 'xy': - surf = openmc.Plane(a=dx, b=dy, d=-c) - elif basis == 'yz': - surf = openmc.Plane(b=dx, c=dy, d=-c) - elif basis == 'xz': - surf = openmc.Plane(a=dx, c=dy, d=-c) - else: - y0 = -c/dy - r2 = dy**2 / dx**2 - # Check if the *slope* of the facet is positive. If dy/dx < 0 - # then we want up to be True for the one-sided cones. - up = dy / dx < 0 - surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=up) - # if (1, -1).(dx, dy) < 0 for up cones we want positive halfspace - # if (1, 1).(dx, dy) < 0 for down cones we want positive halfspace - if (up and dx - dy < 0) or (not up and dx + dy < 0): - op = '__pos__' - else: - op = '__neg__' - - surfs_ops.append((surf, op)) - - return surfs_ops - - -def make_ccw(verts): - """Determine whether the vertices are ordered counter-clockwise - - Parameters - ---------- - verts : np.ndarray (Nx2) - An Nx2 array of coordinate pairs describing the vertices. - - - Returns - ------- - bool : True if vertices are in counter-clockwise order. False otherwise. - - """ - vector = np.empty(verts.shape[0]) - vector[:-1] = (verts[1:, 0] - verts[:-1, 0])*(verts[1:, 1] + verts[:-1, 1]) - vector[-1] = (verts[0, 0] - verts[-1, 0])*(verts[0, 1] + verts[-1, 1]) - - if np.sum(vector) < 0: - return verts - - return verts[::-1, :] - - -def group_simplices(tri, neighbor_map, group=None): - """Generate a list of convex groups of simplices. - - Parameters - ---------- - tri : scipy.spatial.Delaunay - A Delaunay triangulation of points generated from the polygon. - neighbor_map : dict - A map whose keys are simplex indices for simplices inside the polygon - and whose values are a list of simplex indices that neighbor this - simplex and are also inside the polygon. - group : list - A list of simplex indices that comprise the current convex group. - - Returns - ------- - group : list - The list of simplex indices that comprise the complete convex group. - """ - # If neighbor_map is empty there's nothing left to do - if not neighbor_map: - return group - # If group is empty, grab the next simplex in the dictionary and recurse - if group is None: - sidx = next(iter(neighbor_map)) - return group_simplices(tri, neighbor_map, group=[sidx]) - # Otherwise use the last simplex in the group - else: - sidx = group[-1] - # Remove current simplex from dictionary since it is in a group - neighbors = neighbor_map.pop(sidx, []) - # For each neighbor check if it is part of the same convex - # hull as the rest of the group. If yes, recurse. If no, continue on. - for n in neighbors: - if n in group or neighbor_map.get(n, None) is None: - continue - test_group = group + [n] - test_point_idx = np.unique(tri.simplices[test_group, :]) - test_points = tri.points[test_point_idx] - # If test_points are convex keep adding to this group - if len(test_points) == len(ConvexHull(test_points).vertices): - group = group_simplices(tri, neighbor_map, group=test_group) - return group diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 4d680ae7c..0c618250e 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -314,3 +314,7 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): # Make sure repr works repr(s) + +@pytest.mark.parametrize("basis", [("xz",), ("yz",), ("xy",), ("rz",)]) +def test_polygon(basis=basis): + From 13b1bb88d030d2f79ea3e6ebc7ed18b812c332b4 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 18 Oct 2022 17:01:22 -0400 Subject: [PATCH 1259/2654] added unit test --- tests/unit_tests/test_surface_composite.py | 24 ++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 0c618250e..2a77ac5f9 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -315,6 +315,26 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): # Make sure repr works repr(s) -@pytest.mark.parametrize("basis", [("xz",), ("yz",), ("xy",), ("rz",)]) -def test_polygon(basis=basis): +def test_polygon(): + # define a 5 pointed star centered on 1, 1 + star = np.array([[1. , 2. ], + [0.70610737, 1.4045085 ], + [0.04894348, 1.30901699], + [0.52447174, 0.8454915 ], + [0.41221475, 0.19098301], + [1. , 0.5 ], + [1.58778525, 0.19098301], + [1.47552826, 0.8454915 ], + [1.95105652, 1.30901699], + [1.29389263, 1.4045085 ], + [1. , 2. ]]) + points_in = [(1, 1, 0), (0, 1, 1), (1, 0, 1), (.707, .707, 1)] + for i, basis in enumerate(('xy', 'yz', 'xz', 'rz')): + star_poly = openmc.model.Polygon(star, basis=basis) + assert points_in[i] in -star_poly + assert points_in[i] not in +star_poly + assert (0, 0, 0) not in -star_poly + if basis != 'rz': + assert(0, 0, 0) in -star_poly.offset(.6) + From 299525984fc04e0479ffa6ca1d945ca5337f5852 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 18 Oct 2022 20:56:58 -0400 Subject: [PATCH 1260/2654] simplified offset method --- openmc/model/surface_composite.py | 50 ++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 258a7bae7..82ebbfa03 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -662,7 +662,8 @@ class Polygon(CompositeSurface): points = points[:-1, :] check_length('points', points, 3) - self._points = points + # Order the points counter-clockwise (necessary for offset method) + self._points = self._make_ccw(points) # Create a triangulation of the points. self._tri = Delaunay(self._points, qhull_options='QJ') @@ -724,6 +725,29 @@ class Polygon(CompositeSurface): def region(self): return self._region + def _make_ccw(self, points): + """Order a set of points counter-clockwise. + + Parameters + ---------- + points : np.ndarray (Nx2) + An Nx2 array of coordinate pairs describing the vertices. + + Returns + ------- + ordered_points : the input points ordered counter-clockwise + """ + vector = np.empty(points.shape[0]) + this_x, this_y = points[:-1, 0], points[:-1, 1] + next_x, next_y = points[1:, 0], points[1:, 1] + vector[:-1] = (next_x - this_x)*(next_y + this_y) + vector[-1] = (this_x[0] - next_x[-1])*(this_y[0] + next_y[-1]) + + if np.sum(vector) < 0: + return points + + return points[::-1, :] + def _group_simplices(self, neighbor_map, group=None): """Generate a convex grouping of simplices. @@ -883,25 +907,15 @@ class Polygon(CompositeSurface): The distance to offset the polygon by. Positive is outward (expanding) and negative is inward (shrinking). - Returns ------- offset_polygon : openmc.model.Polygon """ - # Get the points of the polygon and outward normals such that - # normals[i] corresponds to the edge between points[i-1] and points[i] - points = self.points - normals = self._normals - normals = np.insert(normals, 0, normals[-1, :], axis=0) - ndotv1 = np.sum(normals[:-1, :]*(points + distance*normals[:-1, :]), - axis=-1, keepdims=True) - ndotv2 = np.sum(normals[1:, :]*(points + distance*normals[1:, :]), - axis=-1, keepdims=True) + normals = np.insert(self._normals, 0, self._normals[-1, :], axis=0) + cos2theta = np.sum(normals[1:, :]*normals[:-1, :], axis=-1, keepdims=True) + costheta = np.cos(np.arccos(cos2theta) / 2) + nvec = (normals[1:, :] + normals[:-1, :]) + unit_nvec = nvec / np.linalg.norm(nvec, axis=-1, keepdims=True) + disp_vec = distance / costheta * unit_nvec - new_points = np.empty_like(points) - denom = normals[:-1, 0]*normals[1:, 1] - normals[:-1, 1]*normals[1:, 0] - new_points[:, 0] = normals[1:, 1]*ndotv1.T - normals[:-1, 1]*ndotv2.T - new_points[:, 1] = -normals[1:, 0]*ndotv1.T + normals[:-1, 0]*ndotv2.T - new_points /= denom[:, None] - - return type(self)(new_points, basis=self.basis) + return type(self)(self.points + disp_vec, basis=self.basis) From fdc3cfcfbba9fe4f48221850757b2c86f415b0d3 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 20 Oct 2022 12:46:29 -0400 Subject: [PATCH 1261/2654] fixed proper boundary_type setting? --- openmc/model/surface_composite.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 82ebbfa03..aeb77c868 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -676,16 +676,18 @@ class Polygon(CompositeSurface): surfnames = [] i = 0 for surfset in self._surfsets: - for surf, op in surfset: - setattr(self, f'surface_{i}', surf) - surfnames.append(f'surface_{i}') - i += 1 + print(surfset) + for surf, op, on_boundary in surfset: + if on_boundary: + setattr(self, f'surface_{i}', surf) + surfnames.append(f'surface_{i}') + i += 1 self._surfnames = tuple(surfnames) # Generate a list of regions whose union represents the polygon. regions = [] for surfs_ops in self._surfsets: - regions.append([getattr(surf, op)() for surf, op in surfs_ops]) + regions.append([getattr(surf, op)() for surf, op, _ in surfs_ops]) self._regions = [openmc.Intersection(regs) for regs in regions] # Create the union of all the convex subsets @@ -717,6 +719,14 @@ class Polygon(CompositeSurface): tangents /= np.linalg.norm(tangents, axis=-1, keepdims=True) return rotation.dot(tangents.T).T + @property + def _equations(self): + normals = self._normals + equations = np.empty((normals.shape[0], 3)) + equations[:, 0:2] = normals + equations[:, 2] = -np.sum(normals*self.points, axis=-1) + return equations + @property def regions(self): return self._regions @@ -804,11 +814,15 @@ class Polygon(CompositeSurface): """ basis = self.basis + boundary_eqns = self._equations # Collect surface/operator pairs such that the intersection of the # regions defined by these pairs is the inside of the polygon. surfs_ops = [] # hull facet equation: dx*x + dy*y + c = 0 for dx, dy, c in qhull.equations: + # check if this facet is on the boundary of the polygon + facet_eq = np.array([dx, dy, c]) + on_boundary = any([np.allclose(facet_eq, eq) for eq in boundary_eqns]) # Check if the facet is horizontal if isclose(dx, 0): if basis in ('xz', 'yz', 'rz'): @@ -850,7 +864,7 @@ class Polygon(CompositeSurface): else: op = '__neg__' - surfs_ops.append((surf, op)) + surfs_ops.append((surf, op, on_boundary)) return surfs_ops From a587f5e1c9966190d1e0f984e41d28145ae3ec2b Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 20 Oct 2022 12:50:33 -0400 Subject: [PATCH 1262/2654] forgot to remove print --- openmc/model/surface_composite.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index aeb77c868..8c47ac130 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -676,7 +676,6 @@ class Polygon(CompositeSurface): surfnames = [] i = 0 for surfset in self._surfsets: - print(surfset) for surf, op, on_boundary in surfset: if on_boundary: setattr(self, f'surface_{i}', surf) From 8ddb045c7d6501db3a85acadd1d9c46f972d6aa2 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 20 Oct 2022 15:28:26 -0400 Subject: [PATCH 1263/2654] added warning about non-transmissive boundary_type --- openmc/model/surface_composite.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 8c47ac130..922e60f0a 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -4,6 +4,7 @@ from math import sqrt, pi, sin, cos, isclose import numpy as np from scipy.spatial import ConvexHull, Delaunay from matplotlib.path import Path +import warnings import openmc from openmc.checkvalue import (check_greater_than, check_value, @@ -702,6 +703,18 @@ class Polygon(CompositeSurface): def _surface_names(self): return self._surfnames + @CompositeSurface.boundary_type.setter + def boundary_type(self, boundary_type): + if boundary_type != 'transmission': + warnings.warn("Setting boundary_type to a value other than " + "'transmission' on Polygon composite surfaces can " + "result in unintended behavior. Please use the " + "regions property of the Polygon to generate " + "individual openmc.Cell objects to avoid unwanted " + "behavior.") + for name in self._surface_names: + getattr(self, name).boundary_type = boundary_type + @property def points(self): return self._points From b0d71b31466b4c1d835e28d11b48b28d0d730bc0 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 8 Nov 2022 21:21:23 -0500 Subject: [PATCH 1264/2654] Apply suggestions from @paulromano code review Co-authored-by: Paul Romano --- openmc/model/surface_composite.py | 10 +++++----- tests/unit_tests/test_surface_composite.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 922e60f0a..3ddaa6653 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -634,17 +634,17 @@ class Polygon(CompositeSurface): ---------- points : np.ndarray An Nx2 array of points defining the vertices of the polygon. - basis : str, {'rz', 'xy', 'yz', 'xz'}, optional + basis : {'rz', 'xy', 'yz', 'xz'}, optional 2D basis set for the polygon. Attributes ---------- points : np.ndarray An Nx2 array of points defining the vertices of the polygon. - basis : str, {'rz', 'xy', 'yz', 'xz'} + basis : {'rz', 'xy', 'yz', 'xz'} 2D basis set for the polygon. regions : list of openmc.Region - A list of openmc.Region objects, one for each of the convex polygons + A list of :class:`openmc.Region` objects, one for each of the convex polygons formed during the decomposition of the input polygon. region : openmc.Union The union of all the regions comprising the polygon. @@ -726,7 +726,7 @@ class Polygon(CompositeSurface): @property def _normals(self): """Generate the outward normal unit vectors for the polygon.""" - rotation = np.array([[0, 1], [-1, 0]]) + rotation = np.array([[0., 1.], [-1., 0.]]) tangents = np.diff(self._points, axis=0, append=[self._points[0, :]]) tangents /= np.linalg.norm(tangents, axis=-1, keepdims=True) return rotation.dot(tangents.T).T @@ -735,7 +735,7 @@ class Polygon(CompositeSurface): def _equations(self): normals = self._normals equations = np.empty((normals.shape[0], 3)) - equations[:, 0:2] = normals + equations[:, :2] = normals equations[:, 2] = -np.sum(normals*self.points, axis=-1) return equations diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 2a77ac5f9..14579df22 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -335,6 +335,6 @@ def test_polygon(): assert points_in[i] not in +star_poly assert (0, 0, 0) not in -star_poly if basis != 'rz': - assert(0, 0, 0) in -star_poly.offset(.6) + assert (0, 0, 0) in -star_poly.offset(.6) From d314bedbd7951be8e8844e439c0349de9b621040 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 8 Nov 2022 21:40:16 -0500 Subject: [PATCH 1265/2654] improving documentation and style --- docs/source/pythonapi/model.rst | 1 + openmc/model/surface_composite.py | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index 636935c6b..cdabee396 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -31,6 +31,7 @@ Composite Surfaces openmc.model.XConeOneSided openmc.model.YConeOneSided openmc.model.ZConeOneSided + openmc.model.Polygon TRISO Fuel Modeling ------------------- diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 3ddaa6653..5229e6f3d 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -1,10 +1,12 @@ from abc import ABC, abstractmethod from copy import copy from math import sqrt, pi, sin, cos, isclose +import warnings +import operator + import numpy as np from scipy.spatial import ConvexHull, Delaunay from matplotlib.path import Path -import warnings import openmc from openmc.checkvalue import (check_greater_than, check_value, @@ -635,7 +637,11 @@ class Polygon(CompositeSurface): points : np.ndarray An Nx2 array of points defining the vertices of the polygon. basis : {'rz', 'xy', 'yz', 'xz'}, optional - 2D basis set for the polygon. + 2D basis set for the polygon. The polygon is two dimensional and has + infinite extent in the third (unspecified) dimension. For example, the + 'xy' basis produces a polygon with infinite extent in the +/- z + direction. For the 'rz' basis the phi extent is infinite, thus forming + an axisymmetric surface. Attributes ---------- @@ -687,7 +693,7 @@ class Polygon(CompositeSurface): # Generate a list of regions whose union represents the polygon. regions = [] for surfs_ops in self._surfsets: - regions.append([getattr(surf, op)() for surf, op, _ in surfs_ops]) + regions.append([op(surf) for surf, op, _ in surfs_ops]) self._regions = [openmc.Intersection(regs) for regs in regions] # Create the union of all the convex subsets @@ -842,7 +848,7 @@ class Polygon(CompositeSurface): else: surf = openmc.YPlane(y0=-c/dy) # if (0, 1).(dx, dy) < 0 we want positive halfspace instead - op = '__pos__' if dy < 0 else '__neg__' + op = operator.pos if dy < 0 else operator.neg # Check if the facet is vertical elif isclose(dy, 0): if basis in ('xy', 'xz'): @@ -852,10 +858,10 @@ class Polygon(CompositeSurface): else: surf = openmc.ZCylinder(r=-c/dx) # if (1, 0).(dx, dy) < 0 we want positive halfspace instead - op = '__pos__' if dx < 0 else '__neg__' + op = operator.pos if dx < 0 else operator.neg # Otherwise the facet is at an angle else: - op = '__neg__' + op = operator.neg if basis == 'xy': surf = openmc.Plane(a=dx, b=dy, d=-c) elif basis == 'yz': @@ -871,10 +877,9 @@ class Polygon(CompositeSurface): surf = openmc.model.ZConeOneSided(z0=y0, r2=r2, up=up) # if (1, -1).(dx, dy) < 0 for up cones we want positive halfspace # if (1, 1).(dx, dy) < 0 for down cones we want positive halfspace + # otherwise we keep the negative halfspace operator if (up and dx - dy < 0) or (not up and dx + dy < 0): - op = '__pos__' - else: - op = '__neg__' + op = operator.pos surfs_ops.append((surf, op, on_boundary)) From 2adbe971942f134babcfae92090f8fc9bc374fad Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 10 Nov 2022 11:14:20 -0500 Subject: [PATCH 1266/2654] updated algorithms and documentation --- openmc/model/surface_composite.py | 19 +++++++++++++------ tests/unit_tests/test_surface_composite.py | 7 ++++--- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 5229e6f3d..5d1553a38 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -732,9 +732,17 @@ class Polygon(CompositeSurface): @property def _normals(self): """Generate the outward normal unit vectors for the polygon.""" + # Rotation matrix for 90 degree clockwise rotation (-90 degrees about z + # axis for an 'xy' basis). rotation = np.array([[0., 1.], [-1., 0.]]) + # Get the unit vectors that point from one point in the polygon to the + # next given that they are ordered counterclockwise and that the final + # point is connected to the first point tangents = np.diff(self._points, axis=0, append=[self._points[0, :]]) tangents /= np.linalg.norm(tangents, axis=-1, keepdims=True) + # Rotate the tangent vectors clockwise by 90 degrees, which for a + # counter-clockwise ordered polygon will produce the outward normal + # vectors. return rotation.dot(tangents.T).T @property @@ -765,13 +773,12 @@ class Polygon(CompositeSurface): ------- ordered_points : the input points ordered counter-clockwise """ - vector = np.empty(points.shape[0]) - this_x, this_y = points[:-1, 0], points[:-1, 1] - next_x, next_y = points[1:, 0], points[1:, 1] - vector[:-1] = (next_x - this_x)*(next_y + this_y) - vector[-1] = (this_x[0] - next_x[-1])*(this_y[0] + next_y[-1]) + # Calculates twice the signed area of the polygon using the "Shoelace + # Formula" https://en.wikipedia.org/wiki/Shoelace_formula + xpts, ypts = points.T - if np.sum(vector) < 0: + # If signed area is positive the curve is oriented counter-clockwise + if np.sum(ypts*(np.roll(xpts, 1) - np.roll(xpts, -1))) > 0: return points return points[::-1, :] diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 14579df22..dbfaa62b1 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -332,9 +332,10 @@ def test_polygon(): for i, basis in enumerate(('xy', 'yz', 'xz', 'rz')): star_poly = openmc.model.Polygon(star, basis=basis) assert points_in[i] in -star_poly + assert any([points_in[i] in reg for reg in star_poly.regions]) assert points_in[i] not in +star_poly assert (0, 0, 0) not in -star_poly if basis != 'rz': - assert (0, 0, 0) in -star_poly.offset(.6) - - + offset_star = star_poly.offset(.6) + assert (0, 0, 0) in -offset_star + assert any([(0, 0, 0) in reg for reg in offset_star.regions]) From 2283e08fdcccbc4b2f49f6fc212f2d424fb419b7 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 10 Nov 2022 13:00:11 -0500 Subject: [PATCH 1267/2654] add abs_tol to prevent cones with infinite or 0 slope --- openmc/model/surface_composite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 5d1553a38..002fad9d9 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -849,7 +849,7 @@ class Polygon(CompositeSurface): facet_eq = np.array([dx, dy, c]) on_boundary = any([np.allclose(facet_eq, eq) for eq in boundary_eqns]) # Check if the facet is horizontal - if isclose(dx, 0): + if isclose(dx, 0, abs_tol=1e-8): if basis in ('xz', 'yz', 'rz'): surf = openmc.ZPlane(z0=-c/dy) else: @@ -857,7 +857,7 @@ class Polygon(CompositeSurface): # if (0, 1).(dx, dy) < 0 we want positive halfspace instead op = operator.pos if dy < 0 else operator.neg # Check if the facet is vertical - elif isclose(dy, 0): + elif isclose(dy, 0, abs_tol=1e-8): if basis in ('xy', 'xz'): surf = openmc.XPlane(x0=-c/dx) elif basis == 'yz': From ae785fda5f821e9144b1c93e5344d788c7382ce7 Mon Sep 17 00:00:00 2001 From: Coline Larmier Date: Thu, 10 Nov 2022 15:14:09 +0100 Subject: [PATCH 1268/2654] Fix the case where the yield is zero. Problem detected in the context of a code-to-code comparison between OpenMC and TRIPOLI-4: - configuration: sphere of radius R = 30 cm containing the isotope ZR93 at 293K - sphere irradiated at the center by an isotropic, mono-energy, point source (E_0 = 14.1 MeV) - data from JEFF-3.3 For some isotopes, namely ZR93 at 293K, the sampled yield can be equal to 0 (namely for MT=5: interaction "n-other"). In such a case, it is necessary to deactivate the particle. --- src/physics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/physics.cpp b/src/physics.cpp index bcdcf7ecf..ae59b49cb 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -1127,7 +1127,7 @@ void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p) // evaluate yield double yield = (*rx.products_[0].yield_)(E_in); - if (std::floor(yield) == yield) { + if (std::floor(yield) == yield && yield > 0) { // If yield is integral, create exactly that many secondary particles for (int i = 0; i < static_cast(std::round(yield)) - 1; ++i) { p.create_secondary(p.wgt(), p.u(), p.E(), ParticleType::neutron); From 6ede028b39a021636ae44873e13b93859d957e80 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 11 Nov 2022 20:50:36 -0600 Subject: [PATCH 1269/2654] Prevent out-of-bounds memory access on Compton profile data --- src/photon.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/photon.cpp b/src/photon.cpp index 2f9bc5e3d..a500ff2d4 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -226,8 +226,9 @@ PhotonInteraction::PhotonInteraction(hid_t group) // Create Compton profile CDF auto n_profile = data::compton_profile_pz.size(); - profile_cdf_ = xt::empty({n_shell, n_profile}); - for (int i = 0; i < profile_pdf_.shape(0); ++i) { + auto n_shell_compton = profile_pdf_.shape(0); + profile_cdf_ = xt::empty({n_shell_compton, n_profile}); + for (int i = 0; i < n_shell_compton; ++i) { double c = 0.0; profile_cdf_(i, 0) = 0.0; for (int j = 0; j < n_profile - 1; ++j) { @@ -409,6 +410,13 @@ void PhotonInteraction::compton_scatter(double alpha, bool doppler, double E_out; this->compton_doppler(alpha, *mu, &E_out, i_shell, seed); *alpha_out = E_out / MASS_ELECTRON_EV; + + // It's possible for the Compton profile data to have more shells than + // there are in the ENDF data. Make sure the shell index doesn't end up + // out of bounds. + if (*i_shell >= shells_.size()) { + *i_shell = -1; + } } else { *i_shell = -1; } From a28a175261c7b8ddab4c33c8e88b522fa9f043e4 Mon Sep 17 00:00:00 2001 From: myerspat Date: Sat, 12 Nov 2022 13:19:21 -0500 Subject: [PATCH 1270/2654] Added catch2 submodule for cpp testing --- .gitmodules | 3 +++ vendor/Catch2 | 1 + 2 files changed, 4 insertions(+) create mode 160000 vendor/Catch2 diff --git a/.gitmodules b/.gitmodules index ff9120010..b16ecb580 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "vendor/fmt"] path = vendor/fmt url = https://github.com/fmtlib/fmt.git +[submodule "vendor/Catch2"] + path = vendor/Catch2 + url = git@github.com:catchorg/Catch2.git diff --git a/vendor/Catch2 b/vendor/Catch2 new file mode 160000 index 000000000..41990e0fe --- /dev/null +++ b/vendor/Catch2 @@ -0,0 +1 @@ +Subproject commit 41990e0fe6274d716134eecfd4d780e976c8fbf5 From 4072fc430b763e7026e0cefff11fbda6dc019eb8 Mon Sep 17 00:00:00 2001 From: myerspat Date: Sat, 12 Nov 2022 13:31:27 -0500 Subject: [PATCH 1271/2654] Removing excess probability vector --- include/openmc/distribution.h | 9 ++++----- src/distribution.cpp | 16 ++++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index de1664275..e2c710ae9 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -48,14 +48,13 @@ public: // Properties const vector& x() const { return x_; } const vector& p() const { return p_; } + const vector& alias() const { return alias_; } private: vector x_; //!< Possible outcomes - vector p_; //!< Probability of each outcome - - //! Alies method tables - vector prob_; - vector alias_; + vector + p_; //!< Probability of each outcome, mapped to alias method table + vector alias_; //!< Alias table //! Normalize distribution so that probabilities sum to unity void normalize(); diff --git a/src/distribution.cpp b/src/distribution.cpp index 55b6c53b7..436e34116 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -38,17 +38,16 @@ Discrete::Discrete(const double* x, const double* p, int n) normalize(); // Vectors for large and small probabilities based on 1/n - vector large; - vector small; + vector large; + vector small; // Set and allocate memory - prob_ = p_; alias_.reserve(n); // Fill large and small vectors based on 1/n for (int i = 0; i < n; i++) { - prob_[i] *= n; - if (prob_[i] > 1.0) { + p_[i] *= n; + if (p_[i] > 1.0) { large.push_back(i); } else { small.push_back(i); @@ -63,11 +62,11 @@ Discrete::Discrete(const double* x, const double* p, int n) small.pop_back(); // Update probability and alias based on Vose's algorithm - prob_[k] += prob_[j] - 1; + p_[k] += p_[j] - 1.0; alias_[j] = k; // Remove last vector element and or move large index to small vector - if (prob_[k] < 1.0) { + if (p_[k] < 1.0) { small.push_back(k); large.pop_back(); } @@ -76,10 +75,11 @@ Discrete::Discrete(const double* x, const double* p, int n) double Discrete::sample(uint64_t* seed) const { + // Alias sampling of discrete distribution int n = x_.size(); if (n > 1) { int u = prn(seed) * n; - if (prn(seed) < prob_[u]) { + if (prn(seed) < p_[u]) { return x_[u]; } else { return x_[alias_[u]]; From d65ac06bd628f9ee540248e2eb6a33e4417b610f Mon Sep 17 00:00:00 2001 From: myerspat Date: Sat, 12 Nov 2022 13:32:41 -0500 Subject: [PATCH 1272/2654] Catch2 unit testing capabilities and alias sampling unit test --- CMakeLists.txt | 12 +++++++ tests/cpp_unit_tests/CMakeLists.txt | 9 +++++ tests/cpp_unit_tests/test_distribution.cpp | 40 ++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 tests/cpp_unit_tests/CMakeLists.txt create mode 100644 tests/cpp_unit_tests/test_distribution.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 521b46cfc..e0a98b1e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,6 +265,14 @@ if (NOT gsl-lite_FOUND) target_compile_definitions(gsl-lite-v1 INTERFACE gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=1) endif() +#=============================================================================== +# Catch2 library +#=============================================================================== +find_package_write_status(Catch2) +if (NOT Catch2) + add_subdirectory(vendor/Catch2) +endif() + #=============================================================================== # RPATH information #=============================================================================== @@ -482,6 +490,10 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() +# Add cpp tests directory +include(CTest) +add_subdirectory(tests/cpp_unit_tests) + #=============================================================================== # openmc executable #=============================================================================== diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt new file mode 100644 index 000000000..c26547f77 --- /dev/null +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -0,0 +1,9 @@ +set(TEST_NAMES + test_distribution +) + +foreach(test ${TEST_NAMES}) + add_executable(${test} ${test}.cpp) + target_link_libraries(${test} Catch2::Catch2WithMain libopenmc) + add_test(NAME ${test} COMMAND ${test} WORKING_DIRECTORY ${UNIT_TEST_BIN_OUTPUT_DIR}) +endforeach() diff --git a/tests/cpp_unit_tests/test_distribution.cpp b/tests/cpp_unit_tests/test_distribution.cpp new file mode 100644 index 000000000..772fc136a --- /dev/null +++ b/tests/cpp_unit_tests/test_distribution.cpp @@ -0,0 +1,40 @@ +#include "openmc/distribution.h" +#include "openmc/random_lcg.h" +#include + +TEST_CASE("Test alias method sampling of a discrete distribution") +{ + int n_samples = 1e6; + double x[5] = {-1.6, 1.1, 20.3, 4.7, 0.9}; + double p[5] = {0.2, 0.1, 0.5, 0.05, 0.15}; + double samples[n_samples]; + + // Initialize distribution + openmc::Discrete dist(x, p, 5); + uint64_t seed = openmc::init_seed(0, 0); + + // Calculate expected distribution mean + double mean = 0.0; + for (size_t i = 0; i < 5; i++) { + mean += x[i] * p[i]; + } + + // Sample distribution and calculate mean + double dist_mean = 0.0; + for (size_t i = 0; i < n_samples; i++) { + samples[i] = dist.sample(&seed); + dist_mean += samples[i]; + } + dist_mean /= n_samples; + + // Calculate standard deviation + double std = 0.0; + for (size_t i = 0; i < n_samples; i++) { + std += (samples[i] - dist_mean) * (samples[i] - dist_mean); + } + std /= n_samples; + + // Require sampled distribution mean is within 3 standard deviations of the + // expected mean + REQUIRE(std::abs(dist_mean - mean) < 3 * std); +} From 2aef8052e9277fe2598b40162e2daaaf616741e8 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sun, 13 Nov 2022 16:11:23 +0000 Subject: [PATCH 1273/2654] added acceptable keys to help user --- openmc/config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openmc/config.py b/openmc/config.py index 087a8c27e..3b8992536 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -42,7 +42,9 @@ class _Config(MutableMapping): # Reset photon source data since it relies on chain file _DECAY_PHOTON_ENERGY.clear() else: - raise KeyError(f'Unrecognized config key: {key}') + raise KeyError(f'Unrecognized config key: {key}. Acceptable keys ' + 'are "cross_sections", "mg_cross_sections" and ' + '"chain_file"') def __iter__(self): return iter(self._mapping) From 70981bcd5df1fde7e6a26376dd7ba8f8587b87c2 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 14 Nov 2022 13:05:22 -0600 Subject: [PATCH 1274/2654] Correction to error message regarding WW shape --- src/weight_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index f0431f71f..a433cc6b3 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -184,7 +184,7 @@ WeightWindows::WeightWindows(pugi::xml_node node) fmt::format("In weight window domain {} the number of spatial " "energy/spatial bins ({}) does not match the number " "of weight bins ({})", - id_, num_energy_bins, num_weight_bins); + id_, num_energy_bins * num_spatial_bins, num_weight_bins); fatal_error(err_msg); } } From dc5f2746d3a2c0355402e3141f55dd0cee2ce4d6 Mon Sep 17 00:00:00 2001 From: josh Date: Mon, 14 Nov 2022 20:36:11 +0000 Subject: [PATCH 1275/2654] avoid double reading thermal scattering libraries --- src/thermal.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/thermal.cpp b/src/thermal.cpp index b54f07b36..982bf226a 100644 --- a/src/thermal.cpp +++ b/src/thermal.cpp @@ -119,20 +119,22 @@ ThermalScattering::ThermalScattering( if (!found) { // If no pairs found, check if the desired temperature falls within // bounds' tolerance - if (std::abs(T - temps_available[0]) <= - settings::temperature_tolerance) { + if (std::abs(T - temps_available[0]) <= settings::temperature_tolerance){ + if (std::find(temps_to_read.begin(), temps_to_read.end(), std::round(temps_available[0])) == + temps_to_read.end()) { temps_to_read.push_back(std::round(temps_available[0])); - break; - } - if (std::abs(T - temps_available[n - 1]) <= - settings::temperature_tolerance) { + }} + else if (std::abs(T - temps_available[n - 1]) <= settings::temperature_tolerance){ + if (std::find(temps_to_read.begin(), temps_to_read.end(), std::round(temps_available[n - 1])) == + temps_to_read.end()){ temps_to_read.push_back(std::round(temps_available[n - 1])); - break; - } - fatal_error( + }} + else { + fatal_error( fmt::format("Nuclear data library does not contain cross " "sections for {} at temperatures that bound {} K.", name_, std::round(T))); + } } } } From b2d5ca1176305a55f46836da7752aa7d4936d224 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 14 Nov 2022 19:50:47 -0600 Subject: [PATCH 1276/2654] Fixing a typo and adding some clarity --- src/weight_windows.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index a433cc6b3..e8e8f4b05 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -181,9 +181,9 @@ WeightWindows::WeightWindows(pugi::xml_node node) int num_weight_bins = lower_ww_.size(); if (num_weight_bins != num_spatial_bins * num_energy_bins) { auto err_msg = - fmt::format("In weight window domain {} the number of spatial " + fmt::format("In weight window domain {} the number of " "energy/spatial bins ({}) does not match the number " - "of weight bins ({})", + "of weight bins provided ({})", id_, num_energy_bins * num_spatial_bins, num_weight_bins); fatal_error(err_msg); } From e224adf4313056e8dfb8700126d7329511de0721 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 16 Nov 2022 10:31:15 +0100 Subject: [PATCH 1277/2654] follow source code conventions Co-authored-by: Paul Romano --- include/openmc/state_point.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 2d92c935a..698ed2c93 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -26,7 +26,7 @@ void restart_set_keff(); void write_unstructured_mesh_results(); #ifdef OPENMC_MCPL -void write_mcpl_source_point(const char *filename_, bool surf_source_bank = false); +void write_mcpl_source_point(const char* filename, bool surf_source_bank = false); void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); #endif From b2320ae1d477d7f3d932a406eb2989eee5cf37e3 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 16 Nov 2022 13:42:25 +0100 Subject: [PATCH 1278/2654] not needed since mcpl-file is created by openmc --- .../source_mcpl_file/gen_dummy_mcpl.c | 98 ------------------- 1 file changed, 98 deletions(-) delete mode 100644 tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c diff --git a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c b/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c deleted file mode 100644 index 61eea95c6..000000000 --- a/tests/regression_tests/source_mcpl_file/gen_dummy_mcpl.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include - -const int batches=10; -const int particles=10000; - -double rand01(){ - double r=rand()/((double) RAND_MAX); - return r; -} - - -int main(int argc, char **argv){ - char outfilename[128]; - snprintf(outfilename,127,"source.%d.mcpl",batches); - - /*generate an mcpl_header_of sorts*/ - mcpl_outfile_t outfile=mcpl_create_outfile(outfilename); - mcpl_particle_t *particle, Particle; - - char line[256]; - snprintf(line,255,"gen_dummy_mcpl.c"); - mcpl_hdr_set_srcname(outfile,line); - mcpl_enable_universal_pdgcode(outfile,2112);/*all particles are neutrons*/ - snprintf(line,255,"Dummy MCPL-file for testing OpenMC mcpl input"); - mcpl_hdr_add_comment(outfile,line); - - /*also add the instrument file and the command line as blobs*/ - FILE *fp; - if( (fp=fopen("gen_dummy_mcpl.c","rb"))!=NULL){ - unsigned char *buffer; - int size,status; - /*find the file size by seeking to end, "tell" the position, and then go back again*/ - fseek(fp, 0L, SEEK_END); - size = ftell(fp); // get current file pointer - fseek(fp, 0L, SEEK_SET); // seek back to beginning of file - if ( size && (buffer=malloc(size))!=NULL){ - if (size!=(fread(buffer,1,size,fp))){ - fprintf(stderr,"Warning: c source generator file not read cleanly\n"); - } - mcpl_hdr_add_data(outfile, "mcpl_point_source_file_generator", size, buffer); - free(buffer); - } - fclose(fp); - } else { - fprintf(stderr,"Warning: could not open c source generator file, hence not embedded.\n"); - } - - - /*the main particle loop*/ - particle=&Particle; - int i; - srand(1234); - for (i=0;iposition[0]=0; - particle->position[1]=0; - particle->position[2]=0; - - /*generate a random direction on unit sphere*/ - double nrm=2.0; - double vx,vy,vz; - int iter=0; - do { - if(iter>100){ - printf("Warning: Exceeded max random vector attempts: at loop %d -> %g %d\n",i,nrm,iter); - } - vx=rand01()*2.0-1.0; - vy=rand01()*2.0-1.0; - vz=rand01()*2.0-1.0; - nrm=(vx*vx + vy*vy + vz*vz); - iter++; - } while (nrm>1.0); - vx/=sqrt(nrm); - vy/=sqrt(nrm); - vz/=sqrt(nrm); - particle->direction[0]=vx; - particle->direction[1]=vy; - particle->direction[2]=vz; - - /*generate the kinetic energy (in MeV) of the particle*/ - particle->ekin=1e-3; - - /*set time=0*/ - particle->time=0; - /*set weight*/ - particle->weight=1; - - particle->userflags=0; - mcpl_add_particle(outfile,particle); - } - mcpl_close_outfile(outfile); -} From 3e60d51f904ca413030716aa1882866bebab8c23 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 16 Nov 2022 13:54:08 +0100 Subject: [PATCH 1279/2654] from_xml mcpl-settings functionality --- openmc/settings.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 0937a3e48..b2c184f78 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1341,13 +1341,15 @@ class Settings: def _surf_source_write_from_xml_element(self, root): elem = root.find('surf_source_write') if elem is not None: - for key in ('surface_ids', 'max_particles'): + for key in ('surface_ids', 'max_particles','mcpl'): value = get_text(elem, key) if value is not None: if key == 'surface_ids': value = [int(x) for x in value.split()] elif key in ('max_particles'): value = int(value) + elif key == 'mcpl': + value = True self.surf_source_write[key] = value def _confidence_intervals_from_xml_element(self, root): From d6a4a3ecb9d14f90e3232c55360d5998beccd343 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Nov 2022 15:10:11 -0600 Subject: [PATCH 1280/2654] Produce light particles from decay --- openmc/deplete/chain.py | 22 +++++++--- openmc/deplete/independent_operator.py | 6 +-- openmc/deplete/stepresult.py | 26 ++++++----- .../unit_tests/test_deplete_decay_products.py | 43 +++++++++++++++++++ 4 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 tests/unit_tests/test_deplete_decay_products.py diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index 33ac8a342..f439cedc3 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -630,15 +630,27 @@ class Chain: # Gain from radioactive decay if nuc.n_decay_modes != 0: - for _, target, branching_ratio in nuc.decay_modes: - # Allow for total annihilation for debug purposes - if target is not None: - branch_val = branching_ratio * decay_constant + for decay_type, target, branching_ratio in nuc.decay_modes: + branch_val = branching_ratio * decay_constant - if branch_val != 0.0: + # Allow for total annihilation for debug purposes + if branch_val != 0.0: + if target is not None: k = self.nuclide_dict[target] matrix[k, i] += branch_val + # Produce alphas and protons from decay + if 'alpha' in decay_type: + k = self.nuclide_dict.get('He4') + if k is not None: + count = decay_type.count('alpha') + matrix[k, i] += count * branch_val + elif 'p' in decay_type: + k = self.nuclide_dict.get('H1') + if k is not None: + count = decay_type.count('p') + matrix[k, i] += count * branch_val + if nuc.name in rates.index_nuc: # Extract all reactions for this nuclide in this cell nuc_ind = rates.index_nuc[nuc.name] diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index f628a7db1..a8249a98e 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -150,7 +150,7 @@ class IndependentOperator(OpenMCOperator): @classmethod def from_nuclides(cls, volume, nuclides, micro_xs, - chain_file, + chain_file=None, nuc_units='atom/b-cm', keff=None, normalization_mode='fission-q', @@ -170,9 +170,9 @@ class IndependentOperator(OpenMCOperator): values. micro_xs : MicroXS One-group microscopic cross sections. - chain_file : str + chain_file : str, optional Path to the depletion chain XML file. - nuc_units : {'atom/cm3', 'atom/b-cm'} + nuc_units : {'atom/cm3', 'atom/b-cm'}, optional Units for nuclide concentration. keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index c8b35a1fa..042fa46a1 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -318,10 +318,11 @@ class StepResult: chunks=(1, 1, n_mats, n_nuc_number), dtype='float64') - handle.create_dataset("reaction rates", (1, n_stages, n_mats, n_nuc_rxn, n_rxn), - maxshape=(None, n_stages, n_mats, n_nuc_rxn, n_rxn), - chunks=(1, 1, n_mats, n_nuc_rxn, n_rxn), - dtype='float64') + if n_nuc_rxn > 0 and n_rxn > 0: + handle.create_dataset("reaction rates", (1, n_stages, n_mats, n_nuc_rxn, n_rxn), + maxshape=(None, n_stages, n_mats, n_nuc_rxn, n_rxn), + chunks=(1, 1, n_mats, n_nuc_rxn, n_rxn), + dtype='float64') handle.create_dataset("eigenvalues", (1, n_stages, 2), maxshape=(None, n_stages, 2), dtype='float64') @@ -358,7 +359,9 @@ class StepResult: # Grab handles number_dset = handle["/number"] - rxn_dset = handle["/reaction rates"] + has_reactions = ("reaction rates" in handle) + if has_reactions: + rxn_dset = handle["/reaction rates"] eigenvalues_dset = handle["/eigenvalues"] time_dset = handle["/time"] source_rate_dset = handle["/source_rate"] @@ -375,9 +378,10 @@ class StepResult: number_shape[0] = new_shape number_dset.resize(number_shape) - rxn_shape = list(rxn_dset.shape) - rxn_shape[0] = new_shape - rxn_dset.resize(rxn_shape) + if has_reactions: + rxn_shape = list(rxn_dset.shape) + rxn_shape[0] = new_shape + rxn_dset.resize(rxn_shape) eigenvalues_shape = list(eigenvalues_dset.shape) eigenvalues_shape[0] = new_shape @@ -407,7 +411,8 @@ class StepResult: high = max(inds) for i in range(n_stages): number_dset[index, i, low:high+1] = self.data[i] - rxn_dset[index, i, low:high+1] = self.rates[i] + if has_reactions: + rxn_dset[index, i, low:high+1] = self.rates[i] if comm.rank == 0: eigenvalues_dset[index, i] = self.k[i] if comm.rank == 0: @@ -483,7 +488,8 @@ class StepResult: for i in range(results.n_stages): rate = ReactionRates(results.index_mat, rxn_nuc_to_ind, rxn_to_ind, True) - rate[:] = handle["/reaction rates"][step, i, :, :, :] + if "reaction rates" in handle: + rate[:] = handle["/reaction rates"][step, i, :, :, :] results.rates.append(rate) return results diff --git a/tests/unit_tests/test_deplete_decay_products.py b/tests/unit_tests/test_deplete_decay_products.py new file mode 100644 index 000000000..34ca1b067 --- /dev/null +++ b/tests/unit_tests/test_deplete_decay_products.py @@ -0,0 +1,43 @@ +import openmc.deplete +import pytest + + +def test_deplete_decay_products(run_in_tmpdir): + # Create chain file with H1, He4, and Li5 + with open('test_chain.xml', 'w') as chain_file: + chain_file.write(""" + + + + + + + + + """) + + # Create depletion operator with no reactions + micro_xs = openmc.deplete.MicroXS() + op = openmc.deplete.IndependentOperator.from_nuclides( + volume=1.0, + nuclides={'Li5': 1.0}, + micro_xs=micro_xs, + chain_file='test_chain.xml', + normalization_mode='source-rate' + ) + + # Create time-integrator and integrate + integrator = openmc.deplete.PredictorIntegrator( + op, timesteps=[1.0], source_rates=[0.0], timestep_units='d' + ) + integrator.integrate(final_step=False) + + # Get concentration of H1 and He4 + results = openmc.deplete.Results('depletion_results.h5') + _, h1 = results.get_atoms("1", "H1") + _, he4 = results.get_atoms("1", "He4") + + # Since we started with 1e24 atoms of Li5, we should have 1e24 atoms of both + # H1 and He4 + assert h1[1] == pytest.approx(1e24) + assert he4[1] == pytest.approx(1e24) From cf96ddf8bbedac4d72e1730e313d5b7a9cd94284 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:47:03 +0100 Subject: [PATCH 1281/2654] Basic introduction to NCrystal Included references to the main papers and documentation --- docs/source/methods/cross_sections.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/source/methods/cross_sections.rst b/docs/source/methods/cross_sections.rst index 3396d7f25..c700b3f2d 100644 --- a/docs/source/methods/cross_sections.rst +++ b/docs/source/methods/cross_sections.rst @@ -178,6 +178,24 @@ been selected. There are three methods available: section data is loaded for a single temperature and is used in the unresolved resonance and fast energy ranges. +------------------ +NCrystal materials +------------------ + +As an alternative of the standard thermal scattering treatment using :math:`S(\alpha,\beta)` +tables, OpenMC allows to create materials using NCrystal_. In addition to the regular thermal elastic, +and thermal inelastic processes, NCrystal allows the generation of models for materials that +cannot currently included in ACE files such as oriented single crystals (see the `NCrystal paper`_), +and further extend the physics `using plugins`_. Thermal scattering kernels are generated on +the fly from dynamic and structural data, or loaded from :math:`S(\alpha,\beta)` tables converted +from ENDF6 evaluations. These kernels are sampled in a direct way using a fast `rejection algorithm`_ +that does not require previous processing. A `large library` of materials is already included in +the NCrystal distribution, and new materials can be easily defined from scratch in the `NCMAT format` +or `combining existing files`. + +The compositions of the materials defined in NCrystal are passed on to OpenMC all other reactions +except for thermal neutron scattering are handled by continuous energy ACE libraries. + ---------------- Multi-Group Data ---------------- @@ -279,3 +297,10 @@ or even isotropic scattering. .. _ENDF/B data: https://www.nndc.bnl.gov/endf-b8.0/ .. _Leppanen: https://doi.org/10.1016/j.anucene.2009.03.019 .. _algorithms: http://ab-initio.mit.edu/wiki/index.php/Faddeeva_Package +.. _NCrystal: https://github.com/mctools/ncrystal +.. _NCrystal paper: https://doi.org/10.1016/j.cpc.2019.07.015 +.. _using plugins: https://doi.org/10.1016/j.cpc.2021.108082 +.. _rejection algorithm: https://doi.org/10.1016/j.jcp.2018.11.043 +.. _large library: https://github.com/mctools/ncrystal/wiki/Data-library +.. _NCMAT format: https://github.com/mctools/ncrystal/wiki/NCMAT-format +.. _combining existing files: https://github.com/mctools/ncrystal/wiki/Announcement-Release3.0.0#2-multiphase-materials From 24572a71f22b588eb628e855618a4a4a27a63e4c Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Thu, 17 Nov 2022 16:33:48 +0100 Subject: [PATCH 1282/2654] Added simple NCrystal test --- tests/regression_tests/ncrystal/__init__.py | 0 .../regression_tests/ncrystal/inputs_true.dat | 45 +++++ .../ncrystal/results_true.dat | 181 ++++++++++++++++++ tests/regression_tests/ncrystal/test.py | 70 +++++++ 4 files changed, 296 insertions(+) create mode 100644 tests/regression_tests/ncrystal/__init__.py create mode 100644 tests/regression_tests/ncrystal/inputs_true.dat create mode 100644 tests/regression_tests/ncrystal/results_true.dat create mode 100644 tests/regression_tests/ncrystal/test.py diff --git a/tests/regression_tests/ncrystal/__init__.py b/tests/regression_tests/ncrystal/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/ncrystal/inputs_true.dat b/tests/regression_tests/ncrystal/inputs_true.dat new file mode 100644 index 000000000..7a3f20eb3 --- /dev/null +++ b/tests/regression_tests/ncrystal/inputs_true.dat @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + fixed source + 100000 + 10 + + + 0 0 -20 + + + + 0.012 1.0 + + + + + + + 1 + + + 0.0 0.017453292519943295 0.03490658503988659 0.05235987755982989 0.06981317007977318 0.08726646259971647 0.10471975511965978 0.12217304763960307 0.13962634015954636 0.15707963267948966 0.17453292519943295 0.19198621771937624 0.20943951023931956 0.22689280275926285 0.24434609527920614 0.2617993877991494 0.2792526803190927 0.29670597283903605 0.3141592653589793 0.33161255787892263 0.3490658503988659 0.3665191429188092 0.3839724354387525 0.4014257279586958 0.4188790204786391 0.4363323129985824 0.4537856055185257 0.47123889803846897 0.4886921905584123 0.5061454830783556 0.5235987755982988 0.5410520681182421 0.5585053606381855 0.5759586531581288 0.5934119456780721 0.6108652381980153 0.6283185307179586 0.6457718232379019 0.6632251157578453 0.6806784082777885 0.6981317007977318 0.7155849933176751 0.7330382858376184 0.7504915783575618 0.767944870877505 0.7853981633974483 0.8028514559173916 0.8203047484373349 0.8377580409572782 0.8552113334772214 0.8726646259971648 0.8901179185171081 0.9075712110370514 0.9250245035569946 0.9424777960769379 0.9599310885968813 0.9773843811168246 0.9948376736367679 1.0122909661567112 1.0297442586766545 1.0471975511965976 1.064650843716541 1.0821041362364843 1.0995574287564276 1.117010721276371 1.1344640137963142 1.1519173063162575 1.1693705988362009 1.1868238913561442 1.2042771838760873 1.2217304763960306 1.239183768915974 1.2566370614359172 1.2740903539558606 1.2915436464758039 1.3089969389957472 1.3264502315156905 1.3439035240356338 1.361356816555577 1.3788101090755203 1.3962634015954636 1.413716694115407 1.4311699866353502 1.4486232791552935 1.4660765716752369 1.4835298641951802 1.5009831567151235 1.5184364492350666 1.53588974175501 1.5533430342749532 1.5707963267948966 1.5882496193148399 1.6057029118347832 1.6231562043547265 1.6406094968746698 1.6580627893946132 1.6755160819145565 1.6929693744344996 1.710422666954443 1.7278759594743862 1.7453292519943295 1.7627825445142729 1.7802358370342162 1.7976891295541595 1.8151424220741028 1.8325957145940461 1.8500490071139892 1.8675022996339325 1.8849555921538759 1.9024088846738192 1.9198621771937625 1.9373154697137058 1.9547687622336491 1.9722220547535925 1.9896753472735358 2.007128639793479 2.0245819323134224 2.0420352248333655 2.059488517353309 2.076941809873252 2.0943951023931953 2.111848394913139 2.129301687433082 2.1467549799530254 2.1642082724729685 2.181661564992912 2.199114857512855 2.2165681500327987 2.234021442552742 2.251474735072685 2.2689280275926285 2.2863813201125716 2.303834612632515 2.321287905152458 2.3387411976724017 2.356194490192345 2.3736477827122884 2.3911010752322315 2.4085543677521746 2.426007660272118 2.443460952792061 2.4609142453120048 2.478367537831948 2.4958208303518914 2.5132741228718345 2.530727415391778 2.548180707911721 2.5656340004316642 2.5830872929516078 2.600540585471551 2.6179938779914944 2.6354471705114375 2.652900463031381 2.670353755551324 2.6878070480712677 2.705260340591211 2.722713633111154 2.7401669256310974 2.7576202181510405 2.775073510670984 2.792526803190927 2.8099800957108707 2.827433388230814 2.8448866807507573 2.8623399732707004 2.8797932657906435 2.897246558310587 2.91469985083053 2.9321531433504737 2.949606435870417 2.9670597283903604 2.9845130209103035 3.001966313430247 3.01941960595019 3.036872898470133 3.0543261909900767 3.07177948351002 3.0892327760299634 3.1066860685499065 3.12413936106985 3.141592653589793 + + + 1 + + + 1 2 3 + current + + diff --git a/tests/regression_tests/ncrystal/results_true.dat b/tests/regression_tests/ncrystal/results_true.dat new file mode 100644 index 000000000..3ef0306fd --- /dev/null +++ b/tests/regression_tests/ncrystal/results_true.dat @@ -0,0 +1,181 @@ + surface polar low [rad] polar high [rad] cellfrom nuclide score mean std. dev. +0 1 0.00e+00 1.75e-02 1 total current 9.82e-01 1.43e-04 +1 1 1.75e-02 3.49e-02 1 total current 0.00e+00 0.00e+00 +2 1 3.49e-02 5.24e-02 1 total current 1.00e-06 1.00e-06 +3 1 5.24e-02 6.98e-02 1 total current 0.00e+00 0.00e+00 +4 1 6.98e-02 8.73e-02 1 total current 0.00e+00 0.00e+00 +5 1 8.73e-02 1.05e-01 1 total current 1.00e-06 1.00e-06 +6 1 1.05e-01 1.22e-01 1 total current 0.00e+00 0.00e+00 +7 1 1.22e-01 1.40e-01 1 total current 1.00e-06 1.00e-06 +8 1 1.40e-01 1.57e-01 1 total current 1.00e-06 1.00e-06 +9 1 1.57e-01 1.75e-01 1 total current 1.00e-06 1.00e-06 +10 1 1.75e-01 1.92e-01 1 total current 0.00e+00 0.00e+00 +11 1 1.92e-01 2.09e-01 1 total current 2.00e-06 1.33e-06 +12 1 2.09e-01 2.27e-01 1 total current 0.00e+00 0.00e+00 +13 1 2.27e-01 2.44e-01 1 total current 1.00e-06 1.00e-06 +14 1 2.44e-01 2.62e-01 1 total current 1.00e-06 1.00e-06 +15 1 2.62e-01 2.79e-01 1 total current 2.00e-06 1.33e-06 +16 1 2.79e-01 2.97e-01 1 total current 0.00e+00 0.00e+00 +17 1 2.97e-01 3.14e-01 1 total current 2.00e-06 2.00e-06 +18 1 3.14e-01 3.32e-01 1 total current 1.00e-06 1.00e-06 +19 1 3.32e-01 3.49e-01 1 total current 1.00e-06 1.00e-06 +20 1 3.49e-01 3.67e-01 1 total current 2.00e-06 1.33e-06 +21 1 3.67e-01 3.84e-01 1 total current 0.00e+00 0.00e+00 +22 1 3.84e-01 4.01e-01 1 total current 2.00e-06 1.33e-06 +23 1 4.01e-01 4.19e-01 1 total current 2.00e-06 1.33e-06 +24 1 4.19e-01 4.36e-01 1 total current 1.00e-06 1.00e-06 +25 1 4.36e-01 4.54e-01 1 total current 2.00e-06 2.00e-06 +26 1 4.54e-01 4.71e-01 1 total current 5.00e-06 2.24e-06 +27 1 4.71e-01 4.89e-01 1 total current 4.00e-06 1.63e-06 +28 1 4.89e-01 5.06e-01 1 total current 3.00e-06 1.53e-06 +29 1 5.06e-01 5.24e-01 1 total current 3.00e-06 1.53e-06 +30 1 5.24e-01 5.41e-01 1 total current 3.00e-06 1.53e-06 +31 1 5.41e-01 5.59e-01 1 total current 7.00e-06 2.13e-06 +32 1 5.59e-01 5.76e-01 1 total current 3.00e-06 1.53e-06 +33 1 5.76e-01 5.93e-01 1 total current 3.00e-06 1.53e-06 +34 1 5.93e-01 6.11e-01 1 total current 2.00e-06 1.33e-06 +35 1 6.11e-01 6.28e-01 1 total current 2.00e-06 1.33e-06 +36 1 6.28e-01 6.46e-01 1 total current 3.00e-06 2.13e-06 +37 1 6.46e-01 6.63e-01 1 total current 3.00e-06 1.53e-06 +38 1 6.63e-01 6.81e-01 1 total current 2.00e-06 1.33e-06 +39 1 6.81e-01 6.98e-01 1 total current 3.00e-06 1.53e-06 +40 1 6.98e-01 7.16e-01 1 total current 1.00e-06 1.00e-06 +41 1 7.16e-01 7.33e-01 1 total current 6.00e-06 2.67e-06 +42 1 7.33e-01 7.50e-01 1 total current 6.00e-06 2.21e-06 +43 1 7.50e-01 7.68e-01 1 total current 7.00e-06 3.35e-06 +44 1 7.68e-01 7.85e-01 1 total current 6.00e-06 2.67e-06 +45 1 7.85e-01 8.03e-01 1 total current 6.00e-06 2.21e-06 +46 1 8.03e-01 8.20e-01 1 total current 7.00e-06 2.13e-06 +47 1 8.20e-01 8.38e-01 1 total current 5.00e-06 2.24e-06 +48 1 8.38e-01 8.55e-01 1 total current 3.00e-06 1.53e-06 +49 1 8.55e-01 8.73e-01 1 total current 8.00e-06 3.27e-06 +50 1 8.73e-01 8.90e-01 1 total current 7.00e-06 2.13e-06 +51 1 8.90e-01 9.08e-01 1 total current 6.00e-06 2.21e-06 +52 1 9.08e-01 9.25e-01 1 total current 4.00e-06 2.21e-06 +53 1 9.25e-01 9.42e-01 1 total current 1.20e-05 3.27e-06 +54 1 9.42e-01 9.60e-01 1 total current 8.00e-06 3.89e-06 +55 1 9.60e-01 9.77e-01 1 total current 1.20e-05 4.42e-06 +56 1 9.77e-01 9.95e-01 1 total current 7.00e-06 3.67e-06 +57 1 9.95e-01 1.01e+00 1 total current 1.20e-05 3.89e-06 +58 1 1.01e+00 1.03e+00 1 total current 9.00e-06 2.33e-06 +59 1 1.03e+00 1.05e+00 1 total current 6.00e-06 2.67e-06 +60 1 1.05e+00 1.06e+00 1 total current 7.00e-06 2.13e-06 +61 1 1.06e+00 1.08e+00 1 total current 5.00e-06 2.24e-06 +62 1 1.08e+00 1.10e+00 1 total current 1.20e-05 2.91e-06 +63 1 1.10e+00 1.12e+00 1 total current 1.30e-05 3.35e-06 +64 1 1.12e+00 1.13e+00 1 total current 9.00e-06 3.14e-06 +65 1 1.13e+00 1.15e+00 1 total current 1.20e-05 3.89e-06 +66 1 1.15e+00 1.17e+00 1 total current 6.00e-06 2.21e-06 +67 1 1.17e+00 1.19e+00 1 total current 5.11e-03 4.20e-05 +68 1 1.19e+00 1.20e+00 1 total current 8.00e-06 3.27e-06 +69 1 1.20e+00 1.22e+00 1 total current 1.30e-05 4.48e-06 +70 1 1.22e+00 1.24e+00 1 total current 1.20e-05 3.89e-06 +71 1 1.24e+00 1.26e+00 1 total current 1.50e-05 4.28e-06 +72 1 1.26e+00 1.27e+00 1 total current 7.00e-06 3.00e-06 +73 1 1.27e+00 1.29e+00 1 total current 1.60e-05 3.71e-06 +74 1 1.29e+00 1.31e+00 1 total current 9.00e-06 3.79e-06 +75 1 1.31e+00 1.33e+00 1 total current 1.30e-05 2.60e-06 +76 1 1.33e+00 1.34e+00 1 total current 1.60e-05 3.06e-06 +77 1 1.34e+00 1.36e+00 1 total current 1.40e-05 2.67e-06 +78 1 1.36e+00 1.38e+00 1 total current 1.40e-05 6.86e-06 +79 1 1.38e+00 1.40e+00 1 total current 1.50e-05 4.28e-06 +80 1 1.40e+00 1.41e+00 1 total current 3.26e-03 6.93e-05 +81 1 1.41e+00 1.43e+00 1 total current 1.40e-05 3.71e-06 +82 1 1.43e+00 1.45e+00 1 total current 1.30e-05 3.00e-06 +83 1 1.45e+00 1.47e+00 1 total current 1.30e-05 3.67e-06 +84 1 1.47e+00 1.48e+00 1 total current 1.70e-05 5.59e-06 +85 1 1.48e+00 1.50e+00 1 total current 1.70e-05 3.67e-06 +86 1 1.50e+00 1.52e+00 1 total current 1.40e-05 3.40e-06 +87 1 1.52e+00 1.54e+00 1 total current 2.50e-05 4.53e-06 +88 1 1.54e+00 1.55e+00 1 total current 1.30e-05 5.39e-06 +89 1 1.55e+00 1.57e+00 1 total current 1.80e-05 4.67e-06 +90 1 1.57e+00 1.59e+00 1 total current 1.40e-05 4.52e-06 +91 1 1.59e+00 1.61e+00 1 total current 1.70e-05 4.23e-06 +92 1 1.61e+00 1.62e+00 1 total current 1.40e-05 3.71e-06 +93 1 1.62e+00 1.64e+00 1 total current 1.00e-05 2.11e-06 +94 1 1.64e+00 1.66e+00 1 total current 2.00e-05 4.22e-06 +95 1 1.66e+00 1.68e+00 1 total current 2.30e-05 5.59e-06 +96 1 1.68e+00 1.69e+00 1 total current 1.70e-05 6.51e-06 +97 1 1.69e+00 1.71e+00 1 total current 1.30e-05 3.00e-06 +98 1 1.71e+00 1.73e+00 1 total current 1.50e-05 4.01e-06 +99 1 1.73e+00 1.75e+00 1 total current 1.70e-05 3.96e-06 +100 1 1.75e+00 1.76e+00 1 total current 1.80e-05 5.12e-06 +101 1 1.76e+00 1.78e+00 1 total current 2.50e-05 6.54e-06 +102 1 1.78e+00 1.80e+00 1 total current 1.80e-05 3.59e-06 +103 1 1.80e+00 1.82e+00 1 total current 1.50e-05 4.01e-06 +104 1 1.82e+00 1.83e+00 1 total current 1.10e-05 4.07e-06 +105 1 1.83e+00 1.85e+00 1 total current 1.50e-05 4.01e-06 +106 1 1.85e+00 1.87e+00 1 total current 1.90e-05 4.82e-06 +107 1 1.87e+00 1.88e+00 1 total current 2.20e-05 3.89e-06 +108 1 1.88e+00 1.90e+00 1 total current 2.10e-05 3.79e-06 +109 1 1.90e+00 1.92e+00 1 total current 1.50e-05 3.42e-06 +110 1 1.92e+00 1.94e+00 1 total current 2.20e-05 5.12e-06 +111 1 1.94e+00 1.95e+00 1 total current 2.10e-05 5.86e-06 +112 1 1.95e+00 1.97e+00 1 total current 2.60e-05 4.27e-06 +113 1 1.97e+00 1.99e+00 1 total current 2.20e-05 4.16e-06 +114 1 1.99e+00 2.01e+00 1 total current 2.40e-05 5.42e-06 +115 1 2.01e+00 2.02e+00 1 total current 1.60e-05 4.52e-06 +116 1 2.02e+00 2.04e+00 1 total current 1.30e-05 3.35e-06 +117 1 2.04e+00 2.06e+00 1 total current 1.90e-05 4.07e-06 +118 1 2.06e+00 2.08e+00 1 total current 1.30e-05 3.00e-06 +119 1 2.08e+00 2.09e+00 1 total current 1.40e-05 4.00e-06 +120 1 2.09e+00 2.11e+00 1 total current 3.10e-05 5.47e-06 +121 1 2.11e+00 2.13e+00 1 total current 2.30e-05 5.39e-06 +122 1 2.13e+00 2.15e+00 1 total current 2.20e-05 4.67e-06 +123 1 2.15e+00 2.16e+00 1 total current 1.70e-05 4.48e-06 +124 1 2.16e+00 2.18e+00 1 total current 1.60e-05 4.00e-06 +125 1 2.18e+00 2.20e+00 1 total current 1.80e-05 4.16e-06 +126 1 2.20e+00 2.22e+00 1 total current 1.80e-05 4.42e-06 +127 1 2.22e+00 2.23e+00 1 total current 1.80e-05 5.54e-06 +128 1 2.23e+00 2.25e+00 1 total current 1.90e-05 4.33e-06 +129 1 2.25e+00 2.27e+00 1 total current 1.00e-05 3.33e-06 +130 1 2.27e+00 2.29e+00 1 total current 1.80e-05 4.42e-06 +131 1 2.29e+00 2.30e+00 1 total current 4.15e-03 5.40e-05 +132 1 2.30e+00 2.32e+00 1 total current 1.90e-05 2.33e-06 +133 1 2.32e+00 2.34e+00 1 total current 2.30e-05 3.96e-06 +134 1 2.34e+00 2.36e+00 1 total current 1.90e-05 3.48e-06 +135 1 2.36e+00 2.37e+00 1 total current 1.60e-05 3.71e-06 +136 1 2.37e+00 2.39e+00 1 total current 1.60e-05 4.27e-06 +137 1 2.39e+00 2.41e+00 1 total current 2.30e-05 4.48e-06 +138 1 2.41e+00 2.43e+00 1 total current 2.10e-05 3.48e-06 +139 1 2.43e+00 2.44e+00 1 total current 1.60e-05 2.21e-06 +140 1 2.44e+00 2.46e+00 1 total current 9.00e-06 2.77e-06 +141 1 2.46e+00 2.48e+00 1 total current 1.30e-05 3.00e-06 +142 1 2.48e+00 2.50e+00 1 total current 2.70e-05 3.67e-06 +143 1 2.50e+00 2.51e+00 1 total current 1.90e-05 4.07e-06 +144 1 2.51e+00 2.53e+00 1 total current 1.20e-05 4.16e-06 +145 1 2.53e+00 2.55e+00 1 total current 1.30e-05 2.13e-06 +146 1 2.55e+00 2.57e+00 1 total current 1.10e-05 2.33e-06 +147 1 2.57e+00 2.58e+00 1 total current 1.50e-05 3.07e-06 +148 1 2.58e+00 2.60e+00 1 total current 1.20e-05 2.49e-06 +149 1 2.60e+00 2.62e+00 1 total current 1.80e-05 5.54e-06 +150 1 2.62e+00 2.64e+00 1 total current 1.30e-05 3.67e-06 +151 1 2.64e+00 2.65e+00 1 total current 1.60e-05 3.40e-06 +152 1 2.65e+00 2.67e+00 1 total current 7.00e-06 3.35e-06 +153 1 2.67e+00 2.69e+00 1 total current 1.00e-05 2.98e-06 +154 1 2.69e+00 2.71e+00 1 total current 7.00e-06 3.35e-06 +155 1 2.71e+00 2.72e+00 1 total current 1.20e-05 2.91e-06 +156 1 2.72e+00 2.74e+00 1 total current 9.00e-06 2.33e-06 +157 1 2.74e+00 2.76e+00 1 total current 1.00e-05 3.33e-06 +158 1 2.76e+00 2.78e+00 1 total current 1.10e-05 3.14e-06 +159 1 2.78e+00 2.79e+00 1 total current 1.00e-05 3.33e-06 +160 1 2.79e+00 2.81e+00 1 total current 1.40e-05 4.76e-06 +161 1 2.81e+00 2.83e+00 1 total current 8.00e-06 2.91e-06 +162 1 2.83e+00 2.84e+00 1 total current 5.00e-06 2.69e-06 +163 1 2.84e+00 2.86e+00 1 total current 6.00e-06 2.21e-06 +164 1 2.86e+00 2.88e+00 1 total current 5.00e-06 1.67e-06 +165 1 2.88e+00 2.90e+00 1 total current 4.00e-06 2.21e-06 +166 1 2.90e+00 2.91e+00 1 total current 7.00e-06 2.13e-06 +167 1 2.91e+00 2.93e+00 1 total current 6.00e-06 2.67e-06 +168 1 2.93e+00 2.95e+00 1 total current 7.00e-06 2.13e-06 +169 1 2.95e+00 2.97e+00 1 total current 5.00e-06 1.67e-06 +170 1 2.97e+00 2.98e+00 1 total current 3.00e-06 1.53e-06 +171 1 2.98e+00 3.00e+00 1 total current 6.00e-06 2.21e-06 +172 1 3.00e+00 3.02e+00 1 total current 3.00e-06 1.53e-06 +173 1 3.02e+00 3.04e+00 1 total current 1.00e-05 2.98e-06 +174 1 3.04e+00 3.05e+00 1 total current 2.00e-06 1.33e-06 +175 1 3.05e+00 3.07e+00 1 total current 1.00e-06 1.00e-06 +176 1 3.07e+00 3.09e+00 1 total current 2.00e-06 1.33e-06 +177 1 3.09e+00 3.11e+00 1 total current 0.00e+00 0.00e+00 +178 1 3.11e+00 3.12e+00 1 total current 1.00e-06 1.00e-06 +179 1 3.12e+00 3.14e+00 1 total current 0.00e+00 0.00e+00 \ No newline at end of file diff --git a/tests/regression_tests/ncrystal/test.py b/tests/regression_tests/ncrystal/test.py new file mode 100644 index 000000000..51a0f07b7 --- /dev/null +++ b/tests/regression_tests/ncrystal/test.py @@ -0,0 +1,70 @@ +import numpy as np +import openmc +from tests.testing_harness import PyAPITestHarness + +def compute_angular_distribution(cfg, E0, N): + """Return a openmc.model.Model() object for a monoenergetic pencil + beam hitting a 1 mm sphere filled with the material defined by + the cfg string, and compute the angular distribution""" + + # Material definition + + m1 = openmc.Material.from_ncrystal(cfg) + materials = openmc.Materials([m1]) + + # Geometry definition + + sample_sphere = openmc.Sphere(r=0.1) + outer_sphere = openmc.Sphere(r=100, boundary_type="vacuum") + cell1 = openmc.Cell(region= -sample_sphere, fill=m1) + cell2_region= +sample_sphere&-outer_sphere + cell2 = openmc.Cell(region= cell2_region, fill=None) + uni1 = openmc.Universe(cells=[cell1, cell2]) + geometry = openmc.Geometry(uni1) + + # Source definition + + source = openmc.Source() + source.space = openmc.stats.Point(xyz = (0,0,-20)) + source.angle = openmc.stats.Monodirectional(reference_uvw = (0,0,1)) + source.energy = openmc.stats.Discrete([E0], [1.0]) + + # Execution settings + + settings = openmc.Settings() + settings.source = source + settings.run_mode = "fixed source" + settings.batches = 10 + settings.particles = N + + # Tally definition + + tally1 = openmc.Tally(name="angular distribution") + tally1.scores = ["current"] + filter1 = openmc.filter.SurfaceFilter(sample_sphere) + filter2 = openmc.filter.PolarFilter(np.linspace(0,np.pi,180+1)) + filter3 = openmc.filter.CellFromFilter(cell1) + tally1.filters = [filter1, filter2, filter3] + tallies = openmc.Tallies([tally1]) + + return openmc.model.Model(geometry, materials, settings, tallies) + + +class NCrystalTest(PyAPITestHarness): + def _get_results(self): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + sp = openmc.StatePoint(self._sp_name) + tal = sp.get_tally(name='angular distribution') + df = tal.get_pandas_dataframe() + return df.to_string() + +def test_ncrystal(): + NParticles = 100000 + T = 293.6 # K + E0 = 0.012 # eV + cfg = 'Al_sg225.ncmat' + test = compute_angular_distribution(cfg, E0, NParticles) + harness = NCrystalTest('statepoint.10.h5', model=test) + harness.main() From a17fe6cc828dd6a54166aa4065eafc0deb145dad Mon Sep 17 00:00:00 2001 From: jiankai-yu Date: Thu, 17 Nov 2022 23:57:01 -0500 Subject: [PATCH 1283/2654] Add decay heat function in material (#2287) * add decay heat in material.py * add decay_energy.json into eggs * fix a bug when returned decay_ery is None * add unit test for decayheat * fix typo in doc string * address reviewer's comments * add user defined decay energy * remove json for decay energy * address a few comments * add to docs --- docs/source/pythonapi/data.rst | 1 + openmc/data/decay.py | 46 +++++++++++++++++++++++++++++++ openmc/material.py | 43 +++++++++++++++++++++++++++++ tests/chain_simple.xml | 4 +-- tests/unit_tests/test_material.py | 46 +++++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 2 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 55289864f..960abec2f 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -63,6 +63,7 @@ Core Functions atomic_weight combine_distributions decay_constant + decay_energy decay_photon_energy dose_coefficients gnd_name diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 8268d4a36..0db842201 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -621,3 +621,49 @@ def decay_photon_energy(nuclide: str) -> Optional[Univariate]: "sources listed.") return _DECAY_PHOTON_ENERGY.get(nuclide) + + +_DECAY_ENERGY = {} + + +def decay_energy(nuclide: str): + """Get decay energy value resulting from the decay of a nuclide + + This function relies on data stored in a depletion chain. Before calling it + for the first time, you need to ensure that a depletion chain has been + specified in openmc.config['chain_file']. + + .. versionadded:: 0.13.3 + + Parameters + ---------- + nuclide : str + Name of nuclide, e.g., 'H3' + + Returns + ------- + float + Decay energy of nuclide in [eV]. If the nuclide is stable, a value of + 0.0 is returned. + """ + if not _DECAY_ENERGY: + chain_file = openmc.config.get('chain_file') + if chain_file is None: + raise DataError( + "A depletion chain file must be specified with " + "openmc.config['chain_file'] in order to load decay data." + ) + + from openmc.deplete import Chain + chain = Chain.from_xml(chain_file) + for nuc in chain.nuclides: + if nuc.decay_energy: + _DECAY_ENERGY[nuc.name] = nuc.decay_energy + + # If the chain file contained no decay energy, warn the user + if not _DECAY_ENERGY: + warn(f"Chain file '{chain_file}' does not have any decay energy.") + + return _DECAY_ENERGY.get(nuclide, 0.0) + + diff --git a/openmc/material.py b/openmc/material.py index 10ade8bfe..420a08521 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -990,7 +990,50 @@ class Material(IDManagerMixin): activity[nuclide] = inv_seconds * 1e24 * atoms_per_bcm * multiplier return activity if by_nuclide else sum(activity.values()) + + def get_decay_heat(self, units: str = 'W', by_nuclide: bool = False): + """Returns the decay heat of the material or for each nuclide in the + material in units of [W], [W/g] or [W/cm3]. + .. versionadded:: 0.13.3 + + Parameters + ---------- + units : {'W', 'W/g', 'W/cm3'} + Specifies the units of decay heat to return. Options include total + heat [W], specific [W/g] or volumetric heat [W/cm3]. + Default is total heat [W]. + by_nuclide : bool + Specifies if the decay heat should be returned for the material as a + whole or per nuclide. Default is False. + + Returns + ------- + Union[dict, float] + If `by_nuclide` is True then a dictionary whose keys are nuclide + names and values are decay heat is returned. Otherwise the decay heat + of the material is returned as a float. + """ + + cv.check_value('units', units, {'W', 'W/g', 'W/cm3'}) + cv.check_type('by_nuclide', by_nuclide, bool) + + if units == 'W': + multiplier = self.volume + elif units == 'W/cm3': + multiplier = 1 + elif units == 'W/g': + multiplier = 1.0 / self.get_mass_density() + + decayheat = {} + for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): + decay_erg = openmc.data.decay_energy(nuclide) + inv_seconds = openmc.data.decay_constant(nuclide) + decay_erg *= openmc.data.JOULE_PER_EV + decayheat[nuclide] = inv_seconds * decay_erg * 1e24 * atoms_per_bcm * multiplier + + return decayheat if by_nuclide else sum(decayheat.values()) + def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material diff --git a/tests/chain_simple.xml b/tests/chain_simple.xml index 28c5739c9..4e08995a8 100644 --- a/tests/chain_simple.xml +++ b/tests/chain_simple.xml @@ -1,13 +1,13 @@ - + 3696.125 4095.822 4477.27 5097.122 29452.1 29781.3 33566.5 33629.4 33865.1 33878.5 34395.3 34408.0 34486.2 34488.2 112780.0 113150.0 162650.0 165740.0 184490.0 197190.0 220502.0 229720.0 247500.0 254740.0 264260.0 288451.0 290270.0 304910.0 305830.0 326000.0 333600.0 342520.0 361850.0 403030.0 414830.0 417633.0 429930.0 433741.0 451630.0 530800.0 546557.0 575970.0 588280.0 616900.0 649850.0 656090.0 679220.0 684600.0 690130.0 707920.0 785480.0 795500.0 797710.0 807200.0 836804.0 960290.0 961430.0 971960.0 972620.0 995090.0 1038760.0 1096860.0 1101580.0 1124000.0 1131511.0 1151510.0 1159900.0 1169040.0 1225600.0 1240470.0 1254800.0 1260409.0 1315770.0 1334800.0 1343660.0 1367890.0 1441800.0 1448350.0 1457560.0 1502790.0 1521990.0 1543700.0 1566410.0 1678027.0 1706459.0 1791196.0 1830690.0 1845300.0 1927300.0 1948490.0 2045880.0 2112400.0 2151500.0 2189400.0 2255457.0 2408650.0 2466070.0 2477100.0 9.714352819815078e-10 7.460941651551526e-09 6.047882056201745e-09 8.510389107205747e-10 3.7979729633684727e-08 7.033747061198817e-08 6.602815946851458e-09 1.2800909198245071e-08 6.513060244589454e-11 8.894667887850525e-11 1.3843783302275766e-09 2.700005498135763e-09 1.2141115256573815e-11 1.654893875618862e-11 3.7007705885806645e-09 2.0186021392258173e-09 2.859686363903241e-09 9.16781804898392e-09 6.896890642354875e-09 9.588360161322631e-09 5.130613770532286e-07 7.06510748729036e-08 8.410842246774237e-09 6.7286737974193905e-09 5.3829390379355124e-08 9.083709626516178e-07 8.915492781580693e-08 9.251926471451662e-09 2.783988783682273e-08 6.728673797419391e-10 1.093409492080651e-08 2.5232526740322717e-10 5.467047460403255e-08 6.812782219887132e-08 8.83138435911295e-08 1.0345335963532313e-06 8.915492781580693e-08 1.623292553627428e-07 9.251926471451663e-08 9.251926471451662e-09 2.0942997194467853e-06 3.784879011048407e-08 1.513951604419363e-08 1.093409492080651e-08 1.337323917237104e-07 2.186818984161302e-08 1.5980600268871052e-08 6.7286737974193905e-09 3.784879011048407e-08 1.9344937167580748e-07 4.457746390790346e-08 6.7286737974193905e-09 5.0465053480645434e-08 1.3457347594838781e-08 1.9597262434983976e-06 1.0093010696129087e-08 4.289529545854862e-08 2.607361096500014e-07 3.53255374364518e-07 4.541854813258089e-08 2.329803302356464e-06 2.607361096500014e-08 4.7100716581935733e-07 1.059766123093554e-06 6.6193328482113254e-06 4.205421123387119e-10 3.027903208838726e-08 2.565306885266143e-07 1.2616263370161358e-08 2.649415307733885e-07 3.3643368987096953e-09 8.410842246774237e-06 1.934493716758075e-08 9.251926471451662e-09 2.2709274066290446e-08 1.7830985563161385e-07 5.046505348064544e-09 9.251926471451663e-08 2.5400743585258203e-06 3.154065842540339e-07 1.093409492080651e-08 7.569758022096815e-09 3.784879011048407e-07 2.8008104681758214e-06 1.2027504412887161e-06 2.26251656438227e-06 1.6989901338483962e-07 1.6821684493548476e-09 8.663167514177466e-08 1.8503852942903323e-08 2.5568960430193683e-07 2.0186021392258175e-08 6.560456952483906e-09 3.784879011048407e-09 1.7999202408096872e-07 2.800810468175822e-07 2.1027105616935597e-08 4.205421123387119e-10 - + diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 80935d68d..e435c7493 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -545,6 +545,52 @@ def test_get_activity(): assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq] +def test_get_decay_heat(): + # Set chain file for testing + openmc.config['chain_file'] = Path(__file__).parents[1] / 'chain_simple.xml' + + """Tests the decay heat of stable, metastable and active materials""" + m1 = openmc.Material() + m1.add_nuclide("U235", 0.2) + m1.add_nuclide("U238", 0.8) + m1.set_density('g/cm3', 10.5) + # decay heat in W/cc and W/g should not require volume setting + assert m1.get_decay_heat(units='W/cm3') == 0 + assert m1.get_decay_heat(units='W/g') == 0 + m1.volume = 1 + assert m1.get_decay_heat(units='W') == 0 + + # Checks that 1g of tritium has the correct decay heat scaling + m2 = openmc.Material() + m2.add_nuclide("I135", 1) + m2.set_density('g/cm3', 1) + m2.volume = 1 + assert pytest.approx(m2.get_decay_heat(units='W')) == 40175.15720273193 + m2.set_density('g/cm3', 2) + assert pytest.approx(m2.get_decay_heat(units='W')) == 40175.15720273193*2 + m2.volume = 3 + assert pytest.approx(m2.get_decay_heat(units='W')) == 40175.15720273193*2*3 + + # Checks that 1 mol of a metastable nuclides has the correct decay heat + m3 = openmc.Material() + m3.add_nuclide("Xe135", 1) + m3.set_density('g/cm3', 1) + m3.volume = 98.9 + assert pytest.approx(m3.get_decay_heat(units='W'), rel=0.001) == 846181.2921143445 + + # Checks that specific and volumetric decay heat of tritium are correct + m4 = openmc.Material() + m4.add_nuclide("I135", 1) + m4.set_density('g/cm3', 1.5) + assert pytest.approx(m4.get_decay_heat(units='W/g')) == 40175.15720273193 # [W/g] + assert pytest.approx(m4.get_decay_heat(units='W/g', by_nuclide=True)["I135"]) == 40175.15720273193 # [W/g] + assert pytest.approx(m4.get_decay_heat(units='W/cm3')) == 40175.15720273193*3/2 # [W/cc] + assert pytest.approx(m4.get_decay_heat(units='W/cm3', by_nuclide=True)["I135"]) == 40175.15720273193*3/2 #[W/cc] + # volume is required to calculate total decay heat + m4.volume = 10. + assert pytest.approx(m4.get_decay_heat(units='W')) == 40175.15720273193*3/2*10 # [W] + + def test_decay_photon_energy(): # Set chain file for testing openmc.config['chain_file'] = Path(__file__).parents[1] / 'chain_simple.xml' From f60f95feb4e49d4b46c6aa5ec63b7ed4ddeeec87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Fri, 18 Nov 2022 09:03:35 -0500 Subject: [PATCH 1284/2654] [skip ci] removed # TODOs --- openmc/mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index b4cd04d51..79ab7fd5a 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -165,7 +165,7 @@ class StructuredMesh(MeshBase): pass @property - def vertices(self): # TODO needs changing + def vertices(self): """Return coordinates of mesh vertices. Returns @@ -178,7 +178,7 @@ class StructuredMesh(MeshBase): return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) @property - def centroids(self): # TODO needs changing + def centroids(self): """Return coordinates of mesh element centroids. Returns From 54745f507641489bc82acbfb4303a728c7bf4fca Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Fri, 18 Nov 2022 11:11:37 -0300 Subject: [PATCH 1285/2654] Changed example NCrystal cfg strings --- docs/source/usersguide/materials.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index ab5a8c5af..1886a772b 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -114,13 +114,13 @@ that define the material, e.g: :: - mat = openmc.Material.from_ncrystal('Al_sg225.ncmat') + mat = openmc.Material.from_ncrystal('Al_sg225.ncmat;temp=300K') defines a material containing polycrystalline alumnium, :: - mat = openmc.Material.from_ncrystal(""""Ge_sg227.ncmat;dcutoff=0.5;mos=40arcsec; + mat = openmc.Material.from_ncrystal("""Ge_sg227.ncmat;dcutoff=0.5;mos=40arcsec; dir1=@crys_hkl:5,1,1@lab:0,0,1; dir2=@crys_hkl:0,-1,1@lab:0,1,0""") From e4281408f674ce795f237d8b568396793b159206 Mon Sep 17 00:00:00 2001 From: yardasol Date: Fri, 18 Nov 2022 10:31:58 -0600 Subject: [PATCH 1286/2654] reset timers after writing statepoint file --- openmc/deplete/coupled_operator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index a8c1fa156..669e98dda 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -460,7 +460,6 @@ class CoupledOperator(OpenMCOperator): # Run OpenMC openmc.lib.run() - openmc.lib.reset_timers() # Extract results rates = self._calculate_reaction_rates(source_rate) @@ -529,6 +528,8 @@ class CoupledOperator(OpenMCOperator): "openmc_simulation_n{}.h5".format(step), write_source=False) + openmc.lib.reset_timers() + def finalize(self): """Finalize a depletion simulation and release resources.""" if self.cleanup_when_done: From 91f939a391032db72220e4be715b888d0f8db287 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Fri, 18 Nov 2022 18:26:31 +0100 Subject: [PATCH 1287/2654] Add flag for NCrystal --- include/openmc/settings.h | 2 ++ openmc/lib/__init__.py | 3 +++ src/settings.cpp | 7 +++++++ tests/regression_tests/ncrystal/test.py | 7 +++++++ 4 files changed, 19 insertions(+) diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 9bb447005..b01c75d45 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -20,6 +20,8 @@ namespace openmc { // Global variable declarations //============================================================================== +extern "C" const bool NCRYSTAL_ENABLED; + namespace settings { // Boolean flags diff --git a/openmc/lib/__init__.py b/openmc/lib/__init__.py index c14b0d9c2..55e2ec11b 100644 --- a/openmc/lib/__init__.py +++ b/openmc/lib/__init__.py @@ -42,6 +42,9 @@ else: def _dagmc_enabled(): return c_bool.in_dll(_dll, "DAGMC_ENABLED").value +def _ncrystal_enabled(): + return c_bool.in_dll(_dll, "NCRYSTAL_ENABLED").value + def _coord_levels(): return c_int.in_dll(_dll, "n_coord_levels").value diff --git a/src/settings.cpp b/src/settings.cpp index 87c24eedd..be7228d68 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -36,6 +36,13 @@ namespace openmc { // Global variables //============================================================================== +#ifdef NCRYSTAL +const bool NCRYSTAL_ENABLED = true; +#else +const bool NCRYSTAL_ENABLED = false; +#endif + + namespace settings { // Default values for boolean flags diff --git a/tests/regression_tests/ncrystal/test.py b/tests/regression_tests/ncrystal/test.py index 51a0f07b7..0a47d634d 100644 --- a/tests/regression_tests/ncrystal/test.py +++ b/tests/regression_tests/ncrystal/test.py @@ -1,7 +1,14 @@ import numpy as np import openmc +import openmc.lib +import pytest + from tests.testing_harness import PyAPITestHarness +pytestmark = pytest.mark.skipif( + not openmc.lib._ncrystal_enabled(), + reason="NCrystal materials are not enabled.") + def compute_angular_distribution(cfg, E0, N): """Return a openmc.model.Model() object for a monoenergetic pencil beam hitting a 1 mm sphere filled with the material defined by From 5f8e64b463aa2e0509d2b9955dc7de6686d5497b Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:47:21 -0300 Subject: [PATCH 1288/2654] Add NCrystal vairables to ci.yml --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e267c0d8e..321f18874 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ jobs: mpi: [n, y] omp: [n, y] dagmc: [n] + ncrystal: [n] libmesh: [n] event: [n] vectfit: [n] @@ -47,6 +48,10 @@ jobs: python-version: '3.10' mpi: y omp: y + - ncrystal: y + python-version: '3.10' + mpi: n + omp: n - libmesh: y python-version: '3.10' mpi: y @@ -64,7 +69,7 @@ jobs: omp: n mpi: y name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }}, - mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }}, + mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }}, ncrystal=${{ matrix.ncrystal }}, libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }} vectfit=${{ matrix.vectfit }})" @@ -73,6 +78,7 @@ jobs: PHDF5: ${{ matrix.mpi }} OMP: ${{ matrix.omp }} DAGMC: ${{ matrix.dagmc }} + NCRYSTAL: ${{ matrix.ncrystal }} EVENT: ${{ matrix.event }} VECTFIT: ${{ matrix.vectfit }} LIBMESH: ${{ matrix.libmesh }} From 87ed26babee2c7b69c229529e146d335a90fd952 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:48:19 -0300 Subject: [PATCH 1289/2654] Add option to install NCrystal --- tools/ci/gha-install.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index aa40eb90b..e5390be1e 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -17,6 +17,11 @@ if [[ $DAGMC = 'y' ]]; then ./tools/ci/gha-install-dagmc.sh fi +# Install NCrystal if needed +if [[ $NCRYSTAL = 'y' ]]; then + ./tools/ci/gha-install-ncrystal.sh +fi + # Install vectfit for WMP generation if needed if [[ $VECTFIT = 'y' ]]; then ./tools/ci/gha-install-vectfit.sh From 8cf9dbe320baf4ff98eb57979f6e249e69ee0424 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Fri, 18 Nov 2022 22:28:04 +0100 Subject: [PATCH 1290/2654] Fixed in NCrystal docs --- docs/source/methods/cross_sections.rst | 4 ++-- docs/source/usersguide/materials.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/methods/cross_sections.rst b/docs/source/methods/cross_sections.rst index c700b3f2d..64e4fac3d 100644 --- a/docs/source/methods/cross_sections.rst +++ b/docs/source/methods/cross_sections.rst @@ -190,8 +190,8 @@ and further extend the physics `using plugins`_. Thermal scattering kernels are the fly from dynamic and structural data, or loaded from :math:`S(\alpha,\beta)` tables converted from ENDF6 evaluations. These kernels are sampled in a direct way using a fast `rejection algorithm`_ that does not require previous processing. A `large library` of materials is already included in -the NCrystal distribution, and new materials can be easily defined from scratch in the `NCMAT format` -or `combining existing files`. +the NCrystal distribution, and new materials can be easily defined from scratch in the `NCMAT format`_ +or `combining existing files`_. The compositions of the materials defined in NCrystal are passed on to OpenMC all other reactions except for thermal neutron scattering are handled by continuous energy ACE libraries. diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index 1886a772b..1eaae846c 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -127,8 +127,8 @@ defines a material containing polycrystalline alumnium, defines an oriented germanium single crystal with 40 arcsec mosaicity. NCrystal only handles low energy neutron interactions. Other interaction are -provided by standard ACE files. NCrystal_ comes with a `predefined library -https://github.com/mctools/ncrystal/wiki/Data-library`_ but more materials can +provided by standard ACE files. NCrystal_ comes with a `predefined library +`_ but more materials can be added by creating NCMAT files or on-the-fly in the configuration string. .. warning:: Currently, NCrystal_ materials cannot be modified after created. From b9e8f1324e72dc4730185b5f1f350eea62ab6757 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Fri, 18 Nov 2022 22:40:46 +0100 Subject: [PATCH 1291/2654] Attempt to fix NCrystal installation script --- tools/ci/gha-install-ncrystal.sh | 4 ++++ tools/ci/gha-install.py | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index c18087f23..5f577b8da 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -28,6 +28,7 @@ cmake \ -DEMBED_DATA=ON \ -DINSTALL_DATA=OFF \ -DNO_DIRECT_PYMODINST=ON \ + -DCMAKE_INSTALL_PREFIX="${INST_DIR}" \ -DPython3_EXECUTABLE="$PYTHON" make -j${CPU_COUNT:-1} @@ -60,3 +61,6 @@ liblocation = pathlib.Path('${TMPNCRYSTALLIBLOCATION}'.strip()) EOF $PYTHON -m pip install ./ncrystal_pypkg/ -vv + +setup ${INST_DIR}/setup.sh + diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index 4c69ba70b..f3a29273f 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -19,7 +19,7 @@ def which(program): return None -def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): +def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, ncrystal=False): # Create build directory and change to it shutil.rmtree('build', ignore_errors=True) os.mkdir('build') @@ -54,6 +54,9 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): libmesh_path = os.environ.get('HOME') + '/LIBMESH' cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + libmesh_path) + if ncrystal: + cmake_cmd.append('-DOPENMC_USE_NCRYSTAL=ON') + # Build in coverage mode for coverage testing cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') @@ -70,10 +73,11 @@ def main(): mpi = (os.environ.get('MPI') == 'y') phdf5 = (os.environ.get('PHDF5') == 'y') dagmc = (os.environ.get('DAGMC') == 'y') + ncrystal = (os.environ.get('NCRYSTAL') == 'y') libmesh = (os.environ.get('LIBMESH') == 'y') # Build and install - install(omp, mpi, phdf5, dagmc, libmesh) + install(omp, mpi, phdf5, dagmc, libmesh, ncrystal) if __name__ == '__main__': main() From d45c37b20619154db60c48d5a18a750152fbeb48 Mon Sep 17 00:00:00 2001 From: yardasol Date: Fri, 18 Nov 2022 10:54:41 -0600 Subject: [PATCH 1292/2654] Add test for runtime attribute on depletion statepoints --- .../deplete_with_transport/test.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/regression_tests/deplete_with_transport/test.py b/tests/regression_tests/deplete_with_transport/test.py index 9b37e4351..977241644 100644 --- a/tests/regression_tests/deplete_with_transport/test.py +++ b/tests/regression_tests/deplete_with_transport/test.py @@ -122,8 +122,18 @@ def test_full(run_in_tmpdir, problem, multiproc): n_tallies = np.empty(N + 1, dtype=int) # Get statepoint files for all BOS points and EOL + runtimes = {} for n in range(N + 1): statepoint = openmc.StatePoint(f"openmc_simulation_n{n}.h5") + runtime = statepoint.runtime + if n == 0: + for measure, time in runtime.items(): + runtimes.update({measure: np.array([time])}) + else: + for measure, time in runtime.items(): + current = runtimes[measure] + updated = np.append(current, time) + runtimes.update({measure: updated}) k_n = statepoint.keff k_state[n] = [k_n.nominal_value, k_n.std_dev] n_tallies[n] = len(statepoint.tallies) @@ -134,6 +144,18 @@ def test_full(run_in_tmpdir, problem, multiproc): # Check that no additional tallies are loaded from the files assert np.all(n_tallies == 0) + # Check that runtimes are qualitatively correct + assert runtimes['reading cross sections'][0] != 0 + assert runtimes['total initialization'][0] != 0 + assert np.all(runtimes['reading cross sections'][1:] == 0) + assert np.all(runtimes['total initialization'][1:] == 0) + assert np.all(runtimes['inactive batches'] == 0) + del runtimes['reading cross sections'] + del runtimes['total initialization'] + del runtimes['inactive batches'] + for measure, times in runtimes.items(): + assert np.all(times != 0) + def test_depletion_results_to_material(run_in_tmpdir, problem): """Checks openmc.Materials objects can be created from depletion results""" From 6442de68348eefe5f26ba9a0c74fd082067e95fd Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 18 Nov 2022 23:26:24 +0100 Subject: [PATCH 1293/2654] remove unneccessary initialization Co-authored-by: Paul Romano --- src/source.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/source.cpp b/src/source.cpp index 1c46e4939..67a4a511d 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -381,7 +381,6 @@ FileSource::FileSource(mcpl_file_t mcpl_file) //mcpl stores time in ms site_.time=mcpl_particle->time*1e-3; site_.wgt=mcpl_particle->weight; - site_.delayed_group=0; sites_[i]=site_; } mcpl_close_file(mcpl_file); From a299dcc56b4d79e73a996ed3c47baaa2729fd795 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 16 Nov 2022 14:02:01 +0100 Subject: [PATCH 1294/2654] add a documentation entry to surf_source_write --- docs/source/io_formats/settings.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 1a8f63716..285dfa229 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -767,6 +767,15 @@ certain surfaces and write out the source bank in a separate file called *Default*: None + :mcpl: + An optional boolean which indicates if the banked particle should + be written to a file in the MCPL-format (documented in mcpl_). + instead of the native hdf5-based format. + + *Default*: false + + .. _mcpl: https://mctools.github.io/mcpl/mcpl.pdf + ------------------------------ ```` Element ------------------------------ From a40cc14d8ebb08da619b2d9fcaa9fc58adca1efa Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Sat, 19 Nov 2022 00:33:04 +0100 Subject: [PATCH 1295/2654] check in the c++-layer if it's an mcpl-file --- src/settings.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 9098eb620..0ca430de6 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -431,12 +431,13 @@ void read_settings_xml() for (pugi::xml_node node : root.children("source")) { if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); - model::external_sources.push_back(make_unique(path)); #ifdef OPENMC_MCPL - } else if (check_for_node(node, "mcpl")) { - auto path = get_node_value(node, "mcpl", false, true); - model::external_sources.push_back(make_unique(mcpl_open_file(path.c_str()))); + if ( (path.size() >= 5 && path.compare(path.size()-5,5,".mcpl")==0 ) || + (path.size() >= 8 && path.compare(path.size()-8,8,".mcpl.gz")==0 ) ) { + model::external_sources.push_back(make_unique(mcpl_open_file(path.c_str()))); + } else #endif + model::external_sources.push_back(make_unique(path)); } else if (check_for_node(node, "library")) { // Get shared library path and parameters auto path = get_node_value(node, "library", false, true); From 8bfb1af81e874a6e9b55c59a12e816f071592ab0 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Sat, 19 Nov 2022 01:41:02 +0100 Subject: [PATCH 1296/2654] remove unneccessary in-code comments --- src/state_point.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index d0fe92bdf..3ee5f13b3 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -621,10 +621,7 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) std::string line; if (mpi::master) { - // this must be rewritten: file_open is h5-specific file_id = mcpl_create_outfile(filename_.c_str()); - //write_attribute(file_id, "filetype", "source"); - //write header stuff (oopy in xml-files as binary blobs for instance)) if (VERSION_DEV){ line=fmt::format("OpenMC {0}.{1}.{2}-development",VERSION_MAJOR,VERSION_MINOR,VERSION_RELEASE); } else { From 727161f95ab8364a04499de060e25fcdc28d474a Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Sat, 19 Nov 2022 01:44:47 +0100 Subject: [PATCH 1297/2654] remove some in-code comments --- src/source.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 1c46e4939..2e6335aad 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -332,8 +332,6 @@ FileSource::FileSource(std::string path) #ifdef OPENMC_MCPL FileSource::FileSource(mcpl_file_t mcpl_file) { - //do checks on the mcpl_file to see if particles are many enough. - // should model this on the example source shown in the docs. size_t n_sites=mcpl_hdr_nparticles(mcpl_file); sites_.resize(n_sites); @@ -348,8 +346,6 @@ FileSource::FileSource(mcpl_file_t mcpl_file) while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { mcpl_particle=mcpl_read(mcpl_file); pdg=mcpl_particle->pdgcode; - //should check for file exhaustion. This could happen if particles are other than - //neutrons, photons, electrons, or positrons. } switch(pdg){ From ccbef891ef7d2585b21b7bd5dd0e76d872017210 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Sat, 19 Nov 2022 01:49:31 +0100 Subject: [PATCH 1298/2654] update to doc-string --- docs/source/io_formats/settings.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 285dfa229..a162e8de6 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -768,9 +768,10 @@ certain surfaces and write out the source bank in a separate file called *Default*: None :mcpl: - An optional boolean which indicates if the banked particle should + An optional boolean which indicates if the banked particles should be written to a file in the MCPL-format (documented in mcpl_). - instead of the native hdf5-based format. + instead of the native hdf5-based format.If activated the output + output file name is altered to ``surface_source.mcpl`` *Default*: false From fab1ddac003648e7954ad85b8d4718e7685df0e4 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Sat, 19 Nov 2022 02:19:41 +0100 Subject: [PATCH 1299/2654] prefer native as default Co-authored-by: Paul Romano --- src/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.cpp b/src/settings.cpp index 9098eb620..91a13289c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -60,7 +60,7 @@ bool run_CE {true}; bool source_latest {false}; bool source_separate {false}; bool source_write {true}; -bool source_mcpl_write {true}; +bool source_mcpl_write {false}; bool surf_source_write {false}; bool surf_mcpl_write {false}; bool surf_source_read {false}; From d7ab491f473e87f5865e365bd5f9fbcfcd24943e Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Sat, 19 Nov 2022 08:57:00 +0100 Subject: [PATCH 1300/2654] Try fix of NCrystal install --- tools/ci/gha-install-ncrystal.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index 5f577b8da..78a1a44f2 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -45,7 +45,7 @@ make install cat < ./findncrystallib.py import pathlib libname = pathlib.Path('./cfg_ncrystal_libname.txt').read_text().strip() -libs = list(pathlib.Path("/usr").glob("**/lib*/**/%s"%libname)) +libs = list(pathlib.Path("${INST_DIR}").glob("**/lib*/**/%s"%libname)) assert len(libs)==1 pathlib.Path('ncrystal_liblocation.txt').write_text(str(libs[0])) EOF From b199db9cb9c6de05117c2749c21ce5ea3d474f7d Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Sat, 19 Nov 2022 09:06:42 +0100 Subject: [PATCH 1301/2654] Update gha-install-ncrystal.sh --- tools/ci/gha-install-ncrystal.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index 78a1a44f2..715e4da94 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -62,5 +62,5 @@ EOF $PYTHON -m pip install ./ncrystal_pypkg/ -vv -setup ${INST_DIR}/setup.sh +source ${INST_DIR}/setup.sh From 39d0c5cd61224b2a80b8c6ee75597588e132842b Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Sat, 19 Nov 2022 09:38:34 +0100 Subject: [PATCH 1302/2654] Try to initialize with setup.sh --- tools/ci/gha-install-ncrystal.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index 715e4da94..8e75cc60a 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -24,7 +24,7 @@ cmake \ -DMODIFY_RPATH=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EXAMPLES=OFF \ - -DINSTALL_SETUPSH=OFF \ + -DINSTALL_SETUPSH=ON \ -DEMBED_DATA=ON \ -DINSTALL_DATA=OFF \ -DNO_DIRECT_PYMODINST=ON \ From 9e1abb328429072d9349fd5c01ae6249c438d187 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Sat, 19 Nov 2022 10:47:26 +0100 Subject: [PATCH 1303/2654] Update gha-install-ncrystal.sh --- tools/ci/gha-install-ncrystal.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index 8e75cc60a..c080c16d8 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -24,7 +24,7 @@ cmake \ -DMODIFY_RPATH=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EXAMPLES=OFF \ - -DINSTALL_SETUPSH=ON \ + -DINSTALL_SETUPSH=OFF \ -DEMBED_DATA=ON \ -DINSTALL_DATA=OFF \ -DNO_DIRECT_PYMODINST=ON \ @@ -62,5 +62,5 @@ EOF $PYTHON -m pip install ./ncrystal_pypkg/ -vv -source ${INST_DIR}/setup.sh +# source ${INST_DIR}/setup.sh From c9c74f08b2cae9c57f818c4a93abf986514fd809 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 21 Nov 2022 00:34:30 +0100 Subject: [PATCH 1304/2654] apply clang-format --- src/source.cpp | 78 +++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 2e6335aad..af108f3fa 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -234,7 +234,8 @@ SourceSite IndependentSource::sample(uint64_t* seed) const auto id = (domain_type_ == DomainType::CELL) ? model::cells[coord.cell]->id_ : model::universes[coord.universe]->id_; - if (found = contains(domain_ids_, id)) break; + if (found = contains(domain_ids_, id)) + break; } } } @@ -332,57 +333,57 @@ FileSource::FileSource(std::string path) #ifdef OPENMC_MCPL FileSource::FileSource(mcpl_file_t mcpl_file) { - size_t n_sites=mcpl_hdr_nparticles(mcpl_file); + size_t n_sites = mcpl_hdr_nparticles(mcpl_file); sites_.resize(n_sites); - for (int i=0;ipdgcode; - while ( pdg!=2112 && pdg!=22 && pdg!=11 && pdg!=-11) { - mcpl_particle=mcpl_read(mcpl_file); - pdg=mcpl_particle->pdgcode; + int pdg = mcpl_particle->pdgcode; + while (pdg != 2112 && pdg != 22 && pdg != 11 && pdg != -11) { + mcpl_particle = mcpl_read(mcpl_file); + pdg = mcpl_particle->pdgcode; } - switch(pdg){ - case 2112: - site_.particle=ParticleType::neutron; - break; - case 22: - site_.particle=ParticleType::photon; - break; - case 11: - site_.particle=ParticleType::electron; - break; - case -11: - site_.particle=ParticleType::positron; - break; + switch (pdg) { + case 2112: + site_.particle = ParticleType::neutron; + break; + case 22: + site_.particle = ParticleType::photon; + break; + case 11: + site_.particle = ParticleType::electron; + break; + case -11: + site_.particle = ParticleType::positron; + break; } - //particle is good, convert to openmc-formalism - site_.r.x=mcpl_particle->position[0]; - site_.r.y=mcpl_particle->position[1]; - site_.r.z=mcpl_particle->position[2]; + // particle is good, convert to openmc-formalism + site_.r.x = mcpl_particle->position[0]; + site_.r.y = mcpl_particle->position[1]; + site_.r.z = mcpl_particle->position[2]; - site_.u.x=mcpl_particle->direction[0]; - site_.u.y=mcpl_particle->direction[1]; - site_.u.z=mcpl_particle->direction[2]; + site_.u.x = mcpl_particle->direction[0]; + site_.u.y = mcpl_particle->direction[1]; + site_.u.z = mcpl_particle->direction[2]; - //mcpl stores kinetic energy in MeV - site_.E=mcpl_particle->ekin*1e6; - //mcpl stores time in ms - site_.time=mcpl_particle->time*1e-3; - site_.wgt=mcpl_particle->weight; - site_.delayed_group=0; - sites_[i]=site_; + // mcpl stores kinetic energy in MeV + site_.E = mcpl_particle->ekin * 1e6; + // mcpl stores time in ms + site_.time = mcpl_particle->time * 1e-3; + site_.wgt = mcpl_particle->weight; + site_.delayed_group = 0; + sites_[i] = site_; } mcpl_close_file(mcpl_file); } -#endif //OPENMC_MCPL +#endif // OPENMC_MCPL SourceSite FileSource::sample(uint64_t* seed) const { @@ -443,7 +444,6 @@ CustomSourceWrapper::~CustomSourceWrapper() #endif } - //============================================================================== // Non-member functions //============================================================================== From c5affa805e06ce46276dc1c148888b3540b1e29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Mon, 21 Nov 2022 09:37:57 -0500 Subject: [PATCH 1305/2654] Review suggestions Co-authored-by: Patrick Shriwise --- src/mesh.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 57fe49ba6..3849f4d03 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -977,9 +977,7 @@ StructuredMesh::MeshIndex CylindricalMesh::get_indices( mapped_r[0] = std::hypot(r.x, r.y); mapped_r[2] = r[2]; - mapped_r[0] += origin_[0]; - mapped_r[1] += origin_[1]; - mapped_r[2] += origin_[2]; + mapped_r -= origin_; if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; From 6d787d5fb0e2ed7790e83f2ea8d00560f60c292e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Mon, 21 Nov 2022 09:39:01 -0500 Subject: [PATCH 1306/2654] Apply suggestions from code review Co-authored-by: Patrick Shriwise --- openmc/mesh.py | 6 +++--- src/mesh.cpp | 4 +--- tests/unit_tests/test_deplete_activation.py | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 79ab7fd5a..3936572f9 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1322,7 +1322,7 @@ class CylindricalMesh(StructuredMesh): pts_cartesian[:, 1] = r * np.sin(phi) # offset with origin - if self.origin != [0.0, 0.0, 0.0]: + if any(self.origin != (0.0, 0.0, 0.0)): pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] @@ -1375,7 +1375,7 @@ class SphericalMesh(StructuredMesh): self._r_grid = None self._theta_grid = [0, pi] self._phi_grid = [0, 2*pi] - self._origin = [0., 0., 0.] + self._origin = (0., 0., 0.) @property def dimension(self): @@ -1577,7 +1577,7 @@ class SphericalMesh(StructuredMesh): pts_cartesian[:, 2] = r * np.cos(phi) # offset with origin - if self.origin != [0.0, 0.0, 0.0]: + if any(self.origin != (0.0, 0.0, 0.0)): pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] diff --git a/src/mesh.cpp b/src/mesh.cpp index 3849f4d03..82644db08 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1213,9 +1213,7 @@ StructuredMesh::MeshIndex SphericalMesh::get_indices( mapped_r[0] = r.norm(); - mapped_r[0] += origin_[0]; - mapped_r[1] += origin_[1]; - mapped_r[2] += origin_[2]; + mapped_r -= origin_; if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 2dc911c86..64167c8af 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -53,7 +53,6 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts # Determine (n.gamma) reaction rate using initial run sp = model.run() with openmc.StatePoint(sp) as sp: - print(sp.tallies) tally = sp.get_tally(name='activation tally') capture_rate = tally.mean.flat[0] From 8681751238a27d4b94a75c446903c035de6f72dd Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 21 Nov 2022 09:45:11 -0500 Subject: [PATCH 1307/2654] check length origin --- openmc/mesh.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 3936572f9..0eba6871b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1097,6 +1097,7 @@ class CylindricalMesh(StructuredMesh): @origin.setter def origin(self, coords): cv.check_type('mesh origin', coords, Iterable, Real) + cv.check_length("mesh origin", coords, 3) self._origin = np.asarray(coords) @r_grid.setter @@ -1420,6 +1421,7 @@ class SphericalMesh(StructuredMesh): @origin.setter def origin(self, coords): cv.check_type('mesh origin', coords, Iterable, Real) + cv.check_length("mesh origin", coords, 3) self._origin = np.asarray(coords) @r_grid.setter From df1a45b65407f0dc67e286600aac58d1b8744682 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 21 Nov 2022 09:46:13 -0500 Subject: [PATCH 1308/2654] origin from_hdf5 --- openmc/mesh.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 0eba6871b..64217fa77 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1145,6 +1145,7 @@ class CylindricalMesh(StructuredMesh): mesh.r_grid = group['r_grid'][()] mesh.phi_grid = group['phi_grid'][()] mesh.z_grid = group['z_grid'][()] + mesh.origin = group['origin'][()] return mesh @@ -1469,6 +1470,7 @@ class SphericalMesh(StructuredMesh): mesh.r_grid = group['r_grid'][()] mesh.theta_grid = group['theta_grid'][()] mesh.phi_grid = group['phi_grid'][()] + mesh.origin = group['origin'][()] return mesh From b63ec9cdc3ee988afe1051126cdba2b7d83ff629 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 21 Nov 2022 09:48:42 -0500 Subject: [PATCH 1309/2654] read mesh optional --- openmc/mesh.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 64217fa77..0d92208aa 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1145,7 +1145,8 @@ class CylindricalMesh(StructuredMesh): mesh.r_grid = group['r_grid'][()] mesh.phi_grid = group['phi_grid'][()] mesh.z_grid = group['z_grid'][()] - mesh.origin = group['origin'][()] + if 'origin' in group: + mesh.origin = group['origin'][()] return mesh @@ -1268,7 +1269,8 @@ class CylindricalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] mesh.z_grid = [float(x) for x in get_text(elem, "z_grid").split()] - mesh.origin = [float(x) for x in get_text(elem, "origin").split()] + if "origin" in elem.attrib: + mesh.origin = [float(x) for x in get_text(elem, "origin").split()] return mesh @@ -1470,7 +1472,8 @@ class SphericalMesh(StructuredMesh): mesh.r_grid = group['r_grid'][()] mesh.theta_grid = group['theta_grid'][()] mesh.phi_grid = group['phi_grid'][()] - mesh.origin = group['origin'][()] + if 'origin' in group: + mesh.origin = group['origin'][()] return mesh @@ -1523,7 +1526,8 @@ class SphericalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.theta_grid = [float(x) for x in get_text(elem, "theta_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] - mesh.origin = [float(x) for x in get_text(elem, "origin").split()] + if "origin" in elem.attrib: + mesh.origin = [float(x) for x in get_text(elem, "origin").split()] return mesh From f51f18176135926ea1c4be5f2287c95a8741c8fd Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 21 Nov 2022 11:53:49 -0500 Subject: [PATCH 1310/2654] fixed optional xml reading --- openmc/mesh.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 0d92208aa..31b7789ee 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1269,8 +1269,7 @@ class CylindricalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] mesh.z_grid = [float(x) for x in get_text(elem, "z_grid").split()] - if "origin" in elem.attrib: - mesh.origin = [float(x) for x in get_text(elem, "origin").split()] + mesh.origin = [float(x) for x in get_text(elem, "origin", default=[0., 0., 0.]).split()] return mesh @@ -1526,8 +1525,7 @@ class SphericalMesh(StructuredMesh): mesh.r_grid = [float(x) for x in get_text(elem, "r_grid").split()] mesh.theta_grid = [float(x) for x in get_text(elem, "theta_grid").split()] mesh.phi_grid = [float(x) for x in get_text(elem, "phi_grid").split()] - if "origin" in elem.attrib: - mesh.origin = [float(x) for x in get_text(elem, "origin").split()] + mesh.origin = [float(x) for x in get_text(elem, "origin", default=[0., 0., 0.]).split()] return mesh From 3325667c51538748e2078261fb9457c769b11e3e Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 21 Nov 2022 12:22:39 -0500 Subject: [PATCH 1311/2654] minor version bump for statepoint files --- include/openmc/constants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index fa2251b84..a97180faf 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -24,7 +24,7 @@ using double_4dvec = vector>>>; constexpr int HDF5_VERSION[] {3, 0}; // Version numbers for binary files -constexpr array VERSION_STATEPOINT {18, 0}; +constexpr array VERSION_STATEPOINT {18, 1}; constexpr array VERSION_PARTICLE_RESTART {2, 0}; constexpr array VERSION_TRACK {3, 0}; constexpr array VERSION_SUMMARY {6, 0}; From 10a95186e391517ff0f5d1f7487d6aa4c4cd8d93 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 21 Nov 2022 14:07:45 -0500 Subject: [PATCH 1312/2654] origin is tuple + fixed any --- openmc/mesh.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 31b7789ee..615514c68 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1052,7 +1052,7 @@ class CylindricalMesh(StructuredMesh): self._r_grid = None self._phi_grid = [0.0, 2*pi] self._z_grid = None - self._origin = [0., 0., 0.] + self._origin = (0., 0., 0.) @property def dimension(self): @@ -1325,7 +1325,7 @@ class CylindricalMesh(StructuredMesh): pts_cartesian[:, 1] = r * np.sin(phi) # offset with origin - if any(self.origin != (0.0, 0.0, 0.0)): + if any([coord != 0 for coord in self.origin]): pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] @@ -1583,7 +1583,7 @@ class SphericalMesh(StructuredMesh): pts_cartesian[:, 2] = r * np.cos(phi) # offset with origin - if any(self.origin != (0.0, 0.0, 0.0)): + if any([coord != 0 for coord in self.origin]): pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] From f0721ac5351eec9425ecf4e33a90b5ac13eba1cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Mon, 21 Nov 2022 14:30:36 -0500 Subject: [PATCH 1313/2654] Apply suggestions from code review Co-authored-by: Patrick Shriwise --- openmc/mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 615514c68..307d9d952 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1052,7 +1052,7 @@ class CylindricalMesh(StructuredMesh): self._r_grid = None self._phi_grid = [0.0, 2*pi] self._z_grid = None - self._origin = (0., 0., 0.) + self.origin = (0., 0., 0.) @property def dimension(self): @@ -1378,7 +1378,7 @@ class SphericalMesh(StructuredMesh): self._r_grid = None self._theta_grid = [0, pi] self._phi_grid = [0, 2*pi] - self._origin = (0., 0., 0.) + self.origin = (0., 0., 0.) @property def dimension(self): From 5dc65503121f4131c4ad9ebd7c9ed4c53cfb7f79 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Nov 2022 14:51:40 -0600 Subject: [PATCH 1314/2654] Rename divide_by_adens --> divide_by_atoms --- openmc/deplete/abc.py | 4 ++-- openmc/deplete/openmc_operator.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 45432218a..279082c30 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -265,8 +265,8 @@ class ReactionRateHelper(ABC): Ordering of reactions """ - def divide_by_adens(self, number): - """Normalize reaction rates by number of nuclides + def divide_by_atoms(self, number): + """Normalize reaction rates by number of atoms Acts on the current material examined by :meth:`get_material_rates` diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index fd9e66524..9678c509e 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -541,10 +541,10 @@ class OpenMCOperator(TransportOperator): self._normalization_helper.update( tally_rates[:, fission_ind]) - # Divide by total number and store - rates[i] = self._rate_helper.divide_by_adens(number) + # Divide by total number of atoms and store + rates[i] = self._rate_helper.divide_by_atoms(number) - # Scale reaction rates to obtain units of reactions/sec + # Scale reaction rates to obtain units of reactions/sec/atom rates *= self._normalization_helper.factor(source_rate) # Store new fission yields on the chain From ea0892f0f3e53169a8ea80e424a5002c3d643935 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Nov 2022 15:20:12 -0600 Subject: [PATCH 1315/2654] Updated docstring to better explain chain_file and micro_xs --- openmc/deplete/independent_operator.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index a8249a98e..d11730240 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -31,6 +31,9 @@ class IndependentOperator(OpenMCOperator): passed to an integrator class, such as :class:`openmc.deplete.CECMIntegrator`. + Note that passing an empty :class:`~openmc.deplete.MicroXS` instance to the + ``micro_xs`` argument allows a decay-only calculation to be run. + .. versionadded:: 0.13.1 Parameters @@ -38,9 +41,11 @@ class IndependentOperator(OpenMCOperator): materials : openmc.Materials Materials to deplete. micro_xs : MicroXS - One-group microscopic cross sections in [b] . + One-group microscopic cross sections in [b]. If the + :class:`~openmc.deplete.MicroXS` is empty, a decay-only calculation will + be run. chain_file : str - Path to the depletion chain XML file. Defaults to + Path to the depletion chain XML file. Defaults to ``openmc.config['chain_file']``. keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. @@ -169,9 +174,12 @@ class IndependentOperator(OpenMCOperator): Dictionary with nuclide names as keys and nuclide concentrations as values. micro_xs : MicroXS - One-group microscopic cross sections. + One-group microscopic cross sections in [b]. If the + :class:`~openmc.deplete.MicroXS` is empty, a decay-only calculation + will be run. chain_file : str, optional - Path to the depletion chain XML file. + Path to the depletion chain XML file. Defaults to + ``openmc.config['chain_file']``. nuc_units : {'atom/cm3', 'atom/b-cm'}, optional Units for nuclide concentration. keff : 2-tuple of float, optional From 102288f94a99f4fd702ab43e9f2999b688c0f803 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Nov 2022 15:36:34 -0600 Subject: [PATCH 1316/2654] Apply @yardasol suggestions from code review Co-authored-by: Olek <45364492+yardasol@users.noreply.github.com> --- openmc/deplete/independent_operator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index d11730240..0c950b31b 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -42,7 +42,7 @@ class IndependentOperator(OpenMCOperator): Materials to deplete. micro_xs : MicroXS One-group microscopic cross sections in [b]. If the - :class:`~openmc.deplete.MicroXS` is empty, a decay-only calculation will + :class:`~openmc.deplete.MicroXS` object is empty, a decay-only calculation will be run. chain_file : str Path to the depletion chain XML file. Defaults to @@ -175,7 +175,7 @@ class IndependentOperator(OpenMCOperator): values. micro_xs : MicroXS One-group microscopic cross sections in [b]. If the - :class:`~openmc.deplete.MicroXS` is empty, a decay-only calculation + :class:`~openmc.deplete.MicroXS` object is empty, a decay-only calculation will be run. chain_file : str, optional Path to the depletion chain XML file. Defaults to From a08072e45092ff96a13ba496ce192bade5764666 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Nov 2022 15:57:23 -0600 Subject: [PATCH 1317/2654] Update comment in openmc_operator.py per @yardasol suggestion Co-authored-by: Olek <45364492+yardasol@users.noreply.github.com> --- openmc/deplete/openmc_operator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 9678c509e..b00d83127 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -544,7 +544,7 @@ class OpenMCOperator(TransportOperator): # Divide by total number of atoms and store rates[i] = self._rate_helper.divide_by_atoms(number) - # Scale reaction rates to obtain units of reactions/sec/atom + # Scale reaction rates to obtain units of (reactions/sec)/atom rates *= self._normalization_helper.factor(source_rate) # Store new fission yields on the chain From 8163d7a759d4212d1e8ca76471ce0a8f887a6c90 Mon Sep 17 00:00:00 2001 From: Olek <45364492+yardasol@users.noreply.github.com> Date: Mon, 21 Nov 2022 15:33:54 -0600 Subject: [PATCH 1318/2654] use defaultdict Co-authored-by: Paul Romano --- .../deplete_with_transport/test.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/regression_tests/deplete_with_transport/test.py b/tests/regression_tests/deplete_with_transport/test.py index 977241644..477959d1c 100644 --- a/tests/regression_tests/deplete_with_transport/test.py +++ b/tests/regression_tests/deplete_with_transport/test.py @@ -3,6 +3,7 @@ from math import floor import shutil from pathlib import Path +from collections import defaultdict from difflib import unified_diff import numpy as np @@ -122,18 +123,11 @@ def test_full(run_in_tmpdir, problem, multiproc): n_tallies = np.empty(N + 1, dtype=int) # Get statepoint files for all BOS points and EOL - runtimes = {} + runtimes = defaultdict(list) for n in range(N + 1): statepoint = openmc.StatePoint(f"openmc_simulation_n{n}.h5") - runtime = statepoint.runtime - if n == 0: - for measure, time in runtime.items(): - runtimes.update({measure: np.array([time])}) - else: - for measure, time in runtime.items(): - current = runtimes[measure] - updated = np.append(current, time) - runtimes.update({measure: updated}) + for measure, time in statepoint.runtime.items(): + runtimes[measure].append(time) k_n = statepoint.keff k_state[n] = [k_n.nominal_value, k_n.std_dev] n_tallies[n] = len(statepoint.tallies) @@ -144,6 +138,9 @@ def test_full(run_in_tmpdir, problem, multiproc): # Check that no additional tallies are loaded from the files assert np.all(n_tallies == 0) + # Convert values in runtimes to arrays + runtimes = {k: np.array(v) for k, v in runtimes.items()} + # Check that runtimes are qualitatively correct assert runtimes['reading cross sections'][0] != 0 assert runtimes['total initialization'][0] != 0 From 5a716f1f3ad41cdaabe1dc1221404befa4cdad59 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Fri, 18 Nov 2022 11:56:27 -0500 Subject: [PATCH 1319/2654] moved coordinate axis to 0 --- openmc/mesh.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 72b021066..d180bc7bd 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -172,10 +172,10 @@ class StructuredMesh(MeshBase): ------- vertices : numpy.ndarray Returns a numpy.ndarray representing the coordinates of the mesh - vertices with a shape equal to (dim1 + 1, ..., dimn + 1, ndim). + vertices with a shape equal to (ndim, dim1 + 1, ..., dimn + 1). """ - return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1) + return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=0) @property def centroids(self): @@ -185,13 +185,14 @@ class StructuredMesh(MeshBase): ------- centroids : numpy.ndarray Returns a numpy.ndarray representing the mesh element centroid - coordinates with a shape equal to (dim1, ..., dimn, ndim). + coordinates with a shape equal to (ndim, dim1, ..., dimn). Can be + unpacked by the first dimension with xx, yy, zz = mesh.centroids """ ndim = self.n_dimension vertices = self.vertices - s0 = (slice(0, -1),)*ndim + (slice(None),) - s1 = (slice(1, None),)*ndim + (slice(None),) + s0 = (slice(None),) + (slice(0, -1),)*ndim + s1 = (slice(None),) + (slice(1, None),)*ndim return (vertices[s0] + vertices[s1]) / 2 @property From 3794673c704b18756ed28c836d7bab4be24c4f35 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sun, 27 Nov 2022 15:54:03 -0500 Subject: [PATCH 1320/2654] Apply suggestions from code review Co-authored-by: Patrick Shriwise --- openmc/mesh.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index d180bc7bd..157e78263 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -172,7 +172,8 @@ class StructuredMesh(MeshBase): ------- vertices : numpy.ndarray Returns a numpy.ndarray representing the coordinates of the mesh - vertices with a shape equal to (ndim, dim1 + 1, ..., dimn + 1). + vertices with a shape equal to (ndim, dim1 + 1, ..., dimn + 1). Can be + unpacked along the first dimension with xx, yy, zz = mesh.vertices. """ return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=0) @@ -186,7 +187,8 @@ class StructuredMesh(MeshBase): centroids : numpy.ndarray Returns a numpy.ndarray representing the mesh element centroid coordinates with a shape equal to (ndim, dim1, ..., dimn). Can be - unpacked by the first dimension with xx, yy, zz = mesh.centroids + unpacked along the first dimension with xx, yy, zz = mesh.centroids. + """ ndim = self.n_dimension From 3e6bb9d5f669d2729fa96acdb4894ed1d338f2c5 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 08:51:23 -0300 Subject: [PATCH 1321/2654] Upgrade installation script to NCrystal 3.5.0 --- tools/ci/gha-install-ncrystal.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index c080c16d8..18472dfa6 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -21,13 +21,12 @@ cmake \ "${SRC_DIR}" \ -DBUILD_SHARED_LIBS=ON \ -DNCRYSTAL_NOTOUCH_CMAKE_BUILD_TYPE=ON \ - -DMODIFY_RPATH=OFF \ + -DNCRYSTAL_MODIFY_RPATH=OFF \ -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_EXAMPLES=OFF \ - -DINSTALL_SETUPSH=OFF \ - -DEMBED_DATA=ON \ - -DINSTALL_DATA=OFF \ - -DNO_DIRECT_PYMODINST=ON \ + -DNCRYSTAL_ENABLE_EXAMPLES=OFF \ + -DNCRYSTAL_ENABLE_SETUPSH=OFF \ + -DNCRYSTAL_ENABLE_DATA=OFF \ + -DNCRYSTAL_SKIP_PYMODINST=ON \ -DCMAKE_INSTALL_PREFIX="${INST_DIR}" \ -DPython3_EXECUTABLE="$PYTHON" @@ -62,5 +61,5 @@ EOF $PYTHON -m pip install ./ncrystal_pypkg/ -vv -# source ${INST_DIR}/setup.sh +eval $( "${INST_DIR}/bin/ncrystal-config --setup" ) From be330a11b6798850ddaa54635167c89030bfb511 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:15:45 -0300 Subject: [PATCH 1322/2654] Update gha-install-ncrystal.sh --- tools/ci/gha-install-ncrystal.sh | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index 18472dfa6..1bcc89627 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -25,8 +25,7 @@ cmake \ -DCMAKE_BUILD_TYPE=Release \ -DNCRYSTAL_ENABLE_EXAMPLES=OFF \ -DNCRYSTAL_ENABLE_SETUPSH=OFF \ - -DNCRYSTAL_ENABLE_DATA=OFF \ - -DNCRYSTAL_SKIP_PYMODINST=ON \ + -DNCRYSTAL_ENABLE_DATA=EMBED \ -DCMAKE_INSTALL_PREFIX="${INST_DIR}" \ -DPython3_EXECUTABLE="$PYTHON" @@ -36,30 +35,8 @@ make install #Note: There is no "make test" or "make ctest" functionality for NCrystal # yet. If it appears in the future, we should add it here. - -#The next stuff is not pretty, but it is needed as a temporary -#workaround until NCrystal add better support for system-wide -#installations in CMake: - -cat < ./findncrystallib.py -import pathlib -libname = pathlib.Path('./cfg_ncrystal_libname.txt').read_text().strip() -libs = list(pathlib.Path("${INST_DIR}").glob("**/lib*/**/%s"%libname)) -assert len(libs)==1 -pathlib.Path('ncrystal_liblocation.txt').write_text(str(libs[0])) -EOF - -python3 ./findncrystallib.py - -TMPNCRYSTALLIBLOCATION=$(cat ./ncrystal_liblocation.txt) - -cat < ./ncrystal_pypkg/NCrystal/_nclibpath.py -#File autogenerated for working with systemwide install of NCrystal: -import pathlib -liblocation = pathlib.Path('${TMPNCRYSTALLIBLOCATION}'.strip()) -EOF - -$PYTHON -m pip install ./ncrystal_pypkg/ -vv - eval $( "${INST_DIR}/bin/ncrystal-config --setup" ) +# Check installation worked + +ncrystal-config --setup From fff545ac79d39b6aad0ee4dd055ac1da38cc344a Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:27:12 -0300 Subject: [PATCH 1323/2654] Update gha-install-ncrystal.sh --- tools/ci/gha-install-ncrystal.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index 1bcc89627..390b7dba5 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -35,8 +35,14 @@ make install #Note: There is no "make test" or "make ctest" functionality for NCrystal # yet. If it appears in the future, we should add it here. -eval $( "${INST_DIR}/bin/ncrystal-config --setup" ) +# Output the configuration to the log + +"${INST_DIR}/bin/ncrystal-config" --setup + +# Change environmental variables + +eval $( "${INST_DIR}/bin/ncrystal-config" --setup ) # Check installation worked -ncrystal-config --setup +nctool --test From 8598ff7e4311c80c3dc7993a34eb6fc40976d7ed Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:45:27 -0300 Subject: [PATCH 1324/2654] Pass CMAKE_PREFIX_PATH from NCrystall installation --- tools/ci/gha-install.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index f3a29273f..95fe70abe 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -56,6 +56,8 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, ncrys if ncrystal: cmake_cmd.append('-DOPENMC_USE_NCRYSTAL=ON') + ncrystal_path = os.environ.get('CMAKE_PREFIX_PATH') + cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + ncrystal_path) # Build in coverage mode for coverage testing cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') From c98a12171010e00fb78572c72f7327b0de740718 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:56:10 -0300 Subject: [PATCH 1325/2654] Update gha-install.py --- tools/ci/gha-install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index 95fe70abe..f5779c935 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -56,8 +56,8 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, ncrys if ncrystal: cmake_cmd.append('-DOPENMC_USE_NCRYSTAL=ON') - ncrystal_path = os.environ.get('CMAKE_PREFIX_PATH') - cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + ncrystal_path) + ncrystal_cmake_path = os.environ.get('HOME')+'/ncrystal_inst/lib/cmake' + cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + ncrystal_cmake_path) # Build in coverage mode for coverage testing cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') From 19bf624b34806efcffc52a8f18ad915624b8811b Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 11:03:41 -0300 Subject: [PATCH 1326/2654] Add NCrystal installation test --- tools/ci/gha-script.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/ci/gha-script.sh b/tools/ci/gha-script.sh index c791167e9..4c125b529 100755 --- a/tools/ci/gha-script.sh +++ b/tools/ci/gha-script.sh @@ -14,5 +14,10 @@ if [[ $EVENT == 'y' ]]; then args="${args} --event " fi +# Check NCrystal installation +if [[ $NCRYSTAL = 'y' ]]; then + nctool --test +fi + # Run regression and unit tests pytest --cov=openmc -v $args tests From 4391d601fde4f74f91d594238e98564632c695b8 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 11:06:06 -0300 Subject: [PATCH 1327/2654] find NCrystal --- cmake/OpenMCConfig.cmake.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/OpenMCConfig.cmake.in b/cmake/OpenMCConfig.cmake.in index d0e2beb82..162e3aad7 100644 --- a/cmake/OpenMCConfig.cmake.in +++ b/cmake/OpenMCConfig.cmake.in @@ -9,6 +9,11 @@ if(@OPENMC_USE_DAGMC@) find_package(DAGMC REQUIRED HINTS @DAGMC_DIR@) endif() +if(@OPENMC_USE_NCRYSTAL@) + find_package(NCrystal REQUIRED) + message(STATUS "Found NCrystal: ${NCrystal_DIR} (version ${NCrystal_VERSION})") +endif() + if(@OPENMC_USE_LIBMESH@) include(FindPkgConfig) list(APPEND CMAKE_PREFIX_PATH @LIBMESH_PREFIX@) From e626447a4e8dbce5ff8211b0ada661c329e3cd3d Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Date: Mon, 28 Nov 2022 11:18:32 -0300 Subject: [PATCH 1328/2654] Update gha-script.sh --- tools/ci/gha-script.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ci/gha-script.sh b/tools/ci/gha-script.sh index 4c125b529..85fdef49f 100755 --- a/tools/ci/gha-script.sh +++ b/tools/ci/gha-script.sh @@ -16,6 +16,8 @@ fi # Check NCrystal installation if [[ $NCRYSTAL = 'y' ]]; then + # Change environmental variables + eval $( "${HOME}/ncrystal_inst/bin/ncrystal-config" --setup ) nctool --test fi From 71631ada048c9ca870765dfbd32c6bbc0c4e623e Mon Sep 17 00:00:00 2001 From: josh Date: Tue, 29 Nov 2022 03:39:39 +0000 Subject: [PATCH 1329/2654] fix universe's get_nuclide_density without volumes present --- openmc/universe.py | 2 +- tests/unit_tests/test_universe.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index 94ea5624a..db0d55f21 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -469,7 +469,7 @@ class Universe(UniverseBase): """ nuclides = OrderedDict() - if self._atoms is not None: + if len(self._atoms) > 0: volume = self.volume for name, atoms in self._atoms.items(): nuclide = openmc.Nuclide(name) diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py index ab3fd6e33..6f4177f54 100644 --- a/tests/unit_tests/test_universe.py +++ b/tests/unit_tests/test_universe.py @@ -132,3 +132,14 @@ def test_create_xml(cell_with_lattice): assert all(c.get('universe') == str(u.id) for c in cell_elems) assert not (set(c.get('id') for c in cell_elems) ^ set(str(c.id) for c in cells)) + + +def test_get_nuclide_densities(): + surf = openmc.Sphere() + material = openmc.Material() + material.add_elements_from_formula("H2O") + material.set_density("g/cm3", 1) + cell = openmc.Cell(region=-surf,fill=material) + universe = openmc.Universe(cells=[cell]) + with pytest.raises(RuntimeError): + universe.get_nuclide_densities() From e7b4285bd5214d0028700c07897fe60919ef8689 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Marquez Damian Date: Tue, 29 Nov 2022 11:21:04 +0100 Subject: [PATCH 1330/2654] Cleanup --- docs/source/methods/cross_sections.rst | 2 +- docs/source/usersguide/materials.rst | 2 +- tools/ci/gha-install-ncrystal.sh | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/source/methods/cross_sections.rst b/docs/source/methods/cross_sections.rst index 64e4fac3d..0b87913e5 100644 --- a/docs/source/methods/cross_sections.rst +++ b/docs/source/methods/cross_sections.rst @@ -189,7 +189,7 @@ cannot currently included in ACE files such as oriented single crystals (see the and further extend the physics `using plugins`_. Thermal scattering kernels are generated on the fly from dynamic and structural data, or loaded from :math:`S(\alpha,\beta)` tables converted from ENDF6 evaluations. These kernels are sampled in a direct way using a fast `rejection algorithm`_ -that does not require previous processing. A `large library` of materials is already included in +that does not require previous processing. A `large library`_ of materials is already included in the NCrystal distribution, and new materials can be easily defined from scratch in the `NCMAT format`_ or `combining existing files`_. diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index 1eaae846c..a3c05f421 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -106,7 +106,7 @@ Adding NCrystal materials ------------------ Additional support for thermal scattering can be added by using NCrystal_. -The :meth:`Material.from_ncrystal` class method generates a material object from +The :meth:`Material.from_ncrystal` class method generates a :class:`openmc.Material` object from an `NCrystal configuration string `_. Temperature, material composition and density are passed from the configuration string and the `NCMAT file `_ diff --git a/tools/ci/gha-install-ncrystal.sh b/tools/ci/gha-install-ncrystal.sh index 390b7dba5..16f77e13e 100755 --- a/tools/ci/gha-install-ncrystal.sh +++ b/tools/ci/gha-install-ncrystal.sh @@ -15,8 +15,6 @@ CPU_COUNT=1 mkdir "$BLD_DIR" cd ncrystal_bld -#cmake -Dstatic=on .. && make 2>/dev/null && sudo make install - cmake \ "${SRC_DIR}" \ -DBUILD_SHARED_LIBS=ON \ From 01e86efc9e40ebe815323581be1d9d024fe19a6c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 29 Nov 2022 13:29:57 -0600 Subject: [PATCH 1331/2654] Only show print() output from openmc.deplete on rank 0 --- openmc/deplete/abc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 279082c30..5b405b1d5 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -798,7 +798,7 @@ class Integrator(ABC): t, self._i_res = self._get_start_data() for i, (dt, source_rate) in enumerate(self): - if output: + if output and comm.rank == 0: print(f"[openmc.deplete] t={t} s, dt={dt} s, source={source_rate}") # Solve transport equation (or obtain result from restart) @@ -818,7 +818,7 @@ class Integrator(ABC): conc = conc_list.pop() StepResult.save(self.operator, conc_list, res_list, [t, t + dt], - source_rate, self._i_res + i, proc_time) + source_rate, self._i_res + i, proc_time) t += dt @@ -826,7 +826,7 @@ class Integrator(ABC): # source rate is passed to the transport operator (which knows to # just return zero reaction rates without actually doing a transport # solve) - if output and final_step: + if output and final_step and comm.rank == 0: print(f"[openmc.deplete] t={t} (final operator evaluation)") res_list = [self.operator(conc, source_rate if final_step else 0.0)] StepResult.save(self.operator, [conc], res_list, [t, t], From b66d9e0a907c2bd87547d6016f3d41c8455e8a22 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 29 Nov 2022 16:21:47 -0600 Subject: [PATCH 1332/2654] Add check for presence of atomic relaxation data in PhotonInteraction --- include/openmc/photon.h | 3 +++ openmc/data/photon.py | 4 +++- src/photon.cpp | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/openmc/photon.h b/include/openmc/photon.h index 09fb3ba01..9901c8c6d 100644 --- a/include/openmc/photon.h +++ b/include/openmc/photon.h @@ -100,6 +100,9 @@ public: // Bremsstrahlung scaled DCS xt::xtensor dcs_; + // Whether atomic relaxation data is present + bool has_atomic_relaxation_ {false}; + // Constant data static constexpr int MAX_STACK_SIZE = 7; //!< maximum possible size of atomic relaxation stack diff --git a/openmc/data/photon.py b/openmc/data/photon.py index 48ecc3748..fc5da19eb 100644 --- a/openmc/data/photon.py +++ b/openmc/data/photon.py @@ -13,7 +13,7 @@ from scipy.interpolate import CubicSpline import openmc.checkvalue as cv from openmc.mixin import EqualityMixin -from . import HDF5_VERSION +from . import HDF5_VERSION, HDF5_VERSION_MAJOR from .ace import Table, get_metadata, get_table from .data import ATOMIC_SYMBOL, EV_PER_MEV from .endf import Evaluation, get_head_record, get_tab1_record, get_list_record @@ -143,6 +143,8 @@ class AtomicRelaxation(EqualityMixin): Dictionary indicating the number of electrons in a subshell when neutral (values) for given subshells (keys). The subshells should be given as strings, e.g., 'K', 'L1', 'L2', etc. + subshells : list + List of subshells as strings, e.g. ``['K', 'L1', ...]`` transitions : pandas.DataFrame Dictionary indicating allowed transitions and their probabilities (values) for given subshells (keys). The subshells should be given as diff --git a/src/photon.cpp b/src/photon.cpp index a500ff2d4..590e0cc9f 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -156,8 +156,14 @@ PhotonInteraction::PhotonInteraction(hid_t group) // Read binding energy and number of electrons hid_t tgroup = open_group(rgroup, designator.c_str()); - read_attribute(tgroup, "binding_energy", shell.binding_energy); - read_attribute(tgroup, "num_electrons", shell.n_electrons); + + // Read binding energy energy and number of electrons if atomic relaxation + // data is present + if (attribute_exists(tgroup, "binding_energy")) { + has_atomic_relaxation_ = true; + read_attribute(tgroup, "binding_energy", shell.binding_energy); + read_attribute(tgroup, "num_electrons", shell.n_electrons); + } // Read subshell cross section xt::xtensor xs; @@ -757,6 +763,10 @@ void PhotonInteraction::pair_production(double alpha, double* E_electron, void PhotonInteraction::atomic_relaxation(int i_shell, Particle& p) const { + // Return if no atomic relaxation data is present + if (!has_atomic_relaxation_) + return; + // Stack for unprocessed holes left by transitioning electrons int n_holes = 0; array holes; From ea7e2a13d0b10a62ac6d7b5a80efd3d7dd48bbe2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 29 Nov 2022 17:31:29 -0600 Subject: [PATCH 1333/2654] Docs: clarify use of environment variables in tests --- docs/source/devguide/tests.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/source/devguide/tests.rst b/docs/source/devguide/tests.rst index d55713062..922f47eb3 100644 --- a/docs/source/devguide/tests.rst +++ b/docs/source/devguide/tests.rst @@ -31,9 +31,13 @@ Prerequisites - The test suite requires a specific set of cross section data in order for tests to pass. A download URL for the data that OpenMC expects can be found - within ``tools/ci/download-xs.sh``. + within ``tools/ci/download-xs.sh``. Once the tarball is downloaded and + unpacked, set the :envvar:`OPENMC_CROSS_SECTIONS` environment variable to the + path of the ``cross_sections.xml`` file within the unpacked data. - In addition to the HDF5 data, some tests rely on ENDF files. A download URL - for those can also be found in ``tools/ci/download-xs.sh``. + for those can also be found in ``tools/ci/download-xs.sh``. Once the tarball + is downloaded and unpacked, set the :envvar:`OPENMC_ENDF_DATA` environment + variable to the top-level directory of the unpacked tarball. - Some tests require `NJOY `_ to preprocess cross section data. The test suite assumes that you have an ``njoy`` executable available on your :envvar:`PATH`. From 3f83699c225629688d8111e4b1fea9882c744af1 Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 30 Nov 2022 00:59:26 +0000 Subject: [PATCH 1334/2654] update styling --- openmc/universe.py | 2 +- tests/unit_tests/test_universe.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index db0d55f21..bdd6e6ec9 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -469,7 +469,7 @@ class Universe(UniverseBase): """ nuclides = OrderedDict() - if len(self._atoms) > 0: + if self._atoms: volume = self.volume for name, atoms in self._atoms.items(): nuclide = openmc.Nuclide(name) diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py index 6f4177f54..33c86b150 100644 --- a/tests/unit_tests/test_universe.py +++ b/tests/unit_tests/test_universe.py @@ -139,7 +139,7 @@ def test_get_nuclide_densities(): material = openmc.Material() material.add_elements_from_formula("H2O") material.set_density("g/cm3", 1) - cell = openmc.Cell(region=-surf,fill=material) + cell = openmc.Cell(region=-surf, fill=material) universe = openmc.Universe(cells=[cell]) with pytest.raises(RuntimeError): universe.get_nuclide_densities() From 43c0dcb1b8f00418a338bfe85181ed99c0430b7c Mon Sep 17 00:00:00 2001 From: valeriogiusti <77335624+valeriogiusti@users.noreply.github.com> Date: Thu, 1 Dec 2022 11:49:52 +0100 Subject: [PATCH 1335/2654] Update universe.py Running a Jupyter notebook prepared some time ago, I got the following error when trying to plot a universe. ``` --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in 1 universe = openmc.Universe(cells=(fuel, moderator)) ----> 2 universe.plot(origin=[0.,0.,0.],width=[2.4,2.4],basis='xy') ~/.local/lib/python3.8/site-packages/openmc/universe.py in plot(self, origin, width, pixels, basis, color_by, colors, seed, openmc_exec, axes, **kwargs) 362 if not img_path.is_file(): 363 img_path = img_path.with_suffix('.ppm') --> 364 img = mpimg.imread(img_path) 365 366 # Create a figure sized such that the size of the axes within /usr/lib/python3/dist-packages/matplotlib/image.py in imread(fname, format) 1434 return handler(fd) 1435 else: -> 1436 return handler(fname) 1437 1438 /usr/lib/python3/dist-packages/matplotlib/image.py in read_png(*args, **kwargs) 1388 def read_png(*args, **kwargs): 1389 from matplotlib import _png -> 1390 return _png.read_png(*args, **kwargs) 1391 1392 handlers = {'png': read_png, } TypeError: Object does not appear to be a 8-bit string path or a Python file-like object ``` The error disappears and the plot is correctly shown if line 364 is changed as follows: `img = mpimg.imread(str(img_path))` Does this change sound reasonable? I'm running Python 3.8.10. --- openmc/universe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/universe.py b/openmc/universe.py index bdd6e6ec9..9c93e6da1 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -361,7 +361,7 @@ class Universe(UniverseBase): img_path = Path(tmpdir) / f'plot_{plot.id}.png' if not img_path.is_file(): img_path = img_path.with_suffix('.ppm') - img = mpimg.imread(img_path) + img = mpimg.imread(str(img_path)) # Create a figure sized such that the size of the axes within # exactly matches the number of pixels specified From e99f6e45e9373acaca773e3930704fff0d726880 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 5 Dec 2022 10:33:52 -0600 Subject: [PATCH 1336/2654] Fix algorithm for adding parentheses in region expressions --- src/cell.cpp | 54 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index 10799fedb..9ba14c6cf 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -100,11 +100,15 @@ void Cell::set_temperature(double T, int32_t instance, bool set_contained) { if (settings::temperature_method == TemperatureMethod::INTERPOLATION) { if (T < (data::temperature_min - settings::temperature_tolerance)) { - throw std::runtime_error {fmt::format("Temperature of {} K is below minimum temperature at " - "which data is available of {} K.", T, data::temperature_min)}; + throw std::runtime_error { + fmt::format("Temperature of {} K is below minimum temperature at " + "which data is available of {} K.", + T, data::temperature_min)}; } else if (T > (data::temperature_max + settings::temperature_tolerance)) { - throw std::runtime_error {fmt::format("Temperature of {} K is above maximum temperature at " - "which data is available of {} K.", T, data::temperature_max)}; + throw std::runtime_error { + fmt::format("Temperature of {} K is above maximum temperature at " + "which data is available of {} K.", + T, data::temperature_max)}; } } @@ -586,8 +590,13 @@ std::vector::iterator Region::add_parentheses( } start++; - // Initialize return iterator - auto return_iterator = expression_.begin(); + // Keep track of return iterator distance. If we don't encounter a left + // parenthesis, we return an iterator corresponding to wherever the right + // parenthesis is inserted. If a left parenthesis is encountered, an iterator + // corresponding to the left parenthesis is returned. Also note that we keep + // track of a *distance* instead of an iterator because the underlying memory + // allocation may change. + std::size_t return_it_dist = 0; // Add right parenthesis // While the start iterator is within the bounds of infix @@ -600,9 +609,9 @@ std::vector::iterator Region::add_parentheses( // add right parenthesis, right parenthesis position depends on the // operator, when the operator is a union then do not include the operator // in the region, when the operator is an intersection then include the - // operato and next surface + // operator and next surface if (*start == OP_LEFT_PAREN) { - return_iterator = start; + return_it_dist = std::distance(expression_.begin(), start); int depth = 1; do { start++; @@ -617,20 +626,22 @@ std::vector::iterator Region::add_parentheses( } else { start = expression_.insert( start_token == OP_UNION ? start - 1 : start, OP_RIGHT_PAREN); - if (return_iterator == expression_.begin()) { - return_iterator = start - 1; + if (return_it_dist > 0) { + return expression_.begin() + return_it_dist; + } else { + return start - 1; } - return return_iterator; } } } // If we get here a right parenthesis hasn't been placed, // return iterator expression_.push_back(OP_RIGHT_PAREN); - if (return_iterator == expression_.begin()) { - return_iterator = start - 1; + if (return_it_dist > 0) { + return expression_.begin() + return_it_dist; + } else { + return start - 1; } - return return_iterator; } //============================================================================== @@ -638,6 +649,7 @@ std::vector::iterator Region::add_parentheses( void Region::add_precedence() { int32_t current_op = 0; + std::size_t current_dist = 0; for (auto it = expression_.begin(); it != expression_.end(); it++) { int32_t token = *it; @@ -646,15 +658,22 @@ void Region::add_precedence() if (current_op == 0) { // Set the current operator if is hasn't been set current_op = token; + current_dist = std::distance(expression_.begin(), it); } else if (token != current_op) { // If the current operator doesn't match the token, add parenthesis to // assert precedence - it = add_parentheses(it); + if (current_op == OP_INTERSECTION) { + it = add_parentheses(expression_.begin() + current_dist); + } else { + it = add_parentheses(it); + } current_op = 0; + current_dist = 0; } } else if (token > OP_COMPLEMENT) { // If the token is a parenthesis reset the current operator current_op = 0; + current_dist = 0; } } } @@ -770,7 +789,6 @@ std::pair Region::distance( double min_dist {INFTY}; int32_t i_surf {std::numeric_limits::max()}; - for (int32_t token : expression_) { // Ignore this token if it corresponds to an operator rather than a region. if (token >= OP_UNION) @@ -943,13 +961,13 @@ vector Region::surfaces() const vector surfaces = expression_; - auto it = std::find_if(surfaces.begin(), surfaces.end(), + auto it = std::find_if(surfaces.begin(), surfaces.end(), [&](const auto& value) { return value >= OP_UNION; }); while (it != surfaces.end()) { surfaces.erase(it); - it = std::find_if(surfaces.begin(), surfaces.end(), + it = std::find_if(surfaces.begin(), surfaces.end(), [&](const auto& value) { return value >= OP_UNION; }); } From db6a818a566ab84fdc523da0c5fb153422a8091c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 5 Dec 2022 10:35:24 -0600 Subject: [PATCH 1337/2654] Ensure complex cell test case covers need for adding precedence --- tests/regression_tests/complex_cell/geometry.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/complex_cell/geometry.xml b/tests/regression_tests/complex_cell/geometry.xml index a695396e0..638c7c9b8 100644 --- a/tests/regression_tests/complex_cell/geometry.xml +++ b/tests/regression_tests/complex_cell/geometry.xml @@ -19,7 +19,7 @@ - + From 185920a7f1c99f6943934289c5a574e9e1dbb45a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 5 Dec 2022 16:19:58 -0600 Subject: [PATCH 1338/2654] Allow source particles with energy below cutoff (will just deposit energy) --- docs/source/usersguide/tallies.rst | 5 ++--- src/source.cpp | 7 ++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/source/usersguide/tallies.rst b/docs/source/usersguide/tallies.rst index da2c5f26d..97ca319a2 100644 --- a/docs/source/usersguide/tallies.rst +++ b/docs/source/usersguide/tallies.rst @@ -269,9 +269,8 @@ The following tables show all valid scores: |heating |Total nuclear heating in units of eV per source | | |particle. For neutrons, this corresponds to MT=301 | | |produced by NJOY's HEATR module while for photons, | - | |this is tallied from either direct photon energy | - | |deposition (analog estimator) or pre-generated | - | |photon heating number. See :ref:`methods_heating` | + | |this is tallied from direct photon energy | + | |deposition. See :ref:`methods_heating`. | +----------------------+---------------------------------------------------+ |heating-local |Total nuclear heating in units of eV per source | | |particle assuming energy from secondary photons is | diff --git a/src/source.cpp b/src/source.cpp index d201e3c03..3a80e1156 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -256,9 +256,6 @@ SourceSite IndependentSource::sample(uint64_t* seed) const if (xt::any(energies > data::energy_max[p])) { fatal_error("Source energy above range of energies of at least " "one cross section table"); - } else if (xt::any(energies < data::energy_min[p])) { - fatal_error("Source energy below range of energies of at least " - "one cross section table"); } } @@ -266,8 +263,8 @@ SourceSite IndependentSource::sample(uint64_t* seed) const // Sample energy spectrum site.E = energy_->sample(seed); - // Resample if energy falls outside minimum or maximum particle energy - if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) + // Resample if energy falls above maximum particle energy + if (site.E < data::energy_max[p]) break; n_reject++; From f9309bf09094445c9bca3c42bdf2d5c93fe77dc9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 5 Dec 2022 22:09:52 -0600 Subject: [PATCH 1339/2654] Check for valid binding energy for photoelectric effect --- src/photon.cpp | 1 - src/physics.cpp | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/photon.cpp b/src/photon.cpp index 590e0cc9f..c4beff019 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -154,7 +154,6 @@ PhotonInteraction::PhotonInteraction(hid_t group) // TODO: Move to ElectronSubshell constructor - // Read binding energy and number of electrons hid_t tgroup = open_group(rgroup, designator.c_str()); // Read binding energy energy and number of electrons if atomic relaxation diff --git a/src/physics.cpp b/src/physics.cpp index ae59b49cb..7d391fdf6 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -366,7 +366,14 @@ void sample_photon_reaction(Particle& p) xs_lower(i_shell) + f * (xs_upper(i_shell) - xs_lower(i_shell))); if (prob > cutoff) { - double E_electron = p.E() - shell.binding_energy; + // Determine binding energy based on whether atomic relaxation data is + // present (if not, use value from Compton profile data) + double binding_energy = element.has_atomic_relaxation_ + ? shell.binding_energy + : element.binding_energy_[i_shell]; + + // Determine energy of secondary electron + double E_electron = p.E() - binding_energy; // Sample mu using non-relativistic Sauter distribution. // See Eqns 3.19 and 3.20 in "Implementing a photon physics From f9884650ece2ae1398bcb6bea31c1b39a98b7a0e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 5 Dec 2022 23:10:01 -0600 Subject: [PATCH 1340/2654] Fix IncidentNeutron.from_njoy for high temperatures --- openmc/data/neutron.py | 3 +-- tests/unit_tests/test_data_neutron.py | 9 +++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py index db78ce27b..e0574d76d 100644 --- a/openmc/data/neutron.py +++ b/openmc/data/neutron.py @@ -868,9 +868,8 @@ class IncidentNeutron(EqualityMixin): heatr_evals = get_evaluations(kwargs["heatr"]) heatr_local_evals = get_evaluations(kwargs["heatr"] + "_local") - for ev, ev_local in zip(heatr_evals, heatr_local_evals): - temp = "{}K".format(round(ev.target["temperature"])) + for ev, ev_local, temp in zip(heatr_evals, heatr_local_evals, data.temperatures): # Get total KERMA (originally from ACE file) and energy grid kerma = data.reactions[301].xs[temp] E = kerma.x diff --git a/tests/unit_tests/test_data_neutron.py b/tests/unit_tests/test_data_neutron.py index 0b33f05fc..c0d6a1f15 100644 --- a/tests/unit_tests/test_data_neutron.py +++ b/tests/unit_tests/test_data_neutron.py @@ -531,3 +531,12 @@ def test_ace_table_types(): assert TT.from_suffix('20t') == TT.THERMAL_SCATTERING with pytest.raises(ValueError): TT.from_suffix('z') + + +@needs_njoy +def test_high_temperature(): + endf_data = os.environ['OPENMC_ENDF_DATA'] + endf_file = os.path.join(endf_data, 'neutrons', 'n-001_H_001.endf') + + # Ensure that from_njoy works when given a high temperature + openmc.data.IncidentNeutron.from_njoy(endf_file, temperatures=[123_456.0]) From 5b807d4e6cdb988a10e42647f98c7f0da1ac3000 Mon Sep 17 00:00:00 2001 From: josh Date: Tue, 6 Dec 2022 18:31:28 +0000 Subject: [PATCH 1341/2654] add capability to set cell temperature to None --- openmc/cell.py | 4 ++-- tests/unit_tests/test_cell.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 0cea73b32..9a7c00962 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -318,12 +318,12 @@ class Cell(IDManagerMixin): @temperature.setter def temperature(self, temperature): # Make sure temperatures are positive - cv.check_type('cell temperature', temperature, (Iterable, Real)) + cv.check_type('cell temperature', temperature, (Iterable, Real), none_ok=True) if isinstance(temperature, Iterable): cv.check_type('cell temperature', temperature, Iterable, Real) for T in temperature: cv.check_greater_than('cell temperature', T, 0.0, True) - else: + elif isinstance(temperature, Real): cv.check_greater_than('cell temperature', temperature, 0.0, True) # If this cell is filled with a universe or lattice, propagate diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 56e610e26..1c2e1b70e 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -92,6 +92,9 @@ def test_temperature(cell_with_lattice): assert c2.temperature == 400.0 with pytest.raises(ValueError): c.temperature = -100. + c.temperature = None + assert c1.temperature == None + assert c2.temperature == None # distributed temperature cells, _, _, _ = cell_with_lattice From 2555b951a4c585ab31942d4a718c2c5354d082a8 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 18:27:53 -0500 Subject: [PATCH 1342/2654] Factor out to_xml_element methods for XML classes --- openmc/geometry.py | 52 +++++++++++++-------- openmc/plots.py | 21 +++++---- openmc/settings.py | 109 ++++++++++++++++++++++++--------------------- openmc/tallies.py | 25 +++++++---- 4 files changed, 120 insertions(+), 87 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 3b6933362..889cb6b31 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -103,6 +103,38 @@ class Geometry: if universe.id in volume_calc.volumes: universe.add_volume_information(volume_calc) + def to_xml_element(self, remove_surfs=False): + """Creates a 'geometry' element to be written to an XML file. + + Parameters + ---------- + remove_surfs : bool + Whether or not to remove redundant surfaces from the geometry when + exporting + + """ + # Find and remove redundant surfaces from the geometry + if remove_surfs: + warnings.warn("remove_surfs kwarg will be deprecated soon, please " + "set the Geometry.merge_surfaces attribute instead.") + self.merge_surfaces = True + + if self.merge_surfaces: + self.remove_redundant_surfaces() + + # Create XML representation + element = ET.Element("geometry") + self.root_universe.create_xml_subelement(element, memo=set()) + + # Sort the elements in the file + element[:] = sorted(element, key=lambda x: ( + x.tag, int(x.get('id')))) + + # Clean the indentation in the file to be user-readable + xml.clean_indentation(element) + + return element + def export_to_xml(self, path='geometry.xml', remove_surfs=False): """Export geometry to an XML file. @@ -117,25 +149,7 @@ class Geometry: .. versionadded:: 0.12 """ - # Find and remove redundant surfaces from the geometry - if remove_surfs: - warnings.warn("remove_surfs kwarg will be deprecated soon, please " - "set the Geometry.merge_surfaces attribute instead.") - self.merge_surfaces = True - - if self.merge_surfaces: - self.remove_redundant_surfaces() - - # Create XML representation - root_element = ET.Element("geometry") - self.root_universe.create_xml_subelement(root_element, memo=set()) - - # Sort the elements in the file - root_element[:] = sorted(root_element, key=lambda x: ( - x.tag, int(x.get('id')))) - - # Clean the indentation in the file to be user-readable - xml.clean_indentation(root_element) + root_element = self.to_xml_element(remove_surfs) # Check if path is a directory p = Path(path) diff --git a/openmc/plots.py b/openmc/plots.py index 2708683b1..52dcf3fc1 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -909,14 +909,8 @@ class Plots(cv.CheckedList): self._plots_file.append(xml_element) - def export_to_xml(self, path='plots.xml'): - """Export plot specifications to an XML file. - - Parameters - ---------- - path : str - Path to file to write. Defaults to 'plots.xml'. - + def to_xml_element(self): + """Create a 'plots' element to be written to an XML file. """ # Reset xml element tree self._plots_file.clear() @@ -926,6 +920,17 @@ class Plots(cv.CheckedList): # Clean the indentation in the file to be user-readable clean_indentation(self._plots_file) + return self._plots_file + + def export_to_xml(self, path='plots.xml'): + """Export plot specifications to an XML file. + + Parameters + ---------- + path : str + Path to file to write. Defaults to 'plots.xml'. + + """ # Check if path is a directory p = Path(path) if p.is_dir(): diff --git a/openmc/settings.py b/openmc/settings.py index 7d327ce7c..29e19db2e 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1539,6 +1539,63 @@ class Settings: if text is not None: self.max_tracks = int(text) + def to_xml_element(self): + """Create a 'settings' element to be written to an XML file. + """ + + # Reset xml element tree + element = ET.Element("settings") + + self._create_run_mode_subelement(element) + self._create_particles_subelement(element) + self._create_batches_subelement(element) + self._create_inactive_subelement(element) + self._create_max_lost_particles_subelement(element) + self._create_rel_max_lost_particles_subelement(element) + self._create_generations_per_batch_subelement(element) + self._create_keff_trigger_subelement(element) + self._create_source_subelement(element) + self._create_output_subelement(element) + self._create_statepoint_subelement(element) + self._create_sourcepoint_subelement(element) + self._create_surf_source_read_subelement(element) + self._create_surf_source_write_subelement(element) + self._create_confidence_intervals(element) + self._create_electron_treatment_subelement(element) + self._create_energy_mode_subelement(element) + self._create_max_order_subelement(element) + self._create_photon_transport_subelement(element) + self._create_ptables_subelement(element) + self._create_seed_subelement(element) + self._create_survival_biasing_subelement(element) + self._create_cutoff_subelement(element) + self._create_entropy_mesh_subelement(element) + self._create_trigger_subelement(element) + self._create_no_reduce_subelement(element) + self._create_verbosity_subelement(element) + self._create_tabular_legendre_subelements(element) + self._create_temperature_subelements(element) + self._create_trace_subelement(element) + self._create_track_subelement(element) + self._create_ufs_mesh_subelement(element) + self._create_resonance_scattering_subelement(element) + self._create_volume_calcs_subelement(element) + self._create_create_fission_neutrons_subelement(element) + self._create_delayed_photon_scaling_subelement(element) + self._create_event_based_subelement(element) + self._create_max_particles_in_flight_subelement(element) + self._create_material_cell_offsets_subelement(element) + self._create_log_grid_bins_subelement(element) + self._create_write_initial_source_subelement(element) + self._create_weight_windows_subelement(element) + self._create_max_splits_subelement(element) + self._create_max_tracks_subelement(element) + + # Clean the indentation in the file to be user-readable + clean_indentation(element) + + return element + def export_to_xml(self, path: PathLike = 'settings.xml'): """Export simulation settings to an XML file. @@ -1548,57 +1605,7 @@ class Settings: Path to file to write. Defaults to 'settings.xml'. """ - - # Reset xml element tree - root_element = ET.Element("settings") - - self._create_run_mode_subelement(root_element) - self._create_particles_subelement(root_element) - self._create_batches_subelement(root_element) - self._create_inactive_subelement(root_element) - self._create_max_lost_particles_subelement(root_element) - self._create_rel_max_lost_particles_subelement(root_element) - self._create_generations_per_batch_subelement(root_element) - self._create_keff_trigger_subelement(root_element) - self._create_source_subelement(root_element) - self._create_output_subelement(root_element) - self._create_statepoint_subelement(root_element) - self._create_sourcepoint_subelement(root_element) - self._create_surf_source_read_subelement(root_element) - self._create_surf_source_write_subelement(root_element) - self._create_confidence_intervals(root_element) - self._create_electron_treatment_subelement(root_element) - self._create_energy_mode_subelement(root_element) - self._create_max_order_subelement(root_element) - self._create_photon_transport_subelement(root_element) - self._create_ptables_subelement(root_element) - self._create_seed_subelement(root_element) - self._create_survival_biasing_subelement(root_element) - self._create_cutoff_subelement(root_element) - self._create_entropy_mesh_subelement(root_element) - self._create_trigger_subelement(root_element) - self._create_no_reduce_subelement(root_element) - self._create_verbosity_subelement(root_element) - self._create_tabular_legendre_subelements(root_element) - self._create_temperature_subelements(root_element) - self._create_trace_subelement(root_element) - self._create_track_subelement(root_element) - self._create_ufs_mesh_subelement(root_element) - self._create_resonance_scattering_subelement(root_element) - self._create_volume_calcs_subelement(root_element) - self._create_create_fission_neutrons_subelement(root_element) - self._create_delayed_photon_scaling_subelement(root_element) - self._create_event_based_subelement(root_element) - self._create_max_particles_in_flight_subelement(root_element) - self._create_material_cell_offsets_subelement(root_element) - self._create_log_grid_bins_subelement(root_element) - self._create_write_initial_source_subelement(root_element) - self._create_weight_windows_subelement(root_element) - self._create_max_splits_subelement(root_element) - self._create_max_tracks_subelement(root_element) - - # Clean the indentation in the file to be user-readable - clean_indentation(root_element) + root_element = self.to_xml_element() # Check if path is a directory p = Path(path) diff --git a/openmc/tallies.py b/openmc/tallies.py index d0355f14e..dfb0c98bf 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3155,6 +3155,21 @@ class Tallies(cv.CheckedList): for d in derivs: root_element.append(d.to_xml_element()) + def to_xml_element(self): + """Creates a 'tallies' element to be written to an XML file. + """ + element = ET.Element("tallies") + self._create_mesh_subelements(element) + self._create_filter_subelements(element) + self._create_tally_subelements(element) + self._create_derivative_subelements(element) + + # Clean the indentation in the file to be user-readable + clean_indentation(element) + + return element + + def export_to_xml(self, path='tallies.xml'): """Create a tallies.xml file that can be used for a simulation. @@ -3164,15 +3179,7 @@ class Tallies(cv.CheckedList): Path to file to write. Defaults to 'tallies.xml'. """ - - root_element = ET.Element("tallies") - self._create_mesh_subelements(root_element) - self._create_filter_subelements(root_element) - self._create_tally_subelements(root_element) - self._create_derivative_subelements(root_element) - - # Clean the indentation in the file to be user-readable - clean_indentation(root_element) + root_element = self.to_xml_element() # Check if path is a directory p = Path(path) From ad746cb3e1d57c2fec163fbb4b8f87286bf72852 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 19:09:15 -0500 Subject: [PATCH 1343/2654] Writing all main nodes to a single XML file --- openmc/material.py | 62 +++++++++++++++++++++++++------------------ openmc/model/model.py | 34 +++++++++++++++++------- openmc/settings.py | 2 +- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 420a08521..af42e2e24 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1449,6 +1449,41 @@ class Materials(cv.CheckedList): for material in self: material.make_isotropic_in_lab() + def _write_xml(self, file): + """Writes XML content of the materials to an open file handle. + + Parameters + ---------- + file : IOTextWrapper + Open file handle to write content into. + """ + # Write the header and the opening tag for the root element. + file.write("\n") + file.write('\n') + + # Write the element. + if self.cross_sections is not None: + element = ET.Element('cross_sections') + element.text = str(self.cross_sections) + clean_indentation(element, level=1) + element.tail = element.tail.strip(' ') + file.write(' ') + reorder_attributes(element) # TODO: Remove when support is Python 3.8+ + ET.ElementTree(element).write(file, encoding='unicode') + + # Write the elements. + for material in sorted(self, key=lambda x: x.id): + element = material.to_xml_element() + clean_indentation(element, level=1) + element.tail = element.tail.strip(' ') + file.write(' ') + reorder_attributes(element) # TODO: Remove when support is Python 3.8+ + ET.ElementTree(element).write(file, encoding='unicode') + + # Write the closing tag for the root element. + file.write('\n') + + def export_to_xml(self, path: PathLike = 'materials.xml'): """Export material collection to an XML file. @@ -1468,32 +1503,7 @@ class Materials(cv.CheckedList): # one go. with open(str(p), 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: - - # Write the header and the opening tag for the root element. - fh.write("\n") - fh.write('\n') - - # Write the element. - if self.cross_sections is not None: - element = ET.Element('cross_sections') - element.text = str(self.cross_sections) - clean_indentation(element, level=1) - element.tail = element.tail.strip(' ') - fh.write(' ') - reorder_attributes(element) # TODO: Remove when support is Python 3.8+ - ET.ElementTree(element).write(fh, encoding='unicode') - - # Write the elements. - for material in sorted(self, key=lambda x: x.id): - element = material.to_xml_element() - clean_indentation(element, level=1) - element.tail = element.tail.strip(' ') - fh.write(' ') - reorder_attributes(element) # TODO: Remove when support is Python 3.8+ - ET.ElementTree(element).write(fh, encoding='unicode') - - # Write the closing tag for the root element. - fh.write('\n') + self._write_xml(fh) @classmethod def from_xml(cls, path: PathLike = 'materials.xml'): diff --git a/openmc/model/model.py b/openmc/model/model.py index 98136b2d5..5a1b86a1f 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -5,11 +5,16 @@ import os from pathlib import Path from numbers import Integral from tempfile import NamedTemporaryFile +<<<<<<< HEAD import warnings +======= +from xml.etree import ElementTree as ET +>>>>>>> d42935a08 (Writing all main nodes to a single XML file) import h5py import openmc +import openmc._xml as xml from openmc.dummy_comm import DummyCommunicator from openmc.executor import _process_CLI_arguments from openmc.checkvalue import check_type, check_value @@ -404,7 +409,7 @@ class Model: Parameters ---------- directory : str - Directory to write XML files to. If it doesn't exist already, it + Directory to write the model.xml file to. If it doesn't exist already, it will be created. remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when @@ -416,8 +421,8 @@ class Model: d = Path(directory) if not d.is_dir(): d.mkdir(parents=True) + d /= 'model.xml' - self.settings.export_to_xml(d) if remove_surfs: warnings.warn("remove_surfs kwarg will be deprecated soon, please " "set the Geometry.merge_surfaces attribute instead.") @@ -425,22 +430,33 @@ class Model: # Can be used to modify tallies in case any surfaces are redundant redundant_surfaces = self.geometry.remove_redundant_surfaces() - self.geometry.export_to_xml(d) + settings_element = self.settings.to_xml_element() + geometry_element = self.geometry.to_xml_element() # If a materials collection was specified, export it. Otherwise, look # for all materials in the geometry and use that to automatically build # a collection. if self.materials: - self.materials.export_to_xml(d) + materials = self.materials else: materials = openmc.Materials(self.geometry.get_all_materials() .values()) - materials.export_to_xml(d) - if self.tallies: - self.tallies.export_to_xml(d) - if self.plots: - self.plots.export_to_xml(d) + with open(d, 'w', encoding='utf-8', + errors='xmlcharrefreplace') as fh: + # Write the materials collection to the open XML file first. + # This will write the XML header also + materials._write_xml(fh) + # Write remaining elements as a tree + ET.ElementTree(geometry_element).write(fh, encoding='unicode') + ET.ElementTree(settings_element).write(fh, encoding='unicode') + + if self.tallies: + tallies_element = self.tallies.to_xml_element() + ET.ElementTree(tallies_element).write(fh, encoding='unicode') + if self.plots: + plots_element = self.plots.to_xml_element() + ET.ElementTree(plots_element).write(fh, encoding='unicode') def import_properties(self, filename): """Import physical properties diff --git a/openmc/settings.py b/openmc/settings.py index 29e19db2e..dd0041351 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1595,7 +1595,7 @@ class Settings: clean_indentation(element) return element - + def export_to_xml(self, path: PathLike = 'settings.xml'): """Export simulation settings to an XML file. From a09a61e77b10416ad52613bb578e03d60af72ebf Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 19:12:18 -0500 Subject: [PATCH 1344/2654] Writing all output under a single root node --- openmc/material.py | 7 +++++-- openmc/model/model.py | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index af42e2e24..9e3951ccf 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1449,16 +1449,19 @@ class Materials(cv.CheckedList): for material in self: material.make_isotropic_in_lab() - def _write_xml(self, file): + def _write_xml(self, file, header=True): """Writes XML content of the materials to an open file handle. Parameters ---------- file : IOTextWrapper Open file handle to write content into. + header : bool + Whether or not to write the XML header """ # Write the header and the opening tag for the root element. - file.write("\n") + if header: + file.write("\n") file.write('\n') # Write the element. diff --git a/openmc/model/model.py b/openmc/model/model.py index 5a1b86a1f..1af3bdffc 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -444,9 +444,12 @@ class Model: with open(d, 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: + # write the XML header + fh.write("\n") + fh.write("\n") # Write the materials collection to the open XML file first. # This will write the XML header also - materials._write_xml(fh) + materials._write_xml(fh, False) # Write remaining elements as a tree ET.ElementTree(geometry_element).write(fh, encoding='unicode') ET.ElementTree(settings_element).write(fh, encoding='unicode') @@ -457,6 +460,7 @@ class Model: if self.plots: plots_element = self.plots.to_xml_element() ET.ElementTree(plots_element).write(fh, encoding='unicode') + fh.write("\n") def import_properties(self, filename): """Import physical properties From 7a9d8c95afa53fca2a8d99cf48a6be13f1786107 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 19:18:39 -0500 Subject: [PATCH 1345/2654] Keeping old option to write separate XMLs so I can still use to tests to make sure I don't break stuff. --- openmc/model/model.py | 61 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 1af3bdffc..e3c4c4ae1 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -403,7 +403,66 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.', remove_surfs=False): + def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True): + """Export model to separate XML files. + + Parameters + ---------- + directory : str + Directory to write XML files to. If it doesn't exist already, it + will be created. + remove_surfs : bool + Whether or not to remove redundant surfaces from the geometry when + exporting. + + .. versionadded:: 0.13.1 + + separate_xmls : bool + Whether or not to write a single model.xml file or many XML files. + """ + if separate_xmls: + self.export_to_separate_xmls(directory, remove_surfs) + else: + self.export_to_single_xml(directory, remove_surfs) + + def export_to_separate_xmls(self, directory='.', remove_surfs=False): + """Export model to separate XML files. + + Parameters + ---------- + directory : str + Directory to write XML files to. If it doesn't exist already, it + will be created. + remove_surfs : bool + Whether or not to remove redundant surfaces from the geometry when + exporting. + + .. versionadded:: 0.13.1 + """ + # Create directory if required + d = Path(directory) + if not d.is_dir(): + d.mkdir(parents=True) + + self.settings.export_to_xml(d) + self.geometry.export_to_xml(d, remove_surfs=remove_surfs) + + # If a materials collection was specified, export it. Otherwise, look + # for all materials in the geometry and use that to automatically build + # a collection. + if self.materials: + self.materials.export_to_xml(d) + else: + materials = openmc.Materials(self.geometry.get_all_materials() + .values()) + materials.export_to_xml(d) + + if self.tallies: + self.tallies.export_to_xml(d) + if self.plots: + self.plots.export_to_xml(d) + + def export_to_single_xml(self, directory='.', remove_surfs=False): """Export model to XML files. Parameters From 040965245dc5a7476aa005829e7cb42f75a9233c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 20:10:22 -0500 Subject: [PATCH 1346/2654] Adding signatures for reading information from an XML node where necessary. --- include/openmc/cross_sections.h | 5 +++ include/openmc/geometry_aux.h | 6 ++++ include/openmc/material.h | 4 +++ include/openmc/plot.h | 4 +++ include/openmc/settings.h | 5 ++- include/openmc/tallies/tally.h | 8 +++-- src/cross_sections.cpp | 8 +++-- src/geometry_aux.cpp | 8 +++-- src/initialize.cpp | 63 ++++++++++++++++++++++++++++++--- src/material.cpp | 9 +++-- src/plot.cpp | 7 ++-- src/settings.cpp | 14 +++++--- src/tallies/tally.cpp | 8 +++-- 13 files changed, 127 insertions(+), 22 deletions(-) diff --git a/include/openmc/cross_sections.h b/include/openmc/cross_sections.h index 2b0473bec..06140a6a8 100644 --- a/include/openmc/cross_sections.h +++ b/include/openmc/cross_sections.h @@ -62,6 +62,11 @@ extern vector libraries; //! libraries void read_cross_sections_xml(); +//! Read cross sections file (either XML or multigroup H5) and populate data +//! libraries +//! \param[in] root node of the cross_sections.xml +void read_cross_sections_xml(pugi::xml_node root); + //! Load nuclide and thermal scattering data from HDF5 files // //! \param[in] nuc_temps Temperatures for each nuclide in [K] diff --git a/include/openmc/geometry_aux.h b/include/openmc/geometry_aux.h index b248d491a..a4c506c31 100644 --- a/include/openmc/geometry_aux.h +++ b/include/openmc/geometry_aux.h @@ -10,6 +10,7 @@ #include #include "openmc/vector.h" +#include "openmc/xml_interface.h" namespace openmc { @@ -19,8 +20,13 @@ extern std::unordered_map> extern std::unordered_map universe_level_counts; } // namespace model +//! Read geometry from XML file void read_geometry_xml(); +//! Read geometry from XML node +//! \param[in] root node of geometry XML element +void read_geometry_xml(pugi::xml_node root); + //============================================================================== //! Replace Universe, Lattice, and Material IDs with indices. //============================================================================== diff --git a/include/openmc/material.h b/include/openmc/material.h index b251a3ca8..81f4e1421 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -221,6 +221,10 @@ double density_effect(const vector& f, const vector& e_b_sq, //! Read material data from materials.xml void read_materials_xml(); +//! Read material data XML node +//! \param[in] root node of materials XML element +void read_materials_xml(pugi::xml_node root); + void free_memory_material(); } // namespace openmc diff --git a/include/openmc/plot.h b/include/openmc/plot.h index 650b7e16a..a415b1747 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -279,6 +279,10 @@ void voxel_finalize(hid_t dspace, hid_t dset, hid_t memspace); //! Read plot specifications from a plots.xml file void read_plots_xml(); +//! Read plot specifications from an XML Node +//! \param[in] XML node containing plot info +void read_plots_xml(pugi::xml_node root); + //! Clear memory void free_memory_plot(); diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 1e061b235..cd0ab477c 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -127,9 +127,12 @@ extern double weight_survive; //!< Survival weight after Russian roulette //============================================================================== //! Read settings from XML file -//! \param[in] root XML node for void read_settings_xml(); +//! Read settings from XML node +//! \param[in] root XML node for +void read_settings_xml(pugi::xml_node root); + void free_memory_settings(); } // namespace openmc diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h index 3cead91dc..56a51370a 100644 --- a/include/openmc/tallies/tally.h +++ b/include/openmc/tallies/tally.h @@ -48,10 +48,10 @@ public: void set_nuclides(const vector& nuclides); //! returns vector of indices corresponding to the tally this is called on - const vector& filters() const { return filters_; } + const vector& filters() const { return filters_; } //! \brief Returns the tally filter at index i - int32_t filters(int i) const { return filters_[i]; } + int32_t filters(int i) const { return filters_[i]; } void set_filters(gsl::span filters); @@ -178,6 +178,10 @@ extern double global_tally_leakage; //! Read tally specification from tallies.xml void read_tallies_xml(); +//! Read tally specification from an XML node +//! \param[in] root node of tallies XML element +void read_tallies_xml(pugi::xml_node root); + //! \brief Accumulate the sum of the contributions from each history within the //! batch to a new random variable void accumulate_tallies(); diff --git a/src/cross_sections.cpp b/src/cross_sections.cpp index afb0a1f36..2094fd551 100644 --- a/src/cross_sections.cpp +++ b/src/cross_sections.cpp @@ -91,8 +91,7 @@ Library::Library(pugi::xml_node node, const std::string& directory) // Non-member functions //============================================================================== -void read_cross_sections_xml() -{ +void read_cross_sections_xml() { pugi::xml_document doc; std::string filename = settings::path_input + "materials.xml"; // Check if materials.xml exists @@ -104,6 +103,11 @@ void read_cross_sections_xml() auto root = doc.document_element(); + read_cross_sections_xml(root); +} + +void read_cross_sections_xml(pugi::xml_node root) +{ // Find cross_sections.xml file -- the first place to look is the // materials.xml file. If no file is found there, then we check the // OPENMC_CROSS_SECTIONS environment variable diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 261471984..83e8494de 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -40,8 +40,7 @@ void update_universe_cell_count(int32_t a, int32_t b) } } -void read_geometry_xml() -{ +void read_geometry_xml() { // Display output message write_message("Reading geometry XML file...", 5); @@ -61,6 +60,11 @@ void read_geometry_xml() // Get root element pugi::xml_node root = doc.document_element(); + read_geometry_xml(root); +} + +void read_geometry_xml(pugi::xml_node root) +{ // Read surfaces, cells, lattice read_surfaces(root); read_cells(root); diff --git a/src/initialize.cpp b/src/initialize.cpp index aa353aa9c..44f84034a 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -14,6 +14,7 @@ #include "openmc/constants.h" #include "openmc/cross_sections.h" #include "openmc/error.h" +#include "openmc/file_utils.h" #include "openmc/geometry_aux.h" #include "openmc/hdf5_interface.h" #include "openmc/material.h" @@ -291,10 +292,53 @@ int parse_command_line(int argc, char* argv[]) void read_input_xml() { - read_settings_xml(); + + // search for a single model.xml file + // Check if settings.xml exists + std::string model_filename = settings::path_input + "model.xml"; + bool use_model_file = file_exists(model_filename); + pugi::xml_node model_root; + if (use_model_file) { + write_message("Found model.xml file."); + pugi::xml_document doc; + auto result = doc.load_file(model_filename.c_str()); + if (!result) { + fatal_error("Error processing model.xml file."); + } + auto model_root = doc.document_element(); + + auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; + for (const auto& input : other_inputs) { + if (file_exists(settings::path_input + input)) { + warning(fmt::format("A '{}' file is also present. This file will be ignored.", input)); + } + } + } else { + write_message("No model.xml found. Reading separate XML inputs..."); + } + if (use_model_file) { + if (!check_for_node(model_root, "settings")) { + fatal_error("No node present in the model.xml file."); + } + read_settings_xml(model_root.child("settings")); + } else { + read_settings_xml(); + } + read_cross_sections_xml(); - read_materials_xml(); - read_geometry_xml(); + if (use_model_file) { + if (!check_for_node(model_root, "materials")) { + fatal_error("No node present in the model.xml file."); + } + read_materials_xml(model_root.child("materials")); + if (!check_for_node(model_root, "geometry")) { + fatal_error("No node present in the model.xml_file."); + } + read_geometry_xml(model_root.child("geometry")); + } else { + read_materials_xml(); + read_geometry_xml(); + } // Final geometry setup and assign temperatures finalize_geometry(); @@ -302,14 +346,23 @@ void read_input_xml() // Finalize cross sections having assigned temperatures finalize_cross_sections(); - read_tallies_xml(); + if (use_model_file && check_for_node(model_root, "tallies")) { + read_tallies_xml(model_root.child("tallies")); + } else { + read_tallies_xml(); + } // Initialize distribcell_filters prepare_distribcell(); // Read the plots.xml regardless of plot mode in case plots are requested // via the API - read_plots_xml(); + if (use_model_file) { + if (check_for_node(model_root, "plots")) + read_plots_xml(model_root.child("plots")); + } else { + read_plots_xml(); + } if (settings::run_mode == RunMode::PLOTTING) { // Read plots.xml if it exists if (mpi::master && settings::verbosity >= 5) diff --git a/src/material.cpp b/src/material.cpp index 30dfa5ed5..f2e23aede 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -1264,8 +1264,7 @@ double density_effect(const vector& f, const vector& e_b_sq, return delta - w_sq * (1.0 - beta_sq); } -void read_materials_xml() -{ +void read_materials_xml() { write_message("Reading materials XML file...", 5); pugi::xml_document doc; @@ -1281,6 +1280,12 @@ void read_materials_xml() // Loop over XML material elements and populate the array. pugi::xml_node root = doc.document_element(); + + read_materials_xml(root); +} + +void read_materials_xml(pugi::xml_node root) +{ for (pugi::xml_node material_node : root.children("material")) { model::materials.push_back(make_unique(material_node)); } diff --git a/src/plot.cpp b/src/plot.cpp index b012ed131..e28543cdf 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -124,8 +124,7 @@ extern "C" int openmc_plot_geometry() return 0; } -void read_plots_xml() -{ +void read_plots_xml() { // Check if plots.xml exists; this is only necessary when the plot runmode is // initiated. Otherwise, we want to read plots.xml because it may be called // later via the API. In that case, its ok for a plots.xml to not exist @@ -141,6 +140,10 @@ void read_plots_xml() doc.load_file(filename.c_str()); pugi::xml_node root = doc.document_element(); +} + +void read_plots_xml(pugi::xml_node root) +{ for (auto node : root.children("plot")) { model::plots.emplace_back(node); model::plot_map[model::plots.back().id_] = model::plots.size() - 1; diff --git a/src/settings.cpp b/src/settings.cpp index eb0d4936c..710fb2810 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -211,13 +211,11 @@ void get_run_parameters(pugi::xml_node node_base) } } -void read_settings_xml() -{ +void read_settings_xml() { using namespace settings; using namespace pugi; - // Check if settings.xml exists - std::string filename = path_input + "settings.xml"; + std::string filename = settings::path_input + "settings.xml"; if (!file_exists(filename)) { if (run_mode != RunMode::PLOTTING) { fatal_error( @@ -245,6 +243,14 @@ void read_settings_xml() // Get root element xml_node root = doc.document_element(); + read_settings_xml(root); +} + +void read_settings_xml(pugi::xml_node root) +{ + using namespace settings; + using namespace pugi; + // Verbosity if (check_for_node(root, "verbosity")) { verbosity = std::stoi(get_node_value(root, "verbosity")); diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 51194684a..1c1f274d7 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -705,8 +705,7 @@ std::string Tally::nuclide_name(int nuclide_idx) const // Non-member functions //============================================================================== -void read_tallies_xml() -{ +void read_tallies_xml() { // Check if tallies.xml exists. If not, just return since it is optional std::string filename = settings::path_input + "tallies.xml"; if (!file_exists(filename)) @@ -719,6 +718,11 @@ void read_tallies_xml() doc.load_file(filename.c_str()); pugi::xml_node root = doc.document_element(); + read_tallies_xml(root); +} + +void read_tallies_xml(pugi::xml_node root) +{ // Check for setting if (check_for_node(root, "assume_separate")) { settings::assume_separate = get_node_value_bool(root, "assume_separate"); From cdd2a6b1cacb54387de050e96c36bca74c114777 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 20:43:29 -0500 Subject: [PATCH 1347/2654] Correcting doc scope and some reads --- src/initialize.cpp | 10 ++++++---- src/settings.cpp | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/initialize.cpp b/src/initialize.cpp index 44f84034a..cb35ebce9 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -298,14 +298,14 @@ void read_input_xml() std::string model_filename = settings::path_input + "model.xml"; bool use_model_file = file_exists(model_filename); pugi::xml_node model_root; + pugi::xml_document doc; if (use_model_file) { - write_message("Found model.xml file."); - pugi::xml_document doc; + write_message("Reading model.xml..."); auto result = doc.load_file(model_filename.c_str()); if (!result) { fatal_error("Error processing model.xml file."); } - auto model_root = doc.document_element(); + model_root = doc.document_element(); auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; for (const auto& input : other_inputs) { @@ -320,12 +320,14 @@ void read_input_xml() if (!check_for_node(model_root, "settings")) { fatal_error("No node present in the model.xml file."); } - read_settings_xml(model_root.child("settings")); + auto settings_root = model_root.child("settings"); + read_settings_xml(); } else { read_settings_xml(); } read_cross_sections_xml(); + if (use_model_file) { if (!check_for_node(model_root, "materials")) { fatal_error("No node present in the model.xml file."); diff --git a/src/settings.cpp b/src/settings.cpp index 710fb2810..de24e200a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -266,6 +266,7 @@ void read_settings_xml(pugi::xml_node root) // Find if a multi-group or continuous-energy simulation is desired if (check_for_node(root, "energy_mode")) { + std::cout << "Here" << std::endl; std::string temp_str = get_node_value(root, "energy_mode", true, true); if (temp_str == "mg" || temp_str == "multi-group") { run_CE = false; @@ -273,6 +274,7 @@ void read_settings_xml(pugi::xml_node root) run_CE = true; } } + std::cout << "Here" << std::endl; // Look for deprecated cross_sections.xml file in settings.xml if (check_for_node(root, "cross_sections")) { From bec9bf6f20805e12134e798aca98b90dd8e71d23 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 21:18:04 -0500 Subject: [PATCH 1348/2654] Refactoring model read into it's own function. --- include/openmc/initialize.h | 1 + src/initialize.cpp | 148 +++++++++++++++++++++++------------- src/settings.cpp | 19 +++-- 3 files changed, 106 insertions(+), 62 deletions(-) diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h index 869be4441..47474c986 100644 --- a/include/openmc/initialize.h +++ b/include/openmc/initialize.h @@ -11,6 +11,7 @@ int parse_command_line(int argc, char* argv[]); #ifdef OPENMC_MPI void initialize_mpi(MPI_Comm intracomm); #endif +bool read_model_xml(); void read_input_xml(); } // namespace openmc diff --git a/src/initialize.cpp b/src/initialize.cpp index cb35ebce9..254ad88da 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -290,81 +290,125 @@ int parse_command_line(int argc, char* argv[]) return 0; } -void read_input_xml() -{ - - // search for a single model.xml file - // Check if settings.xml exists +bool read_model_xml() { + // get verbosity from settings node std::string model_filename = settings::path_input + "model.xml"; bool use_model_file = file_exists(model_filename); - pugi::xml_node model_root; + if (!file_exists(model_filename)) return false; + + // attempt to open the document pugi::xml_document doc; - if (use_model_file) { - write_message("Reading model.xml..."); - auto result = doc.load_file(model_filename.c_str()); - if (!result) { - fatal_error("Error processing model.xml file."); - } - model_root = doc.document_element(); - - auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; - for (const auto& input : other_inputs) { - if (file_exists(settings::path_input + input)) { - warning(fmt::format("A '{}' file is also present. This file will be ignored.", input)); - } - } - } else { - write_message("No model.xml found. Reading separate XML inputs..."); + auto result = doc.load_file(model_filename.c_str()); + if (!result) { + fatal_error("Error processing model.xml file."); } - if (use_model_file) { - if (!check_for_node(model_root, "settings")) { + pugi::xml_node root = doc.document_element(); + + // Read settings + if (!check_for_node(root, "settings")) { fatal_error("No node present in the model.xml file."); - } - auto settings_root = model_root.child("settings"); - read_settings_xml(); - } else { - read_settings_xml(); + } + auto settings_root = root.child("settings"); + + // Verbosity + if (check_for_node(settings_root, "verbosity")) { + settings::verbosity = std::stoi(get_node_value(settings_root, "verbosity")); } - read_cross_sections_xml(); - - if (use_model_file) { - if (!check_for_node(model_root, "materials")) { - fatal_error("No node present in the model.xml file."); - } - read_materials_xml(model_root.child("materials")); - if (!check_for_node(model_root, "geometry")) { - fatal_error("No node present in the model.xml_file."); - } - read_geometry_xml(model_root.child("geometry")); - } else { - read_materials_xml(); - read_geometry_xml(); + // To this point, we haven't displayed any output since we didn't know what + // the verbosity is. Now that we checked for it, show the title if necessary + if (mpi::master) { + if (settings::verbosity >= 2) + title(); } + write_message("Reading model XML file...", 5); + + read_settings_xml(settings_root); + + // If other XML files are present, display warning + // that they will be ignored + auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; + for (const auto& input : other_inputs) { + if (file_exists(settings::path_input + input)) { + warning(("Other XML file input(s) are present. These file will be ignored in favor of the model.xml file.")); + break; + } + } + + // Read materials and cross sections + if (!check_for_node(root, "materials")) { + fatal_error("No node present in the model.xml file."); + } + auto materials_node = root.child("materials"); + read_cross_sections_xml(materials_node); + read_materials_xml(root.child("materials")); + + // Read geometry + if (!check_for_node(root, "geometry")) { + fatal_error("No node present in the model.xml_file."); + } + read_geometry_xml(root.child("geometry")); + // Final geometry setup and assign temperatures finalize_geometry(); // Finalize cross sections having assigned temperatures finalize_cross_sections(); - if (use_model_file && check_for_node(model_root, "tallies")) { - read_tallies_xml(model_root.child("tallies")); + if (check_for_node(root, "tallies")) + read_tallies_xml(root.child("tallies")); + + // Initialize distribcell_filters + prepare_distribcell(); + + if (check_for_node(root, "plots")) + read_plots_xml(root.child("plots")); + + if (settings::run_mode == RunMode::PLOTTING) { + // Read plots.xml if it exists + if (mpi::master && settings::verbosity >= 5) + print_plot(); + } else { - read_tallies_xml(); + // Write summary information + if (mpi::master && settings::output_summary) + write_summary(); + + // Warn if overlap checking is on + if (mpi::master && settings::check_overlaps) { + warning("Cell overlap checking is ON."); + } } + return true; +} + +void read_input_xml() +{ + // attempt to reach the model.xml file if present + if (read_model_xml()) return; + + read_settings_xml(); + read_cross_sections_xml(); + read_materials_xml(); + read_geometry_xml(); + + // Final geometry setup and assign temperatures + finalize_geometry(); + + // Finalize cross sections having assigned temperatures + finalize_cross_sections(); + + read_tallies_xml(); + // Initialize distribcell_filters prepare_distribcell(); // Read the plots.xml regardless of plot mode in case plots are requested // via the API - if (use_model_file) { - if (check_for_node(model_root, "plots")) - read_plots_xml(model_root.child("plots")); - } else { - read_plots_xml(); - } + read_plots_xml(); + if (settings::run_mode == RunMode::PLOTTING) { // Read plots.xml if it exists if (mpi::master && settings::verbosity >= 5) diff --git a/src/settings.cpp b/src/settings.cpp index de24e200a..3048862e3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -243,14 +243,6 @@ void read_settings_xml() { // Get root element xml_node root = doc.document_element(); - read_settings_xml(root); -} - -void read_settings_xml(pugi::xml_node root) -{ - using namespace settings; - using namespace pugi; - // Verbosity if (check_for_node(root, "verbosity")) { verbosity = std::stoi(get_node_value(root, "verbosity")); @@ -262,11 +254,19 @@ void read_settings_xml(pugi::xml_node root) if (verbosity >= 2) title(); } + write_message("Reading settings XML file...", 5); + read_settings_xml(root); +} + +void read_settings_xml(pugi::xml_node root) +{ + using namespace settings; + using namespace pugi; + // Find if a multi-group or continuous-energy simulation is desired if (check_for_node(root, "energy_mode")) { - std::cout << "Here" << std::endl; std::string temp_str = get_node_value(root, "energy_mode", true, true); if (temp_str == "mg" || temp_str == "multi-group") { run_CE = false; @@ -274,7 +274,6 @@ void read_settings_xml(pugi::xml_node root) run_CE = true; } } - std::cout << "Here" << std::endl; // Look for deprecated cross_sections.xml file in settings.xml if (check_for_node(root, "cross_sections")) { From 81aa653d506bf3e9f9288679c8e92a6f21b6ad46 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 21:22:41 -0500 Subject: [PATCH 1349/2654] Factoring out some common lines between reader functions --- include/openmc/initialize.h | 1 + src/initialize.cpp | 22 ++++++---------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h index 47474c986..d3d12d45d 100644 --- a/include/openmc/initialize.h +++ b/include/openmc/initialize.h @@ -13,6 +13,7 @@ void initialize_mpi(MPI_Comm intracomm); #endif bool read_model_xml(); void read_input_xml(); +void initial_output(); } // namespace openmc diff --git a/src/initialize.cpp b/src/initialize.cpp index 254ad88da..aa3e15efa 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -108,6 +108,9 @@ int openmc_init(int argc, char* argv[], const void* intracomm) // Read XML input files read_input_xml(); + // Write some initial output under the header if needed + initial_output(); + // Check for particle restart run if (settings::particle_restart_run) settings::run_mode = RunMode::PARTICLE; @@ -365,22 +368,6 @@ bool read_model_xml() { if (check_for_node(root, "plots")) read_plots_xml(root.child("plots")); - if (settings::run_mode == RunMode::PLOTTING) { - // Read plots.xml if it exists - if (mpi::master && settings::verbosity >= 5) - print_plot(); - - } else { - // Write summary information - if (mpi::master && settings::output_summary) - write_summary(); - - // Warn if overlap checking is on - if (mpi::master && settings::check_overlaps) { - warning("Cell overlap checking is ON."); - } - } - return true; } @@ -408,7 +395,10 @@ void read_input_xml() // Read the plots.xml regardless of plot mode in case plots are requested // via the API read_plots_xml(); +} +void initial_output() { + // handle some final output if (settings::run_mode == RunMode::PLOTTING) { // Read plots.xml if it exists if (mpi::master && settings::verbosity >= 5) From 9391f17cff9a798c048ec62b9eed3a9188baa534 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 22:29:36 -0500 Subject: [PATCH 1350/2654] Adding import for single or multiple XMLs --- openmc/geometry.py | 46 +++++++++++----- openmc/material.py | 40 ++++++++++---- openmc/model/model.py | 37 ++++++++++++- openmc/plots.py | 28 ++++++++-- openmc/settings.py | 119 ++++++++++++++++++++++++------------------ openmc/tallies.py | 72 +++++++++++++++---------- 6 files changed, 232 insertions(+), 110 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 889cb6b31..b4f8046bd 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -162,13 +162,13 @@ class Geometry: tree.write(str(p), xml_declaration=True, encoding='utf-8') @classmethod - def from_xml(cls, path='geometry.xml', materials=None): - """Generate geometry from XML file + def from_xml_element(cls, elem, materials=None): + """Generate geometry from an XML element Parameters ---------- - path : str, optional - Path to geometry XML file + elem : xml.etree.ElementTree.Element + XML element materials : openmc.Materials or None Materials used to assign to cells. If None, an attempt is made to generate it from the materials.xml file. @@ -187,13 +187,10 @@ class Geometry: universes[univ_id] = univ return universes[univ_id] - tree = ET.parse(path) - root = tree.getroot() - # Get surfaces surfaces = {} periodic = {} - for surface in root.findall('surface'): + for surface in elem.findall('surface'): s = openmc.Surface.from_xml_element(surface) surfaces[s.id] = s @@ -207,15 +204,15 @@ class Geometry: surfaces[s1].periodic_surface = surfaces[s2] # Add any DAGMC universes - for elem in root.findall('dagmc_universe'): + for elem in elem.findall('dagmc_universe'): dag_univ = openmc.DAGMCUniverse.from_xml_element(elem) universes[dag_univ.id] = dag_univ # Dictionary that maps each universe to a list of cells/lattices that - # contain it (needed to determine which universe is the root) + # contain it (needed to determine which universe is the elem) child_of = defaultdict(list) - for elem in root.findall('lattice'): + for elem in elem.findall('lattice'): lat = openmc.RectLattice.from_xml_element(elem, get_universe) universes[lat.id] = lat if lat.outer is not None: @@ -223,7 +220,7 @@ class Geometry: for u in lat.universes.ravel(): child_of[u].append(lat) - for elem in root.findall('hex_lattice'): + for elem in elem.findall('hex_lattice'): lat = openmc.HexLattice.from_xml_element(elem, get_universe) universes[lat.id] = lat if lat.outer is not None: @@ -245,7 +242,7 @@ class Geometry: mats = {str(m.id): m for m in materials} mats['void'] = None - for elem in root.findall('cell'): + for elem in elem.findall('cell'): c = openmc.Cell.from_xml_element(elem, surfaces, mats, get_universe) if c.fill_type in ('universe', 'lattice'): child_of[c.fill].append(c) @@ -258,6 +255,29 @@ class Geometry: else: raise ValueError('Error determining root universe.') + @classmethod + def from_xml(cls, path='geometry.xml', materials=None): + """Generate geometry from XML file + + Parameters + ---------- + path : str, optional + Path to geometry XML file + materials : openmc.Materials or None + Materials used to assign to cells. If None, an attempt is made to + generate it from the materials.xml file. + + Returns + ------- + openmc.Geometry + Geometry object + + """ + tree = ET.parse(path) + root = tree.getroot() + + return cls.from_xml_element(root, materials) + def find(self, point): """Find cells/universes/lattices which contain a given point diff --git a/openmc/material.py b/openmc/material.py index 9e3951ccf..c33596800 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1508,6 +1508,34 @@ class Materials(cv.CheckedList): errors='xmlcharrefreplace') as fh: self._write_xml(fh) + @classmethod + def from_xml_element(cls, elem): + """Generate materials collection from XML file + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + XML element + + Returns + ------- + openmc.Materials + Materials collection + + """ + # Generate each material + materials = cls() + for material in elem.findall('material'): + materials.append(Material.from_xml_element(material)) + + # Check for cross sections settings + xs = elem.find('cross_sections') + if xs is not None: + materials.cross_sections = xs.text + + return materials + + @classmethod def from_xml(cls, path: PathLike = 'materials.xml'): """Generate materials collection from XML file @@ -1526,14 +1554,4 @@ class Materials(cv.CheckedList): tree = ET.parse(path) root = tree.getroot() - # Generate each material - materials = cls() - for material in root.findall('material'): - materials.append(Material.from_xml_element(material)) - - # Check for cross sections settings - xs = tree.find('cross_sections') - if xs is not None: - materials.cross_sections = xs.text - - return materials + return cls.from_xml_element(root) \ No newline at end of file diff --git a/openmc/model/model.py b/openmc/model/model.py index e3c4c4ae1..2193084c3 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -208,7 +208,42 @@ class Model: self._plots.append(plot) @classmethod - def from_xml(cls, geometry='geometry.xml', materials='materials.xml', + def from_xml(cls, separate_xmls=True, **kwargs): + if separate_xmls: + return cls.from_separate_xmls(**kwargs) + else: + return cls.from_model_xml(**kwargs) + + @classmethod + def from_model_xml(cls, path='model.xml'): + """Create model from single XML file + + Parameters + ---------- + path : str or Pathlike + Path to model.xml file + """ + tree = ET.parse(path) + root = tree.getroot() + + model = cls() + + model.settings = openmc.Settings.from_xml_element(root.find('settings')) + model.materials = openmc.Materials.from_xml_element(root.find('materials')) + model.geometry = \ + openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) + + if tally_node := root.find('tallies'): + print(tally_node) + model.tallies = openmc.Tallies.from_xml_element(tally_node) + + if plots_node := root.find('plots'): + model.plots = openmc.Plots.from_xml_element(plots_node) + + return model + + @classmethod + def from_separate_xmls(cls, geometry='geometry.xml', materials='materials.xml', settings='settings.xml', tallies='tallies.xml', plots='plots.xml'): """Create model from existing XML files diff --git a/openmc/plots.py b/openmc/plots.py index 52dcf3fc1..badea2e58 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -941,6 +941,27 @@ class Plots(cv.CheckedList): tree = ET.ElementTree(self._plots_file) tree.write(str(p), xml_declaration=True, encoding='utf-8') + @classmethod + def from_xml_element(cls, elem): + """Generate plots collection from XML file + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + XML element + + Returns + ------- + openmc.Plots + Plots collection + + """ + # Generate each plot + plots = cls() + for elem in elem.findall('plot'): + plots.append(Plot.from_xml_element(elem)) + return plots + @classmethod def from_xml(cls, path='plots.xml'): """Generate plots collection from XML file @@ -958,9 +979,6 @@ class Plots(cv.CheckedList): """ tree = ET.parse(path) root = tree.getroot() + return cls.from_xml_element(root) + - # Generate each plot - plots = cls() - for elem in root.findall('plot'): - plots.append(Plot.from_xml_element(elem)) - return plots diff --git a/openmc/settings.py b/openmc/settings.py index dd0041351..c2fca98f7 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1595,7 +1595,7 @@ class Settings: clean_indentation(element) return element - + def export_to_xml(self, path: PathLike = 'settings.xml'): """Export simulation settings to an XML file. @@ -1617,6 +1617,71 @@ class Settings: tree = ET.ElementTree(root_element) tree.write(str(p), xml_declaration=True, encoding='utf-8') + @classmethod + def from_xml_element(cls, elem): + """Generate settings from XML element + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + XML element + + Returns + ------- + openmc.Settings + Settings object + + """ + settings = cls() + settings._eigenvalue_from_xml_element(elem) + settings._run_mode_from_xml_element(elem) + settings._particles_from_xml_element(elem) + settings._batches_from_xml_element(elem) + settings._inactive_from_xml_element(elem) + settings._max_lost_particles_from_xml_element(elem) + settings._rel_max_lost_particles_from_xml_element(elem) + settings._generations_per_batch_from_xml_element(elem) + settings._keff_trigger_from_xml_element(elem) + settings._source_from_xml_element(elem) + settings._volume_calcs_from_xml_element(elem) + settings._output_from_xml_element(elem) + settings._statepoint_from_xml_element(elem) + settings._sourcepoint_from_xml_element(elem) + settings._surf_source_read_from_xml_element(elem) + settings._surf_source_write_from_xml_element(elem) + settings._confidence_intervals_from_xml_element(elem) + settings._electron_treatment_from_xml_element(elem) + settings._energy_mode_from_xml_element(elem) + settings._max_order_from_xml_element(elem) + settings._photon_transport_from_xml_element(elem) + settings._ptables_from_xml_element(elem) + settings._seed_from_xml_element(elem) + settings._survival_biasing_from_xml_element(elem) + settings._cutoff_from_xml_element(elem) + settings._entropy_mesh_from_xml_element(elem) + settings._trigger_from_xml_element(elem) + settings._no_reduce_from_xml_element(elem) + settings._verbosity_from_xml_element(elem) + settings._tabular_legendre_from_xml_element(elem) + settings._temperature_from_xml_element(elem) + settings._trace_from_xml_element(elem) + settings._track_from_xml_element(elem) + settings._ufs_mesh_from_xml_element(elem) + settings._resonance_scattering_from_xml_element(elem) + settings._create_fission_neutrons_from_xml_element(elem) + settings._delayed_photon_scaling_from_xml_element(elem) + settings._event_based_from_xml_element(elem) + settings._max_particles_in_flight_from_xml_element(elem) + settings._material_cell_offsets_from_xml_element(elem) + settings._log_grid_bins_from_xml_element(elem) + settings._write_initial_source_from_xml_element(elem) + settings._weight_windows_from_xml_element(elem) + settings._max_splits_from_xml_element(elem) + settings._max_tracks_from_xml_element(elem) + + # TODO: Get volume calculations + return settings + @classmethod def from_xml(cls, path: PathLike = 'settings.xml'): """Generate settings from XML file @@ -1636,54 +1701,4 @@ class Settings: """ tree = ET.parse(path) root = tree.getroot() - - settings = cls() - settings._eigenvalue_from_xml_element(root) - settings._run_mode_from_xml_element(root) - settings._particles_from_xml_element(root) - settings._batches_from_xml_element(root) - settings._inactive_from_xml_element(root) - settings._max_lost_particles_from_xml_element(root) - settings._rel_max_lost_particles_from_xml_element(root) - settings._generations_per_batch_from_xml_element(root) - settings._keff_trigger_from_xml_element(root) - settings._source_from_xml_element(root) - settings._volume_calcs_from_xml_element(root) - settings._output_from_xml_element(root) - settings._statepoint_from_xml_element(root) - settings._sourcepoint_from_xml_element(root) - settings._surf_source_read_from_xml_element(root) - settings._surf_source_write_from_xml_element(root) - settings._confidence_intervals_from_xml_element(root) - settings._electron_treatment_from_xml_element(root) - settings._energy_mode_from_xml_element(root) - settings._max_order_from_xml_element(root) - settings._photon_transport_from_xml_element(root) - settings._ptables_from_xml_element(root) - settings._seed_from_xml_element(root) - settings._survival_biasing_from_xml_element(root) - settings._cutoff_from_xml_element(root) - settings._entropy_mesh_from_xml_element(root) - settings._trigger_from_xml_element(root) - settings._no_reduce_from_xml_element(root) - settings._verbosity_from_xml_element(root) - settings._tabular_legendre_from_xml_element(root) - settings._temperature_from_xml_element(root) - settings._trace_from_xml_element(root) - settings._track_from_xml_element(root) - settings._ufs_mesh_from_xml_element(root) - settings._resonance_scattering_from_xml_element(root) - settings._create_fission_neutrons_from_xml_element(root) - settings._delayed_photon_scaling_from_xml_element(root) - settings._event_based_from_xml_element(root) - settings._max_particles_in_flight_from_xml_element(root) - settings._material_cell_offsets_from_xml_element(root) - settings._log_grid_bins_from_xml_element(root) - settings._write_initial_source_from_xml_element(root) - settings._weight_windows_from_xml_element(root) - settings._max_splits_from_xml_element(root) - settings._max_tracks_from_xml_element(root) - - # TODO: Get volume calculations - - return settings + return cls.from_xml_element(root) diff --git a/openmc/tallies.py b/openmc/tallies.py index dfb0c98bf..0355568ec 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3191,6 +3191,49 @@ class Tallies(cv.CheckedList): tree = ET.ElementTree(root_element) tree.write(str(p), xml_declaration=True, encoding='utf-8') + @classmethod + def from_xml_element(cls, elem): + """Generate tallies from an XML element + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + XML element + + Returns + ------- + openmc.Tallies + Tallies object + + """ + # Read mesh elements + meshes = {} + for elem in elem.findall('mesh'): + mesh = MeshBase.from_xml_element(elem) + meshes[mesh.id] = mesh + + # Read filter elements + filters = {} + for elem in elem.findall('filter'): + filter = openmc.Filter.from_xml_element(elem, meshes=meshes) + filters[filter.id] = filter + + # Read derivative elements + derivatives = {} + for elem in elem.findall('derivative'): + deriv = openmc.TallyDerivative.from_xml_element(elem) + derivatives[deriv.id] = deriv + + # Read tally elements + tallies = [] + for elem in elem.findall('tally'): + tally = openmc.Tally.from_xml_element( + elem, filters=filters, derivatives=derivatives + ) + tallies.append(tally) + + return cls(tallies) + @classmethod def from_xml(cls, path='tallies.xml'): """Generate tallies from XML file @@ -3208,31 +3251,4 @@ class Tallies(cv.CheckedList): """ tree = ET.parse(path) root = tree.getroot() - - # Read mesh elements - meshes = {} - for elem in root.findall('mesh'): - mesh = MeshBase.from_xml_element(elem) - meshes[mesh.id] = mesh - - # Read filter elements - filters = {} - for elem in root.findall('filter'): - filter = openmc.Filter.from_xml_element(elem, meshes=meshes) - filters[filter.id] = filter - - # Read derivative elements - derivatives = {} - for elem in root.findall('derivative'): - deriv = openmc.TallyDerivative.from_xml_element(elem) - derivatives[deriv.id] = deriv - - # Read tally elements - tallies = [] - for elem in root.findall('tally'): - tally = openmc.Tally.from_xml_element( - elem, filters=filters, derivatives=derivatives - ) - tallies.append(tally) - - return cls(tallies) + return cls.from_xml_element(root) From af6b0af1e3ab2fc84224a12e55928cc0030a27d4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 22:41:28 -0500 Subject: [PATCH 1351/2654] Fix loop variable overwrite --- openmc/tallies.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 0355568ec..2996f1b03 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3208,27 +3208,27 @@ class Tallies(cv.CheckedList): """ # Read mesh elements meshes = {} - for elem in elem.findall('mesh'): - mesh = MeshBase.from_xml_element(elem) + for e in elem.findall('mesh'): + mesh = MeshBase.from_xml_element(e) meshes[mesh.id] = mesh # Read filter elements filters = {} - for elem in elem.findall('filter'): - filter = openmc.Filter.from_xml_element(elem, meshes=meshes) + for e in elem.findall('filter'): + filter = openmc.Filter.from_xml_element(e, meshes=meshes) filters[filter.id] = filter # Read derivative elements derivatives = {} - for elem in elem.findall('derivative'): - deriv = openmc.TallyDerivative.from_xml_element(elem) + for e in elem.findall('derivative'): + deriv = openmc.TallyDerivative.from_xml_element(e) derivatives[deriv.id] = deriv # Read tally elements tallies = [] - for elem in elem.findall('tally'): + for e in elem.findall('tally'): tally = openmc.Tally.from_xml_element( - elem, filters=filters, derivatives=derivatives + e, filters=filters, derivatives=derivatives ) tallies.append(tally) From 5ac6e87a68c0666ef41ef1c6d9b60aa19500b1a5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 23:15:14 -0500 Subject: [PATCH 1352/2654] Properly call read_plots_xml --- src/plot.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plot.cpp b/src/plot.cpp index e28543cdf..1a62fe263 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -140,6 +140,8 @@ void read_plots_xml() { doc.load_file(filename.c_str()); pugi::xml_node root = doc.document_element(); + + read_plots_xml(root); } void read_plots_xml(pugi::xml_node root) From 2e716589a14d2465ab4a494e12ddf86172af72e3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 3 Nov 2022 23:57:22 -0500 Subject: [PATCH 1353/2654] Other bug fixes --- openmc/geometry.py | 32 ++++++++++++++++---------------- openmc/model/model.py | 6 +++--- openmc/plots.py | 7 ++++--- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index b4f8046bd..d036df9c7 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -204,24 +204,24 @@ class Geometry: surfaces[s1].periodic_surface = surfaces[s2] # Add any DAGMC universes - for elem in elem.findall('dagmc_universe'): - dag_univ = openmc.DAGMCUniverse.from_xml_element(elem) + for e in elem.findall('dagmc_universe'): + dag_univ = openmc.DAGMCUniverse.from_xml_element(e) universes[dag_univ.id] = dag_univ # Dictionary that maps each universe to a list of cells/lattices that # contain it (needed to determine which universe is the elem) child_of = defaultdict(list) - for elem in elem.findall('lattice'): - lat = openmc.RectLattice.from_xml_element(elem, get_universe) + for e in elem.findall('lattice'): + lat = openmc.RectLattice.from_xml_element(e, get_universe) universes[lat.id] = lat if lat.outer is not None: child_of[lat.outer].append(lat) for u in lat.universes.ravel(): child_of[u].append(lat) - for elem in elem.findall('hex_lattice'): - lat = openmc.HexLattice.from_xml_element(elem, get_universe) + for e in elem.findall('hex_lattice'): + lat = openmc.HexLattice.from_xml_element(e, get_universe) universes[lat.id] = lat if lat.outer is not None: child_of[lat.outer].append(lat) @@ -235,15 +235,8 @@ class Geometry: for u in ring: child_of[u].append(lat) - # Create dictionary to easily look up materials - if materials is None: - filename = Path(path).parent / 'materials.xml' - materials = openmc.Materials.from_xml(str(filename)) - mats = {str(m.id): m for m in materials} - mats['void'] = None - - for elem in elem.findall('cell'): - c = openmc.Cell.from_xml_element(elem, surfaces, mats, get_universe) + for e in elem.findall('cell'): + c = openmc.Cell.from_xml_element(e, surfaces, materials, get_universe) if c.fill_type in ('universe', 'lattice'): child_of[c.fill].append(c) @@ -276,7 +269,14 @@ class Geometry: tree = ET.parse(path) root = tree.getroot() - return cls.from_xml_element(root, materials) + # Create dictionary to easily look up materials + if materials is None: + filename = Path(path).parent / 'materials.xml' + materials = openmc.Materials.from_xml(str(filename)) + mats = {str(m.id): m for m in materials} + mats['void'] = None + + return cls.from_xml_element(root, mats) def find(self, point): """Find cells/universes/lattices which contain a given point diff --git a/openmc/model/model.py b/openmc/model/model.py index 2193084c3..a839dc8f0 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -208,11 +208,11 @@ class Model: self._plots.append(plot) @classmethod - def from_xml(cls, separate_xmls=True, **kwargs): + def from_xml(cls, *args, separate_xmls=True, **kwargs): if separate_xmls: - return cls.from_separate_xmls(**kwargs) + return cls.from_separate_xmls(*args, **kwargs) else: - return cls.from_model_xml(**kwargs) + return cls.from_model_xml(*args, **kwargs) @classmethod def from_model_xml(cls, path='model.xml'): diff --git a/openmc/plots.py b/openmc/plots.py index badea2e58..b1f192787 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -919,6 +919,7 @@ class Plots(cv.CheckedList): # Clean the indentation in the file to be user-readable clean_indentation(self._plots_file) + reorder_attributes(self._plots_file) # TODO: Remove when support is Python 3.8+ return self._plots_file @@ -936,8 +937,8 @@ class Plots(cv.CheckedList): if p.is_dir(): p /= 'plots.xml' + self.to_xml_element() # Write the XML Tree to the plots.xml file - reorder_attributes(self._plots_file) # TODO: Remove when support is Python 3.8+ tree = ET.ElementTree(self._plots_file) tree.write(str(p), xml_declaration=True, encoding='utf-8') @@ -958,8 +959,8 @@ class Plots(cv.CheckedList): """ # Generate each plot plots = cls() - for elem in elem.findall('plot'): - plots.append(Plot.from_xml_element(elem)) + for e in elem.findall('plot'): + plots.append(Plot.from_xml_element(e)) return plots @classmethod From b4dcc30f92c4b8ff29b77505cdf654fa7eff7181 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Nov 2022 00:58:43 -0500 Subject: [PATCH 1354/2654] Removing walrus operator --- openmc/model/model.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index a839dc8f0..bc8f0b531 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -233,12 +233,11 @@ class Model: model.geometry = \ openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) - if tally_node := root.find('tallies'): - print(tally_node) - model.tallies = openmc.Tallies.from_xml_element(tally_node) + if root.find('tallies'): + model.tallies = openmc.Tallies.from_xml_element(root.find('tallies')) - if plots_node := root.find('plots'): - model.plots = openmc.Plots.from_xml_element(plots_node) + if root.find('plots'): + model.plots = openmc.Plots.from_xml_element(root.find('plots')) return model From 611475a835be98beee0082727e94660b3fcd3000 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Nov 2022 22:43:25 -0500 Subject: [PATCH 1355/2654] Restructureing input function calls a little --- src/initialize.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/initialize.cpp b/src/initialize.cpp index aa3e15efa..3f6e69ecd 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -106,7 +106,7 @@ int openmc_init(int argc, char* argv[], const void* intracomm) openmc::openmc_set_seed(DEFAULT_SEED); // Read XML input files - read_input_xml(); + if (!read_model_xml()) read_input_xml(); // Write some initial output under the header if needed initial_output(); @@ -373,9 +373,6 @@ bool read_model_xml() { void read_input_xml() { - // attempt to reach the model.xml file if present - if (read_model_xml()) return; - read_settings_xml(); read_cross_sections_xml(); read_materials_xml(); From 021bb280c9b4cad713ecdd516c9ef8b9ee97bd2c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Nov 2022 22:45:37 -0500 Subject: [PATCH 1356/2654] Adding initial test for exporting model.xmls. Correcting material maps --- openmc/model/model.py | 3 ++- tests/unit_tests/test_model.py | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index bc8f0b531..6950642e0 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -230,8 +230,9 @@ class Model: model.settings = openmc.Settings.from_xml_element(root.find('settings')) model.materials = openmc.Materials.from_xml_element(root.find('materials')) + materials = {str(m.id): m for m in model.materials} model.geometry = \ - openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) + openmc.Geometry.from_xml_element(root.find('geometry'), materials) if root.find('tallies'): model.tallies = openmc.Tallies.from_xml_element(root.find('tallies')) diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 9b05ed2a5..ce81b00ee 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -7,6 +7,8 @@ import pytest import openmc import openmc.lib +from .. import cdtemp + @pytest.fixture(scope='function') def pin_model_attributes(): @@ -529,3 +531,22 @@ def test_calc_volumes(run_in_tmpdir, pin_model_attributes, mpi_intracomm): assert openmc.lib.materials[3].volume == mats[2].volume test_model.finalize_lib() + +def test_model_xml(): + + with cdtemp(): + # load a model from examples + pwr_model = openmc.examples.pwr_core() + + # export to separate XMLs manually + pwr_model.settings.export_to_xml('settings_ref.xml') + pwr_model.materials.export_to_xml('materials_ref.xml') + pwr_model.geometry.export_to_xml('geometry_ref.xml') + + # now write and read a model.xml file + pwr_model.export_to_xml(separate_xmls=False) + new_model = openmc.Model.from_xml(separate_xmls=False) + + # make sure we can also export this again to separate + # XML files + new_model.export_to_xml(separate_xmls=True) \ No newline at end of file From abd3d515b0906363ce1975ffadd983c6c5a86f2b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 4 Nov 2022 22:46:11 -0500 Subject: [PATCH 1357/2654] Correcting doc strings for material mapping sent to --- openmc/cell.py | 2 +- openmc/geometry.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 0cea73b32..d03052623 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -650,7 +650,7 @@ class Cell(IDManagerMixin): surfaces : dict Dictionary mapping surface IDs to :class:`openmc.Surface` instances materials : dict - Dictionary mapping material IDs to :class:`openmc.Material` + Dictionary mapping material ID strings to :class:`openmc.Material` instances (defined in :math:`openmc.Geometry.from_xml`) get_universe : function Function returning universe (defined in diff --git a/openmc/geometry.py b/openmc/geometry.py index d036df9c7..57aab1884 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -256,9 +256,9 @@ class Geometry: ---------- path : str, optional Path to geometry XML file - materials : openmc.Materials or None - Materials used to assign to cells. If None, an attempt is made to - generate it from the materials.xml file. + materials : dict + Dictionary mapping material ID strings to :class:`openmc.Material` + instances (defined in :math:`openmc.Geometry.from_xml`) Returns ------- From 662d83a7dd72240b4da8594319bab416977ec71b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 9 Nov 2022 23:29:17 -0600 Subject: [PATCH 1358/2654] Running some existing regression tests using single XML file --- .../adj_cell_rotation/__init__.py | 2 + .../regression_tests/energy_laws/__init__.py | 1 + .../lattice_multiple/__init__.py | 1 + tests/regression_tests/model_xml/__init__.py | 0 .../model_xml/inputs_true.dat | 38 ++++++++++ tests/regression_tests/model_xml/test.py | 76 +++++++++++++++++++ .../photon_production/__init__.py | 1 + 7 files changed, 119 insertions(+) create mode 100644 tests/regression_tests/model_xml/__init__.py create mode 100644 tests/regression_tests/model_xml/inputs_true.dat create mode 100644 tests/regression_tests/model_xml/test.py diff --git a/tests/regression_tests/adj_cell_rotation/__init__.py b/tests/regression_tests/adj_cell_rotation/__init__.py index e69de29bb..7efe44865 100644 --- a/tests/regression_tests/adj_cell_rotation/__init__.py +++ b/tests/regression_tests/adj_cell_rotation/__init__.py @@ -0,0 +1,2 @@ + +from .test import model \ No newline at end of file diff --git a/tests/regression_tests/energy_laws/__init__.py b/tests/regression_tests/energy_laws/__init__.py index e69de29bb..29fbfcc0c 100644 --- a/tests/regression_tests/energy_laws/__init__.py +++ b/tests/regression_tests/energy_laws/__init__.py @@ -0,0 +1 @@ +from .test import model \ No newline at end of file diff --git a/tests/regression_tests/lattice_multiple/__init__.py b/tests/regression_tests/lattice_multiple/__init__.py index e69de29bb..29fbfcc0c 100644 --- a/tests/regression_tests/lattice_multiple/__init__.py +++ b/tests/regression_tests/lattice_multiple/__init__.py @@ -0,0 +1 @@ +from .test import model \ No newline at end of file diff --git a/tests/regression_tests/model_xml/__init__.py b/tests/regression_tests/model_xml/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/model_xml/inputs_true.dat b/tests/regression_tests/model_xml/inputs_true.dat new file mode 100644 index 000000000..5aedbfa14 --- /dev/null +++ b/tests/regression_tests/model_xml/inputs_true.dat @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 10000 + 10 + 5 + + + -4.0 -4.0 -4.0 4.0 4.0 4.0 + + + + diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py new file mode 100644 index 000000000..448079b3f --- /dev/null +++ b/tests/regression_tests/model_xml/test.py @@ -0,0 +1,76 @@ +from difflib import unified_diff +import filecmp +import os + +import openmc +import pytest + +from tests.testing_harness import PyAPITestHarness, colorize + +# use a few models from other tests to make sure the same results are +# produced when using a single model.xml file as input +from ..adj_cell_rotation import model as adj_cell_rotation_model +from ..lattice_multiple import model as lattice_mult_model +from ..energy_laws import model as energy_laws_model +from ..photon_production import model as photon_prod_model + + +class ModelXMLTestHarness(PyAPITestHarness): + """Accept a results file to check against and assume inputs_true is the contents of a model.xml file. + """ + def __init__(self, model=None, inputs_true=None, results_true=None): + statepoint_name = f'statepoint.{model.settings.batches}.h5' + super().__init__(statepoint_name, model, inputs_true) + + self.results_true = 'results_true.dat' if results_true is None else results_true + + def _build_inputs(self): + self._model.export_to_xml(separate_xmls=False) + + def _get_inputs(self): + return open('model.xml').read() + + def _compare_inputs(self): + """Skip input comparisons for now + """ + pass + + def _compare_results(self): + """Make sure the current results agree with the reference.""" + compare = filecmp.cmp('results_test.dat', self.results_true) + if not compare: + expected = open(self.results_true).readlines() + actual = open('results_test.dat').readlines() + diff = unified_diff(expected, actual, self.results_true, + 'results_test.dat') + print('Result differences:') + print(''.join(colorize(diff))) + os.rename('results_test.dat', 'results_error.dat') + assert compare, 'Results do not agree' + + def _cleanup(self): + super()._cleanup() + if os.path.exists('model.xml'): + os.remove('model.xml') + + +models = [ +'adj_cell_rotation_model', +'lattice_mult_model', +'energy_laws_model', +'photon_prod_model' +] +paths = [ +'../adj_cell_rotation', +'../lattice_multiple', +'../energy_laws', +'../photon_production' +] + + +@pytest.mark.parametrize("model, path", zip(models, paths)) +def test_model_xml(model, path, request): + inputs = path + "/inputs_true.dat" + results = path + "/results_true.dat" + harness = ModelXMLTestHarness(request.getfixturevalue(model), inputs, results) + harness.main() \ No newline at end of file diff --git a/tests/regression_tests/photon_production/__init__.py b/tests/regression_tests/photon_production/__init__.py index e69de29bb..29fbfcc0c 100644 --- a/tests/regression_tests/photon_production/__init__.py +++ b/tests/regression_tests/photon_production/__init__.py @@ -0,0 +1 @@ +from .test import model \ No newline at end of file From 1e7dbe99cf7d6c262a9900930836f5786f519f9a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 10 Nov 2022 00:01:40 -0600 Subject: [PATCH 1359/2654] Making sure meshes are only written once to a model.xml file --- openmc/model/model.py | 18 ++++++++++++------ openmc/settings.py | 15 ++++++++++----- openmc/tallies.py | 24 ++++++++++++------------ 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 6950642e0..cb84f2c17 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -5,11 +5,8 @@ import os from pathlib import Path from numbers import Integral from tempfile import NamedTemporaryFile -<<<<<<< HEAD import warnings -======= from xml.etree import ElementTree as ET ->>>>>>> d42935a08 (Writing all main nodes to a single XML file) import h5py @@ -234,8 +231,16 @@ class Model: model.geometry = \ openmc.Geometry.from_xml_element(root.find('geometry'), materials) + # gather meshses from other classes before reading the tally node + meshes = {} + if model.settings.entropy_mesh is not None: + meshes[model.settings.entropy_mesh.id] = model.settings.entropy_mesh + + for ww in model.settings.weight_windows: + meshes[ww.mesh.id] = ww.mesh + if root.find('tallies'): - model.tallies = openmc.Tallies.from_xml_element(root.find('tallies')) + model.tallies = openmc.Tallies.from_xml_element(root.find('tallies'), meshes) if root.find('plots'): model.plots = openmc.Plots.from_xml_element(root.find('plots')) @@ -524,7 +529,8 @@ class Model: # Can be used to modify tallies in case any surfaces are redundant redundant_surfaces = self.geometry.remove_redundant_surfaces() - settings_element = self.settings.to_xml_element() + memo = set() + settings_element = self.settings.to_xml_element(memo) geometry_element = self.geometry.to_xml_element() # If a materials collection was specified, export it. Otherwise, look @@ -549,7 +555,7 @@ class Model: ET.ElementTree(settings_element).write(fh, encoding='unicode') if self.tallies: - tallies_element = self.tallies.to_xml_element() + tallies_element = self.tallies.to_xml_element(memo) ET.ElementTree(tallies_element).write(fh, encoding='unicode') if self.plots: plots_element = self.plots.to_xml_element() diff --git a/openmc/settings.py b/openmc/settings.py index c2fca98f7..74ec0d54a 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1073,7 +1073,7 @@ class Settings: subelement = ET.SubElement(element, key) subelement.text = str(value) - def _create_entropy_mesh_subelement(self, root): + def _create_entropy_mesh_subelement(self, root, memo=None): if self.entropy_mesh is not None: # use default heuristic for entropy mesh if not set by user if self.entropy_mesh.dimension is None: @@ -1207,15 +1207,20 @@ class Settings: elem = ET.SubElement(root, "write_initial_source") elem.text = str(self._write_initial_source).lower() - def _create_weight_windows_subelement(self, root): + def _create_weight_windows_subelement(self, root, memo=None): for ww in self._weight_windows: # Add weight window information root.append(ww.to_xml_element()) + # check the memo for a mesh + if memo and ww.mesh.id in memo: + continue + # See if a element already exists -- if not, add it path = f"./mesh[@id='{ww.mesh.id}']" if root.find(path) is None: root.append(ww.mesh.to_xml_element()) + if memo is not None: memo.add(ww.mesh.id) if self._weight_windows_on is not None: elem = ET.SubElement(root, "weight_windows_on") @@ -1539,7 +1544,7 @@ class Settings: if text is not None: self.max_tracks = int(text) - def to_xml_element(self): + def to_xml_element(self, memo=None): """Create a 'settings' element to be written to an XML file. """ @@ -1569,7 +1574,7 @@ class Settings: self._create_seed_subelement(element) self._create_survival_biasing_subelement(element) self._create_cutoff_subelement(element) - self._create_entropy_mesh_subelement(element) + self._create_entropy_mesh_subelement(element, memo) self._create_trigger_subelement(element) self._create_no_reduce_subelement(element) self._create_verbosity_subelement(element) @@ -1587,7 +1592,7 @@ class Settings: self._create_material_cell_offsets_subelement(element) self._create_log_grid_bins_subelement(element) self._create_write_initial_source_subelement(element) - self._create_weight_windows_subelement(element) + self._create_weight_windows_subelement(element, memo) self._create_max_splits_subelement(element) self._create_max_tracks_subelement(element) diff --git a/openmc/tallies.py b/openmc/tallies.py index 2996f1b03..e37f04e25 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3119,17 +3119,17 @@ class Tallies(cv.CheckedList): for tally in self: root_element.append(tally.to_xml_element()) - def _create_mesh_subelements(self, root_element): - already_written = set() + def _create_mesh_subelements(self, root_element, memo=None): + already_written = memo if memo else set() for tally in self: for f in tally.filters: if isinstance(f, openmc.MeshFilter): - if f.mesh.id not in already_written: - if len(f.mesh.name) > 0: - root_element.append(ET.Comment(f.mesh.name)) - - root_element.append(f.mesh.to_xml_element()) - already_written.add(f.mesh.id) + if f.mesh.id in already_written: + continue + if len(f.mesh.name) > 0: + root_element.append(ET.Comment(f.mesh.name)) + root_element.append(f.mesh.to_xml_element()) + already_written.add(f.mesh.id) def _create_filter_subelements(self, root_element): already_written = dict() @@ -3155,11 +3155,11 @@ class Tallies(cv.CheckedList): for d in derivs: root_element.append(d.to_xml_element()) - def to_xml_element(self): + def to_xml_element(self, memo=None): """Creates a 'tallies' element to be written to an XML file. """ element = ET.Element("tallies") - self._create_mesh_subelements(element) + self._create_mesh_subelements(element, memo) self._create_filter_subelements(element) self._create_tally_subelements(element) self._create_derivative_subelements(element) @@ -3192,7 +3192,7 @@ class Tallies(cv.CheckedList): tree.write(str(p), xml_declaration=True, encoding='utf-8') @classmethod - def from_xml_element(cls, elem): + def from_xml_element(cls, elem, meshes=None): """Generate tallies from an XML element Parameters @@ -3207,7 +3207,7 @@ class Tallies(cv.CheckedList): """ # Read mesh elements - meshes = {} + meshes = {} if meshes is None else meshes for e in elem.findall('mesh'): mesh = MeshBase.from_xml_element(e) meshes[mesh.id] = mesh From d034e1de9c8fe166f38624ee872b8bc46643c66a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 21:23:36 -0600 Subject: [PATCH 1360/2654] Apply suggestions from code review Incorporating suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/geometry.py | 2 +- openmc/model/model.py | 6 ++---- tests/regression_tests/model_xml/test.py | 16 ++++++++-------- tests/unit_tests/test_model.py | 2 -- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 57aab1884..630106628 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -256,7 +256,7 @@ class Geometry: ---------- path : str, optional Path to geometry XML file - materials : dict + materials : dict Dictionary mapping material ID strings to :class:`openmc.Material` instances (defined in :math:`openmc.Geometry.from_xml`) diff --git a/openmc/model/model.py b/openmc/model/model.py index cb84f2c17..559def570 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -228,8 +228,7 @@ class Model: model.settings = openmc.Settings.from_xml_element(root.find('settings')) model.materials = openmc.Materials.from_xml_element(root.find('materials')) materials = {str(m.id): m for m in model.materials} - model.geometry = \ - openmc.Geometry.from_xml_element(root.find('geometry'), materials) + model.geometry = .Geometry.from_xml_element(root.find('geometry'), materials) # gather meshses from other classes before reading the tally node meshes = {} @@ -542,8 +541,7 @@ class Model: materials = openmc.Materials(self.geometry.get_all_materials() .values()) - with open(d, 'w', encoding='utf-8', - errors='xmlcharrefreplace') as fh: + with open(d, 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: # write the XML header fh.write("\n") fh.write("\n") diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 448079b3f..289bd4655 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -55,16 +55,16 @@ class ModelXMLTestHarness(PyAPITestHarness): models = [ -'adj_cell_rotation_model', -'lattice_mult_model', -'energy_laws_model', -'photon_prod_model' + 'adj_cell_rotation_model', + 'lattice_mult_model', + 'energy_laws_model', + 'photon_prod_model' ] paths = [ -'../adj_cell_rotation', -'../lattice_multiple', -'../energy_laws', -'../photon_production' + '../adj_cell_rotation', + '../lattice_multiple', + '../energy_laws', + '../photon_production' ] diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index ce81b00ee..928bf0715 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -7,8 +7,6 @@ import pytest import openmc import openmc.lib -from .. import cdtemp - @pytest.fixture(scope='function') def pin_model_attributes(): From b76825fa9f0598ca563d1c9d579968aa7bffa370 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 22:16:34 -0600 Subject: [PATCH 1361/2654] Addressing some comments from PR --- include/openmc/initialize.h | 6 ++++- openmc/geometry.py | 6 ++--- openmc/model/model.py | 49 ++++++++++++++++++++++++---------- openmc/plots.py | 6 +++++ src/initialize.cpp | 4 +-- tests/unit_tests/test_model.py | 27 +++++++++---------- 6 files changed, 64 insertions(+), 34 deletions(-) diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h index d3d12d45d..5caccceda 100644 --- a/include/openmc/initialize.h +++ b/include/openmc/initialize.h @@ -11,8 +11,12 @@ int parse_command_line(int argc, char* argv[]); #ifdef OPENMC_MPI void initialize_mpi(MPI_Comm intracomm); #endif + +//! Read material, geometry, settings, and tallies from a single XML file bool read_model_xml(); -void read_input_xml(); +//! Read inputs from separate XML files +void read_separate_xml_files(); +//! Write some output that occurs right after initialization void initial_output(); } // namespace openmc diff --git a/openmc/geometry.py b/openmc/geometry.py index 630106628..d036df9c7 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -256,9 +256,9 @@ class Geometry: ---------- path : str, optional Path to geometry XML file - materials : dict - Dictionary mapping material ID strings to :class:`openmc.Material` - instances (defined in :math:`openmc.Geometry.from_xml`) + materials : openmc.Materials or None + Materials used to assign to cells. If None, an attempt is made to + generate it from the materials.xml file. Returns ------- diff --git a/openmc/model/model.py b/openmc/model/model.py index 559def570..2ed9bf668 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -205,8 +205,24 @@ class Model: self._plots.append(plot) @classmethod - def from_xml(cls, *args, separate_xmls=True, **kwargs): - if separate_xmls: + def from_xml(cls, *args, path='model.xml', separate_xmls=True, **kwargs): + """Generate geometry from XML file + + Parameters + ---------- + path : str, optional + Path to model XML file + separate_xmls : bool + Whether or not to read from a single or separate XML files + + Returns + ------- + openmc.Geometry + Geometry object + + """ + + if separate_xmls or not Path(path).exists(): return cls.from_separate_xmls(*args, **kwargs) else: return cls.from_model_xml(*args, **kwargs) @@ -228,7 +244,7 @@ class Model: model.settings = openmc.Settings.from_xml_element(root.find('settings')) model.materials = openmc.Materials.from_xml_element(root.find('materials')) materials = {str(m.id): m for m in model.materials} - model.geometry = .Geometry.from_xml_element(root.find('geometry'), materials) + model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), materials) # gather meshses from other classes before reading the tally node meshes = {} @@ -442,8 +458,8 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True): - """Export model to separate XML files. + def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True, filename='model.xml'): + """Export model to an XML file(s). Parameters ---------- @@ -453,6 +469,8 @@ class Model: remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when exporting. + filename : str + Name of the single XML file to create (only used :math:`separate_xmls` if False) .. versionadded:: 0.13.1 @@ -460,11 +478,15 @@ class Model: Whether or not to write a single model.xml file or many XML files. """ if separate_xmls: - self.export_to_separate_xmls(directory, remove_surfs) + if filename != 'model.xml': + warnings.warn('Export filename parameter {filename} is ignored ' + 'because the model is being written to separate XML files.') + self._export_to_separate_xmls(directory, remove_surfs) else: - self.export_to_single_xml(directory, remove_surfs) + filename = Path(directory) / Path(filename) + self._export_to_single_xml(filename, remove_surfs) - def export_to_separate_xmls(self, directory='.', remove_surfs=False): + def _export_to_separate_xmls(self, directory='.', remove_surfs=False): """Export model to separate XML files. Parameters @@ -501,7 +523,7 @@ class Model: if self.plots: self.plots.export_to_xml(d) - def export_to_single_xml(self, directory='.', remove_surfs=False): + def _export_to_single_xml(self, path='model.xml', remove_surfs=False): """Export model to XML files. Parameters @@ -516,10 +538,9 @@ class Model: .. versionadded:: 0.13.1 """ # Create directory if required - d = Path(directory) - if not d.is_dir(): - d.mkdir(parents=True) - d /= 'model.xml' + xml_path = Path(path) + if not xml_path.parent.exists: + raise RuntimeError(f'The directory "{xml_path}" does not exist.') if remove_surfs: warnings.warn("remove_surfs kwarg will be deprecated soon, please " @@ -541,7 +562,7 @@ class Model: materials = openmc.Materials(self.geometry.get_all_materials() .values()) - with open(d, 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: + with open(xml_path, 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: # write the XML header fh.write("\n") fh.write("\n") diff --git a/openmc/plots.py b/openmc/plots.py index b1f192787..0a0451625 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -911,6 +911,12 @@ class Plots(cv.CheckedList): def to_xml_element(self): """Create a 'plots' element to be written to an XML file. + + Returns + ------- + element : xml.etree.ElementTree.Element + XML element containing all plot elements + """ # Reset xml element tree self._plots_file.clear() diff --git a/src/initialize.cpp b/src/initialize.cpp index 3f6e69ecd..dc5c0c3c1 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -106,7 +106,7 @@ int openmc_init(int argc, char* argv[], const void* intracomm) openmc::openmc_set_seed(DEFAULT_SEED); // Read XML input files - if (!read_model_xml()) read_input_xml(); + if (!read_model_xml()) read_separate_xml_files(); // Write some initial output under the header if needed initial_output(); @@ -371,7 +371,7 @@ bool read_model_xml() { return true; } -void read_input_xml() +void read_separate_xml_files() { read_settings_xml(); read_cross_sections_xml(); diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 928bf0715..87557ddc5 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -530,21 +530,20 @@ def test_calc_volumes(run_in_tmpdir, pin_model_attributes, mpi_intracomm): test_model.finalize_lib() -def test_model_xml(): +def test_model_xml(run_in_tmpdir): - with cdtemp(): - # load a model from examples - pwr_model = openmc.examples.pwr_core() + # load a model from examples + pwr_model = openmc.examples.pwr_core() - # export to separate XMLs manually - pwr_model.settings.export_to_xml('settings_ref.xml') - pwr_model.materials.export_to_xml('materials_ref.xml') - pwr_model.geometry.export_to_xml('geometry_ref.xml') + # export to separate XMLs manually + pwr_model.settings.export_to_xml('settings_ref.xml') + pwr_model.materials.export_to_xml('materials_ref.xml') + pwr_model.geometry.export_to_xml('geometry_ref.xml') - # now write and read a model.xml file - pwr_model.export_to_xml(separate_xmls=False) - new_model = openmc.Model.from_xml(separate_xmls=False) + # now write and read a model.xml file + pwr_model.export_to_xml(separate_xmls=False) + new_model = openmc.Model.from_xml(separate_xmls=False) - # make sure we can also export this again to separate - # XML files - new_model.export_to_xml(separate_xmls=True) \ No newline at end of file + # make sure we can also export this again to separate + # XML files + new_model.export_to_xml(separate_xmls=True) \ No newline at end of file From d9847163e86a4131016a1a6a5f0cd7c0e12b34cc Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 23:06:31 -0600 Subject: [PATCH 1362/2654] Adding ability to specify an input filename to the executable or to the python exec --- include/openmc/initialize.h | 4 +++ openmc/executor.py | 37 +++++++++++++++++++----- openmc/model/model.py | 1 - src/initialize.cpp | 24 +++++++++++---- tests/regression_tests/model_xml/test.py | 22 +++++++++++++- 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h index 5caccceda..c37208e5e 100644 --- a/include/openmc/initialize.h +++ b/include/openmc/initialize.h @@ -1,6 +1,8 @@ #ifndef OPENMC_INITIALIZE_H #define OPENMC_INITIALIZE_H +#include + #ifdef OPENMC_MPI #include "mpi.h" #endif @@ -19,6 +21,8 @@ void read_separate_xml_files(); //! Write some output that occurs right after initialization void initial_output(); + +std::string args_xml_filename {}; } // namespace openmc #endif // OPENMC_INITIALIZE_H diff --git a/openmc/executor.py b/openmc/executor.py index a73d896ff..b14313213 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -9,7 +9,7 @@ from .plots import _get_plot_image def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, plot=False, restart_file=None, threads=None, tracks=False, event_based=None, - openmc_exec='openmc', mpi_args=None): + openmc_exec='openmc', mpi_args=None, input_file=None): """Converts user-readable flags in to command-line arguments to be run with the OpenMC executable via subprocess. @@ -42,6 +42,8 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, mpi_args : list of str, optional MPI execute command and any additional MPI arguments to pass, e.g. ['mpiexec', '-n', '8']. + input_file : str or Pathlike + Name of a single XML input file for the OpenMC executable to read. .. versionadded:: 0.13.0 @@ -82,6 +84,9 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, if mpi_args is not None: args = mpi_args + args + if input_file is not None: + args += ['-i', input_file] + return args @@ -118,7 +123,7 @@ def _run(args, output, cwd): raise RuntimeError(error_msg) -def plot_geometry(output=True, openmc_exec='openmc', cwd='.'): +def plot_geometry(output=True, openmc_exec='openmc', cwd='.', input_file=None): """Run OpenMC in plotting mode Parameters @@ -129,6 +134,8 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'): Path to OpenMC executable cwd : str, optional Path to working directory to run in + input_file : str + Name of a single XML input file for the OpenMC executable to read. Raises ------ @@ -136,10 +143,13 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'): If the `openmc` executable returns a non-zero status """ + args = [openmc_exec, '-p'] + if input_file is not None: + args += ['-i', input_file] _run([openmc_exec, '-p'], output, cwd) -def plot_inline(plots, openmc_exec='openmc', cwd='.'): +def plot_inline(plots, openmc_exec='openmc', cwd='.', input_file=None): """Display plots inline in a Jupyter notebook. .. versionchanged:: 0.13.0 @@ -155,6 +165,8 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.'): Path to OpenMC executable cwd : str, optional Path to working directory to run in + input_file : str + Name of a single XML input file for the OpenMC executable to read. Raises ------ @@ -171,7 +183,7 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.'): openmc.Plots(plots).export_to_xml(cwd) # Run OpenMC in geometry plotting mode - plot_geometry(False, openmc_exec, cwd) + plot_geometry(False, openmc_exec, cwd, input_file) if plots is not None: images = [_get_plot_image(p, cwd) for p in plots] @@ -179,7 +191,8 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.'): def calculate_volumes(threads=None, output=True, cwd='.', - openmc_exec='openmc', mpi_args=None): + openmc_exec='openmc', mpi_args=None, + input_file=None): """Run stochastic volume calculations in OpenMC. This function runs OpenMC in stochastic volume calculation mode. To specify @@ -210,6 +223,8 @@ def calculate_volumes(threads=None, output=True, cwd='.', cwd : str, optional Path to working directory to run in. Defaults to the current working directory. + input_file : str or Pathlike + Name of a single XML input file for the OpenMC executable to read. Raises ------ @@ -223,14 +238,16 @@ def calculate_volumes(threads=None, output=True, cwd='.', """ args = _process_CLI_arguments(volume=True, threads=threads, - openmc_exec=openmc_exec, mpi_args=mpi_args) + openmc_exec=openmc_exec, mpi_args=mpi_args, + input_file=input_file) _run(args, output, cwd) def run(particles=None, threads=None, geometry_debug=False, restart_file=None, tracks=False, output=True, cwd='.', - openmc_exec='openmc', mpi_args=None, event_based=False): + openmc_exec='openmc', mpi_args=None, event_based=False, + input_file=None): """Run an OpenMC simulation. Parameters @@ -265,6 +282,9 @@ def run(particles=None, threads=None, geometry_debug=False, .. versionadded:: 0.12 + input_file : str or Pathlike + Name of a single XML input file for the OpenMC executable to read. + Raises ------ RuntimeError @@ -275,6 +295,7 @@ def run(particles=None, threads=None, geometry_debug=False, args = _process_CLI_arguments( volume=False, geometry_debug=geometry_debug, particles=particles, restart_file=restart_file, threads=threads, tracks=tracks, - event_based=event_based, openmc_exec=openmc_exec, mpi_args=mpi_args) + event_based=event_based, openmc_exec=openmc_exec, mpi_args=mpi_args, + input_file=input_file) _run(args, output, cwd) diff --git a/openmc/model/model.py b/openmc/model/model.py index 2ed9bf668..15effd3e4 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -221,7 +221,6 @@ class Model: Geometry object """ - if separate_xmls or not Path(path).exists(): return cls.from_separate_xmls(*args, **kwargs) else: diff --git a/src/initialize.cpp b/src/initialize.cpp index dc5c0c3c1..02a4f9ab7 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -181,10 +181,11 @@ int parse_command_line(int argc, char* argv[]) } else if (arg == "-e" || arg == "--event") { settings::event_based = true; - + } else if (arg == "-i" || arg == "--input") { + i += 1; + args_xml_filename = std::string(argv[i]); } else if (arg == "-r" || arg == "--restart") { i += 1; - // Check what type of file this is hid_t file_id = file_open(argv[i], 'r', true); std::string filetype; @@ -295,9 +296,19 @@ int parse_command_line(int argc, char* argv[]) bool read_model_xml() { // get verbosity from settings node - std::string model_filename = settings::path_input + "model.xml"; - bool use_model_file = file_exists(model_filename); - if (!file_exists(model_filename)) return false; + + std::string xml_filename = "model.xml"; + if (!args_xml_filename.empty()) xml_filename = args_xml_filename; + std::string model_filename = settings::path_input + xml_filename; + + // check that the model file exists. If it does not and a custom filename was + // supplied by the user report an error + if (!file_exists(model_filename)) { + if (!args_xml_filename.empty()) { + fatal_error(fmt::format("The input file '{}' specified on the command line does not exist", args_xml_filename)); + } + return false; + } // attempt to open the document pugi::xml_document doc; @@ -325,6 +336,9 @@ bool read_model_xml() { title(); } + if (!args_xml_filename.empty()) + write_message(fmt::format("Reaging user-specified input '{}'...", args_xml_filename), 5); + else write_message("Reading model XML file...", 5); read_settings_xml(settings_root); diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 289bd4655..342d7dca9 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -73,4 +73,24 @@ def test_model_xml(model, path, request): inputs = path + "/inputs_true.dat" results = path + "/results_true.dat" harness = ModelXMLTestHarness(request.getfixturevalue(model), inputs, results) - harness.main() \ No newline at end of file + harness.main() + +def test_input_arg(run_in_tmpdir): + + pincell = openmc.examples.pwr_pin_cell() + + pincell.settings.particles = 100 + + # export to separate XML files and run + pincell.export_to_xml(separate_xmls=True) + openmc.run() + + # now export to a single XML file with a custom name + pincell.export_to_xml(filename='pincell.xml', separate_xmls=False) + + # run by specifying that single file + openmc.run(input_file='pincell.xml') + + # now ensure we get an error for an incorrect filename + with pytest.raises(RuntimeError): + openmc.run(input_file='ex-em-ell.xml') \ No newline at end of file From 366f9e905c4f049e8971f743b6cca5d210fff04e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 23:10:57 -0600 Subject: [PATCH 1363/2654] Test comment and updated error messages --- src/initialize.cpp | 8 +++++--- tests/regression_tests/model_xml/test.py | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/initialize.cpp b/src/initialize.cpp index 02a4f9ab7..68436f07e 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -348,14 +348,15 @@ bool read_model_xml() { auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; for (const auto& input : other_inputs) { if (file_exists(settings::path_input + input)) { - warning(("Other XML file input(s) are present. These file will be ignored in favor of the model.xml file.")); + warning((fmt::format("Other XML file input(s) are present. These file will be ignored in favor of the {} file.", xml_filename)); break; } } // Read materials and cross sections if (!check_for_node(root, "materials")) { - fatal_error("No node present in the model.xml file."); + fatal_error( + fmt::format("No node present in the {} file.", xml_filename)); } auto materials_node = root.child("materials"); read_cross_sections_xml(materials_node); @@ -363,7 +364,8 @@ bool read_model_xml() { // Read geometry if (!check_for_node(root, "geometry")) { - fatal_error("No node present in the model.xml_file."); + fatal_error(fmt::format( + "No node present in the model.xml_file.", xml_filename)); } read_geometry_xml(root.child("geometry")); diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 342d7dca9..5bfe912a4 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -91,6 +91,7 @@ def test_input_arg(run_in_tmpdir): # run by specifying that single file openmc.run(input_file='pincell.xml') - # now ensure we get an error for an incorrect filename + # now ensure we get an error for an incorrect filename, + # even in the presence of other, valid XML files with pytest.raises(RuntimeError): openmc.run(input_file='ex-em-ell.xml') \ No newline at end of file From 1e6cb68ea420558f6f120e830602b8938f2c1319 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 23:14:30 -0600 Subject: [PATCH 1364/2654] Addressing a few more comments in C++ code --- src/initialize.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/initialize.cpp b/src/initialize.cpp index 68436f07e..87e839dfd 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -358,8 +358,12 @@ bool read_model_xml() { fatal_error( fmt::format("No node present in the {} file.", xml_filename)); } + + // find materials node this object cannot be used after being passed to the + // cross section reading function below auto materials_node = root.child("materials"); read_cross_sections_xml(materials_node); + read_materials_xml(root.child("materials")); // Read geometry @@ -411,7 +415,7 @@ void read_separate_xml_files() } void initial_output() { - // handle some final output + // write initial output if (settings::run_mode == RunMode::PLOTTING) { // Read plots.xml if it exists if (mpi::master && settings::verbosity >= 5) From 7a203fbf7266f365d3d209461687402edcb3b56b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 23:16:57 -0600 Subject: [PATCH 1365/2654] Correcting parenthesis --- src/initialize.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/initialize.cpp b/src/initialize.cpp index 87e839dfd..a6a6b5a77 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -348,7 +348,7 @@ bool read_model_xml() { auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; for (const auto& input : other_inputs) { if (file_exists(settings::path_input + input)) { - warning((fmt::format("Other XML file input(s) are present. These file will be ignored in favor of the {} file.", xml_filename)); + warning((fmt::format("Other XML file input(s) are present. These file will be ignored in favor of the {} file.", xml_filename))); break; } } From fe47d565fd7fddb464e3e67907936211bc76a857 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 23:17:11 -0600 Subject: [PATCH 1366/2654] Spot check in error message from failed run --- tests/regression_tests/model_xml/test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 5bfe912a4..0dc2cc289 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -93,5 +93,6 @@ def test_input_arg(run_in_tmpdir): # now ensure we get an error for an incorrect filename, # even in the presence of other, valid XML files - with pytest.raises(RuntimeError): - openmc.run(input_file='ex-em-ell.xml') \ No newline at end of file + with pytest.raises(RuntimeError) as execinfo: + openmc.run(input_file='ex-em-ell.xml') + assert 'ex-em-ell.xml' in execinfo.value \ No newline at end of file From 6f7a6febd3fe01531979d2276f1c40fb6f8430f7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Nov 2022 08:22:57 -0600 Subject: [PATCH 1367/2654] Updating model XML file format w/ indentation. --- openmc/_xml.py | 28 ++++-- openmc/material.py | 27 +++-- openmc/model/model.py | 7 +- .../model_xml/inputs_true.dat | 99 ++++++++++++------- 4 files changed, 111 insertions(+), 50 deletions(-) diff --git a/openmc/_xml.py b/openmc/_xml.py index 32679fd89..b4e08c751 100644 --- a/openmc/_xml.py +++ b/openmc/_xml.py @@ -1,22 +1,36 @@ -def clean_indentation(element, level=0, spaces_per_level=2): - """ - copy and paste from https://effbot.org/zone/element-lib.htm#prettyprint - it basically walks your tree and adds spaces and newlines so the tree is - printed in a nice way +def clean_indentation(element, level=0, spaces_per_level=2, trailing_indent=True): + """Set indentation of XML element and its sub-elements. + Copied and pastee from https://effbot.org/zone/element-lib.htm#prettyprint. + It walks your tree and adds spaces and newlines so the tree is + printed in a nice way. + + Parameters + ---------- + level : int + Indentation level for the element passed in (default 0) + spaces_per_level : int + Number of spaces per indentation level (default 2) + trailing_indent : bool + Whether or not to include an indentation after closing the element + """ i = "\n" + level*spaces_per_level*" " + # ensure there's awlays some tail for the element passed in + if not element.tail: + element.tail = "" + if len(element): if not element.text or not element.text.strip(): element.text = i + spaces_per_level*" " - if not element.tail or not element.tail.strip(): + if trailing_indent and (not element.tail or not element.tail.strip()): element.tail = i for sub_element in element: clean_indentation(sub_element, level+1, spaces_per_level) if not sub_element.tail or not sub_element.tail.strip(): sub_element.tail = i else: - if level and (not element.tail or not element.tail.strip()): + if trailing_indent and level and (not element.tail or not element.tail.strip()): element.tail = i diff --git a/openmc/material.py b/openmc/material.py index c33596800..332f8c965 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1449,7 +1449,7 @@ class Materials(cv.CheckedList): for material in self: material.make_isotropic_in_lab() - def _write_xml(self, file, header=True): + def _write_xml(self, file, header=True, level=0, spaces_per_level=2, trailing_indent=True): """Writes XML content of the materials to an open file handle. Parameters @@ -1458,33 +1458,46 @@ class Materials(cv.CheckedList): Open file handle to write content into. header : bool Whether or not to write the XML header + level : int + Indentation level of materials element + spaces_per_level : int + Number of spaces per indentation + trailing_indentation : bool + Whether or not to write a trailing indentation for the materials element + """ + indentation = level*spaces_per_level*' ' # Write the header and the opening tag for the root element. if header: file.write("\n") - file.write('\n') + file.write(indentation+'\n') # Write the element. if self.cross_sections is not None: element = ET.Element('cross_sections') element.text = str(self.cross_sections) - clean_indentation(element, level=1) + clean_indentation(element, level=level+1) element.tail = element.tail.strip(' ') - file.write(' ') + file.write((level+1)*spaces_per_level*' ') reorder_attributes(element) # TODO: Remove when support is Python 3.8+ ET.ElementTree(element).write(file, encoding='unicode') # Write the elements. for material in sorted(self, key=lambda x: x.id): element = material.to_xml_element() - clean_indentation(element, level=1) + clean_indentation(element, level=level+1) element.tail = element.tail.strip(' ') - file.write(' ') + file.write((level+1)*spaces_per_level*' ') reorder_attributes(element) # TODO: Remove when support is Python 3.8+ ET.ElementTree(element).write(file, encoding='unicode') # Write the closing tag for the root element. - file.write('\n') + file.write(indentation+'\n') + + # Write a trailing indentation for the next element + # at this level if needed + if trailing_indent: + file.write(indentation) def export_to_xml(self, path: PathLike = 'materials.xml'): diff --git a/openmc/model/model.py b/openmc/model/model.py index 15effd3e4..9c38d27c3 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -552,6 +552,9 @@ class Model: settings_element = self.settings.to_xml_element(memo) geometry_element = self.geometry.to_xml_element() + xml.clean_indentation(geometry_element, level=1) + xml.clean_indentation(settings_element, level=1) + # If a materials collection was specified, export it. Otherwise, look # for all materials in the geometry and use that to automatically build # a collection. @@ -567,16 +570,18 @@ class Model: fh.write("\n") # Write the materials collection to the open XML file first. # This will write the XML header also - materials._write_xml(fh, False) + materials._write_xml(fh, False, level=1) # Write remaining elements as a tree ET.ElementTree(geometry_element).write(fh, encoding='unicode') ET.ElementTree(settings_element).write(fh, encoding='unicode') if self.tallies: tallies_element = self.tallies.to_xml_element(memo) + xml.clean_indentation(tallies_element, level=1, trailing_indent=self.plots) ET.ElementTree(tallies_element).write(fh, encoding='unicode') if self.plots: plots_element = self.plots.to_xml_element() + xml.clean_indentation(plots_element, level=1, trailing_indent=False) ET.ElementTree(plots_element).write(fh, encoding='unicode') fh.write("\n") diff --git a/tests/regression_tests/model_xml/inputs_true.dat b/tests/regression_tests/model_xml/inputs_true.dat index 5aedbfa14..c40802631 100644 --- a/tests/regression_tests/model_xml/inputs_true.dat +++ b/tests/regression_tests/model_xml/inputs_true.dat @@ -1,38 +1,67 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 10000 - 10 - 5 - - - -4.0 -4.0 -4.0 4.0 4.0 4.0 - - - + + + + + + + + + + + + + + + + + fixed source + 10000 + 1 + + + 0 0 0 + + + + 14000000.0 1.0 + + + ttb + true + + 1000.0 + + + + + 16 + + + neutron photon electron positron + + + 1 2 + current + + + 2 + Al27 total + total (n,gamma) + tracklength + + + 2 + Al27 total + total heating (n,gamma) + collision + + + 2 + Al27 total + total heating (n,gamma) + analog + + From 5d1ead2e6a88affe5900067412e0464171cba8e4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 26 Nov 2022 00:46:12 -0600 Subject: [PATCH 1368/2654] Addressing some more PR comments. A couple of typo fixes too. --- openmc/_xml.py | 2 +- openmc/model/model.py | 2 +- src/initialize.cpp | 6 +----- tests/regression_tests/adj_cell_rotation/__init__.py | 2 -- tests/regression_tests/energy_laws/__init__.py | 1 - tests/regression_tests/lattice_multiple/__init__.py | 1 - tests/regression_tests/model_xml/test.py | 8 ++++---- tests/regression_tests/photon_production/__init__.py | 1 - 8 files changed, 7 insertions(+), 16 deletions(-) diff --git a/openmc/_xml.py b/openmc/_xml.py index b4e08c751..450c8a99b 100644 --- a/openmc/_xml.py +++ b/openmc/_xml.py @@ -11,7 +11,7 @@ def clean_indentation(element, level=0, spaces_per_level=2, trailing_indent=True spaces_per_level : int Number of spaces per indentation level (default 2) trailing_indent : bool - Whether or not to include an indentation after closing the element + Whether or not to add indentation after closing the element """ i = "\n" + level*spaces_per_level*" " diff --git a/openmc/model/model.py b/openmc/model/model.py index 9c38d27c3..145a2151b 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -469,7 +469,7 @@ class Model: Whether or not to remove redundant surfaces from the geometry when exporting. filename : str - Name of the single XML file to create (only used :math:`separate_xmls` if False) + Name of the single XML file to create (only used :math:`separate_xmls` is False) .. versionadded:: 0.13.1 diff --git a/src/initialize.cpp b/src/initialize.cpp index a6a6b5a77..212b2f7bd 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -359,11 +359,7 @@ bool read_model_xml() { fmt::format("No node present in the {} file.", xml_filename)); } - // find materials node this object cannot be used after being passed to the - // cross section reading function below - auto materials_node = root.child("materials"); - read_cross_sections_xml(materials_node); - + read_cross_sections_xml(root.child("materials")); read_materials_xml(root.child("materials")); // Read geometry diff --git a/tests/regression_tests/adj_cell_rotation/__init__.py b/tests/regression_tests/adj_cell_rotation/__init__.py index 7efe44865..e69de29bb 100644 --- a/tests/regression_tests/adj_cell_rotation/__init__.py +++ b/tests/regression_tests/adj_cell_rotation/__init__.py @@ -1,2 +0,0 @@ - -from .test import model \ No newline at end of file diff --git a/tests/regression_tests/energy_laws/__init__.py b/tests/regression_tests/energy_laws/__init__.py index 29fbfcc0c..e69de29bb 100644 --- a/tests/regression_tests/energy_laws/__init__.py +++ b/tests/regression_tests/energy_laws/__init__.py @@ -1 +0,0 @@ -from .test import model \ No newline at end of file diff --git a/tests/regression_tests/lattice_multiple/__init__.py b/tests/regression_tests/lattice_multiple/__init__.py index 29fbfcc0c..e69de29bb 100644 --- a/tests/regression_tests/lattice_multiple/__init__.py +++ b/tests/regression_tests/lattice_multiple/__init__.py @@ -1 +0,0 @@ -from .test import model \ No newline at end of file diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 0dc2cc289..52f67f76f 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -9,10 +9,10 @@ from tests.testing_harness import PyAPITestHarness, colorize # use a few models from other tests to make sure the same results are # produced when using a single model.xml file as input -from ..adj_cell_rotation import model as adj_cell_rotation_model -from ..lattice_multiple import model as lattice_mult_model -from ..energy_laws import model as energy_laws_model -from ..photon_production import model as photon_prod_model +from ..adj_cell_rotation.test import model as adj_cell_rotation_model +from ..lattice_multiple.test import model as lattice_mult_model +from ..energy_laws.test import model as energy_laws_model +from ..photon_production.test import model as photon_prod_model class ModelXMLTestHarness(PyAPITestHarness): diff --git a/tests/regression_tests/photon_production/__init__.py b/tests/regression_tests/photon_production/__init__.py index 29fbfcc0c..e69de29bb 100644 --- a/tests/regression_tests/photon_production/__init__.py +++ b/tests/regression_tests/photon_production/__init__.py @@ -1 +0,0 @@ -from .test import model \ No newline at end of file From e7f95b0c7a5fc0c1548183f38606ce158c2eb31c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Nov 2022 00:44:05 -0600 Subject: [PATCH 1369/2654] Docstring correction and a note about the recursion --- openmc/_xml.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openmc/_xml.py b/openmc/_xml.py index 450c8a99b..6d298638d 100644 --- a/openmc/_xml.py +++ b/openmc/_xml.py @@ -1,6 +1,6 @@ def clean_indentation(element, level=0, spaces_per_level=2, trailing_indent=True): """Set indentation of XML element and its sub-elements. - Copied and pastee from https://effbot.org/zone/element-lib.htm#prettyprint. + Copied and pasted from https://effbot.org/zone/element-lib.htm#prettyprint. It walks your tree and adds spaces and newlines so the tree is printed in a nice way. @@ -26,6 +26,8 @@ def clean_indentation(element, level=0, spaces_per_level=2, trailing_indent=True if trailing_indent and (not element.tail or not element.tail.strip()): element.tail = i for sub_element in element: + # `trailing_indent` intentionally not passed to the recursive call. + # it only applies to the element for the initial of this function. clean_indentation(sub_element, level+1, spaces_per_level) if not sub_element.tail or not sub_element.tail.strip(): sub_element.tail = i From b3225be24d384ba834fab6f003ff7ba39e9d99b1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Nov 2022 20:03:42 -0600 Subject: [PATCH 1370/2654] Adding executor tests --- tests/unit_tests/test_model.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 87557ddc5..5d4765d65 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -1,5 +1,6 @@ from math import pi from pathlib import Path +import os import numpy as np import pytest @@ -546,4 +547,23 @@ def test_model_xml(run_in_tmpdir): # make sure we can also export this again to separate # XML files - new_model.export_to_xml(separate_xmls=True) \ No newline at end of file + new_model.export_to_xml(separate_xmls=True) + +def test_model_exec(run_in_tmpdir): + + pincell_model = openmc.examples.pwr_pin_cell() + + pincell_model.export_to_xml(filename='pwr_pincell.xml', separate_xmls=False) + + openmc.run(input_file='pwr_pincell.xml') + + with pytest.raises(RuntimeError, match='ex-em-ell.xml'): + openmc.run(input_file='ex-em-ell.xml') + + # test that a file in a different directory can be used + os.mkdir('inputs') + pincell_model.export_to_xml(directory='./inputs', filename='pincell.xml', separate_xmls=False) + openmc.run(input_file='./inputs/pincell.xml') + + with pytest.raises(RuntimeError, match='input_dir'): + openmc.run(input_file='input_dir/pincell.xml') \ No newline at end of file From 72ff942226e8fb60801328a64530ad1cd94b1da0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Nov 2022 20:04:45 -0600 Subject: [PATCH 1371/2654] Checking RuntimeError message correctly --- tests/regression_tests/model_xml/test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 52f67f76f..51c25a603 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -93,6 +93,5 @@ def test_input_arg(run_in_tmpdir): # now ensure we get an error for an incorrect filename, # even in the presence of other, valid XML files - with pytest.raises(RuntimeError) as execinfo: - openmc.run(input_file='ex-em-ell.xml') - assert 'ex-em-ell.xml' in execinfo.value \ No newline at end of file + with pytest.raises(RuntimeError, match='ex-em-ell.xml'): + openmc.run(input_file='ex-em-ell.xml') \ No newline at end of file From 7f5d2a583932206bc681a8555d658334d74ebc9d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Nov 2022 23:54:26 -0600 Subject: [PATCH 1372/2654] Refactoring model_xml regression tests a bit and adding input checking --- .../adj_cell_rotation_inputs_true.dat | 38 +++++++++++ .../model_xml/energy_laws_inputs_true.dat | 23 +++++++ .../lattice_multiple_inputs_true.dat | 53 +++++++++++++++ .../photon_production_inputs_true.dat | 67 +++++++++++++++++++ tests/regression_tests/model_xml/test.py | 42 ++++++------ 5 files changed, 201 insertions(+), 22 deletions(-) create mode 100644 tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat create mode 100644 tests/regression_tests/model_xml/energy_laws_inputs_true.dat create mode 100644 tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat create mode 100644 tests/regression_tests/model_xml/photon_production_inputs_true.dat diff --git a/tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat b/tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat new file mode 100644 index 000000000..3b14f304e --- /dev/null +++ b/tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 10000 + 10 + 5 + + + -4.0 -4.0 -4.0 4.0 4.0 4.0 + + + + diff --git a/tests/regression_tests/model_xml/energy_laws_inputs_true.dat b/tests/regression_tests/model_xml/energy_laws_inputs_true.dat new file mode 100644 index 000000000..62485ff72 --- /dev/null +++ b/tests/regression_tests/model_xml/energy_laws_inputs_true.dat @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + diff --git a/tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat b/tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat new file mode 100644 index 000000000..d828b25f6 --- /dev/null +++ b/tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + 1.2 1.2 + 1 + 2 2 + -1.2 -1.2 + +2 1 +1 1 + + + 2.4 2.4 + 2 2 + -2.4 -2.4 + +4 4 +4 4 + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + diff --git a/tests/regression_tests/model_xml/photon_production_inputs_true.dat b/tests/regression_tests/model_xml/photon_production_inputs_true.dat new file mode 100644 index 000000000..9e60033be --- /dev/null +++ b/tests/regression_tests/model_xml/photon_production_inputs_true.dat @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + fixed source + 10000 + 1 + + + 0 0 0 + + + + 14000000.0 1.0 + + + ttb + true + + 1000.0 + + + + + 1 + + + neutron photon electron positron + + + 1 2 + current + + + 2 + Al27 total + total (n,gamma) + tracklength + + + 2 + Al27 total + total heating (n,gamma) + collision + + + 2 + Al27 total + total heating (n,gamma) + analog + + + diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 51c25a603..9da5438db 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -10,9 +10,9 @@ from tests.testing_harness import PyAPITestHarness, colorize # use a few models from other tests to make sure the same results are # produced when using a single model.xml file as input from ..adj_cell_rotation.test import model as adj_cell_rotation_model -from ..lattice_multiple.test import model as lattice_mult_model +from ..lattice_multiple.test import model as lattice_multiple_model from ..energy_laws.test import model as energy_laws_model -from ..photon_production.test import model as photon_prod_model +from ..photon_production.test import model as photon_production_model class ModelXMLTestHarness(PyAPITestHarness): @@ -30,10 +30,10 @@ class ModelXMLTestHarness(PyAPITestHarness): def _get_inputs(self): return open('model.xml').read() - def _compare_inputs(self): - """Skip input comparisons for now - """ - pass + # def _compare_inputs(self): + # """Skip input comparisons for now + # """ + # pass def _compare_results(self): """Make sure the current results agree with the reference.""" @@ -54,25 +54,23 @@ class ModelXMLTestHarness(PyAPITestHarness): os.remove('model.xml') -models = [ - 'adj_cell_rotation_model', - 'lattice_mult_model', - 'energy_laws_model', - 'photon_prod_model' -] -paths = [ - '../adj_cell_rotation', - '../lattice_multiple', - '../energy_laws', - '../photon_production' +test_names = [ + 'adj_cell_rotation', + 'lattice_multiple', + 'energy_laws', + 'photon_production' ] -@pytest.mark.parametrize("model, path", zip(models, paths)) -def test_model_xml(model, path, request): - inputs = path + "/inputs_true.dat" - results = path + "/results_true.dat" - harness = ModelXMLTestHarness(request.getfixturevalue(model), inputs, results) +@pytest.mark.parametrize("test_name", test_names, ids=lambda test: test) +def test_model_xml(test_name, request): + openmc.reset_auto_ids() + + test_path = '../' + test_name + results = test_path + "/results_true.dat" + inputs = test_name + "_inputs_true.dat" + model_name = test_name + "_model" + harness = ModelXMLTestHarness(request.getfixturevalue(model_name), inputs, results) harness.main() def test_input_arg(run_in_tmpdir): From 3f4a9eb7a2056f3136b00b82a814e934f52803e3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Nov 2022 01:19:38 -0600 Subject: [PATCH 1373/2654] Reordering geometry XML element attributes --- openmc/geometry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index d036df9c7..afcae1d55 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -132,6 +132,7 @@ class Geometry: # Clean the indentation in the file to be user-readable xml.clean_indentation(element) + xml.reorder_attributes(element) # TODO: Remove when support is Python 3.8+ return element @@ -157,7 +158,6 @@ class Geometry: p /= 'geometry.xml' # Write the XML Tree to the geometry.xml file - xml.reorder_attributes(root_element) # TODO: Remove when support is Python 3.8+ tree = ET.ElementTree(root_element) tree.write(str(p), xml_declaration=True, encoding='utf-8') From 83cf6848d0f0fbe0a59798b333542daf3255c7e5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Nov 2022 11:11:06 -0600 Subject: [PATCH 1374/2654] Updating expected inputs with reordering --- .../adj_cell_rotation_inputs_true.dat | 20 +++++++++---------- .../model_xml/energy_laws_inputs_true.dat | 2 +- .../lattice_multiple_inputs_true.dat | 16 +++++++-------- .../photon_production_inputs_true.dat | 8 ++++---- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat b/tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat index 3b14f304e..1c4516f42 100644 --- a/tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat +++ b/tests/regression_tests/model_xml/adj_cell_rotation_inputs_true.dat @@ -13,16 +13,16 @@ - - - - - - - - - - + + + + + + + + + + eigenvalue diff --git a/tests/regression_tests/model_xml/energy_laws_inputs_true.dat b/tests/regression_tests/model_xml/energy_laws_inputs_true.dat index 62485ff72..c89ccc97e 100644 --- a/tests/regression_tests/model_xml/energy_laws_inputs_true.dat +++ b/tests/regression_tests/model_xml/energy_laws_inputs_true.dat @@ -12,7 +12,7 @@ - + eigenvalue diff --git a/tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat b/tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat index d828b25f6..0eed3c201 100644 --- a/tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat +++ b/tests/regression_tests/model_xml/lattice_multiple_inputs_true.dat @@ -18,8 +18,8 @@ - - + + 1.2 1.2 1 @@ -37,12 +37,12 @@ 4 4 4 4 - - - - - - + + + + + + eigenvalue diff --git a/tests/regression_tests/model_xml/photon_production_inputs_true.dat b/tests/regression_tests/model_xml/photon_production_inputs_true.dat index 9e60033be..e4fe9a585 100644 --- a/tests/regression_tests/model_xml/photon_production_inputs_true.dat +++ b/tests/regression_tests/model_xml/photon_production_inputs_true.dat @@ -10,10 +10,10 @@ - - - - + + + + fixed source From 2c27d1065a1e583a3778aa493f70a36724b46306 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Nov 2022 13:45:10 -0600 Subject: [PATCH 1375/2654] Moving other relevant XML reorder calls and updating expected input again. --- openmc/settings.py | 2 +- openmc/tallies.py | 2 +- .../model_xml/photon_production_inputs_true.dat | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 74ec0d54a..3c1c8c7f5 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1598,6 +1598,7 @@ class Settings: # Clean the indentation in the file to be user-readable clean_indentation(element) + reorder_attributes(element) # TODO: Remove when support is Python 3.8+ return element @@ -1618,7 +1619,6 @@ class Settings: p /= 'settings.xml' # Write the XML Tree to the settings.xml file - reorder_attributes(root_element) # TODO: Remove when support is Python 3.8+ tree = ET.ElementTree(root_element) tree.write(str(p), xml_declaration=True, encoding='utf-8') diff --git a/openmc/tallies.py b/openmc/tallies.py index e37f04e25..e17e7c99d 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3166,6 +3166,7 @@ class Tallies(cv.CheckedList): # Clean the indentation in the file to be user-readable clean_indentation(element) + reorder_attributes(element) # TODO: Remove when support is Python 3.8+ return element @@ -3187,7 +3188,6 @@ class Tallies(cv.CheckedList): p /= 'tallies.xml' # Write the XML Tree to the tallies.xml file - reorder_attributes(root_element) # TODO: Remove when support is Python 3.8+ tree = ET.ElementTree(root_element) tree.write(str(p), xml_declaration=True, encoding='utf-8') diff --git a/tests/regression_tests/model_xml/photon_production_inputs_true.dat b/tests/regression_tests/model_xml/photon_production_inputs_true.dat index e4fe9a585..0b2b43468 100644 --- a/tests/regression_tests/model_xml/photon_production_inputs_true.dat +++ b/tests/regression_tests/model_xml/photon_production_inputs_true.dat @@ -23,7 +23,7 @@ 0 0 0 - + 14000000.0 1.0 From cd7c3bf6ba62cd019c378a3a22880e24e847f8ef Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 12:58:32 -0600 Subject: [PATCH 1376/2654] Updates to import/export methods suggested by @paulromano --- openmc/model/model.py | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 145a2151b..6ca6f72b6 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -205,15 +205,19 @@ class Model: self._plots.append(plot) @classmethod - def from_xml(cls, *args, path='model.xml', separate_xmls=True, **kwargs): + def from_xml(cls, *args, separate_xmls=True, **kwargs): """Generate geometry from XML file Parameters ---------- - path : str, optional - Path to model XML file + args : list + Positional arguments to be forwarded to + :func:`Model.from_separate_xmls` or :func:`Model.from_model_xml`. separate_xmls : bool - Whether or not to read from a single or separate XML files + Whether or not to read from a single or separate XML files. + kwargs : dict, optional + Keyword arguments to be forwarded to + :func:`Model.from_separate_xmls` or :func:`Model.from_model_xml`. Returns ------- @@ -221,7 +225,7 @@ class Model: Geometry object """ - if separate_xmls or not Path(path).exists(): + if separate_xmls: return cls.from_separate_xmls(*args, **kwargs) else: return cls.from_model_xml(*args, **kwargs) @@ -457,19 +461,19 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True, filename='model.xml'): + def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True, path='model.xml'): """Export model to an XML file(s). Parameters ---------- directory : str Directory to write XML files to. If it doesn't exist already, it - will be created. + will be created. Only used if :math:`separate_xmls` is True. remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when exporting. - filename : str - Name of the single XML file to create (only used :math:`separate_xmls` is False) + path : str + Path to an output filename or directory. Only used if :math:`separate_xmls` is False. .. versionadded:: 0.13.1 @@ -477,13 +481,9 @@ class Model: Whether or not to write a single model.xml file or many XML files. """ if separate_xmls: - if filename != 'model.xml': - warnings.warn('Export filename parameter {filename} is ignored ' - 'because the model is being written to separate XML files.') self._export_to_separate_xmls(directory, remove_surfs) else: - filename = Path(directory) / Path(filename) - self._export_to_single_xml(filename, remove_surfs) + self._export_to_single_xml(path, remove_surfs) def _export_to_separate_xmls(self, directory='.', remove_surfs=False): """Export model to separate XML files. @@ -530,16 +530,25 @@ class Model: directory : str Directory to write the model.xml file to. If it doesn't exist already, it will be created. + path : str or Pathlike + Location of the XML file to write. Can be a directory or file path. remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when exporting. .. versionadded:: 0.13.1 """ - # Create directory if required xml_path = Path(path) - if not xml_path.parent.exists: - raise RuntimeError(f'The directory "{xml_path}" does not exist.') + # if the provided path doesn't end with the XML extension, assume the + # input path is meant to be a directory. If the directory does not + # exist, create it and place a 'model.xml' file there. + if not str(xml_path).endswith('.xml') and not xml_path.exists(): + os.mkdir(xml_path) + xml_path /= 'model.xml' + # if this is an XML file location and the file's parent directory does + # not exist, create it before continuing + elif not xml_path.parent.exists(): + os.mkdir(xml_path.parent) if remove_surfs: warnings.warn("remove_surfs kwarg will be deprecated soon, please " From ef2f690e3d4c7bb1f700f189bdaad88689fa5b16 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 12:59:08 -0600 Subject: [PATCH 1377/2654] Updating handling of single XML input to leverage existing settings::path_input --- src/initialize.cpp | 42 +++++++++++++++++++----------------------- src/settings.cpp | 3 ++- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/initialize.cpp b/src/initialize.cpp index 212b2f7bd..c0333e01c 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -181,9 +181,6 @@ int parse_command_line(int argc, char* argv[]) } else if (arg == "-e" || arg == "--event") { settings::event_based = true; - } else if (arg == "-i" || arg == "--input") { - i += 1; - args_xml_filename = std::string(argv[i]); } else if (arg == "-r" || arg == "--restart") { i += 1; // Check what type of file this is @@ -295,27 +292,24 @@ int parse_command_line(int argc, char* argv[]) } bool read_model_xml() { - // get verbosity from settings node + std::string model_filename = settings::path_input; - std::string xml_filename = "model.xml"; - if (!args_xml_filename.empty()) xml_filename = args_xml_filename; - std::string model_filename = settings::path_input + xml_filename; - - // check that the model file exists. If it does not and a custom filename was - // supplied by the user report an error - if (!file_exists(model_filename)) { - if (!args_xml_filename.empty()) { - fatal_error(fmt::format("The input file '{}' specified on the command line does not exist", args_xml_filename)); - } - return false; + // if the path input isn't an existing file, assume its a directory + // and append the default model.xml filename + if (!file_exists(settings::path_input)) { + model_filename += "/model.xml"; + if (!file_exists(model_filename)) + return false; } - // attempt to open the document + // try to process the path input as an XML file pugi::xml_document doc; - auto result = doc.load_file(model_filename.c_str()); - if (!result) { - fatal_error("Error processing model.xml file."); + // if the input is a file, try to read it + if (!doc.load_file(model_filename.c_str())) { + fatal_error(fmt::format( + "Error reading from single XML input file '{}'", model_filename)); } + pugi::xml_node root = doc.document_element(); // Read settings @@ -348,15 +342,17 @@ bool read_model_xml() { auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; for (const auto& input : other_inputs) { if (file_exists(settings::path_input + input)) { - warning((fmt::format("Other XML file input(s) are present. These file will be ignored in favor of the {} file.", xml_filename))); + warning((fmt::format("Other XML file input(s) are present. These file " + "will be ignored in favor of the {} file.", + model_filename))); break; } } // Read materials and cross sections if (!check_for_node(root, "materials")) { - fatal_error( - fmt::format("No node present in the {} file.", xml_filename)); + fatal_error(fmt::format( + "No node present in the {} file.", model_filename)); } read_cross_sections_xml(root.child("materials")); @@ -365,7 +361,7 @@ bool read_model_xml() { // Read geometry if (!check_for_node(root, "geometry")) { fatal_error(fmt::format( - "No node present in the model.xml_file.", xml_filename)); + "No node present in the model.xml_file.", model_filename)); } read_geometry_xml(root.child("geometry")); diff --git a/src/settings.cpp b/src/settings.cpp index 3048862e3..74d45543d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -222,7 +222,8 @@ void read_settings_xml() { fmt::format("Settings XML file '{}' does not exist! In order " "to run OpenMC, you first need a set of input files; at a " "minimum, this " - "includes settings.xml, geometry.xml, and materials.xml. " + "includes settings.xml, geometry.xml, and materials.xml " + "or a single XML file containing all of these files. " "Please consult " "the user's guide at https://docs.openmc.org for further " "information.", From 574845b18b1de2d2fa9fa8415d7770e18d411bd6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 13:09:04 -0600 Subject: [PATCH 1378/2654] Moving Model.from_separate_xmls back to Model.from_xml. --- openmc/model/model.py | 78 +++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 52 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 6ca6f72b6..34cc085b8 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -205,30 +205,40 @@ class Model: self._plots.append(plot) @classmethod - def from_xml(cls, *args, separate_xmls=True, **kwargs): - """Generate geometry from XML file + def from_xml(cls, geometry='geometry.xml', materials='materials.xml', + settings='settings.xml', tallies='tallies.xml', + plots='plots.xml'): + """Create model from existing XML files Parameters ---------- - args : list - Positional arguments to be forwarded to - :func:`Model.from_separate_xmls` or :func:`Model.from_model_xml`. - separate_xmls : bool - Whether or not to read from a single or separate XML files. - kwargs : dict, optional - Keyword arguments to be forwarded to - :func:`Model.from_separate_xmls` or :func:`Model.from_model_xml`. + geometry : str + Path to geometry.xml file + materials : str + Path to materials.xml file + settings : str + Path to settings.xml file + tallies : str + Path to tallies.xml file + + .. versionadded:: 0.13.0 + plots : str + Path to plots.xml file + + .. versionadded:: 0.13.0 Returns ------- - openmc.Geometry - Geometry object + openmc.model.Model + Model created from XML files """ - if separate_xmls: - return cls.from_separate_xmls(*args, **kwargs) - else: - return cls.from_model_xml(*args, **kwargs) + materials = openmc.Materials.from_xml(materials) + geometry = openmc.Geometry.from_xml(geometry, materials) + settings = openmc.Settings.from_xml(settings) + tallies = openmc.Tallies.from_xml(tallies) if Path(tallies).exists() else None + plots = openmc.Plots.from_xml(plots) if Path(plots).exists() else None + return cls(geometry, materials, settings, tallies, plots) @classmethod def from_model_xml(cls, path='model.xml'): @@ -265,42 +275,6 @@ class Model: return model - @classmethod - def from_separate_xmls(cls, geometry='geometry.xml', materials='materials.xml', - settings='settings.xml', tallies='tallies.xml', - plots='plots.xml'): - """Create model from existing XML files - - Parameters - ---------- - geometry : str - Path to geometry.xml file - materials : str - Path to materials.xml file - settings : str - Path to settings.xml file - tallies : str - Path to tallies.xml file - - .. versionadded:: 0.13.0 - plots : str - Path to plots.xml file - - .. versionadded:: 0.13.0 - - Returns - ------- - openmc.model.Model - Model created from XML files - - """ - materials = openmc.Materials.from_xml(materials) - geometry = openmc.Geometry.from_xml(geometry, materials) - settings = openmc.Settings.from_xml(settings) - tallies = openmc.Tallies.from_xml(tallies) if Path(tallies).exists() else None - plots = openmc.Plots.from_xml(plots) if Path(plots).exists() else None - return cls(geometry, materials, settings, tallies, plots) - def init_lib(self, threads=None, geometry_debug=False, restart_file=None, tracks=False, output=True, event_based=None, intracomm=None): """Initializes the model in memory via the C API From 270331aff956b95b1193e121c545345e64d3716c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 14:39:44 -0600 Subject: [PATCH 1379/2654] Adding function to check if a path is a directory --- include/openmc/file_utils.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/openmc/file_utils.h b/include/openmc/file_utils.h index f9c23468d..ae3a26e94 100644 --- a/include/openmc/file_utils.h +++ b/include/openmc/file_utils.h @@ -3,15 +3,31 @@ #include // for ifstream #include +#include namespace openmc { +// TODO: replace with std::filesysem when switch to C++17 is made +//! Determine if a path is a directory +//! \param[in] path Path to check +//! \return Whether the path is a directory +inline bool is_dir(const std::string& path) { + struct stat s; + if (stat(path.c_str(), &s) != 0) return false; + + return s.st_mode & S_IFDIR; +} + //! Determine if a file exists //! \param[in] filename Path to file //! \return Whether file exists inline bool file_exists(const std::string& filename) { + // rule out file being a directory path + if (is_dir(filename)) return false; + std::ifstream s {filename}; + s.seekg(0, std::ios::beg); return s.good(); } From bc1791d367b307656ce31bdfdf7c4b794def44ad Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 14:40:02 -0600 Subject: [PATCH 1380/2654] Updates to simplify model filename checking --- include/openmc/initialize.h | 2 -- src/initialize.cpp | 30 ++++++++++++++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h index c37208e5e..a9b8b336f 100644 --- a/include/openmc/initialize.h +++ b/include/openmc/initialize.h @@ -21,8 +21,6 @@ void read_separate_xml_files(); //! Write some output that occurs right after initialization void initial_output(); - -std::string args_xml_filename {}; } // namespace openmc #endif // OPENMC_INITIALIZE_H diff --git a/src/initialize.cpp b/src/initialize.cpp index c0333e01c..b75f410a1 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -282,7 +282,12 @@ int parse_command_line(int argc, char* argv[]) if (argc > 1 && last_flag < argc - 1) { settings::path_input = std::string(argv[last_flag + 1]); - // Add slash at end of directory if it isn't there + // check that the path is either a valid directory or file + if (!is_dir(settings::path_input) && !file_exists(settings::path_input)) { + fatal_error(fmt::format("The specified path '{}' does not exist.", settings::path_input)); + } + + // Add slash at end of directory if it isn't the if (!ends_with(settings::path_input, "/")) { settings::path_input += "/"; } @@ -294,13 +299,17 @@ int parse_command_line(int argc, char* argv[]) bool read_model_xml() { std::string model_filename = settings::path_input; - // if the path input isn't an existing file, assume its a directory - // and append the default model.xml filename - if (!file_exists(settings::path_input)) { - model_filename += "/model.xml"; - if (!file_exists(model_filename)) - return false; - } + // some string cleanup + // a trailing "/" is applied to path_input if it's present, + // remove it for the first attempt at reading the input file + if (ends_with(model_filename, "/")) model_filename.pop_back(); + if (model_filename.length() == 0) model_filename = "."; + + // if the current filename is a directory, append the default model filename + if (is_dir(model_filename)) model_filename += "/model.xml"; + + // if this file doesn't exist, stop here + if (!file_exists(model_filename)) return false; // try to process the path input as an XML file pugi::xml_document doc; @@ -330,10 +339,7 @@ bool read_model_xml() { title(); } - if (!args_xml_filename.empty()) - write_message(fmt::format("Reaging user-specified input '{}'...", args_xml_filename), 5); - else - write_message("Reading model XML file...", 5); + write_message(fmt::format("Reading model XML file '{}' ...", model_filename), 5); read_settings_xml(settings_root); From 5634d8318ad110ee20f79d69ab277f7134a0d277 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 14:40:59 -0600 Subject: [PATCH 1381/2654] Changing name of input argument for Python executor --- openmc/executor.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index b14313213..9267366e8 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -9,7 +9,7 @@ from .plots import _get_plot_image def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, plot=False, restart_file=None, threads=None, tracks=False, event_based=None, - openmc_exec='openmc', mpi_args=None, input_file=None): + openmc_exec='openmc', mpi_args=None, path_input=None): """Converts user-readable flags in to command-line arguments to be run with the OpenMC executable via subprocess. @@ -42,7 +42,7 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, mpi_args : list of str, optional MPI execute command and any additional MPI arguments to pass, e.g. ['mpiexec', '-n', '8']. - input_file : str or Pathlike + path_input : str or Pathlike Name of a single XML input file for the OpenMC executable to read. .. versionadded:: 0.13.0 @@ -84,8 +84,8 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, if mpi_args is not None: args = mpi_args + args - if input_file is not None: - args += ['-i', input_file] + if path_input is not None: + args += [path_input] return args @@ -95,6 +95,7 @@ def _run(args, output, cwd): p = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) + print(args) # Capture and re-print OpenMC output in real-time lines = [] while True: @@ -123,7 +124,7 @@ def _run(args, output, cwd): raise RuntimeError(error_msg) -def plot_geometry(output=True, openmc_exec='openmc', cwd='.', input_file=None): +def plot_geometry(output=True, openmc_exec='openmc', cwd='.', path_input=None): """Run OpenMC in plotting mode Parameters @@ -134,7 +135,7 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.', input_file=None): Path to OpenMC executable cwd : str, optional Path to working directory to run in - input_file : str + path_input : str Name of a single XML input file for the OpenMC executable to read. Raises @@ -144,12 +145,12 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.', input_file=None): """ args = [openmc_exec, '-p'] - if input_file is not None: - args += ['-i', input_file] + if path_input is not None: + args += ['-i', path_input] _run([openmc_exec, '-p'], output, cwd) -def plot_inline(plots, openmc_exec='openmc', cwd='.', input_file=None): +def plot_inline(plots, openmc_exec='openmc', cwd='.', path_input=None): """Display plots inline in a Jupyter notebook. .. versionchanged:: 0.13.0 @@ -165,7 +166,7 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', input_file=None): Path to OpenMC executable cwd : str, optional Path to working directory to run in - input_file : str + path_input : str Name of a single XML input file for the OpenMC executable to read. Raises @@ -183,7 +184,7 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', input_file=None): openmc.Plots(plots).export_to_xml(cwd) # Run OpenMC in geometry plotting mode - plot_geometry(False, openmc_exec, cwd, input_file) + plot_geometry(False, openmc_exec, cwd, path_input) if plots is not None: images = [_get_plot_image(p, cwd) for p in plots] @@ -192,7 +193,7 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', input_file=None): def calculate_volumes(threads=None, output=True, cwd='.', openmc_exec='openmc', mpi_args=None, - input_file=None): + path_input=None): """Run stochastic volume calculations in OpenMC. This function runs OpenMC in stochastic volume calculation mode. To specify @@ -223,7 +224,7 @@ def calculate_volumes(threads=None, output=True, cwd='.', cwd : str, optional Path to working directory to run in. Defaults to the current working directory. - input_file : str or Pathlike + path_input : str or Pathlike Name of a single XML input file for the OpenMC executable to read. Raises @@ -239,7 +240,7 @@ def calculate_volumes(threads=None, output=True, cwd='.', args = _process_CLI_arguments(volume=True, threads=threads, openmc_exec=openmc_exec, mpi_args=mpi_args, - input_file=input_file) + path_input=path_input) _run(args, output, cwd) @@ -247,7 +248,7 @@ def calculate_volumes(threads=None, output=True, cwd='.', def run(particles=None, threads=None, geometry_debug=False, restart_file=None, tracks=False, output=True, cwd='.', openmc_exec='openmc', mpi_args=None, event_based=False, - input_file=None): + path_input=None): """Run an OpenMC simulation. Parameters @@ -282,7 +283,7 @@ def run(particles=None, threads=None, geometry_debug=False, .. versionadded:: 0.12 - input_file : str or Pathlike + path_input : str or Pathlike Name of a single XML input file for the OpenMC executable to read. Raises @@ -296,6 +297,6 @@ def run(particles=None, threads=None, geometry_debug=False, volume=False, geometry_debug=geometry_debug, particles=particles, restart_file=restart_file, threads=threads, tracks=tracks, event_based=event_based, openmc_exec=openmc_exec, mpi_args=mpi_args, - input_file=input_file) + path_input=path_input) _run(args, output, cwd) From d639d1dc1b2796e9fae599d74283b9f125e3801a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 14:41:11 -0600 Subject: [PATCH 1382/2654] Docstring correction --- openmc/model/model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 34cc085b8..a7a6f2d7d 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -450,7 +450,6 @@ class Model: Path to an output filename or directory. Only used if :math:`separate_xmls` is False. .. versionadded:: 0.13.1 - separate_xmls : bool Whether or not to write a single model.xml file or many XML files. """ From 939adbe70e2c73e2d503260bc5a912812d1b0087 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 14:41:26 -0600 Subject: [PATCH 1383/2654] Updating tests to reflect changes to API --- tests/regression_tests/model_xml/test.py | 12 +++++++++--- tests/unit_tests/test_model.py | 14 +++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 9da5438db..8aa9e5c2e 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -1,6 +1,8 @@ from difflib import unified_diff +import glob import filecmp import os +from pathlib import Path import openmc import pytest @@ -83,13 +85,17 @@ def test_input_arg(run_in_tmpdir): pincell.export_to_xml(separate_xmls=True) openmc.run() + # make sure the executable isn't falling back on the separate XMLs + [os.remove(f) for f in glob.glob('*.xml')] # now export to a single XML file with a custom name - pincell.export_to_xml(filename='pincell.xml', separate_xmls=False) + pincell.export_to_xml(path='pincell.xml', separate_xmls=False) + assert Path('pincell.xml').exists() # run by specifying that single file - openmc.run(input_file='pincell.xml') + openmc.run(path_input='pincell.xml') # now ensure we get an error for an incorrect filename, # even in the presence of other, valid XML files + pincell.export_to_xml(separate_xmls=True) with pytest.raises(RuntimeError, match='ex-em-ell.xml'): - openmc.run(input_file='ex-em-ell.xml') \ No newline at end of file + openmc.run(path_input='ex-em-ell.xml') \ No newline at end of file diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 5d4765d65..11a88d76c 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -543,7 +543,7 @@ def test_model_xml(run_in_tmpdir): # now write and read a model.xml file pwr_model.export_to_xml(separate_xmls=False) - new_model = openmc.Model.from_xml(separate_xmls=False) + new_model = openmc.Model.from_model_xml() # make sure we can also export this again to separate # XML files @@ -553,17 +553,17 @@ def test_model_exec(run_in_tmpdir): pincell_model = openmc.examples.pwr_pin_cell() - pincell_model.export_to_xml(filename='pwr_pincell.xml', separate_xmls=False) + pincell_model.export_to_xml(path='pwr_pincell.xml', separate_xmls=False) - openmc.run(input_file='pwr_pincell.xml') + openmc.run(path_input='pwr_pincell.xml') with pytest.raises(RuntimeError, match='ex-em-ell.xml'): - openmc.run(input_file='ex-em-ell.xml') + openmc.run(path_input='ex-em-ell.xml') # test that a file in a different directory can be used os.mkdir('inputs') - pincell_model.export_to_xml(directory='./inputs', filename='pincell.xml', separate_xmls=False) - openmc.run(input_file='./inputs/pincell.xml') + pincell_model.export_to_xml(path='./inputs/pincell.xml', separate_xmls=False) + openmc.run(path_input='./inputs/pincell.xml') with pytest.raises(RuntimeError, match='input_dir'): - openmc.run(input_file='input_dir/pincell.xml') \ No newline at end of file + openmc.run(path_input='input_dir/pincell.xml') \ No newline at end of file From 7fdfed22f37e2c50913ba96adce55da98daf4c40 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 21:49:46 -0600 Subject: [PATCH 1384/2654] Some cleanup of file utils --- include/openmc/file_utils.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/openmc/file_utils.h b/include/openmc/file_utils.h index ae3a26e94..439af6ee0 100644 --- a/include/openmc/file_utils.h +++ b/include/openmc/file_utils.h @@ -7,7 +7,7 @@ namespace openmc { -// TODO: replace with std::filesysem when switch to C++17 is made +// TODO: replace with std::filesystem when switch to C++17 is made //! Determine if a path is a directory //! \param[in] path Path to check //! \return Whether the path is a directory @@ -27,7 +27,6 @@ inline bool file_exists(const std::string& filename) if (is_dir(filename)) return false; std::ifstream s {filename}; - s.seekg(0, std::ios::beg); return s.good(); } From 55d77cf06c86726d9ebaf7abcb8de232b01af505 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 21:50:08 -0600 Subject: [PATCH 1385/2654] Small improvements to read_model_xml --- src/initialize.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/initialize.cpp b/src/initialize.cpp index b75f410a1..041712d5a 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -284,7 +284,9 @@ int parse_command_line(int argc, char* argv[]) // check that the path is either a valid directory or file if (!is_dir(settings::path_input) && !file_exists(settings::path_input)) { - fatal_error(fmt::format("The specified path '{}' does not exist.", settings::path_input)); + fatal_error(fmt::format( + "The path specified to the OpenMC executable '{}' does not exist.", + settings::path_input)); } // Add slash at end of directory if it isn't the @@ -297,13 +299,14 @@ int parse_command_line(int argc, char* argv[]) } bool read_model_xml() { - std::string model_filename = settings::path_input; + std::string model_filename = + settings::path_input.empty() ? "." : settings::path_input; // some string cleanup - // a trailing "/" is applied to path_input if it's present, + // a trailing "/" is applied to path_input if it's specified, // remove it for the first attempt at reading the input file - if (ends_with(model_filename, "/")) model_filename.pop_back(); - if (model_filename.length() == 0) model_filename = "."; + if (ends_with(model_filename, "/")) + model_filename.pop_back(); // if the current filename is a directory, append the default model filename if (is_dir(model_filename)) model_filename += "/model.xml"; @@ -313,7 +316,6 @@ bool read_model_xml() { // try to process the path input as an XML file pugi::xml_document doc; - // if the input is a file, try to read it if (!doc.load_file(model_filename.c_str())) { fatal_error(fmt::format( "Error reading from single XML input file '{}'", model_filename)); From 7873b4d6c1bfb983a7ec4c87ad29b492d4bbb088 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 6 Dec 2022 21:50:49 -0600 Subject: [PATCH 1386/2654] Update tests/regression_tests/model_xml/test.py Co-authored-by: Paul Romano --- tests/regression_tests/model_xml/test.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 8aa9e5c2e..d040f4649 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -32,11 +32,6 @@ class ModelXMLTestHarness(PyAPITestHarness): def _get_inputs(self): return open('model.xml').read() - # def _compare_inputs(self): - # """Skip input comparisons for now - # """ - # pass - def _compare_results(self): """Make sure the current results agree with the reference.""" compare = filecmp.cmp('results_test.dat', self.results_true) From f2c28706a6eaf2206da5ff73867c279946b55f4b Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Wed, 7 Dec 2022 10:12:23 +0100 Subject: [PATCH 1387/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- CMakeLists.txt | 2 -- docs/source/usersguide/materials.rst | 14 ++++---- openmc/material.py | 43 +++++++++++++------------ tests/regression_tests/ncrystal/test.py | 29 ++++++++--------- tools/ci/gha-install.py | 4 +-- tools/ci/gha-script.sh | 6 ++-- 6 files changed, 47 insertions(+), 51 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2815230d4..5c4d489e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -497,8 +497,6 @@ if(OPENMC_USE_NCRYSTAL) target_link_libraries(libopenmc NCrystal::NCrystal) endif() - - #=============================================================================== # openmc executable #=============================================================================== diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index a3c05f421..fbf9effd8 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -101,19 +101,17 @@ you would need to add hydrogen and oxygen to a material and then assign the .. _usersguide_naming: ------------------- +------------------------- Adding NCrystal materials ------------------- +------------------------- Additional support for thermal scattering can be added by using NCrystal_. The :meth:`Material.from_ncrystal` class method generates a :class:`openmc.Material` object from an `NCrystal configuration string `_. -Temperature, material composition and density are passed from the configuration string +Temperature, material composition, and density are passed from the configuration string and the `NCMAT file `_ -that define the material, e.g: +that define the material, e.g.:: -:: - mat = openmc.Material.from_ncrystal('Al_sg225.ncmat;temp=300K') defines a material containing polycrystalline alumnium, @@ -126,12 +124,12 @@ defines a material containing polycrystalline alumnium, defines an oriented germanium single crystal with 40 arcsec mosaicity. -NCrystal only handles low energy neutron interactions. Other interaction are +NCrystal only handles low energy neutron interactions. Other interactions are provided by standard ACE files. NCrystal_ comes with a `predefined library `_ but more materials can be added by creating NCMAT files or on-the-fly in the configuration string. -.. warning:: Currently, NCrystal_ materials cannot be modified after created. +.. warning:: Currently, NCrystal_ materials cannot be modified after they are created. Density, temperature and composition should be defined in the configuration string or the NCMAT file. diff --git a/openmc/material.py b/openmc/material.py index de4a22cb8..298731c92 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -336,11 +336,12 @@ class Material(IDManagerMixin): @classmethod def from_ncrystal(cls, cfg, material_id=None, name=''): - """Create material from NCrystal configuration string. Density, - temperature, and material composition, and (ultimately) thermal neutron - scattering, will be automatically be provided by NCrystal based on this - string. The name and material_id parameters are simply passed on to the - Material constructor. + """Create material from NCrystal configuration string. + + Density, temperature, and material composition, and (ultimately) thermal + neutron scattering will be automatically be provided by NCrystal based + on this string. The name and material_id parameters are simply passed on + to the Material constructor. Parameters ---------- @@ -363,41 +364,41 @@ class Material(IDManagerMixin): import NCrystal nc_mat = NCrystal.createInfo(cfg) - def openmc_natabund( Z ): + def openmc_natabund(Z): #nc_mat.getFlattenedComposition might need natural abundancies. #This call-back function is used so NCrystal can flatten composition #using OpenMC's natural abundancies. In practice this function will #only get invoked in the unlikely case where a material is specified #by referring both to natural elements and specific isotopes of the #same element. - elem_name = openmc.data.ATOMIC_SYMBOL.get( Z, None ) + elem_name = openmc.data.ATOMIC_SYMBOL.get(Z) if not elem_name: raise ValueError( f'Element with Z={Z} is not known' ) - l = [] - for iso_name,abund in openmc.data.isotopes( elem_name ): - l.append( ( int(iso_name[ len(elem_name) : ]), abund ) ) - return l + return [ + (int(iso_name[len(elem_name):]), abund) + for iso_name, abund in openmc.data.isotopes(elem_name) + ] - flat_compos = nc_mat.getFlattenedComposition( preferNaturalElements = True, - naturalAbundProvider = openmc_natabund ) + flat_compos = nc_mat.getFlattenedComposition(preferNaturalElements = True, + naturalAbundProvider=openmc_natabund) # Create the Material - material = cls( material_id = material_id, - name = name, - temperature = nc_mat.getTemperature() ) + material = cls(material_id=material_id, + name=name, + temperature=nc_mat.getTemperature()) for Z, A_vals in flat_compos: - elemname = openmc.data.ATOMIC_SYMBOL.get(Z,None) + elemname = openmc.data.ATOMIC_SYMBOL.get(Z) if not elemname: raise ValueError(f'Element with Z={Z} is not known') for A, frac in A_vals: if A: - material.add_nuclide( elemname + str(A), frac, 'ao' ) + material.add_nuclide(f'{elemname}{A}', frac) else: - material.add_element( elemname, frac, 'ao' ) + material.add_element(elemname, frac) - material.set_density( 'g/cm3', nc_mat.getDensity() ) - material._ncrystal_cfg = NCrystal.normaliseCfg( cfg ) + material.set_density('g/cm3', nc_mat.getDensity()) + material._ncrystal_cfg = NCrystal.normaliseCfg(cfg) return material diff --git a/tests/regression_tests/ncrystal/test.py b/tests/regression_tests/ncrystal/test.py index 0a47d634d..3137515d4 100644 --- a/tests/regression_tests/ncrystal/test.py +++ b/tests/regression_tests/ncrystal/test.py @@ -10,7 +10,7 @@ pytestmark = pytest.mark.skipif( reason="NCrystal materials are not enabled.") def compute_angular_distribution(cfg, E0, N): - """Return a openmc.model.Model() object for a monoenergetic pencil + """Return an openmc.Model() object for a monoenergetic pencil beam hitting a 1 mm sphere filled with the material defined by the cfg string, and compute the angular distribution""" @@ -23,17 +23,16 @@ def compute_angular_distribution(cfg, E0, N): sample_sphere = openmc.Sphere(r=0.1) outer_sphere = openmc.Sphere(r=100, boundary_type="vacuum") - cell1 = openmc.Cell(region= -sample_sphere, fill=m1) - cell2_region= +sample_sphere&-outer_sphere - cell2 = openmc.Cell(region= cell2_region, fill=None) - uni1 = openmc.Universe(cells=[cell1, cell2]) - geometry = openmc.Geometry(uni1) + cell1 = openmc.Cell(region=-sample_sphere, fill=m1) + cell2_region= +sample_sphere & -outer_sphere + cell2 = openmc.Cell(region=cell2_region, fill=None) + geometry = openmc.Geometry([cell1, cell2]) # Source definition source = openmc.Source() - source.space = openmc.stats.Point(xyz = (0,0,-20)) - source.angle = openmc.stats.Monodirectional(reference_uvw = (0,0,1)) + source.space = openmc.stats.Point((0, 0, -20)) + source.angle = openmc.stats.Monodirectional(reference_uvw=(0, 0, 1)) source.energy = openmc.stats.Discrete([E0], [1.0]) # Execution settings @@ -48,13 +47,13 @@ def compute_angular_distribution(cfg, E0, N): tally1 = openmc.Tally(name="angular distribution") tally1.scores = ["current"] - filter1 = openmc.filter.SurfaceFilter(sample_sphere) - filter2 = openmc.filter.PolarFilter(np.linspace(0,np.pi,180+1)) - filter3 = openmc.filter.CellFromFilter(cell1) + filter1 = openmc.SurfaceFilter(sample_sphere) + filter2 = openmc.PolarFilter(np.linspace(0, np.pi, 180+1)) + filter3 = openmc.CellFromFilter(cell1) tally1.filters = [filter1, filter2, filter3] tallies = openmc.Tallies([tally1]) - return openmc.model.Model(geometry, materials, settings, tallies) + return openmc.Model(geometry, materials, settings, tallies) class NCrystalTest(PyAPITestHarness): @@ -62,9 +61,9 @@ class NCrystalTest(PyAPITestHarness): """Digest info in the statepoint and return as a string.""" # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - tal = sp.get_tally(name='angular distribution') - df = tal.get_pandas_dataframe() + with openmc.StatePoint(self._sp_name) as sp: + tal = sp.get_tally(name='angular distribution') + df = tal.get_pandas_dataframe() return df.to_string() def test_ncrystal(): diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index f5779c935..ac10bb3f6 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -56,8 +56,8 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, ncrys if ncrystal: cmake_cmd.append('-DOPENMC_USE_NCRYSTAL=ON') - ncrystal_cmake_path = os.environ.get('HOME')+'/ncrystal_inst/lib/cmake' - cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + ncrystal_cmake_path) + ncrystal_cmake_path = os.environ.get('HOME') + '/ncrystal_inst/lib/cmake' + cmake_cmd.append(f'-DCMAKE_PREFIX_PATH={ncrystal_cmake_path}') # Build in coverage mode for coverage testing cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') diff --git a/tools/ci/gha-script.sh b/tools/ci/gha-script.sh index 85fdef49f..1f1c3a1eb 100755 --- a/tools/ci/gha-script.sh +++ b/tools/ci/gha-script.sh @@ -16,9 +16,9 @@ fi # Check NCrystal installation if [[ $NCRYSTAL = 'y' ]]; then - # Change environmental variables - eval $( "${HOME}/ncrystal_inst/bin/ncrystal-config" --setup ) - nctool --test + # Change environmental variables + eval $( "${HOME}/ncrystal_inst/bin/ncrystal-config" --setup ) + nctool --test fi # Run regression and unit tests From a86e74f59a27236a4705ab0b4dc8c79736cd2c56 Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Wed, 7 Dec 2022 12:51:31 +0100 Subject: [PATCH 1388/2654] Rename compute_angular_distribution to pencil_beam_model --- tests/regression_tests/ncrystal/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/ncrystal/test.py b/tests/regression_tests/ncrystal/test.py index 3137515d4..2a789dac7 100644 --- a/tests/regression_tests/ncrystal/test.py +++ b/tests/regression_tests/ncrystal/test.py @@ -9,7 +9,7 @@ pytestmark = pytest.mark.skipif( not openmc.lib._ncrystal_enabled(), reason="NCrystal materials are not enabled.") -def compute_angular_distribution(cfg, E0, N): +def pencil_beam_model(cfg, E0, N): """Return an openmc.Model() object for a monoenergetic pencil beam hitting a 1 mm sphere filled with the material defined by the cfg string, and compute the angular distribution""" @@ -71,6 +71,6 @@ def test_ncrystal(): T = 293.6 # K E0 = 0.012 # eV cfg = 'Al_sg225.ncmat' - test = compute_angular_distribution(cfg, E0, NParticles) + test = pencil_beam_model(cfg, E0, NParticles) harness = NCrystalTest('statepoint.10.h5', model=test) harness.main() From ef13643f297dfe030c644d7a776fd85be54afdaa Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 7 Dec 2022 08:28:13 -0600 Subject: [PATCH 1389/2654] Some housekeeping in the Python classes --- openmc/model/model.py | 8 ++------ openmc/settings.py | 38 ++++++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index a7a6f2d7d..1fdd12730 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -496,13 +496,10 @@ class Model: self.plots.export_to_xml(d) def _export_to_single_xml(self, path='model.xml', remove_surfs=False): - """Export model to XML files. + """Export model to a single XML file. Parameters ---------- - directory : str - Directory to write the model.xml file to. If it doesn't exist already, it - will be created. path : str or Pathlike Location of the XML file to write. Can be a directory or file path. remove_surfs : bool @@ -530,8 +527,7 @@ class Model: # Can be used to modify tallies in case any surfaces are redundant redundant_surfaces = self.geometry.remove_redundant_surfaces() - memo = set() - settings_element = self.settings.to_xml_element(memo) + settings_element = self.settings.to_xml_element() geometry_element = self.geometry.to_xml_element() xml.clean_indentation(geometry_element, level=1) diff --git a/openmc/settings.py b/openmc/settings.py index 3c1c8c7f5..3f56f729f 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1073,7 +1073,7 @@ class Settings: subelement = ET.SubElement(element, key) subelement.text = str(value) - def _create_entropy_mesh_subelement(self, root, memo=None): + def _create_entropy_mesh_subelement(self, root, mesh_memo=None): if self.entropy_mesh is not None: # use default heuristic for entropy mesh if not set by user if self.entropy_mesh.dimension is None: @@ -1085,13 +1085,20 @@ class Settings: d = len(self.entropy_mesh.lower_left) self.entropy_mesh.dimension = (n,)*d + # add mesh ID to this element + subelement = ET.SubElement(root, "entropy_mesh") + subelement.text = str(self.entropy_mesh.id) + + # If this mesh has already been written outside the + # settings element, skip writing it again + if mesh_memo and self.entropy_mesh.id in mesh_memo: + return + # See if a element already exists -- if not, add it path = f"./mesh[@id='{self.entropy_mesh.id}']" if root.find(path) is None: root.append(self.entropy_mesh.to_xml_element()) - - subelement = ET.SubElement(root, "entropy_mesh") - subelement.text = str(self.entropy_mesh.id) + if mesh_memo is not None: mesh_memo.add(self.entropy_mesh.id) def _create_trigger_subelement(self, root): if self._trigger_active is not None: @@ -1207,20 +1214,21 @@ class Settings: elem = ET.SubElement(root, "write_initial_source") elem.text = str(self._write_initial_source).lower() - def _create_weight_windows_subelement(self, root, memo=None): + def _create_weight_windows_subelement(self, root, mesh_memo=None): for ww in self._weight_windows: # Add weight window information root.append(ww.to_xml_element()) - # check the memo for a mesh - if memo and ww.mesh.id in memo: + # if this mesh has already been written, + # skip writing the mesh element + if mesh_memo and ww.mesh.id in mesh_memo: continue # See if a element already exists -- if not, add it path = f"./mesh[@id='{ww.mesh.id}']" if root.find(path) is None: root.append(ww.mesh.to_xml_element()) - if memo is not None: memo.add(ww.mesh.id) + if mesh_memo is not None: mesh_memo.add(ww.mesh.id) if self._weight_windows_on is not None: elem = ET.SubElement(root, "weight_windows_on") @@ -1544,10 +1552,16 @@ class Settings: if text is not None: self.max_tracks = int(text) - def to_xml_element(self, memo=None): + def to_xml_element(self, mesh_memo=None): """Create a 'settings' element to be written to an XML file. - """ + Parameters + ---------- + mesh_memo : set of ints + A set of mesh IDs to keep track of whether a mesh has already been written. + """ + # create a memo object if one isn't passed in already + mesh_memo = mesh_memo if mesh_memo else set() # Reset xml element tree element = ET.Element("settings") @@ -1574,7 +1588,7 @@ class Settings: self._create_seed_subelement(element) self._create_survival_biasing_subelement(element) self._create_cutoff_subelement(element) - self._create_entropy_mesh_subelement(element, memo) + self._create_entropy_mesh_subelement(element, mesh_memo) self._create_trigger_subelement(element) self._create_no_reduce_subelement(element) self._create_verbosity_subelement(element) @@ -1592,7 +1606,7 @@ class Settings: self._create_material_cell_offsets_subelement(element) self._create_log_grid_bins_subelement(element) self._create_write_initial_source_subelement(element) - self._create_weight_windows_subelement(element, memo) + self._create_weight_windows_subelement(element, mesh_memo) self._create_max_splits_subelement(element) self._create_max_tracks_subelement(element) From 9c942db45eaca790dc0f7f142b801381d2574daa Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 7 Dec 2022 10:10:22 -0600 Subject: [PATCH 1390/2654] Correct use of mesh memo in single XML export --- openmc/model/model.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 1fdd12730..a54cd6076 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -527,7 +527,9 @@ class Model: # Can be used to modify tallies in case any surfaces are redundant redundant_surfaces = self.geometry.remove_redundant_surfaces() - settings_element = self.settings.to_xml_element() + # provide a memo to track which meshes have been written + mesh_memo = set() + settings_element = self.settings.to_xml_element(mesh_memo) geometry_element = self.geometry.to_xml_element() xml.clean_indentation(geometry_element, level=1) @@ -554,7 +556,7 @@ class Model: ET.ElementTree(settings_element).write(fh, encoding='unicode') if self.tallies: - tallies_element = self.tallies.to_xml_element(memo) + tallies_element = self.tallies.to_xml_element(mesh_memo) xml.clean_indentation(tallies_element, level=1, trailing_indent=self.plots) ET.ElementTree(tallies_element).write(fh, encoding='unicode') if self.plots: From 916863f82ae304ff6f936701cbb058c5e7c2583a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 7 Dec 2022 11:02:10 -0600 Subject: [PATCH 1391/2654] Renaming and docstring/comment updates --- include/openmc/file_utils.h | 8 +++++--- include/openmc/geometry_aux.h | 2 +- openmc/settings.py | 2 -- src/initialize.cpp | 6 ++++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/openmc/file_utils.h b/include/openmc/file_utils.h index 439af6ee0..cb52b33c8 100644 --- a/include/openmc/file_utils.h +++ b/include/openmc/file_utils.h @@ -11,7 +11,8 @@ namespace openmc { //! Determine if a path is a directory //! \param[in] path Path to check //! \return Whether the path is a directory -inline bool is_dir(const std::string& path) { +inline bool dir_exists(const std::string& path) +{ struct stat s; if (stat(path.c_str(), &s) != 0) return false; @@ -23,8 +24,9 @@ inline bool is_dir(const std::string& path) { //! \return Whether file exists inline bool file_exists(const std::string& filename) { - // rule out file being a directory path - if (is_dir(filename)) return false; + // rule out file being a path to a directory + if (dir_exists(filename)) + return false; std::ifstream s {filename}; return s.good(); diff --git a/include/openmc/geometry_aux.h b/include/openmc/geometry_aux.h index a4c506c31..cf62debc0 100644 --- a/include/openmc/geometry_aux.h +++ b/include/openmc/geometry_aux.h @@ -24,7 +24,7 @@ extern std::unordered_map universe_level_counts; void read_geometry_xml(); //! Read geometry from XML node -//! \param[in] root node of geometry XML element +//! \param[in] root node of geometry XML element void read_geometry_xml(pugi::xml_node root); //============================================================================== diff --git a/openmc/settings.py b/openmc/settings.py index 3f56f729f..294aea7a3 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1560,8 +1560,6 @@ class Settings: mesh_memo : set of ints A set of mesh IDs to keep track of whether a mesh has already been written. """ - # create a memo object if one isn't passed in already - mesh_memo = mesh_memo if mesh_memo else set() # Reset xml element tree element = ET.Element("settings") diff --git a/src/initialize.cpp b/src/initialize.cpp index 041712d5a..3b332c3b2 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -283,7 +283,8 @@ int parse_command_line(int argc, char* argv[]) settings::path_input = std::string(argv[last_flag + 1]); // check that the path is either a valid directory or file - if (!is_dir(settings::path_input) && !file_exists(settings::path_input)) { + if (!dir_exists(settings::path_input) && + !file_exists(settings::path_input)) { fatal_error(fmt::format( "The path specified to the OpenMC executable '{}' does not exist.", settings::path_input)); @@ -309,7 +310,8 @@ bool read_model_xml() { model_filename.pop_back(); // if the current filename is a directory, append the default model filename - if (is_dir(model_filename)) model_filename += "/model.xml"; + if (dir_exists(model_filename)) + model_filename += "/model.xml"; // if this file doesn't exist, stop here if (!file_exists(model_filename)) return false; From 145594ebb8697ff2c711b6a8f57abbfedfebf8c7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 12 Dec 2022 20:23:49 -0600 Subject: [PATCH 1392/2654] Apply @paulromano suggestions from code review Co-authored-by: Paul Romano --- openmc/_xml.py | 2 +- openmc/executor.py | 3 +-- openmc/material.py | 1 - openmc/model/model.py | 2 +- src/initialize.cpp | 4 ++-- tests/regression_tests/model_xml/test.py | 3 ++- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/openmc/_xml.py b/openmc/_xml.py index 6d298638d..aeaeb45b5 100644 --- a/openmc/_xml.py +++ b/openmc/_xml.py @@ -16,7 +16,7 @@ def clean_indentation(element, level=0, spaces_per_level=2, trailing_indent=True """ i = "\n" + level*spaces_per_level*" " - # ensure there's awlays some tail for the element passed in + # ensure there's always some tail for the element passed in if not element.tail: element.tail = "" diff --git a/openmc/executor.py b/openmc/executor.py index 9267366e8..38421ecc2 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -95,7 +95,6 @@ def _run(args, output, cwd): p = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) - print(args) # Capture and re-print OpenMC output in real-time lines = [] while True: @@ -146,7 +145,7 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.', path_input=None): """ args = [openmc_exec, '-p'] if path_input is not None: - args += ['-i', path_input] + args += [path_input] _run([openmc_exec, '-p'], output, cwd) diff --git a/openmc/material.py b/openmc/material.py index 332f8c965..aa778cab6 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1548,7 +1548,6 @@ class Materials(cv.CheckedList): return materials - @classmethod def from_xml(cls, path: PathLike = 'materials.xml'): """Generate materials collection from XML file diff --git a/openmc/model/model.py b/openmc/model/model.py index a54cd6076..9983d5c60 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -259,7 +259,7 @@ class Model: materials = {str(m.id): m for m in model.materials} model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), materials) - # gather meshses from other classes before reading the tally node + # gather meshes from other classes before reading the tally node meshes = {} if model.settings.entropy_mesh is not None: meshes[model.settings.entropy_mesh.id] = model.settings.entropy_mesh diff --git a/src/initialize.cpp b/src/initialize.cpp index 3b332c3b2..0c137795b 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -352,7 +352,7 @@ bool read_model_xml() { auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; for (const auto& input : other_inputs) { if (file_exists(settings::path_input + input)) { - warning((fmt::format("Other XML file input(s) are present. These file " + warning((fmt::format("Other XML file input(s) are present. These files " "will be ignored in favor of the {} file.", model_filename))); break; @@ -371,7 +371,7 @@ bool read_model_xml() { // Read geometry if (!check_for_node(root, "geometry")) { fatal_error(fmt::format( - "No node present in the model.xml_file.", model_filename)); + "No node present in the {} file.", model_filename)); } read_geometry_xml(root.child("geometry")); diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index d040f4649..fbff02357 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -81,7 +81,8 @@ def test_input_arg(run_in_tmpdir): openmc.run() # make sure the executable isn't falling back on the separate XMLs - [os.remove(f) for f in glob.glob('*.xml')] + for f in glob.glob('*.xml'): + os.remove(f) # now export to a single XML file with a custom name pincell.export_to_xml(path='pincell.xml', separate_xmls=False) assert Path('pincell.xml').exists() From f3bcad37b72629cfc64e857aebdbe7c38461cabb Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 12 Dec 2022 21:18:48 -0600 Subject: [PATCH 1393/2654] Addressing comments from @paulromano --- openmc/executor.py | 32 ++++++----- openmc/geometry.py | 19 ++++--- openmc/model/model.py | 33 ++---------- openmc/settings.py | 68 +++++++++++++----------- tests/regression_tests/model_xml/test.py | 11 ++-- tests/unit_tests/test_model.py | 10 ++-- 6 files changed, 85 insertions(+), 88 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index 38421ecc2..22862a7cf 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -43,7 +43,8 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, MPI execute command and any additional MPI arguments to pass, e.g. ['mpiexec', '-n', '8']. path_input : str or Pathlike - Name of a single XML input file for the OpenMC executable to read. + Path to a single XML file or a directory containing XML files for the + OpenMC executable to read. .. versionadded:: 0.13.0 @@ -135,7 +136,8 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.', path_input=None): cwd : str, optional Path to working directory to run in path_input : str - Name of a single XML input file for the OpenMC executable to read. + Path to a single XML file or a directory containing XML files for the + OpenMC executable to read. Raises ------ @@ -146,7 +148,7 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.', path_input=None): args = [openmc_exec, '-p'] if path_input is not None: args += [path_input] - _run([openmc_exec, '-p'], output, cwd) + _run(args, output, cwd) def plot_inline(plots, openmc_exec='openmc', cwd='.', path_input=None): @@ -166,7 +168,8 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', path_input=None): cwd : str, optional Path to working directory to run in path_input : str - Name of a single XML input file for the OpenMC executable to read. + Path to a single XML file or a directory containing XML files for the + OpenMC executable to read. Raises ------ @@ -224,7 +227,9 @@ def calculate_volumes(threads=None, output=True, cwd='.', Path to working directory to run in. Defaults to the current working directory. path_input : str or Pathlike - Name of a single XML input file for the OpenMC executable to read. + Path to a single XML file or a directory containing XML files for the + OpenMC executable to read. + Raises ------ @@ -256,17 +261,17 @@ def run(particles=None, threads=None, geometry_debug=False, Number of particles to simulate per generation. threads : int, optional Number of OpenMP threads. If OpenMC is compiled with OpenMP threading - enabled, the default is implementation-dependent but is usually equal - to the number of hardware threads available (or a value set by the + enabled, the default is implementation-dependent but is usually equal to + the number of hardware threads available (or a value set by the :envvar:`OMP_NUM_THREADS` environment variable). geometry_debug : bool, optional Turn on geometry debugging during simulation. Defaults to False. restart_file : str, optional Path to restart file to use tracks : bool, optional - Enables the writing of particles tracks. The number of particle - tracks written to tracks.h5 is limited to 1000 unless - Settings.max_tracks is set. Defaults to False. + Enables the writing of particles tracks. The number of particle tracks + written to tracks.h5 is limited to 1000 unless Settings.max_tracks is + set. Defaults to False. output : bool Capture OpenMC output from standard out cwd : str, optional @@ -275,15 +280,16 @@ def run(particles=None, threads=None, geometry_debug=False, openmc_exec : str, optional Path to OpenMC executable. Defaults to 'openmc'. mpi_args : list of str, optional - MPI execute command and any additional MPI arguments to pass, - e.g. ['mpiexec', '-n', '8']. + MPI execute command and any additional MPI arguments to pass, e.g. + ['mpiexec', '-n', '8']. event_based : bool, optional Turns on event-based parallelism, instead of default history-based .. versionadded:: 0.12 path_input : str or Pathlike - Name of a single XML input file for the OpenMC executable to read. + Path to a single XML file or a directory containing XML files for the + OpenMC executable to read. Raises ------ diff --git a/openmc/geometry.py b/openmc/geometry.py index afcae1d55..a43899daa 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -179,6 +179,11 @@ class Geometry: Geometry object """ + mats = dict() + if materials is not None: + mats.update({str(m.id): m for m in materials}) + mats['void'] = None + # Helper function for keeping a cache of Universe instances universes = {} def get_universe(univ_id): @@ -236,7 +241,7 @@ class Geometry: child_of[u].append(lat) for e in elem.findall('cell'): - c = openmc.Cell.from_xml_element(e, surfaces, materials, get_universe) + c = openmc.Cell.from_xml_element(e, surfaces, mats, get_universe) if c.fill_type in ('universe', 'lattice'): child_of[c.fill].append(c) @@ -266,17 +271,15 @@ class Geometry: Geometry object """ - tree = ET.parse(path) - root = tree.getroot() - - # Create dictionary to easily look up materials + # Create dictionary to easily look up materials if materials is None: filename = Path(path).parent / 'materials.xml' materials = openmc.Materials.from_xml(str(filename)) - mats = {str(m.id): m for m in materials} - mats['void'] = None - return cls.from_xml_element(root, mats) + tree = ET.parse(path) + root = tree.getroot() + + return cls.from_xml_element(root, materials) def find(self, point): """Find cells/universes/lattices which contain a given point diff --git a/openmc/model/model.py b/openmc/model/model.py index 9983d5c60..a8dc1ce48 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -256,8 +256,7 @@ class Model: model.settings = openmc.Settings.from_xml_element(root.find('settings')) model.materials = openmc.Materials.from_xml_element(root.find('materials')) - materials = {str(m.id): m for m in model.materials} - model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), materials) + model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) # gather meshes from other classes before reading the tally node meshes = {} @@ -435,30 +434,7 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True, path='model.xml'): - """Export model to an XML file(s). - - Parameters - ---------- - directory : str - Directory to write XML files to. If it doesn't exist already, it - will be created. Only used if :math:`separate_xmls` is True. - remove_surfs : bool - Whether or not to remove redundant surfaces from the geometry when - exporting. - path : str - Path to an output filename or directory. Only used if :math:`separate_xmls` is False. - - .. versionadded:: 0.13.1 - separate_xmls : bool - Whether or not to write a single model.xml file or many XML files. - """ - if separate_xmls: - self._export_to_separate_xmls(directory, remove_surfs) - else: - self._export_to_single_xml(path, remove_surfs) - - def _export_to_separate_xmls(self, directory='.', remove_surfs=False): + def export_to_xml(self, directory='.', remove_surfs=False): """Export model to separate XML files. Parameters @@ -495,13 +471,14 @@ class Model: if self.plots: self.plots.export_to_xml(d) - def _export_to_single_xml(self, path='model.xml', remove_surfs=False): + def export_to_model_xml(self, path='model.xml', remove_surfs=False): """Export model to a single XML file. Parameters ---------- path : str or Pathlike - Location of the XML file to write. Can be a directory or file path. + Location of the XML file to write (default is 'model.xml'). Can be a + directory or file path. remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when exporting. diff --git a/openmc/settings.py b/openmc/settings.py index 294aea7a3..8f6d3ec07 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1074,31 +1074,33 @@ class Settings: subelement.text = str(value) def _create_entropy_mesh_subelement(self, root, mesh_memo=None): - if self.entropy_mesh is not None: - # use default heuristic for entropy mesh if not set by user - if self.entropy_mesh.dimension is None: - if self.particles is None: - raise RuntimeError("Number of particles must be set in order to " \ - "use entropy mesh dimension heuristic") - else: - n = ceil((self.particles / 20.0)**(1.0 / 3.0)) - d = len(self.entropy_mesh.lower_left) - self.entropy_mesh.dimension = (n,)*d + if self.entropy_mesh is None: + return - # add mesh ID to this element - subelement = ET.SubElement(root, "entropy_mesh") - subelement.text = str(self.entropy_mesh.id) + # use default heuristic for entropy mesh if not set by user + if self.entropy_mesh.dimension is None: + if self.particles is None: + raise RuntimeError("Number of particles must be set in order to " \ + "use entropy mesh dimension heuristic") + else: + n = ceil((self.particles / 20.0)**(1.0 / 3.0)) + d = len(self.entropy_mesh.lower_left) + self.entropy_mesh.dimension = (n,)*d - # If this mesh has already been written outside the - # settings element, skip writing it again - if mesh_memo and self.entropy_mesh.id in mesh_memo: - return + # add mesh ID to this element + subelement = ET.SubElement(root, "entropy_mesh") + subelement.text = str(self.entropy_mesh.id) - # See if a element already exists -- if not, add it - path = f"./mesh[@id='{self.entropy_mesh.id}']" - if root.find(path) is None: - root.append(self.entropy_mesh.to_xml_element()) - if mesh_memo is not None: mesh_memo.add(self.entropy_mesh.id) + # If this mesh has already been written outside the + # settings element, skip writing it again + if mesh_memo and self.entropy_mesh.id in mesh_memo: + return + + # See if a element already exists -- if not, add it + path = f"./mesh[@id='{self.entropy_mesh.id}']" + if root.find(path) is None: + root.append(self.entropy_mesh.to_xml_element()) + if mesh_memo is not None: mesh_memo.add(self.entropy_mesh.id) def _create_trigger_subelement(self, root): if self._trigger_active is not None: @@ -1149,15 +1151,21 @@ class Settings: element = ET.SubElement(root, "track") element.text = ' '.join(map(str, itertools.chain(*self._track))) - def _create_ufs_mesh_subelement(self, root): - if self.ufs_mesh is not None: - # See if a element already exists -- if not, add it - path = f"./mesh[@id='{self.ufs_mesh.id}']" - if root.find(path) is None: - root.append(self.ufs_mesh.to_xml_element()) + def _create_ufs_mesh_subelement(self, root, mesh_memo=None): + if self.ufs_mesh is None: + return - subelement = ET.SubElement(root, "ufs_mesh") - subelement.text = str(self.ufs_mesh.id) + subelement = ET.SubElement(root, "ufs_mesh") + subelement.text = str(self.ufs_mesh.id) + + if mesh_memo and self.ufs_mesh.id in mesh_memo: + return + + # See if a element already exists -- if not, add it + path = f"./mesh[@id='{self.ufs_mesh.id}']" + if root.find(path) is None: + root.append(self.ufs_mesh.to_xml_element()) + if mesh_memo is not None: mesh_memo.add(self.ufs_mesh.id) def _create_resonance_scattering_subelement(self, root): res = self.resonance_scattering diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index fbff02357..c67a72ed3 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -27,7 +27,7 @@ class ModelXMLTestHarness(PyAPITestHarness): self.results_true = 'results_true.dat' if results_true is None else results_true def _build_inputs(self): - self._model.export_to_xml(separate_xmls=False) + self._model.export_to_model_xml() def _get_inputs(self): return open('model.xml').read() @@ -77,21 +77,24 @@ def test_input_arg(run_in_tmpdir): pincell.settings.particles = 100 # export to separate XML files and run - pincell.export_to_xml(separate_xmls=True) + pincell.export_to_xml() openmc.run() # make sure the executable isn't falling back on the separate XMLs for f in glob.glob('*.xml'): os.remove(f) # now export to a single XML file with a custom name - pincell.export_to_xml(path='pincell.xml', separate_xmls=False) + pincell.export_to_model_xml('pincell.xml') assert Path('pincell.xml').exists() # run by specifying that single file openmc.run(path_input='pincell.xml') + # check that this works for plotting too + openmc.plot_geometry(path_input='pincell.xml') + # now ensure we get an error for an incorrect filename, # even in the presence of other, valid XML files - pincell.export_to_xml(separate_xmls=True) + pincell.export_to_model_xml() with pytest.raises(RuntimeError, match='ex-em-ell.xml'): openmc.run(path_input='ex-em-ell.xml') \ No newline at end of file diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 11a88d76c..6c483aeb9 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -542,18 +542,18 @@ def test_model_xml(run_in_tmpdir): pwr_model.geometry.export_to_xml('geometry_ref.xml') # now write and read a model.xml file - pwr_model.export_to_xml(separate_xmls=False) + pwr_model.export_to_model_xml() new_model = openmc.Model.from_model_xml() # make sure we can also export this again to separate # XML files - new_model.export_to_xml(separate_xmls=True) + new_model.export_to_xml() -def test_model_exec(run_in_tmpdir): +def test_single_xml_exec(run_in_tmpdir): pincell_model = openmc.examples.pwr_pin_cell() - pincell_model.export_to_xml(path='pwr_pincell.xml', separate_xmls=False) + pincell_model.export_to_model_xml('pwr_pincell.xml') openmc.run(path_input='pwr_pincell.xml') @@ -562,7 +562,7 @@ def test_model_exec(run_in_tmpdir): # test that a file in a different directory can be used os.mkdir('inputs') - pincell_model.export_to_xml(path='./inputs/pincell.xml', separate_xmls=False) + pincell_model.export_to_model_xml('./inputs/pincell.xml') openmc.run(path_input='./inputs/pincell.xml') with pytest.raises(RuntimeError, match='input_dir'): From 43687e5194f854d6d2a9fdf6287ec0c9b45bf3a1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 12 Dec 2022 21:40:48 -0600 Subject: [PATCH 1394/2654] Improve comment on recursion arguments --- openmc/_xml.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/_xml.py b/openmc/_xml.py index aeaeb45b5..2a33d4b8d 100644 --- a/openmc/_xml.py +++ b/openmc/_xml.py @@ -26,8 +26,10 @@ def clean_indentation(element, level=0, spaces_per_level=2, trailing_indent=True if trailing_indent and (not element.tail or not element.tail.strip()): element.tail = i for sub_element in element: - # `trailing_indent` intentionally not passed to the recursive call. - # it only applies to the element for the initial of this function. + # `trailing_indent` is intentionally not forwarded to the recursive + # call. Any child element of the topmost clement should add + # indentation at the end to ensure its parent's indentation is + # correct. clean_indentation(sub_element, level+1, spaces_per_level) if not sub_element.tail or not sub_element.tail.strip(): sub_element.tail = i From 2eca57a299ce91b9ddb68b8d6b40313ad6ddd708 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 13 Dec 2022 23:16:57 -0600 Subject: [PATCH 1395/2654] Adding mesh memo to Settings.from_xml_element --- openmc/model/model.py | 4 ++-- openmc/settings.py | 25 ++++++++++++++++++------- openmc/tallies.py | 4 ++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index a8dc1ce48..7c6d9b828 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -254,12 +254,12 @@ class Model: model = cls() - model.settings = openmc.Settings.from_xml_element(root.find('settings')) + meshes = {} + model.settings = openmc.Settings.from_xml_element(root.find('settings'), meshes) model.materials = openmc.Materials.from_xml_element(root.find('materials')) model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) # gather meshes from other classes before reading the tally node - meshes = {} if model.settings.entropy_mesh is not None: meshes[model.settings.entropy_mesh.id] = model.settings.entropy_mesh diff --git a/openmc/settings.py b/openmc/settings.py index 8f6d3ec07..65ca71957 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1417,13 +1417,15 @@ class Settings: if value is not None: self.cutoff[key] = float(value) - def _entropy_mesh_from_xml_element(self, root): + def _entropy_mesh_from_xml_element(self, root, meshes=None): text = get_text(root, 'entropy_mesh') if text is not None: path = f"./mesh[@id='{int(text)}']" elem = root.find(path) if elem is not None: self.entropy_mesh = RegularMesh.from_xml_element(elem) + if meshes is not None and self.entropy_mesh is not None: + meshes[self.entropy_mesh.id] = self.entropy_mesh def _trigger_from_xml_element(self, root): elem = root.find('trigger') @@ -1483,13 +1485,15 @@ class Settings: values = [int(x) for x in text.split()] self.track = list(zip(values[::3], values[1::3], values[2::3])) - def _ufs_mesh_from_xml_element(self, root): + def _ufs_mesh_from_xml_element(self, root, meshes=None): text = get_text(root, 'ufs_mesh') if text is not None: path = f"./mesh[@id='{int(text)}']" elem = root.find(path) if elem is not None: self.ufs_mesh = RegularMesh.from_xml_element(elem) + if meshes is not None and self.ufs_mesh is not None: + meshes[self.ufs_mesh.id] = self.ufs_mesh def _resonance_scattering_from_xml_element(self, root): elem = root.find('resonance_scattering') @@ -1541,7 +1545,7 @@ class Settings: if text is not None: self.write_initial_source = text in ('true', '1') - def _weight_windows_from_xml_element(self, root): + def _weight_windows_from_xml_element(self, root, meshes=None): for elem in root.findall('weight_windows'): ww = WeightWindows.from_xml_element(elem, root) self.weight_windows.append(ww) @@ -1550,6 +1554,9 @@ class Settings: if text is not None: self.weight_windows_on = text in ('true', '1') + if meshes is not None and self.weight_windows: + meshes.update({ww.mesh.id: ww.mesh for ww in self.weight_windows}) + def _max_splits_from_xml_element(self, root): text = get_text(root, 'max_splits') if text is not None: @@ -1643,13 +1650,17 @@ class Settings: tree.write(str(p), xml_declaration=True, encoding='utf-8') @classmethod - def from_xml_element(cls, elem): + def from_xml_element(cls, elem, meshes=None): """Generate settings from XML element Parameters ---------- elem : xml.etree.ElementTree.Element XML element + meshes : dict or None + A dictionary with mesh IDs as keys and mesh instances as values that + have already been read from XML. Pre-existing meshes are used + and new meshes are added to when creating tally objects. Returns ------- @@ -1683,7 +1694,7 @@ class Settings: settings._seed_from_xml_element(elem) settings._survival_biasing_from_xml_element(elem) settings._cutoff_from_xml_element(elem) - settings._entropy_mesh_from_xml_element(elem) + settings._entropy_mesh_from_xml_element(elem, meshes) settings._trigger_from_xml_element(elem) settings._no_reduce_from_xml_element(elem) settings._verbosity_from_xml_element(elem) @@ -1691,7 +1702,7 @@ class Settings: settings._temperature_from_xml_element(elem) settings._trace_from_xml_element(elem) settings._track_from_xml_element(elem) - settings._ufs_mesh_from_xml_element(elem) + settings._ufs_mesh_from_xml_element(elem, meshes) settings._resonance_scattering_from_xml_element(elem) settings._create_fission_neutrons_from_xml_element(elem) settings._delayed_photon_scaling_from_xml_element(elem) @@ -1700,7 +1711,7 @@ class Settings: settings._material_cell_offsets_from_xml_element(elem) settings._log_grid_bins_from_xml_element(elem) settings._write_initial_source_from_xml_element(elem) - settings._weight_windows_from_xml_element(elem) + settings._weight_windows_from_xml_element(elem, meshes) settings._max_splits_from_xml_element(elem) settings._max_tracks_from_xml_element(elem) diff --git a/openmc/tallies.py b/openmc/tallies.py index e17e7c99d..b22cc4cf0 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3199,6 +3199,10 @@ class Tallies(cv.CheckedList): ---------- elem : xml.etree.ElementTree.Element XML element + meshes : dict or None + A dictionary with mesh IDs as keys and mesh instances as values that + have already been read from XML. Pre-existing meshes are used + and new meshes are added to when creating tally objects. Returns ------- From 907cf7df4d1c221584bc6e4db0cb3a2106b1686e Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 16 Dec 2022 12:30:08 -0500 Subject: [PATCH 1396/2654] changed catch2 clone link to https --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index b16ecb580..4dde5fd5e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,4 +15,4 @@ url = https://github.com/fmtlib/fmt.git [submodule "vendor/Catch2"] path = vendor/Catch2 - url = git@github.com:catchorg/Catch2.git + url = https://github.com/catchorg/Catch2.git From 90509d928bc88d5bed5dd9673c8eaa8d0fa4cc66 Mon Sep 17 00:00:00 2001 From: myerspat Date: Mon, 19 Dec 2022 17:24:33 -0500 Subject: [PATCH 1397/2654] moved alias method to function and fixed sampling bug --- include/openmc/distribution.h | 3 +++ src/distribution.cpp | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index e2c710ae9..4519c285b 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -58,6 +58,9 @@ private: //! Normalize distribution so that probabilities sum to unity void normalize(); + + //! Initialize alias tables for distribution + void init_alias(); }; //============================================================================== diff --git a/src/distribution.cpp b/src/distribution.cpp index 436e34116..c15b56f7b 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -29,12 +29,18 @@ Discrete::Discrete(pugi::xml_node node) std::copy(params.begin(), params.begin() + n / 2, std::back_inserter(x_)); std::copy(params.begin() + n / 2, params.end(), std::back_inserter(p_)); - normalize(); + // Initialize alias tables + init_alias(); } Discrete::Discrete(const double* x, const double* p, int n) : x_ {x, x + n}, p_ {p, p + n} { + // Initialize alias tables + init_alias(); +} + +void Discrete::init_alias() { normalize(); // Vectors for large and small probabilities based on 1/n @@ -42,11 +48,11 @@ Discrete::Discrete(const double* x, const double* p, int n) vector small; // Set and allocate memory - alias_.reserve(n); + alias_.reserve(x_.size()); // Fill large and small vectors based on 1/n - for (int i = 0; i < n; i++) { - p_[i] *= n; + for (int i = 0; i < x_.size(); i++) { + p_[i] *= x_.size(); if (p_[i] > 1.0) { large.push_back(i); } else { @@ -85,7 +91,7 @@ double Discrete::sample(uint64_t* seed) const return x_[alias_[u]]; } } else { - return x_.size(); + return x_[0]; } } From 748e7da3f9bcb8af5832668aec0bf036dee34bb4 Mon Sep 17 00:00:00 2001 From: myerspat Date: Mon, 19 Dec 2022 17:25:20 -0500 Subject: [PATCH 1398/2654] added test for xml node Discrete constructor --- tests/cpp_unit_tests/test_distribution.cpp | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/cpp_unit_tests/test_distribution.cpp b/tests/cpp_unit_tests/test_distribution.cpp index 772fc136a..41cb2b4c4 100644 --- a/tests/cpp_unit_tests/test_distribution.cpp +++ b/tests/cpp_unit_tests/test_distribution.cpp @@ -1,6 +1,7 @@ #include "openmc/distribution.h" #include "openmc/random_lcg.h" #include +#include TEST_CASE("Test alias method sampling of a discrete distribution") { @@ -38,3 +39,25 @@ TEST_CASE("Test alias method sampling of a discrete distribution") // expected mean REQUIRE(std::abs(dist_mean - mean) < 3 * std); } + +TEST_CASE("Test alias sampling method for pugixml constructor") +{ + // XML doc node for Discrete contructor + pugi::xml_document doc; + pugi::xml_node energy = doc.append_child("energy"); + pugi::xml_node parameters = energy.append_child("parameters"); + parameters.append_child(pugi::node_pcdata) + .set_value("17140457.745328166 1.0"); + + // Initialize discrete distribution and seed + openmc::Discrete dist(energy); + uint64_t seed = openmc::init_seed(0, 0); + + // Assertions + REQUIRE(dist.x().size() == 1); + REQUIRE(dist.p().size() == 1); + REQUIRE(dist.alias().size() == 0); + REQUIRE(dist.x()[0] == 17140457.745328166); + REQUIRE(dist.p()[0] == 1.0); + REQUIRE(dist.sample(&seed) == 17140457.745328166); +} From 2b7fa8fdd2dbe313e14cf2d789f9cad1260d964e Mon Sep 17 00:00:00 2001 From: erkn Date: Tue, 20 Dec 2022 23:58:22 +0100 Subject: [PATCH 1399/2654] Revert "enable mcpl from the python layer" This reverts commit e3f1bdaca1f5144563c4ceac45f10e4b0b5b7963. There is now a check in the cpp-layer if the file is named .mcpl --- openmc/source.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openmc/source.py b/openmc/source.py index fdb2d5bc2..48e14f6f7 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -223,10 +223,7 @@ class Source: if self.particle != 'neutron': element.set("particle", self.particle) if self.file is not None: - if (self.file.endswith('.mcpl')): - element.set("mcpl", self.file) - else: - element.set("file", self.file) + element.set("file", self.file) if self.library is not None: element.set("library", self.library) if self.parameters is not None: From 1ab9aa4b6fddf4e6b7216b7fe993d8c672c22468 Mon Sep 17 00:00:00 2001 From: erkn Date: Wed, 21 Dec 2022 00:14:43 +0100 Subject: [PATCH 1400/2654] script for installing mcpl as a ci-thing --- tools/ci/gha-install-mcpl.sh | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 tools/ci/gha-install-mcpl.sh diff --git a/tools/ci/gha-install-mcpl.sh b/tools/ci/gha-install-mcpl.sh new file mode 100755 index 000000000..9b8609398 --- /dev/null +++ b/tools/ci/gha-install-mcpl.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -ex +cd $HOME +git clone https://github.com/mctools/mcpl +cd mcpl +mkdir build && cd build +cmake .. && make 2>/dev/null && sudo make install From 9865a129c49ad2b07628d152a2d8865ad6936fd6 Mon Sep 17 00:00:00 2001 From: erkn Date: Wed, 21 Dec 2022 00:22:38 +0100 Subject: [PATCH 1401/2654] optionally install mcpl depending on environment var --- tools/ci/gha-install.py | 8 ++++++-- tools/ci/gha-install.sh | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index 4c69ba70b..ea317b5f0 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -19,7 +19,7 @@ def which(program): return None -def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): +def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, mcpl=False): # Create build directory and change to it shutil.rmtree('build', ignore_errors=True) os.mkdir('build') @@ -54,6 +54,9 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): libmesh_path = os.environ.get('HOME') + '/LIBMESH' cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + libmesh_path) + if mcpl: + cmake_cmd.append('-DOPENMC_USE_MCPL=ON') + # Build in coverage mode for coverage testing cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') @@ -71,9 +74,10 @@ def main(): phdf5 = (os.environ.get('PHDF5') == 'y') dagmc = (os.environ.get('DAGMC') == 'y') libmesh = (os.environ.get('LIBMESH') == 'y') + mcpl = (os.environ.get('MCPL') == 'y') # Build and install - install(omp, mpi, phdf5, dagmc, libmesh) + install(omp, mpi, phdf5, dagmc, libmesh, mcpl) if __name__ == '__main__': main() diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index aa40eb90b..68e825d48 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -27,6 +27,11 @@ if [[ $LIBMESH = 'y' ]]; then ./tools/ci/gha-install-libmesh.sh fi +# Install mcpl if needed +if [[ $MCPL = 'y' ]]; then + ./tools/ci/gha-install-mcpl.sh +fi + # For MPI configurations, make sure mpi4py and h5py are built against the # correct version of MPI if [[ $MPI == 'y' ]]; then From a50776219fe659be4572a918d4e19bfb9596a5f3 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 21 Dec 2022 11:33:36 +0100 Subject: [PATCH 1402/2654] resolve conflict w. develop --- src/source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/source.cpp b/src/source.cpp index af108f3fa..19d1c2a9d 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -234,7 +234,7 @@ SourceSite IndependentSource::sample(uint64_t* seed) const auto id = (domain_type_ == DomainType::CELL) ? model::cells[coord.cell]->id_ : model::universes[coord.universe]->id_; - if (found = contains(domain_ids_, id)) + if ((found = contains(domain_ids_, id))) break; } } From 19c807ade2fac423cb3ac55eac358b29a88c5ca3 Mon Sep 17 00:00:00 2001 From: myerspat Date: Wed, 21 Dec 2022 10:15:14 -0500 Subject: [PATCH 1403/2654] updated regression tests --- .../last_step_reference_materials.xml | 374 +++++++++--------- .../deplete_with_transport/test_reference.h5 | Bin 166224 -> 163736 bytes .../regression_tests/source/results_true.dat | 2 +- .../surface_source/surface_source_true.h5 | Bin 106144 -> 106144 bytes 4 files changed, 188 insertions(+), 188 deletions(-) diff --git a/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml b/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml index fc9fd0cf5..b81856683 100644 --- a/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml +++ b/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml @@ -4,43 +4,43 @@ - + - + - + - + - + - - + + - + - + - - + + @@ -48,12 +48,12 @@ - - + + - + @@ -67,7 +67,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -89,26 +89,26 @@ - - + + - + - + - + - + @@ -116,13 +116,13 @@ - - + + - + @@ -132,40 +132,40 @@ - + - + - + - + - - + + - + - + - - + + @@ -178,35 +178,35 @@ - + - + - - + + - - + + - + - + @@ -214,7 +214,7 @@ - + @@ -228,13 +228,13 @@ - + - + @@ -256,12 +256,12 @@ - + - + @@ -270,7 +270,7 @@ - + @@ -284,33 +284,33 @@ - + - + - + - - + + - + - - + + @@ -324,13 +324,13 @@ - - - + + + - + @@ -339,13 +339,13 @@ - + - - + + @@ -353,27 +353,27 @@ - + - - + + - + - + - - + + @@ -386,7 +386,7 @@ - + @@ -395,7 +395,7 @@ - + @@ -414,21 +414,21 @@ - + - + - + - + @@ -441,21 +441,21 @@ - + - + - + - + @@ -463,14 +463,14 @@ - - + + - - + + @@ -478,13 +478,13 @@ - + - + @@ -492,34 +492,34 @@ - - + + - + - - - + + + - + - - + + @@ -534,13 +534,13 @@ - + - - + + @@ -548,67 +548,67 @@ - - + + - - + + - - + + - - + + - - - + + + - + - - - + + + - - + + - - - + + + - + @@ -622,8 +622,8 @@ - - + + @@ -631,13 +631,13 @@ - + - - + + @@ -646,11 +646,11 @@ - + - + @@ -658,7 +658,7 @@ - + @@ -673,67 +673,67 @@ - + - + - + - - + + - + - - + + - + - + - + - - + + - - - + + + - + @@ -747,8 +747,8 @@ - - + + @@ -761,7 +761,7 @@ - + @@ -775,16 +775,16 @@ - + - + - + @@ -797,26 +797,26 @@ - - + + - + - - - + + + - + @@ -839,26 +839,26 @@ - - + + - - + + - + - + - + @@ -867,13 +867,13 @@ - - + + - - + + @@ -881,7 +881,7 @@ - + @@ -900,21 +900,21 @@ - - + + - + - + - + @@ -922,8 +922,8 @@ - - + + @@ -934,14 +934,14 @@ - + - + - + @@ -950,7 +950,7 @@ - + @@ -964,12 +964,12 @@ - - + + - + @@ -983,21 +983,21 @@ - + - + - + diff --git a/tests/regression_tests/deplete_with_transport/test_reference.h5 b/tests/regression_tests/deplete_with_transport/test_reference.h5 index d478d628ef662ac0ccb996ac9aa26a241df084e1..952994b86b468a550adcd787666582a53897167c 100644 GIT binary patch delta 42738 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

`h(3 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�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 M-@mc)|1W0#e`;?LOaK4? diff --git a/tests/regression_tests/source/results_true.dat b/tests/regression_tests/source/results_true.dat index 62eaf6eff..f0d69afb5 100644 --- a/tests/regression_tests/source/results_true.dat +++ b/tests/regression_tests/source/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.865754E-01 6.762423E-03 +3.073726E-01 2.535074E-03 diff --git a/tests/regression_tests/surface_source/surface_source_true.h5 b/tests/regression_tests/surface_source/surface_source_true.h5 index c26afee8671dba0b729d6959614a6856166bd37a..eb65846d1cf33d6a2c49af364275d7ec0c053637 100644 GIT binary patch delta 11188 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 delta 11187 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 Date: Wed, 21 Dec 2022 15:39:13 -0600 Subject: [PATCH 1404/2654] Change alias sampling comment Co-authored-by: Paul Wilson --- src/distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index cd3e3fe72..4634aa9d6 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -71,7 +71,7 @@ void Discrete::init_alias() { p_[k] += p_[j] - 1.0; alias_[j] = k; - // Remove last vector element and or move large index to small vector + // Move large index to small vector, if it is no longer large if (p_[k] < 1.0) { small.push_back(k); large.pop_back(); From dd569c616cf063257aa69c37418d8a0cecca06d1 Mon Sep 17 00:00:00 2001 From: myerspat Date: Wed, 21 Dec 2022 16:59:04 -0500 Subject: [PATCH 1405/2654] increased stdev width to 4 --- tests/cpp_unit_tests/test_distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cpp_unit_tests/test_distribution.cpp b/tests/cpp_unit_tests/test_distribution.cpp index 41cb2b4c4..d95dee498 100644 --- a/tests/cpp_unit_tests/test_distribution.cpp +++ b/tests/cpp_unit_tests/test_distribution.cpp @@ -37,7 +37,7 @@ TEST_CASE("Test alias method sampling of a discrete distribution") // Require sampled distribution mean is within 3 standard deviations of the // expected mean - REQUIRE(std::abs(dist_mean - mean) < 3 * std); + REQUIRE(std::abs(dist_mean - mean) < 4 * std); } TEST_CASE("Test alias sampling method for pugixml constructor") From ff48f53595144aa0ecbc1f44f2d28428a7306633 Mon Sep 17 00:00:00 2001 From: erkn Date: Thu, 22 Dec 2022 12:04:29 +0100 Subject: [PATCH 1406/2654] skip mcpl-test if it is not enabled patterned after the dagmc-tests This required the MCPL_ENABLED symbol to be unmangled --- include/openmc/source.h | 1 + tests/regression_tests/source_mcpl_file/test.py | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/openmc/source.h b/include/openmc/source.h index bb7e2d55f..051167b3f 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -32,6 +32,7 @@ constexpr double EXTSRC_REJECT_FRACTION {0.05}; //============================================================================== // Global variables //============================================================================== +extern "C" const bool MCPL_ENABLED; class Source; diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index a005fc2d8..0b8e79104 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -1,10 +1,13 @@ #!/usr/bin/env python - +import openmc.lib +import pytest import glob import os from tests.testing_harness import * - +pytestmark = pytest.mark.skipif( + not openmc.lib._mcpl_enabled(), + reason="MCPL is not enabled.") settings1=""" From fe19cfcdd25966c3ab5cce056b9337c50e3e7743 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 22 Dec 2022 17:16:16 +0100 Subject: [PATCH 1407/2654] set seed to get a deterministic test and set result --- tests/regression_tests/source_mcpl_file/results_true.dat | 2 +- tests/regression_tests/source_mcpl_file/settings.xml | 1 + tests/regression_tests/source_mcpl_file/test.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/source_mcpl_file/results_true.dat b/tests/regression_tests/source_mcpl_file/results_true.dat index 19460623f..e8f4a20a0 100644 --- a/tests/regression_tests/source_mcpl_file/results_true.dat +++ b/tests/regression_tests/source_mcpl_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.039964E-01 3.654869E-04 +3.004254E-01 8.027600E-04 diff --git a/tests/regression_tests/source_mcpl_file/settings.xml b/tests/regression_tests/source_mcpl_file/settings.xml index 47b010bff..2e511461f 100644 --- a/tests/regression_tests/source_mcpl_file/settings.xml +++ b/tests/regression_tests/source_mcpl_file/settings.xml @@ -1,5 +1,6 @@ + 1234 diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 0b8e79104..e87479c5a 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -11,6 +11,7 @@ pytestmark = pytest.mark.skipif( settings1=""" + 1234 From e9c6b03b9e2f5fb50875c64a8a33db8eda1059dd Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 22 Dec 2022 17:17:50 +0100 Subject: [PATCH 1408/2654] remove dead code --- tests/regression_tests/source_mcpl_file/test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index e87479c5a..649278319 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -93,9 +93,6 @@ class SourceFileTestHarness(TestHarness): def _cleanup(self): TestHarness._cleanup(self) output = glob.glob(os.path.join(os.getcwd(), 'source.*')) - #for f in output: - # if os.path.exists(f): - # os.remove(f) with open('settings.xml','w') as fh: fh.write(settings1) From 4d7797c25b3932aaa166b4a6b12c4ffebd48d925 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 22 Dec 2022 17:18:37 +0100 Subject: [PATCH 1409/2654] mistake assigning the wrong variable --- src/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.cpp b/src/settings.cpp index 5e8eb0e58..b0829c1ba 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -656,7 +656,7 @@ void read_settings_xml() source_write = get_node_value_bool(node_sp, "write"); } if (check_for_node(node_sp, "mcpl")) { - source_write = get_node_value_bool(node_sp, "mcpl"); + source_mcpl_write = get_node_value_bool(node_sp, "mcpl"); } if (check_for_node(node_sp, "overwrite_latest")) { source_latest = get_node_value_bool(node_sp, "overwrite_latest"); From 51d3a0c2ce6079f18ea479c7efc158148236f5a7 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 22 Dec 2022 17:19:56 +0100 Subject: [PATCH 1410/2654] check for mcpl-input is in the cpp-layer now --- tests/regression_tests/source_mcpl_file/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 649278319..60e0ad50f 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -35,7 +35,7 @@ settings2 = """ 1000 - source.10.{0} + source.10.{0} """ From 28521c8384c6e68b6ee0f52a7a44425b4a6306bd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 10:53:40 -0600 Subject: [PATCH 1411/2654] Use vector::push_back for building MCPL FileSource --- src/source.cpp | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 19d1c2a9d..4ab087e12 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -335,9 +335,8 @@ FileSource::FileSource(mcpl_file_t mcpl_file) { size_t n_sites = mcpl_hdr_nparticles(mcpl_file); - sites_.resize(n_sites); for (int i = 0; i < n_sites; i++) { - SourceSite site_; + SourceSite site; const mcpl_particle_t* mcpl_particle; // extract particle from mcpl-file @@ -351,36 +350,41 @@ FileSource::FileSource(mcpl_file_t mcpl_file) switch (pdg) { case 2112: - site_.particle = ParticleType::neutron; + site.particle = ParticleType::neutron; break; case 22: - site_.particle = ParticleType::photon; + site.particle = ParticleType::photon; break; case 11: - site_.particle = ParticleType::electron; + site.particle = ParticleType::electron; break; case -11: - site_.particle = ParticleType::positron; + site.particle = ParticleType::positron; break; } - // particle is good, convert to openmc-formalism - site_.r.x = mcpl_particle->position[0]; - site_.r.y = mcpl_particle->position[1]; - site_.r.z = mcpl_particle->position[2]; - - site_.u.x = mcpl_particle->direction[0]; - site_.u.y = mcpl_particle->direction[1]; - site_.u.z = mcpl_particle->direction[2]; + // Copy position and direction + site.r.x = mcpl_particle->position[0]; + site.r.y = mcpl_particle->position[1]; + site.r.z = mcpl_particle->position[2]; + site.u.x = mcpl_particle->direction[0]; + site.u.y = mcpl_particle->direction[1]; + site.u.z = mcpl_particle->direction[2]; // mcpl stores kinetic energy in MeV - site_.E = mcpl_particle->ekin * 1e6; + site.E = mcpl_particle->ekin * 1e6; // mcpl stores time in ms - site_.time = mcpl_particle->time * 1e-3; - site_.wgt = mcpl_particle->weight; - site_.delayed_group = 0; - sites_[i] = site_; + site.time = mcpl_particle->time * 1e-3; + site.wgt = mcpl_particle->weight; + sites_.push_back(site); } + + // Check that some sites were read + if (sites_.empty()) { + fatal_error("MCPL file contained no neutron, photon, electron, or positron " + "source particles."); + } + mcpl_close_file(mcpl_file); } #endif // OPENMC_MCPL From 987293cfffb2934359b0c1f0dcd685eb8140fd63 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 10:57:11 -0600 Subject: [PATCH 1412/2654] Small fixes and formatting changes --- docs/source/io_formats/settings.rst | 8 ++-- include/openmc/state_point.h | 3 +- openmc/settings.py | 2 +- src/settings.cpp | 17 ++++--- src/simulation.cpp | 10 ++--- src/state_point.cpp | 70 ++++++++++++++--------------- 6 files changed, 57 insertions(+), 53 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index a162e8de6..7174c5317 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -768,10 +768,10 @@ certain surfaces and write out the source bank in a separate file called *Default*: None :mcpl: - An optional boolean which indicates if the banked particles should - be written to a file in the MCPL-format (documented in mcpl_). - instead of the native hdf5-based format.If activated the output - output file name is altered to ``surface_source.mcpl`` + An optional boolean which indicates if the banked particles should be + written to a file in the MCPL-format (documented in mcpl_). instead of the + native HDF5-based format. If activated the output file name is changed to + ``surface_source.mcpl``. *Default*: false diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 698ed2c93..730127554 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -26,7 +26,8 @@ void restart_set_keff(); void write_unstructured_mesh_results(); #ifdef OPENMC_MCPL -void write_mcpl_source_point(const char* filename, bool surf_source_bank = false); +void write_mcpl_source_point( + const char* filename, bool surf_source_bank = false); void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); #endif diff --git a/openmc/settings.py b/openmc/settings.py index b2c184f78..fd622870c 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1349,7 +1349,7 @@ class Settings: elif key in ('max_particles'): value = int(value) elif key == 'mcpl': - value = True + value = value in ('true', '1') self.surf_source_write[key] = value def _confidence_intervals_from_xml_element(self, root): diff --git a/src/settings.cpp b/src/settings.cpp index b0829c1ba..de298c58d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -432,12 +432,15 @@ void read_settings_xml() if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); #ifdef OPENMC_MCPL - if ( (path.size() >= 5 && path.compare(path.size()-5,5,".mcpl")==0 ) || - (path.size() >= 8 && path.compare(path.size()-8,8,".mcpl.gz")==0 ) ) { - model::external_sources.push_back(make_unique(mcpl_open_file(path.c_str()))); - } else -#endif + if (ends_with(path, ".mcpl") || ends_with(path, ".mcpl.gz")) { + model::external_sources.push_back( + make_unique(mcpl_open_file(path.c_str()))); + } else { model::external_sources.push_back(make_unique(path)); + } +#else + model::external_sources.push_back(make_unique(path)); +#endif } else if (check_for_node(node, "library")) { // Get shared library path and parameters auto path = get_node_value(node, "library", false, true); @@ -689,8 +692,8 @@ void read_settings_xml() std::stoll(get_node_value(node_ssw, "max_particles")); } #ifdef OPENMC_MCPL - if(check_for_node(node_ssw, "mcpl")){ - surf_mcpl_write=true; + if (check_for_node(node_ssw, "mcpl")) { + surf_mcpl_write = true; } #endif } diff --git a/src/simulation.cpp b/src/simulation.cpp index d7cc2237d..2c1d1c988 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -390,7 +390,7 @@ void finalize_batch() if (settings::run_mode == RunMode::EIGENVALUE) { // Write out a separate source point if it's been specified for this batch #ifdef OPENMC_MCPL - if(! settings::source_mcpl_write) { + if (!settings::source_mcpl_write) { #endif if (contains(settings::sourcepoint_batch, simulation::current_batch) && settings::source_write && settings::source_separate) { @@ -405,8 +405,8 @@ void finalize_batch() #ifdef OPENMC_MCPL } else { if (contains(settings::sourcepoint_batch, simulation::current_batch) && - settings::source_mcpl_write && settings::source_separate) { - write_mcpl_source_point(nullptr); + settings::source_mcpl_write && settings::source_separate) { + write_mcpl_source_point(nullptr); } // Write a continously-overwritten source point if requested. @@ -425,12 +425,12 @@ void finalize_batch() write_source_point(filename.c_str(), true); } #ifdef OPENMC_MCPL - if(settings::surf_mcpl_write && simulation::current_batch == settings::n_batches){ + if (settings::surf_mcpl_write && + simulation::current_batch == settings::n_batches) { auto filename = settings::path_output + "surface_source.mcpl"; write_mcpl_source_point(filename.c_str(), true); } #endif - } void initialize_generation() diff --git a/src/state_point.cpp b/src/state_point.cpp index 3ee5f13b3..9dd0f1374 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -604,7 +604,7 @@ void write_source_point(const char* filename, bool surf_source_bank) } #ifdef OPENMC_MCPL -void write_mcpl_source_point(const char *filename, bool surf_source_bank) +void write_mcpl_source_point(const char* filename, bool surf_source_bank) { std::string filename_; if (filename) { @@ -622,21 +622,21 @@ void write_mcpl_source_point(const char *filename, bool surf_source_bank) std::string line; if (mpi::master) { file_id = mcpl_create_outfile(filename_.c_str()); - if (VERSION_DEV){ - line=fmt::format("OpenMC {0}.{1}.{2}-development",VERSION_MAJOR,VERSION_MINOR,VERSION_RELEASE); + if (VERSION_DEV) { + line = fmt::format("OpenMC {0}.{1}.{2}-development", VERSION_MAJOR, + VERSION_MINOR, VERSION_RELEASE); } else { - line=fmt::format("OpenMC {0}.{1}.{2}",VERSION_MAJOR,VERSION_MINOR,VERSION_RELEASE); + line = fmt::format( + "OpenMC {0}.{1}.{2}", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE); } - mcpl_hdr_set_srcname(file_id,line.c_str()); + mcpl_hdr_set_srcname(file_id, line.c_str()); } write_mcpl_source_bank(file_id, surf_source_bank); if (mpi::master) { - //change this - this is h5 specific mcpl_close_outfile(file_id); } - } #endif @@ -768,7 +768,7 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) vector surf_source_index_vector; vector surf_source_bank_vector; - if(surf_source_bank) { + if (surf_source_bank) { surf_source_index_vector = calculate_surf_source_size(); dims_size = surf_source_index_vector[mpi::n_procs]; count_size = simulation::surf_source_bank.size(); @@ -790,55 +790,56 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) vector temp_source {source_bank->begin(), source_bank->end()}; #endif - //loop over the other nodes and receive data - then write those. + // loop over the other nodes and receive data - then write those. for (int i = 0; i < mpi::n_procs; ++i) { // number of particles for node node i size_t count[] { static_cast((*bank_index)[i + 1] - (*bank_index)[i])}; #ifdef OPENMC_MPI - if (i>0) + if (i > 0) MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, mpi::intracomm, MPI_STATUS_IGNORE); #endif // now write the source_bank data again. - for (vector::iterator _site=source_bank->begin(); _site!=source_bank->end();_site++){ + for (vector::iterator _site = source_bank->begin(); + _site != source_bank->end(); _site++) { // particle is now at the iterator // write it to the mcpl-file mcpl_particle_t p; - p.position[0]=_site->r.x; - p.position[1]=_site->r.y; - p.position[2]=_site->r.z; + p.position[0] = _site->r.x; + p.position[1] = _site->r.y; + p.position[2] = _site->r.z; // mcpl requires that the direction vector is unit length // which is also the case in openmc - p.direction[0]=_site->u.x; - p.direction[1]=_site->u.y; - p.direction[2]=_site->u.z; + p.direction[0] = _site->u.x; + p.direction[1] = _site->u.y; + p.direction[2] = _site->u.z; // mcpl stores kinetic energy in MeV - p.ekin=_site->E*1e-6; + p.ekin = _site->E * 1e-6; - p.time=_site->time*1e3; + p.time = _site->time * 1e3; - p.weight=_site->wgt; + p.weight = _site->wgt; - switch(_site->particle){ - case ParticleType::neutron: - p.pdgcode=2112; - break; - case ParticleType::photon: - p.pdgcode=22; - break; - case ParticleType::electron: - p.pdgcode=11; - break; - case ParticleType::positron: - p.pdgcode=-11; - break; + switch (_site->particle) { + case ParticleType::neutron: + p.pdgcode = 2112; + break; + case ParticleType::photon: + p.pdgcode = 22; + break; + case ParticleType::electron: + p.pdgcode = 11; + break; + case ParticleType::positron: + p.pdgcode = -11; + break; } - mcpl_add_particle(file_id,&p); + mcpl_add_particle(file_id, &p); } } #ifdef OPENMC_MPI @@ -851,7 +852,6 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) mpi::intracomm); #endif } - } #endif From a3065b479c0a47caae6229fa8657da59668be1e9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 11:33:29 -0600 Subject: [PATCH 1413/2654] Move FileSource MCPL reading to mcpl_interface.h/cpp --- CMakeLists.txt | 1 + include/openmc/mcpl_interface.h | 25 +++++++++ include/openmc/source.h | 10 +--- src/mcpl_interface.cpp | 93 +++++++++++++++++++++++++++++++++ src/settings.cpp | 11 ++-- src/source.cpp | 69 ------------------------ 6 files changed, 126 insertions(+), 83 deletions(-) create mode 100644 include/openmc/mcpl_interface.h create mode 100644 src/mcpl_interface.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 24018eb0f..af3a5b4af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,6 +331,7 @@ list(APPEND libopenmc_SOURCES src/lattice.cpp src/material.cpp src/math_functions.cpp + src/mcpl_interface.cpp src/mesh.cpp src/message_passing.cpp src/mgxs.cpp diff --git a/include/openmc/mcpl_interface.h b/include/openmc/mcpl_interface.h new file mode 100644 index 000000000..89dab16bc --- /dev/null +++ b/include/openmc/mcpl_interface.h @@ -0,0 +1,25 @@ +#ifndef OPENMC_MCPL_INTERFACE_H +#define OPENMC_MCPL_INTERFACE_H + +#include "openmc/particle_data.h" + +#include +#include + +#ifdef OPENMC_MCPL +#include +#endif + +namespace openmc { + +extern "C" const bool MCPL_ENABLED; + +//! Get a vector of source sites from an MCPL file +// +//! \param[in] path Path to MCPL file +//! \return Vector of source sites +vector mcpl_source_sites(std::string path); + +} // namespace openmc + +#endif // OPENMC_MCPL_INTERFACE_H diff --git a/include/openmc/source.h b/include/openmc/source.h index 051167b3f..96d659dcb 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -14,10 +14,6 @@ #include "openmc/particle.h" #include "openmc/vector.h" -#ifdef OPENMC_MCPL -#include -#endif - namespace openmc { //============================================================================== @@ -32,7 +28,6 @@ constexpr double EXTSRC_REJECT_FRACTION {0.05}; //============================================================================== // Global variables //============================================================================== -extern "C" const bool MCPL_ENABLED; class Source; @@ -107,9 +102,8 @@ class FileSource : public Source { public: // Constructors explicit FileSource(std::string path); -#ifdef OPENMC_MCPL - explicit FileSource(mcpl_file_t mcpl_file); -#endif + explicit FileSource(const vector& sites) : sites_ {sites} {} + // Methods SourceSite sample(uint64_t* seed) const override; diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp new file mode 100644 index 000000000..d55cc5af7 --- /dev/null +++ b/src/mcpl_interface.cpp @@ -0,0 +1,93 @@ +#include "openmc/mcpl_interface.h" + +#include "openmc/error.h" + +#ifdef OPENMC_MCPL +#include +#endif + +namespace openmc { + +#ifdef OPENMC_MCPL +const bool MCPL_ENABLED = true; +#else +const bool MCPL_ENABLED = false; +#endif + +#ifdef OPENMC_MCPL +SourceSite mcpl_particle_to_site(const mcpl_particle* particle) +{ + SourceSite site; + + switch (particle->pdgcode) { + case 2112: + site.particle = ParticleType::neutron; + break; + case 22: + site.particle = ParticleType::photon; + break; + case 11: + site.particle = ParticleType::electron; + break; + case -11: + site.particle = ParticleType::positron; + break; + } + + // Copy position and direction + site.r.x = mcpl_particle->position[0]; + site.r.y = mcpl_particle->position[1]; + site.r.z = mcpl_particle->position[2]; + site.u.x = mcpl_particle->direction[0]; + site.u.y = mcpl_particle->direction[1]; + site.u.z = mcpl_particle->direction[2]; + + // mcpl stores kinetic energy in MeV + site.E = mcpl_particle->ekin * 1e6; + // mcpl stores time in ms + site.time = mcpl_particle->time * 1e-3; + site.wgt = mcpl_particle->weight; + + return site; +} +#endif + +vector mcpl_source_sites(std::string path) +{ + vector sites; + +#ifdef OPENMC_MCPL + size_t n_sites = mcpl_hdr_nparticles(mcpl_file); + + for (int i = 0; i < n_sites; i++) { + SourceSite site; + + // Extract particle from mcpl-file, checking if it is a neutron, photon, + // electron, or positron. Otherwise skip. + const mcpl_particle_t* particle; + int pdg = 0; + while (pdg != 2112 && pdg != 22 && pdg != 11 && pdg != -11) { + particle = mcpl_read(mcpl_file); + pdg = mcpl_particle->pdgcode; + } + + // Convert to source site and add to vector + sites.push_back(mcpl_particle_to_site(particle)); + } + + // Check that some sites were read + if (sites_.empty()) { + fatal_error("MCPL file contained no neutron, photon, electron, or positron " + "source particles."); + } + + mcpl_close_file(mcpl_file); +#else + fatal_error( + "Your build of OpenMC does not support reading MCPL source files."); +#endif + + return sites; +} + +} // namespace openmc diff --git a/src/settings.cpp b/src/settings.cpp index de298c58d..bc31e2c4d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -18,6 +18,7 @@ #include "openmc/eigenvalue.h" #include "openmc/error.h" #include "openmc/file_utils.h" +#include "openmc/mcpl_interface.h" #include "openmc/mesh.h" #include "openmc/message_passing.h" #include "openmc/output.h" @@ -431,16 +432,14 @@ void read_settings_xml() for (pugi::xml_node node : root.children("source")) { if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); -#ifdef OPENMC_MCPL if (ends_with(path, ".mcpl") || ends_with(path, ".mcpl.gz")) { - model::external_sources.push_back( - make_unique(mcpl_open_file(path.c_str()))); +#ifdef OPENMC_MCPL + auto sites = mcpl_source_sites(path); + model::external_sources.push_back(make_unique(sites)); +#endif } else { model::external_sources.push_back(make_unique(path)); } -#else - model::external_sources.push_back(make_unique(path)); -#endif } else if (check_for_node(node, "library")) { // Get shared library path and parameters auto path = get_node_value(node, "library", false, true); diff --git a/src/source.cpp b/src/source.cpp index 4ab087e12..d201e3c03 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -33,22 +33,12 @@ #include "openmc/state_point.h" #include "openmc/xml_interface.h" -#ifdef OPENMC_MCPL -#include -#endif - namespace openmc { //============================================================================== // Global variables //============================================================================== -#ifdef OPENMC_MCPL -const bool MCPL_ENABLED = true; -#else -const bool MCPL_ENABLED = false; -#endif - namespace model { vector> external_sources; @@ -330,65 +320,6 @@ FileSource::FileSource(std::string path) file_close(file_id); } -#ifdef OPENMC_MCPL -FileSource::FileSource(mcpl_file_t mcpl_file) -{ - size_t n_sites = mcpl_hdr_nparticles(mcpl_file); - - for (int i = 0; i < n_sites; i++) { - SourceSite site; - - const mcpl_particle_t* mcpl_particle; - // extract particle from mcpl-file - mcpl_particle = mcpl_read(mcpl_file); - // check if it is a neutron, photon, electron, or positron. Otherwise skip. - int pdg = mcpl_particle->pdgcode; - while (pdg != 2112 && pdg != 22 && pdg != 11 && pdg != -11) { - mcpl_particle = mcpl_read(mcpl_file); - pdg = mcpl_particle->pdgcode; - } - - switch (pdg) { - case 2112: - site.particle = ParticleType::neutron; - break; - case 22: - site.particle = ParticleType::photon; - break; - case 11: - site.particle = ParticleType::electron; - break; - case -11: - site.particle = ParticleType::positron; - break; - } - - // Copy position and direction - site.r.x = mcpl_particle->position[0]; - site.r.y = mcpl_particle->position[1]; - site.r.z = mcpl_particle->position[2]; - site.u.x = mcpl_particle->direction[0]; - site.u.y = mcpl_particle->direction[1]; - site.u.z = mcpl_particle->direction[2]; - - // mcpl stores kinetic energy in MeV - site.E = mcpl_particle->ekin * 1e6; - // mcpl stores time in ms - site.time = mcpl_particle->time * 1e-3; - site.wgt = mcpl_particle->weight; - sites_.push_back(site); - } - - // Check that some sites were read - if (sites_.empty()) { - fatal_error("MCPL file contained no neutron, photon, electron, or positron " - "source particles."); - } - - mcpl_close_file(mcpl_file); -} -#endif // OPENMC_MCPL - SourceSite FileSource::sample(uint64_t* seed) const { size_t i_site = sites_.size() * prn(seed); From 361b3486efa4c078e87a1c29f76e6ab4a1edc58e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 12:27:56 -0600 Subject: [PATCH 1414/2654] Move remainder of MCPL-related code to mcpl_interface.h/cpp --- CMakeLists.txt | 1 + include/openmc/mcpl_interface.h | 19 +++- include/openmc/state_point.h | 10 -- src/mcpl_interface.cpp | 185 +++++++++++++++++++++++++++++--- src/settings.cpp | 18 +++- src/simulation.cpp | 7 +- src/state_point.cpp | 140 ------------------------ 7 files changed, 201 insertions(+), 179 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af3a5b4af..466816b30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,7 @@ endif() #=============================================================================== if (OPENMC_USE_MCPL) find_package(MCPL REQUIRED) + message(STATUS "Found MCPL: ${MCPL_DIR} (found version \"${MCPL_VERSION}\")") endif() #=============================================================================== diff --git a/include/openmc/mcpl_interface.h b/include/openmc/mcpl_interface.h index 89dab16bc..c931f1774 100644 --- a/include/openmc/mcpl_interface.h +++ b/include/openmc/mcpl_interface.h @@ -6,20 +6,31 @@ #include #include -#ifdef OPENMC_MCPL -#include -#endif - namespace openmc { +//============================================================================== +// Constants +//============================================================================== + extern "C" const bool MCPL_ENABLED; +//============================================================================== +// Functions +//============================================================================== + //! Get a vector of source sites from an MCPL file // //! \param[in] path Path to MCPL file //! \return Vector of source sites vector mcpl_source_sites(std::string path); +//! Write an MCPL source file +// +//! \param[in] filename Path to MCPL file +//! \param[in] surf_source_bank Whether to use the surface source bank +void write_mcpl_source_point( + const char* filename, bool surf_source_bank = false); + } // namespace openmc #endif // OPENMC_MCPL_INTERFACE_H diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 730127554..5ada2bf88 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -9,10 +9,6 @@ #include "openmc/particle.h" #include "openmc/vector.h" -#ifdef OPENMC_MCPL -#include -#endif - namespace openmc { void load_state_point(); @@ -25,11 +21,5 @@ void write_tally_results_nr(hid_t file_id); void restart_set_keff(); void write_unstructured_mesh_results(); -#ifdef OPENMC_MCPL -void write_mcpl_source_point( - const char* filename, bool surf_source_bank = false); -void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank); -#endif - } // namespace openmc #endif // OPENMC_STATE_POINT_H diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp index d55cc5af7..e9bc64830 100644 --- a/src/mcpl_interface.cpp +++ b/src/mcpl_interface.cpp @@ -1,6 +1,13 @@ #include "openmc/mcpl_interface.h" +#include "openmc/bank.h" #include "openmc/error.h" +#include "openmc/message_passing.h" +#include "openmc/settings.h" +#include "openmc/simulation.h" +#include "openmc/state_point.h" + +#include #ifdef OPENMC_MCPL #include @@ -8,14 +15,22 @@ namespace openmc { +//============================================================================== +// Constants +//============================================================================== + #ifdef OPENMC_MCPL const bool MCPL_ENABLED = true; #else const bool MCPL_ENABLED = false; #endif +//============================================================================== +// Functions +//============================================================================== + #ifdef OPENMC_MCPL -SourceSite mcpl_particle_to_site(const mcpl_particle* particle) +SourceSite mcpl_particle_to_site(const mcpl_particle_t* particle) { SourceSite site; @@ -35,40 +50,42 @@ SourceSite mcpl_particle_to_site(const mcpl_particle* particle) } // Copy position and direction - site.r.x = mcpl_particle->position[0]; - site.r.y = mcpl_particle->position[1]; - site.r.z = mcpl_particle->position[2]; - site.u.x = mcpl_particle->direction[0]; - site.u.y = mcpl_particle->direction[1]; - site.u.z = mcpl_particle->direction[2]; + site.r.x = particle->position[0]; + site.r.y = particle->position[1]; + site.r.z = particle->position[2]; + site.u.x = particle->direction[0]; + site.u.y = particle->direction[1]; + site.u.z = particle->direction[2]; // mcpl stores kinetic energy in MeV - site.E = mcpl_particle->ekin * 1e6; + site.E = particle->ekin * 1e6; // mcpl stores time in ms - site.time = mcpl_particle->time * 1e-3; - site.wgt = mcpl_particle->weight; + site.time = particle->time * 1e-3; + site.wgt = particle->weight; return site; } #endif +//============================================================================== + vector mcpl_source_sites(std::string path) { vector sites; #ifdef OPENMC_MCPL + // Open MCPL file and determine number of particles + auto mcpl_file = mcpl_open_file(path.c_str()); size_t n_sites = mcpl_hdr_nparticles(mcpl_file); for (int i = 0; i < n_sites; i++) { - SourceSite site; - // Extract particle from mcpl-file, checking if it is a neutron, photon, // electron, or positron. Otherwise skip. const mcpl_particle_t* particle; int pdg = 0; while (pdg != 2112 && pdg != 22 && pdg != 11 && pdg != -11) { particle = mcpl_read(mcpl_file); - pdg = mcpl_particle->pdgcode; + pdg = particle->pdgcode; } // Convert to source site and add to vector @@ -76,7 +93,7 @@ vector mcpl_source_sites(std::string path) } // Check that some sites were read - if (sites_.empty()) { + if (sites.empty()) { fatal_error("MCPL file contained no neutron, photon, electron, or positron " "source particles."); } @@ -90,4 +107,144 @@ vector mcpl_source_sites(std::string path) return sites; } +//============================================================================== + +#ifdef OPENMC_MCPL +void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) +{ + int64_t dims_size = settings::n_particles; + int64_t count_size = simulation::work_per_rank; + + // Set vectors for source bank and starting bank index of each process + vector* bank_index = &simulation::work_index; + vector* source_bank = &simulation::source_bank; + vector surf_source_index_vector; + vector surf_source_bank_vector; + + if (surf_source_bank) { + surf_source_index_vector = calculate_surf_source_size(); + dims_size = surf_source_index_vector[mpi::n_procs]; + count_size = simulation::surf_source_bank.size(); + + bank_index = &surf_source_index_vector; + + // Copy data in a SharedArray into a vector. + surf_source_bank_vector.resize(count_size); + surf_source_bank_vector.assign(simulation::surf_source_bank.data(), + simulation::surf_source_bank.data() + count_size); + source_bank = &surf_source_bank_vector; + } + + if (mpi::master) { + // Particles are writeen to disk from the master node only + + // Save source bank sites since the array is overwritten below +#ifdef OPENMC_MPI + vector temp_source {source_bank->begin(), source_bank->end()}; +#endif + + // loop over the other nodes and receive data - then write those. + for (int i = 0; i < mpi::n_procs; ++i) { + // number of particles for node node i + size_t count[] { + static_cast((*bank_index)[i + 1] - (*bank_index)[i])}; + +#ifdef OPENMC_MPI + if (i > 0) + MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + mpi::intracomm, MPI_STATUS_IGNORE); +#endif + // now write the source_bank data again. + for (vector::iterator _site = source_bank->begin(); + _site != source_bank->end(); _site++) { + // particle is now at the iterator + // write it to the mcpl-file + mcpl_particle_t p; + p.position[0] = _site->r.x; + p.position[1] = _site->r.y; + p.position[2] = _site->r.z; + + // mcpl requires that the direction vector is unit length + // which is also the case in openmc + p.direction[0] = _site->u.x; + p.direction[1] = _site->u.y; + p.direction[2] = _site->u.z; + + // mcpl stores kinetic energy in MeV + p.ekin = _site->E * 1e-6; + + p.time = _site->time * 1e3; + + p.weight = _site->wgt; + + switch (_site->particle) { + case ParticleType::neutron: + p.pdgcode = 2112; + break; + case ParticleType::photon: + p.pdgcode = 22; + break; + case ParticleType::electron: + p.pdgcode = 11; + break; + case ParticleType::positron: + p.pdgcode = -11; + break; + } + + mcpl_add_particle(file_id, &p); + } + } +#ifdef OPENMC_MPI + // Restore state of source bank + std::copy(temp_source.begin(), temp_source.end(), source_bank->begin()); +#endif + } else { +#ifdef OPENMC_MPI + MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + mpi::intracomm); +#endif + } +} +#endif + +//============================================================================== + +void write_mcpl_source_point(const char* filename, bool surf_source_bank) +{ + std::string filename_; + if (filename) { + filename_ = filename; + } else { + // Determine width for zero padding + int w = std::to_string(settings::n_max_batches).size(); + + filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, + simulation::current_batch, w); + } + +#ifdef OPENMC_MCPL + mcpl_outfile_t file_id; + + std::string line; + if (mpi::master) { + file_id = mcpl_create_outfile(filename_.c_str()); + if (VERSION_DEV) { + line = fmt::format("OpenMC {0}.{1}.{2}-development", VERSION_MAJOR, + VERSION_MINOR, VERSION_RELEASE); + } else { + line = fmt::format( + "OpenMC {0}.{1}.{2}", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE); + } + mcpl_hdr_set_srcname(file_id, line.c_str()); + } + + write_mcpl_source_bank(file_id, surf_source_bank); + + if (mpi::master) { + mcpl_close_outfile(file_id); + } +#endif +} + } // namespace openmc diff --git a/src/settings.cpp b/src/settings.cpp index bc31e2c4d..cb39d0c8b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -433,10 +433,8 @@ void read_settings_xml() if (check_for_node(node, "file")) { auto path = get_node_value(node, "file", false, true); if (ends_with(path, ".mcpl") || ends_with(path, ".mcpl.gz")) { -#ifdef OPENMC_MCPL auto sites = mcpl_source_sites(path); model::external_sources.push_back(make_unique(sites)); -#endif } else { model::external_sources.push_back(make_unique(path)); } @@ -659,6 +657,12 @@ void read_settings_xml() } if (check_for_node(node_sp, "mcpl")) { source_mcpl_write = get_node_value_bool(node_sp, "mcpl"); + + // Make sure MCPL support is enabled + if (source_mcpl_write && !MCPL_ENABLED) { + fatal_error( + "Your build of OpenMC does not support writing MCPL source files."); + } } if (check_for_node(node_sp, "overwrite_latest")) { source_latest = get_node_value_bool(node_sp, "overwrite_latest"); @@ -690,11 +694,15 @@ void read_settings_xml() max_surface_particles = std::stoll(get_node_value(node_ssw, "max_particles")); } -#ifdef OPENMC_MCPL if (check_for_node(node_ssw, "mcpl")) { - surf_mcpl_write = true; + surf_mcpl_write = get_node_value_bool(node_ssw, "mcpl"); + + // Make sure MCPL support is enabled + if (surf_mcpl_write && !MCPL_ENABLED) { + fatal_error("Your build of OpenMC does not support writing MCPL " + "surface source files."); + } } -#endif } // If source is not separate and is to be written out in the statepoint file, diff --git a/src/simulation.cpp b/src/simulation.cpp index 2c1d1c988..497b26124 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -8,6 +8,7 @@ #include "openmc/event.h" #include "openmc/geometry_aux.h" #include "openmc/material.h" +#include "openmc/mcpl_interface.h" #include "openmc/message_passing.h" #include "openmc/nuclide.h" #include "openmc/output.h" @@ -389,9 +390,7 @@ void finalize_batch() if (settings::run_mode == RunMode::EIGENVALUE) { // Write out a separate source point if it's been specified for this batch -#ifdef OPENMC_MCPL if (!settings::source_mcpl_write) { -#endif if (contains(settings::sourcepoint_batch, simulation::current_batch) && settings::source_write && settings::source_separate) { write_source_point(nullptr); @@ -402,7 +401,6 @@ void finalize_batch() auto filename = settings::path_output + "source.h5"; write_source_point(filename.c_str()); } -#ifdef OPENMC_MCPL } else { if (contains(settings::sourcepoint_batch, simulation::current_batch) && settings::source_mcpl_write && settings::source_separate) { @@ -415,7 +413,6 @@ void finalize_batch() write_mcpl_source_point(filename.c_str()); } } -#endif } // Write out surface source if requested. @@ -424,13 +421,11 @@ void finalize_batch() auto filename = settings::path_output + "surface_source.h5"; write_source_point(filename.c_str(), true); } -#ifdef OPENMC_MCPL if (settings::surf_mcpl_write && simulation::current_batch == settings::n_batches) { auto filename = settings::path_output + "surface_source.mcpl"; write_mcpl_source_point(filename.c_str(), true); } -#endif } void initialize_generation() diff --git a/src/state_point.cpp b/src/state_point.cpp index 9dd0f1374..470dd7718 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -28,10 +28,6 @@ #include "openmc/timer.h" #include "openmc/vector.h" -#ifdef OPENMC_MCPL -#include -#endif - namespace openmc { extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) @@ -603,43 +599,6 @@ void write_source_point(const char* filename, bool surf_source_bank) file_close(file_id); } -#ifdef OPENMC_MCPL -void write_mcpl_source_point(const char* filename, bool surf_source_bank) -{ - std::string filename_; - if (filename) { - filename_ = filename; - } else { - // Determine width for zero padding - int w = std::to_string(settings::n_max_batches).size(); - - filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, - simulation::current_batch, w); - } - - mcpl_outfile_t file_id; - - std::string line; - if (mpi::master) { - file_id = mcpl_create_outfile(filename_.c_str()); - if (VERSION_DEV) { - line = fmt::format("OpenMC {0}.{1}.{2}-development", VERSION_MAJOR, - VERSION_MINOR, VERSION_RELEASE); - } else { - line = fmt::format( - "OpenMC {0}.{1}.{2}", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE); - } - mcpl_hdr_set_srcname(file_id, line.c_str()); - } - - write_mcpl_source_bank(file_id, surf_source_bank); - - if (mpi::master) { - mcpl_close_outfile(file_id); - } -} -#endif - void write_source_bank(hid_t group_id, bool surf_source_bank) { hid_t banktype = h5banktype(); @@ -756,105 +715,6 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Tclose(banktype); } -#ifdef OPENMC_MCPL -void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) -{ - int64_t dims_size = settings::n_particles; - int64_t count_size = simulation::work_per_rank; - - // Set vectors for source bank and starting bank index of each process - vector* bank_index = &simulation::work_index; - vector* source_bank = &simulation::source_bank; - vector surf_source_index_vector; - vector surf_source_bank_vector; - - if (surf_source_bank) { - surf_source_index_vector = calculate_surf_source_size(); - dims_size = surf_source_index_vector[mpi::n_procs]; - count_size = simulation::surf_source_bank.size(); - - bank_index = &surf_source_index_vector; - - // Copy data in a SharedArray into a vector. - surf_source_bank_vector.resize(count_size); - surf_source_bank_vector.assign(simulation::surf_source_bank.data(), - simulation::surf_source_bank.data() + count_size); - source_bank = &surf_source_bank_vector; - } - - if (mpi::master) { - // Particles are writeen to disk from the master node only - - // Save source bank sites since the array is overwritten below -#ifdef OPENMC_MPI - vector temp_source {source_bank->begin(), source_bank->end()}; -#endif - - // loop over the other nodes and receive data - then write those. - for (int i = 0; i < mpi::n_procs; ++i) { - // number of particles for node node i - size_t count[] { - static_cast((*bank_index)[i + 1] - (*bank_index)[i])}; - -#ifdef OPENMC_MPI - if (i > 0) - MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, - mpi::intracomm, MPI_STATUS_IGNORE); -#endif - // now write the source_bank data again. - for (vector::iterator _site = source_bank->begin(); - _site != source_bank->end(); _site++) { - // particle is now at the iterator - // write it to the mcpl-file - mcpl_particle_t p; - p.position[0] = _site->r.x; - p.position[1] = _site->r.y; - p.position[2] = _site->r.z; - - // mcpl requires that the direction vector is unit length - // which is also the case in openmc - p.direction[0] = _site->u.x; - p.direction[1] = _site->u.y; - p.direction[2] = _site->u.z; - - // mcpl stores kinetic energy in MeV - p.ekin = _site->E * 1e-6; - - p.time = _site->time * 1e3; - - p.weight = _site->wgt; - - switch (_site->particle) { - case ParticleType::neutron: - p.pdgcode = 2112; - break; - case ParticleType::photon: - p.pdgcode = 22; - break; - case ParticleType::electron: - p.pdgcode = 11; - break; - case ParticleType::positron: - p.pdgcode = -11; - break; - } - - mcpl_add_particle(file_id, &p); - } - } -#ifdef OPENMC_MPI - // Restore state of source bank - std::copy(temp_source.begin(), temp_source.end(), source_bank->begin()); -#endif - } else { -#ifdef OPENMC_MPI - MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, - mpi::intracomm); -#endif - } -} -#endif - // Determine member names of a compound HDF5 datatype std::string dtype_member_names(hid_t dtype_id) { From 9ae44b3fd1e9c6e26c3f5089c9382a7fe97eb48e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 12:43:31 -0600 Subject: [PATCH 1415/2654] Rearragne MCPL source writing logic --- src/simulation.cpp | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 497b26124..2f07f8124 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -390,27 +390,23 @@ void finalize_batch() if (settings::run_mode == RunMode::EIGENVALUE) { // Write out a separate source point if it's been specified for this batch - if (!settings::source_mcpl_write) { - if (contains(settings::sourcepoint_batch, simulation::current_batch) && - settings::source_write && settings::source_separate) { + if (contains(settings::sourcepoint_batch, simulation::current_batch) && + settings::source_write && settings::source_separate) { + if (settings::source_mcpl_write) { + write_mcpl_source_point(nullptr); + } else { write_source_point(nullptr); } + } - // Write a continously-overwritten source point if requested. - if (settings::source_latest) { - auto filename = settings::path_output + "source.h5"; - write_source_point(filename.c_str()); - } - } else { - if (contains(settings::sourcepoint_batch, simulation::current_batch) && - settings::source_mcpl_write && settings::source_separate) { - write_mcpl_source_point(nullptr); - } - - // Write a continously-overwritten source point if requested. - if (settings::source_latest && settings::source_mcpl_write) { + // Write a continously-overwritten source point if requested. + if (settings::source_latest) { + if (settings::source_mcpl_write) { auto filename = settings::path_output + "source.mcpl"; write_mcpl_source_point(filename.c_str()); + } else { + auto filename = settings::path_output + "source.h5"; + write_source_point(filename.c_str()); } } } @@ -418,13 +414,13 @@ void finalize_batch() // Write out surface source if requested. if (settings::surf_source_write && simulation::current_batch == settings::n_batches) { - auto filename = settings::path_output + "surface_source.h5"; - write_source_point(filename.c_str(), true); - } - if (settings::surf_mcpl_write && - simulation::current_batch == settings::n_batches) { - auto filename = settings::path_output + "surface_source.mcpl"; - write_mcpl_source_point(filename.c_str(), true); + if (settings::surf_mcpl_write) { + auto filename = settings::path_output + "surface_source.mcpl"; + write_mcpl_source_point(filename.c_str(), true); + } else { + auto filename = settings::path_output + "surface_source.h5"; + write_source_point(filename.c_str(), true); + } } } From eeab41a19d8bbe1617f6abb63ff8bb2f89dd24f3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 14:03:26 -0600 Subject: [PATCH 1416/2654] Build against MCPL in CI by default --- tools/ci/gha-install.py | 12 ++++-------- tools/ci/gha-install.sh | 6 ++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index ea317b5f0..83e5afac7 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -19,14 +19,14 @@ def which(program): return None -def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, mcpl=False): +def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): # Create build directory and change to it shutil.rmtree('build', ignore_errors=True) os.mkdir('build') os.chdir('build') - # Build in debug mode by default - cmake_cmd = ['cmake', '-DCMAKE_BUILD_TYPE=Debug'] + # Build in debug mode by default with support for MCPL + cmake_cmd = ['cmake', '-DCMAKE_BUILD_TYPE=Debug', '-DOPENMC_USE_MCPL=on'] # Turn off OpenMP if specified if not omp: @@ -54,9 +54,6 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, mcpl= libmesh_path = os.environ.get('HOME') + '/LIBMESH' cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + libmesh_path) - if mcpl: - cmake_cmd.append('-DOPENMC_USE_MCPL=ON') - # Build in coverage mode for coverage testing cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') @@ -74,10 +71,9 @@ def main(): phdf5 = (os.environ.get('PHDF5') == 'y') dagmc = (os.environ.get('DAGMC') == 'y') libmesh = (os.environ.get('LIBMESH') == 'y') - mcpl = (os.environ.get('MCPL') == 'y') # Build and install - install(omp, mpi, phdf5, dagmc, libmesh, mcpl) + install(omp, mpi, phdf5, dagmc, libmesh) if __name__ == '__main__': main() diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index 68e825d48..75fa0ca70 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -27,10 +27,8 @@ if [[ $LIBMESH = 'y' ]]; then ./tools/ci/gha-install-libmesh.sh fi -# Install mcpl if needed -if [[ $MCPL = 'y' ]]; then - ./tools/ci/gha-install-mcpl.sh -fi +# Install MCPL +./tools/ci/gha-install-mcpl.sh # For MPI configurations, make sure mpi4py and h5py are built against the # correct version of MPI From 47848b79abe964be913095397d1d5aaf2780d28c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 14:34:37 -0600 Subject: [PATCH 1417/2654] Allow Settings.sourcepoint['mcpl'] to be set --- docs/source/io_formats/settings.rst | 14 +++++++++++--- openmc/settings.py | 12 ++++++++++-- tests/unit_tests/test_settings.py | 4 ++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 7174c5317..01b1852ca 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -732,6 +732,14 @@ attributes/sub-elements: *Default*: false + :mcpl: + If this element is set to "true", the source point file containing the + source bank will be written as an MCPL_ file name ``source.mcpl`` instead of + an HDF5 file. This option is only applicable if the ```` element + is set to true. + + *Default*: false + ------------------------------ ```` Element ------------------------------ @@ -769,13 +777,13 @@ certain surfaces and write out the source bank in a separate file called :mcpl: An optional boolean which indicates if the banked particles should be - written to a file in the MCPL-format (documented in mcpl_). instead of the - native HDF5-based format. If activated the output file name is changed to + written to a file in the MCPL_-format instead of the native HDF5-based + format. If activated the output file name is changed to ``surface_source.mcpl``. *Default*: false - .. _mcpl: https://mctools.github.io/mcpl/mcpl.pdf + .. _MCPL: https://mctools.github.io/mcpl/mcpl.pdf ------------------------------ ```` Element diff --git a/openmc/settings.py b/openmc/settings.py index fd622870c..cc0ca2964 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -156,6 +156,7 @@ class Settings: :separate: bool indicating whether the source should be written as a separate file :write: bool indicating whether or not to write the source + :mcpl: bool indicating whether to write the source as an MCPL file statepoint : dict Options for writing state points. Acceptable keys are: @@ -620,6 +621,8 @@ class Settings: cv.check_type('sourcepoint write', value, bool) elif key == 'overwrite': cv.check_type('sourcepoint overwrite', value, bool) + elif key == 'mcpl': + cv.check_type('sourcepoint mcpl', value, bool) else: raise ValueError(f"Unknown key '{key}' encountered when " "setting sourcepoint options.") @@ -1019,6 +1022,11 @@ class Settings: subelement = ET.SubElement(element, "overwrite_latest") subelement.text = str(self._sourcepoint['overwrite']).lower() + if 'mcpl' in self._sourcepoint: + subelement = ET.SubElement(element, "mcpl") + subelement.text = str(self._sourcepoint['mcpl']).lower() + + def _create_surf_source_read_subelement(self, root): if self._surf_source_read: element = ET.SubElement(root, "surf_source_read") @@ -1319,10 +1327,10 @@ class Settings: def _sourcepoint_from_xml_element(self, root): elem = root.find('source_point') if elem is not None: - for key in ('separate', 'write', 'overwrite_latest', 'batches'): + for key in ('separate', 'write', 'overwrite_latest', 'batches', 'mcpl'): value = get_text(elem, key) if value is not None: - if key in ('separate', 'write'): + if key in ('separate', 'write', 'mcpl'): value = value in ('true', '1') elif key == 'overwrite_latest': value = value in ('true', '1') diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 7678711a4..f1ae58192 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -17,7 +17,7 @@ def test_export_to_xml(run_in_tmpdir): s.output = {'summary': True, 'tallies': False, 'path': 'here'} s.verbosity = 7 s.sourcepoint = {'batches': [50, 150, 500, 1000], 'separate': True, - 'write': True, 'overwrite': True} + 'write': True, 'overwrite': True, 'mcpl': True} s.statepoint = {'batches': [50, 150, 500, 1000]} s.surf_source_read = {'path': 'surface_source_1.h5'} s.surf_source_write = {'surface_ids': [2], 'max_particles': 200} @@ -75,7 +75,7 @@ def test_export_to_xml(run_in_tmpdir): assert s.output == {'summary': True, 'tallies': False, 'path': 'here'} assert s.verbosity == 7 assert s.sourcepoint == {'batches': [50, 150, 500, 1000], 'separate': True, - 'write': True, 'overwrite': True} + 'write': True, 'overwrite': True, 'mcpl': True} assert s.statepoint == {'batches': [50, 150, 500, 1000]} assert s.surf_source_read == {'path': 'surface_source_1.h5'} assert s.surf_source_write == {'surface_ids': [2], 'max_particles': 200} From 731eff8817520773670d8a56c3ee4fbf7962cca9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 14:43:58 -0600 Subject: [PATCH 1418/2654] Update source_mcpl_file test result --- tests/regression_tests/source_mcpl_file/results_true.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/source_mcpl_file/results_true.dat b/tests/regression_tests/source_mcpl_file/results_true.dat index e8f4a20a0..5651efde7 100644 --- a/tests/regression_tests/source_mcpl_file/results_true.dat +++ b/tests/regression_tests/source_mcpl_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.004254E-01 8.027600E-04 +2.943088E-01 2.093028E-03 From ddbd61cc97ee2767d81f93b62542a3d367be1c85 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 14:49:47 -0600 Subject: [PATCH 1419/2654] Formatting fixes --- CMakeLists.txt | 1 + openmc/settings.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 466816b30..c6c225783 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,6 +162,7 @@ endif() #=============================================================================== # MCPL #=============================================================================== + if (OPENMC_USE_MCPL) find_package(MCPL REQUIRED) message(STATUS "Found MCPL: ${MCPL_DIR} (found version \"${MCPL_VERSION}\")") diff --git a/openmc/settings.py b/openmc/settings.py index cc0ca2964..e445655ca 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1026,7 +1026,6 @@ class Settings: subelement = ET.SubElement(element, "mcpl") subelement.text = str(self._sourcepoint['mcpl']).lower() - def _create_surf_source_read_subelement(self, root): if self._surf_source_read: element = ET.SubElement(root, "surf_source_read") From 25f2bd50f9005cf8fa05ea055ebce0384d488106 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 18:27:42 -0600 Subject: [PATCH 1420/2654] Several small fixes --- openmc/_xml.py | 2 +- openmc/model/model.py | 12 ++++-------- openmc/settings.py | 5 +++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/openmc/_xml.py b/openmc/_xml.py index 2a33d4b8d..6799a4e2d 100644 --- a/openmc/_xml.py +++ b/openmc/_xml.py @@ -27,7 +27,7 @@ def clean_indentation(element, level=0, spaces_per_level=2, trailing_indent=True element.tail = i for sub_element in element: # `trailing_indent` is intentionally not forwarded to the recursive - # call. Any child element of the topmost clement should add + # call. Any child element of the topmost element should add # indentation at the end to ensure its parent's indentation is # correct. clean_indentation(sub_element, level+1, spaces_per_level) diff --git a/openmc/model/model.py b/openmc/model/model.py index 7c6d9b828..2f4489084 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -244,6 +244,8 @@ class Model: def from_model_xml(cls, path='model.xml'): """Create model from single XML file + .. vesionadded:: 0.13.3 + Parameters ---------- path : str or Pathlike @@ -259,13 +261,6 @@ class Model: model.materials = openmc.Materials.from_xml_element(root.find('materials')) model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) - # gather meshes from other classes before reading the tally node - if model.settings.entropy_mesh is not None: - meshes[model.settings.entropy_mesh.id] = model.settings.entropy_mesh - - for ww in model.settings.weight_windows: - meshes[ww.mesh.id] = ww.mesh - if root.find('tallies'): model.tallies = openmc.Tallies.from_xml_element(root.find('tallies'), meshes) @@ -474,6 +469,8 @@ class Model: def export_to_model_xml(self, path='model.xml', remove_surfs=False): """Export model to a single XML file. + .. versionadded:: 0.13.3 + Parameters ---------- path : str or Pathlike @@ -483,7 +480,6 @@ class Model: Whether or not to remove redundant surfaces from the geometry when exporting. - .. versionadded:: 0.13.1 """ xml_path = Path(path) # if the provided path doesn't end with the XML extension, assume the diff --git a/openmc/settings.py b/openmc/settings.py index 65ca71957..4e6f144fe 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1100,7 +1100,8 @@ class Settings: path = f"./mesh[@id='{self.entropy_mesh.id}']" if root.find(path) is None: root.append(self.entropy_mesh.to_xml_element()) - if mesh_memo is not None: mesh_memo.add(self.entropy_mesh.id) + if mesh_memo is not None: + mesh_memo.add(self.entropy_mesh.id) def _create_trigger_subelement(self, root): if self._trigger_active is not None: @@ -1609,7 +1610,7 @@ class Settings: self._create_temperature_subelements(element) self._create_trace_subelement(element) self._create_track_subelement(element) - self._create_ufs_mesh_subelement(element) + self._create_ufs_mesh_subelement(element, mesh_memo) self._create_resonance_scattering_subelement(element) self._create_volume_calcs_subelement(element) self._create_create_fission_neutrons_subelement(element) From a0d8541a0164e19732ff3ce50b94ae9f83e0da13 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 22 Dec 2022 22:27:03 -0600 Subject: [PATCH 1421/2654] Make sure OpenMCConfig.cmake.in includes MCPL --- cmake/OpenMCConfig.cmake.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/OpenMCConfig.cmake.in b/cmake/OpenMCConfig.cmake.in index d0e2beb82..1e3508305 100644 --- a/cmake/OpenMCConfig.cmake.in +++ b/cmake/OpenMCConfig.cmake.in @@ -25,3 +25,7 @@ endif() if(@OPENMC_USE_MPI@) find_package(MPI REQUIRED) endif() + +if(@OPENMC_USE_MCPL@) + find_package(MCPL REQUIRED) +endif() From ecfa94e0ff0c50a83c8db61444e5cad888b16c7a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 14:25:22 -0500 Subject: [PATCH 1422/2654] Rename gnd_name to gnds_name. Change GND to GNDS in comments --- docs/source/pythonapi/data.rst | 2 +- docs/source/usersguide/scripts.rst | 4 ++-- openmc/data/ace.py | 4 ++-- openmc/data/data.py | 19 +++++++++++-------- openmc/data/decay.py | 2 +- openmc/data/endf.py | 12 ++++++------ openmc/data/multipole.py | 4 ++-- openmc/data/neutron.py | 4 ++-- openmc/data/reaction.py | 2 +- openmc/data/thermal.py | 10 +++++----- openmc/deplete/chain.py | 16 ++++++++-------- openmc/deplete/nuclide.py | 2 +- openmc/nuclide.py | 2 +- scripts/openmc-update-inputs | 5 ++--- tests/unit_tests/test_data_misc.py | 12 ++++++------ 15 files changed, 51 insertions(+), 49 deletions(-) diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 960abec2f..1eaf90c97 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -66,7 +66,7 @@ Core Functions decay_energy decay_photon_energy dose_coefficients - gnd_name + gnds_name half_life isotopes kalbach_slope diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst index c433ffe2c..78ee6f775 100644 --- a/docs/source/usersguide/scripts.rst +++ b/docs/source/usersguide/scripts.rst @@ -157,9 +157,9 @@ geometry.xml added. Any 'surfaces' attributes/elements on a cell will be renamed 'region'. materials.xml - Nuclide names will be changed from ACE aliases (e.g., Am-242m) to HDF5/GND + Nuclide names will be changed from ACE aliases (e.g., Am-242m) to HDF5/GNDS names (e.g., Am242_m1). Thermal scattering table names will be changed from - ACE aliases (e.g., HH2O) to HDF5/GND names (e.g., c_H_in_H2O). + ACE aliases (e.g., HH2O) to HDF5/GNDS names (e.g., c_H_in_H2O). ---------------------- ``openmc-update-mgxs`` diff --git a/openmc/data/ace.py b/openmc/data/ace.py index 06c581b42..91cbe4196 100644 --- a/openmc/data/ace.py +++ b/openmc/data/ace.py @@ -24,7 +24,7 @@ import numpy as np import openmc.checkvalue as cv from openmc.mixin import EqualityMixin -from .data import ATOMIC_SYMBOL, gnd_name, EV_PER_MEV, K_BOLTZMANN +from .data import ATOMIC_SYMBOL, gnds_name, EV_PER_MEV, K_BOLTZMANN from .endf import ENDF_FLOAT_RE @@ -88,7 +88,7 @@ def get_metadata(zaid, metastable_scheme='nndc'): # Determine name element = ATOMIC_SYMBOL[Z] - name = gnd_name(Z, mass_number, metastable) + name = gnds_name(Z, mass_number, metastable) return (name, element, Z, mass_number, metastable) diff --git a/openmc/data/data.py b/openmc/data/data.py index 55bfb4f09..d5521d998 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -197,8 +197,8 @@ NEUTRON_MASS = 1.00866491595 # Used in atomic_mass function as a cache _ATOMIC_MASS = {} -# Regex for GND nuclide names (used in zam function) -_GND_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)') +# Regex for GNDS nuclide names (used in zam function) +_GNDS_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)') # Used in half_life function as a cache _HALF_LIFE = {} @@ -436,8 +436,11 @@ def water_density(temperature, pressure=0.1013): return coeff / pi / gamma1_pi -def gnd_name(Z, A, m=0): - """Return nuclide name using GND convention +def gnds_name(Z, A, m=0): + """Return nuclide name using GNDS convention + + .. versionchanged:: 0.14.0 + Function name changed from ``gnd_name`` to ``gnds_name`` Parameters ---------- @@ -451,7 +454,7 @@ def gnd_name(Z, A, m=0): Returns ------- str - Nuclide name in GND convention, e.g., 'Am242_m1' + Nuclide name in GNDS convention, e.g., 'Am242_m1' """ if m > 0: @@ -502,7 +505,7 @@ def zam(name): Parameters ---------- name : str - Name of nuclide using GND convention, e.g., 'Am242_m1' + Name of nuclide using GNDS convention, e.g., 'Am242_m1' Returns ------- @@ -511,10 +514,10 @@ def zam(name): """ try: - symbol, A, state = _GND_NAME_RE.match(name).groups() + symbol, A, state = _GNDS_NAME_RE.match(name).groups() except AttributeError: raise ValueError(f"'{name}' does not appear to be a nuclide name in " - "GND format") + "GNDS format") if symbol not in ATOMIC_NUMBER: raise ValueError(f"'{symbol}' is not a recognized element symbol") diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 0db842201..d00242438 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -144,7 +144,7 @@ class FissionProductYields(EqualityMixin): # Assign basic nuclide properties self.nuclide = { - 'name': ev.gnd_name, + 'name': ev.gnds_name, 'atomic_number': ev.target['atomic_number'], 'mass_number': ev.target['mass_number'], 'isomeric_state': ev.target['isomeric_state'] diff --git a/openmc/data/endf.py b/openmc/data/endf.py index f9b9d0694..d526bc53f 100644 --- a/openmc/data/endf.py +++ b/openmc/data/endf.py @@ -12,7 +12,7 @@ import re import numpy as np -from .data import gnd_name +from .data import gnds_name from .function import Tabulated1D try: from ._endf import float_endf @@ -520,10 +520,10 @@ class Evaluation: self.reaction_list.append((mf, mt, nc, mod)) @property - def gnd_name(self): - return gnd_name(self.target['atomic_number'], - self.target['mass_number'], - self.target['isomeric_state']) + def gnds_name(self): + return gnds_name(self.target['atomic_number'], + self.target['mass_number'], + self.target['isomeric_state']) class Tabulated2D: @@ -531,7 +531,7 @@ class Tabulated2D: This is a dummy class that is not really used other than to store the interpolation information for a two-dimensional function. Once we refactor - to adopt GND-like data containers, this will probably be removed or + to adopt GNDS-like data containers, this will probably be removed or extended. Parameters diff --git a/openmc/data/multipole.py b/openmc/data/multipole.py index 508c76ac4..0be70cdba 100644 --- a/openmc/data/multipole.py +++ b/openmc/data/multipole.py @@ -748,12 +748,12 @@ class WindowedMultipole(EqualityMixin): Parameters ---------- name : str - Name of the nuclide using the GND naming convention + Name of the nuclide using the GNDS naming convention Attributes ---------- name : str - Name of the nuclide using the GND naming convention + Name of the nuclide using the GNDS naming convention spacing : float The width of each window in sqrt(E)-space. For example, the frst window will end at (sqrt(E_min) + spacing)**2 and the second window at diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py index e0574d76d..2d4c13963 100644 --- a/openmc/data/neutron.py +++ b/openmc/data/neutron.py @@ -44,7 +44,7 @@ class IncidentNeutron(EqualityMixin): Parameters ---------- name : str - Name of the nuclide using the GND naming convention + Name of the nuclide using the GNDS naming convention atomic_number : int Number of protons in the target nucleus mass_number : int @@ -75,7 +75,7 @@ class IncidentNeutron(EqualityMixin): Metastable state of the target nucleus. A value of zero indicates ground state. name : str - Name of the nuclide using the GND naming convention + Name of the nuclide using the GNDS naming convention reactions : collections.OrderedDict Contains the cross sections, secondary angle and energy distributions, and other associated data for each reaction. The keys are the MT values diff --git a/openmc/data/reaction.py b/openmc/data/reaction.py index a2431cf1c..ac9d7f14e 100644 --- a/openmc/data/reaction.py +++ b/openmc/data/reaction.py @@ -555,7 +555,7 @@ def _get_activation_products(ev, rx): Z, A = divmod(items[2], 1000) excited_state = items[3] - # Get GND name for product + # Get GNDS name for product symbol = ATOMIC_SYMBOL[Z] if excited_state > 0: name = '{}{}_e{}'.format(symbol, A, excited_state) diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index e6213e5f0..48f6bfc9b 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -104,7 +104,7 @@ def get_thermal_name(name): Returns ------- str - GND-format thermal scattering name + GNDS-format thermal scattering name """ if name in _THERMAL_NAMES: @@ -396,7 +396,7 @@ class ThermalScattering(EqualityMixin): Parameters ---------- name : str - Name of the material using GND convention, e.g. c_H_in_H2O + Name of the material using GNDS convention, e.g. c_H_in_H2O atomic_weight_ratio : float Atomic mass ratio of the target nuclide. kTs : Iterable of float @@ -415,7 +415,7 @@ class ThermalScattering(EqualityMixin): Inelastic scattering cross section derived in the incoherent approximation name : str - Name of the material using GND convention, e.g. c_H_in_H2O + Name of the material using GNDS convention, e.g. c_H_in_H2O temperatures : Iterable of str List of string representations the temperatures of the target nuclide in the data set. The temperatures are strings of the temperature, @@ -491,7 +491,7 @@ class ThermalScattering(EqualityMixin): ACE table to read from. If given as a string, it is assumed to be the filename for the ACE file. name : str - GND-conforming name of the material, e.g. c_H_in_H2O. If none is + GNDS-conforming name of the material, e.g. c_H_in_H2O. If none is passed, the appropriate name is guessed based on the name of the ACE table. @@ -596,7 +596,7 @@ class ThermalScattering(EqualityMixin): ACE table to read from. If given as a string, it is assumed to be the filename for the ACE file. name : str - GND-conforming name of the material, e.g. c_H_in_H2O. If none is + GNDS-conforming name of the material, e.g. c_H_in_H2O. If none is passed, the appropriate name is guessed based on the name of the ACE table. diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index f439cedc3..372ed3510 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -15,7 +15,7 @@ from numbers import Real, Integral from warnings import warn from openmc.checkvalue import check_type, check_greater_than -from openmc.data import gnd_name, zam, DataLibrary +from openmc.data import gnds_name, zam, DataLibrary from openmc.exceptions import DataError from .nuclide import FissionYieldDistribution @@ -135,14 +135,14 @@ def replace_missing(product, decay_data): Parameters ---------- product : str - Name of product in GND format, e.g. 'Y86_m1'. + Name of product in GNDS format, e.g. 'Y86_m1'. decay_data : dict Dictionary of decay data Returns ------- product : str - Replacement for missing product in GND format. + Replacement for missing product in GNDS format. """ # Determine atomic number, mass number, and metastable state @@ -213,7 +213,7 @@ def replace_missing_fpy(actinide, fpy_data, decay_data): # Check if metastable state has data (e.g., Am242m) Z, A, m = zam(actinide) if m == 0: - metastable = gnd_name(Z, A, 1) + metastable = gnds_name(Z, A, 1) if metastable in fpy_data: return metastable @@ -222,7 +222,7 @@ def replace_missing_fpy(actinide, fpy_data, decay_data): while isotone in decay_data: Z += 1 A += 1 - isotone = gnd_name(Z, A, 0) + isotone = gnds_name(Z, A, 0) if isotone in fpy_data: return isotone @@ -231,7 +231,7 @@ def replace_missing_fpy(actinide, fpy_data, decay_data): while isotone in decay_data: Z -= 1 A -= 1 - isotone = gnd_name(Z, A, 0) + isotone = gnds_name(Z, A, 0) if isotone in fpy_data: return isotone @@ -357,7 +357,7 @@ class Chain: reactions = {} for f in neutron_files: evaluation = openmc.data.endf.Evaluation(f) - name = evaluation.gnd_name + name = evaluation.gnds_name reactions[name] = {} for mf, mt, nc, mod in evaluation.reaction_list: if mf == 3: @@ -904,7 +904,7 @@ class Chain: ground_target = grounds.get(parent_name) if ground_target is None: pz, pa, pm = zam(parent_name) - ground_target = gnd_name(pz, pa + 1, 0) + ground_target = gnds_name(pz, pa + 1, 0) new_ratios[ground_target] = ground_br parent.add_reaction(reaction, ground_target, rxn_Q, ground_br) diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py index b84b91a7f..2e9673d5f 100644 --- a/openmc/deplete/nuclide.py +++ b/openmc/deplete/nuclide.py @@ -82,7 +82,7 @@ class Nuclide: Parameters ---------- name : str, optional - GND name of this nuclide, e.g. ``"He4"``, ``"Am242_m1"`` + GNDS name of this nuclide, e.g. ``"He4"``, ``"Am242_m1"`` Attributes ---------- diff --git a/openmc/nuclide.py b/openmc/nuclide.py index 196c8d770..d5ae4bddb 100644 --- a/openmc/nuclide.py +++ b/openmc/nuclide.py @@ -26,7 +26,7 @@ class Nuclide(str): if name.endswith('m'): name = name[:-1] + '_m1' - msg = ('OpenMC nuclides follow the GND naming convention. ' + msg = ('OpenMC nuclides follow the GNDS naming convention. ' f'Nuclide "{orig_name}" is being renamed as "{name}".') warnings.warn(msg) diff --git a/scripts/openmc-update-inputs b/scripts/openmc-update-inputs index c47f888c8..2d49c0626 100755 --- a/scripts/openmc-update-inputs +++ b/scripts/openmc-update-inputs @@ -4,7 +4,6 @@ """ import argparse -from difflib import get_close_matches from itertools import chain from random import randint from shutil import move @@ -27,8 +26,8 @@ geometry.xml: Lattices containing 'outside' attributes/tags will be replaced will be renamed 'region'. materials.xml: Nuclide names will be changed from ACE aliases (e.g., Am-242m) to - HDF5/GND names (e.g., Am242_m1). Thermal scattering table names will be - changed from ACE aliases (e.g., HH2O) to HDF5/GND names (e.g., c_H_in_H2O). + HDF5/GNDS names (e.g., Am242_m1). Thermal scattering table names will be + changed from ACE aliases (e.g., HH2O) to HDF5/GNDS names (e.g., c_H_in_H2O). """ diff --git a/tests/unit_tests/test_data_misc.py b/tests/unit_tests/test_data_misc.py index 37e024fe2..f88be2602 100644 --- a/tests/unit_tests/test_data_misc.py +++ b/tests/unit_tests/test_data_misc.py @@ -101,12 +101,12 @@ def test_water_density(): assert dens(500.0, 3.0) == pytest.approx(1e-3/0.120241800e-2, 1e-6) -def test_gnd_name(): - assert openmc.data.gnd_name(1, 1) == 'H1' - assert openmc.data.gnd_name(40, 90) == ('Zr90') - assert openmc.data.gnd_name(95, 242, 0) == ('Am242') - assert openmc.data.gnd_name(95, 242, 1) == ('Am242_m1') - assert openmc.data.gnd_name(95, 242, 10) == ('Am242_m10') +def test_gnds_name(): + assert openmc.data.gnds_name(1, 1) == 'H1' + assert openmc.data.gnds_name(40, 90) == ('Zr90') + assert openmc.data.gnds_name(95, 242, 0) == ('Am242') + assert openmc.data.gnds_name(95, 242, 1) == ('Am242_m1') + assert openmc.data.gnds_name(95, 242, 10) == ('Am242_m10') def test_isotopes(): From a5bdbd3adbc18ec429647c4b0ae9cee7098d7025 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 23 Dec 2022 00:04:45 -0600 Subject: [PATCH 1423/2654] Address a few warnings from tests --- openmc/mgxs/mgxs.py | 4 ++-- tests/regression_tests/diff_tally/test.py | 5 ++--- tests/regression_tests/surface_tally/test.py | 5 ++--- tests/unit_tests/test_mesh_to_vtk.py | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 15a1128f8..c93b42b88 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -925,7 +925,7 @@ class MGXS: # Tabulate the atomic number densities for all nuclides elif nuclides == 'all': nuclides = self.get_nuclides() - densities = np.zeros(self.num_nuclides, dtype=np.float) + densities = np.zeros(self.num_nuclides, dtype=float) for i, nuclide in enumerate(nuclides): densities[i] += self.get_nuclide_density(nuclide) @@ -3019,7 +3019,7 @@ class DiffusionCoefficient(TransportXS): new_filt = openmc.EnergyFilter(old_filt.values) p1_tally.filters[-2] = new_filt - p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], + p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], filter_bins=[('P1',)],squeeze=True) p1_tally._scores = ['scatter-1'] total_xs = self.tallies['total'] / self.tallies['flux (tracklength)'] diff --git a/tests/regression_tests/diff_tally/test.py b/tests/regression_tests/diff_tally/test.py index b688e6d23..18c501372 100644 --- a/tests/regression_tests/diff_tally/test.py +++ b/tests/regression_tests/diff_tally/test.py @@ -103,9 +103,8 @@ class DiffTallyTestHarness(PyAPITestHarness): sp = openmc.StatePoint(statepoint) # Extract the tally data as a Pandas DataFrame. - df = pd.DataFrame() - for t in sp.tallies.values(): - df = df.append(t.get_pandas_dataframe(), ignore_index=True) + tally_dfs = [t.get_pandas_dataframe() for t in sp.tallies.values()] + df = pd.concat(tally_dfs, ignore_index=True) # Extract the relevant data as a CSV string. cols = ('d_material', 'd_nuclide', 'd_variable', 'score', 'mean', diff --git a/tests/regression_tests/surface_tally/test.py b/tests/regression_tests/surface_tally/test.py index 96199ec2a..d21f361e6 100644 --- a/tests/regression_tests/surface_tally/test.py +++ b/tests/regression_tests/surface_tally/test.py @@ -164,9 +164,8 @@ class SurfaceTallyTestHarness(PyAPITestHarness): sp = openmc.StatePoint(self._sp_name) # Extract the tally data as a Pandas DataFrame. - df = pd.DataFrame() - for t in sp.tallies.values(): - df = df.append(t.get_pandas_dataframe(), ignore_index=True) + tally_dfs = [t.get_pandas_dataframe() for t in sp.tallies.values()] + df = pd.concat(tally_dfs, ignore_index=True) # Extract the relevant data as a CSV string. cols = ('mean', 'std. dev.') diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index d7d5907a2..f90eab134 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -77,8 +77,8 @@ def test_write_data_to_vtk_size_mismatch(mesh): # by regex. These are needed to make the test string match the error message # string when using the match argument as that uses regular expression expected_error_msg = ( - f"The size of the dataset 'label' \({len(data)}\) should be equal to " - f"the number of mesh cells \({mesh.num_mesh_cells}\)" + f"The size of the dataset 'label' ({len(data)}) should be equal to " + f"the number of mesh cells ({mesh.num_mesh_cells})" ) with pytest.raises(ValueError, match=expected_error_msg): mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) From f9c6765eca0026291bf760cb8f33866fe367034b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 12 Dec 2022 21:39:39 -0600 Subject: [PATCH 1424/2654] Update intersphinx URLs --- docs/source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f08333279..ae329dd7e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -247,7 +247,7 @@ napoleon_use_ivar = True intersphinx_mapping = { 'python': ('https://docs.python.org/3', None), 'numpy': ('https://numpy.org/doc/stable/', None), - 'scipy': ('https://docs.scipy.org/doc/scipy/reference', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/', None), 'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None), - 'matplotlib': ('https://matplotlib.org/', None) + 'matplotlib': ('https://matplotlib.org/stable/', None) } From a178f5f85a95d3eb519da91b9e462ae5d906be0c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 23 Dec 2022 10:55:58 -0600 Subject: [PATCH 1425/2654] Use raw f-string in test_mesh_to_vtk.py --- tests/unit_tests/test_mesh_to_vtk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index f90eab134..bc3633c8c 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -77,8 +77,8 @@ def test_write_data_to_vtk_size_mismatch(mesh): # by regex. These are needed to make the test string match the error message # string when using the match argument as that uses regular expression expected_error_msg = ( - f"The size of the dataset 'label' ({len(data)}) should be equal to " - f"the number of mesh cells ({mesh.num_mesh_cells})" + fr"The size of the dataset 'label' \({len(data)}\) should be equal to " + fr"the number of mesh cells \({mesh.num_mesh_cells}\)" ) with pytest.raises(ValueError, match=expected_error_msg): mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) From 954a2bdcdaf47cfbf778f0e07e0c4ab3fba17175 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 23 Dec 2022 11:12:22 -0600 Subject: [PATCH 1426/2654] Fix source definition in source_mcpl_file test --- include/openmc/mcpl_interface.h | 2 +- src/mcpl_interface.cpp | 31 +++++++++---------- .../source_mcpl_file/results_true.dat | 2 +- .../source_mcpl_file/settings.xml | 1 - .../regression_tests/source_mcpl_file/test.py | 3 +- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/openmc/mcpl_interface.h b/include/openmc/mcpl_interface.h index c931f1774..64f15c13a 100644 --- a/include/openmc/mcpl_interface.h +++ b/include/openmc/mcpl_interface.h @@ -2,9 +2,9 @@ #define OPENMC_MCPL_INTERFACE_H #include "openmc/particle_data.h" +#include "openmc/vector.h" #include -#include namespace openmc { diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp index e9bc64830..a38891478 100644 --- a/src/mcpl_interface.cpp +++ b/src/mcpl_interface.cpp @@ -6,6 +6,7 @@ #include "openmc/settings.h" #include "openmc/simulation.h" #include "openmc/state_point.h" +#include "openmc/vector.h" #include @@ -57,9 +58,8 @@ SourceSite mcpl_particle_to_site(const mcpl_particle_t* particle) site.u.y = particle->direction[1]; site.u.z = particle->direction[2]; - // mcpl stores kinetic energy in MeV + // MCPL stores kinetic energy in [MeV], time in [ms] site.E = particle->ekin * 1e6; - // mcpl stores time in ms site.time = particle->time * 1e-3; site.wgt = particle->weight; @@ -155,29 +155,26 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) mpi::intracomm, MPI_STATUS_IGNORE); #endif // now write the source_bank data again. - for (vector::iterator _site = source_bank->begin(); - _site != source_bank->end(); _site++) { + for (const auto& site : *source_bank) { // particle is now at the iterator // write it to the mcpl-file mcpl_particle_t p; - p.position[0] = _site->r.x; - p.position[1] = _site->r.y; - p.position[2] = _site->r.z; + p.position[0] = site.r.x; + p.position[1] = site.r.y; + p.position[2] = site.r.z; // mcpl requires that the direction vector is unit length // which is also the case in openmc - p.direction[0] = _site->u.x; - p.direction[1] = _site->u.y; - p.direction[2] = _site->u.z; + p.direction[0] = site.u.x; + p.direction[1] = site.u.y; + p.direction[2] = site.u.z; - // mcpl stores kinetic energy in MeV - p.ekin = _site->E * 1e-6; + // MCPL stores kinetic energy in [MeV], time in [ms] + p.ekin = site.E * 1e-6; + p.time = site.time * 1e3; + p.weight = site.wgt; - p.time = _site->time * 1e3; - - p.weight = _site->wgt; - - switch (_site->particle) { + switch (site.particle) { case ParticleType::neutron: p.pdgcode = 2112; break; diff --git a/tests/regression_tests/source_mcpl_file/results_true.dat b/tests/regression_tests/source_mcpl_file/results_true.dat index 5651efde7..0a98e9d8c 100644 --- a/tests/regression_tests/source_mcpl_file/results_true.dat +++ b/tests/regression_tests/source_mcpl_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.943088E-01 2.093028E-03 +3.009416E-01 3.229999E-03 diff --git a/tests/regression_tests/source_mcpl_file/settings.xml b/tests/regression_tests/source_mcpl_file/settings.xml index 2e511461f..47b010bff 100644 --- a/tests/regression_tests/source_mcpl_file/settings.xml +++ b/tests/regression_tests/source_mcpl_file/settings.xml @@ -1,6 +1,5 @@ - 1234 diff --git a/tests/regression_tests/source_mcpl_file/test.py b/tests/regression_tests/source_mcpl_file/test.py index 60e0ad50f..84ec005ae 100644 --- a/tests/regression_tests/source_mcpl_file/test.py +++ b/tests/regression_tests/source_mcpl_file/test.py @@ -11,7 +11,6 @@ pytestmark = pytest.mark.skipif( settings1=""" - 1234 @@ -35,7 +34,7 @@ settings2 = """ 1000 - source.10.{0} + source.10.{} """ From 6b0baf8b1d3a823605fb9d8ed9b3a51b409ca61e Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 23 Dec 2022 12:54:24 -0500 Subject: [PATCH 1427/2654] added catch2 testing to ci workflow --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e267c0d8e..e9ac04d59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,7 +118,9 @@ jobs: - name: test shell: bash - run: $GITHUB_WORKSPACE/tools/ci/gha-script.sh + run: | + $GITHUB_WORKSPACE/tools/ci/gha-script.sh + ctest --output-on-failure - name: after_success shell: bash From 761bfc53498de1b1d3f26ae83d26a4105d455b09 Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 23 Dec 2022 12:54:59 -0500 Subject: [PATCH 1428/2654] added documentation on unit testing with catch2 --- docs/source/devguide/tests.rst | 27 ++++++++++++++++++++++++++- tests/cpp_unit_tests/CMakeLists.txt | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/source/devguide/tests.rst b/docs/source/devguide/tests.rst index 922f47eb3..d076511b1 100644 --- a/docs/source/devguide/tests.rst +++ b/docs/source/devguide/tests.rst @@ -45,7 +45,7 @@ Prerequisites Running Tests ------------- -To execute the test suite, go to the ``tests/`` directory and run:: +To execute the Python test suite, go to the ``tests/`` directory and run:: pytest @@ -55,6 +55,14 @@ installed and run:: pytest --cov=../openmc --cov-report=html +To execute the C++ test suite, go to your build directory and run:: + + ctest + +If you want to view testing output on failure run:: + + ctest --output-on-failure + Generating XML Inputs --------------------- @@ -66,6 +74,23 @@ run:: pytest --build-inputs +Adding C++ Unit Tests +--------------------- + +The C++ test suite uses Catch2 integrated with CTest. Each header file should +have a corresponding test file in ``tests/cpp_unit_tests/``. If the test file +does not exist run:: + + touch test_.cpp + +The file must be added to the CMake build system in +``tests/cpp_unit_tests/CMakeLists.txt``. ``test_`` should +be added to ``TEST_NAMES``. + +To add a test case to ``test_.cpp`` ensure +``catch2/catch_test_macros.hpp`` is included. A unit test can then be added +using the ``TEST_CASE`` macro and the ``REQUIRE`` assertion from Catch2. + Adding Tests to the Regression Suite ------------------------------------ diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index c26547f77..3d48545b4 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -1,5 +1,6 @@ set(TEST_NAMES test_distribution + # Add additional unit test files here ) foreach(test ${TEST_NAMES}) From ea1feef6e24eebb485659cbbf9ca3e6012be5b7f Mon Sep 17 00:00:00 2001 From: myerspat Date: Fri, 23 Dec 2022 14:40:54 -0500 Subject: [PATCH 1429/2654] changing CTest workflow in CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9ac04d59..60a331e89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,8 +119,8 @@ jobs: - name: test shell: bash run: | + make CTEST_OUTPUT_ON_FAILURE=1 test -C $GITHUB_WORKSPACE/build/ $GITHUB_WORKSPACE/tools/ci/gha-script.sh - ctest --output-on-failure - name: after_success shell: bash From 577157b846ac6885251ade59456967e4102d6b24 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 24 Dec 2022 22:40:34 +0000 Subject: [PATCH 1430/2654] allowing xml file for materials --- openmc/geometry.py | 29 +++++++++++++++++++---------- tests/unit_tests/test_geometry.py | 19 ++++++++++++++++++- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index a43899daa..eb7fa8200 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -1,3 +1,5 @@ +import os +import typing from collections import OrderedDict, defaultdict from collections.abc import Iterable from copy import deepcopy @@ -7,7 +9,7 @@ import warnings import openmc import openmc._xml as xml -from .checkvalue import check_type, check_less_than, check_greater_than +from .checkvalue import check_type, check_less_than, check_greater_than, PathLike class Geometry: @@ -254,16 +256,20 @@ class Geometry: raise ValueError('Error determining root universe.') @classmethod - def from_xml(cls, path='geometry.xml', materials=None): + def from_xml( + cls, + path: PathLike = 'geometry.xml', + materials: typing.Optional[typing.Union[PathLike, 'openmc.Materials']] = 'materials.xml' + ): """Generate geometry from XML file Parameters ---------- - path : str, optional + path : PathLike, optional Path to geometry XML file - materials : openmc.Materials or None - Materials used to assign to cells. If None, an attempt is made to - generate it from the materials.xml file. + materials : openmc.Materials or or PathLike + Materials used to assign to cells. If PathLike, an attempt is made + to generate materials from the provided xml file. Returns ------- @@ -271,10 +277,13 @@ class Geometry: Geometry object """ - # Create dictionary to easily look up materials - if materials is None: - filename = Path(path).parent / 'materials.xml' - materials = openmc.Materials.from_xml(str(filename)) + + # Using str and os.Pathlike here to avoid error when using just the imported PathLike + # TypeError: Subscripted generics cannot be used with class and instance checks + check_type('materials', materials, (str, os.PathLike, openmc.Materials)) + + if isinstance(materials, (str, os.PathLike)): + materials = openmc.Materials.from_xml(materials) tree = ET.parse(path) root = tree.getroot() diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py index 9db112fd2..843c01def 100644 --- a/tests/unit_tests/test_geometry.py +++ b/tests/unit_tests/test_geometry.py @@ -1,4 +1,5 @@ import xml.etree.ElementTree as ET +from pathlib import Path import numpy as np import openmc @@ -274,7 +275,23 @@ def test_from_xml(run_in_tmpdir, mixed_lattice_model): # Export model mixed_lattice_model.export_to_xml() - # Import geometry + mats_from_xml = openmc.Materials.from_xml('materials.xml') + # checking string a Path are both acceptable + for path in ['geometry.xml', Path('geometry.xml')]: + for materials in [mats_from_xml, 'materials.xml']: + # Import geometry from file + geom = openmc.Geometry.from_xml(path=path, materials=materials) + assert isinstance(geom, openmc.Geometry) + ll, ur = geom.bounding_box + assert ll == pytest.approx((-6.0, -6.0, -np.inf)) + assert ur == pytest.approx((6.0, 6.0, np.inf)) + + with pytest.raises(TypeError) as excinfo: + geom = openmc.Geometry.from_xml(path='geometry.xml', materials=None) + assert 'Unable to set "materials" to "None"' in str(excinfo.value) + + + # checking that the default args also work geom = openmc.Geometry.from_xml() assert isinstance(geom, openmc.Geometry) ll, ur = geom.bounding_box From 238ab5210ee951dbfb6b91f0f14feac1a8e673ba Mon Sep 17 00:00:00 2001 From: NybergWISC Date: Fri, 10 Jun 2022 13:31:39 -0500 Subject: [PATCH 1431/2654] Initial Mesh Sampling Changes --- include/openmc/mesh.h | 17 +++++++++ src/mesh.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index eece0f1ff..6bf49b221 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -75,6 +75,12 @@ public: // Methods + //! Sample a mesh volume using a certain seed + // + //! \param[in] seed Seed to use for random sampling + //! \param[out] r Position within tet + virtual Position sample(uint64_t* seed) const=0; + //! Determine which bins were crossed by a particle // //! \param[in] r0 Previous position of the particle @@ -160,6 +166,8 @@ public: } }; + Position sample(uint64_t* seed) const override; + int get_bin(Position r) const override; int n_bins() const override; @@ -460,7 +468,12 @@ public: static const std::string mesh_type; virtual std::string get_mesh_type() const override; + //! Sample a tetrahedron for an unstructured mesh + virtual Position sample_tet(std::array coords, uint64_t* seed) const; + // Overridden Methods + // TODO Position sample(uint64_t* seed) const=0; + void surface_bins_crossed(Position r0, Position r1, const Direction& u, vector& bins) const override; @@ -552,6 +565,8 @@ public: // Overridden Methods + Position sample(uint64_t* seed) const override; + void bins_crossed(Position r0, Position r1, const Direction& u, vector& bins, vector& lengths) const override; @@ -714,6 +729,8 @@ public: void bins_crossed(Position r0, Position r1, const Direction& u, vector& bins, vector& lengths) const override; + Position sample(uint64_t* seed) const override; + int get_bin(Position r) const override; int n_bins() const override; diff --git a/src/mesh.cpp b/src/mesh.cpp index d9ad0ce8a..191f0af5d 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -195,6 +195,37 @@ UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node) } } +// Sample barycentric coordinates given a seed and the vertex positions and return the sampled position +Position UnstructuredMesh::sample_tet(std::array coords, uint64_t* seed) const { + // Uniform distribution + double s = prn(seed); + double t = prn(seed); + double u = prn(seed); + + // From PyNE implementation of moab tet sampling + // C. Rocchini and P. Cignoni, “Generating Random Points in a Tetrahedron,” + if (s + t > 1) { + s = 1.0 - s; + t = 1.0 - t; + } + if (s + t + u > 1) { + if (t + u > 1) { + double old_t = t; + t = 1.0 - u; + u = 1.0 - s - old_t; + }else if (t + u <= 1) { + double old_s = s; + s = 1.0 - t - u; + u = old_s + t + u - 1; + } + } + return s*(coords[1]-coords[0]) + + t*(coords[2]-coords[0]) + + u*(coords[3]-coords[0]) + + coords[0]; + +} + const std::string UnstructuredMesh::mesh_type = "unstructured"; std::string UnstructuredMesh::get_mesh_type() const @@ -327,6 +358,10 @@ StructuredMesh::MeshIndex StructuredMesh::get_indices_from_bin(int bin) const return ijk; } +Position StructuredMesh::sample(uint64_t* seed) const { + fatal_error("Position sampling on structured meshes is not yet implemented"); +} + int StructuredMesh::get_bin(Position r) const { // Determine indices @@ -2049,6 +2084,36 @@ std::string MOABMesh::library() const return mesh_lib_type; } +// Sample position within a tet for MOAB type tets +Position MOABMesh::sample(uint64_t* seed) const { + // Get bin # assuming equal weights, IMP weigh by activity + int64_t tet_bin = round(n_bins()*prn(seed)); + + moab::EntityHandle tet_ent = get_ent_handle_from_bin(tet_bin); + + // Get vertex coordinates for MOAB tet + vector conn1; + moab::ErrorCode rval = mbi_->get_connectivity(&tet_ent, 1, conn1); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to get tet connectivity"); + } + moab::CartVect p[4]; + rval = mbi_->get_coords(conn1.data(), conn1.size(), p[0].array()); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to get tet coords"); + } + + std::array tet_verts; + for (int i = 0; i < 4; i++) { + tet_verts[i] = {p[i][0], p[i][1], p[i][2]}; + } + // Samples position within tet using Barycentric stuff + Position r = this->sample_tet(tet_verts, seed); + + return r; +} + + double MOABMesh::tet_volume(moab::EntityHandle tet) const { vector conn; @@ -2501,6 +2566,25 @@ void LibMesh::initialize() bbox_ = libMesh::MeshTools::create_bounding_box(*m_); } +// Sample position within a tet for LibMesh type tets +Position LibMesh::sample(uint64_t* seed) const { + // Get bin # assuming equal weights, IMP weigh by activity + int64_t tet_xi = round(n_bins()*prn(seed)); + + const auto& elem = get_element_from_bin(tet_xi); + + // Get tet vertex coordinates from LibMesh + std::array tet_verts; + for (int i = 0; i < elem.n_nodes(); i++) { + auto node_ref = elem.node_ref(i); + tet_verts[i] = {node_ref(0), node_ref(1), node_ref(2)}; + } + // Samples position within tet using Barycentric coordinates + Position r = this->sample_tet(tet_verts, seed); + + return r; +} + Position LibMesh::centroid(int bin) const { const auto& elem = this->get_element_from_bin(bin); From 80077ed3fd04758a1fb10095648e977b515a5305 Mon Sep 17 00:00:00 2001 From: NybergWISC Date: Tue, 21 Jun 2022 12:06:45 -0500 Subject: [PATCH 1432/2654] New changes to spatial distribution and source to include mesh sources. Made some edits suggested by Shriwise, now compiles successfully --- include/openmc/distribution_spatial.h | 19 +++++++++++++++++++ src/distribution_spatial.cpp | 25 +++++++++++++++++++++++++ src/mesh.cpp | 6 ++++-- src/source.cpp | 2 ++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 5e426b878..8a77a4bd3 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -5,6 +5,7 @@ #include "openmc/distribution.h" #include "openmc/position.h" +#include "openmc/mesh.h" namespace openmc { @@ -94,6 +95,24 @@ private: Position origin_; //!< Cartesian coordinates of the sphere center }; +//============================================================================== +//! Distribution of points within a mesh +//============================================================================== + +class MeshIndependent : public SpatialDistribution { +public: + explicit MeshIndependent(pugi::xml_node node); + + //! Sample a position from the distribution + //! \param seed Pseudorandom number seed pointer + //! \return Sampled position + Position sample(uint64_t* seed) const; + +private: + UnstructuredMesh* umesh_ptr_; + Position sampled_; +}; + //============================================================================== //! Uniform distribution of points over a box //============================================================================== diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index a06f84d80..f78c2c49b 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -180,6 +180,31 @@ Position SphericalIndependent::sample(uint64_t* seed) const return {x, y, z}; } +//============================================================================== +// MeshIndependent implementation +//============================================================================== + +// Loosely adapted Patrick's code shown here +MeshIndependent::MeshIndependent(pugi::xml_node node) +{ + // No in-tet distributions implemented, could include distributions for the barycentric coords + + int32_t mesh_id = std::stoi(get_node_value(node, "mesh")); + const auto& mesh_ptr = model::meshes[mesh_id]; + + // line from Patrick code, unsure of use + // int bin = mesh_ptr->get_bin(); + const UnstructuredMesh* umesh_ptr_ = dynamic_cast(mesh_ptr.get()); + if (!umesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not an unstructured mesh object"); } +} + +Position MeshIndependent::sample(uint64_t* seed) const +{ + Position sampled_ = umesh_ptr_->sample(seed); + return sampled_; +} + + //============================================================================== // SpatialBox implementation //============================================================================== diff --git a/src/mesh.cpp b/src/mesh.cpp index 191f0af5d..56d793079 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2087,7 +2087,8 @@ std::string MOABMesh::library() const // Sample position within a tet for MOAB type tets Position MOABMesh::sample(uint64_t* seed) const { // Get bin # assuming equal weights, IMP weigh by activity - int64_t tet_bin = round(n_bins()*prn(seed)); + // This may underweigh first and last bins + int64_t tet_bin = trunc(n_bins()*prn(seed)); moab::EntityHandle tet_ent = get_ent_handle_from_bin(tet_bin); @@ -2569,7 +2570,8 @@ void LibMesh::initialize() // Sample position within a tet for LibMesh type tets Position LibMesh::sample(uint64_t* seed) const { // Get bin # assuming equal weights, IMP weigh by activity - int64_t tet_xi = round(n_bins()*prn(seed)); + // This may underweight first and last bin by 1/2 TODO + int64_t tet_xi = trunc(n_bins()*prn(seed)); const auto& elem = get_element_from_bin(tet_xi); diff --git a/src/source.cpp b/src/source.cpp index 3a80e1156..58aac711f 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -94,6 +94,8 @@ IndependentSource::IndependentSource(pugi::xml_node node) space_ = UPtrSpace {new CylindricalIndependent(node_space)}; } else if (type == "spherical") { space_ = UPtrSpace {new SphericalIndependent(node_space)}; + } else if (type =="mesh"){ + space_ = UPtrSpace {new MeshIndependent(node_space)}; } else if (type == "box") { space_ = UPtrSpace {new SpatialBox(node_space)}; } else if (type == "fission") { From 9f6d536959e3bdfb2d47809410d40c317e253682 Mon Sep 17 00:00:00 2001 From: NybergWISC Date: Wed, 6 Jul 2022 08:59:12 -0500 Subject: [PATCH 1433/2654] Commit including most of the sampling work in distribution_spatial.cpp and testing --- include/openmc/distribution_spatial.h | 8 +- include/openmc/mesh.h | 8 +- openmc/settings.py | 10 + openmc/source.py | 1 + openmc/stats/multivariate.py | 118 ++ src/distribution_spatial.cpp | 70 +- src/initialize.cpp | 1 - src/mesh.cpp | 18 +- src/settings.cpp | 10 +- src/source.cpp | 4 - .../source_sampling/__init__.py | 0 .../source_sampling/inputs_true0.dat | 1066 ++++++++++++++++ .../source_sampling/inputs_true1.dat | 1068 +++++++++++++++++ .../source_sampling/inputs_true2.dat | 1066 ++++++++++++++++ .../source_sampling/inputs_true3.dat | 1068 +++++++++++++++++ .../unstructured_mesh/source_sampling/test.py | 190 +++ .../source_sampling/test_mesh_tets.e | 1 + .../source_sampling/test_mesh_tets.exo | 1 + 18 files changed, 4669 insertions(+), 39 deletions(-) create mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/__init__.py create mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat create mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat create mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat create mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat create mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/test.py create mode 120000 tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e create mode 120000 tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 8a77a4bd3..1d6d6413b 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -110,7 +110,13 @@ public: private: UnstructuredMesh* umesh_ptr_; - Position sampled_; + int32_t mesh_map_idx_; + std::string sample_scheme_; + double total_weight_; + std::vector mesh_CDF_; + std::vector mesh_weights_; + int64_t tot_bins_; + }; //============================================================================== diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 6bf49b221..402b22455 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -79,7 +79,7 @@ public: // //! \param[in] seed Seed to use for random sampling //! \param[out] r Position within tet - virtual Position sample(uint64_t* seed) const=0; + virtual Position sample(uint64_t* seed, int32_t tet_bin) const=0; //! Determine which bins were crossed by a particle // @@ -166,7 +166,7 @@ public: } }; - Position sample(uint64_t* seed) const override; + Position sample(uint64_t* seed, int32_t tet_bin) const override; int get_bin(Position r) const override; @@ -565,7 +565,7 @@ public: // Overridden Methods - Position sample(uint64_t* seed) const override; + Position sample(uint64_t* seed, int32_t tet_bin) const override; void bins_crossed(Position r0, Position r1, const Direction& u, vector& bins, vector& lengths) const override; @@ -729,7 +729,7 @@ public: void bins_crossed(Position r0, Position r1, const Direction& u, vector& bins, vector& lengths) const override; - Position sample(uint64_t* seed) const override; + Position sample(uint64_t* seed, int32_t tet_bin) const override; int get_bin(Position r) const override; diff --git a/openmc/settings.py b/openmc/settings.py index 6f3ef5ab4..ecbe2d7ca 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -11,10 +11,12 @@ from typing import Optional from xml.etree import ElementTree as ET import openmc.checkvalue as cv +from openmc.stats.multivariate import MeshIndependent from . import RegularMesh, Source, VolumeCalculation, WeightWindows from ._xml import clean_indentation, get_text, reorder_attributes from openmc.checkvalue import PathLike +from .mesh import MeshBase class RunMode(Enum): @@ -975,6 +977,8 @@ class Settings: def _create_source_subelement(self, root): for source in self.source: root.append(source.to_xml_element()) + if isinstance(source.space, MeshIndependent): + root.append(source.space.mesh.to_xml_element()) def _create_volume_calcs_subelement(self, root): for calc in self.volume_calculations: @@ -1323,6 +1327,12 @@ class Settings: def _source_from_xml_element(self, root): for elem in root.findall('source'): self.source.append(Source.from_xml_element(elem)) + if isinstance(Source.from_xml_element(elem), MeshIndependent): + mesh_id = int(get_text(elem, 'mesh')) + path = f"./mesh[@id='{mesh_id}']" + mesh_elem = root.find(path) + if mesh_elem is not None: + self.source.space.mesh = MeshBase.from_xml_element(mesh_elem) def _volume_calcs_from_xml_element(self, root): volume_elems = root.findall("volume_calc") diff --git a/openmc/source.py b/openmc/source.py index 9293a5953..32f8ea3d6 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -16,6 +16,7 @@ from openmc.checkvalue import PathLike from openmc.stats.multivariate import UnitSphere, Spatial from openmc.stats.univariate import Univariate from ._xml import get_text +from .mesh import MeshBase class Source: diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 8bb319aa4..4484c62a6 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -3,12 +3,14 @@ from collections.abc import Iterable from math import pi, cos from numbers import Real from xml.etree import ElementTree as ET +from xmlrpc.client import boolean import numpy as np import openmc.checkvalue as cv from .._xml import get_text from .univariate import Univariate, Uniform, PowerLaw +from ..mesh import MeshBase class UnitSphere(ABC): @@ -269,6 +271,8 @@ class Spatial(ABC): return CylindricalIndependent.from_xml_element(elem) elif distribution == 'spherical': return SphericalIndependent.from_xml_element(elem) + elif distribution == 'mesh': + return MeshIndependent.from_xml_element(elem) elif distribution == 'box' or distribution == 'fission': return Box.from_xml_element(elem) elif distribution == 'point': @@ -616,6 +620,120 @@ class CylindricalIndependent(Spatial): origin = [float(x) for x in elem.get('origin').split()] return cls(r, phi, z, origin=origin) +class MeshIndependent(Spatial): + """Spatial distribution for a mesh. + + This distribution allows one to specify a mesh to sample over and the scheme to sample over the entire mesh. + + .. versionadded:: 0.13 + + Parameters + ---------- + elem_weight_scheme : str, optional + The scheme for weighting and sampling elements from the mesh. Options are 'file' and 'volume' based weights. + mesh : openmc.MeshBase + The mesh instance used for sampling, mesh is written into settings.xml, mesh.id is written into the source distribution + weights_from_file : Iterable of Real, optional + A list of values which represent the weights of each element + + + Attributes + ---------- + elem_weight_scheme : str, optional + Weighting scheme for sampling element from mesh, defaults to volume + mesh : openmc.MeshBase + The mesh instance used for sampling, mesh is written into settings.xml, mesh.id is written into the source distribution + weights_from_file : Iterable of Real, optional + A list of values which represent the weights of each element + + """ + + def __init__(self, mesh, weights_from_file=None, volume_weighting=False): + self.mesh = mesh + self.weights_from_file = weights_from_file + self.volume_weighting = volume_weighting + + @property + def mesh(self): + return self._mesh + + @mesh.setter + def mesh(self, mesh): + if mesh != None: + cv.check_type('Unstructured Mesh', mesh, MeshBase) + self._mesh = mesh + + @property + def volume_weighting(self): + return self._volume_weighting + + @volume_weighting.setter + def volume_weighting(self, volume_weighting): + cv.check_type('Scheme for sampling an element from the mesh', volume_weighting, bool) + self._volume_weighting = volume_weighting + + @property + def weights_from_file(self): + return self._weights_from_file + + @weights_from_file.setter + def weights_from_file(self, given_weights): + if given_weights is not None: + self._weights_from_file = (np.array(given_weights, dtype=float)).flatten() + else: + self._weights_from_file = None + + @property + def num_weight_bins(self): + if self.weights_from_file == None: + raise ValueError('Weight bins are not set') + return self.weights_from_file.size + + def to_xml_element(self): + """Return XML representation of the spatial distribution + + Returns + ------- + element : xml.etree.ElementTree.Element + XML element containing spatial distribution data + + """ + element = ET.Element('space') + element.set('type', 'mesh') + element.set("mesh_id", str(self.mesh.id)) + element.set("volume_weighting", str(self.volume_weighting)) + + if self.weights_from_file is not None: + subelement = ET.SubElement(element, 'weights_from_file') + subelement.text = ' '.join(str(e) for e in self.weights_from_file) + + return element + + @classmethod + def from_xml_element(cls, elem): + """Generate spatial distribution from an XML element + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + XML element + + Returns + ------- + openmc.stats.MeshIndependent + Spatial distribution generated from XML element + + """ + + mesh_id = int(elem.get('mesh_id')) + volume_weighting = elem.get("volume_weighting") + volume_weighting = get_text(elem, 'volume_weighting').lower() == 'true' + if elem.get('weights_from_file') is not None: + weights_from_file = [float(b) for b in get_text(elem, 'weights_from_file').split()] + else: + weights_from_file = None + return cls(volume_weighting, mesh_id, weights_from_file) + class Box(Spatial): """Uniform distribution of coordinates in a rectangular cuboid. diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index f78c2c49b..fdac3433a 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -3,6 +3,11 @@ #include "openmc/error.h" #include "openmc/random_lcg.h" #include "openmc/xml_interface.h" +#include "openmc/mesh.h" +#include "openmc/search.h" + +#include +#include namespace openmc { @@ -184,24 +189,71 @@ Position SphericalIndependent::sample(uint64_t* seed) const // MeshIndependent implementation //============================================================================== -// Loosely adapted Patrick's code shown here MeshIndependent::MeshIndependent(pugi::xml_node node) { // No in-tet distributions implemented, could include distributions for the barycentric coords + // Read in unstructured mesh from mesh_id value + int32_t mesh_id = std::stoi(get_node_value(node, "mesh_id")); + // Get pointer to spatial distribution + mesh_map_idx_ = model::mesh_map.at(mesh_id); + const auto& mesh_ptr = model::meshes[mesh_map_idx_]; - int32_t mesh_id = std::stoi(get_node_value(node, "mesh")); - const auto& mesh_ptr = model::meshes[mesh_id]; - - // line from Patrick code, unsure of use - // int bin = mesh_ptr->get_bin(); - const UnstructuredMesh* umesh_ptr_ = dynamic_cast(mesh_ptr.get()); + // Check whether mesh pointer points to an unstructured mesh + umesh_ptr_ = dynamic_cast(mesh_ptr.get()); if (!umesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not an unstructured mesh object"); } + + // Create CDF based on weighting scheme + tot_bins_ = umesh_ptr_->n_bins(); + std::vector weights = {}; + weights.resize(tot_bins_); + double temp_total_weight = 0.0; + mesh_CDF_.resize(tot_bins_+1); + mesh_CDF_[0] = {0.0}; + total_weight_ = 0.0; + mesh_weights_.resize(tot_bins_); + + // Create cdfs for sampling for an element over a mesh + // Volume scheme is weighted by the volume of each tet + // File scheme is weighted by an array given in the xml file + + if (check_for_node(node, "weights_from_file")) { + mesh_weights_ = get_node_array(node, "weights_from_file"); + if (mesh_weights_.size() != tot_bins_){ + write_message("WARNING: The size of the weights array from the xml file does not equal the number of elements in the mesh."); + } if (get_node_value_bool(node, "volume_weighting")){ + for (int i = 0; i < tot_bins_; i++){ + weights[i] = mesh_weights_[i]*umesh_ptr_->volume(i); + } + } else if (!get_node_value_bool(node, "volume_weighting")){ + for (int i = 0; i < tot_bins_; i++){ + weights[i] = mesh_weights_[i]; + } + } + } else if (get_node_value_bool(node, "volume_weighting")){ + for (int i = 0; ivolume(i); + } + } else { + for (int i = 0; isample(seed); - return sampled_; + // Create random variable for sampling element from mesh + float eta = prn(seed); + // Sample over the CDF defined in initialization above + int32_t tet_bin = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); + return umesh_ptr_->sample(seed, tet_bin); } diff --git a/src/initialize.cpp b/src/initialize.cpp index 0c137795b..913e0b1a9 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -405,7 +405,6 @@ void read_separate_xml_files() // Finalize cross sections having assigned temperatures finalize_cross_sections(); - read_tallies_xml(); // Initialize distribcell_filters diff --git a/src/mesh.cpp b/src/mesh.cpp index 56d793079..5225d3074 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -358,7 +358,7 @@ StructuredMesh::MeshIndex StructuredMesh::get_indices_from_bin(int bin) const return ijk; } -Position StructuredMesh::sample(uint64_t* seed) const { +Position StructuredMesh::sample(uint64_t* seed, int32_t tet_bin) const { fatal_error("Position sampling on structured meshes is not yet implemented"); } @@ -2085,10 +2085,7 @@ std::string MOABMesh::library() const } // Sample position within a tet for MOAB type tets -Position MOABMesh::sample(uint64_t* seed) const { - // Get bin # assuming equal weights, IMP weigh by activity - // This may underweigh first and last bins - int64_t tet_bin = trunc(n_bins()*prn(seed)); +Position MOABMesh::sample(uint64_t* seed, int32_t tet_bin) const { moab::EntityHandle tet_ent = get_ent_handle_from_bin(tet_bin); @@ -2568,18 +2565,13 @@ void LibMesh::initialize() } // Sample position within a tet for LibMesh type tets -Position LibMesh::sample(uint64_t* seed) const { - // Get bin # assuming equal weights, IMP weigh by activity - // This may underweight first and last bin by 1/2 TODO - int64_t tet_xi = trunc(n_bins()*prn(seed)); - - const auto& elem = get_element_from_bin(tet_xi); - +Position LibMesh::sample(uint64_t* seed, int32_t tet_bin) const { + const auto& elem = get_element_from_bin(tet_bin); // Get tet vertex coordinates from LibMesh std::array tet_verts; for (int i = 0; i < elem.n_nodes(); i++) { auto node_ref = elem.node_ref(i); - tet_verts[i] = {node_ref(0), node_ref(1), node_ref(2)}; + tet_verts[i] = {node_ref(0), node_ref(1), node_ref(2)}; } // Samples position within tet using Barycentric coordinates Position r = this->sample_tet(tet_verts, seed); diff --git a/src/settings.cpp b/src/settings.cpp index 6386ce52b..c3ecd46b4 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -279,6 +279,9 @@ void read_settings_xml(pugi::xml_node root) } } + // Check for user meshes and allocate + read_meshes(root); + // Look for deprecated cross_sections.xml file in settings.xml if (check_for_node(root, "cross_sections")) { warning( @@ -368,7 +371,6 @@ void read_settings_xml(pugi::xml_node root) } } } - if (run_mode == RunMode::EIGENVALUE || run_mode == RunMode::FIXED_SOURCE) { // Read run parameters get_run_parameters(node_mode); @@ -432,7 +434,6 @@ void read_settings_xml(pugi::xml_node root) "the OMP_NUM_THREADS environment variable to set the number of " "threads."); } - // ========================================================================== // EXTERNAL SOURCE @@ -461,7 +462,6 @@ void read_settings_xml(pugi::xml_node root) model::external_sources.push_back(make_unique(node)); } } - // Check if the user has specified to read surface source if (check_for_node(root, "surf_source_read")) { surf_source_read = true; @@ -532,7 +532,6 @@ void read_settings_xml(pugi::xml_node root) std::stod(get_node_value(node_cutoff, "energy_positron")); } } - // Particle trace if (check_for_node(root, "trace")) { auto temp = get_node_array(root, "trace"); @@ -564,9 +563,6 @@ void read_settings_xml(pugi::xml_node root) } } - // Read meshes - read_meshes(root); - // Shannon Entropy mesh if (check_for_node(root, "entropy_mesh")) { int temp = std::stoi(get_node_value(root, "entropy_mesh")); diff --git a/src/source.cpp b/src/source.cpp index 58aac711f..2ceff9964 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -111,7 +111,6 @@ IndependentSource::IndependentSource(pugi::xml_node node) // If no spatial distribution specified, make it a point source space_ = UPtrSpace {new SpatialPoint()}; } - // Determine external source angular distribution if (check_for_node(node, "angle")) { // Get pointer to angular distribution @@ -131,11 +130,9 @@ IndependentSource::IndependentSource(pugi::xml_node node) fatal_error(fmt::format( "Invalid angular distribution for external source: {}", type)); } - } else { angle_ = UPtrAngle {new Isotropic()}; } - // Determine external source energy distribution if (check_for_node(node, "energy")) { pugi::xml_node node_dist = node.child("energy"); @@ -144,7 +141,6 @@ IndependentSource::IndependentSource(pugi::xml_node node) // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1 energy_ = UPtrDist {new Watt(0.988e6, 2.249e-6)}; } - // Determine external source time distribution if (check_for_node(node, "time")) { pugi::xml_node node_dist = node.child("time"); diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/__init__.py b/tests/regression_tests/unstructured_mesh/source_sampling/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat new file mode 100644 index 000000000..ee30a9dbe --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat @@ -0,0 +1,1066 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 5000 + 2 + + + + 15000000.0 1.0 + + + + test_mesh_tets.e + + 10000 + + + + + scatter total absorption + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat new file mode 100644 index 000000000..fca2bb796 --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -0,0 +1,1068 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 5000 + 2 + + + 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + + + 15000000.0 1.0 + + + + test_mesh_tets.e + + 10000 + + + + + scatter total absorption + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat new file mode 100644 index 000000000..2cd7bf746 --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat @@ -0,0 +1,1066 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 5000 + 2 + + + + 15000000.0 1.0 + + + + test_mesh_tets.e + + 10000 + + + + + scatter total absorption + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat new file mode 100644 index 000000000..271ef9b1b --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat @@ -0,0 +1,1068 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 5000 + 2 + + + 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + + + 15000000.0 1.0 + + + + test_mesh_tets.e + + 10000 + + + + + scatter total absorption + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py new file mode 100644 index 000000000..3149e80aa --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -0,0 +1,190 @@ +import glob +from itertools import product +import os + +import openmc +import openmc.lib +import numpy as np + +import pytest +from tests.testing_harness import PyAPITestHarness +from tests.regression_tests import config +from subprocess import call + +TETS_PER_VOXEL = 12 + +class UnstructuredMeshSourceTest(PyAPITestHarness): + def __init__(self, statepoint_name, model, inputs_true, schemes): + + super().__init__(statepoint_name, model, inputs_true) + self.schemes = schemes + + def _run_openmc(self): + kwargs = {'openmc_exec' : config['exe'], + 'event_based' : config['event'], + 'tracks' : "True"} + + if config['mpi']: + kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']] + + openmc.run(**kwargs) + + def _compare_results(self): + + average_in_hex = 10.0 + + + call(['../../../../scripts/openmc-track-combine', '-o', 'tracks.h5'] + + glob.glob('tracks_p*.h5')) + + # loop over the tracks and get data + tracks = openmc.Tracks(filepath='tracks.h5') + tracks_born = np.empty((len(tracks), 1)) + decimals = 0 + + instances = np.zeros(1000) + + for i in range(0, len(tracks)): + tracks_born[i] = tracks[i].particle_tracks[0].states['cell_id'][0] + instances[int(tracks_born[i])-1] = instances[int(tracks_born[i])-1]+1 + + if self.schemes == "file": + assert(instances[0] > 0 and instances[1] > 0) + assert(instances[0] > instances[1]) + + for i in range(0, len(instances)): + if i != 0 and i != 1: + assert(instances[i] == 0) + + else: + assert(np.average(instances) == average_in_hex) + assert(np.std(instances) < np.average(instances)) + assert(np.amax(instances) < np.average(instances)+6*np.std(instances)) + + + def _cleanup(self): + super()._cleanup() + output = glob.glob('tally*.vtk') + output += glob.glob('tally*.e') + for f in output: + if os.path.exists(f): + os.remove(f) + + + + +param_values = (['libmesh', 'moab'], # mesh libraries + ['volume', 'file']) # Element weighting schemes + +test_cases = [] +# for i, (lib, holes) in enumerate(product(*param_values)): +for i, (lib, schemes) in enumerate(product(*param_values)): + test_cases.append({'library' : lib, + 'schemes' : schemes, + 'inputs_true' : 'inputs_true{}.dat'.format(i)}) + + +@pytest.mark.parametrize("test_opts", test_cases) +def test_unstructured_mesh(test_opts): + + openmc.reset_auto_ids() + + # skip the test if the library is not enabled + if test_opts['library'] == 'moab' and not openmc.lib._dagmc_enabled(): + pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") + + if test_opts['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): + pytest.skip("LibMesh is not enabled in this build.") + + ### Materials ### + materials = openmc.Materials() + + water_mat = openmc.Material(material_id=3, name="water") + water_mat.add_nuclide("H1", 2.0) + water_mat.add_nuclide("O16", 1.0) + water_mat.set_density("atom/b-cm", 0.07416) + materials.append(water_mat) + + materials.export_to_xml() + + ### Geometry ### + dimen = 10 + size_hex = 20.0/dimen + + ### Geometry ### + cell = np.empty((dimen, dimen, dimen), dtype=object) + surfaces = np.empty((dimen+1, 3), dtype=object) + + geometry = openmc.Geometry() + universe = openmc.Universe(universe_id=1, name="Contains all hexes") + + for i in range(0,dimen+1): + surfaces[i][0] = openmc.XPlane(-10.0+i*size_hex, name="X plane at "+str(-10.0+i*size_hex)) + surfaces[i][1] = openmc.YPlane(-10.0+i*size_hex, name="Y plane at "+str(-10.0+i*size_hex)) + surfaces[i][2] = openmc.ZPlane(-10.0+i*size_hex, name="Z plane at "+str(-10.0+i*size_hex)) + + surfaces[i][0].boundary_type = 'vacuum' + surfaces[i][1].boundary_type = 'vacuum' + surfaces[i][2].boundary_type = 'vacuum' + + for k in range(0,dimen): + for j in range(0,dimen): + for i in range(0,dimen): + cell[i][j][k] = openmc.Cell(name=("x " + str(i) +" y " + str(j) +" z " + str(k))) + cell[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ + +surfaces[j][1] & -surfaces[j+1][1] & \ + +surfaces[k][2] & -surfaces[k+1][2] + cell[i][j][k].fill = water_mat + universe.add_cell(cell[i][j][k]) + + geometry = openmc.Geometry(universe) + + mesh_filename = "test_mesh_tets.e" + + uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_opts['library']) + + ### Tallies ### + + # create tallies + tallies = openmc.Tallies() + + tally1 = openmc.Tally(1) + tally1.scores = ['scatter', 'total', 'absorption'] + # Export tallies + tallies = openmc.Tallies([tally1]) + tallies.export_to_xml() + + ### Settings ### + settings = openmc.Settings() + settings.run_mode = 'fixed source' + settings.particles = 5000 + settings.batches = 2 + + # settings.create_fission_neutrons = False + settings.tracks = [(1, 1, 1)] + settings.max_tracks = 10000 + + # source setup + if test_opts['schemes'] == 'volume': + space = openmc.stats.MeshIndependent(volume_weighting=True, mesh=uscd_mesh) + elif test_opts['schemes'] == 'file': + array = np.zeros(12000) + for i in range(0, 12): + array[i] = 10 + array[i+12] = 2 + space = openmc.stats.MeshIndependent(volume_weighting=False, weights_from_file=array, mesh=uscd_mesh) + + energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) + source = openmc.Source(space=space, energy=energy) + settings.source = source + + model = openmc.model.Model(geometry=geometry, + materials=materials, + tallies=tallies, + settings=settings) + + harness = UnstructuredMeshSourceTest('statepoint.2.h5', + model, + test_opts['inputs_true'], + test_opts['schemes']) + harness.main() diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e b/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e new file mode 120000 index 000000000..0aa0d1a23 --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e @@ -0,0 +1 @@ +../test_mesh_tets.e \ No newline at end of file diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo b/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo new file mode 120000 index 000000000..6d40011d4 --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo @@ -0,0 +1 @@ +../test_mesh_tets.exo \ No newline at end of file From 7a3a1876e1a0dc063e43fd1b03ef7d0da1633ff0 Mon Sep 17 00:00:00 2001 From: Matthew Nyberg Date: Mon, 8 Aug 2022 08:35:13 -0500 Subject: [PATCH 1434/2654] Reorganize imports in source_sampling/test.py Co-authored-by: Patrick Shriwise --- .../unstructured_mesh/source_sampling/test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 3149e80aa..f6262971a 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -2,11 +2,12 @@ import glob from itertools import product import os -import openmc -import openmc.lib +import pytest import numpy as np -import pytest +import openmc +import openmc.lib + from tests.testing_harness import PyAPITestHarness from tests.regression_tests import config from subprocess import call From 7c40badfbc62bed28d0771fdc656f4baff41e25b Mon Sep 17 00:00:00 2001 From: NybergWISC Date: Mon, 8 Aug 2022 11:21:09 -0500 Subject: [PATCH 1435/2654] Address comments on initial PR, all changed other than name of class and the use of python API to combine track outputs --- include/openmc/distribution_spatial.h | 5 +- include/openmc/mesh.h | 6 +- openmc/settings.py | 4 +- openmc/stats/multivariate.py | 72 +- src/distribution_spatial.cpp | 43 +- src/mesh.cpp | 12 +- .../source_sampling/inputs_true0.dat | 2002 ++++++++-------- .../source_sampling/inputs_true1.dat | 2004 ++++++++--------- .../source_sampling/inputs_true2.dat | 2002 ++++++++-------- .../source_sampling/inputs_true3.dat | 2004 ++++++++--------- .../unstructured_mesh/source_sampling/test.py | 53 +- 11 files changed, 4096 insertions(+), 4111 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 1d6d6413b..8864e1139 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -112,11 +112,10 @@ private: UnstructuredMesh* umesh_ptr_; int32_t mesh_map_idx_; std::string sample_scheme_; - double total_weight_; + double total_strength_; std::vector mesh_CDF_; - std::vector mesh_weights_; + std::vector mesh_strengths_; int64_t tot_bins_; - }; //============================================================================== diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 402b22455..a4104f75a 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -468,9 +468,6 @@ public: static const std::string mesh_type; virtual std::string get_mesh_type() const override; - //! Sample a tetrahedron for an unstructured mesh - virtual Position sample_tet(std::array coords, uint64_t* seed) const; - // Overridden Methods // TODO Position sample(uint64_t* seed) const=0; @@ -545,6 +542,9 @@ protected: 1.0}; //!< Constant multiplication factor to apply to mesh coordinates bool specified_length_multiplier_ {false}; + //! Sample a tetrahedron for an unstructured mesh + Position sample_tet(std::array coords, uint64_t* seed) const; + private: //! Setup method for the mesh. Builds data structures, //! sets up element mapping, creates bounding boxes, etc. diff --git a/openmc/settings.py b/openmc/settings.py index ecbe2d7ca..045cccd5c 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -978,7 +978,9 @@ class Settings: for source in self.source: root.append(source.to_xml_element()) if isinstance(source.space, MeshIndependent): - root.append(source.space.mesh.to_xml_element()) + path = f"./mesh[@id='{source.space.mesh.id}']" + if root.find(path) is None: + root.append(source.space.mesh.to_xml_element()) def _create_volume_calcs_subelement(self, root): for calc in self.volume_calculations: diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 4484c62a6..0df540ddd 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -3,7 +3,6 @@ from collections.abc import Iterable from math import pi, cos from numbers import Real from xml.etree import ElementTree as ET -from xmlrpc.client import boolean import numpy as np @@ -629,29 +628,25 @@ class MeshIndependent(Spatial): Parameters ---------- - elem_weight_scheme : str, optional - The scheme for weighting and sampling elements from the mesh. Options are 'file' and 'volume' based weights. mesh : openmc.MeshBase The mesh instance used for sampling, mesh is written into settings.xml, mesh.id is written into the source distribution - weights_from_file : Iterable of Real, optional + strengths : Iterable of Real, optional A list of values which represent the weights of each element Attributes ---------- - elem_weight_scheme : str, optional - Weighting scheme for sampling element from mesh, defaults to volume mesh : openmc.MeshBase The mesh instance used for sampling, mesh is written into settings.xml, mesh.id is written into the source distribution - weights_from_file : Iterable of Real, optional + strengths : Iterable of Real, optional A list of values which represent the weights of each element """ - def __init__(self, mesh, weights_from_file=None, volume_weighting=False): + def __init__(self, mesh, strengths=None, volume_normalized=False): self.mesh = mesh - self.weights_from_file = weights_from_file - self.volume_weighting = volume_weighting + self.strengths = strengths + self.volume_normalized = volume_normalized @property def mesh(self): @@ -660,34 +655,35 @@ class MeshIndependent(Spatial): @mesh.setter def mesh(self, mesh): if mesh != None: - cv.check_type('Unstructured Mesh', mesh, MeshBase) + cv.check_type('Unstructured Mesh instance', mesh, MeshBase) self._mesh = mesh @property - def volume_weighting(self): - return self._volume_weighting + def volume_normalized(self): + return self._volume_normalized - @volume_weighting.setter - def volume_weighting(self, volume_weighting): - cv.check_type('Scheme for sampling an element from the mesh', volume_weighting, bool) - self._volume_weighting = volume_weighting + @volume_normalized.setter + def volume_normalized(self, volume_normalized): + cv.check_type('Normalize (multiply) strengths by volume', volume_normalized, bool) + self._volume_normalized = volume_normalized @property - def weights_from_file(self): - return self._weights_from_file + def strengths(self): + return self._strengths - @weights_from_file.setter - def weights_from_file(self, given_weights): - if given_weights is not None: - self._weights_from_file = (np.array(given_weights, dtype=float)).flatten() + @strengths.setter + def strengths(self, given_strengths): + if given_strengths is not None: + cv.check_type('strengths array passed in', given_strengths, Iterable, Real) + self._strengths = np.array(given_strengths, dtype=float).flatten() else: - self._weights_from_file = None + self._strengths = None @property - def num_weight_bins(self): - if self.weights_from_file == None: - raise ValueError('Weight bins are not set') - return self.weights_from_file.size + def num_strength_bins(self): + if self.strengths == None: + raise ValueError('Strengths are not set') + return self.strengths.size def to_xml_element(self): """Return XML representation of the spatial distribution @@ -701,11 +697,11 @@ class MeshIndependent(Spatial): element = ET.Element('space') element.set('type', 'mesh') element.set("mesh_id", str(self.mesh.id)) - element.set("volume_weighting", str(self.volume_weighting)) + element.set("volume_normalized", str(self.volume_normalized)) - if self.weights_from_file is not None: - subelement = ET.SubElement(element, 'weights_from_file') - subelement.text = ' '.join(str(e) for e in self.weights_from_file) + if self.strengths is not None: + subelement = ET.SubElement(element, 'strengths') + subelement.text = ' '.join(str(e) for e in self.strengths) return element @@ -726,13 +722,13 @@ class MeshIndependent(Spatial): """ mesh_id = int(elem.get('mesh_id')) - volume_weighting = elem.get("volume_weighting") - volume_weighting = get_text(elem, 'volume_weighting').lower() == 'true' - if elem.get('weights_from_file') is not None: - weights_from_file = [float(b) for b in get_text(elem, 'weights_from_file').split()] + volume_normalized = elem.get("volume_normalized") + volume_normalized = get_text(elem, 'volume_normalized').lower() == 'true' + if elem.get('strengths') is not None: + strengths = [float(b) for b in get_text(elem, 'strengths').split()] else: - weights_from_file = None - return cls(volume_weighting, mesh_id, weights_from_file) + strengths = None + return cls(volume_normalized, mesh_id, strengths) class Box(Spatial): diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index fdac3433a..0ac24e39a 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -6,9 +6,6 @@ #include "openmc/mesh.h" #include "openmc/search.h" -#include -#include - namespace openmc { //============================================================================== @@ -202,48 +199,48 @@ MeshIndependent::MeshIndependent(pugi::xml_node node) umesh_ptr_ = dynamic_cast(mesh_ptr.get()); if (!umesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not an unstructured mesh object"); } - // Create CDF based on weighting scheme + // Initialize arrays for CDF creation tot_bins_ = umesh_ptr_->n_bins(); - std::vector weights = {}; - weights.resize(tot_bins_); - double temp_total_weight = 0.0; + std::vector strengths = {}; + strengths.resize(tot_bins_); + double temp_total_strength = 0.0; mesh_CDF_.resize(tot_bins_+1); mesh_CDF_[0] = {0.0}; - total_weight_ = 0.0; - mesh_weights_.resize(tot_bins_); + total_strength_ = 0.0; + mesh_strengths_.resize(tot_bins_); // Create cdfs for sampling for an element over a mesh // Volume scheme is weighted by the volume of each tet // File scheme is weighted by an array given in the xml file - if (check_for_node(node, "weights_from_file")) { - mesh_weights_ = get_node_array(node, "weights_from_file"); - if (mesh_weights_.size() != tot_bins_){ - write_message("WARNING: The size of the weights array from the xml file does not equal the number of elements in the mesh."); - } if (get_node_value_bool(node, "volume_weighting")){ + if (check_for_node(node, "strengths")) { + mesh_strengths_ = get_node_array(node, "strengths"); + if (mesh_strengths_.size() != tot_bins_){ + fatal_error("The size of the strengths array from the xml file does not equal the number of elements in the mesh."); + } if (get_node_value_bool(node, "volume_normalized")){ for (int i = 0; i < tot_bins_; i++){ - weights[i] = mesh_weights_[i]*umesh_ptr_->volume(i); + strengths[i] = mesh_strengths_[i]*umesh_ptr_->volume(i); } - } else if (!get_node_value_bool(node, "volume_weighting")){ + } else if (!get_node_value_bool(node, "volume_normalized")){ for (int i = 0; i < tot_bins_; i++){ - weights[i] = mesh_weights_[i]; + strengths[i] = mesh_strengths_[i]; } } - } else if (get_node_value_bool(node, "volume_weighting")){ + } else if (get_node_value_bool(node, "volume_normalized")){ for (int i = 0; ivolume(i); + strengths[i] = umesh_ptr_->volume(i); } } else { for (int i = 0; i conn1; @@ -2103,7 +2103,7 @@ Position MOABMesh::sample(uint64_t* seed, int32_t tet_bin) const { std::array tet_verts; for (int i = 0; i < 4; i++) { - tet_verts[i] = {p[i][0], p[i][1], p[i][2]}; + tet_verts[i] = {p[i][0], p[i][1], p[i][2]}; } // Samples position within tet using Barycentric stuff Position r = this->sample_tet(tet_verts, seed); @@ -2565,8 +2565,8 @@ void LibMesh::initialize() } // Sample position within a tet for LibMesh type tets -Position LibMesh::sample(uint64_t* seed, int32_t tet_bin) const { - const auto& elem = get_element_from_bin(tet_bin); +Position LibMesh::sample(uint64_t* seed, int32_t bin) const { + const auto& elem = get_element_from_bin(bin); // Get tet vertex coordinates from LibMesh std::array tet_verts; for (int i = 0; i < elem.n_nodes(); i++) { diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat index ee30a9dbe..c85bdd920 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat @@ -1,1005 +1,1005 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1048,7 +1048,7 @@ 5000 2 - + 15000000.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat index fca2bb796..dca3958c3 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -1,1005 +1,1005 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1048,8 +1048,8 @@ 5000 2 - - 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + + 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000000.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat index 2cd7bf746..be58bd8f9 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat @@ -1,1005 +1,1005 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1048,7 +1048,7 @@ 5000 2 - + 15000000.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat index 271ef9b1b..5003e7b1b 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat @@ -1,1005 +1,1005 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1048,8 +1048,8 @@ 5000 2 - - 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + + 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000000.0 1.0 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index f6262971a..dfbe74d05 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -16,7 +16,6 @@ TETS_PER_VOXEL = 12 class UnstructuredMeshSourceTest(PyAPITestHarness): def __init__(self, statepoint_name, model, inputs_true, schemes): - super().__init__(statepoint_name, model, inputs_true) self.schemes = schemes @@ -31,60 +30,53 @@ class UnstructuredMeshSourceTest(PyAPITestHarness): openmc.run(**kwargs) def _compare_results(self): - + # There are 10000 particles and 1000 hexes, this leads to the average + # shown below average_in_hex = 10.0 - call(['../../../../scripts/openmc-track-combine', '-o', 'tracks.h5'] + glob.glob('tracks_p*.h5')) # loop over the tracks and get data tracks = openmc.Tracks(filepath='tracks.h5') tracks_born = np.empty((len(tracks), 1)) - decimals = 0 instances = np.zeros(1000) for i in range(0, len(tracks)): tracks_born[i] = tracks[i].particle_tracks[0].states['cell_id'][0] - instances[int(tracks_born[i])-1] = instances[int(tracks_born[i])-1]+1 + instances[int(tracks_born[i])-1] += 1 if self.schemes == "file": assert(instances[0] > 0 and instances[1] > 0) assert(instances[0] > instances[1]) - - for i in range(0, len(instances)): - if i != 0 and i != 1: - assert(instances[i] == 0) + + for i in range(2, len(instances)): + assert(instances[i] == 0) else: assert(np.average(instances) == average_in_hex) - assert(np.std(instances) < np.average(instances)) + assert(np.std(instances) < np.average(instances)) assert(np.amax(instances) < np.average(instances)+6*np.std(instances)) - + def _cleanup(self): super()._cleanup() - output = glob.glob('tally*.vtk') + output = glob.glob('track*.h5') output += glob.glob('tally*.e') for f in output: if os.path.exists(f): os.remove(f) - - - param_values = (['libmesh', 'moab'], # mesh libraries ['volume', 'file']) # Element weighting schemes test_cases = [] -# for i, (lib, holes) in enumerate(product(*param_values)): for i, (lib, schemes) in enumerate(product(*param_values)): test_cases.append({'library' : lib, 'schemes' : schemes, 'inputs_true' : 'inputs_true{}.dat'.format(i)}) - @pytest.mark.parametrize("test_opts", test_cases) def test_unstructured_mesh(test_opts): @@ -110,19 +102,20 @@ def test_unstructured_mesh(test_opts): ### Geometry ### dimen = 10 - size_hex = 20.0/dimen + size_hex = 20.0 / dimen ### Geometry ### cell = np.empty((dimen, dimen, dimen), dtype=object) - surfaces = np.empty((dimen+1, 3), dtype=object) + surfaces = np.empty((dimen + 1, 3), dtype=object) geometry = openmc.Geometry() universe = openmc.Universe(universe_id=1, name="Contains all hexes") for i in range(0,dimen+1): - surfaces[i][0] = openmc.XPlane(-10.0+i*size_hex, name="X plane at "+str(-10.0+i*size_hex)) - surfaces[i][1] = openmc.YPlane(-10.0+i*size_hex, name="Y plane at "+str(-10.0+i*size_hex)) - surfaces[i][2] = openmc.ZPlane(-10.0+i*size_hex, name="Z plane at "+str(-10.0+i*size_hex)) + coord = -10.0 + i * size_hex + surfaces[i][0] = openmc.XPlane(coord, name="X plane at "+str(coord)) + surfaces[i][1] = openmc.YPlane(coord, name="Y plane at "+str(coord)) + surfaces[i][2] = openmc.ZPlane(coord, name="Z plane at "+str(coord)) surfaces[i][0].boundary_type = 'vacuum' surfaces[i][1].boundary_type = 'vacuum' @@ -131,11 +124,11 @@ def test_unstructured_mesh(test_opts): for k in range(0,dimen): for j in range(0,dimen): for i in range(0,dimen): - cell[i][j][k] = openmc.Cell(name=("x " + str(i) +" y " + str(j) +" z " + str(k))) + cell[i][j][k] = openmc.Cell(name=("x = {}, y = {}, z = {}".format(i,j,k))) cell[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ +surfaces[j][1] & -surfaces[j+1][1] & \ +surfaces[k][2] & -surfaces[k+1][2] - cell[i][j][k].fill = water_mat + cell[i][j][k].fill = None universe.add_cell(cell[i][j][k]) geometry = openmc.Geometry(universe) @@ -161,19 +154,17 @@ def test_unstructured_mesh(test_opts): settings.particles = 5000 settings.batches = 2 - # settings.create_fission_neutrons = False - settings.tracks = [(1, 1, 1)] settings.max_tracks = 10000 # source setup if test_opts['schemes'] == 'volume': - space = openmc.stats.MeshIndependent(volume_weighting=True, mesh=uscd_mesh) + space = openmc.stats.MeshIndependent(volume_normalized=True, mesh=uscd_mesh) elif test_opts['schemes'] == 'file': array = np.zeros(12000) for i in range(0, 12): array[i] = 10 array[i+12] = 2 - space = openmc.stats.MeshIndependent(volume_weighting=False, weights_from_file=array, mesh=uscd_mesh) + space = openmc.stats.MeshIndependent(volume_normalized=False, strengths=array, mesh=uscd_mesh) energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) source = openmc.Source(space=space, energy=energy) @@ -185,7 +176,7 @@ def test_unstructured_mesh(test_opts): settings=settings) harness = UnstructuredMeshSourceTest('statepoint.2.h5', - model, - test_opts['inputs_true'], - test_opts['schemes']) + model, + test_opts['inputs_true'], + test_opts['schemes']) harness.main() From bd60956d20c9e538179597d0c6e8029cbea2963c Mon Sep 17 00:00:00 2001 From: NybergWISC Date: Wed, 10 Aug 2022 14:42:57 -0500 Subject: [PATCH 1436/2654] Second round of comments. volume method is now implemented from Mesh instead of UnstructuredMesh --- include/openmc/distribution_spatial.h | 10 ++++---- include/openmc/mesh.h | 19 +++++++++++---- openmc/settings.py | 13 +++++++---- openmc/stats/multivariate.py | 8 +++---- src/distribution_spatial.cpp | 23 +++++++++---------- src/mesh.cpp | 8 ++++++- src/source.cpp | 2 +- .../unstructured_mesh/source_sampling/test.py | 21 ++++++++--------- 8 files changed, 60 insertions(+), 44 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 8864e1139..6d771fd6b 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -99,9 +99,9 @@ private: //! Distribution of points within a mesh //============================================================================== -class MeshIndependent : public SpatialDistribution { +class MeshSpatial : public SpatialDistribution { public: - explicit MeshIndependent(pugi::xml_node node); + explicit MeshSpatial(pugi::xml_node node); //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer @@ -109,13 +109,13 @@ public: Position sample(uint64_t* seed) const; private: - UnstructuredMesh* umesh_ptr_; - int32_t mesh_map_idx_; + Mesh* mesh_ptr_; + int32_t mesh_idx_; std::string sample_scheme_; double total_strength_; std::vector mesh_CDF_; std::vector mesh_strengths_; - int64_t tot_bins_; + int32_t tot_bins_; }; //============================================================================== diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index a4104f75a..8015d2e4c 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -79,7 +79,13 @@ public: // //! \param[in] seed Seed to use for random sampling //! \param[out] r Position within tet - virtual Position sample(uint64_t* seed, int32_t tet_bin) const=0; + virtual Position sample(uint64_t* seed, int32_t bin) const=0; + + //! Get the volume of a mesh bin + // + //! \param[in] bin Bin to return the volume for + //! \return Volume of the bin + virtual double volume(int bin) const = 0; //! Determine which bins were crossed by a particle // @@ -166,7 +172,9 @@ public: } }; - Position sample(uint64_t* seed, int32_t tet_bin) const override; + Position sample(uint64_t* seed, int32_t bin) const override; + + double volume(int bin) const override; int get_bin(Position r) const override; @@ -469,13 +477,14 @@ public: virtual std::string get_mesh_type() const override; // Overridden Methods - // TODO Position sample(uint64_t* seed) const=0; void surface_bins_crossed(Position r0, Position r1, const Direction& u, vector& bins) const override; void to_hdf5(hid_t group) const override; + virtual double volume(int bin) const = 0; + std::string bin_label(int bin) const override; // Methods @@ -565,7 +574,7 @@ public: // Overridden Methods - Position sample(uint64_t* seed, int32_t tet_bin) const override; + Position sample(uint64_t* seed, int32_t bin) const override; void bins_crossed(Position r0, Position r1, const Direction& u, vector& bins, vector& lengths) const override; @@ -729,7 +738,7 @@ public: void bins_crossed(Position r0, Position r1, const Direction& u, vector& bins, vector& lengths) const override; - Position sample(uint64_t* seed, int32_t tet_bin) const override; + Position sample(uint64_t* seed, int32_t bin) const override; int get_bin(Position r) const override; diff --git a/openmc/settings.py b/openmc/settings.py index 045cccd5c..b8b1ec2b4 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -11,7 +11,7 @@ from typing import Optional from xml.etree import ElementTree as ET import openmc.checkvalue as cv -from openmc.stats.multivariate import MeshIndependent +from openmc.stats.multivariate import MeshSpatial from . import RegularMesh, Source, VolumeCalculation, WeightWindows from ._xml import clean_indentation, get_text, reorder_attributes @@ -977,7 +977,7 @@ class Settings: def _create_source_subelement(self, root): for source in self.source: root.append(source.to_xml_element()) - if isinstance(source.space, MeshIndependent): + if isinstance(source.space, MeshSpatial): path = f"./mesh[@id='{source.space.mesh.id}']" if root.find(path) is None: root.append(source.space.mesh.to_xml_element()) @@ -1328,13 +1328,16 @@ class Settings: def _source_from_xml_element(self, root): for elem in root.findall('source'): - self.source.append(Source.from_xml_element(elem)) - if isinstance(Source.from_xml_element(elem), MeshIndependent): + src = Source.from_xml_element(elem) + if isinstance(src.space, MeshSpatial): mesh_id = int(get_text(elem, 'mesh')) path = f"./mesh[@id='{mesh_id}']" mesh_elem = root.find(path) if mesh_elem is not None: - self.source.space.mesh = MeshBase.from_xml_element(mesh_elem) + src.space.mesh = MeshBase.from_xml_element(mesh_elem) + else: + raise RuntimeError('No mesh was specified for the mesh source') + self.source.append(src) def _volume_calcs_from_xml_element(self, root): volume_elems = root.findall("volume_calc") diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 0df540ddd..9aa03b2d7 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -271,7 +271,7 @@ class Spatial(ABC): elif distribution == 'spherical': return SphericalIndependent.from_xml_element(elem) elif distribution == 'mesh': - return MeshIndependent.from_xml_element(elem) + return MeshSpatial.from_xml_element(elem) elif distribution == 'box' or distribution == 'fission': return Box.from_xml_element(elem) elif distribution == 'point': @@ -619,10 +619,10 @@ class CylindricalIndependent(Spatial): origin = [float(x) for x in elem.get('origin').split()] return cls(r, phi, z, origin=origin) -class MeshIndependent(Spatial): +class MeshSpatial(Spatial): """Spatial distribution for a mesh. - This distribution allows one to specify a mesh to sample over and the scheme to sample over the entire mesh. + This distribution specifies a mesh to sample over, chooses whether it will be volume normalized, and can set the source strengths. .. versionadded:: 0.13 @@ -716,7 +716,7 @@ class MeshIndependent(Spatial): Returns ------- - openmc.stats.MeshIndependent + openmc.stats.MeshSpatial Spatial distribution generated from XML element """ diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 0ac24e39a..6d00739b0 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -183,24 +183,23 @@ Position SphericalIndependent::sample(uint64_t* seed) const } //============================================================================== -// MeshIndependent implementation +// MeshSpatial implementation //============================================================================== -MeshIndependent::MeshIndependent(pugi::xml_node node) +MeshSpatial::MeshSpatial(pugi::xml_node node) { // No in-tet distributions implemented, could include distributions for the barycentric coords // Read in unstructured mesh from mesh_id value int32_t mesh_id = std::stoi(get_node_value(node, "mesh_id")); // Get pointer to spatial distribution - mesh_map_idx_ = model::mesh_map.at(mesh_id); - const auto& mesh_ptr = model::meshes[mesh_map_idx_]; + mesh_idx_ = model::mesh_map.at(mesh_id); - // Check whether mesh pointer points to an unstructured mesh - umesh_ptr_ = dynamic_cast(mesh_ptr.get()); - if (!umesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not an unstructured mesh object"); } + // Check whether mesh pointer points to a mesh + mesh_ptr_ = dynamic_cast(model::meshes[mesh_idx_].get()); + if (!mesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not a mesh object"); } // Initialize arrays for CDF creation - tot_bins_ = umesh_ptr_->n_bins(); + tot_bins_ = mesh_ptr_->n_bins(); std::vector strengths = {}; strengths.resize(tot_bins_); double temp_total_strength = 0.0; @@ -219,7 +218,7 @@ MeshIndependent::MeshIndependent(pugi::xml_node node) fatal_error("The size of the strengths array from the xml file does not equal the number of elements in the mesh."); } if (get_node_value_bool(node, "volume_normalized")){ for (int i = 0; i < tot_bins_; i++){ - strengths[i] = mesh_strengths_[i]*umesh_ptr_->volume(i); + strengths[i] = mesh_strengths_[i]*mesh_ptr_->volume(i); } } else if (!get_node_value_bool(node, "volume_normalized")){ for (int i = 0; i < tot_bins_; i++){ @@ -228,7 +227,7 @@ MeshIndependent::MeshIndependent(pugi::xml_node node) } } else if (get_node_value_bool(node, "volume_normalized")){ for (int i = 0; ivolume(i); + strengths[i] = mesh_ptr_->volume(i); } } else { for (int i = 0; isample(seed, tet_bin); + return mesh_ptr_->sample(seed, tet_bin); } diff --git a/src/mesh.cpp b/src/mesh.cpp index b37c238f1..453ce572b 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -358,8 +358,14 @@ StructuredMesh::MeshIndex StructuredMesh::get_indices_from_bin(int bin) const return ijk; } -Position StructuredMesh::sample(uint64_t* seed, int32_t bin) const { +Position StructuredMesh::sample(uint64_t* seed, int32_t bin) const +{ fatal_error("Position sampling on structured meshes is not yet implemented"); +} + +double StructuredMesh::volume(int bin) const +{ + fatal_error("Unable to get volume of structured mesh, not yet implemented"); } int StructuredMesh::get_bin(Position r) const diff --git a/src/source.cpp b/src/source.cpp index 2ceff9964..2fdcc319f 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -95,7 +95,7 @@ IndependentSource::IndependentSource(pugi::xml_node node) } else if (type == "spherical") { space_ = UPtrSpace {new SphericalIndependent(node_space)}; } else if (type =="mesh"){ - space_ = UPtrSpace {new MeshIndependent(node_space)}; + space_ = UPtrSpace {new MeshSpatial(node_space)}; } else if (type == "box") { space_ = UPtrSpace {new SpatialBox(node_space)}; } else if (type == "fission") { diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index dfbe74d05..6f8d6fded 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -34,15 +34,14 @@ class UnstructuredMeshSourceTest(PyAPITestHarness): # shown below average_in_hex = 10.0 - call(['../../../../scripts/openmc-track-combine', '-o', 'tracks.h5'] + - glob.glob('tracks_p*.h5')) - - # loop over the tracks and get data + # Load in tracks + openmc.Tracks.combine(glob.glob('tracks_p*.h5')) tracks = openmc.Tracks(filepath='tracks.h5') tracks_born = np.empty((len(tracks), 1)) instances = np.zeros(1000) + # loop over the tracks and get data for i in range(0, len(tracks)): tracks_born[i] = tracks[i].particle_tracks[0].states['cell_id'][0] instances[int(tracks_born[i])-1] += 1 @@ -113,9 +112,9 @@ def test_unstructured_mesh(test_opts): for i in range(0,dimen+1): coord = -10.0 + i * size_hex - surfaces[i][0] = openmc.XPlane(coord, name="X plane at "+str(coord)) - surfaces[i][1] = openmc.YPlane(coord, name="Y plane at "+str(coord)) - surfaces[i][2] = openmc.ZPlane(coord, name="Z plane at "+str(coord)) + surfaces[i][0] = openmc.XPlane(coord, name=f"X plane at {coord}") + surfaces[i][1] = openmc.YPlane(coord, name=f"Y plane at {coord}") + surfaces[i][2] = openmc.ZPlane(coord, name=f"Z plane at {coord}") surfaces[i][0].boundary_type = 'vacuum' surfaces[i][1].boundary_type = 'vacuum' @@ -126,8 +125,8 @@ def test_unstructured_mesh(test_opts): for i in range(0,dimen): cell[i][j][k] = openmc.Cell(name=("x = {}, y = {}, z = {}".format(i,j,k))) cell[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ - +surfaces[j][1] & -surfaces[j+1][1] & \ - +surfaces[k][2] & -surfaces[k+1][2] + +surfaces[j][1] & -surfaces[j+1][1] & \ + +surfaces[k][2] & -surfaces[k+1][2] cell[i][j][k].fill = None universe.add_cell(cell[i][j][k]) @@ -158,13 +157,13 @@ def test_unstructured_mesh(test_opts): # source setup if test_opts['schemes'] == 'volume': - space = openmc.stats.MeshIndependent(volume_normalized=True, mesh=uscd_mesh) + space = openmc.stats.MeshSpatial(volume_normalized=True, mesh=uscd_mesh) elif test_opts['schemes'] == 'file': array = np.zeros(12000) for i in range(0, 12): array[i] = 10 array[i+12] = 2 - space = openmc.stats.MeshIndependent(volume_normalized=False, strengths=array, mesh=uscd_mesh) + space = openmc.stats.MeshSpatial(volume_normalized=False, strengths=array, mesh=uscd_mesh) energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) source = openmc.Source(space=space, energy=energy) From 115be68953b30e64aa886c55db13b0e9d212f3c5 Mon Sep 17 00:00:00 2001 From: NybergWISC Date: Mon, 15 Aug 2022 09:30:57 -0500 Subject: [PATCH 1437/2654] Small refactor of distribution_spatial.cpp and change default of volume_normalized to True --- openmc/stats/multivariate.py | 2 +- src/distribution_spatial.cpp | 33 ++++++++----------- .../unstructured_mesh/source_sampling/test.py | 4 ++- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 9aa03b2d7..88beea2f7 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -643,7 +643,7 @@ class MeshSpatial(Spatial): """ - def __init__(self, mesh, strengths=None, volume_normalized=False): + def __init__(self, mesh, strengths=None, volume_normalized=True): self.mesh = mesh self.strengths = strengths self.volume_normalized = volume_normalized diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 6d00739b0..b47b85281 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -212,34 +212,27 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) // Volume scheme is weighted by the volume of each tet // File scheme is weighted by an array given in the xml file + mesh_strengths_ = std::vector(tot_bins_, 1.0); if (check_for_node(node, "strengths")) { - mesh_strengths_ = get_node_array(node, "strengths"); - if (mesh_strengths_.size() != tot_bins_){ - fatal_error("The size of the strengths array from the xml file does not equal the number of elements in the mesh."); - } if (get_node_value_bool(node, "volume_normalized")){ - for (int i = 0; i < tot_bins_; i++){ - strengths[i] = mesh_strengths_[i]*mesh_ptr_->volume(i); - } - } else if (!get_node_value_bool(node, "volume_normalized")){ - for (int i = 0; i < tot_bins_; i++){ - strengths[i] = mesh_strengths_[i]; + strengths = get_node_array(node, "strengths"); + if (strengths.size() != mesh_strengths_.size()){ + fatal_error("Number of entries in the strength matrix does not match the number of mesh entities"); } - } - } else if (get_node_value_bool(node, "volume_normalized")){ - for (int i = 0; ivolume(i); - } - } else { - for (int i = 0; ivolume(i); } } + for (int i = 0; i Date: Mon, 15 Aug 2022 13:04:47 -0500 Subject: [PATCH 1438/2654] Remove second volume method from mesh header file --- include/openmc/mesh.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 8015d2e4c..310320486 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -483,8 +483,6 @@ public: void to_hdf5(hid_t group) const override; - virtual double volume(int bin) const = 0; - std::string bin_label(int bin) const override; // Methods @@ -528,10 +526,6 @@ public: //! \return element connectivity as IDs of the vertices virtual std::vector connectivity(int id) const = 0; - //! Get the volume of a mesh bin - // - //! \param[in] bin Bin to return the volume for - //! \return Volume of the bin virtual double volume(int bin) const = 0; //! Get the library used for this unstructured mesh From fba3a9a118220b40065bbdcd7d641a3b8926cb50 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 21 Dec 2022 10:52:52 -0600 Subject: [PATCH 1439/2654] tet_bin to elem_bin suggestion from @eepeterson --- src/distribution_spatial.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index b47b85281..a0cfec2f0 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -193,7 +193,7 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) int32_t mesh_id = std::stoi(get_node_value(node, "mesh_id")); // Get pointer to spatial distribution mesh_idx_ = model::mesh_map.at(mesh_id); - + // Check whether mesh pointer points to a mesh mesh_ptr_ = dynamic_cast(model::meshes[mesh_idx_].get()); if (!mesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not a mesh object"); } @@ -237,15 +237,14 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) } Position MeshSpatial::sample(uint64_t* seed) const -{ +{ // Create random variable for sampling element from mesh float eta = prn(seed); // Sample over the CDF defined in initialization above - int32_t tet_bin = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); - return mesh_ptr_->sample(seed, tet_bin); + int32_t elem_bin = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); + return mesh_ptr_->sample(seed, elem_bin); } - //============================================================================== // SpatialBox implementation //============================================================================== From 0ffe0b39c11259c50b1be8fa8210830208af8cec Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Dec 2022 12:10:47 -0600 Subject: [PATCH 1440/2654] Adding docstrings to MeshSpatial Python class --- openmc/stats/multivariate.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 88beea2f7..bff8c301a 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -9,7 +9,7 @@ import numpy as np import openmc.checkvalue as cv from .._xml import get_text from .univariate import Univariate, Uniform, PowerLaw -from ..mesh import MeshBase +from ..mesh import MeshBase, MESHES class UnitSphere(ABC): @@ -276,6 +276,8 @@ class Spatial(ABC): return Box.from_xml_element(elem) elif distribution == 'point': return Point.from_xml_element(elem) + elif distribution == 'mesh': + return MeshSpatial.from_xml_element(elem) class CartesianIndependent(Spatial): @@ -622,29 +624,36 @@ class CylindricalIndependent(Spatial): class MeshSpatial(Spatial): """Spatial distribution for a mesh. - This distribution specifies a mesh to sample over, chooses whether it will be volume normalized, and can set the source strengths. + This distribution specifies a mesh to sample over, chooses whether it will + be volume normalized, and can set the source strengths. .. versionadded:: 0.13 Parameters ---------- mesh : openmc.MeshBase - The mesh instance used for sampling, mesh is written into settings.xml, mesh.id is written into the source distribution + The mesh instance used for sampling, mesh is written into settings.xml, + mesh.id is written into the source distribution strengths : Iterable of Real, optional - A list of values which represent the weights of each element - + A list of values which represent the weights of each element. If no source + strengths are specified, they will be equal for all mesh elements. + volume_normalized : bool, optional + Whether or not the strengths will be normalized by volume. Default is True. Attributes ---------- mesh : openmc.MeshBase - The mesh instance used for sampling, mesh is written into settings.xml, mesh.id is written into the source distribution + The mesh instance used for sampling, mesh is written into settings.xml, + mesh.id is written into the source distribution strengths : Iterable of Real, optional A list of values which represent the weights of each element - + volume_normalized : bool + Whether or not the strengths will be normalized by volume. """ - def __init__(self, mesh, strengths=None, volume_normalized=True): - self.mesh = mesh + def __init__(self, + mesh, strengths=None, volume_normalized=True): + self.mesh = mesh self.strengths = strengths self.volume_normalized = volume_normalized @@ -684,7 +693,7 @@ class MeshSpatial(Spatial): if self.strengths == None: raise ValueError('Strengths are not set') return self.strengths.size - + def to_xml_element(self): """Return XML representation of the spatial distribution @@ -722,13 +731,18 @@ class MeshSpatial(Spatial): """ mesh_id = int(elem.get('mesh_id')) + + # check if this mesh has been read in from another location already + if mesh_id not in MESHES: + raise RuntimeError(f'Could not locate mesh with ID "{mesh_id}"') + volume_normalized = elem.get("volume_normalized") volume_normalized = get_text(elem, 'volume_normalized').lower() == 'true' if elem.get('strengths') is not None: strengths = [float(b) for b in get_text(elem, 'strengths').split()] else: strengths = None - return cls(volume_normalized, mesh_id, strengths) + return cls(MESHES[mesh_id], strengths, volume_normalized) class Box(Spatial): From e100689c8fb84a9dcc55c784839458cec1aa8720 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Dec 2022 12:13:04 -0600 Subject: [PATCH 1441/2654] Minor updates to C++ source. Fix for CDF distribution sampling --- include/openmc/distribution_spatial.h | 11 +++++---- src/distribution_spatial.cpp | 32 +++++++++++++-------------- src/mesh.cpp | 18 +++++++-------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 6d771fd6b..0be6329f5 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -108,14 +108,17 @@ public: //! \return Sampled position Position sample(uint64_t* seed) const; + const unique_ptr& mesh() const { return model::meshes.at(mesh_idx_); } + + int32_t n_sources() const { return this->mesh()->n_bins(); } + private: - Mesh* mesh_ptr_; - int32_t mesh_idx_; + Mesh* mesh_ptr_ {nullptr}; + int32_t mesh_idx_ {C_NONE}; std::string sample_scheme_; - double total_strength_; + double total_strength_ {0.0}; std::vector mesh_CDF_; std::vector mesh_strengths_; - int32_t tot_bins_; }; //============================================================================== diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index a0cfec2f0..7418b483a 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -198,21 +198,18 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) mesh_ptr_ = dynamic_cast(model::meshes[mesh_idx_].get()); if (!mesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not a mesh object"); } - // Initialize arrays for CDF creation - tot_bins_ = mesh_ptr_->n_bins(); - std::vector strengths = {}; - strengths.resize(tot_bins_); - double temp_total_strength = 0.0; - mesh_CDF_.resize(tot_bins_+1); + int32_t n_bins = this->n_sources(); + std::vector strengths(n_bins, 0.0); + + mesh_CDF_.resize(n_bins+1); mesh_CDF_[0] = {0.0}; total_strength_ = 0.0; - mesh_strengths_.resize(tot_bins_); + mesh_strengths_.resize(n_bins); // Create cdfs for sampling for an element over a mesh // Volume scheme is weighted by the volume of each tet // File scheme is weighted by an array given in the xml file - - mesh_strengths_ = std::vector(tot_bins_, 1.0); + mesh_strengths_ = std::vector(n_bins, 1.0); if (check_for_node(node, "strengths")) { strengths = get_node_array(node, "strengths"); if (strengths.size() != mesh_strengths_.size()){ @@ -222,24 +219,27 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) } if (get_node_value_bool(node, "volume_normalized")) { - for (int i = 0; i < tot_bins_; i++) { + for (int i = 0; i < n_bins; i++) { mesh_strengths_[i] *= mesh_ptr_->volume(i); } } - for (int i = 0; i FP_COINCIDENT) { + fatal_error(fmt::format("Mesh sampling CDF is incorrectly formed. Final value is: {}", mesh_CDF_.back())); + } + mesh_CDF_.back() = 1.0; } Position MeshSpatial::sample(uint64_t* seed) const { // Create random variable for sampling element from mesh - float eta = prn(seed); + double eta = prn(seed); // Sample over the CDF defined in initialization above int32_t elem_bin = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); return mesh_ptr_->sample(seed, elem_bin); diff --git a/src/mesh.cpp b/src/mesh.cpp index 453ce572b..abb6f8b8c 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -219,9 +219,9 @@ Position UnstructuredMesh::sample_tet(std::array coords, uint64_t* u = old_s + t + u - 1; } } - return s*(coords[1]-coords[0]) - + t*(coords[2]-coords[0]) - + u*(coords[3]-coords[0]) + return s*(coords[1]-coords[0]) + + t*(coords[2]-coords[0]) + + u*(coords[3]-coords[0]) + coords[0]; } @@ -358,12 +358,12 @@ StructuredMesh::MeshIndex StructuredMesh::get_indices_from_bin(int bin) const return ijk; } -Position StructuredMesh::sample(uint64_t* seed, int32_t bin) const +Position StructuredMesh::sample(uint64_t* seed, int32_t bin) const { fatal_error("Position sampling on structured meshes is not yet implemented"); -} +} -double StructuredMesh::volume(int bin) const +double StructuredMesh::volume(int bin) const { fatal_error("Unable to get volume of structured mesh, not yet implemented"); } @@ -2111,7 +2111,7 @@ Position MOABMesh::sample(uint64_t* seed, int32_t bin) const { for (int i = 0; i < 4; i++) { tet_verts[i] = {p[i][0], p[i][1], p[i][2]}; } - // Samples position within tet using Barycentric stuff + // Samples position within tet using Barycentric stuff Position r = this->sample_tet(tet_verts, seed); return r; @@ -2579,7 +2579,7 @@ Position LibMesh::sample(uint64_t* seed, int32_t bin) const { auto node_ref = elem.node_ref(i); tet_verts[i] = {node_ref(0), node_ref(1), node_ref(2)}; } - // Samples position within tet using Barycentric coordinates + // Samples position within tet using Barycentric coordinates Position r = this->sample_tet(tet_verts, seed); return r; @@ -2766,7 +2766,7 @@ const libMesh::Elem& LibMesh::get_element_from_bin(int bin) const double LibMesh::volume(int bin) const { - return m_->elem_ref(bin).volume(); + return this->get_element_from_bin(bin).volume(); } #endif // LIBMESH From 8e6ce2e16f00c9c61eaef699dc85adec075a75d0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Dec 2022 12:13:35 -0600 Subject: [PATCH 1442/2654] Updates to unstructured mesh sampling tests. --- .../source_sampling/inputs_true0.dat | 6 - .../source_sampling/inputs_true1.dat | 6 - .../source_sampling/inputs_true2.dat | 6 - .../source_sampling/inputs_true3.dat | 6 - .../unstructured_mesh/source_sampling/test.py | 109 +++++++++--------- 5 files changed, 56 insertions(+), 77 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat index c85bdd920..d632825ba 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat @@ -1058,9 +1058,3 @@ 10000 - - - - scatter total absorption - - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat index dca3958c3..7ea0a1bd7 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -1060,9 +1060,3 @@ 10000 - - - - scatter total absorption - - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat index be58bd8f9..24c9400c9 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat @@ -1058,9 +1058,3 @@ 10000 - - - - scatter total absorption - - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat index 5003e7b1b..b4a17a948 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat @@ -1060,9 +1060,3 @@ 10000 - - - - scatter total absorption - - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 46d1e0cb0..b0473a839 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -14,10 +14,13 @@ from subprocess import call TETS_PER_VOXEL = 12 +# This test uses a geometry file that resembles a regular mesh. +# 12 tets are used to match each voxel in the geometry. + class UnstructuredMeshSourceTest(PyAPITestHarness): - def __init__(self, statepoint_name, model, inputs_true, schemes): + def __init__(self, statepoint_name, model, inputs_true, source_strengths): super().__init__(statepoint_name, model, inputs_true) - self.schemes = schemes + self.source_strengths = source_strengths def _run_openmc(self): kwargs = {'openmc_exec' : config['exe'], @@ -30,36 +33,43 @@ class UnstructuredMeshSourceTest(PyAPITestHarness): openmc.run(**kwargs) def _compare_results(self): - # There are 10000 particles and 1000 hexes, this leads to the average - # shown below + # This model contains 1000 geometry cells. Each cell is a hex + # corresponding to 12 of the tets. This test runs 10000 particles. This + # results in the following average for each cell + + # we can compute this based on the number of particles run in the simulation average_in_hex = 10.0 # Load in tracks if config['mpi']: openmc.Tracks.combine(glob.glob('tracks_p*.h5')) - + tracks = openmc.Tracks(filepath='tracks.h5') tracks_born = np.empty((len(tracks), 1)) - instances = np.zeros(1000) + # create an array with an entry for each geometric cell + cell_counts = np.zeros(1000) # loop over the tracks and get data for i in range(0, len(tracks)): + # get the initial cell ID of the track, and assign it for the tracks_born array tracks_born[i] = tracks[i].particle_tracks[0].states['cell_id'][0] - instances[int(tracks_born[i])-1] += 1 + # increment the cell_counts entry for this cell_id + cell_counts[int(tracks_born[i])-1] += 1 - if self.schemes == "file": - assert(instances[0] > 0 and instances[1] > 0) - assert(instances[0] > instances[1]) + if self.source_strengths == 'manual': + assert(cell_counts[0] > 0 and cell_counts[1] > 0) + assert(cell_counts[0] > cell_counts[1]) - for i in range(2, len(instances)): - assert(instances[i] == 0) + # counts for all other cells should be zero + for i in range(2, len(cell_counts)): + assert(cell_counts[i] == 0) else: - assert(np.average(instances) == average_in_hex) - assert(np.std(instances) < np.average(instances)) - assert(np.amax(instances) < np.average(instances)+6*np.std(instances)) - + # check that the average number of source sites in each cell + assert(np.average(cell_counts) == average_in_hex) # this probably shouldn't be exact??? + assert(np.std(cell_counts) < np.average(cell_counts)) + assert(np.amax(cell_counts) < np.average(cell_counts)+6*np.std(cell_counts)) def _cleanup(self): super()._cleanup() @@ -70,24 +80,23 @@ class UnstructuredMeshSourceTest(PyAPITestHarness): os.remove(f) param_values = (['libmesh', 'moab'], # mesh libraries - ['volume', 'file']) # Element weighting schemes + ['uniform', 'manual']) # Element weighting schemes test_cases = [] for i, (lib, schemes) in enumerate(product(*param_values)): test_cases.append({'library' : lib, - 'schemes' : schemes, + 'source_strengths' : schemes, 'inputs_true' : 'inputs_true{}.dat'.format(i)}) -@pytest.mark.parametrize("test_opts", test_cases) -def test_unstructured_mesh(test_opts): - +@pytest.mark.parametrize("test_cases", test_cases) +def test_unstructured_mesh_sampling(test_cases): openmc.reset_auto_ids() # skip the test if the library is not enabled - if test_opts['library'] == 'moab' and not openmc.lib._dagmc_enabled(): + if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") - if test_opts['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): + if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): pytest.skip("LibMesh is not enabled in this build.") ### Materials ### @@ -134,38 +143,34 @@ def test_unstructured_mesh(test_opts): geometry = openmc.Geometry(universe) - mesh_filename = "test_mesh_tets.e" - - uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_opts['library']) - - ### Tallies ### - - # create tallies - tallies = openmc.Tallies() - - tally1 = openmc.Tally(1) - tally1.scores = ['scatter', 'total', 'absorption'] - # Export tallies - tallies = openmc.Tallies([tally1]) - tallies.export_to_xml() - ### Settings ### settings = openmc.Settings() settings.run_mode = 'fixed source' settings.particles = 5000 settings.batches = 2 - settings.max_tracks = 10000 + settings.max_tracks = settings.particles * settings.batches - # source setup - if test_opts['schemes'] == 'volume': - space = openmc.stats.MeshSpatial(volume_normalized=True, mesh=uscd_mesh) - elif test_opts['schemes'] == 'file': - array = np.zeros(12000) - for i in range(0, 12): - array[i] = 10 - array[i+12] = 2 - space = openmc.stats.MeshSpatial(volume_normalized=False, strengths=array, mesh=uscd_mesh) + ### Source ### + mesh_filename = "test_mesh_tets.e" + + uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_cases['library']) + + # set source weights according to test case + if test_cases['source_strengths'] == 'uniform': + vol_norm = True + strengths = None + + elif test_cases['source_strengths'] == 'manual': + vol_norm = False + strengths = np.zeros(12000) + # set non-zero strengths only for the tets corresponding to the + # first two geometric hex cells + strengths[0:12] = 10 + strengths[12:24] = 2 + + # create the spatial distribution based on the mesh + space = openmc.stats.MeshSpatial(uscd_mesh, strengths, vol_norm) energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) source = openmc.Source(space=space, energy=energy) @@ -173,11 +178,9 @@ def test_unstructured_mesh(test_opts): model = openmc.model.Model(geometry=geometry, materials=materials, - tallies=tallies, settings=settings) - harness = UnstructuredMeshSourceTest('statepoint.2.h5', model, - test_opts['inputs_true'], - test_opts['schemes']) - harness.main() + test_cases['inputs_true'], + test_cases['source_strengths']) + harness.main() \ No newline at end of file From 03811745a06208ebf8d749d85fe9ba92c9251ca9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Dec 2022 14:33:56 -0600 Subject: [PATCH 1443/2654] Skip mesh elements without an ID due to overlap in name with WW element --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 157e78263..e314aab3e 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -188,7 +188,7 @@ class StructuredMesh(MeshBase): Returns a numpy.ndarray representing the mesh element centroid coordinates with a shape equal to (ndim, dim1, ..., dimn). Can be unpacked along the first dimension with xx, yy, zz = mesh.centroids. - + """ ndim = self.n_dimension From ce956f851546536711b6dbd44cc791ab5f72f605 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Dec 2022 14:34:17 -0600 Subject: [PATCH 1444/2654] Run ww unit test in tmp dir --- tests/unit_tests/weightwindows/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/weightwindows/test.py b/tests/unit_tests/weightwindows/test.py index d73a52f45..1dfad56aa 100644 --- a/tests/unit_tests/weightwindows/test.py +++ b/tests/unit_tests/weightwindows/test.py @@ -225,7 +225,7 @@ def test_lower_ww_bounds_shape(): assert ww.lower_ww_bounds.shape == (2, 3, 4, 1) -def test_roundtrip(model, wws): +def test_roundtrip(run_in_tmpdir, model, wws): model.settings.weight_windows = wws # write the model with weight windows to XML From 0a83824bea30cfdd8b9fc289f6441d737ad03a02 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Dec 2022 23:44:04 -0600 Subject: [PATCH 1445/2654] Improve distribution testing --- .../unstructured_mesh/source_sampling/test.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index b0473a839..a2d23b226 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -18,9 +18,8 @@ TETS_PER_VOXEL = 12 # 12 tets are used to match each voxel in the geometry. class UnstructuredMeshSourceTest(PyAPITestHarness): - def __init__(self, statepoint_name, model, inputs_true, source_strengths): + def __init__(self, statepoint_name, model, inputs_true): super().__init__(statepoint_name, model, inputs_true) - self.source_strengths = source_strengths def _run_openmc(self): kwargs = {'openmc_exec' : config['exe'], @@ -57,7 +56,9 @@ class UnstructuredMeshSourceTest(PyAPITestHarness): # increment the cell_counts entry for this cell_id cell_counts[int(tracks_born[i])-1] += 1 - if self.source_strengths == 'manual': + source_strengths = self._model.settings.source[0].space.strengths + + if source_strengths is not None: assert(cell_counts[0] > 0 and cell_counts[1] > 0) assert(cell_counts[0] > cell_counts[1]) @@ -67,9 +68,11 @@ class UnstructuredMeshSourceTest(PyAPITestHarness): else: # check that the average number of source sites in each cell + diff = np.abs(cell_counts - average_in_hex) + assert(np.average(cell_counts) == average_in_hex) # this probably shouldn't be exact??? - assert(np.std(cell_counts) < np.average(cell_counts)) - assert(np.amax(cell_counts) < np.average(cell_counts)+6*np.std(cell_counts)) + assert((diff < 2*cell_counts.std()).sum() / diff.size >= 0.75) + assert((diff < 6*cell_counts.std()).sum() / diff.size >= 0.97) def _cleanup(self): super()._cleanup() @@ -181,6 +184,5 @@ def test_unstructured_mesh_sampling(test_cases): settings=settings) harness = UnstructuredMeshSourceTest('statepoint.2.h5', model, - test_cases['inputs_true'], - test_cases['source_strengths']) + test_cases['inputs_true']) harness.main() \ No newline at end of file From 2779902287af68278e8a8f0be9930f6e4f9462c4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 26 Dec 2022 15:24:43 -0600 Subject: [PATCH 1446/2654] Refactoring mesh sampling test to use openmc.lib. Making model a fixture --- .../unstructured_mesh/source_sampling/test.py | 262 ++++++++---------- 1 file changed, 118 insertions(+), 144 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index a2d23b226..3e1609426 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -8,55 +8,141 @@ import numpy as np import openmc import openmc.lib -from tests.testing_harness import PyAPITestHarness +from tests import cdtemp from tests.regression_tests import config from subprocess import call TETS_PER_VOXEL = 12 -# This test uses a geometry file that resembles a regular mesh. -# 12 tets are used to match each voxel in the geometry. -class UnstructuredMeshSourceTest(PyAPITestHarness): - def __init__(self, statepoint_name, model, inputs_true): - super().__init__(statepoint_name, model, inputs_true) +@pytest.fixture +def model(): + ### Materials ### + materials = openmc.Materials() - def _run_openmc(self): - kwargs = {'openmc_exec' : config['exe'], - 'event_based' : config['event'], - 'tracks' : "True"} + water_mat = openmc.Material(material_id=3, name="water") + water_mat.add_nuclide("H1", 2.0) + water_mat.add_nuclide("O16", 1.0) + water_mat.set_density("atom/b-cm", 0.07416) + materials.append(water_mat) - if config['mpi']: - kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']] + ### Geometry ### + # This test uses a geometry file that resembles a regular mesh. + # 12 tets are used to match each voxel in the geometry. - openmc.run(**kwargs) + dimen = 10 + size_hex = 20.0 / dimen + + cells = np.empty((dimen, dimen, dimen), dtype=object) + surfaces = np.empty((dimen + 1, 3), dtype=object) + + geometry = openmc.Geometry() + universe = openmc.Universe(universe_id=1, name="Contains all hexes") + + for i in range(0,dimen+1): + coord = -dimen + i * size_hex + surfaces[i][0] = openmc.XPlane(coord, name=f"X plane at {coord}") + surfaces[i][1] = openmc.YPlane(coord, name=f"Y plane at {coord}") + surfaces[i][2] = openmc.ZPlane(coord, name=f"Z plane at {coord}") + + surfaces[i][0].boundary_type = 'vacuum' + surfaces[i][1].boundary_type = 'vacuum' + surfaces[i][2].boundary_type = 'vacuum' + + for (k, j, i) in np.ndindex(cells.shape): + cells[i][j][k] = openmc.Cell(name=("x = {}, y = {}, z = {}".format(i,j,k))) + cells[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ + +surfaces[j][1] & -surfaces[j+1][1] & \ + +surfaces[k][2] & -surfaces[k+1][2] + cells[i][j][k].fill = None + + universe.add_cell(cells[i][j][k]) + + geometry = openmc.Geometry(universe) + + ### Settings ### + settings = openmc.Settings() + settings.run_mode = 'fixed source' + settings.particles = 5000 + settings.batches = 2 + + return openmc.model.Model(geometry=geometry, + materials=materials, + settings=settings) + + +param_values = (['libmesh', 'moab'], # mesh libraries + ['uniform', 'manual']) # Element weighting schemes + +test_cases = [] +for i, (lib, schemes) in enumerate(product(*param_values)): + test_cases.append({'library' : lib, + 'source_strengths' : schemes, + 'inputs_true' : 'inputs_true{}.dat'.format(i)}) + +def ids(params): + return f"{params['library']}-{params['source_strengths']}" + +@pytest.mark.parametrize("test_cases", test_cases, ids=ids) +def test_unstructured_mesh_sampling(model, test_cases): + # skip the test if the library is not enabled + if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): + pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") + + if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): + pytest.skip("LibMesh is not enabled in this build.") + + # setup mesh source ### + mesh_filename = "test_mesh_tets.e" + + uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_cases['library']) + + n_cells = len(model.geometry.get_all_cells()) + + # set source weights according to test case + if test_cases['source_strengths'] == 'uniform': + vol_norm = True + strengths = None + elif test_cases['source_strengths'] == 'manual': + vol_norm = False + strengths = np.zeros(n_cells*TETS_PER_VOXEL) + # set non-zero strengths only for the tets corresponding to the + # first two geometric hex cells + strengths[0:TETS_PER_VOXEL] = 10 + strengths[TETS_PER_VOXEL:2*TETS_PER_VOXEL] = 2 + + # create the spatial distribution based on the mesh + space = openmc.stats.MeshSpatial(uscd_mesh, strengths, vol_norm) + + energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) + source = openmc.Source(space=space, energy=energy) + model.settings.source = source + + with cdtemp(['test_mesh_tets.e', 'test_mesh_tets.exo']): + model.export_to_xml() + + n_cells = len(model.geometry.get_all_cells()) + + n_samples = 100000 + + cell_counts = np.zeros(n_cells) - def _compare_results(self): # This model contains 1000 geometry cells. Each cell is a hex # corresponding to 12 of the tets. This test runs 10000 particles. This # results in the following average for each cell + average_in_hex = n_samples / n_cells - # we can compute this based on the number of particles run in the simulation - average_in_hex = 10.0 + openmc.lib.init([]) - # Load in tracks - if config['mpi']: - openmc.Tracks.combine(glob.glob('tracks_p*.h5')) + sites = openmc.lib.sample_external_source(n_samples) + cells = [openmc.lib.find_cell(s.r) for s in sites] - tracks = openmc.Tracks(filepath='tracks.h5') - tracks_born = np.empty((len(tracks), 1)) + openmc.lib.finalize() - # create an array with an entry for each geometric cell - cell_counts = np.zeros(1000) + for c in cells: + cell_counts[c[0]._index] += 1 - # loop over the tracks and get data - for i in range(0, len(tracks)): - # get the initial cell ID of the track, and assign it for the tracks_born array - tracks_born[i] = tracks[i].particle_tracks[0].states['cell_id'][0] - # increment the cell_counts entry for this cell_id - cell_counts[int(tracks_born[i])-1] += 1 - - source_strengths = self._model.settings.source[0].space.strengths + source_strengths = model.settings.source[0].space.strengths if source_strengths is not None: assert(cell_counts[0] > 0 and cell_counts[1] > 0) @@ -68,121 +154,9 @@ class UnstructuredMeshSourceTest(PyAPITestHarness): else: # check that the average number of source sites in each cell + # is within the expected deviation diff = np.abs(cell_counts - average_in_hex) assert(np.average(cell_counts) == average_in_hex) # this probably shouldn't be exact??? assert((diff < 2*cell_counts.std()).sum() / diff.size >= 0.75) assert((diff < 6*cell_counts.std()).sum() / diff.size >= 0.97) - - def _cleanup(self): - super()._cleanup() - output = glob.glob('track*.h5') - output += glob.glob('tally*.e') - for f in output: - if os.path.exists(f): - os.remove(f) - -param_values = (['libmesh', 'moab'], # mesh libraries - ['uniform', 'manual']) # Element weighting schemes - -test_cases = [] -for i, (lib, schemes) in enumerate(product(*param_values)): - test_cases.append({'library' : lib, - 'source_strengths' : schemes, - 'inputs_true' : 'inputs_true{}.dat'.format(i)}) - -@pytest.mark.parametrize("test_cases", test_cases) -def test_unstructured_mesh_sampling(test_cases): - openmc.reset_auto_ids() - - # skip the test if the library is not enabled - if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): - pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") - - if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): - pytest.skip("LibMesh is not enabled in this build.") - - ### Materials ### - materials = openmc.Materials() - - water_mat = openmc.Material(material_id=3, name="water") - water_mat.add_nuclide("H1", 2.0) - water_mat.add_nuclide("O16", 1.0) - water_mat.set_density("atom/b-cm", 0.07416) - materials.append(water_mat) - - materials.export_to_xml() - - ### Geometry ### - dimen = 10 - size_hex = 20.0 / dimen - - ### Geometry ### - cell = np.empty((dimen, dimen, dimen), dtype=object) - surfaces = np.empty((dimen + 1, 3), dtype=object) - - geometry = openmc.Geometry() - universe = openmc.Universe(universe_id=1, name="Contains all hexes") - - for i in range(0,dimen+1): - coord = -10.0 + i * size_hex - surfaces[i][0] = openmc.XPlane(coord, name=f"X plane at {coord}") - surfaces[i][1] = openmc.YPlane(coord, name=f"Y plane at {coord}") - surfaces[i][2] = openmc.ZPlane(coord, name=f"Z plane at {coord}") - - surfaces[i][0].boundary_type = 'vacuum' - surfaces[i][1].boundary_type = 'vacuum' - surfaces[i][2].boundary_type = 'vacuum' - - for k in range(0,dimen): - for j in range(0,dimen): - for i in range(0,dimen): - cell[i][j][k] = openmc.Cell(name=("x = {}, y = {}, z = {}".format(i,j,k))) - cell[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ - +surfaces[j][1] & -surfaces[j+1][1] & \ - +surfaces[k][2] & -surfaces[k+1][2] - cell[i][j][k].fill = None - universe.add_cell(cell[i][j][k]) - - geometry = openmc.Geometry(universe) - - ### Settings ### - settings = openmc.Settings() - settings.run_mode = 'fixed source' - settings.particles = 5000 - settings.batches = 2 - - settings.max_tracks = settings.particles * settings.batches - - ### Source ### - mesh_filename = "test_mesh_tets.e" - - uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_cases['library']) - - # set source weights according to test case - if test_cases['source_strengths'] == 'uniform': - vol_norm = True - strengths = None - - elif test_cases['source_strengths'] == 'manual': - vol_norm = False - strengths = np.zeros(12000) - # set non-zero strengths only for the tets corresponding to the - # first two geometric hex cells - strengths[0:12] = 10 - strengths[12:24] = 2 - - # create the spatial distribution based on the mesh - space = openmc.stats.MeshSpatial(uscd_mesh, strengths, vol_norm) - - energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) - source = openmc.Source(space=space, energy=energy) - settings.source = source - - model = openmc.model.Model(geometry=geometry, - materials=materials, - settings=settings) - harness = UnstructuredMeshSourceTest('statepoint.2.h5', - model, - test_cases['inputs_true']) - harness.main() \ No newline at end of file From ef14e0e8006dc1a8751299ade65d8f485123c3c4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 26 Dec 2022 22:29:15 -0600 Subject: [PATCH 1447/2654] Separating tests into unit and regression tests. --- .../source_sampling/inputs_true0.dat | 7 +- .../source_sampling/inputs_true1.dat | 3 +- .../source_sampling/inputs_true2.dat | 1060 ---------------- .../source_sampling/inputs_true3.dat | 1062 ----------------- .../unstructured_mesh/source_sampling/test.py | 106 +- tests/unit_tests/test_mesh_tets.e | 1 + tests/unit_tests/test_source_mesh.py | 154 +++ 7 files changed, 187 insertions(+), 2206 deletions(-) delete mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat delete mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat create mode 120000 tests/unit_tests/test_mesh_tets.e create mode 100644 tests/unit_tests/test_source_mesh.py diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat index d632825ba..43942c473 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat @@ -1045,10 +1045,12 @@ fixed source - 5000 + 100 2 - + + 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + 15000000.0 1.0 @@ -1056,5 +1058,4 @@ test_mesh_tets.e - 10000 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat index 7ea0a1bd7..43942c473 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -1045,7 +1045,7 @@ fixed source - 5000 + 100 2 @@ -1058,5 +1058,4 @@ test_mesh_tets.e - 10000 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat deleted file mode 100644 index 24c9400c9..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true2.dat +++ /dev/null @@ -1,1060 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 5000 - 2 - - - - 15000000.0 1.0 - - - - test_mesh_tets.e - - 10000 - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat deleted file mode 100644 index b4a17a948..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true3.dat +++ /dev/null @@ -1,1062 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 5000 - 2 - - - 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - - - 15000000.0 1.0 - - - - test_mesh_tets.e - - 10000 - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 3e1609426..3612c6cf4 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -1,6 +1,4 @@ -import glob from itertools import product -import os import pytest import numpy as np @@ -9,6 +7,7 @@ import openmc import openmc.lib from tests import cdtemp +from tests.testing_harness import PyAPITestHarness from tests.regression_tests import config from subprocess import call @@ -17,6 +16,8 @@ TETS_PER_VOXEL = 12 @pytest.fixture def model(): + openmc.reset_auto_ids() + ### Materials ### materials = openmc.Materials() @@ -63,100 +64,47 @@ def model(): ### Settings ### settings = openmc.Settings() settings.run_mode = 'fixed source' - settings.particles = 5000 + settings.particles = 100 settings.batches = 2 - return openmc.model.Model(geometry=geometry, - materials=materials, - settings=settings) - - -param_values = (['libmesh', 'moab'], # mesh libraries - ['uniform', 'manual']) # Element weighting schemes - -test_cases = [] -for i, (lib, schemes) in enumerate(product(*param_values)): - test_cases.append({'library' : lib, - 'source_strengths' : schemes, - 'inputs_true' : 'inputs_true{}.dat'.format(i)}) - -def ids(params): - return f"{params['library']}-{params['source_strengths']}" - -@pytest.mark.parametrize("test_cases", test_cases, ids=ids) -def test_unstructured_mesh_sampling(model, test_cases): - # skip the test if the library is not enabled - if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): - pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") - - if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): - pytest.skip("LibMesh is not enabled in this build.") - - # setup mesh source ### mesh_filename = "test_mesh_tets.e" - uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_cases['library']) + uscd_mesh = openmc.UnstructuredMesh(mesh_filename, 'libmesh') - n_cells = len(model.geometry.get_all_cells()) + n_cells = len(geometry.get_all_cells()) # set source weights according to test case - if test_cases['source_strengths'] == 'uniform': - vol_norm = True - strengths = None - elif test_cases['source_strengths'] == 'manual': - vol_norm = False - strengths = np.zeros(n_cells*TETS_PER_VOXEL) - # set non-zero strengths only for the tets corresponding to the - # first two geometric hex cells - strengths[0:TETS_PER_VOXEL] = 10 - strengths[TETS_PER_VOXEL:2*TETS_PER_VOXEL] = 2 + vol_norm = False + strengths = np.zeros(n_cells*TETS_PER_VOXEL) + # set non-zero strengths only for the tets corresponding to the + # first two geometric hex cells + strengths[0:TETS_PER_VOXEL] = 10 + strengths[TETS_PER_VOXEL:2*TETS_PER_VOXEL] = 2 # create the spatial distribution based on the mesh space = openmc.stats.MeshSpatial(uscd_mesh, strengths, vol_norm) energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) source = openmc.Source(space=space, energy=energy) - model.settings.source = source + settings.source = source - with cdtemp(['test_mesh_tets.e', 'test_mesh_tets.exo']): - model.export_to_xml() + return openmc.model.Model(geometry=geometry, + materials=materials, + settings=settings) - n_cells = len(model.geometry.get_all_cells()) - n_samples = 100000 +test_cases = [] +for i, lib, in enumerate(['libmesh', 'moab']): + test_cases.append({'library' : lib, + 'inputs_true' : 'inputs_true{}.dat'.format(i)}) - cell_counts = np.zeros(n_cells) +def ids(params): + return params['library'] - # This model contains 1000 geometry cells. Each cell is a hex - # corresponding to 12 of the tets. This test runs 10000 particles. This - # results in the following average for each cell - average_in_hex = n_samples / n_cells +@pytest.mark.parametrize("test_cases", test_cases, ids=ids) +def test_unstructured_mesh_sampling(model, test_cases): - openmc.lib.init([]) + model.settings.source[0].space.mesh.libaray = test_cases['library'] - sites = openmc.lib.sample_external_source(n_samples) - cells = [openmc.lib.find_cell(s.r) for s in sites] - - openmc.lib.finalize() - - for c in cells: - cell_counts[c[0]._index] += 1 - - source_strengths = model.settings.source[0].space.strengths - - if source_strengths is not None: - assert(cell_counts[0] > 0 and cell_counts[1] > 0) - assert(cell_counts[0] > cell_counts[1]) - - # counts for all other cells should be zero - for i in range(2, len(cell_counts)): - assert(cell_counts[i] == 0) - - else: - # check that the average number of source sites in each cell - # is within the expected deviation - diff = np.abs(cell_counts - average_in_hex) - - assert(np.average(cell_counts) == average_in_hex) # this probably shouldn't be exact??? - assert((diff < 2*cell_counts.std()).sum() / diff.size >= 0.75) - assert((diff < 6*cell_counts.std()).sum() / diff.size >= 0.97) + harness = PyAPITestHarness('statepoint.2.h5', model, test_cases['inputs_true']) + harness.main() \ No newline at end of file diff --git a/tests/unit_tests/test_mesh_tets.e b/tests/unit_tests/test_mesh_tets.e new file mode 120000 index 000000000..8a6287b4d --- /dev/null +++ b/tests/unit_tests/test_mesh_tets.e @@ -0,0 +1 @@ +../regression_tests/unstructured_mesh/test_mesh_tets.e \ No newline at end of file diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py new file mode 100644 index 000000000..f9273b7c5 --- /dev/null +++ b/tests/unit_tests/test_source_mesh.py @@ -0,0 +1,154 @@ +from itertools import product + +import pytest +import numpy as np + +import openmc +import openmc.lib + +from tests import cdtemp +from tests.regression_tests import config +from subprocess import call + +TETS_PER_VOXEL = 12 + +@pytest.fixture +def model(): + openmc.reset_auto_ids() + + ### Materials ### + materials = openmc.Materials() + + water_mat = openmc.Material(material_id=3, name="water") + water_mat.add_nuclide("H1", 2.0) + water_mat.add_nuclide("O16", 1.0) + water_mat.set_density("atom/b-cm", 0.07416) + materials.append(water_mat) + + ### Geometry ### + # This test uses a geometry file that resembles a regular mesh. + # 12 tets are used to match each voxel in the geometry. + + dimen = 10 + size_hex = 20.0 / dimen + + cells = np.empty((dimen, dimen, dimen), dtype=object) + surfaces = np.empty((dimen + 1, 3), dtype=object) + + geometry = openmc.Geometry() + universe = openmc.Universe(universe_id=1, name="Contains all hexes") + + for i in range(0, dimen+1): + coord = -dimen + i * size_hex + surfaces[i][0] = openmc.XPlane(coord, name=f"X plane at {coord}") + surfaces[i][1] = openmc.YPlane(coord, name=f"Y plane at {coord}") + surfaces[i][2] = openmc.ZPlane(coord, name=f"Z plane at {coord}") + + surfaces[i][0].boundary_type = 'vacuum' + surfaces[i][1].boundary_type = 'vacuum' + surfaces[i][2].boundary_type = 'vacuum' + + for (k, j, i) in np.ndindex(cells.shape): + cells[i][j][k] = openmc.Cell(name=("x = {}, y = {}, z = {}".format(i,j,k))) + cells[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ + +surfaces[j][1] & -surfaces[j+1][1] & \ + +surfaces[k][2] & -surfaces[k+1][2] + cells[i][j][k].fill = None + + universe.add_cell(cells[i][j][k]) + + geometry = openmc.Geometry(universe) + + ### Settings ### + settings = openmc.Settings() + settings.run_mode = 'fixed source' + settings.particles = 100 + settings.batches = 2 + + return openmc.model.Model(geometry=geometry, + materials=materials, + settings=settings) + +param_values = (['libmesh', 'moab'], # mesh libraries + ['uniform', 'manual']) # Element weighting schemes + +test_cases = [] +for i, (lib, schemes) in enumerate(product(*param_values)): + test_cases.append({'library' : lib, + 'source_strengths' : schemes}) + +def ids(params): + return f"{params['library']}-{params['source_strengths']}" + +@pytest.mark.parametrize("test_cases", test_cases, ids=ids) +def test_unstructured_mesh_sampling(model, test_cases): + # skip the test if the library is not enabled + if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): + pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") + + if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): + pytest.skip("LibMesh is not enabled in this build.") + + # setup mesh source ### + mesh_filename = "test_mesh_tets.e" + + uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_cases['library']) + + n_cells = len(model.geometry.get_all_cells()) + + # set source weights according to test case + if test_cases['source_strengths'] == 'uniform': + vol_norm = True + strengths = None + elif test_cases['source_strengths'] == 'manual': + vol_norm = False + strengths = np.zeros(n_cells*TETS_PER_VOXEL) + # set non-zero strengths only for the tets corresponding to the + # first two geometric hex cells + strengths[0:TETS_PER_VOXEL] = 10 + strengths[TETS_PER_VOXEL:2*TETS_PER_VOXEL] = 2 + + # create the spatial distribution based on the mesh + space = openmc.stats.MeshSpatial(uscd_mesh, strengths, vol_norm) + + energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) + source = openmc.Source(space=space, energy=energy) + model.settings.source = source + + with cdtemp(['test_mesh_tets.e']): + model.export_to_xml() + + n_cells = len(model.geometry.get_all_cells()) + + n_samples = 50000 + + cell_counts = np.zeros(n_cells) + + # This model contains 1000 geometry cells. Each cell is a hex + # corresponding to 12 of the tets. This test runs 10000 particles. This + # results in the following average for each cell + average_in_hex = n_samples / n_cells + + openmc.lib.init([]) + sites = openmc.lib.sample_external_source(n_samples) + cells = [openmc.lib.find_cell(s.r) for s in sites] + openmc.lib.finalize() + + for c in cells: + cell_counts[c[0]._index] += 1 + + if strengths is not None: + assert(cell_counts[0] > 0 and cell_counts[1] > 0) + assert(cell_counts[0] > cell_counts[1]) + + # counts for all other cells should be zero + for i in range(2, len(cell_counts)): + assert(cell_counts[i] == 0) + else: + # check that the average number of source sites in each cell + # is within the expected deviation + diff = np.abs(cell_counts - average_in_hex) + + assert(np.average(cell_counts) == average_in_hex) # this probably shouldn't be exact??? + assert((diff < 2*cell_counts.std()).sum() / diff.size >= 0.75) + assert((diff < 6*cell_counts.std()).sum() / diff.size >= 0.97) From bc7c8cd89260181c4b30c9e854062bb515602b51 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 26 Dec 2022 22:30:18 -0600 Subject: [PATCH 1448/2654] Adding empty results for now --- .../unstructured_mesh/source_sampling/results_true.dat | 0 .../unstructured_mesh/source_sampling/test_mesh_tets.exo | 1 - 2 files changed, 1 deletion(-) create mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat delete mode 120000 tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat b/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo b/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo deleted file mode 120000 index 6d40011d4..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.exo +++ /dev/null @@ -1 +0,0 @@ -../test_mesh_tets.exo \ No newline at end of file From 996930f7f1a924d127829dda136e6a76d9e4db4d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 26 Dec 2022 22:57:37 -0600 Subject: [PATCH 1449/2654] Improved testing for manually set source strengths --- tests/unit_tests/test_source_mesh.py | 50 +++++++++++++++------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index f9273b7c5..18c6f3360 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -102,11 +102,8 @@ def test_unstructured_mesh_sampling(model, test_cases): strengths = None elif test_cases['source_strengths'] == 'manual': vol_norm = False - strengths = np.zeros(n_cells*TETS_PER_VOXEL) - # set non-zero strengths only for the tets corresponding to the - # first two geometric hex cells - strengths[0:TETS_PER_VOXEL] = 10 - strengths[TETS_PER_VOXEL:2*TETS_PER_VOXEL] = 2 + # assign random weights + strengths = np.random.rand(n_cells*TETS_PER_VOXEL) # create the spatial distribution based on the mesh space = openmc.stats.MeshSpatial(uscd_mesh, strengths, vol_norm) @@ -120,9 +117,10 @@ def test_unstructured_mesh_sampling(model, test_cases): n_cells = len(model.geometry.get_all_cells()) - n_samples = 50000 + n_measurements = 100 + n_samples = 1000 - cell_counts = np.zeros(n_cells) + cell_counts = np.zeros((n_cells, n_measurements)) # This model contains 1000 geometry cells. Each cell is a hex # corresponding to 12 of the tets. This test runs 10000 particles. This @@ -130,25 +128,31 @@ def test_unstructured_mesh_sampling(model, test_cases): average_in_hex = n_samples / n_cells openmc.lib.init([]) - sites = openmc.lib.sample_external_source(n_samples) - cells = [openmc.lib.find_cell(s.r) for s in sites] + + # perform many sets of samples and track counts for each cell + for m in range(n_measurements): + sites = openmc.lib.sample_external_source(n_samples) + cells = [openmc.lib.find_cell(s.r) for s in sites] + + for c in cells: + cell_counts[c[0]._index, m] += 1 + openmc.lib.finalize() - for c in cells: - cell_counts[c[0]._index] += 1 + # normalize cell counts to get sampling frequency per particle + cell_counts /= n_samples - if strengths is not None: - assert(cell_counts[0] > 0 and cell_counts[1] > 0) - assert(cell_counts[0] > cell_counts[1]) + # get the mean and std. dev. of the cell counts + mean = cell_counts.mean(axis=1) + std_dev = cell_counts.std(axis=1) - # counts for all other cells should be zero - for i in range(2, len(cell_counts)): - assert(cell_counts[i] == 0) + if test_cases['source_strengths'] == 'uniform': + exp_vals = np.ones(n_cells) / n_cells else: - # check that the average number of source sites in each cell - # is within the expected deviation - diff = np.abs(cell_counts - average_in_hex) + # sum up the source strengths for each tet, these are the expected true mean + # of the sampling frequency for that cell + exp_vals = strengths.reshape(-1, 12).sum(axis=1) / sum(strengths) - assert(np.average(cell_counts) == average_in_hex) # this probably shouldn't be exact??? - assert((diff < 2*cell_counts.std()).sum() / diff.size >= 0.75) - assert((diff < 6*cell_counts.std()).sum() / diff.size >= 0.97) + diff = np.abs(mean - exp_vals) + assert((diff < 2*std_dev).sum() / diff[:10].size >= 0.95) + assert((diff < 6*std_dev).sum() / diff.size >= 0.97) From eca2a1ad2eefa5c3ee14c63ea612c150330cf781 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Dec 2022 11:45:11 -0600 Subject: [PATCH 1450/2654] Reworking geometry model. --- .../source_sampling/inputs_true0.dat | 2155 +++++++++-------- .../source_sampling/inputs_true1.dat | 2155 +++++++++-------- .../unstructured_mesh/source_sampling/test.py | 44 +- tests/unit_tests/test_source_mesh.py | 47 +- 4 files changed, 2274 insertions(+), 2127 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat index 43942c473..dcb56d403 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat @@ -1,1038 +1,1127 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 2 2 + 10 10 10 + -10 -10 -10 + +91 92 93 94 95 96 97 98 99 100 +81 82 83 84 85 86 87 88 89 90 +71 72 73 74 75 76 77 78 79 80 +61 62 63 64 65 66 67 68 69 70 +51 52 53 54 55 56 57 58 59 60 +41 42 43 44 45 46 47 48 49 50 +31 32 33 34 35 36 37 38 39 40 +21 22 23 24 25 26 27 28 29 30 +11 12 13 14 15 16 17 18 19 20 +1 2 3 4 5 6 7 8 9 10 + +191 192 193 194 195 196 197 198 199 200 +181 182 183 184 185 186 187 188 189 190 +171 172 173 174 175 176 177 178 179 180 +161 162 163 164 165 166 167 168 169 170 +151 152 153 154 155 156 157 158 159 160 +141 142 143 144 145 146 147 148 149 150 +131 132 133 134 135 136 137 138 139 140 +121 122 123 124 125 126 127 128 129 130 +111 112 113 114 115 116 117 118 119 120 +101 102 103 104 105 106 107 108 109 110 + +291 292 293 294 295 296 297 298 299 300 +281 282 283 284 285 286 287 288 289 290 +271 272 273 274 275 276 277 278 279 280 +261 262 263 264 265 266 267 268 269 270 +251 252 253 254 255 256 257 258 259 260 +241 242 243 244 245 246 247 248 249 250 +231 232 233 234 235 236 237 238 239 240 +221 222 223 224 225 226 227 228 229 230 +211 212 213 214 215 216 217 218 219 220 +201 202 203 204 205 206 207 208 209 210 + +391 392 393 394 395 396 397 398 399 400 +381 382 383 384 385 386 387 388 389 390 +371 372 373 374 375 376 377 378 379 380 +361 362 363 364 365 366 367 368 369 370 +351 352 353 354 355 356 357 358 359 360 +341 342 343 344 345 346 347 348 349 350 +331 332 333 334 335 336 337 338 339 340 +321 322 323 324 325 326 327 328 329 330 +311 312 313 314 315 316 317 318 319 320 +301 302 303 304 305 306 307 308 309 310 + +491 492 493 494 495 496 497 498 499 500 +481 482 483 484 485 486 487 488 489 490 +471 472 473 474 475 476 477 478 479 480 +461 462 463 464 465 466 467 468 469 470 +451 452 453 454 455 456 457 458 459 460 +441 442 443 444 445 446 447 448 449 450 +431 432 433 434 435 436 437 438 439 440 +421 422 423 424 425 426 427 428 429 430 +411 412 413 414 415 416 417 418 419 420 +401 402 403 404 405 406 407 408 409 410 + +591 592 593 594 595 596 597 598 599 600 +581 582 583 584 585 586 587 588 589 590 +571 572 573 574 575 576 577 578 579 580 +561 562 563 564 565 566 567 568 569 570 +551 552 553 554 555 556 557 558 559 560 +541 542 543 544 545 546 547 548 549 550 +531 532 533 534 535 536 537 538 539 540 +521 522 523 524 525 526 527 528 529 530 +511 512 513 514 515 516 517 518 519 520 +501 502 503 504 505 506 507 508 509 510 + +691 692 693 694 695 696 697 698 699 700 +681 682 683 684 685 686 687 688 689 690 +671 672 673 674 675 676 677 678 679 680 +661 662 663 664 665 666 667 668 669 670 +651 652 653 654 655 656 657 658 659 660 +641 642 643 644 645 646 647 648 649 650 +631 632 633 634 635 636 637 638 639 640 +621 622 623 624 625 626 627 628 629 630 +611 612 613 614 615 616 617 618 619 620 +601 602 603 604 605 606 607 608 609 610 + +791 792 793 794 795 796 797 798 799 800 +781 782 783 784 785 786 787 788 789 790 +771 772 773 774 775 776 777 778 779 780 +761 762 763 764 765 766 767 768 769 770 +751 752 753 754 755 756 757 758 759 760 +741 742 743 744 745 746 747 748 749 750 +731 732 733 734 735 736 737 738 739 740 +721 722 723 724 725 726 727 728 729 730 +711 712 713 714 715 716 717 718 719 720 +701 702 703 704 705 706 707 708 709 710 + +891 892 893 894 895 896 897 898 899 900 +881 882 883 884 885 886 887 888 889 890 +871 872 873 874 875 876 877 878 879 880 +861 862 863 864 865 866 867 868 869 870 +851 852 853 854 855 856 857 858 859 860 +841 842 843 844 845 846 847 848 849 850 +831 832 833 834 835 836 837 838 839 840 +821 822 823 824 825 826 827 828 829 830 +811 812 813 814 815 816 817 818 819 820 +801 802 803 804 805 806 807 808 809 810 + +991 992 993 994 995 996 997 998 999 1000 +981 982 983 984 985 986 987 988 989 990 +971 972 973 974 975 976 977 978 979 980 +961 962 963 964 965 966 967 968 969 970 +951 952 953 954 955 956 957 958 959 960 +941 942 943 944 945 946 947 948 949 950 +931 932 933 934 935 936 937 938 939 940 +921 922 923 924 925 926 927 928 929 930 +911 912 913 914 915 916 917 918 919 920 +901 902 903 904 905 906 907 908 909 910 + + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat index 43942c473..dcb56d403 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -1,1038 +1,1127 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 2 2 + 10 10 10 + -10 -10 -10 + +91 92 93 94 95 96 97 98 99 100 +81 82 83 84 85 86 87 88 89 90 +71 72 73 74 75 76 77 78 79 80 +61 62 63 64 65 66 67 68 69 70 +51 52 53 54 55 56 57 58 59 60 +41 42 43 44 45 46 47 48 49 50 +31 32 33 34 35 36 37 38 39 40 +21 22 23 24 25 26 27 28 29 30 +11 12 13 14 15 16 17 18 19 20 +1 2 3 4 5 6 7 8 9 10 + +191 192 193 194 195 196 197 198 199 200 +181 182 183 184 185 186 187 188 189 190 +171 172 173 174 175 176 177 178 179 180 +161 162 163 164 165 166 167 168 169 170 +151 152 153 154 155 156 157 158 159 160 +141 142 143 144 145 146 147 148 149 150 +131 132 133 134 135 136 137 138 139 140 +121 122 123 124 125 126 127 128 129 130 +111 112 113 114 115 116 117 118 119 120 +101 102 103 104 105 106 107 108 109 110 + +291 292 293 294 295 296 297 298 299 300 +281 282 283 284 285 286 287 288 289 290 +271 272 273 274 275 276 277 278 279 280 +261 262 263 264 265 266 267 268 269 270 +251 252 253 254 255 256 257 258 259 260 +241 242 243 244 245 246 247 248 249 250 +231 232 233 234 235 236 237 238 239 240 +221 222 223 224 225 226 227 228 229 230 +211 212 213 214 215 216 217 218 219 220 +201 202 203 204 205 206 207 208 209 210 + +391 392 393 394 395 396 397 398 399 400 +381 382 383 384 385 386 387 388 389 390 +371 372 373 374 375 376 377 378 379 380 +361 362 363 364 365 366 367 368 369 370 +351 352 353 354 355 356 357 358 359 360 +341 342 343 344 345 346 347 348 349 350 +331 332 333 334 335 336 337 338 339 340 +321 322 323 324 325 326 327 328 329 330 +311 312 313 314 315 316 317 318 319 320 +301 302 303 304 305 306 307 308 309 310 + +491 492 493 494 495 496 497 498 499 500 +481 482 483 484 485 486 487 488 489 490 +471 472 473 474 475 476 477 478 479 480 +461 462 463 464 465 466 467 468 469 470 +451 452 453 454 455 456 457 458 459 460 +441 442 443 444 445 446 447 448 449 450 +431 432 433 434 435 436 437 438 439 440 +421 422 423 424 425 426 427 428 429 430 +411 412 413 414 415 416 417 418 419 420 +401 402 403 404 405 406 407 408 409 410 + +591 592 593 594 595 596 597 598 599 600 +581 582 583 584 585 586 587 588 589 590 +571 572 573 574 575 576 577 578 579 580 +561 562 563 564 565 566 567 568 569 570 +551 552 553 554 555 556 557 558 559 560 +541 542 543 544 545 546 547 548 549 550 +531 532 533 534 535 536 537 538 539 540 +521 522 523 524 525 526 527 528 529 530 +511 512 513 514 515 516 517 518 519 520 +501 502 503 504 505 506 507 508 509 510 + +691 692 693 694 695 696 697 698 699 700 +681 682 683 684 685 686 687 688 689 690 +671 672 673 674 675 676 677 678 679 680 +661 662 663 664 665 666 667 668 669 670 +651 652 653 654 655 656 657 658 659 660 +641 642 643 644 645 646 647 648 649 650 +631 632 633 634 635 636 637 638 639 640 +621 622 623 624 625 626 627 628 629 630 +611 612 613 614 615 616 617 618 619 620 +601 602 603 604 605 606 607 608 609 610 + +791 792 793 794 795 796 797 798 799 800 +781 782 783 784 785 786 787 788 789 790 +771 772 773 774 775 776 777 778 779 780 +761 762 763 764 765 766 767 768 769 770 +751 752 753 754 755 756 757 758 759 760 +741 742 743 744 745 746 747 748 749 750 +731 732 733 734 735 736 737 738 739 740 +721 722 723 724 725 726 727 728 729 730 +711 712 713 714 715 716 717 718 719 720 +701 702 703 704 705 706 707 708 709 710 + +891 892 893 894 895 896 897 898 899 900 +881 882 883 884 885 886 887 888 889 890 +871 872 873 874 875 876 877 878 879 880 +861 862 863 864 865 866 867 868 869 870 +851 852 853 854 855 856 857 858 859 860 +841 842 843 844 845 846 847 848 849 850 +831 832 833 834 835 836 837 838 839 840 +821 822 823 824 825 826 827 828 829 830 +811 812 813 814 815 816 817 818 819 820 +801 802 803 804 805 806 807 808 809 810 + +991 992 993 994 995 996 997 998 999 1000 +981 982 983 984 985 986 987 988 989 990 +971 972 973 974 975 976 977 978 979 980 +961 962 963 964 965 966 967 968 969 970 +951 952 953 954 955 956 957 958 959 960 +941 942 943 944 945 946 947 948 949 950 +931 932 933 934 935 936 937 938 939 940 +921 922 923 924 925 926 927 928 929 930 +911 912 913 914 915 916 917 918 919 920 +901 902 903 904 905 906 907 908 909 910 + + + + + + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 3612c6cf4..d4b445f35 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -13,6 +13,8 @@ from subprocess import call TETS_PER_VOXEL = 12 +# This test uses a geometry file that resembles a regular mesh. + @pytest.fixture def model(): @@ -31,35 +33,19 @@ def model(): # This test uses a geometry file that resembles a regular mesh. # 12 tets are used to match each voxel in the geometry. - dimen = 10 - size_hex = 20.0 / dimen + # create a regular mesh that matches the superimposed mesh + regular_mesh = openmc.RegularMesh(mesh_id=10) + regular_mesh.lower_left = (-10, -10, -10) + regular_mesh.dimension = (10, 10, 10) + regular_mesh.width = (2, 2, 2) - cells = np.empty((dimen, dimen, dimen), dtype=object) - surfaces = np.empty((dimen + 1, 3), dtype=object) + root_cell, cells = regular_mesh.build_cells() - geometry = openmc.Geometry() - universe = openmc.Universe(universe_id=1, name="Contains all hexes") + geometry = openmc.Geometry(root=[root_cell]) - for i in range(0,dimen+1): - coord = -dimen + i * size_hex - surfaces[i][0] = openmc.XPlane(coord, name=f"X plane at {coord}") - surfaces[i][1] = openmc.YPlane(coord, name=f"Y plane at {coord}") - surfaces[i][2] = openmc.ZPlane(coord, name=f"Z plane at {coord}") - - surfaces[i][0].boundary_type = 'vacuum' - surfaces[i][1].boundary_type = 'vacuum' - surfaces[i][2].boundary_type = 'vacuum' - - for (k, j, i) in np.ndindex(cells.shape): - cells[i][j][k] = openmc.Cell(name=("x = {}, y = {}, z = {}".format(i,j,k))) - cells[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ - +surfaces[j][1] & -surfaces[j+1][1] & \ - +surfaces[k][2] & -surfaces[k+1][2] - cells[i][j][k].fill = None - - universe.add_cell(cells[i][j][k]) - - geometry = openmc.Geometry(universe) + # set boundary conditions of the root cell + for surface in root_cell.region.get_surfaces().values(): + surface.boundary_type = 'vacuum' ### Settings ### settings = openmc.Settings() @@ -68,10 +54,10 @@ def model(): settings.batches = 2 mesh_filename = "test_mesh_tets.e" - uscd_mesh = openmc.UnstructuredMesh(mesh_filename, 'libmesh') - n_cells = len(geometry.get_all_cells()) + # subtract one to account for root cell + n_cells = len(geometry.get_all_cells()) - 1 # set source weights according to test case vol_norm = False @@ -87,12 +73,10 @@ def model(): energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) source = openmc.Source(space=space, energy=energy) settings.source = source - return openmc.model.Model(geometry=geometry, materials=materials, settings=settings) - test_cases = [] for i, lib, in enumerate(['libmesh', 'moab']): test_cases.append({'library' : lib, diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index 18c6f3360..223524fdf 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -29,35 +29,19 @@ def model(): # This test uses a geometry file that resembles a regular mesh. # 12 tets are used to match each voxel in the geometry. - dimen = 10 - size_hex = 20.0 / dimen + # create a regular mesh that matches the superimposed mesh + regular_mesh = openmc.RegularMesh(mesh_id=10) + regular_mesh.lower_left = (-10, -10, -10) + regular_mesh.dimension = (10, 10, 10) + regular_mesh.width = (2, 2, 2) - cells = np.empty((dimen, dimen, dimen), dtype=object) - surfaces = np.empty((dimen + 1, 3), dtype=object) + root_cell, cells = regular_mesh.build_cells() - geometry = openmc.Geometry() - universe = openmc.Universe(universe_id=1, name="Contains all hexes") + geometry = openmc.Geometry(root=[root_cell]) - for i in range(0, dimen+1): - coord = -dimen + i * size_hex - surfaces[i][0] = openmc.XPlane(coord, name=f"X plane at {coord}") - surfaces[i][1] = openmc.YPlane(coord, name=f"Y plane at {coord}") - surfaces[i][2] = openmc.ZPlane(coord, name=f"Z plane at {coord}") - - surfaces[i][0].boundary_type = 'vacuum' - surfaces[i][1].boundary_type = 'vacuum' - surfaces[i][2].boundary_type = 'vacuum' - - for (k, j, i) in np.ndindex(cells.shape): - cells[i][j][k] = openmc.Cell(name=("x = {}, y = {}, z = {}".format(i,j,k))) - cells[i][j][k].region = +surfaces[i][0] & -surfaces[i+1][0] & \ - +surfaces[j][1] & -surfaces[j+1][1] & \ - +surfaces[k][2] & -surfaces[k+1][2] - cells[i][j][k].fill = None - - universe.add_cell(cells[i][j][k]) - - geometry = openmc.Geometry(universe) + # set boundary conditions of the root cell + for surface in root_cell.region.get_surfaces().values(): + surface.boundary_type = 'vacuum' ### Settings ### settings = openmc.Settings() @@ -69,6 +53,7 @@ def model(): materials=materials, settings=settings) +### Setup test cases ### param_values = (['libmesh', 'moab'], # mesh libraries ['uniform', 'manual']) # Element weighting schemes @@ -78,6 +63,7 @@ for i, (lib, schemes) in enumerate(product(*param_values)): 'source_strengths' : schemes}) def ids(params): + """Test naming function for clarity""" return f"{params['library']}-{params['source_strengths']}" @pytest.mark.parametrize("test_cases", test_cases, ids=ids) @@ -91,10 +77,10 @@ def test_unstructured_mesh_sampling(model, test_cases): # setup mesh source ### mesh_filename = "test_mesh_tets.e" - uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_cases['library']) - n_cells = len(model.geometry.get_all_cells()) + # subtract one to account for root cell produced by RegularMesh.build_cells + n_cells = len(model.geometry.get_all_cells()) - 1 # set source weights according to test case if test_cases['source_strengths'] == 'uniform': @@ -115,8 +101,6 @@ def test_unstructured_mesh_sampling(model, test_cases): with cdtemp(['test_mesh_tets.e']): model.export_to_xml() - n_cells = len(model.geometry.get_all_cells()) - n_measurements = 100 n_samples = 1000 @@ -135,7 +119,8 @@ def test_unstructured_mesh_sampling(model, test_cases): cells = [openmc.lib.find_cell(s.r) for s in sites] for c in cells: - cell_counts[c[0]._index, m] += 1 + # subtract one from index to account for root cell + cell_counts[c[0]._index - 1, m] += 1 openmc.lib.finalize() From 7fd2f0d7ff28f21032005ed9c4389bffbfa6f6c0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Dec 2022 11:50:29 -0600 Subject: [PATCH 1451/2654] Correcting filepath for test run outside directory --- tests/unit_tests/test_source_mesh.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index 223524fdf..ffc7d73b4 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -1,5 +1,6 @@ from itertools import product +from pathlib import Path import pytest import numpy as np @@ -67,7 +68,7 @@ def ids(params): return f"{params['library']}-{params['source_strengths']}" @pytest.mark.parametrize("test_cases", test_cases, ids=ids) -def test_unstructured_mesh_sampling(model, test_cases): +def test_unstructured_mesh_sampling(model, request, test_cases): # skip the test if the library is not enabled if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") @@ -76,7 +77,7 @@ def test_unstructured_mesh_sampling(model, test_cases): pytest.skip("LibMesh is not enabled in this build.") # setup mesh source ### - mesh_filename = "test_mesh_tets.e" + mesh_filename = Path(request.fspath).parent / "test_mesh_tets.e" uscd_mesh = openmc.UnstructuredMesh(mesh_filename, test_cases['library']) # subtract one to account for root cell produced by RegularMesh.build_cells @@ -98,7 +99,7 @@ def test_unstructured_mesh_sampling(model, test_cases): source = openmc.Source(space=space, energy=energy) model.settings.source = source - with cdtemp(['test_mesh_tets.e']): + with cdtemp([mesh_filename]): model.export_to_xml() n_measurements = 100 From f001d411eee02ba8a6e7599e9235a2adf25d5421 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Dec 2022 12:21:01 -0600 Subject: [PATCH 1452/2654] More small improvements to tests --- .../unstructured_mesh/source_sampling/test.py | 37 +++++++++++-------- tests/unit_tests/test_source_mesh.py | 5 ++- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index d4b445f35..83458e440 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -1,5 +1,6 @@ from itertools import product +from pathlib import Path import pytest import numpy as np @@ -8,14 +9,11 @@ import openmc.lib from tests import cdtemp from tests.testing_harness import PyAPITestHarness -from tests.regression_tests import config -from subprocess import call TETS_PER_VOXEL = 12 -# This test uses a geometry file that resembles a regular mesh. - - +# This test uses a geometry file with cells that match a regular mesh. Each cell +# in the geometry corresponds to 12 tetrahedra in the unstructured mesh file. @pytest.fixture def model(): openmc.reset_auto_ids() @@ -30,16 +28,13 @@ def model(): materials.append(water_mat) ### Geometry ### - # This test uses a geometry file that resembles a regular mesh. - # 12 tets are used to match each voxel in the geometry. - # create a regular mesh that matches the superimposed mesh regular_mesh = openmc.RegularMesh(mesh_id=10) regular_mesh.lower_left = (-10, -10, -10) regular_mesh.dimension = (10, 10, 10) regular_mesh.width = (2, 2, 2) - root_cell, cells = regular_mesh.build_cells() + root_cell, _ = regular_mesh.build_cells() geometry = openmc.Geometry(root=[root_cell]) @@ -59,7 +54,8 @@ def model(): # subtract one to account for root cell n_cells = len(geometry.get_all_cells()) - 1 - # set source weights according to test case + # set source weights manually so the C++ that checks the + # size of the array is executed vol_norm = False strengths = np.zeros(n_cells*TETS_PER_VOXEL) # set non-zero strengths only for the tets corresponding to the @@ -77,18 +73,29 @@ def model(): materials=materials, settings=settings) + test_cases = [] for i, lib, in enumerate(['libmesh', 'moab']): test_cases.append({'library' : lib, 'inputs_true' : 'inputs_true{}.dat'.format(i)}) -def ids(params): - return params['library'] - -@pytest.mark.parametrize("test_cases", test_cases, ids=ids) +@pytest.mark.parametrize("test_cases", test_cases, ids=lambda p: p['library']) def test_unstructured_mesh_sampling(model, test_cases): model.settings.source[0].space.mesh.libaray = test_cases['library'] harness = PyAPITestHarness('statepoint.2.h5', model, test_cases['inputs_true']) - harness.main() \ No newline at end of file + harness.main() + + +def test_strengths_size_failure(request, model): + mesh_source = model.settings.source[0] + + # make sure that an incorrrectly sized strengths array causes a failure + mesh_source.space.strengths = mesh_source.space.strengths[:-1] + + mesh_filename = Path(request.fspath).parent / mesh_source.space.mesh.filename + + with pytest.raises(RuntimeError, match=r'strengths array'), cdtemp([mesh_filename]): + model.export_to_xml() + openmc.run() diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index ffc7d73b4..6549734e8 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -13,6 +13,8 @@ from subprocess import call TETS_PER_VOXEL = 12 +# This test uses a geometry file with cells that match a regular mesh. Each cell +# in the geometry corresponds to 12 tetrahedra in the unstructured mesh file. @pytest.fixture def model(): openmc.reset_auto_ids() @@ -36,7 +38,7 @@ def model(): regular_mesh.dimension = (10, 10, 10) regular_mesh.width = (2, 2, 2) - root_cell, cells = regular_mesh.build_cells() + root_cell, _ = regular_mesh.build_cells() geometry = openmc.Geometry(root=[root_cell]) @@ -142,3 +144,4 @@ def test_unstructured_mesh_sampling(model, request, test_cases): diff = np.abs(mean - exp_vals) assert((diff < 2*std_dev).sum() / diff[:10].size >= 0.95) assert((diff < 6*std_dev).sum() / diff.size >= 0.97) + From 60a2a0e1f80a6438e0cbda436effdf9174d4fafc Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Dec 2022 12:21:27 -0600 Subject: [PATCH 1453/2654] Adding clarity to error message re: improperly sized strengths array --- src/distribution_spatial.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 7418b483a..89fef6155 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -204,7 +204,6 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) mesh_CDF_.resize(n_bins+1); mesh_CDF_[0] = {0.0}; total_strength_ = 0.0; - mesh_strengths_.resize(n_bins); // Create cdfs for sampling for an element over a mesh // Volume scheme is weighted by the volume of each tet @@ -212,10 +211,13 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) mesh_strengths_ = std::vector(n_bins, 1.0); if (check_for_node(node, "strengths")) { strengths = get_node_array(node, "strengths"); - if (strengths.size() != mesh_strengths_.size()){ - fatal_error("Number of entries in the strength matrix does not match the number of mesh entities"); + if (strengths.size() != n_bins) { + fatal_error( + fmt::format("Number of entries in the source strengths array {} does " + "not match the number of entities in mesh {} ({}).", + strengths.size(), mesh_id, n_bins)); } - mesh_strengths_ = strengths; + mesh_strengths_ = std::move(strengths); } if (get_node_value_bool(node, "volume_normalized")) { From 251d7f5436d9a85255ea95b85dd844a300bdc367 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Dec 2022 12:40:16 -0600 Subject: [PATCH 1454/2654] Skip tests if libraries are not enabled --- .../unstructured_mesh/source_sampling/test.py | 6 ++++++ tests/unit_tests/test_source_mesh.py | 1 + 2 files changed, 7 insertions(+) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 83458e440..81f552698 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -81,6 +81,12 @@ for i, lib, in enumerate(['libmesh', 'moab']): @pytest.mark.parametrize("test_cases", test_cases, ids=lambda p: p['library']) def test_unstructured_mesh_sampling(model, test_cases): + # skip the test if the library is not enabled + if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): + pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") + + if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): + pytest.skip("LibMesh is not enabled in this build.") model.settings.source[0].space.mesh.libaray = test_cases['library'] diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index 6549734e8..f093d54d6 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -11,6 +11,7 @@ from tests import cdtemp from tests.regression_tests import config from subprocess import call + TETS_PER_VOXEL = 12 # This test uses a geometry file with cells that match a regular mesh. Each cell From 3779c5cc4dc79816b0c9acf846b705b9efa2e046 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Dec 2022 16:34:58 -0600 Subject: [PATCH 1455/2654] Skip test in absence of UM support --- .../unstructured_mesh/source_sampling/test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 81f552698..0188af3f1 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -97,6 +97,13 @@ def test_unstructured_mesh_sampling(model, test_cases): def test_strengths_size_failure(request, model): mesh_source = model.settings.source[0] + # skip the test if unstructured mesh is not available + if not openmc.lib._libmesh_enabled(): + if openmc.lib._dagmc_enabled(): + mesh_source.space.mesh.library = 'moab' + else: + pytest.skip("Unstructured mesh support unavailable.") + # make sure that an incorrrectly sized strengths array causes a failure mesh_source.space.strengths = mesh_source.space.strengths[:-1] From c6f0d36bdb0ecdc91a13c7acbc630d4926972792 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Dec 2022 23:06:07 -0600 Subject: [PATCH 1456/2654] Correcting attribute name --- .../unstructured_mesh/source_sampling/inputs_true1.dat | 2 +- .../regression_tests/unstructured_mesh/source_sampling/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat index dcb56d403..9e22063f1 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -1144,7 +1144,7 @@ 15000000.0 1.0 - + test_mesh_tets.e diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 0188af3f1..e34bf3b75 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -88,7 +88,7 @@ def test_unstructured_mesh_sampling(model, test_cases): if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): pytest.skip("LibMesh is not enabled in this build.") - model.settings.source[0].space.mesh.libaray = test_cases['library'] + model.settings.source[0].space.mesh.library = test_cases['library'] harness = PyAPITestHarness('statepoint.2.h5', model, test_cases['inputs_true']) harness.main() From 43549cf1f1edb971efba00c593444f71c6539d5c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Dec 2022 08:15:45 -0600 Subject: [PATCH 1457/2654] A couple small changes from original PR comments --- openmc/stats/multivariate.py | 5 ++--- src/distribution_spatial.cpp | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index bff8c301a..799cb9add 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -627,7 +627,7 @@ class MeshSpatial(Spatial): This distribution specifies a mesh to sample over, chooses whether it will be volume normalized, and can set the source strengths. - .. versionadded:: 0.13 + .. versionadded:: 0.13.3 Parameters ---------- @@ -651,8 +651,7 @@ class MeshSpatial(Spatial): Whether or not the strengths will be normalized by volume. """ - def __init__(self, - mesh, strengths=None, volume_normalized=True): + def __init__(self, mesh, strengths=None, volume_normalized=True): self.mesh = mesh self.strengths = strengths self.volume_normalized = volume_normalized diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 89fef6155..c1e000fcd 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -243,8 +243,8 @@ Position MeshSpatial::sample(uint64_t* seed) const // Create random variable for sampling element from mesh double eta = prn(seed); // Sample over the CDF defined in initialization above - int32_t elem_bin = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); - return mesh_ptr_->sample(seed, elem_bin); + int32_t elem_idx = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); + return mesh_ptr_->sample(seed, elem_idx); } //============================================================================== From 580096d4233f757220558560dd013a4c017fc99f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 29 Dec 2022 10:39:41 -0600 Subject: [PATCH 1458/2654] Removing MESHES import --- openmc/stats/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 799cb9add..b491a6843 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -9,7 +9,7 @@ import numpy as np import openmc.checkvalue as cv from .._xml import get_text from .univariate import Univariate, Uniform, PowerLaw -from ..mesh import MeshBase, MESHES +from ..mesh import MeshBase class UnitSphere(ABC): From 8657123baceeb9ac91fe06d991c60db38950e10f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 30 Dec 2022 07:21:11 -0600 Subject: [PATCH 1459/2654] Add some documentation for the new MeshSpatial class. --- docs/source/pythonapi/stats.rst | 1 + docs/source/usersguide/settings.rst | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/pythonapi/stats.rst b/docs/source/pythonapi/stats.rst index fb6383fc7..ffb4fcda2 100644 --- a/docs/source/pythonapi/stats.rst +++ b/docs/source/pythonapi/stats.rst @@ -57,6 +57,7 @@ Spatial Distributions openmc.stats.SphericalIndependent openmc.stats.Box openmc.stats.Point + openmc.stats.MeshSpatial .. autosummary:: :toctree: generated diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index 336982ac6..19373d26e 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -187,7 +187,9 @@ The spatial distribution can be set equal to a sub-class of :class:`openmc.stats.CartesianIndependent`. To independently specify distributions using spherical or cylindrical coordinates, you can use :class:`openmc.stats.SphericalIndependent` or -:class:`openmc.stats.CylindricalIndependent`, respectively. +:class:`openmc.stats.CylindricalIndependent`, respectively. Meshes can also be +used to represent spatial distributions with :class:`openmc.stats.MeshSpatial` +by specifying a mesh and source strengths for each mesh element. The angular distribution can be set equal to a sub-class of :class:`openmc.stats.UnitSphere` such as :class:`openmc.stats.Isotropic`, From 5e2cb6778da11b23579884915fce906d6f06f1c2 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 30 Dec 2022 22:01:11 -0600 Subject: [PATCH 1460/2654] Adding the mesh spatial option to the IO description --- docs/source/io_formats/settings.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 71ca61d54..fc98b662e 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -493,7 +493,10 @@ attributes/sub-elements: independent distributions of r-, cos_theta-, and phi-coordinates where cos_theta is the cosine of the angle with respect to the z-axis, phi is the azimuthal angle, and the sphere is centered on the coordinate - (x0,y0,z0). + (x0,y0,z0). A "mesh" spatial distribution source sites from a mesh element + based on the relative strengths provided in the node. Source locations + within an element are sampled isotropically. If no strengths are provided, + the space within the mesh is uniformly sampled. *Default*: None From 80dad0f2403176c8fe5a501ec7a29ef0963ddf03 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 31 Dec 2022 11:32:39 +0700 Subject: [PATCH 1461/2654] Small fix in plot_xs when S(a,b) tables are present --- openmc/plotter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/plotter.py b/openmc/plotter.py index 16760868e..e2d18d085 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -563,7 +563,7 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., for nuclide in nuclides.items(): sabs[nuclide[0]] = None if isinstance(this, openmc.Material): - for sab_name in this._sab: + for sab_name, _ in this._sab: sab = openmc.data.ThermalScattering.from_hdf5( library.get_by_material(sab_name, data_type='thermal')['path']) for nuc in sab.nuclides: From 219a4b04da32e870301ceabbc0dea45852777c29 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 3 Jan 2023 10:35:44 -0600 Subject: [PATCH 1462/2654] Addressing comments from @NybergWISC Co-authored-by: Matthew Nyberg --- openmc/stats/multivariate.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index b491a6843..171ff4b40 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -270,8 +270,6 @@ class Spatial(ABC): return CylindricalIndependent.from_xml_element(elem) elif distribution == 'spherical': return SphericalIndependent.from_xml_element(elem) - elif distribution == 'mesh': - return MeshSpatial.from_xml_element(elem) elif distribution == 'box' or distribution == 'fission': return Box.from_xml_element(elem) elif distribution == 'point': @@ -625,7 +623,7 @@ class MeshSpatial(Spatial): """Spatial distribution for a mesh. This distribution specifies a mesh to sample over, chooses whether it will - be volume normalized, and can set the source strengths. + be adjusted by element volume, and can set the source strengths. .. versionadded:: 0.13.3 @@ -635,10 +633,12 @@ class MeshSpatial(Spatial): The mesh instance used for sampling, mesh is written into settings.xml, mesh.id is written into the source distribution strengths : Iterable of Real, optional - A list of values which represent the weights of each element. If no source - strengths are specified, they will be equal for all mesh elements. + A list of values which represent the weights of each element. If no + source strengths are specified, they will be equal for all mesh + elements. volume_normalized : bool, optional - Whether or not the strengths will be normalized by volume. Default is True. + Whether or not the strengths will be multiplied by element volumes at + runtime. Default is True. Attributes ---------- @@ -648,7 +648,8 @@ class MeshSpatial(Spatial): strengths : Iterable of Real, optional A list of values which represent the weights of each element volume_normalized : bool - Whether or not the strengths will be normalized by volume. + Whether or not the strengths will be multiplied by element volumes at + runtime. """ def __init__(self, mesh, strengths=None, volume_normalized=True): @@ -672,7 +673,7 @@ class MeshSpatial(Spatial): @volume_normalized.setter def volume_normalized(self, volume_normalized): - cv.check_type('Normalize (multiply) strengths by volume', volume_normalized, bool) + cv.check_type('Multiply strengths by element volumes', volume_normalized, bool) self._volume_normalized = volume_normalized @property From ac2ba93b3a573353a6e2fd051a1a35581f32c257 Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 4 Jan 2023 03:31:07 +0000 Subject: [PATCH 1463/2654] remove cell deepcopying for creating a fresh instance --- openmc/cell.py | 11 ++++++++--- tests/unit_tests/test_cell.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 2aa538012..8169ca4d2 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -1,6 +1,5 @@ from collections import OrderedDict from collections.abc import Iterable -from copy import deepcopy from math import cos, sin, pi from numbers import Real from xml.etree import ElementTree as ET @@ -519,8 +518,14 @@ class Cell(IDManagerMixin): paths = self._paths self._paths = None - clone = deepcopy(self) - clone.id = None + clone = openmc.Cell() + clone.name = self.name + clone.temperature = self.temperature + clone.volume = self.volume + if self.translation is not None: + clone.translation = self.translation + if self.rotation is not None: + clone.rotation = self.rotation clone._num_instances = None # Restore paths on original instance diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 1c2e1b70e..eebe0f895 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -58,24 +58,54 @@ def test_clone(): cyl = openmc.ZCylinder() c = openmc.Cell(fill=m, region=-cyl) c.temperature = 650. + c.translation = (1,2,3) + c.rotation = (4,5,6) + c.volume = 100 c2 = c.clone() assert c2.id != c.id assert c2.fill != c.fill assert c2.region != c.region assert c2.temperature == c.temperature + assert all(c2.translation == c.translation) + assert all(c2.rotation == c.rotation) + assert c2.volume == c.volume c3 = c.clone(clone_materials=False) assert c3.id != c.id assert c3.fill == c.fill assert c3.region != c.region assert c3.temperature == c.temperature + assert all(c2.translation == c.translation) + assert all(c2.rotation == c.rotation) c4 = c.clone(clone_regions=False) assert c4.id != c.id assert c4.fill != c.fill assert c4.region == c.region assert c4.temperature == c.temperature + assert all(c2.translation == c.translation) + assert all(c2.rotation == c.rotation) + + c5 = c.clone(clone_materials=False, clone_regions=False) + assert c5.id != c.id + assert c5.fill == c.fill + assert c5.region == c.region + assert c5.temperature == c.temperature + assert all(c2.translation == c.translation) + assert all(c2.rotation == c.rotation) + + # Mutate the original to ensure the changes are not seen in the clones + c.fill = openmc.Material() + c.region = +openmc.ZCylinder() + c.translation = [-1,-2,-3] + c.rotation = [-4,-5,-6] + c.temperature = 1 + assert c5.fill != c.fill + assert c5.region != c.region + assert c5.temperature != c.temperature + assert all(c2.translation != c.translation) + assert all(c2.rotation != c.rotation) def test_temperature(cell_with_lattice): From affc62f09cdb66bd2fea9ffdf6b44099b1e0afde Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 4 Jan 2023 22:53:55 +0000 Subject: [PATCH 1464/2654] only reassign temps when not None --- openmc/cell.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/cell.py b/openmc/cell.py index 8169ca4d2..cea362ed8 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -520,8 +520,9 @@ class Cell(IDManagerMixin): clone = openmc.Cell() clone.name = self.name - clone.temperature = self.temperature clone.volume = self.volume + if self.temperature is not None: + clone.temperature = self.temperature if self.translation is not None: clone.translation = self.translation if self.rotation is not None: From 60f9a4271172d61c2c36dd57ebbe8bc4a02fe587 Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 4 Jan 2023 22:54:26 +0000 Subject: [PATCH 1465/2654] simplify cell cloning test changes --- tests/unit_tests/test_cell.py | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index eebe0f895..4185e9a44 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -57,43 +57,37 @@ def test_clone(): m = openmc.Material() cyl = openmc.ZCylinder() c = openmc.Cell(fill=m, region=-cyl) - c.temperature = 650. - c.translation = (1,2,3) - c.rotation = (4,5,6) - c.volume = 100 + # Check cloning with all optional params as the defaults c2 = c.clone() assert c2.id != c.id assert c2.fill != c.fill assert c2.region != c.region - assert c2.temperature == c.temperature - assert all(c2.translation == c.translation) - assert all(c2.rotation == c.rotation) - assert c2.volume == c.volume c3 = c.clone(clone_materials=False) assert c3.id != c.id assert c3.fill == c.fill assert c3.region != c.region - assert c3.temperature == c.temperature - assert all(c2.translation == c.translation) - assert all(c2.rotation == c.rotation) c4 = c.clone(clone_regions=False) assert c4.id != c.id assert c4.fill != c.fill assert c4.region == c.region - assert c4.temperature == c.temperature - assert all(c2.translation == c.translation) - assert all(c2.rotation == c.rotation) + + # Add optional properties to the original cell to ensure they're cloned successfully + c.temperature = 650. + c.translation = [1,2,3] + c.rotation = [4,5,6] + c.volume = 100 c5 = c.clone(clone_materials=False, clone_regions=False) assert c5.id != c.id assert c5.fill == c.fill assert c5.region == c.region assert c5.temperature == c.temperature - assert all(c2.translation == c.translation) - assert all(c2.rotation == c.rotation) + assert c5.volume == c.volume + assert all(c5.translation == c.translation) + assert all(c5.rotation == c.rotation) # Mutate the original to ensure the changes are not seen in the clones c.fill = openmc.Material() @@ -101,11 +95,13 @@ def test_clone(): c.translation = [-1,-2,-3] c.rotation = [-4,-5,-6] c.temperature = 1 + c.volume = 1 assert c5.fill != c.fill assert c5.region != c.region assert c5.temperature != c.temperature - assert all(c2.translation != c.translation) - assert all(c2.rotation != c.rotation) + assert c5.volume != c.volume + assert all(c5.translation != c.translation) + assert all(c5.rotation != c.rotation) def test_temperature(cell_with_lattice): From 82429cbb19d4ba10aa771a5493a092cd35711b4f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 5 Jan 2023 11:16:16 +0000 Subject: [PATCH 1466/2654] added test for sab xs appears in xs calc --- tests/unit_tests/test_plotter.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/unit_tests/test_plotter.py diff --git a/tests/unit_tests/test_plotter.py b/tests/unit_tests/test_plotter.py new file mode 100644 index 000000000..a3f1ff666 --- /dev/null +++ b/tests/unit_tests/test_plotter.py @@ -0,0 +1,27 @@ +import openmc +import numpy as np + + +def test_calculate_cexs_elem_mat_sab(): + """Checks that sab cross sections are included in the + _calculate_cexs_elem_mat method and have the correct shape""" + + mat_1 = openmc.Material() + mat_1.add_element("H", 4.0, "ao") + mat_1.add_element("O", 4.0, "ao") + mat_1.add_element("C", 4.0, "ao") + + mat_1.add_s_alpha_beta("c_C6H6") + mat_1.set_density("g/cm3", 0.865) + + energy_grid, data = openmc.plotter._calculate_cexs_elem_mat( + mat_1, + ["inelastic"], + sab_name="c_C6H6", + ) + + assert isinstance(energy_grid, np.ndarray) + assert isinstance(data, np.ndarray) + assert len(energy_grid) > 1 + assert len(data) == 1 + assert len(data[0]) == len(energy_grid) From 9fac1bb4d25d7399d7c942e8605c7dc01cd4824a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 5 Jan 2023 12:13:55 -0600 Subject: [PATCH 1467/2654] Updating note on photon transport limitations --- docs/source/usersguide/settings.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index 336982ac6..760a08e90 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -474,7 +474,6 @@ selected:: Some features related to photon transport are not currently implemented, including: - * Tallying photon energy deposition. * Generating a photon source from a neutron calculation that can be used for a later fixed source photon calculation. * Photoneutron reactions. From 9615b9f5da9a1bccfd0a693f74c9c0437ec1329a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 5 Jan 2023 16:04:33 -0600 Subject: [PATCH 1468/2654] Adding tests for tally triggers. --- tests/unit_tests/test_triggers.py | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests/unit_tests/test_triggers.py diff --git a/tests/unit_tests/test_triggers.py b/tests/unit_tests/test_triggers.py new file mode 100644 index 000000000..4fe6e044a --- /dev/null +++ b/tests/unit_tests/test_triggers.py @@ -0,0 +1,75 @@ + +import openmc + +def test_tally_trigger(run_in_tmpdir): + pincell = openmc.examples.pwr_pin_cell() + + # create a tally filter on the materials + mat_filter = openmc.MaterialFilter(pincell.materials) + + # create a tally with triggers applied + tally = openmc.Tally() + tally.filters = [mat_filter] + tally.scores = ['scatter'] + + trigger = openmc.Trigger('rel_err', 0.05) + trigger.scores = ['scatter'] + + tally.triggers = [trigger] + + pincell.tallies = [tally] + + pincell.settings.trigger_active = True + pincell.settings.trigger_max_batches = 100 + pincell.settings.trigger_batch_interval = 5 + + sp_file = pincell.run() + with openmc.StatePoint(sp_file) as sp: + expected_realizations = sp.n_realizations + + # adding other scores to the tally should not change the + # number of batches required to satisfy the trigger + tally.scores = ['total', 'absorption', 'scatter'] + + sp_file = pincell.run() + + with openmc.StatePoint(sp_file) as sp: + realizations = sp.n_realizations + + assert realizations == expected_realizations + + +def test_tally_trigger_null_score(run_in_tmpdir): + pincell = openmc.examples.pwr_pin_cell() + + # create a tally filter on the materials + mat_filter = openmc.MaterialFilter(pincell.materials) + + # apply a tally with a score that be tallied in this model + tally = openmc.Tally() + tally.filters = [mat_filter] + tally.scores = ['pair-production'] + + trigger = openmc.Trigger('rel_err', 0.05) + trigger.scores = ['pair-production'] + + tally.triggers = [trigger] + + pincell.tallies = [tally] + + pincell.settings.trigger_active = True + pincell.settings.trigger_max_batches = 50 + pincell.settings.trigger_batch_interval = 5 + + sp_file = pincell.run() + + with openmc.StatePoint(sp_file) as sp: + # verify that the tally mean is zero + tally_out = sp.get_tally(id=tally.id) + assert all(tally_out.mean == 0.0) + + # we expect that this simulation will run + # up to the max allowed batches + total_batches = sp.n_realizations + sp.n_inactive + assert total_batches == pincell.settings.trigger_max_batches + From bfcbecdbaa002954c5a25edae670d108ea95369a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 5 Jan 2023 16:25:15 -0600 Subject: [PATCH 1469/2654] Fixing tally triggers. Refs #2342 and #2343 --- src/tallies/trigger.cpp | 87 ++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/src/tallies/trigger.cpp b/src/tallies/trigger.cpp index 2c155980e..79af65879 100644 --- a/src/tallies/trigger.cpp +++ b/src/tallies/trigger.cpp @@ -37,6 +37,10 @@ std::pair get_tally_uncertainty( int n = tally->n_realizations_; auto mean = sum / n; + + // if the result has no contributions, return an invalid pair + if (mean == 0) return {-1 , -1}; + double std_dev = std::sqrt((sum_sq / n - mean * mean) / (n - 1)); double rel_err = (mean != 0.) ? std_dev / std::abs(mean) : 0.; @@ -68,42 +72,49 @@ void check_tally_triggers(double& ratio, int& tally_id, int& score) const auto& results = t.results_; for (auto filter_index = 0; filter_index < results.shape()[0]; ++filter_index) { - for (auto score_index = 0; score_index < results.shape()[1]; - ++score_index) { - // Compute the tally uncertainty metrics. - auto uncert_pair = - get_tally_uncertainty(i_tally, score_index, filter_index); - double std_dev = uncert_pair.first; - double rel_err = uncert_pair.second; + // Compute the tally uncertainty metrics. + auto uncert_pair = + get_tally_uncertainty(i_tally, trigger.score_index, filter_index); - // Pick out the relevant uncertainty metric for this trigger. - double uncertainty; - switch (trigger.metric) { - case TriggerMetric::variance: - uncertainty = std_dev * std_dev; - break; - case TriggerMetric::standard_deviation: - uncertainty = std_dev; - break; - case TriggerMetric::relative_error: - uncertainty = rel_err; - break; - case TriggerMetric::not_active: - UNREACHABLE(); - } + // if there is a score without contributions, set ratio to inf and + // exit early + if (uncert_pair.first == -1) { + ratio = INFINITY; + score = t.scores_[trigger.score_index]; + tally_id = t.id_; + return; + } - // Compute the uncertainty / threshold ratio. - double this_ratio = uncertainty / trigger.threshold; - if (trigger.metric == TriggerMetric::variance) { - this_ratio = std::sqrt(ratio); - } + double std_dev = uncert_pair.first; + double rel_err = uncert_pair.second; - // If this is the most uncertain value, set the output variables. - if (this_ratio > ratio) { - ratio = this_ratio; - score = t.scores_[trigger.score_index]; - tally_id = t.id_; - } + // Pick out the relevant uncertainty metric for this trigger. + double uncertainty; + switch (trigger.metric) { + case TriggerMetric::variance: + uncertainty = std_dev * std_dev; + break; + case TriggerMetric::standard_deviation: + uncertainty = std_dev; + break; + case TriggerMetric::relative_error: + uncertainty = rel_err; + break; + case TriggerMetric::not_active: + UNREACHABLE(); + } + + // Compute the uncertainty / threshold ratio. + double this_ratio = uncertainty / trigger.threshold; + if (trigger.metric == TriggerMetric::variance) { + this_ratio = std::sqrt(ratio); + } + + // If this is the most uncertain value, set the output variables. + if (this_ratio > ratio) { + ratio = this_ratio; + score = t.scores_[trigger.score_index]; + tally_id = t.id_; } } } @@ -181,9 +192,13 @@ void check_triggers() "eigenvalue", keff_ratio); } else { - msg = fmt::format( - "Triggers unsatisfied, max unc./thresh. is {} for {} in tally {}", - tally_ratio, reaction_name(score), tally_id); + if (tally_ratio == INFINITY) { + msg = fmt::format("Triggers unsatisfied, no result tallied for score {} in tally {}", reaction_name(score), tally_id); + } else{ + msg = fmt::format( + "Triggers unsatisfied, max unc./thresh. is {} for {} in tally {}", + tally_ratio, reaction_name(score), tally_id); + } } write_message(msg, 7); From 62af77310897b6de1ef43906a781da0c9fcfe15f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 9 Jan 2023 18:16:45 +0700 Subject: [PATCH 1470/2654] Refactor NCrystal interface code to ncrystal_interface.h/cpp --- CMakeLists.txt | 1 + include/openmc/material.h | 25 ++----- include/openmc/ncrystal_interface.h | 91 +++++++++++++++++++++++ include/openmc/physics.h | 28 +------- include/openmc/settings.h | 8 +-- src/material.cpp | 39 +++------- src/ncrystal_interface.cpp | 108 ++++++++++++++++++++++++++++ src/physics.cpp | 30 ++------ src/settings.cpp | 12 +--- 9 files changed, 229 insertions(+), 113 deletions(-) create mode 100644 include/openmc/ncrystal_interface.h create mode 100644 src/ncrystal_interface.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dee3f90e..4737ff47b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -348,6 +348,7 @@ list(APPEND libopenmc_SOURCES src/message_passing.cpp src/mgxs.cpp src/mgxs_interface.cpp + src/ncrystal_interface.cpp src/nuclide.cpp src/output.cpp src/particle.cpp diff --git a/include/openmc/material.h b/include/openmc/material.h index 5326ad6de..8db9bb628 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -12,13 +12,10 @@ #include "openmc/bremsstrahlung.h" #include "openmc/constants.h" #include "openmc/memory.h" // for unique_ptr +#include "openmc/ncrystal_interface.h" #include "openmc/particle.h" #include "openmc/vector.h" -#ifdef NCRYSTAL -#include "NCrystal/NCrystal.hh" -#endif - namespace openmc { //============================================================================== @@ -155,25 +152,17 @@ public: //! \return Temperature in [K] double temperature() const; -#ifdef NCRYSTAL //! Get pointer to NCrystal material object //! \return Pointer to NCrystal material object - std::shared_ptr ncrystal_mat() const - { - return ncrystal_mat_; - }; -#endif + const NCrystalMat& ncrystal_mat() const { return ncrystal_mat_; }; //---------------------------------------------------------------------------- // Data - int32_t id_ {C_NONE}; //!< Unique ID - std::string name_; //!< Name of material - vector nuclide_; //!< Indices in nuclides vector - vector element_; //!< Indices in elements vector -#ifdef NCRYSTAL - std::string ncrystal_cfg_; //!< NCrystal configuration string - std::shared_ptr ncrystal_mat_; -#endif + int32_t id_ {C_NONE}; //!< Unique ID + std::string name_; //!< Name of material + vector nuclide_; //!< Indices in nuclides vector + vector element_; //!< Indices in elements vector + NCrystalMat ncrystal_mat_; //!< NCrystal material object xt::xtensor atom_density_; //!< Nuclide atom density in [atom/b-cm] double density_; //!< Total atom density in [atom/b-cm] double density_gpcc_; //!< Total atom density in [g/cm^3] diff --git a/include/openmc/ncrystal_interface.h b/include/openmc/ncrystal_interface.h new file mode 100644 index 000000000..36038d50c --- /dev/null +++ b/include/openmc/ncrystal_interface.h @@ -0,0 +1,91 @@ +#ifndef OPENMC_NCRYSTAL_INTERFACE_H +#define OPENMC_NCRYSTAL_INTERFACE_H + +#ifdef NCRYSTAL +#include "NCrystal/NCRNG.hh" +#include "NCrystal/NCrystal.hh" +#endif + +#include "openmc/particle.h" + +#include // for uint64_t +#include // for numeric_limits +#include + +namespace openmc { + +//============================================================================== +// Constants +//============================================================================== + +extern "C" const bool NCRYSTAL_ENABLED; + +//============================================================================== +// Wrapper class an NCrystal material +//============================================================================== + +class NCrystalMat { +public: + //---------------------------------------------------------------------------- + // Constructors + NCrystalMat() = default; + explicit NCrystalMat(const std::string& cfg); + + //---------------------------------------------------------------------------- + // Methods + +#ifdef NCRYSTAL + //! Return configuration string + std::string cfg() const; + + //! Get cross section from NCrystal material + // + //! \param[in] p Particle object + //! \return Cross section in [b] + double xs(const Particle& p) const; + + // Process scattering event + // + //! \param[in] p Particle object + void scatter(Particle& p) const; + + //! Whether the object holds a valid NCrystal material + operator bool() const; +#else + + //---------------------------------------------------------------------------- + // Trivial methods when compiling without NCRYSTAL + std::string cfg() const + { + return ""; + } + double xs(const Particle& p) const + { + return -1.0; + } + void scatter(Particle& p) const {} + operator bool() const + { + return false; + } +#endif + +private: + //---------------------------------------------------------------------------- + // Data members (only present when compiling with NCrystal support) +#ifdef NCRYSTAL + std::string cfg_; //!< NCrystal configuration string + std::shared_ptr + ptr_; //!< Pointer to NCrystal material object +#endif +}; + +//============================================================================== +// Functions +//============================================================================== + +void ncrystal_update_micro(double xs, NuclideMicroXS& micro); + +} // namespace openmc + +#endif // OPENMC_NCRYSTAL_INTERFACE_H diff --git a/include/openmc/physics.h b/include/openmc/physics.h index 806297c4e..382f0f0dd 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -8,10 +8,6 @@ #include "openmc/reaction.h" #include "openmc/vector.h" -#ifdef NCRYSTAL -#include "NCrystal/NCRNG.hh" -#endif - namespace openmc { //============================================================================== @@ -100,31 +96,11 @@ void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p); void sample_secondary_photons(Particle& p, int i_nuclide); -//!Split or Roulette particles based their weight and the lower weight window -// bound. +// !Split or Roulette particles based their weight and the lower weight window +// bound. //! \param[in] p, particle to be split or rouletted with the weight window. void split_particle(Particle& p); -#ifdef NCRYSTAL -//============================================================================== -// NCrystal wrapper class for the OpenMC random number generator -//============================================================================== - -class NCrystalRNGWrapper : public NCrystal::RNGStream { -public: - constexpr NCrystalRNGWrapper(uint64_t* seed) noexcept : openmc_seed_(seed) {} - -protected: - double actualGenerate() override - { - return std::max( - std::numeric_limits::min(), prn(openmc_seed_)); - } -private: - uint64_t* openmc_seed_; -}; -#endif - } // namespace openmc #endif // OPENMC_PHYSICS_H diff --git a/include/openmc/settings.h b/include/openmc/settings.h index fb5f8387a..9cd430deb 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -20,8 +20,6 @@ namespace openmc { // Global variable declarations //============================================================================== -extern "C" const bool NCRYSTAL_ENABLED; - namespace settings { // Boolean flags @@ -93,6 +91,8 @@ extern int n_log_bins; //!< number of bins for logarithmic energy grid extern int n_batches; //!< number of (inactive+active) batches extern int n_max_batches; //!< Maximum number of batches extern int max_tracks; //!< Maximum number of particle tracks written to file +extern double + ncrystal_max_energy; //!< Energy in eV to switch between NCrystal and ENDF extern ResScatMethod res_scat_method; //!< resonance upscattering method extern double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering extern double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering @@ -124,10 +124,6 @@ extern int trigger_batch_interval; //!< Batch interval for triggers extern "C" int verbosity; //!< How verbose to make output extern double weight_cutoff; //!< Weight cutoff for Russian roulette extern double weight_survive; //!< Survival weight after Russian roulette -#ifdef NCRYSTAL -extern double - ncrystal_max_energy; //!< Energy in eV to switch between NCrystal and ENDF -#endif } // namespace settings //============================================================================== diff --git a/src/material.cpp b/src/material.cpp index 25014c448..2d55d6a04 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -60,13 +60,12 @@ Material::Material(pugi::xml_node node) name_ = get_node_value(node, "name"); } -#ifdef NCRYSTAL if (check_for_node(node, "cfg")) { - ncrystal_cfg_ = get_node_value(node, "cfg"); - write_message(5, "NCrystal config string for material #{}: '{}'", this->id(), ncrystal_cfg_); - ncrystal_mat_ = NCrystal::FactImpl::createScatter(ncrystal_cfg_); + auto cfg = get_node_value(node, "cfg"); + write_message( + 5, "NCrystal config string for material #{}: '{}'", this->id(), cfg); + ncrystal_mat_ = NCrystalMat(cfg); } -#endif if (check_for_node(node, "depletable")) { depletable_ = get_node_value_bool(node, "depletable"); @@ -800,19 +799,11 @@ void Material::calculate_neutron_xs(Particle& p) const // Initialize position in i_sab_nuclides int j = 0; -#ifdef NCRYSTAL - double ncrystal_xs = -1; - + // Calculate NCrystal cross section + double ncrystal_xs = -1.0; if (ncrystal_mat_ && p.E() < settings::ncrystal_max_energy) { - // Calculate scattering XS per atom with NCrystal, only once per material - NCrystal::CachePtr dummy_cache; - auto nc_energy = NCrystal::NeutronEnergy {p.E()}; - ncrystal_xs = - ncrystal_mat_ - ->crossSection(dummy_cache, nc_energy, {p.u().x, p.u().y, p.u().z}) - .get(); + ncrystal_xs = ncrystal_mat_.xs(p); } -#endif // Add contribution from each nuclide in material for (int i = 0; i < nuclide_.size(); ++i) { @@ -852,26 +843,16 @@ void Material::calculate_neutron_xs(Particle& p) const int i_nuclide = nuclide_[i]; // Calculate microscopic cross section for this nuclide -#ifdef NCRYSTAL auto& micro {p.neutron_xs(i_nuclide)}; -#else - const auto& micro {p.neutron_xs(i_nuclide)}; -#endif if (p.E() != micro.last_E || p.sqrtkT() != micro.last_sqrtkT || i_sab != micro.index_sab || sab_frac != micro.sab_frac) { data::nuclides[i_nuclide]->calculate_xs(i_sab, i_grid, sab_frac, p); -#ifdef NCRYSTAL + + // If NCrystal is being used, update micro cross section cache if (ncrystal_xs >= 0.0) { - if (micro.thermal > 0 || micro.thermal_elastic > 0) { - fatal_error("S(a,b) treatment and NCrystal are not compatible."); - } data::nuclides[i_nuclide]->calculate_elastic_xs(p); - // remove free atom cross section - // and replace it by scattering cross section per atom from NCrystal - micro.total = micro.total - micro.elastic + ncrystal_xs; - micro.elastic = ncrystal_xs; + ncrystal_update_micro(ncrystal_xs, micro); } -#endif } // ====================================================================== diff --git a/src/ncrystal_interface.cpp b/src/ncrystal_interface.cpp new file mode 100644 index 000000000..b39f62d90 --- /dev/null +++ b/src/ncrystal_interface.cpp @@ -0,0 +1,108 @@ +#include "openmc/ncrystal_interface.h" + +#include "openmc/error.h" +#include "openmc/material.h" +#include "openmc/random_lcg.h" + +namespace openmc { + +//============================================================================== +// Constants +//============================================================================== + +#ifdef NCRYSTAL +const bool NCRYSTAL_ENABLED = true; +#else +const bool NCRYSTAL_ENABLED = false; +#endif + +//============================================================================== +// NCrystal wrapper class for the OpenMC random number generator +//============================================================================== + +#ifdef NCRYSTAL +class NCrystalRNGWrapper : public NCrystal::RNGStream { +public: + constexpr NCrystalRNGWrapper(uint64_t* seed) noexcept : openmc_seed_(seed) {} + +protected: + double actualGenerate() override + { + return std::max( + std::numeric_limits::min(), prn(openmc_seed_)); + } + +private: + uint64_t* openmc_seed_; +}; +#endif + +//============================================================================== +// NCrystal implementation +//============================================================================== + +NCrystalMat::NCrystalMat(const std::string& cfg) +{ +#ifdef NCRYSTAL + cfg_ = cfg; + ptr_ = NCrystal::FactImpl::createScatter(cfg); +#else + fatal_error("Your build of OpenMC does not support NCrystal materials."); +#endif +} + +#ifdef NCRYSTAL +std::string NCrystalMat::cfg() const +{ + return cfg_; +} + +double NCrystalMat::xs(const Particle& p) const +{ + // Calculate scattering XS per atom with NCrystal, only once per material + NCrystal::CachePtr dummy_cache; + auto nc_energy = NCrystal::NeutronEnergy {p.E()}; + return ptr_->crossSection(dummy_cache, nc_energy, {p.u().x, p.u().y, p.u().z}) + .get(); +} + +void NCrystalMat::scatter(Particle& p) const +{ + NCrystalRNGWrapper rng(p.current_seed()); // Initialize RNG + // create a cache pointer for multi thread physics + NCrystal::CachePtr dummy_cache; + auto nc_energy = NCrystal::NeutronEnergy {p.E()}; + auto outcome = ptr_->sampleScatter( + dummy_cache, rng, nc_energy, {p.u().x, p.u().y, p.u().z}); + + // Modify attributes of particle + p.E() = outcome.ekin.get(); + Direction u_old {p.u()}; + p.u() = + Direction(outcome.direction[0], outcome.direction[1], outcome.direction[2]); + p.mu() = u_old.dot(p.u()); + p.event_mt() = ELASTIC; +} + +NCrystalMat::operator bool() const +{ + return ptr_.get(); +} +#endif + +//============================================================================== +// Functions +//============================================================================== + +void ncrystal_update_micro(double xs, NuclideMicroXS& micro) +{ + if (micro.thermal > 0 || micro.thermal_elastic > 0) { + fatal_error("S(a,b) treatment and NCrystal are not compatible."); + } + // remove free atom cross section + // and replace it by scattering cross section per atom from NCrystal + micro.total = micro.total - micro.elastic + xs; + micro.elastic = xs; +} + +} // namespace openmc diff --git a/src/physics.cpp b/src/physics.cpp index c1ef282f7..46bf37aa9 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -10,6 +10,7 @@ #include "openmc/material.h" #include "openmc/math_functions.h" #include "openmc/message_passing.h" +#include "openmc/ncrystal_interface.h" #include "openmc/nuclide.h" #include "openmc/photon.h" #include "openmc/physics_common.h" @@ -138,32 +139,15 @@ void sample_neutron_reaction(Particle& p) if (!p.alive()) return; - // Sample a scattering reaction and determine the secondary energy of the - // exiting neutron - -#ifdef NCRYSTAL - if (model::materials[p.material()]->ncrystal_mat() && - p.E() < settings::ncrystal_max_energy) { - NCrystalRNGWrapper rng(p.current_seed()); // Initialize RNG - // create a cache pointer for multi thread physics - NCrystal::CachePtr dummy_cache; - auto nc_energy = NCrystal::NeutronEnergy {p.E()}; - auto outcome = - model::materials[p.material()]->ncrystal_mat()->sampleScatter( - dummy_cache, rng, nc_energy, {p.u().x, p.u().y, p.u().z}); - p.E_last() = p.E(); - p.E() = outcome.ekin.get(); - Direction u_old {p.u()}; - p.u() = Direction( - outcome.direction[0], outcome.direction[1], outcome.direction[2]); - p.mu() = u_old.dot(p.u()); - p.event_mt() = ELASTIC; + // Sample a scattering reaction and determine the secondary energy of the + // exiting neutron + const auto& ncrystal_mat = model::materials[p.material()]->ncrystal_mat(); + if (ncrystal_mat && p.E() < settings::ncrystal_max_energy) { + ncrystal_mat.scatter(p); } else { scatter(p, i_nuclide); } -#else - scatter(p, i_nuclide); -#endif + // Advance URR seed stream 'N' times after energy changes if (p.E() != p.E_last()) { p.stream() = STREAM_URR_PTABLE; diff --git a/src/settings.cpp b/src/settings.cpp index 6f6e4e090..9174d4114 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -37,13 +37,6 @@ namespace openmc { // Global variables //============================================================================== -#ifdef NCRYSTAL -const bool NCRYSTAL_ENABLED = true; -#else -const bool NCRYSTAL_ENABLED = false; -#endif - - namespace settings { // Default values for boolean flags @@ -106,6 +99,7 @@ int n_batches; int n_max_batches; int max_splits {1000}; int max_tracks {1000}; +double ncrystal_max_energy {5.0}; ResScatMethod res_scat_method {ResScatMethod::rvs}; double res_scat_energy_min {0.01}; double res_scat_energy_max {1000.0}; @@ -128,10 +122,6 @@ int verbosity {7}; double weight_cutoff {0.25}; double weight_survive {1.0}; -#ifdef NCRYSTAL -double ncrystal_max_energy {5.0}; -#endif - } // namespace settings //============================================================================== From 4eda693133a3a0f6c55eea084ca7ddeb3ab0769d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 10 Jan 2023 10:39:22 +0700 Subject: [PATCH 1471/2654] Style and spacing changes --- docs/source/methods/cross_sections.rst | 27 ++++++++++++++----------- docs/source/usersguide/install.rst | 11 +++++----- docs/source/usersguide/materials.rst | 20 +++++++++--------- include/openmc/physics.h | 5 +++-- tests/regression_tests/ncrystal/test.py | 16 +++++++++------ 5 files changed, 45 insertions(+), 34 deletions(-) diff --git a/docs/source/methods/cross_sections.rst b/docs/source/methods/cross_sections.rst index 0b87913e5..2cafa8691 100644 --- a/docs/source/methods/cross_sections.rst +++ b/docs/source/methods/cross_sections.rst @@ -182,19 +182,22 @@ been selected. There are three methods available: NCrystal materials ------------------ -As an alternative of the standard thermal scattering treatment using :math:`S(\alpha,\beta)` -tables, OpenMC allows to create materials using NCrystal_. In addition to the regular thermal elastic, -and thermal inelastic processes, NCrystal allows the generation of models for materials that -cannot currently included in ACE files such as oriented single crystals (see the `NCrystal paper`_), -and further extend the physics `using plugins`_. Thermal scattering kernels are generated on -the fly from dynamic and structural data, or loaded from :math:`S(\alpha,\beta)` tables converted -from ENDF6 evaluations. These kernels are sampled in a direct way using a fast `rejection algorithm`_ -that does not require previous processing. A `large library`_ of materials is already included in -the NCrystal distribution, and new materials can be easily defined from scratch in the `NCMAT format`_ -or `combining existing files`_. +As an alternative of the standard thermal scattering treatment using +:math:`S(\alpha,\beta)` tables, OpenMC allows to create materials using +NCrystal_. In addition to the regular thermal elastic, and thermal inelastic +processes, NCrystal allows the generation of models for materials that cannot +currently included in ACE files such as oriented single crystals (see the +`NCrystal paper`_), and further extend the physics `using plugins`_. Thermal +scattering kernels are generated on the fly from dynamic and structural data, or +loaded from :math:`S(\alpha,\beta)` tables converted from ENDF6 evaluations. +These kernels are sampled in a direct way using a fast `rejection algorithm`_ +that does not require previous processing. A `large library`_ of materials is +already included in the NCrystal distribution, and new materials can be easily +defined from scratch in the `NCMAT format`_ or `combining existing files`_. -The compositions of the materials defined in NCrystal are passed on to OpenMC all other reactions -except for thermal neutron scattering are handled by continuous energy ACE libraries. +The compositions of the materials defined in NCrystal are passed on to OpenMC +all other reactions except for thermal neutron scattering are handled by +continuous energy ACE libraries. ---------------- Multi-Group Data diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 9e5ba1ffd..537dda824 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -274,9 +274,10 @@ Prerequisites * NCrystal_ library for defining materials with enhanced thermal neutron transport Adding this option allows the creation of materials from NCrystal, which - replaces the scattering kernel treatment of ACE files with a modular, on-the-fly approach. - To use it `install `_ and - `initialize `_ + replaces the scattering kernel treatment of ACE files with a modular, + on-the-fly approach. To use it `install + `_ and `initialize + `_ NCrystal and turn on the option in the CMake configuration step: cmake -DOPENMC_USE_NCRYSTAL=on .. @@ -374,8 +375,8 @@ OPENMC_USE_DAGMC (Default: off) OPENMC_USE_NCRYSTAL - Turns on support for NCrystal materials. NCrystal must be - `installed `_ and + Turns on support for NCrystal materials. NCrystal must be + `installed `_ and `initialized `_. (Default: off) diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index fbf9effd8..83af55805 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -105,12 +105,14 @@ you would need to add hydrogen and oxygen to a material and then assign the Adding NCrystal materials ------------------------- -Additional support for thermal scattering can be added by using NCrystal_. -The :meth:`Material.from_ncrystal` class method generates a :class:`openmc.Material` object from -an `NCrystal configuration string `_. -Temperature, material composition, and density are passed from the configuration string -and the `NCMAT file `_ -that define the material, e.g.:: +Additional support for thermal scattering can be added by using NCrystal_. The +:meth:`Material.from_ncrystal` class method generates a :class:`openmc.Material` +object from an `NCrystal configuration string +`_. +Temperature, material composition, and density are passed from the configuration +string and the `NCMAT file +`_ that define the +material, e.g.:: mat = openmc.Material.from_ncrystal('Al_sg225.ncmat;temp=300K') @@ -125,12 +127,12 @@ defines a material containing polycrystalline alumnium, defines an oriented germanium single crystal with 40 arcsec mosaicity. NCrystal only handles low energy neutron interactions. Other interactions are -provided by standard ACE files. NCrystal_ comes with a `predefined library +provided by standard ACE files. NCrystal_ comes with a `predefined library `_ but more materials can be added by creating NCMAT files or on-the-fly in the configuration string. -.. warning:: Currently, NCrystal_ materials cannot be modified after they are created. - Density, temperature and composition should be defined in the +.. warning:: Currently, NCrystal_ materials cannot be modified after they are created. + Density, temperature and composition should be defined in the configuration string or the NCMAT file. .. _NCrystal: https://github.com/mctools/ncrystal diff --git a/include/openmc/physics.h b/include/openmc/physics.h index 382f0f0dd..6e7327d38 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -96,8 +96,9 @@ void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p); void sample_secondary_photons(Particle& p, int i_nuclide); -// !Split or Roulette particles based their weight and the lower weight window -// bound. +//! Split or Roulette particles based their weight and the lower weight window +//! bound. +// //! \param[in] p, particle to be split or rouletted with the weight window. void split_particle(Particle& p); diff --git a/tests/regression_tests/ncrystal/test.py b/tests/regression_tests/ncrystal/test.py index 2a789dac7..cb6421b03 100644 --- a/tests/regression_tests/ncrystal/test.py +++ b/tests/regression_tests/ncrystal/test.py @@ -1,3 +1,5 @@ +from math import pi + import numpy as np import openmc import openmc.lib @@ -9,6 +11,7 @@ pytestmark = pytest.mark.skipif( not openmc.lib._ncrystal_enabled(), reason="NCrystal materials are not enabled.") + def pencil_beam_model(cfg, E0, N): """Return an openmc.Model() object for a monoenergetic pencil beam hitting a 1 mm sphere filled with the material defined by @@ -24,7 +27,7 @@ def pencil_beam_model(cfg, E0, N): sample_sphere = openmc.Sphere(r=0.1) outer_sphere = openmc.Sphere(r=100, boundary_type="vacuum") cell1 = openmc.Cell(region=-sample_sphere, fill=m1) - cell2_region= +sample_sphere & -outer_sphere + cell2_region = +sample_sphere & -outer_sphere cell2 = openmc.Cell(region=cell2_region, fill=None) geometry = openmc.Geometry([cell1, cell2]) @@ -48,7 +51,7 @@ def pencil_beam_model(cfg, E0, N): tally1 = openmc.Tally(name="angular distribution") tally1.scores = ["current"] filter1 = openmc.SurfaceFilter(sample_sphere) - filter2 = openmc.PolarFilter(np.linspace(0, np.pi, 180+1)) + filter2 = openmc.PolarFilter(np.linspace(0, pi, 180+1)) filter3 = openmc.CellFromFilter(cell1) tally1.filters = [filter1, filter2, filter3] tallies = openmc.Tallies([tally1]) @@ -66,11 +69,12 @@ class NCrystalTest(PyAPITestHarness): df = tal.get_pandas_dataframe() return df.to_string() + def test_ncrystal(): - NParticles = 100000 - T = 293.6 # K - E0 = 0.012 # eV + n_particles = 100000 + T = 293.6 # K + E0 = 0.012 # eV cfg = 'Al_sg225.ncmat' - test = pencil_beam_model(cfg, E0, NParticles) + test = pencil_beam_model(cfg, E0, n_particles) harness = NCrystalTest('statepoint.10.h5', model=test) harness.main() From c4227f7dc1b30879dd7492730e8dbb02b14006d5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 10 Jan 2023 10:39:45 +0700 Subject: [PATCH 1472/2654] Change Material.from_ncrystal to accept kwargs --- openmc/material.py | 51 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 68ec199c3..7844ec131 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -99,6 +99,10 @@ class Material(IDManagerMixin): [decay/sec]. .. versionadded:: 0.13.2 + ncrystal_cfg : str + NCrystal configuration string + + .. versionadded:: 0.13.3 """ @@ -141,7 +145,8 @@ class Material(IDManagerMixin): string += '{: <16}\n'.format('\tS(a,b) Tables') - string += '{: <16}=\t{}\n'.format('\tNCrystal conf', self._ncrystal_cfg) + if self._ncrystal_cfg: + string += '{: <16}=\t{}\n'.format('\tNCrystal conf', self._ncrystal_cfg) for sab in self._sab: string += '{: <16}=\t{}\n'.format('\tS(a,b)', sab) @@ -222,6 +227,10 @@ class Material(IDManagerMixin): def volume(self): return self._volume + @property + def ncrystal_cfg(self): + return self._ncrystal_cfg + @name.setter def name(self, name: Optional[str]): if name is not None: @@ -335,9 +344,9 @@ class Material(IDManagerMixin): return material @classmethod - def from_ncrystal(cls, cfg, material_id=None, name=''): + def from_ncrystal(cls, cfg, **kwargs): """Create material from NCrystal configuration string. - + Density, temperature, and material composition, and (ultimately) thermal neutron scattering will be automatically be provided by NCrystal based on this string. The name and material_id parameters are simply passed on @@ -347,12 +356,8 @@ class Material(IDManagerMixin): ---------- cfg : str NCrystal configuration string - material_id : int, optional - Unique identifier for the material. If not specified, an identifier will - automatically be assigned. - name : str, optional - Name of the material. If not specified, the name will be the empty - string. + **kwargs + Keyword arguments passed to :class:`openmc.Material` Returns ------- @@ -371,26 +376,20 @@ class Material(IDManagerMixin): #only get invoked in the unlikely case where a material is specified #by referring both to natural elements and specific isotopes of the #same element. - elem_name = openmc.data.ATOMIC_SYMBOL.get(Z) - if not elem_name: - raise ValueError( f'Element with Z={Z} is not known' ) + elem_name = openmc.data.ATOMIC_SYMBOL[Z] return [ (int(iso_name[len(elem_name):]), abund) for iso_name, abund in openmc.data.isotopes(elem_name) ] - flat_compos = nc_mat.getFlattenedComposition(preferNaturalElements = True, - naturalAbundProvider=openmc_natabund) + flat_compos = nc_mat.getFlattenedComposition( + preferNaturalElements=True, naturalAbundProvider=openmc_natabund) # Create the Material - material = cls(material_id=material_id, - name=name, - temperature=nc_mat.getTemperature()) + material = cls(temperature=nc_mat.getTemperature(), **kwargs) for Z, A_vals in flat_compos: - elemname = openmc.data.ATOMIC_SYMBOL.get(Z) - if not elemname: - raise ValueError(f'Element with Z={Z} is not known') + elemname = openmc.data.ATOMIC_SYMBOL[Z] for A, frac in A_vals: if A: material.add_nuclide(f'{elemname}{A}', frac) @@ -1067,7 +1066,7 @@ class Material(IDManagerMixin): activity[nuclide] = inv_seconds * 1e24 * atoms_per_bcm * multiplier return activity if by_nuclide else sum(activity.values()) - + def get_decay_heat(self, units: str = 'W', by_nuclide: bool = False): """Returns the decay heat of the material or for each nuclide in the material in units of [W], [W/g] or [W/cm3]. @@ -1101,16 +1100,16 @@ class Material(IDManagerMixin): multiplier = 1 elif units == 'W/g': multiplier = 1.0 / self.get_mass_density() - - decayheat = {} + + decayheat = {} for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): decay_erg = openmc.data.decay_energy(nuclide) inv_seconds = openmc.data.decay_constant(nuclide) decay_erg *= openmc.data.JOULE_PER_EV decayheat[nuclide] = inv_seconds * decay_erg * 1e24 * atoms_per_bcm * multiplier - return decayheat if by_nuclide else sum(decayheat.values()) - + return decayheat if by_nuclide else sum(decayheat.values()) + def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material @@ -1651,4 +1650,4 @@ class Materials(cv.CheckedList): tree = ET.parse(path) root = tree.getroot() - return cls.from_xml_element(root) \ No newline at end of file + return cls.from_xml_element(root) From e83ced88dc58d0a9fcf83f04390a5284b30d06b9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 11 Jan 2023 01:17:53 +0700 Subject: [PATCH 1473/2654] Change ncrystal_max_energy to be a global constant --- include/openmc/ncrystal_interface.h | 3 +++ include/openmc/settings.h | 2 -- src/material.cpp | 2 +- src/physics.cpp | 2 +- src/settings.cpp | 1 - 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/openmc/ncrystal_interface.h b/include/openmc/ncrystal_interface.h index 36038d50c..5a3882df9 100644 --- a/include/openmc/ncrystal_interface.h +++ b/include/openmc/ncrystal_interface.h @@ -20,6 +20,9 @@ namespace openmc { extern "C" const bool NCRYSTAL_ENABLED; +//! Energy in [eV] to switch between NCrystal and ENDF +constexpr double NCRYSTAL_MAX_ENERGY {5.0}; + //============================================================================== // Wrapper class an NCrystal material //============================================================================== diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 9cd430deb..90f1e8c29 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -91,8 +91,6 @@ extern int n_log_bins; //!< number of bins for logarithmic energy grid extern int n_batches; //!< number of (inactive+active) batches extern int n_max_batches; //!< Maximum number of batches extern int max_tracks; //!< Maximum number of particle tracks written to file -extern double - ncrystal_max_energy; //!< Energy in eV to switch between NCrystal and ENDF extern ResScatMethod res_scat_method; //!< resonance upscattering method extern double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering extern double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering diff --git a/src/material.cpp b/src/material.cpp index 2d55d6a04..74a8d7e35 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -801,7 +801,7 @@ void Material::calculate_neutron_xs(Particle& p) const // Calculate NCrystal cross section double ncrystal_xs = -1.0; - if (ncrystal_mat_ && p.E() < settings::ncrystal_max_energy) { + if (ncrystal_mat_ && p.E() < NCRYSTAL_MAX_ENERGY) { ncrystal_xs = ncrystal_mat_.xs(p); } diff --git a/src/physics.cpp b/src/physics.cpp index 46bf37aa9..7cb8040f6 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -142,7 +142,7 @@ void sample_neutron_reaction(Particle& p) // Sample a scattering reaction and determine the secondary energy of the // exiting neutron const auto& ncrystal_mat = model::materials[p.material()]->ncrystal_mat(); - if (ncrystal_mat && p.E() < settings::ncrystal_max_energy) { + if (ncrystal_mat && p.E() < NCRYSTAL_MAX_ENERGY) { ncrystal_mat.scatter(p); } else { scatter(p, i_nuclide); diff --git a/src/settings.cpp b/src/settings.cpp index 9174d4114..2fda352ce 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -99,7 +99,6 @@ int n_batches; int n_max_batches; int max_splits {1000}; int max_tracks {1000}; -double ncrystal_max_energy {5.0}; ResScatMethod res_scat_method {ResScatMethod::rvs}; double res_scat_energy_min {0.01}; double res_scat_energy_max {1000.0}; From a0afa5de441bbd584721bf7f6c029e966675291f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 10 Jan 2023 19:04:12 +0000 Subject: [PATCH 1474/2654] added get_surfaces_by_name method --- openmc/geometry.py | 21 +++++++++++++++++++++ tests/unit_tests/test_geometry.py | 16 ++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index a43899daa..f9aecca9c 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -525,6 +525,27 @@ class Geometry: """ return self._get_domains_by_name(name, case_sensitive, matching, 'cell') + def get_surfaces_by_name(self, name, case_sensitive=False, matching=False): + """Return a list of surfaces with matching names. + + Parameters + ---------- + name : str + The name to search match + case_sensitive : bool + Whether to distinguish upper and lower case letters in each + surface's name (default is False) + matching : bool + Whether the names must match completely (default is False) + + Returns + ------- + list of openmc.Surface + Surfaces matching the queried name + + """ + return self._get_domains_by_name(name, case_sensitive, matching, 'surface') + def get_cells_by_fill_name(self, name, case_sensitive=False, matching=False): """Return a list of cells with fills with matching names. diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py index 9db112fd2..f8c523071 100644 --- a/tests/unit_tests/test_geometry.py +++ b/tests/unit_tests/test_geometry.py @@ -159,12 +159,13 @@ def test_get_by_name(): m2 = openmc.Material(name='Zirconium') m2.add_element('Zr', 1.0) - c1 = openmc.Cell(fill=m1, name='cell1') + s1 = openmc.Sphere(name='surface1') + c1 = openmc.Cell(fill=m1, region=-s1, name='cell1') u1 = openmc.Universe(name='Zircaloy universe', cells=[c1]) - cyl = openmc.ZCylinder() - c2 = openmc.Cell(fill=u1, region=-cyl, name='cell2') - c3 = openmc.Cell(fill=m2, region=+cyl, name='Cell3') + s2 = openmc.ZCylinder(name='surface2') + c2 = openmc.Cell(fill=u1, region=-s2, name='cell2') + c3 = openmc.Cell(fill=m2, region=+s2, name='Cell3') root = openmc.Universe(name='root Universe', cells=[c2, c3]) geom = openmc.Geometry(root) @@ -177,6 +178,13 @@ def test_get_by_name(): mats = geom.get_materials_by_name('zirconium', True, True) assert not mats + surfaces = set(geom.get_surfaces_by_name('surface')) + assert not surfaces ^ {s1, s2} + surfaces = set(geom.get_surfaces_by_name('Surface2', False, True)) + assert not surfaces ^ {s2} + surfaces = geom.get_surfaces_by_name('Surface2', True, True) + assert not surfaces + cells = set(geom.get_cells_by_name('cell')) assert not cells ^ {c1, c2, c3} cells = set(geom.get_cells_by_name('cell', True)) From 2c9df1b77e5828ed410dbd00250856265ec211ca Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 11 Jan 2023 09:32:02 +0000 Subject: [PATCH 1475/2654] Apply typo fixes identified incode review by @paulromano Co-authored-by: Paul Romano --- openmc/geometry.py | 2 +- tests/unit_tests/test_geometry.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index eb7fa8200..a9817fbbb 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -267,7 +267,7 @@ class Geometry: ---------- path : PathLike, optional Path to geometry XML file - materials : openmc.Materials or or PathLike + materials : openmc.Materials or PathLike Materials used to assign to cells. If PathLike, an attempt is made to generate materials from the provided xml file. diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py index 843c01def..0e952ab0f 100644 --- a/tests/unit_tests/test_geometry.py +++ b/tests/unit_tests/test_geometry.py @@ -290,7 +290,6 @@ def test_from_xml(run_in_tmpdir, mixed_lattice_model): geom = openmc.Geometry.from_xml(path='geometry.xml', materials=None) assert 'Unable to set "materials" to "None"' in str(excinfo.value) - # checking that the default args also work geom = openmc.Geometry.from_xml() assert isinstance(geom, openmc.Geometry) From 50892c61b7865a92b27e289be88299ad2667343b Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer Date: Wed, 11 Jan 2023 13:56:54 -0500 Subject: [PATCH 1476/2654] unit test and description --- tests/unit_tests/test_settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 1ea66d1f6..15e86ca61 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -49,6 +49,7 @@ def test_export_to_xml(run_in_tmpdir): domains=[openmc.Cell()], samples=1000, lower_left=(-10., -10., -10.), upper_right = (10., 10., 10.)) s.create_fission_neutrons = True + s.create_delayed_neutrons = False s.log_grid_bins = 2000 s.photon_transport = False s.electron_treatment = 'led' @@ -107,6 +108,7 @@ def test_export_to_xml(run_in_tmpdir): 'energy_min': 1.0, 'energy_max': 1000.0, 'nuclides': ['U235', 'U238', 'Pu239']} assert s.create_fission_neutrons + assert not s.create_delayed_neutrons assert s.log_grid_bins == 2000 assert not s.photon_transport assert s.electron_treatment == 'led' From 9d86274fcc790e7ba05d030234ec099ef8c09d15 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer Date: Wed, 11 Jan 2023 14:17:29 -0500 Subject: [PATCH 1477/2654] merge conflict --- openmc/settings.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmc/settings.py b/openmc/settings.py index 6f3ef5ab4..6271e05dc 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -224,6 +224,10 @@ class Settings: weight_windows : WeightWindows iterable of WeightWindows Weight windows to use for variance reduction + .. versionadded:: 0.13.3 + create_delayed_neutrons : bool + Whether delayed neutrons are created in fission. + .. versionadded:: 0.13 weight_windows_on : bool Whether weight windows are enabled From e266bb15bfcbbdbaa77a0a30c2c9909f60612bb8 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer Date: Wed, 11 Jan 2023 14:50:06 -0500 Subject: [PATCH 1478/2654] old changes for delayed neutron feature --- docs/source/io_formats/settings.rst | 11 +++++++++++ include/openmc/settings.h | 1 + openmc/settings.py | 23 +++++++++++++++++++++++ src/finalize.cpp | 1 + src/nuclide.cpp | 4 ++-- src/settings.cpp | 7 +++++++ 6 files changed, 45 insertions(+), 2 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 71ca61d54..6dff76838 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -32,6 +32,17 @@ standard deviation. *Default*: false +------------------------------------- +```` Element +------------------------------------- + +The ```` element indicates whether delayed neutrons +are created in fission. If this element is set to "true", delayed neutrons +will be created in fission events; otherwise only prompt neutrons will be +created. + + *Default*: true + ------------------------------------- ```` Element ------------------------------------- diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 90f1e8c29..806288efe 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -28,6 +28,7 @@ extern bool check_overlaps; //!< check overlaps in geometry? extern bool confidence_intervals; //!< use confidence intervals for results? extern bool create_fission_neutrons; //!< create fission neutrons (fixed source)? +extern bool create_delayed_neutrons; //!< create delayed fission neutrons? extern "C" bool cmfd_run; //!< is a CMFD run? extern bool delayed_photon_scaling; //!< Scale fission photon yield to include delayed diff --git a/openmc/settings.py b/openmc/settings.py index 6271e05dc..3f5873c0a 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -300,6 +300,7 @@ class Settings: VolumeCalculation, 'volume calculations') self._create_fission_neutrons = None + self._create_delayed_neutrons = None self._delayed_photon_scaling = None self._material_cell_offsets = None self._log_grid_bins = None @@ -463,6 +464,10 @@ class Settings: def create_fission_neutrons(self) -> bool: return self._create_fission_neutrons + @property + def create_delayed_neutrons(self) -> bool: + return self._create_delayed_neutrons + @property def delayed_photon_scaling(self) -> bool: return self._delayed_photon_scaling @@ -870,6 +875,12 @@ class Settings: create_fission_neutrons, bool) self._create_fission_neutrons = create_fission_neutrons + @create_delayed_neutrons.setter + def create_delayed_neutrons(self, create_delayed_neutrons: bool): + cv.check_type('Whether create only prompt neutrons', + create_delayed_neutrons, bool) + self._create_delayed_neutrons = create_delayed_neutrons + @delayed_photon_scaling.setter def delayed_photon_scaling(self, value: bool): cv.check_type('delayed photon scaling', value, bool) @@ -1211,6 +1222,11 @@ class Settings: elem = ET.SubElement(root, "create_fission_neutrons") elem.text = str(self._create_fission_neutrons).lower() + def _create_create_delayed_neutrons_subelement(self, root): + if self._create_delayed_neutrons is not None: + elem = ET.SubElement(root, "create_delayed_neutrons") + elem.text = str(self._create_delayed_neutrons).lower() + def _create_delayed_photon_scaling_subelement(self, root): if self._delayed_photon_scaling is not None: elem = ET.SubElement(root, "delayed_photon_scaling") @@ -1536,6 +1552,11 @@ class Settings: if text is not None: self.create_fission_neutrons = text in ('true', '1') + def _create_delayed_neutrons_from_xml_element(self, root): + text = get_text(root, 'create_delayed_neutrons') + if text is not None: + self.create_delayed_neutrons = text in ('true', '1') + def _delayed_photon_scaling_from_xml_element(self, root): text = get_text(root, 'delayed_photon_scaling') if text is not None: @@ -1634,6 +1655,7 @@ class Settings: self._create_resonance_scattering_subelement(element) self._create_volume_calcs_subelement(element) self._create_create_fission_neutrons_subelement(element) + self._create_create_delayed_neutrons_subelement(root_element) self._create_delayed_photon_scaling_subelement(element) self._create_event_based_subelement(element) self._create_max_particles_in_flight_subelement(element) @@ -1726,6 +1748,7 @@ class Settings: settings._ufs_mesh_from_xml_element(elem, meshes) settings._resonance_scattering_from_xml_element(elem) settings._create_fission_neutrons_from_xml_element(elem) + settings._create_delayed_neutrons_from_xml_element(root) settings._delayed_photon_scaling_from_xml_element(elem) settings._event_based_from_xml_element(elem) settings._max_particles_in_flight_from_xml_element(elem) diff --git a/src/finalize.cpp b/src/finalize.cpp index 0c2c62310..59294b28c 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -74,6 +74,7 @@ int openmc_finalize() settings::check_overlaps = false; settings::confidence_intervals = false; settings::create_fission_neutrons = true; + settings::create_delayed_neutrons = true; settings::electron_treatment = ElectronTreatment::LED; settings::delayed_photon_scaling = true; settings::energy_cutoff = {0.0, 1000.0, 0.0, 0.0}; diff --git a/src/nuclide.cpp b/src/nuclide.cpp index 134e2d6b9..99ed44b11 100644 --- a/src/nuclide.cpp +++ b/src/nuclide.cpp @@ -519,7 +519,7 @@ double Nuclide::nu(double E, EmissionMode mode, int group) const case EmissionMode::prompt: return (*fission_rx_[0]->products_[0].yield_)(E); case EmissionMode::delayed: - if (n_precursor_ > 0) { + if (n_precursor_ > 0 && settings::create_delayed_neutrons) { auto rx = fission_rx_[0]; if (group >= 1 && group < rx->products_.size()) { // If delayed group specified, determine yield immediately @@ -544,7 +544,7 @@ double Nuclide::nu(double E, EmissionMode mode, int group) const return 0.0; } case EmissionMode::total: - if (total_nu_) { + if (total_nu_ && settings::create_delayed_neutrons) { return (*total_nu_)(E); } else { return (*fission_rx_[0]->products_[0].yield_)(E); diff --git a/src/settings.cpp b/src/settings.cpp index 6386ce52b..1b822f3b9 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -44,6 +44,7 @@ bool assume_separate {false}; bool check_overlaps {false}; bool cmfd_run {false}; bool confidence_intervals {false}; +bool create_delayed_neutrons {true}; bool create_fission_neutrons {true}; bool delayed_photon_scaling {true}; bool entropy_on {false}; @@ -872,6 +873,12 @@ void read_settings_xml(pugi::xml_node root) } } + // Check whether create delayed neutrons in fission + if (check_for_node(root, "create_delayed_neutrons")) { + create_delayed_neutrons = + get_node_value_bool(root, "create_delayed_neutrons"); + } + // Check whether create fission sites if (run_mode == RunMode::FIXED_SOURCE) { if (check_for_node(root, "create_fission_neutrons")) { From 8b1ecaad09546901231dc0890e55fc57622b77bf Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer Date: Wed, 11 Jan 2023 15:38:16 -0500 Subject: [PATCH 1479/2654] deleted white spaces --- openmc/settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 3f5873c0a..2210b23a2 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -465,7 +465,7 @@ class Settings: return self._create_fission_neutrons @property - def create_delayed_neutrons(self) -> bool: + def create_delayed_neutrons(self) -> bool: return self._create_delayed_neutrons @property @@ -875,7 +875,7 @@ class Settings: create_fission_neutrons, bool) self._create_fission_neutrons = create_fission_neutrons - @create_delayed_neutrons.setter + @create_delayed_neutrons.setter def create_delayed_neutrons(self, create_delayed_neutrons: bool): cv.check_type('Whether create only prompt neutrons', create_delayed_neutrons, bool) @@ -1222,7 +1222,7 @@ class Settings: elem = ET.SubElement(root, "create_fission_neutrons") elem.text = str(self._create_fission_neutrons).lower() - def _create_create_delayed_neutrons_subelement(self, root): + def _create_create_delayed_neutrons_subelement(self, root): if self._create_delayed_neutrons is not None: elem = ET.SubElement(root, "create_delayed_neutrons") elem.text = str(self._create_delayed_neutrons).lower() @@ -1552,7 +1552,7 @@ class Settings: if text is not None: self.create_fission_neutrons = text in ('true', '1') - def _create_delayed_neutrons_from_xml_element(self, root): + def _create_delayed_neutrons_from_xml_element(self, root): text = get_text(root, 'create_delayed_neutrons') if text is not None: self.create_delayed_neutrons = text in ('true', '1') From 3ba117fcd95afa1f8aba745dd368db705a3a5102 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer Date: Wed, 11 Jan 2023 15:41:31 -0500 Subject: [PATCH 1480/2654] indentation level change --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 2210b23a2..79d28c44b 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1222,7 +1222,7 @@ class Settings: elem = ET.SubElement(root, "create_fission_neutrons") elem.text = str(self._create_fission_neutrons).lower() - def _create_create_delayed_neutrons_subelement(self, root): + def _create_create_delayed_neutrons_subelement(self, root): if self._create_delayed_neutrons is not None: elem = ET.SubElement(root, "create_delayed_neutrons") elem.text = str(self._create_delayed_neutrons).lower() From afa490f6a6c98e41062c180eb74fae20ddffdad4 Mon Sep 17 00:00:00 2001 From: Josh May Date: Wed, 11 Jan 2023 13:27:06 -0800 Subject: [PATCH 1481/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- openmc/cell.py | 3 +-- tests/unit_tests/test_cell.py | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index cea362ed8..a8e1178f4 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -518,8 +518,7 @@ class Cell(IDManagerMixin): paths = self._paths self._paths = None - clone = openmc.Cell() - clone.name = self.name + clone = openmc.Cell(name=self.name) clone.volume = self.volume if self.temperature is not None: clone.temperature = self.temperature diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 4185e9a44..cef77f160 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -76,8 +76,8 @@ def test_clone(): # Add optional properties to the original cell to ensure they're cloned successfully c.temperature = 650. - c.translation = [1,2,3] - c.rotation = [4,5,6] + c.translation = (1., 2., 3.) + c.rotation = (4., 5., 6.) c.volume = 100 c5 = c.clone(clone_materials=False, clone_regions=False) @@ -92,8 +92,8 @@ def test_clone(): # Mutate the original to ensure the changes are not seen in the clones c.fill = openmc.Material() c.region = +openmc.ZCylinder() - c.translation = [-1,-2,-3] - c.rotation = [-4,-5,-6] + c.translation = (-1., -2., -3.) + c.rotation = (-4., -5., -6.) c.temperature = 1 c.volume = 1 assert c5.fill != c.fill From f7c1a57b15ba1fe5bb697db077bf4cd29d595f79 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer Date: Wed, 11 Jan 2023 16:55:27 -0500 Subject: [PATCH 1482/2654] settings change element --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 79d28c44b..911131387 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1655,7 +1655,7 @@ class Settings: self._create_resonance_scattering_subelement(element) self._create_volume_calcs_subelement(element) self._create_create_fission_neutrons_subelement(element) - self._create_create_delayed_neutrons_subelement(root_element) + self._create_create_delayed_neutrons_subelement(element) self._create_delayed_photon_scaling_subelement(element) self._create_event_based_subelement(element) self._create_max_particles_in_flight_subelement(element) From 36249d3742dabfe95ee50e2aac822caf72f1e1a9 Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Thu, 12 Jan 2023 06:25:52 -0500 Subject: [PATCH 1483/2654] Update openmc/settings.py yes Co-authored-by: Paul Romano --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 911131387..9330d99b6 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1748,7 +1748,7 @@ class Settings: settings._ufs_mesh_from_xml_element(elem, meshes) settings._resonance_scattering_from_xml_element(elem) settings._create_fission_neutrons_from_xml_element(elem) - settings._create_delayed_neutrons_from_xml_element(root) + settings._create_delayed_neutrons_from_xml_element(elem) settings._delayed_photon_scaling_from_xml_element(elem) settings._event_based_from_xml_element(elem) settings._max_particles_in_flight_from_xml_element(elem) From a66d4da53f1ce87f6a14902636ab12eb765c895b Mon Sep 17 00:00:00 2001 From: Christopher Fichtlscherer <29277544+cfichtlscherer@users.noreply.github.com> Date: Thu, 12 Jan 2023 06:26:07 -0500 Subject: [PATCH 1484/2654] Update openmc/settings.py version number Co-authored-by: Paul Romano --- openmc/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 9330d99b6..22a83509f 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -224,11 +224,11 @@ class Settings: weight_windows : WeightWindows iterable of WeightWindows Weight windows to use for variance reduction - .. versionadded:: 0.13.3 + .. versionadded:: 0.13 create_delayed_neutrons : bool Whether delayed neutrons are created in fission. - .. versionadded:: 0.13 + .. versionadded:: 0.13.3 weight_windows_on : bool Whether weight windows are enabled From e799346502d7e10500f35cedb4d1a4e4a6a3fc48 Mon Sep 17 00:00:00 2001 From: josh Date: Thu, 12 Jan 2023 21:58:22 +0000 Subject: [PATCH 1485/2654] switch universe deepcopying for a fresh instance on clones --- openmc/universe.py | 11 ++++++++--- tests/unit_tests/test_universe.py | 8 ++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 9c93e6da1..15bea0ba9 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -1,7 +1,6 @@ from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Iterable -from copy import deepcopy from numbers import Integral, Real from pathlib import Path from tempfile import TemporaryDirectory @@ -138,8 +137,14 @@ class UniverseBase(ABC, IDManagerMixin): # If no memoize'd clone exists, instantiate one if self not in memo: - clone = deepcopy(self) - clone.id = None + clone = openmc.Universe(name=self.name) + clone.volume = self.volume + # Try to set DAGMCUniverse-specific attributes on the clone + try: + clone.auto_geom_ids = self.auto_geom_ids + clone.auto_mat_ids = self.auto_mat_ids + except AttributeError: + pass # Clone all cells for the universe clone clone._cells = OrderedDict() diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py index 33c86b150..39d1eec21 100644 --- a/tests/unit_tests/test_universe.py +++ b/tests/unit_tests/test_universe.py @@ -120,6 +120,14 @@ def test_clone(): assert next(iter(u3.cells.values())).region ==\ next(iter(u1.cells.values())).region + dagmc_u = openmc.DAGMCUniverse(filename="") + dagmc_u.auto_geom_ids = True + dagmc_u.auto_mat_ids = True + dagmc_u1 = dagmc_u.clone() + assert dagmc_u1.name == dagmc_u.name + assert dagmc_u1.auto_geom_ids == dagmc_u.auto_geom_ids + assert dagmc_u1.auto_mat_ids == dagmc_u.auto_mat_ids + def test_create_xml(cell_with_lattice): cells = [openmc.Cell() for i in range(5)] From 402b7b2ced81d3f09b2363f4c0a1f086ba314f33 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Jan 2023 12:02:20 +0700 Subject: [PATCH 1486/2654] Happy new year 2023! --- LICENSE | 2 +- docs/source/conf.py | 2 +- docs/source/license.rst | 2 +- man/man1/openmc.1 | 2 +- src/output.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LICENSE b/LICENSE index 7fb6e3f27..81c1f5f7b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2022 Massachusetts Institute of Technology, UChicago Argonne +Copyright (c) 2011-2023 Massachusetts Institute of Technology, UChicago Argonne LLC, and OpenMC contributors Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/docs/source/conf.py b/docs/source/conf.py index ae329dd7e..988e626cf 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -62,7 +62,7 @@ master_doc = 'index' # General information about the project. project = 'OpenMC' -copyright = '2011-2022, Massachusetts Institute of Technology, UChicago Argonne LLC, and OpenMC contributors' +copyright = '2011-2023, Massachusetts Institute of Technology, UChicago Argonne LLC, and OpenMC contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/source/license.rst b/docs/source/license.rst index 9d2638bfb..fb29afbc0 100644 --- a/docs/source/license.rst +++ b/docs/source/license.rst @@ -4,7 +4,7 @@ License Agreement ================= -Copyright © 2011-2022 Massachusetts Institute of Technology, UChicago Argonne +Copyright © 2011-2023 Massachusetts Institute of Technology, UChicago Argonne LLC, and OpenMC contributors Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/man/man1/openmc.1 b/man/man1/openmc.1 index 6310750a2..4aa288a8c 100644 --- a/man/man1/openmc.1 +++ b/man/man1/openmc.1 @@ -57,7 +57,7 @@ Indicates the default path to an HDF5 file that contains multi-group cross section libraries if the user has not specified the tag in .I materials.xml\fP. .SH LICENSE -Copyright \(co 2011-2022 Massachusetts Institute of Technology, UChicago +Copyright \(co 2011-2023 Massachusetts Institute of Technology, UChicago Argonne LLC, and OpenMC contributors. .PP Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/src/output.cpp b/src/output.cpp index 18efed656..ae0907d02 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -74,7 +74,7 @@ void title() // Write version information fmt::print( " | The OpenMC Monte Carlo Code\n" - " Copyright | 2011-2022 MIT, UChicago Argonne LLC, and contributors\n" + " Copyright | 2011-2023 MIT, UChicago Argonne LLC, and contributors\n" " License | https://docs.openmc.org/en/latest/license.html\n" " Version | {}.{}.{}{}\n", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE, VERSION_DEV ? "-dev" : ""); @@ -340,7 +340,7 @@ void print_version() #ifdef GIT_SHA1 fmt::print("Git SHA1: {}\n", GIT_SHA1); #endif - fmt::print("Copyright (c) 2011-2022 MIT, UChicago Argonne LLC, and " + fmt::print("Copyright (c) 2011-2023 MIT, UChicago Argonne LLC, and " "contributors\nMIT/X license at " "\n"); } From 0a8454d7f7ded14cdfc19512ba0366ec00184ea6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Jan 2023 12:08:26 +0700 Subject: [PATCH 1487/2654] Mention MCPL in optional dependencies --- docs/source/usersguide/install.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 537dda824..899e16506 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -271,6 +271,16 @@ Prerequisites cmake -DOPENMC_USE_DAGMC=on -DCMAKE_PREFIX_PATH=/path/to/dagmc/installation .. + * MCPL_ library for reading and writing .mcpl files + + This option allows OpenMC to read and write MCPL (Monte Carlo Particle + Lists) files instead of .h5 files for sources (external source + distribution, k-eigenvalue source distribution, and surface sources). To + turn this option on in the CMake configuration step, add the following + option: + + cmake -DOPENMC_USE_MCPL=on .. + * NCrystal_ library for defining materials with enhanced thermal neutron transport Adding this option allows the creation of materials from NCrystal, which @@ -305,6 +315,7 @@ Prerequisites .. _MOAB: https://bitbucket.org/fathomteam/moab .. _libMesh: https://libmesh.github.io/ .. _libpng: http://www.libpng.org/pub/png/libpng.html +.. _MCPL: https://github.com/mctools/mcpl .. _NCrystal: https://github.com/mctools/ncrystal Obtaining the Source From e873db9a07a79500e6740e3362828c2357fd2731 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Jan 2023 23:13:09 -0600 Subject: [PATCH 1488/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- docs/source/io_formats/settings.rst | 2 +- include/openmc/distribution_spatial.h | 1 - openmc/source.py | 1 - openmc/stats/multivariate.py | 27 +++++++++---------- src/mesh.cpp | 9 ++----- .../unstructured_mesh/source_sampling/test.py | 16 ++++++----- 6 files changed, 25 insertions(+), 31 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index fc98b662e..b97049d38 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -493,7 +493,7 @@ attributes/sub-elements: independent distributions of r-, cos_theta-, and phi-coordinates where cos_theta is the cosine of the angle with respect to the z-axis, phi is the azimuthal angle, and the sphere is centered on the coordinate - (x0,y0,z0). A "mesh" spatial distribution source sites from a mesh element + (x0,y0,z0). A "mesh" spatial distribution samples source sites from a mesh element based on the relative strengths provided in the node. Source locations within an element are sampled isotropically. If no strengths are provided, the space within the mesh is uniformly sampled. diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 0be6329f5..ece706759 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -115,7 +115,6 @@ public: private: Mesh* mesh_ptr_ {nullptr}; int32_t mesh_idx_ {C_NONE}; - std::string sample_scheme_; double total_strength_ {0.0}; std::vector mesh_CDF_; std::vector mesh_strengths_; diff --git a/openmc/source.py b/openmc/source.py index 32f8ea3d6..9293a5953 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -16,7 +16,6 @@ from openmc.checkvalue import PathLike from openmc.stats.multivariate import UnitSphere, Spatial from openmc.stats.univariate import Univariate from ._xml import get_text -from .mesh import MeshBase class Source: diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 171ff4b40..db13b9bc9 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -619,21 +619,21 @@ class CylindricalIndependent(Spatial): origin = [float(x) for x in elem.get('origin').split()] return cls(r, phi, z, origin=origin) + class MeshSpatial(Spatial): """Spatial distribution for a mesh. - This distribution specifies a mesh to sample over, chooses whether it will - be adjusted by element volume, and can set the source strengths. + This distribution specifies a mesh to sample over with source strengths + specified for each mesh element. .. versionadded:: 0.13.3 Parameters ---------- mesh : openmc.MeshBase - The mesh instance used for sampling, mesh is written into settings.xml, - mesh.id is written into the source distribution - strengths : Iterable of Real, optional - A list of values which represent the weights of each element. If no + The mesh instance used for sampling + strengths : iterable of float, optional + An iterable of values that represents the weights of each element. If no source strengths are specified, they will be equal for all mesh elements. volume_normalized : bool, optional @@ -643,10 +643,9 @@ class MeshSpatial(Spatial): Attributes ---------- mesh : openmc.MeshBase - The mesh instance used for sampling, mesh is written into settings.xml, - mesh.id is written into the source distribution - strengths : Iterable of Real, optional - A list of values which represent the weights of each element + The mesh instance used for sampling + strengths : numpy.ndarray or None + An array of source strengths for each mesh element volume_normalized : bool Whether or not the strengths will be multiplied by element volumes at runtime. @@ -663,8 +662,8 @@ class MeshSpatial(Spatial): @mesh.setter def mesh(self, mesh): - if mesh != None: - cv.check_type('Unstructured Mesh instance', mesh, MeshBase) + if mesh is not None: + cv.check_type('mesh instance', mesh, MeshBase) self._mesh = mesh @property @@ -684,13 +683,13 @@ class MeshSpatial(Spatial): def strengths(self, given_strengths): if given_strengths is not None: cv.check_type('strengths array passed in', given_strengths, Iterable, Real) - self._strengths = np.array(given_strengths, dtype=float).flatten() + self._strengths = np.asarray(given_strengths, dtype=float).flatten() else: self._strengths = None @property def num_strength_bins(self): - if self.strengths == None: + if self.strengths is None: raise ValueError('Strengths are not set') return self.strengths.size diff --git a/src/mesh.cpp b/src/mesh.cpp index abb6f8b8c..2102f953d 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -195,7 +195,6 @@ UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node) } } -// Sample barycentric coordinates given a seed and the vertex positions and return the sampled position Position UnstructuredMesh::sample_tet(std::array coords, uint64_t* seed) const { // Uniform distribution double s = prn(seed); @@ -2112,9 +2111,7 @@ Position MOABMesh::sample(uint64_t* seed, int32_t bin) const { tet_verts[i] = {p[i][0], p[i][1], p[i][2]}; } // Samples position within tet using Barycentric stuff - Position r = this->sample_tet(tet_verts, seed); - - return r; + return this->sample_tet(tet_verts, seed); } @@ -2580,9 +2577,7 @@ Position LibMesh::sample(uint64_t* seed, int32_t bin) const { tet_verts[i] = {node_ref(0), node_ref(1), node_ref(2)}; } // Samples position within tet using Barycentric coordinates - Position r = this->sample_tet(tet_verts, seed); - - return r; + return this->sample_tet(tet_verts, seed); } Position LibMesh::centroid(int bin) const diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index e34bf3b75..facd0cad5 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -1,15 +1,15 @@ from itertools import product - from pathlib import Path + import pytest import numpy as np - import openmc import openmc.lib from tests import cdtemp from tests.testing_harness import PyAPITestHarness + TETS_PER_VOXEL = 12 # This test uses a geometry file with cells that match a regular mesh. Each cell @@ -60,7 +60,8 @@ def model(): strengths = np.zeros(n_cells*TETS_PER_VOXEL) # set non-zero strengths only for the tets corresponding to the # first two geometric hex cells - strengths[0:TETS_PER_VOXEL] = 10 + strengths[:TETS_PER_VOXEL] = 10 + strengths[TETS_PER_VOXEL:2*TETS_PER_VOXEL] = 2 # create the spatial distribution based on the mesh @@ -74,10 +75,11 @@ def model(): settings=settings) -test_cases = [] -for i, lib, in enumerate(['libmesh', 'moab']): - test_cases.append({'library' : lib, - 'inputs_true' : 'inputs_true{}.dat'.format(i)}) +test_cases = [ + {'library': lib, 'inputs_true': f'inputs_true{i}.dat'} + for i, lib in enumerate(('libmesh', 'moab')) +] + @pytest.mark.parametrize("test_cases", test_cases, ids=lambda p: p['library']) def test_unstructured_mesh_sampling(model, test_cases): From d4cbcd12fc70cb52625e041c409c22e68d009395 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Jan 2023 23:13:35 -0600 Subject: [PATCH 1489/2654] Addressing comments from @paulromano's review --- include/openmc/distribution_spatial.h | 1 - include/openmc/mesh.h | 12 ++++++++-- src/distribution_spatial.cpp | 20 ++++++++++++---- src/mesh.cpp | 34 ++++++++++++++++++++------- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index ece706759..939d055ba 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -113,7 +113,6 @@ public: int32_t n_sources() const { return this->mesh()->n_bins(); } private: - Mesh* mesh_ptr_ {nullptr}; int32_t mesh_idx_ {C_NONE}; double total_strength_ {0.0}; std::vector mesh_CDF_; diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 310320486..73a4f0bb7 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -78,7 +78,8 @@ public: //! Sample a mesh volume using a certain seed // //! \param[in] seed Seed to use for random sampling - //! \param[out] r Position within tet + //! \param[in] bin Bin value of the tet sampled + //! \return sampled position within tet virtual Position sample(uint64_t* seed, int32_t bin) const=0; //! Get the volume of a mesh bin @@ -536,6 +537,8 @@ public: true}; //!< Write tallies onto the unstructured mesh at the end of a run std::string filename_; //!< Path to unstructured mesh file + ElementType element_type(int bin) const; + protected: //! Set the length multiplier to apply to each point in the mesh void set_length_multiplier(const double length_multiplier); @@ -545,7 +548,12 @@ protected: 1.0}; //!< Constant multiplication factor to apply to mesh coordinates bool specified_length_multiplier_ {false}; - //! Sample a tetrahedron for an unstructured mesh + //! Sample barycentric coordinates given a seed and the vertex positions and + //! return the sampled position + // + //! \param[in] coords Coordinates of the tetrahedron + //! \param[in] seed Random number generation seed + //! \return Sampled position within the tetrahedron Position sample_tet(std::array coords, uint64_t* seed) const; private: diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index c1e000fcd..fbe5ce658 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -194,9 +194,19 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) // Get pointer to spatial distribution mesh_idx_ = model::mesh_map.at(mesh_id); - // Check whether mesh pointer points to a mesh - mesh_ptr_ = dynamic_cast(model::meshes[mesh_idx_].get()); - if (!mesh_ptr_) {fatal_error("Mesh passed to spatial distribution is not a mesh object"); } + auto mesh_ptr = + dynamic_cast(model::meshes.at(mesh_idx_).get()); + if (!mesh_ptr) { + fatal_error("Only unstructured mesh is supported for source sampling."); + } + + // ensure that the unstructured mesh contains only linear tets + for (int bin = 0; bin < mesh_ptr->n_bins(); bin++) { + if (mesh_ptr->element_type(bin) != ElementType::LINEAR_TET) { + fatal_error( + "Mesh specified for source must contain only linear tetrahedra."); + } + } int32_t n_bins = this->n_sources(); std::vector strengths(n_bins, 0.0); @@ -222,7 +232,7 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) if (get_node_value_bool(node, "volume_normalized")) { for (int i = 0; i < n_bins; i++) { - mesh_strengths_[i] *= mesh_ptr_->volume(i); + mesh_strengths_[i] *= mesh()->volume(i); } } @@ -244,7 +254,7 @@ Position MeshSpatial::sample(uint64_t* seed) const double eta = prn(seed); // Sample over the CDF defined in initialization above int32_t elem_idx = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); - return mesh_ptr_->sample(seed, elem_idx); + return mesh()->sample(seed, elem_idx); } //============================================================================== diff --git a/src/mesh.cpp b/src/mesh.cpp index 2102f953d..39b5a225e 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -195,14 +195,17 @@ UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node) } } -Position UnstructuredMesh::sample_tet(std::array coords, uint64_t* seed) const { +Position UnstructuredMesh::sample_tet( + std::array coords, uint64_t* seed) const +{ // Uniform distribution double s = prn(seed); double t = prn(seed); double u = prn(seed); - // From PyNE implementation of moab tet sampling - // C. Rocchini and P. Cignoni, “Generating Random Points in a Tetrahedron,” + // From PyNE implementation of moab tet sampling C. Rocchini & P. Cignoni + // (2000) Generating Random Points in a Tetrahedron, Journal of Graphics + // Tools, 5:4, 9-12, DOI: 10.1080/10867651.2000.10487528 if (s + t > 1) { s = 1.0 - s; t = 1.0 - t; @@ -222,7 +225,6 @@ Position UnstructuredMesh::sample_tet(std::array coords, uint64_t* + t*(coords[2]-coords[0]) + u*(coords[3]-coords[0]) + coords[0]; - } const std::string UnstructuredMesh::mesh_type = "unstructured"; @@ -313,6 +315,18 @@ void UnstructuredMesh::set_length_multiplier(double length_multiplier) specified_length_multiplier_ = true; } +ElementType UnstructuredMesh::element_type(int bin) const +{ + auto conn = connectivity(bin); + + if (conn.size() == 4) + return ElementType::LINEAR_TET; + else if (conn.size() == 8) + return ElementType::LINEAR_HEX; + else + return ElementType::UNSUPPORTED; +} + StructuredMesh::MeshIndex StructuredMesh::get_indices( Position r, bool& in_mesh) const { @@ -2095,10 +2109,14 @@ Position MOABMesh::sample(uint64_t* seed, int32_t bin) const { moab::EntityHandle tet_ent = get_ent_handle_from_bin(bin); // Get vertex coordinates for MOAB tet - vector conn1; - moab::ErrorCode rval = mbi_->get_connectivity(&tet_ent, 1, conn1); - if (rval != moab::MB_SUCCESS) { - fatal_error("Failed to get tet connectivity"); + std::array conn1; + int conn1_size; + moab::ErrorCode rval = + mbi_->get_connectivity(&tet_ent, 1, conn1.data(), conn1_size); + if (rval != moab::MB_SUCCESS || conn1_size != 4) { + fatal_error(fmt::format( + "Failed to get tet connectivity or connectivity size () is invalid.", + conn1_size)); } moab::CartVect p[4]; rval = mbi_->get_coords(conn1.data(), conn1.size(), p[0].array()); From 4195d1e8ca464aa5435f9376ac70d1ead190d7eb Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Jan 2023 23:18:25 -0600 Subject: [PATCH 1490/2654] Restoring blank lines in settings.cpp and source.cpp --- src/settings.cpp | 4 ++++ src/source.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/settings.cpp b/src/settings.cpp index c3ecd46b4..310378517 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -371,6 +371,7 @@ void read_settings_xml(pugi::xml_node root) } } } + if (run_mode == RunMode::EIGENVALUE || run_mode == RunMode::FIXED_SOURCE) { // Read run parameters get_run_parameters(node_mode); @@ -434,6 +435,7 @@ void read_settings_xml(pugi::xml_node root) "the OMP_NUM_THREADS environment variable to set the number of " "threads."); } + // ========================================================================== // EXTERNAL SOURCE @@ -462,6 +464,7 @@ void read_settings_xml(pugi::xml_node root) model::external_sources.push_back(make_unique(node)); } } + // Check if the user has specified to read surface source if (check_for_node(root, "surf_source_read")) { surf_source_read = true; @@ -532,6 +535,7 @@ void read_settings_xml(pugi::xml_node root) std::stod(get_node_value(node_cutoff, "energy_positron")); } } + // Particle trace if (check_for_node(root, "trace")) { auto temp = get_node_array(root, "trace"); diff --git a/src/source.cpp b/src/source.cpp index 2fdcc319f..2cb5632b3 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -111,6 +111,7 @@ IndependentSource::IndependentSource(pugi::xml_node node) // If no spatial distribution specified, make it a point source space_ = UPtrSpace {new SpatialPoint()}; } + // Determine external source angular distribution if (check_for_node(node, "angle")) { // Get pointer to angular distribution @@ -130,9 +131,11 @@ IndependentSource::IndependentSource(pugi::xml_node node) fatal_error(fmt::format( "Invalid angular distribution for external source: {}", type)); } + } else { angle_ = UPtrAngle {new Isotropic()}; } + // Determine external source energy distribution if (check_for_node(node, "energy")) { pugi::xml_node node_dist = node.child("energy"); @@ -141,6 +144,7 @@ IndependentSource::IndependentSource(pugi::xml_node node) // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1 energy_ = UPtrDist {new Watt(0.988e6, 2.249e-6)}; } + // Determine external source time distribution if (check_for_node(node, "time")) { pugi::xml_node node_dist = node.child("time"); From 55138aa144942816ae5bdd457cbfc5194cefa988 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Jan 2023 23:49:31 -0600 Subject: [PATCH 1491/2654] Picking up an additional suggestion from @paulromano Co-authored-by: Paul Romano --- .../regression_tests/unstructured_mesh/source_sampling/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index facd0cad5..7627a68db 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -36,7 +36,7 @@ def model(): root_cell, _ = regular_mesh.build_cells() - geometry = openmc.Geometry(root=[root_cell]) + geometry = openmc.Geometry([root_cell]) # set boundary conditions of the root cell for surface in root_cell.region.get_surfaces().values(): From 4d06ed5640604dd8a6c65bab16f27308cace684e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Jan 2023 23:51:12 -0600 Subject: [PATCH 1492/2654] Passing mesh memo through to source from_xml method --- openmc/settings.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index b8b1ec2b4..129ae2655 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -978,8 +978,8 @@ class Settings: for source in self.source: root.append(source.to_xml_element()) if isinstance(source.space, MeshSpatial): - path = f"./mesh[@id='{source.space.mesh.id}']" - if root.find(path) is None: + path = f"./mesh[@id='{source.space.mesh.id}']" + if root.find(path) is None: root.append(source.space.mesh.to_xml_element()) def _create_volume_calcs_subelement(self, root): @@ -1326,17 +1326,22 @@ class Settings: threshold = float(get_text(elem, 'threshold')) self.keff_trigger = {'type': trigger, 'threshold': threshold} - def _source_from_xml_element(self, root): + def _source_from_xml_element(self, root, meshes=None): for elem in root.findall('source'): src = Source.from_xml_element(elem) if isinstance(src.space, MeshSpatial): mesh_id = int(get_text(elem, 'mesh')) - path = f"./mesh[@id='{mesh_id}']" - mesh_elem = root.find(path) - if mesh_elem is not None: - src.space.mesh = MeshBase.from_xml_element(mesh_elem) - else: - raise RuntimeError('No mesh was specified for the mesh source') + if mesh_id not in meshes: + path = f"./mesh[@id='{mesh_id}']" + mesh_elem = root.find(path) + if mesh_elem is not None: + mesh = MeshBase.from_xml_element(mesh_elem) + meshes[mesh.id] = mesh + try: + src.space.mesh = meshes[mesh_id] + except KeyError as e: + raise e(f'Mesh with ID {mesh_id} was not found.') + # add newly constructed source object to the list self.source.append(src) def _volume_calcs_from_xml_element(self, root): @@ -1710,7 +1715,7 @@ class Settings: settings._rel_max_lost_particles_from_xml_element(elem) settings._generations_per_batch_from_xml_element(elem) settings._keff_trigger_from_xml_element(elem) - settings._source_from_xml_element(elem) + settings._source_from_xml_element(elem, meshes) settings._volume_calcs_from_xml_element(elem) settings._output_from_xml_element(elem) settings._statepoint_from_xml_element(elem) From 4675ff0231739849f27019afc2e866cce0e83f87 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Jan 2023 23:52:34 -0600 Subject: [PATCH 1493/2654] Correcting MOAB call args --- src/mesh.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 39b5a225e..ffe239015 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2109,17 +2109,17 @@ Position MOABMesh::sample(uint64_t* seed, int32_t bin) const { moab::EntityHandle tet_ent = get_ent_handle_from_bin(bin); // Get vertex coordinates for MOAB tet - std::array conn1; + const moab::EntityHandle* conn1; int conn1_size; moab::ErrorCode rval = - mbi_->get_connectivity(&tet_ent, 1, conn1.data(), conn1_size); + mbi_->get_connectivity(tet_ent, conn1, conn1_size); if (rval != moab::MB_SUCCESS || conn1_size != 4) { fatal_error(fmt::format( - "Failed to get tet connectivity or connectivity size () is invalid.", + "Failed to get tet connectivity or connectivity size ({}) is invalid.", conn1_size)); } moab::CartVect p[4]; - rval = mbi_->get_coords(conn1.data(), conn1.size(), p[0].array()); + rval = mbi_->get_coords(conn1, conn1_size, p[0].array()); if (rval != moab::MB_SUCCESS) { fatal_error("Failed to get tet coords"); } From 6f0c6f52962cb37f5ec1420c1537f868630297f7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Jan 2023 23:52:57 -0600 Subject: [PATCH 1494/2654] Applying suggestions for tests from @paulromano. --- .../unstructured_mesh/source_sampling/test.py | 8 ++------ tests/unit_tests/test_source_mesh.py | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 7627a68db..35b3be63e 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -21,7 +21,7 @@ def model(): ### Materials ### materials = openmc.Materials() - water_mat = openmc.Material(material_id=3, name="water") + water_mat = openmc.Material(name="water") water_mat.add_nuclide("H1", 2.0) water_mat.add_nuclide("O16", 1.0) water_mat.set_density("atom/b-cm", 0.07416) @@ -34,14 +34,10 @@ def model(): regular_mesh.dimension = (10, 10, 10) regular_mesh.width = (2, 2, 2) - root_cell, _ = regular_mesh.build_cells() + root_cell, _ = regular_mesh.build_cells(bc=['vacuum']*6) geometry = openmc.Geometry([root_cell]) - # set boundary conditions of the root cell - for surface in root_cell.region.get_surfaces().values(): - surface.boundary_type = 'vacuum' - ### Settings ### settings = openmc.Settings() settings.run_mode = 'fixed source' diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index f093d54d6..34f84f450 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -23,7 +23,7 @@ def model(): ### Materials ### materials = openmc.Materials() - water_mat = openmc.Material(material_id=3, name="water") + water_mat = openmc.Material(name="water") water_mat.add_nuclide("H1", 2.0) water_mat.add_nuclide("O16", 1.0) water_mat.set_density("atom/b-cm", 0.07416) @@ -39,14 +39,10 @@ def model(): regular_mesh.dimension = (10, 10, 10) regular_mesh.width = (2, 2, 2) - root_cell, _ = regular_mesh.build_cells() + root_cell, _ = regular_mesh.build_cells(bc=['vacuum']*6) geometry = openmc.Geometry(root=[root_cell]) - # set boundary conditions of the root cell - for surface in root_cell.region.get_surfaces().values(): - surface.boundary_type = 'vacuum' - ### Settings ### settings = openmc.Settings() settings.run_mode = 'fixed source' From d0988327fef653bb09b4152640d099206e55f482 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 13 Jan 2023 00:00:16 -0600 Subject: [PATCH 1495/2654] Applying formatter --- include/openmc/distribution_spatial.h | 2 +- include/openmc/mesh.h | 19 ++++---- src/distribution_spatial.cpp | 38 ++++++++------- src/initialize.cpp | 22 +++++---- src/mesh.cpp | 66 +++++++++++++++------------ src/settings.cpp | 3 +- src/source.cpp | 2 +- 7 files changed, 86 insertions(+), 66 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 939d055ba..78fb316db 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -4,8 +4,8 @@ #include "pugixml.hpp" #include "openmc/distribution.h" -#include "openmc/position.h" #include "openmc/mesh.h" +#include "openmc/position.h" namespace openmc { diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 73a4f0bb7..7abc8a832 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -7,8 +7,8 @@ #include #include "hdf5.h" -#include "xtensor/xtensor.hpp" #include "pugixml.hpp" +#include "xtensor/xtensor.hpp" #include "openmc/memory.h" // for unique_ptr #include "openmc/particle.h" @@ -41,7 +41,7 @@ namespace openmc { // Constants //============================================================================== -enum class ElementType { UNSUPPORTED=-1, LINEAR_TET, LINEAR_HEX }; +enum class ElementType { UNSUPPORTED = -1, LINEAR_TET, LINEAR_HEX }; //============================================================================== // Global variables @@ -80,7 +80,7 @@ public: //! \param[in] seed Seed to use for random sampling //! \param[in] bin Bin value of the tet sampled //! \return sampled position within tet - virtual Position sample(uint64_t* seed, int32_t bin) const=0; + virtual Position sample(uint64_t* seed, int32_t bin) const = 0; //! Get the volume of a mesh bin // @@ -713,7 +713,7 @@ private: std::pair get_score_tags(std::string score) const; // Data members - moab::Range ehs_; //!< Range of tetrahedra EntityHandle's in the mesh + moab::Range ehs_; //!< Range of tetrahedra EntityHandle's in the mesh moab::Range verts_; //!< Range of vertex EntityHandle's in the mesh moab::EntityHandle tetset_; //!< EntitySet containing all tetrahedra moab::EntityHandle kdtree_root_; //!< Root of the MOAB KDTree @@ -731,8 +731,8 @@ class LibMesh : public UnstructuredMesh { public: // Constructors LibMesh(pugi::xml_node node); - LibMesh(const std::string & filename, double length_multiplier = 1.0); - LibMesh(libMesh::MeshBase & input_mesh, double length_multiplier = 1.0); + LibMesh(const std::string& filename, double length_multiplier = 1.0); + LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier = 1.0); static const std::string mesh_lib_type; @@ -787,8 +787,11 @@ private: int get_bin_from_element(const libMesh::Elem* elem) const; // Data members - unique_ptr unique_m_ = nullptr; //!< pointer to the libMesh MeshBase instance, only used if mesh is created inside OpenMC - libMesh::MeshBase* m_; //!< pointer to libMesh MeshBase instance, always set during intialization + unique_ptr unique_m_ = + nullptr; //!< pointer to the libMesh MeshBase instance, only used if mesh is + //!< created inside OpenMC + libMesh::MeshBase* m_; //!< pointer to libMesh MeshBase instance, always set + //!< during intialization vector> pl_; //!< per-thread point locators unique_ptr diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index fbe5ce658..fb1fbf099 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -1,10 +1,10 @@ #include "openmc/distribution_spatial.h" #include "openmc/error.h" -#include "openmc/random_lcg.h" -#include "openmc/xml_interface.h" #include "openmc/mesh.h" +#include "openmc/random_lcg.h" #include "openmc/search.h" +#include "openmc/xml_interface.h" namespace openmc { @@ -139,7 +139,8 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node) pugi::xml_node node_dist = node.child("cos_theta"); cos_theta_ = distribution_from_xml(node_dist); } else { - // If no distribution was specified, default to a single point at cos_theta=0 + // If no distribution was specified, default to a single point at + // cos_theta=0 double x[] {0.0}; double p[] {1.0}; cos_theta_ = make_unique(x, p, 1); @@ -188,8 +189,8 @@ Position SphericalIndependent::sample(uint64_t* seed) const MeshSpatial::MeshSpatial(pugi::xml_node node) { - // No in-tet distributions implemented, could include distributions for the barycentric coords - // Read in unstructured mesh from mesh_id value + // No in-tet distributions implemented, could include distributions for the + // barycentric coords Read in unstructured mesh from mesh_id value int32_t mesh_id = std::stoi(get_node_value(node, "mesh_id")); // Get pointer to spatial distribution mesh_idx_ = model::mesh_map.at(mesh_id); @@ -211,7 +212,7 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) int32_t n_bins = this->n_sources(); std::vector strengths(n_bins, 0.0); - mesh_CDF_.resize(n_bins+1); + mesh_CDF_.resize(n_bins + 1); mesh_CDF_[0] = {0.0}; total_strength_ = 0.0; @@ -220,14 +221,14 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) // File scheme is weighted by an array given in the xml file mesh_strengths_ = std::vector(n_bins, 1.0); if (check_for_node(node, "strengths")) { - strengths = get_node_array(node, "strengths"); - if (strengths.size() != n_bins) { - fatal_error( - fmt::format("Number of entries in the source strengths array {} does " - "not match the number of entities in mesh {} ({}).", - strengths.size(), mesh_id, n_bins)); - } - mesh_strengths_ = std::move(strengths); + strengths = get_node_array(node, "strengths"); + if (strengths.size() != n_bins) { + fatal_error( + fmt::format("Number of entries in the source strengths array {} does " + "not match the number of entities in mesh {} ({}).", + strengths.size(), mesh_id, n_bins)); + } + mesh_strengths_ = std::move(strengths); } if (get_node_value_bool(node, "volume_normalized")) { @@ -236,14 +237,17 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) } } - total_strength_ = std::accumulate(mesh_strengths_.begin(), mesh_strengths_.end(), 0.0); + total_strength_ = + std::accumulate(mesh_strengths_.begin(), mesh_strengths_.end(), 0.0); for (int i = 0; i < n_bins; i++) { - mesh_CDF_[i+1] = mesh_CDF_[i] + mesh_strengths_[i]/total_strength_; + mesh_CDF_[i + 1] = mesh_CDF_[i] + mesh_strengths_[i] / total_strength_; } if (fabs(mesh_CDF_.back() - 1.0) > FP_COINCIDENT) { - fatal_error(fmt::format("Mesh sampling CDF is incorrectly formed. Final value is: {}", mesh_CDF_.back())); + fatal_error( + fmt::format("Mesh sampling CDF is incorrectly formed. Final value is: {}", + mesh_CDF_.back())); } mesh_CDF_.back() = 1.0; } diff --git a/src/initialize.cpp b/src/initialize.cpp index 913e0b1a9..6383af64e 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -106,7 +106,8 @@ int openmc_init(int argc, char* argv[], const void* intracomm) openmc::openmc_set_seed(DEFAULT_SEED); // Read XML input files - if (!read_model_xml()) read_separate_xml_files(); + if (!read_model_xml()) + read_separate_xml_files(); // Write some initial output under the header if needed initial_output(); @@ -299,7 +300,8 @@ int parse_command_line(int argc, char* argv[]) return 0; } -bool read_model_xml() { +bool read_model_xml() +{ std::string model_filename = settings::path_input.empty() ? "." : settings::path_input; @@ -314,7 +316,8 @@ bool read_model_xml() { model_filename += "/model.xml"; // if this file doesn't exist, stop here - if (!file_exists(model_filename)) return false; + if (!file_exists(model_filename)) + return false; // try to process the path input as an XML file pugi::xml_document doc; @@ -327,7 +330,7 @@ bool read_model_xml() { // Read settings if (!check_for_node(root, "settings")) { - fatal_error("No node present in the model.xml file."); + fatal_error("No node present in the model.xml file."); } auto settings_root = root.child("settings"); @@ -343,13 +346,15 @@ bool read_model_xml() { title(); } - write_message(fmt::format("Reading model XML file '{}' ...", model_filename), 5); + write_message( + fmt::format("Reading model XML file '{}' ...", model_filename), 5); read_settings_xml(settings_root); // If other XML files are present, display warning // that they will be ignored - auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", "tallies.xml", "plots.xml"}; + auto other_inputs = {"materials.xml", "geometry.xml", "settings.xml", + "tallies.xml", "plots.xml"}; for (const auto& input : other_inputs) { if (file_exists(settings::path_input + input)) { warning((fmt::format("Other XML file input(s) are present. These files " @@ -384,7 +389,7 @@ bool read_model_xml() { if (check_for_node(root, "tallies")) read_tallies_xml(root.child("tallies")); - // Initialize distribcell_filters + // Initialize distribcell_filters prepare_distribcell(); if (check_for_node(root, "plots")) @@ -415,7 +420,8 @@ void read_separate_xml_files() read_plots_xml(); } -void initial_output() { +void initial_output() +{ // write initial output if (settings::run_mode == RunMode::PLOTTING) { // Read plots.xml if it exists diff --git a/src/mesh.cpp b/src/mesh.cpp index ffe239015..121ca1f8a 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -207,24 +207,22 @@ Position UnstructuredMesh::sample_tet( // (2000) Generating Random Points in a Tetrahedron, Journal of Graphics // Tools, 5:4, 9-12, DOI: 10.1080/10867651.2000.10487528 if (s + t > 1) { - s = 1.0 - s; - t = 1.0 - t; + s = 1.0 - s; + t = 1.0 - t; } if (s + t + u > 1) { if (t + u > 1) { double old_t = t; t = 1.0 - u; u = 1.0 - s - old_t; - }else if (t + u <= 1) { + } else if (t + u <= 1) { double old_s = s; s = 1.0 - t - u; u = old_s + t + u - 1; } } - return s*(coords[1]-coords[0]) - + t*(coords[2]-coords[0]) - + u*(coords[3]-coords[0]) - + coords[0]; + return s * (coords[1] - coords[0]) + t * (coords[2] - coords[0]) + + u * (coords[3] - coords[0]) + coords[0]; } const std::string UnstructuredMesh::mesh_type = "unstructured"; @@ -268,8 +266,8 @@ void UnstructuredMesh::to_hdf5(hid_t group) const // write element types and connectivity vector volumes; - xt::xtensor connectivity ({static_cast(this->n_bins()), 8}); - xt::xtensor elem_types ({static_cast(this->n_bins()), 1}); + xt::xtensor connectivity({static_cast(this->n_bins()), 8}); + xt::xtensor elem_types({static_cast(this->n_bins()), 1}); for (int i = 0; i < this->n_bins(); i++) { auto conn = this->connectivity(i); @@ -277,17 +275,20 @@ void UnstructuredMesh::to_hdf5(hid_t group) const // write linear tet element if (conn.size() == 4) { - xt::view(elem_types, i, xt::all()) = static_cast(ElementType::LINEAR_TET); - xt::view(connectivity, i, xt::all()) = xt::xarray({conn[0], conn[1], conn[2], conn[3], - -1, -1, -1, -1}); - // write linear hex element + xt::view(elem_types, i, xt::all()) = + static_cast(ElementType::LINEAR_TET); + xt::view(connectivity, i, xt::all()) = + xt::xarray({conn[0], conn[1], conn[2], conn[3], -1, -1, -1, -1}); + // write linear hex element } else if (conn.size() == 8) { - xt::view(elem_types, i, xt::all()) = static_cast(ElementType::LINEAR_HEX); - xt::view(connectivity, i, xt::all()) = xt::xarray({conn[0], conn[1], conn[2], conn[3], - conn[4], conn[5], conn[6], conn[7]}); + xt::view(elem_types, i, xt::all()) = + static_cast(ElementType::LINEAR_HEX); + xt::view(connectivity, i, xt::all()) = xt::xarray({conn[0], conn[1], + conn[2], conn[3], conn[4], conn[5], conn[6], conn[7]}); } else { num_elem_skipped++; - xt::view(elem_types, i, xt::all()) = static_cast(ElementType::UNSUPPORTED); + xt::view(elem_types, i, xt::all()) = + static_cast(ElementType::UNSUPPORTED); xt::view(connectivity, i, xt::all()) = -1; } } @@ -1873,7 +1874,6 @@ void MOABMesh::initialize() fatal_error("Failed to get all vertex handles"); } - // make an entity set for all tetrahedra // this is used for convenience later in output rval = mbi_->create_meshset(moab::MESHSET_SET, tetset_); @@ -2104,15 +2104,15 @@ std::string MOABMesh::library() const } // Sample position within a tet for MOAB type tets -Position MOABMesh::sample(uint64_t* seed, int32_t bin) const { +Position MOABMesh::sample(uint64_t* seed, int32_t bin) const +{ moab::EntityHandle tet_ent = get_ent_handle_from_bin(bin); // Get vertex coordinates for MOAB tet const moab::EntityHandle* conn1; int conn1_size; - moab::ErrorCode rval = - mbi_->get_connectivity(tet_ent, conn1, conn1_size); + moab::ErrorCode rval = mbi_->get_connectivity(tet_ent, conn1, conn1_size); if (rval != moab::MB_SUCCESS || conn1_size != 4) { fatal_error(fmt::format( "Failed to get tet connectivity or connectivity size ({}) is invalid.", @@ -2132,7 +2132,6 @@ Position MOABMesh::sample(uint64_t* seed, int32_t bin) const { return this->sample_tet(tet_verts, seed); } - double MOABMesh::tet_volume(moab::EntityHandle tet) const { vector conn; @@ -2253,10 +2252,12 @@ std::pair, vector> MOABMesh::plot( return {}; } -int MOABMesh::get_vert_idx_from_handle(moab::EntityHandle vert) const { +int MOABMesh::get_vert_idx_from_handle(moab::EntityHandle vert) const +{ int idx = vert - verts_[0]; if (idx >= n_vertices()) { - fatal_error(fmt::format("Invalid vertex idx {} (# vertices {})", idx, n_vertices())); + fatal_error( + fmt::format("Invalid vertex idx {} (# vertices {})", idx, n_vertices())); } return idx; } @@ -2328,11 +2329,13 @@ Position MOABMesh::centroid(int bin) const return {centroid[0], centroid[1], centroid[2]}; } -int MOABMesh::n_vertices() const { +int MOABMesh::n_vertices() const +{ return verts_.size(); } -Position MOABMesh::vertex(int id) const { +Position MOABMesh::vertex(int id) const +{ moab::ErrorCode rval; @@ -2347,7 +2350,8 @@ Position MOABMesh::vertex(int id) const { return {coords[0], coords[1], coords[2]}; } -std::vector MOABMesh::connectivity(int bin) const { +std::vector MOABMesh::connectivity(int bin) const +{ moab::ErrorCode rval; auto tet = get_ent_handle_from_bin(bin); @@ -2501,14 +2505,15 @@ const std::string LibMesh::mesh_lib_type = "libmesh"; LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { - // filename_ and length_multiplier_ will already be set by the UnstructuredMesh constructor + // filename_ and length_multiplier_ will already be set by the + // UnstructuredMesh constructor set_mesh_pointer_from_filename(filename_); set_length_multiplier(length_multiplier_); initialize(); } // create the mesh from a pointer to a libMesh Mesh -LibMesh::LibMesh(libMesh::MeshBase & input_mesh, double length_multiplier) +LibMesh::LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier) { m_ = &input_mesh; set_length_multiplier(length_multiplier); @@ -2586,7 +2591,8 @@ void LibMesh::initialize() } // Sample position within a tet for LibMesh type tets -Position LibMesh::sample(uint64_t* seed, int32_t bin) const { +Position LibMesh::sample(uint64_t* seed, int32_t bin) const +{ const auto& elem = get_element_from_bin(bin); // Get tet vertex coordinates from LibMesh std::array tet_verts; diff --git a/src/settings.cpp b/src/settings.cpp index 310378517..1eceb5b3d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -214,7 +214,8 @@ void get_run_parameters(pugi::xml_node node_base) } } -void read_settings_xml() { +void read_settings_xml() +{ using namespace settings; using namespace pugi; // Check if settings.xml exists diff --git a/src/source.cpp b/src/source.cpp index 2cb5632b3..5862a41e2 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -94,7 +94,7 @@ IndependentSource::IndependentSource(pugi::xml_node node) space_ = UPtrSpace {new CylindricalIndependent(node_space)}; } else if (type == "spherical") { space_ = UPtrSpace {new SphericalIndependent(node_space)}; - } else if (type =="mesh"){ + } else if (type == "mesh") { space_ = UPtrSpace {new MeshSpatial(node_space)}; } else if (type == "box") { space_ = UPtrSpace {new SpatialBox(node_space)}; From 124839796eeb9e17188423c631a2c672abd0bf39 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 13 Jan 2023 00:04:22 -0600 Subject: [PATCH 1496/2654] Updating test inputs for auto-generated material ID. --- .../unstructured_mesh/source_sampling/inputs_true0.dat | 2 +- .../unstructured_mesh/source_sampling/inputs_true1.dat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat index dcb56d403..e50fc71ac 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat @@ -1125,7 +1125,7 @@ - + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat index 9e22063f1..b416ffb34 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -1125,7 +1125,7 @@ - + From 606457a1f0ed306fe6a90e1c1474e792b820df5c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Jan 2023 13:36:51 +0700 Subject: [PATCH 1497/2654] A few style fixes in material.py --- openmc/material.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 7844ec131..29c01d146 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -416,10 +416,10 @@ class Material(IDManagerMixin): self._atoms = volume_calc.atoms[self.id] else: raise ValueError('No volume information found for material ID={}.' - .format(self.id)) + .format(self.id)) else: raise ValueError('No volume information found for material ID={}.' - .format(self.id)) + .format(self.id)) def set_density(self, units: str, density: Optional[float] = None): """Set the density of the material @@ -531,11 +531,10 @@ class Material(IDManagerMixin): params['percent_type'] = percent_type - ## check if nuclide + # check if nuclide if not component.isalpha(): self.add_nuclide(component, **params) - else: # is element - kwargs = params + else: self.add_element(component, **params) def remove_nuclide(self, nuclide: str): @@ -1583,7 +1582,6 @@ class Materials(cv.CheckedList): if trailing_indent: file.write(indentation) - def export_to_xml(self, path: PathLike = 'materials.xml'): """Export material collection to an XML file. From bbe39dbc1b7a613ae3405af37e4125e5b137d701 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Jan 2023 13:41:00 +0700 Subject: [PATCH 1498/2654] Added some missing versionadded directives --- openmc/executor.py | 12 +++++++++--- openmc/material.py | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index 22862a7cf..accffd06a 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -41,7 +41,7 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, Path to OpenMC executable. Defaults to 'openmc'. mpi_args : list of str, optional MPI execute command and any additional MPI arguments to pass, - e.g. ['mpiexec', '-n', '8']. + e.g., ['mpiexec', '-n', '8']. path_input : str or Pathlike Path to a single XML file or a directory containing XML files for the OpenMC executable to read. @@ -139,6 +139,8 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.', path_input=None): Path to a single XML file or a directory containing XML files for the OpenMC executable to read. + .. versionadded:: 0.13.3 + Raises ------ RuntimeError @@ -171,6 +173,8 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', path_input=None): Path to a single XML file or a directory containing XML files for the OpenMC executable to read. + .. versionadded:: 0.13.3 + Raises ------ RuntimeError @@ -222,7 +226,7 @@ def calculate_volumes(threads=None, output=True, cwd='.', Path to OpenMC executable. Defaults to 'openmc'. mpi_args : list of str, optional MPI execute command and any additional MPI arguments to pass, - e.g. ['mpiexec', '-n', '8']. + e.g., ['mpiexec', '-n', '8']. cwd : str, optional Path to working directory to run in. Defaults to the current working directory. @@ -280,7 +284,7 @@ def run(particles=None, threads=None, geometry_debug=False, openmc_exec : str, optional Path to OpenMC executable. Defaults to 'openmc'. mpi_args : list of str, optional - MPI execute command and any additional MPI arguments to pass, e.g. + MPI execute command and any additional MPI arguments to pass, e.g., ['mpiexec', '-n', '8']. event_based : bool, optional Turns on event-based parallelism, instead of default history-based @@ -291,6 +295,8 @@ def run(particles=None, threads=None, geometry_debug=False, Path to a single XML file or a directory containing XML files for the OpenMC executable to read. + .. versionadded:: 0.13.3 + Raises ------ RuntimeError diff --git a/openmc/material.py b/openmc/material.py index 29c01d146..a213a53fd 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -352,6 +352,8 @@ class Material(IDManagerMixin): on this string. The name and material_id parameters are simply passed on to the Material constructor. + .. versionadded:: 0.13.3 + Parameters ---------- cfg : str From f92515d6f2152b4a04e75c911a03abcd23ffb598 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 13 Jan 2023 08:45:48 -0600 Subject: [PATCH 1499/2654] Correcting sampling unit test --- tests/unit_tests/test_source_mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index 34f84f450..d50e85e3f 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -139,6 +139,6 @@ def test_unstructured_mesh_sampling(model, request, test_cases): exp_vals = strengths.reshape(-1, 12).sum(axis=1) / sum(strengths) diff = np.abs(mean - exp_vals) - assert((diff < 2*std_dev).sum() / diff[:10].size >= 0.95) - assert((diff < 6*std_dev).sum() / diff.size >= 0.97) + assert((diff < 2*std_dev).sum() / diff.size >= 0.95) + assert((diff < 6*std_dev).sum() / diff.size >= 0.997) From 17c836731e793dcf250cb45f539bb428eb7cda8a Mon Sep 17 00:00:00 2001 From: Patrick A Myers Date: Fri, 13 Jan 2023 10:47:56 -0500 Subject: [PATCH 1500/2654] added cmake option for building tests --- CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 655ff4a6f..51db85207 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ endif() #=============================================================================== option(OPENMC_USE_OPENMP "Enable shared-memory parallelism with OpenMP" ON) +option(OPENMC_BUILD_TESTS "Build tests" ON) option(OPENMC_ENABLE_PROFILE "Compile with profiling flags" OFF) option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" OFF) option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF) @@ -288,9 +289,12 @@ endif() #=============================================================================== # Catch2 library #=============================================================================== -find_package_write_status(Catch2) -if (NOT Catch2) - add_subdirectory(vendor/Catch2) + +if(OPENMC_BUILD_TESTS) + find_package_write_status(Catch2) + if (NOT Catch2) + add_subdirectory(vendor/Catch2) + endif() endif() #=============================================================================== From 8cbcf23b8d0d8343dafef95609a55b3fe67325fb Mon Sep 17 00:00:00 2001 From: Patrick A Myers Date: Fri, 13 Jan 2023 10:50:03 -0500 Subject: [PATCH 1501/2654] added option for build tests to linking tests library --- CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 51db85207..11ae71ac6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -516,9 +516,11 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() -# Add cpp tests directory -include(CTest) -add_subdirectory(tests/cpp_unit_tests) +if (OPENMC_BUILD_TESTS) + # Add cpp tests directory + include(CTest) + add_subdirectory(tests/cpp_unit_tests) +endif() if (OPENMC_USE_MCPL) target_compile_definitions(libopenmc PUBLIC OPENMC_MCPL) From 8288b558226e3b729ffe04fc02b7a88d9d64cc2b Mon Sep 17 00:00:00 2001 From: Patrick A Myers Date: Fri, 13 Jan 2023 10:53:18 -0500 Subject: [PATCH 1502/2654] moved make after environment variable --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b9a7d7a0..687753963 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,7 +125,7 @@ jobs: - name: test shell: bash run: | - make CTEST_OUTPUT_ON_FAILURE=1 test -C $GITHUB_WORKSPACE/build/ + CTEST_OUTPUT_ON_FAILURE=1 make test -C $GITHUB_WORKSPACE/build/ $GITHUB_WORKSPACE/tools/ci/gha-script.sh - name: after_success From ff9b5fd74141b0f24676136f5ebec7a69f347ac1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 13 Jan 2023 10:24:05 -0600 Subject: [PATCH 1503/2654] Adding not about moving the mesh cdf in the future. --- include/openmc/distribution_spatial.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 78fb316db..8840b0539 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -115,6 +115,8 @@ public: private: int32_t mesh_idx_ {C_NONE}; double total_strength_ {0.0}; + // TODO: move to an independent class in the future that's similar + // to a discrete distribution without outcomes std::vector mesh_CDF_; std::vector mesh_strengths_; }; From 9313f809a471f4b7050057f1179e42252089cb22 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 13 Jan 2023 10:34:30 -0600 Subject: [PATCH 1504/2654] Adding a tally to the unstructured mesh regression test. --- .../source_sampling/inputs_true0.dat | 15 + .../source_sampling/inputs_true1.dat | 15 + .../source_sampling/results_true.dat | 2001 +++++++++++++++++ .../unstructured_mesh/source_sampling/test.py | 11 +- 4 files changed, 2041 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat index e50fc71ac..986d80054 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat @@ -1148,3 +1148,18 @@ test_mesh_tets.e + + + + 10 10 10 + -10 -10 -10 + 2 2 2 + + + 10 + + + 1 + flux + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat index b416ffb34..38d5aa497 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat @@ -1148,3 +1148,18 @@ test_mesh_tets.e + + + + 10 10 10 + -10 -10 -10 + 2 2 2 + + + 10 + + + 1 + flux + + diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat b/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat index e69de29bb..2a4e11d06 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat +++ b/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat @@ -0,0 +1,2001 @@ +tally 1: +1.593417E+00 +1.270534E+00 +6.435684E-01 +2.112550E-01 +1.658901E-01 +1.600397E-02 +1.283617E-02 +8.238393E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.437438E-01 +5.945848E-02 +1.616140E-01 +1.856954E-02 +1.615653E-01 +1.561656E-02 +4.938536E-02 +1.239963E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.113048E-01 +6.215464E-03 +4.271852E-02 +1.824872E-03 +1.761175E-02 +1.760674E-04 +1.205084E-01 +1.054273E-02 +6.127572E-02 +1.996189E-03 +1.652343E-02 +2.730237E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.960809E-02 +6.146617E-04 +4.470296E-02 +1.998355E-03 +6.648900E-03 +4.420787E-05 +2.239550E-02 +4.238383E-04 +6.025002E-02 +3.246093E-03 +4.429460E-02 +1.476567E-03 +2.292967E-02 +5.257698E-04 +1.155621E-02 +1.335461E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.006629E-02 +4.026559E-04 +1.373329E-02 +1.886032E-04 +2.885571E-02 +8.326518E-04 +0.000000E+00 +0.000000E+00 +8.681819E-03 +7.269326E-05 +1.729655E-02 +2.991705E-04 +0.000000E+00 +0.000000E+00 +1.137346E-02 +1.293555E-04 +2.292967E-02 +5.257698E-04 +6.588997E-03 +4.341488E-05 +8.403494E-03 +7.061872E-05 +0.000000E+00 +0.000000E+00 +4.258899E-02 +1.813822E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.770928E-03 +7.678044E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.634067E-02 +2.670176E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.316088E-02 +5.364264E-04 +1.942811E-02 +3.774516E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.932682E-02 +3.735258E-04 +2.326218E-02 +5.411290E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.203632E-02 +1.026326E-03 +1.055267E-02 +1.113588E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.093434E-02 +4.382464E-04 +2.165466E-02 +4.689242E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.733898E-01 +7.002510E-02 +2.309913E-01 +2.966987E-02 +1.527013E-01 +1.167932E-02 +8.319432E-02 +3.486622E-03 +5.053980E-02 +1.792018E-03 +4.025393E-02 +1.620379E-03 +1.411059E-02 +1.991089E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.005911E-01 +2.480369E-02 +1.606208E-01 +1.414104E-02 +2.700608E-02 +6.633840E-04 +6.338189E-02 +2.821858E-03 +2.966171E-02 +8.798173E-04 +2.082516E-02 +4.336873E-04 +2.082516E-02 +4.336873E-04 +4.992758E-03 +2.492763E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.481143E-02 +2.319748E-03 +4.078821E-02 +8.322204E-04 +5.300165E-02 +2.052940E-03 +1.632808E-02 +2.666061E-04 +5.095870E-03 +2.596789E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.759583E-02 +7.105825E-04 +8.335504E-03 +6.948063E-05 +0.000000E+00 +0.000000E+00 +2.834069E-02 +8.031945E-04 +2.788621E-02 +7.776405E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.122608E-02 +4.505464E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.480612E-02 +5.637391E-04 +2.562242E-02 +6.565086E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.122608E-02 +4.505464E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.155726E-02 +1.335702E-04 +2.713223E-02 +3.711933E-04 +1.066759E-02 +1.137975E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.938184E-02 +3.756556E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.387549E-02 +5.700390E-04 +2.178250E-02 +4.744771E-04 +4.038634E-03 +1.631057E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.614637E-03 +6.836328E-06 +2.126085E-02 +4.520238E-04 +2.582113E-02 +6.667308E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.524705E-02 +2.324725E-04 +2.590321E-03 +6.709765E-06 +2.323081E-02 +5.396705E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.219277E-03 +8.499508E-05 +1.660185E-02 +2.756215E-04 +2.063044E-02 +2.178208E-04 +1.117596E-01 +6.818370E-03 +4.897447E-02 +2.398498E-03 +1.499157E-02 +2.055896E-04 +2.464135E-03 +6.071962E-06 +0.000000E+00 +0.000000E+00 +6.772930E-03 +4.587259E-05 +2.037464E-02 +4.151259E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.580972E-02 +5.237084E-03 +5.810675E-02 +1.810352E-03 +3.382651E-02 +9.872507E-04 +3.231698E-02 +5.261563E-04 +4.236960E-02 +1.686234E-03 +2.526663E-02 +6.384027E-04 +0.000000E+00 +0.000000E+00 +1.634129E-02 +2.509239E-04 +4.170868E-02 +8.698088E-04 +2.977611E-02 +5.151998E-04 +5.717053E-02 +3.268469E-03 +6.132386E-02 +2.510165E-03 +9.358069E-02 +5.433557E-03 +1.609396E-02 +2.590155E-04 +4.065491E-02 +8.691452E-04 +2.041493E-02 +3.815802E-04 +2.283520E-02 +5.214466E-04 +8.540726E-03 +7.294400E-05 +0.000000E+00 +0.000000E+00 +1.193257E-02 +1.423862E-04 +6.562332E-03 +2.259782E-05 +5.029737E-02 +1.266099E-03 +2.948965E-02 +5.111548E-04 +3.472063E-02 +6.621828E-04 +5.350398E-04 +2.862676E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.415816E-02 +9.758404E-04 +1.866923E-02 +3.356958E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.812608E-02 +7.910764E-04 +1.925567E-03 +3.707808E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.822746E-02 +7.413062E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.275168E-02 +1.072673E-03 +2.157887E-02 +4.656475E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.472410E-03 +8.972655E-05 +1.844240E-03 +3.401222E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.374014E-02 +1.887915E-04 +1.325496E-02 +1.756940E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.122608E-02 +4.505464E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.963906E-02 +3.856926E-04 +5.151301E-03 +2.653590E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.168075E-02 +1.364400E-04 +9.545323E-03 +9.111320E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.300459E-03 +5.292110E-06 +6.327981E-03 +4.004335E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.122608E-02 +4.505464E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.387549E-02 +5.700390E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.627290E-02 +7.956933E-04 +4.792259E-02 +1.364038E-03 +3.499583E-02 +1.224708E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.163818E-02 +2.060150E-03 +4.159379E-02 +8.685600E-04 +4.253859E-03 +1.615120E-05 +6.757111E-03 +4.565855E-05 +1.814466E-02 +3.292288E-04 +7.449618E-03 +5.549681E-05 +2.539823E-02 +6.450699E-04 +1.274061E-03 +1.623232E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.668842E-02 +2.179809E-03 +4.556030E-02 +1.050861E-03 +2.476208E-02 +3.198567E-04 +3.207245E-02 +6.091098E-04 +0.000000E+00 +0.000000E+00 +3.802341E-02 +7.237092E-04 +0.000000E+00 +0.000000E+00 +5.283494E-03 +2.791531E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.304278E-03 +8.656959E-05 +5.627276E-02 +3.166624E-03 +4.848590E-03 +2.350883E-05 +4.296135E-02 +1.194861E-03 +2.282442E-02 +5.209543E-04 +1.239555E-02 +7.727435E-05 +3.153349E-02 +4.984208E-04 +9.010984E-03 +8.119784E-05 +2.283520E-02 +5.214466E-04 +2.033042E-02 +4.133258E-04 +0.000000E+00 +0.000000E+00 +3.003110E-02 +5.010297E-04 +1.944727E-02 +2.544423E-04 +2.144284E-02 +2.308237E-04 +4.003007E-02 +8.079146E-04 +1.048308E-02 +1.098949E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.504789E-03 +6.273966E-06 +5.930696E-03 +3.517315E-05 +2.241816E-02 +5.025737E-04 +1.134177E-02 +1.286358E-04 +5.854880E-03 +3.427961E-05 +7.824866E-03 +6.122854E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.468575E-02 +6.597708E-04 +1.840323E-02 +3.386789E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.741205E-02 +7.514206E-04 +2.354781E-03 +5.544993E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.484796E-02 +6.391249E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.748226E-02 +7.552746E-04 +4.489315E-03 +2.015395E-05 +0.000000E+00 +0.000000E+00 +2.141990E-02 +4.588121E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.692746E-02 +7.250880E-04 +8.874956E-04 +7.876485E-07 +1.536058E-03 +2.359473E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.671029E-02 +7.134394E-04 +0.000000E+00 +0.000000E+00 +1.051597E-03 +1.105856E-06 +6.452999E-02 +2.238885E-03 +5.295854E-03 +2.804607E-05 +2.738601E-02 +7.499937E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.967339E-02 +3.313781E-04 +0.000000E+00 +0.000000E+00 +4.584765E-02 +1.051619E-03 +0.000000E+00 +0.000000E+00 +2.030458E-02 +4.122759E-04 +4.597195E-03 +2.113420E-05 +0.000000E+00 +0.000000E+00 +2.412417E-02 +5.819754E-04 +9.997740E-03 +9.995481E-05 +0.000000E+00 +0.000000E+00 +2.601738E-02 +5.109608E-04 +1.133629E-02 +1.285116E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.372903E-02 +5.630669E-04 +4.193295E-02 +1.142818E-03 +4.507083E-03 +2.031379E-05 +3.307050E-02 +5.598584E-04 +3.159351E-02 +4.990749E-04 +0.000000E+00 +0.000000E+00 +2.378321E-02 +2.922266E-04 +1.586381E-02 +1.878945E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.377890E-03 +1.141014E-05 +4.122238E-02 +1.699285E-03 +0.000000E+00 +0.000000E+00 +2.161783E-02 +3.365314E-04 +1.827596E-02 +3.340106E-04 +0.000000E+00 +0.000000E+00 +3.637583E-02 +7.202075E-04 +5.929600E-03 +3.516015E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.349882E-02 +2.794124E-04 +1.991652E-02 +3.966678E-04 +3.690232E-03 +1.361781E-05 +3.480244E-02 +6.232648E-04 +1.973558E-02 +3.894929E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.014926E-03 +1.611963E-05 +2.233296E-02 +4.987612E-04 +1.655835E-02 +2.741789E-04 +0.000000E+00 +0.000000E+00 +1.298923E-02 +1.687200E-04 +1.225490E-02 +9.257926E-05 +2.969123E-03 +8.815691E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.310198E-03 +8.667980E-05 +2.241816E-02 +5.025737E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.273826E-02 +5.170283E-04 +1.848781E-02 +3.417992E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.616298E-02 +6.845017E-04 +2.783995E-03 +7.750628E-06 +2.993240E-02 +4.963407E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.705304E-02 +7.318672E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.103212E-02 +8.737693E-04 +3.454947E-02 +6.395950E-04 +1.476239E-03 +2.179280E-06 +2.631350E-02 +6.924005E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.813296E-02 +7.488786E-04 +1.150146E-03 +1.322835E-06 +0.000000E+00 +0.000000E+00 +8.473361E-03 +7.179785E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.985404E-03 +2.485425E-05 +0.000000E+00 +0.000000E+00 +2.293169E-02 +4.790237E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.564545E-03 +4.309325E-05 +0.000000E+00 +0.000000E+00 +1.642841E-02 +2.698927E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.041508E-02 +1.084739E-04 +1.872142E-02 +3.504915E-04 +4.201836E-03 +1.765542E-05 +0.000000E+00 +0.000000E+00 +2.494768E-02 +6.223869E-04 +0.000000E+00 +0.000000E+00 +2.630088E-04 +6.917362E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.952720E-02 +3.813114E-04 +2.582846E-02 +6.671093E-04 +8.222055E-03 +6.162640E-05 +0.000000E+00 +0.000000E+00 +4.111592E-02 +9.592563E-04 +2.156382E-02 +4.178815E-04 +0.000000E+00 +0.000000E+00 +3.077065E-03 +9.468328E-06 +3.174197E-02 +5.438564E-04 +6.451599E-03 +4.162314E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.989772E-02 +1.591828E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.115799E-02 +4.476606E-04 +9.599575E-03 +9.215184E-05 +0.000000E+00 +0.000000E+00 +1.764513E-02 +3.113507E-04 +2.303668E-02 +2.914406E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.920843E-03 +5.145277E-05 +1.628053E-02 +2.650555E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.267840E-02 +2.956815E-04 +2.131581E-02 +4.543639E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.437863E-02 +5.943177E-04 +1.244256E-03 +1.548174E-06 +2.452714E-02 +6.015808E-04 +0.000000E+00 +0.000000E+00 +1.446335E-02 +2.091885E-04 +1.456619E-02 +1.211898E-04 +2.427522E-02 +5.892863E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.930343E-03 +1.544760E-05 +8.945522E-03 +8.002236E-05 +0.000000E+00 +0.000000E+00 +1.490420E-03 +2.221351E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.268970E-02 +1.610285E-04 +2.241816E-02 +5.025737E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.027115E-02 +4.109196E-04 +3.849791E-02 +7.551064E-04 +6.812524E-03 +4.641048E-05 +2.548748E-03 +6.496114E-06 +2.524100E-02 +6.371078E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.909784E-03 +8.466841E-06 +1.945952E-02 +3.786728E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.186038E-02 +4.778760E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.347835E-02 +5.512330E-04 +0.000000E+00 +0.000000E+00 +8.950272E-03 +8.010737E-05 +1.595150E-02 +2.544504E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.676807E-03 +4.457975E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.770795E-02 +3.135715E-04 +6.969937E-03 +4.858002E-05 +2.532875E-02 +6.415453E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.087263E-02 +8.225934E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.021082E-03 +3.625342E-05 +1.813282E-02 +3.287991E-04 +9.217641E-03 +8.496490E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.068594E-02 +5.279156E-04 +2.138418E-02 +4.572831E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.721641E-02 +1.788283E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.472761E-03 +6.114549E-06 +3.329332E-02 +1.108445E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.897689E-02 +3.601223E-04 +5.626331E-03 +3.165561E-05 +0.000000E+00 +0.000000E+00 +8.612011E-03 +7.416673E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.742334E-02 +3.035727E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.049796E-02 +2.263917E-04 +4.544831E-03 +2.065549E-05 +1.424894E-05 +2.030322E-10 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.543311E-02 +2.381809E-04 +0.000000E+00 +0.000000E+00 +2.428098E-02 +5.895660E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.593748E-02 +2.540032E-04 +1.595037E-02 +2.544142E-04 +2.880580E-02 +8.297742E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.993671E-02 +3.974725E-04 +0.000000E+00 +0.000000E+00 +1.219389E-02 +1.486909E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.413656E-04 +8.861691E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.027115E-02 +4.109196E-04 +1.629920E-02 +2.656639E-04 +2.901123E-02 +5.793980E-04 +0.000000E+00 +0.000000E+00 +3.621256E-03 +1.311350E-05 +2.416849E-02 +5.841157E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.236930E-02 +5.003856E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.425632E-03 +1.173495E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.206052E-02 +1.454560E-04 +1.141784E-02 +1.303670E-04 +0.000000E+00 +0.000000E+00 +2.249774E-02 +5.061483E-04 +2.404034E-03 +5.779379E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.843474E-02 +3.398398E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.407967E-03 +1.943017E-05 +8.822362E-03 +7.783407E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.372903E-02 +5.630669E-04 +0.000000E+00 +0.000000E+00 +1.451080E-02 +2.105632E-04 +1.209842E-02 +1.463717E-04 +0.000000E+00 +0.000000E+00 +8.128789E-03 +6.607721E-05 +1.699068E-02 +1.455906E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.131766E-02 +1.280895E-04 +9.142882E-03 +8.359228E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.546445E-02 +1.579151E-04 +2.235882E-02 +4.999168E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.163445E-02 +1.000739E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.679579E-02 +2.820984E-04 +1.653088E-03 +2.732699E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.839123E-03 +6.145185E-05 +1.306490E-02 +1.706917E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.925889E-02 +3.709049E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.441919E-03 +1.973064E-05 +0.000000E+00 +0.000000E+00 +1.696490E-03 +2.878077E-06 +1.188102E-02 +1.411586E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.647024E-02 +2.712688E-04 +1.447624E-02 +2.095615E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.027115E-02 +4.109196E-04 +0.000000E+00 +0.000000E+00 +1.220227E-02 +8.388744E-05 +1.513623E-02 +2.291055E-04 +0.000000E+00 +0.000000E+00 +4.693765E-03 +2.203143E-05 +2.309598E-02 +5.334242E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.896430E-03 +3.596447E-06 +1.797193E-02 +3.229902E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.165452E-03 +1.735099E-05 +3.978577E-02 +8.171648E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.623932E-03 +6.885018E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.186038E-02 +4.778760E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.227784E-02 +4.963022E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.485032E-03 +5.602571E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.532875E-02 +6.415453E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.624400E-02 +2.638675E-04 +0.000000E+00 +0.000000E+00 +2.205166E-02 +4.862755E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.741186E-02 +3.031728E-04 +1.866250E-02 +1.752786E-04 +3.291961E-03 +1.083700E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.776803E-03 +1.426424E-05 +9.793825E-03 +9.591902E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.534928E-03 +1.249572E-05 +2.004150E-02 +4.016618E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.138556E-03 +4.573422E-06 +2.536426E-02 +6.433459E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.229453E-02 +1.511554E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.438471E-02 +5.946143E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.320156E-03 +5.383124E-06 +2.309308E-02 +5.332904E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.027115E-02 +4.109196E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.335984E-02 +5.456821E-04 +5.005121E-05 +2.505124E-09 +0.000000E+00 +0.000000E+00 +5.766274E-03 +3.324992E-05 +2.202347E-02 +4.850332E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.190054E-02 +4.796338E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.664785E-02 +5.186916E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.560194E-03 +3.091576E-05 +5.012432E-03 +2.512448E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.078818E-03 +1.663676E-05 +1.512098E-02 +2.286441E-04 +0.000000E+00 +0.000000E+00 +1.114343E-02 +1.241761E-04 +1.375834E-02 +1.892919E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.128775E-02 +1.274133E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.512973E-03 +2.289086E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.099115E-02 +4.406282E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.181004E-02 +1.394771E-04 +1.200573E-02 +1.441375E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.737885E-03 +7.496015E-06 +0.000000E+00 +0.000000E+00 +2.582846E-02 +6.671093E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.669493E-02 +7.126192E-04 +1.193971E-02 +9.099511E-05 +9.937766E-03 +9.875918E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.044477E-02 +1.090932E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.437034E-02 +2.065067E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.337119E-02 +5.462125E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.140183E-03 +3.770184E-05 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py index 35b3be63e..d6f16315a 100644 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ b/tests/regression_tests/unstructured_mesh/source_sampling/test.py @@ -38,6 +38,14 @@ def model(): geometry = openmc.Geometry([root_cell]) + ### Tallies ### + + # create a mesh flux tally + tally = openmc.Tally() + tally.filters.append(openmc.MeshFilter(regular_mesh)) + tally.scores = ['flux'] + tallies = openmc.Tallies([tally]) + ### Settings ### settings = openmc.Settings() settings.run_mode = 'fixed source' @@ -68,7 +76,8 @@ def model(): settings.source = source return openmc.model.Model(geometry=geometry, materials=materials, - settings=settings) + settings=settings, + tallies=tallies) test_cases = [ From beb3085469581fb7d6954f82f1442c7efcf74518 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 13 Jan 2023 12:24:24 -0600 Subject: [PATCH 1505/2654] Changing to const Mesh* --- include/openmc/distribution_spatial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 8840b0539..dda23927e 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -108,7 +108,7 @@ public: //! \return Sampled position Position sample(uint64_t* seed) const; - const unique_ptr& mesh() const { return model::meshes.at(mesh_idx_); } + const Mesh* mesh() const { return model::meshes.at(mesh_idx_).get(); } int32_t n_sources() const { return this->mesh()->n_bins(); } From 4122c02ad4955e34774db35c37c928d8a693e1f0 Mon Sep 17 00:00:00 2001 From: Patrick A Myers Date: Fri, 13 Jan 2023 16:50:50 -0500 Subject: [PATCH 1506/2654] change p to prob and fix alias table --- include/openmc/distribution.h | 8 ++++---- src/distribution.cpp | 38 +++++++++++++++++------------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 4519c285b..8563ee031 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -47,13 +47,13 @@ public: // Properties const vector& x() const { return x_; } - const vector& p() const { return p_; } + const vector& prob() const { return prob_; } const vector& alias() const { return alias_; } private: - vector x_; //!< Possible outcomes - vector - p_; //!< Probability of each outcome, mapped to alias method table + vector x_; //!< Possible outcomes + vector prob_; //!< Probability of accepting the uniformly sampled bin, + //!< mapped to alias method table vector alias_; //!< Alias table //! Normalize distribution so that probabilities sum to unity diff --git a/src/distribution.cpp b/src/distribution.cpp index 4634aa9d6..50913dfe4 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -1,6 +1,7 @@ #include "openmc/distribution.h" #include // for copy +#include #include // for sqrt, floor, max #include // for back_inserter #include // for accumulate @@ -26,34 +27,33 @@ Discrete::Discrete(pugi::xml_node node) auto params = get_node_array(node, "parameters"); std::size_t n = params.size(); - std::copy(params.begin(), params.begin() + n / 2, std::back_inserter(x_)); - std::copy(params.begin() + n / 2, params.end(), std::back_inserter(p_)); + double x[n / 2], p[n / 2]; - // Initialize alias tables - init_alias(); + std::copy(params.begin(), params.begin() + n / 2, x); + std::copy(params.begin() + n / 2, params.end(), p); + + new (this) Discrete(x, p, n / 2); } Discrete::Discrete(const double* x, const double* p, int n) - : x_ {x, x + n}, p_ {p, p + n} + : x_ {x, x + n}, prob_ {p, p + n} { - // Initialize alias tables - init_alias(); -} - -void Discrete::init_alias() { normalize(); + // The initialization and sampling method is base on Vose + // (DOI: 10.1109/32.92917) // Vectors for large and small probabilities based on 1/n vector large; vector small; // Set and allocate memory - alias_.reserve(x_.size()); + vector alias(x_.size(), 0); + alias_ = alias; // Fill large and small vectors based on 1/n - for (int i = 0; i < x_.size(); i++) { - p_[i] *= x_.size(); - if (p_[i] > 1.0) { + for (size_t i = 0; i < x_.size(); i++) { + prob_[i] *= x_.size(); + if (prob_[i] > 1.0) { large.push_back(i); } else { small.push_back(i); @@ -68,11 +68,11 @@ void Discrete::init_alias() { small.pop_back(); // Update probability and alias based on Vose's algorithm - p_[k] += p_[j] - 1.0; + prob_[k] += prob_[j] - 1.0; alias_[j] = k; // Move large index to small vector, if it is no longer large - if (p_[k] < 1.0) { + if (prob_[k] < 1.0) { small.push_back(k); large.pop_back(); } @@ -85,7 +85,7 @@ double Discrete::sample(uint64_t* seed) const int n = x_.size(); if (n > 1) { int u = prn(seed) * n; - if (prn(seed) < p_[u]) { + if (prn(seed) < prob_[u]) { return x_[u]; } else { return x_[alias_[u]]; @@ -98,8 +98,8 @@ double Discrete::sample(uint64_t* seed) const void Discrete::normalize() { // Renormalize density function so that it sums to unity - double norm = std::accumulate(p_.begin(), p_.end(), 0.0); - for (auto& p_i : p_) { + double norm = std::accumulate(prob_.begin(), prob_.end(), 0.0); + for (auto& p_i : prob_) { p_i /= norm; } } From d0e071be94828c5d71a1e698d08657da8d7cd21f Mon Sep 17 00:00:00 2001 From: Patrick A Myers Date: Fri, 13 Jan 2023 16:51:13 -0500 Subject: [PATCH 1507/2654] update tests to be more robust --- tests/cpp_unit_tests/test_distribution.cpp | 61 ++++++++++++++-------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/tests/cpp_unit_tests/test_distribution.cpp b/tests/cpp_unit_tests/test_distribution.cpp index d95dee498..a5166fb25 100644 --- a/tests/cpp_unit_tests/test_distribution.cpp +++ b/tests/cpp_unit_tests/test_distribution.cpp @@ -1,14 +1,14 @@ #include "openmc/distribution.h" #include "openmc/random_lcg.h" #include +#include #include TEST_CASE("Test alias method sampling of a discrete distribution") { - int n_samples = 1e6; + constexpr int n_samples = 1000000; double x[5] = {-1.6, 1.1, 20.3, 4.7, 0.9}; - double p[5] = {0.2, 0.1, 0.5, 0.05, 0.15}; - double samples[n_samples]; + double p[5] = {0.2, 0.1, 0.65, 0.02, 0.03}; // Initialize distribution openmc::Discrete dist(x, p, 5); @@ -20,24 +20,31 @@ TEST_CASE("Test alias method sampling of a discrete distribution") mean += x[i] * p[i]; } - // Sample distribution and calculate mean + // Sample distribution and calculate mean, standard deviation, and number of + // x[0] sampled double dist_mean = 0.0; - for (size_t i = 0; i < n_samples; i++) { - samples[i] = dist.sample(&seed); - dist_mean += samples[i]; - } - dist_mean /= n_samples; - - // Calculate standard deviation double std = 0.0; - for (size_t i = 0; i < n_samples; i++) { - std += (samples[i] - dist_mean) * (samples[i] - dist_mean); - } - std /= n_samples; + int counter = 0; - // Require sampled distribution mean is within 3 standard deviations of the + for (size_t i = 0; i < n_samples; i++) { + auto sample = dist.sample(&seed); + std += sample * sample / n_samples; + dist_mean += sample; + + if (sample == x[0]) + counter++; + } + + dist_mean /= n_samples; + std -= dist_mean * dist_mean; + + // Require sampled distribution mean is within 4 standard deviations of the // expected mean REQUIRE(std::abs(dist_mean - mean) < 4 * std); + + // Require counter of number of x[0] is within 4 standard deviations of + // 200,000 + REQUIRE(std::abs(counter - n_samples * p[0]) < 4 * std); } TEST_CASE("Test alias sampling method for pugixml constructor") @@ -47,17 +54,25 @@ TEST_CASE("Test alias sampling method for pugixml constructor") pugi::xml_node energy = doc.append_child("energy"); pugi::xml_node parameters = energy.append_child("parameters"); parameters.append_child(pugi::node_pcdata) - .set_value("17140457.745328166 1.0"); + .set_value("800 500000 30000 0.1 0.6 0.3"); // Initialize discrete distribution and seed openmc::Discrete dist(energy); uint64_t seed = openmc::init_seed(0, 0); + auto sample = dist.sample(&seed); // Assertions - REQUIRE(dist.x().size() == 1); - REQUIRE(dist.p().size() == 1); - REQUIRE(dist.alias().size() == 0); - REQUIRE(dist.x()[0] == 17140457.745328166); - REQUIRE(dist.p()[0] == 1.0); - REQUIRE(dist.sample(&seed) == 17140457.745328166); + REQUIRE(dist.x().size() == 3); + REQUIRE(dist.prob().size() == 3); + REQUIRE(dist.alias().size() == 3); + + openmc::vector correct_x = {800, 500000, 30000}; + openmc::vector correct_prob = {0.3, 1.0, 0.9}; + openmc::vector correct_alias = {1, 0, 1}; + + for (size_t i = 0; i < 3; i++) { + REQUIRE(dist.x()[i] == correct_x[i]); + REQUIRE(dist.prob()[i] == Catch::Approx(correct_prob[i]).epsilon(1e-12)); + REQUIRE(dist.alias()[i] == correct_alias[i]); + } } From 06e6d5d347fd6e3d0833bc3e3a194940d3edfcb8 Mon Sep 17 00:00:00 2001 From: josh Date: Tue, 17 Jan 2023 02:42:40 +0000 Subject: [PATCH 1508/2654] add dagmc testing --- tests/unit_tests/test_universe.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py index 39d1eec21..26b7779a7 100644 --- a/tests/unit_tests/test_universe.py +++ b/tests/unit_tests/test_universe.py @@ -107,11 +107,13 @@ def test_clone(): c2.fill = openmc.Material() c3 = openmc.Cell() u1 = openmc.Universe(name='cool', cells=(c1, c2, c3)) + u1.volume = 1. u2 = u1.clone() assert u2.name == u1.name assert u2.cells != u1.cells assert u2.get_all_materials() != u1.get_all_materials() + assert u2.volume == u1.volume u2 = u1.clone(clone_materials=False) assert u2.get_all_materials() == u1.get_all_materials() @@ -120,14 +122,33 @@ def test_clone(): assert next(iter(u3.cells.values())).region ==\ next(iter(u1.cells.values())).region - dagmc_u = openmc.DAGMCUniverse(filename="") + # Change attributes, make sure clone stays intact + u1.volume = 2. + u1.name = "different name" + assert u3.volume != u1.volume + assert u3.name != u1.name + + # Test cloning a DAGMC universe + dagmc_u = openmc.DAGMCUniverse(filename="", name="DAGMC universe") + dagmc_u.volume = 1. dagmc_u.auto_geom_ids = True dagmc_u.auto_mat_ids = True dagmc_u1 = dagmc_u.clone() assert dagmc_u1.name == dagmc_u.name + assert dagmc_u1.volume == dagmc_u.volume assert dagmc_u1.auto_geom_ids == dagmc_u.auto_geom_ids assert dagmc_u1.auto_mat_ids == dagmc_u.auto_mat_ids + # Change attributes, check the clone remained intact + dagmc_u.name = "another name" + dagmc_u.auto_geom_ids = False + dagmc_u.auto_mat_ids = False + dagmc_u.volume = 2. + assert dagmc_u1.name != dagmc_u.name + assert dagmc_u1.volume != dagmc_u.volume + assert dagmc_u1.auto_geom_ids != dagmc_u.auto_geom_ids + assert dagmc_u1.auto_mat_ids != dagmc_u.auto_mat_ids + def test_create_xml(cell_with_lattice): cells = [openmc.Cell() for i in range(5)] From 3d6179fa32a1b07d2fc860158c77bb550da0ee73 Mon Sep 17 00:00:00 2001 From: josh Date: Tue, 17 Jan 2023 02:43:02 +0000 Subject: [PATCH 1509/2654] remove try/except for class-specific 'deepcopy' --- openmc/universe.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 15bea0ba9..8babddfeb 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Iterable +from copy import deepcopy from numbers import Integral, Real from pathlib import Path from tempfile import TemporaryDirectory @@ -110,6 +111,12 @@ class UniverseBase(ABC, IDManagerMixin): """ + def _deepcopy_universe_for_clone(self): + """Deepcopy an openmc.UniverseBase object. This is a paceholder for any future classes inherited from this one. + This should only to be used within the openmc.UniverseBase.clone() context. + """ + return deepcopy(self) + def clone(self, clone_materials=True, clone_regions=True, memo=None): """Create a copy of this universe with a new unique ID, and clones all cells within this universe. @@ -137,14 +144,7 @@ class UniverseBase(ABC, IDManagerMixin): # If no memoize'd clone exists, instantiate one if self not in memo: - clone = openmc.Universe(name=self.name) - clone.volume = self.volume - # Try to set DAGMCUniverse-specific attributes on the clone - try: - clone.auto_geom_ids = self.auto_geom_ids - clone.auto_mat_ids = self.auto_mat_ids - except AttributeError: - pass + clone = self._deepcopy_universe_for_clone() # Clone all cells for the universe clone clone._cells = OrderedDict() @@ -616,6 +616,14 @@ class Universe(UniverseBase): if not instances_only: cell._paths.append(cell_path) + def _deepcopy_universe_for_clone(self): + """Clone all of the openmc.Universe object's attributes except for its cells, as they will be handled within the clone function. + This should only to be used within the openmc.UniverseBase.clone() context and is more performant than a deepcopy. + """ + clone = openmc.Universe(name=self.name) + clone.volume = self.volume + return clone + class DAGMCUniverse(UniverseBase): """A reference to a DAGMC file to be used in the model. @@ -952,3 +960,13 @@ class DAGMCUniverse(UniverseBase): out.auto_mat_ids = bool(elem.get('auto_mat_ids')) return out + + def _deepcopy_universe_for_clone(self): + """Clone all of the openmc.DAGMCUniverse object's attributes except for its cells, as they will be handled within the clone function. + This should only to be used within the openmc.UniverseBase.clone() context and is more performant than a deepcopy. + """ + clone = openmc.DAGMCUniverse(name=self.name, filename=self.filename) + clone.volume = self.volume + clone.auto_geom_ids = self.auto_geom_ids + clone.auto_mat_ids = self.auto_mat_ids + return clone \ No newline at end of file From d4a940d44d9fde91fca7a1dd950976795b5e1f9c Mon Sep 17 00:00:00 2001 From: April Novak Date: Tue, 17 Jan 2023 10:59:53 -0800 Subject: [PATCH 1510/2654] Remove unused dagmc settings parameter. Refs #2353 --- tests/regression_tests/dagmc/legacy/test.py | 2 -- tests/regression_tests/dagmc/refl/test.py | 2 -- tests/regression_tests/dagmc/uwuw/test.py | 2 -- 3 files changed, 6 deletions(-) diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index 502775148..36da44808 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -26,8 +26,6 @@ def model(): model.settings.source = source - model.settings.dagmc = True - # geometry dag_univ = openmc.DAGMCUniverse(Path("dagmc.h5m")) model.geometry = openmc.Geometry(dag_univ) diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py index 3fe41345c..5afc1a7a2 100644 --- a/tests/regression_tests/dagmc/refl/test.py +++ b/tests/regression_tests/dagmc/refl/test.py @@ -23,8 +23,6 @@ class UWUWTest(PyAPITestHarness): [ 4, 4, 4])) model.settings.source = source - model.settings.dagmc = True - model.settings.export_to_xml() # geometry diff --git a/tests/regression_tests/dagmc/uwuw/test.py b/tests/regression_tests/dagmc/uwuw/test.py index 5c9777d48..a8da2da60 100644 --- a/tests/regression_tests/dagmc/uwuw/test.py +++ b/tests/regression_tests/dagmc/uwuw/test.py @@ -23,8 +23,6 @@ class UWUWTest(PyAPITestHarness): [ 4, 4, 4])) model.settings.source = source - model.settings.dagmc = True - model.settings.export_to_xml() # geometry From bbacb383cdddb2e1e6f55a0d078109acf7e48b7e Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Wed, 18 Jan 2023 14:04:41 +0100 Subject: [PATCH 1511/2654] allowing to pass additiinal args to pool.deplete when using user specified maxtrix_func --- openmc/deplete/pool.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/pool.py b/openmc/deplete/pool.py index a3d37f79f..40e870daf 100644 --- a/openmc/deplete/pool.py +++ b/openmc/deplete/pool.py @@ -15,7 +15,7 @@ USE_MULTIPROCESSING = True NUM_PROCESSES = None -def deplete(func, chain, x, rates, dt, matrix_func=None): +def deplete(func, chain, x, rates, dt, matrix_func=None, **func_args): """Deplete materials using given reaction rates for a specified time Parameters @@ -37,6 +37,8 @@ def deplete(func, chain, x, rates, dt, matrix_func=None): ``fission_yields = {parent: {product: yield_frac}}`` Expected to return the depletion matrix required by ``func`` + func_args : dict + Remaining keyword arguments passed to the matrix_func Returns ------- @@ -57,7 +59,8 @@ def deplete(func, chain, x, rates, dt, matrix_func=None): if matrix_func is None: matrices = map(chain.form_matrix, rates, fission_yields) else: - matrices = map(matrix_func, repeat(chain), rates, fission_yields) + matrices = map(matrix_func, repeat(chain), rates, fission_yields, + **func_args) inputs = zip(matrices, x, repeat(dt)) From dcfac1d10e0b40dfc17079037d81da7298a01d59 Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Wed, 18 Jan 2023 14:12:00 +0100 Subject: [PATCH 1512/2654] tweaking comments --- openmc/deplete/pool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/pool.py b/openmc/deplete/pool.py index 40e870daf..13acb8bf5 100644 --- a/openmc/deplete/pool.py +++ b/openmc/deplete/pool.py @@ -38,7 +38,7 @@ def deplete(func, chain, x, rates, dt, matrix_func=None, **func_args): Expected to return the depletion matrix required by ``func`` func_args : dict - Remaining keyword arguments passed to the matrix_func + Remaining keyword arguments passed to matrix_func when used Returns ------- From cd7ad7de7a86c6e4996ae8dec1f74ccd17834116 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 18 Jan 2023 11:10:33 -0600 Subject: [PATCH 1513/2654] Adding failure check to mesh source unit test. --- tests/unit_tests/test_source_mesh.py | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index d50e85e3f..dc4cbf06c 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -122,6 +122,8 @@ def test_unstructured_mesh_sampling(model, request, test_cases): # subtract one from index to account for root cell cell_counts[c[0]._index - 1, m] += 1 + # make sure particle transport is successful + openmc.lib.run() openmc.lib.finalize() # normalize cell counts to get sampling frequency per particle @@ -142,3 +144,35 @@ def test_unstructured_mesh_sampling(model, request, test_cases): assert((diff < 2*std_dev).sum() / diff.size >= 0.95) assert((diff < 6*std_dev).sum() / diff.size >= 0.997) + +def test_strengths_size_failure(request, model): + # setup mesh source ### + mesh_filename = Path(request.fspath).parent / "test_mesh_tets.e" + uscd_mesh = openmc.UnstructuredMesh(mesh_filename, 'libmesh') + + # intentionally incorrectly sized to trigger an error + n_cells = len(model.geometry.get_all_cells()) + strengths = np.random.rand(n_cells*TETS_PER_VOXEL) + + # create the spatial distribution based on the mesh + space = openmc.stats.MeshSpatial(uscd_mesh, strengths) + + energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) + source = openmc.Source(space=space, energy=energy) + model.settings.source = source + + # skip the test if unstructured mesh is not available + if not openmc.lib._libmesh_enabled(): + if openmc.lib._dagmc_enabled(): + source.space.mesh.library = 'moab' + else: + pytest.skip("Unstructured mesh support unavailable.") + + # make sure that an incorrrectly sized strengths array causes a failure + source.space.strengths = source.space.strengths[:-1] + + mesh_filename = Path(request.fspath).parent / source.space.mesh.filename + + with pytest.raises(RuntimeError, match=r'strengths array'), cdtemp([mesh_filename]): + model.export_to_xml() + openmc.run() \ No newline at end of file From de8f99adbebe4303e102b7a4c6bacde9fcdab525 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 18 Jan 2023 11:12:10 -0600 Subject: [PATCH 1514/2654] Removing unstructured mesh source sampling test. The test cases here almost entirely overlapped with those in the unit test. The test for an invalid size on the strengths array has been moved to the test_mesh_source.py unit test. --- .../source_sampling/__init__.py | 0 .../source_sampling/inputs_true0.dat | 1165 ---------- .../source_sampling/inputs_true1.dat | 1165 ---------- .../source_sampling/results_true.dat | 2001 ----------------- .../unstructured_mesh/source_sampling/test.py | 121 - .../source_sampling/test_mesh_tets.e | 1 - 6 files changed, 4453 deletions(-) delete mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/__init__.py delete mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat delete mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat delete mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat delete mode 100644 tests/regression_tests/unstructured_mesh/source_sampling/test.py delete mode 120000 tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/__init__.py b/tests/regression_tests/unstructured_mesh/source_sampling/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat deleted file mode 100644 index 986d80054..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true0.dat +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 2 2 - 10 10 10 - -10 -10 -10 - -91 92 93 94 95 96 97 98 99 100 -81 82 83 84 85 86 87 88 89 90 -71 72 73 74 75 76 77 78 79 80 -61 62 63 64 65 66 67 68 69 70 -51 52 53 54 55 56 57 58 59 60 -41 42 43 44 45 46 47 48 49 50 -31 32 33 34 35 36 37 38 39 40 -21 22 23 24 25 26 27 28 29 30 -11 12 13 14 15 16 17 18 19 20 -1 2 3 4 5 6 7 8 9 10 - -191 192 193 194 195 196 197 198 199 200 -181 182 183 184 185 186 187 188 189 190 -171 172 173 174 175 176 177 178 179 180 -161 162 163 164 165 166 167 168 169 170 -151 152 153 154 155 156 157 158 159 160 -141 142 143 144 145 146 147 148 149 150 -131 132 133 134 135 136 137 138 139 140 -121 122 123 124 125 126 127 128 129 130 -111 112 113 114 115 116 117 118 119 120 -101 102 103 104 105 106 107 108 109 110 - -291 292 293 294 295 296 297 298 299 300 -281 282 283 284 285 286 287 288 289 290 -271 272 273 274 275 276 277 278 279 280 -261 262 263 264 265 266 267 268 269 270 -251 252 253 254 255 256 257 258 259 260 -241 242 243 244 245 246 247 248 249 250 -231 232 233 234 235 236 237 238 239 240 -221 222 223 224 225 226 227 228 229 230 -211 212 213 214 215 216 217 218 219 220 -201 202 203 204 205 206 207 208 209 210 - -391 392 393 394 395 396 397 398 399 400 -381 382 383 384 385 386 387 388 389 390 -371 372 373 374 375 376 377 378 379 380 -361 362 363 364 365 366 367 368 369 370 -351 352 353 354 355 356 357 358 359 360 -341 342 343 344 345 346 347 348 349 350 -331 332 333 334 335 336 337 338 339 340 -321 322 323 324 325 326 327 328 329 330 -311 312 313 314 315 316 317 318 319 320 -301 302 303 304 305 306 307 308 309 310 - -491 492 493 494 495 496 497 498 499 500 -481 482 483 484 485 486 487 488 489 490 -471 472 473 474 475 476 477 478 479 480 -461 462 463 464 465 466 467 468 469 470 -451 452 453 454 455 456 457 458 459 460 -441 442 443 444 445 446 447 448 449 450 -431 432 433 434 435 436 437 438 439 440 -421 422 423 424 425 426 427 428 429 430 -411 412 413 414 415 416 417 418 419 420 -401 402 403 404 405 406 407 408 409 410 - -591 592 593 594 595 596 597 598 599 600 -581 582 583 584 585 586 587 588 589 590 -571 572 573 574 575 576 577 578 579 580 -561 562 563 564 565 566 567 568 569 570 -551 552 553 554 555 556 557 558 559 560 -541 542 543 544 545 546 547 548 549 550 -531 532 533 534 535 536 537 538 539 540 -521 522 523 524 525 526 527 528 529 530 -511 512 513 514 515 516 517 518 519 520 -501 502 503 504 505 506 507 508 509 510 - -691 692 693 694 695 696 697 698 699 700 -681 682 683 684 685 686 687 688 689 690 -671 672 673 674 675 676 677 678 679 680 -661 662 663 664 665 666 667 668 669 670 -651 652 653 654 655 656 657 658 659 660 -641 642 643 644 645 646 647 648 649 650 -631 632 633 634 635 636 637 638 639 640 -621 622 623 624 625 626 627 628 629 630 -611 612 613 614 615 616 617 618 619 620 -601 602 603 604 605 606 607 608 609 610 - -791 792 793 794 795 796 797 798 799 800 -781 782 783 784 785 786 787 788 789 790 -771 772 773 774 775 776 777 778 779 780 -761 762 763 764 765 766 767 768 769 770 -751 752 753 754 755 756 757 758 759 760 -741 742 743 744 745 746 747 748 749 750 -731 732 733 734 735 736 737 738 739 740 -721 722 723 724 725 726 727 728 729 730 -711 712 713 714 715 716 717 718 719 720 -701 702 703 704 705 706 707 708 709 710 - -891 892 893 894 895 896 897 898 899 900 -881 882 883 884 885 886 887 888 889 890 -871 872 873 874 875 876 877 878 879 880 -861 862 863 864 865 866 867 868 869 870 -851 852 853 854 855 856 857 858 859 860 -841 842 843 844 845 846 847 848 849 850 -831 832 833 834 835 836 837 838 839 840 -821 822 823 824 825 826 827 828 829 830 -811 812 813 814 815 816 817 818 819 820 -801 802 803 804 805 806 807 808 809 810 - -991 992 993 994 995 996 997 998 999 1000 -981 982 983 984 985 986 987 988 989 990 -971 972 973 974 975 976 977 978 979 980 -961 962 963 964 965 966 967 968 969 970 -951 952 953 954 955 956 957 958 959 960 -941 942 943 944 945 946 947 948 949 950 -931 932 933 934 935 936 937 938 939 940 -921 922 923 924 925 926 927 928 929 930 -911 912 913 914 915 916 917 918 919 920 -901 902 903 904 905 906 907 908 909 910 - - - - - - - - - - - - - - - - - - - fixed source - 100 - 2 - - - 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - - - 15000000.0 1.0 - - - - test_mesh_tets.e - - - - - - 10 10 10 - -10 -10 -10 - 2 2 2 - - - 10 - - - 1 - flux - - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat deleted file mode 100644 index 38d5aa497..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/inputs_true1.dat +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 2 2 - 10 10 10 - -10 -10 -10 - -91 92 93 94 95 96 97 98 99 100 -81 82 83 84 85 86 87 88 89 90 -71 72 73 74 75 76 77 78 79 80 -61 62 63 64 65 66 67 68 69 70 -51 52 53 54 55 56 57 58 59 60 -41 42 43 44 45 46 47 48 49 50 -31 32 33 34 35 36 37 38 39 40 -21 22 23 24 25 26 27 28 29 30 -11 12 13 14 15 16 17 18 19 20 -1 2 3 4 5 6 7 8 9 10 - -191 192 193 194 195 196 197 198 199 200 -181 182 183 184 185 186 187 188 189 190 -171 172 173 174 175 176 177 178 179 180 -161 162 163 164 165 166 167 168 169 170 -151 152 153 154 155 156 157 158 159 160 -141 142 143 144 145 146 147 148 149 150 -131 132 133 134 135 136 137 138 139 140 -121 122 123 124 125 126 127 128 129 130 -111 112 113 114 115 116 117 118 119 120 -101 102 103 104 105 106 107 108 109 110 - -291 292 293 294 295 296 297 298 299 300 -281 282 283 284 285 286 287 288 289 290 -271 272 273 274 275 276 277 278 279 280 -261 262 263 264 265 266 267 268 269 270 -251 252 253 254 255 256 257 258 259 260 -241 242 243 244 245 246 247 248 249 250 -231 232 233 234 235 236 237 238 239 240 -221 222 223 224 225 226 227 228 229 230 -211 212 213 214 215 216 217 218 219 220 -201 202 203 204 205 206 207 208 209 210 - -391 392 393 394 395 396 397 398 399 400 -381 382 383 384 385 386 387 388 389 390 -371 372 373 374 375 376 377 378 379 380 -361 362 363 364 365 366 367 368 369 370 -351 352 353 354 355 356 357 358 359 360 -341 342 343 344 345 346 347 348 349 350 -331 332 333 334 335 336 337 338 339 340 -321 322 323 324 325 326 327 328 329 330 -311 312 313 314 315 316 317 318 319 320 -301 302 303 304 305 306 307 308 309 310 - -491 492 493 494 495 496 497 498 499 500 -481 482 483 484 485 486 487 488 489 490 -471 472 473 474 475 476 477 478 479 480 -461 462 463 464 465 466 467 468 469 470 -451 452 453 454 455 456 457 458 459 460 -441 442 443 444 445 446 447 448 449 450 -431 432 433 434 435 436 437 438 439 440 -421 422 423 424 425 426 427 428 429 430 -411 412 413 414 415 416 417 418 419 420 -401 402 403 404 405 406 407 408 409 410 - -591 592 593 594 595 596 597 598 599 600 -581 582 583 584 585 586 587 588 589 590 -571 572 573 574 575 576 577 578 579 580 -561 562 563 564 565 566 567 568 569 570 -551 552 553 554 555 556 557 558 559 560 -541 542 543 544 545 546 547 548 549 550 -531 532 533 534 535 536 537 538 539 540 -521 522 523 524 525 526 527 528 529 530 -511 512 513 514 515 516 517 518 519 520 -501 502 503 504 505 506 507 508 509 510 - -691 692 693 694 695 696 697 698 699 700 -681 682 683 684 685 686 687 688 689 690 -671 672 673 674 675 676 677 678 679 680 -661 662 663 664 665 666 667 668 669 670 -651 652 653 654 655 656 657 658 659 660 -641 642 643 644 645 646 647 648 649 650 -631 632 633 634 635 636 637 638 639 640 -621 622 623 624 625 626 627 628 629 630 -611 612 613 614 615 616 617 618 619 620 -601 602 603 604 605 606 607 608 609 610 - -791 792 793 794 795 796 797 798 799 800 -781 782 783 784 785 786 787 788 789 790 -771 772 773 774 775 776 777 778 779 780 -761 762 763 764 765 766 767 768 769 770 -751 752 753 754 755 756 757 758 759 760 -741 742 743 744 745 746 747 748 749 750 -731 732 733 734 735 736 737 738 739 740 -721 722 723 724 725 726 727 728 729 730 -711 712 713 714 715 716 717 718 719 720 -701 702 703 704 705 706 707 708 709 710 - -891 892 893 894 895 896 897 898 899 900 -881 882 883 884 885 886 887 888 889 890 -871 872 873 874 875 876 877 878 879 880 -861 862 863 864 865 866 867 868 869 870 -851 852 853 854 855 856 857 858 859 860 -841 842 843 844 845 846 847 848 849 850 -831 832 833 834 835 836 837 838 839 840 -821 822 823 824 825 826 827 828 829 830 -811 812 813 814 815 816 817 818 819 820 -801 802 803 804 805 806 807 808 809 810 - -991 992 993 994 995 996 997 998 999 1000 -981 982 983 984 985 986 987 988 989 990 -971 972 973 974 975 976 977 978 979 980 -961 962 963 964 965 966 967 968 969 970 -951 952 953 954 955 956 957 958 959 960 -941 942 943 944 945 946 947 948 949 950 -931 932 933 934 935 936 937 938 939 940 -921 922 923 924 925 926 927 928 929 930 -911 912 913 914 915 916 917 918 919 920 -901 902 903 904 905 906 907 908 909 910 - - - - - - - - - - - - - - - - - - - fixed source - 100 - 2 - - - 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - - - 15000000.0 1.0 - - - - test_mesh_tets.e - - - - - - 10 10 10 - -10 -10 -10 - 2 2 2 - - - 10 - - - 1 - flux - - diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat b/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat deleted file mode 100644 index 2a4e11d06..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/results_true.dat +++ /dev/null @@ -1,2001 +0,0 @@ -tally 1: -1.593417E+00 -1.270534E+00 -6.435684E-01 -2.112550E-01 -1.658901E-01 -1.600397E-02 -1.283617E-02 -8.238393E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.437438E-01 -5.945848E-02 -1.616140E-01 -1.856954E-02 -1.615653E-01 -1.561656E-02 -4.938536E-02 -1.239963E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.113048E-01 -6.215464E-03 -4.271852E-02 -1.824872E-03 -1.761175E-02 -1.760674E-04 -1.205084E-01 -1.054273E-02 -6.127572E-02 -1.996189E-03 -1.652343E-02 -2.730237E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.960809E-02 -6.146617E-04 -4.470296E-02 -1.998355E-03 -6.648900E-03 -4.420787E-05 -2.239550E-02 -4.238383E-04 -6.025002E-02 -3.246093E-03 -4.429460E-02 -1.476567E-03 -2.292967E-02 -5.257698E-04 -1.155621E-02 -1.335461E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.006629E-02 -4.026559E-04 -1.373329E-02 -1.886032E-04 -2.885571E-02 -8.326518E-04 -0.000000E+00 -0.000000E+00 -8.681819E-03 -7.269326E-05 -1.729655E-02 -2.991705E-04 -0.000000E+00 -0.000000E+00 -1.137346E-02 -1.293555E-04 -2.292967E-02 -5.257698E-04 -6.588997E-03 -4.341488E-05 -8.403494E-03 -7.061872E-05 -0.000000E+00 -0.000000E+00 -4.258899E-02 -1.813822E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.770928E-03 -7.678044E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.634067E-02 -2.670176E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.316088E-02 -5.364264E-04 -1.942811E-02 -3.774516E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.932682E-02 -3.735258E-04 -2.326218E-02 -5.411290E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.203632E-02 -1.026326E-03 -1.055267E-02 -1.113588E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.093434E-02 -4.382464E-04 -2.165466E-02 -4.689242E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.733898E-01 -7.002510E-02 -2.309913E-01 -2.966987E-02 -1.527013E-01 -1.167932E-02 -8.319432E-02 -3.486622E-03 -5.053980E-02 -1.792018E-03 -4.025393E-02 -1.620379E-03 -1.411059E-02 -1.991089E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.005911E-01 -2.480369E-02 -1.606208E-01 -1.414104E-02 -2.700608E-02 -6.633840E-04 -6.338189E-02 -2.821858E-03 -2.966171E-02 -8.798173E-04 -2.082516E-02 -4.336873E-04 -2.082516E-02 -4.336873E-04 -4.992758E-03 -2.492763E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.481143E-02 -2.319748E-03 -4.078821E-02 -8.322204E-04 -5.300165E-02 -2.052940E-03 -1.632808E-02 -2.666061E-04 -5.095870E-03 -2.596789E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.759583E-02 -7.105825E-04 -8.335504E-03 -6.948063E-05 -0.000000E+00 -0.000000E+00 -2.834069E-02 -8.031945E-04 -2.788621E-02 -7.776405E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.122608E-02 -4.505464E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.480612E-02 -5.637391E-04 -2.562242E-02 -6.565086E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.122608E-02 -4.505464E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.155726E-02 -1.335702E-04 -2.713223E-02 -3.711933E-04 -1.066759E-02 -1.137975E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.938184E-02 -3.756556E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.387549E-02 -5.700390E-04 -2.178250E-02 -4.744771E-04 -4.038634E-03 -1.631057E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.614637E-03 -6.836328E-06 -2.126085E-02 -4.520238E-04 -2.582113E-02 -6.667308E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.524705E-02 -2.324725E-04 -2.590321E-03 -6.709765E-06 -2.323081E-02 -5.396705E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.219277E-03 -8.499508E-05 -1.660185E-02 -2.756215E-04 -2.063044E-02 -2.178208E-04 -1.117596E-01 -6.818370E-03 -4.897447E-02 -2.398498E-03 -1.499157E-02 -2.055896E-04 -2.464135E-03 -6.071962E-06 -0.000000E+00 -0.000000E+00 -6.772930E-03 -4.587259E-05 -2.037464E-02 -4.151259E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.580972E-02 -5.237084E-03 -5.810675E-02 -1.810352E-03 -3.382651E-02 -9.872507E-04 -3.231698E-02 -5.261563E-04 -4.236960E-02 -1.686234E-03 -2.526663E-02 -6.384027E-04 -0.000000E+00 -0.000000E+00 -1.634129E-02 -2.509239E-04 -4.170868E-02 -8.698088E-04 -2.977611E-02 -5.151998E-04 -5.717053E-02 -3.268469E-03 -6.132386E-02 -2.510165E-03 -9.358069E-02 -5.433557E-03 -1.609396E-02 -2.590155E-04 -4.065491E-02 -8.691452E-04 -2.041493E-02 -3.815802E-04 -2.283520E-02 -5.214466E-04 -8.540726E-03 -7.294400E-05 -0.000000E+00 -0.000000E+00 -1.193257E-02 -1.423862E-04 -6.562332E-03 -2.259782E-05 -5.029737E-02 -1.266099E-03 -2.948965E-02 -5.111548E-04 -3.472063E-02 -6.621828E-04 -5.350398E-04 -2.862676E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.415816E-02 -9.758404E-04 -1.866923E-02 -3.356958E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.812608E-02 -7.910764E-04 -1.925567E-03 -3.707808E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.822746E-02 -7.413062E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.275168E-02 -1.072673E-03 -2.157887E-02 -4.656475E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.472410E-03 -8.972655E-05 -1.844240E-03 -3.401222E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.374014E-02 -1.887915E-04 -1.325496E-02 -1.756940E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.122608E-02 -4.505464E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.963906E-02 -3.856926E-04 -5.151301E-03 -2.653590E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.168075E-02 -1.364400E-04 -9.545323E-03 -9.111320E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300459E-03 -5.292110E-06 -6.327981E-03 -4.004335E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.122608E-02 -4.505464E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.387549E-02 -5.700390E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.627290E-02 -7.956933E-04 -4.792259E-02 -1.364038E-03 -3.499583E-02 -1.224708E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.163818E-02 -2.060150E-03 -4.159379E-02 -8.685600E-04 -4.253859E-03 -1.615120E-05 -6.757111E-03 -4.565855E-05 -1.814466E-02 -3.292288E-04 -7.449618E-03 -5.549681E-05 -2.539823E-02 -6.450699E-04 -1.274061E-03 -1.623232E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.668842E-02 -2.179809E-03 -4.556030E-02 -1.050861E-03 -2.476208E-02 -3.198567E-04 -3.207245E-02 -6.091098E-04 -0.000000E+00 -0.000000E+00 -3.802341E-02 -7.237092E-04 -0.000000E+00 -0.000000E+00 -5.283494E-03 -2.791531E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.304278E-03 -8.656959E-05 -5.627276E-02 -3.166624E-03 -4.848590E-03 -2.350883E-05 -4.296135E-02 -1.194861E-03 -2.282442E-02 -5.209543E-04 -1.239555E-02 -7.727435E-05 -3.153349E-02 -4.984208E-04 -9.010984E-03 -8.119784E-05 -2.283520E-02 -5.214466E-04 -2.033042E-02 -4.133258E-04 -0.000000E+00 -0.000000E+00 -3.003110E-02 -5.010297E-04 -1.944727E-02 -2.544423E-04 -2.144284E-02 -2.308237E-04 -4.003007E-02 -8.079146E-04 -1.048308E-02 -1.098949E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.504789E-03 -6.273966E-06 -5.930696E-03 -3.517315E-05 -2.241816E-02 -5.025737E-04 -1.134177E-02 -1.286358E-04 -5.854880E-03 -3.427961E-05 -7.824866E-03 -6.122854E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.468575E-02 -6.597708E-04 -1.840323E-02 -3.386789E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.741205E-02 -7.514206E-04 -2.354781E-03 -5.544993E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.484796E-02 -6.391249E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.748226E-02 -7.552746E-04 -4.489315E-03 -2.015395E-05 -0.000000E+00 -0.000000E+00 -2.141990E-02 -4.588121E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.692746E-02 -7.250880E-04 -8.874956E-04 -7.876485E-07 -1.536058E-03 -2.359473E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.671029E-02 -7.134394E-04 -0.000000E+00 -0.000000E+00 -1.051597E-03 -1.105856E-06 -6.452999E-02 -2.238885E-03 -5.295854E-03 -2.804607E-05 -2.738601E-02 -7.499937E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.967339E-02 -3.313781E-04 -0.000000E+00 -0.000000E+00 -4.584765E-02 -1.051619E-03 -0.000000E+00 -0.000000E+00 -2.030458E-02 -4.122759E-04 -4.597195E-03 -2.113420E-05 -0.000000E+00 -0.000000E+00 -2.412417E-02 -5.819754E-04 -9.997740E-03 -9.995481E-05 -0.000000E+00 -0.000000E+00 -2.601738E-02 -5.109608E-04 -1.133629E-02 -1.285116E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.372903E-02 -5.630669E-04 -4.193295E-02 -1.142818E-03 -4.507083E-03 -2.031379E-05 -3.307050E-02 -5.598584E-04 -3.159351E-02 -4.990749E-04 -0.000000E+00 -0.000000E+00 -2.378321E-02 -2.922266E-04 -1.586381E-02 -1.878945E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.377890E-03 -1.141014E-05 -4.122238E-02 -1.699285E-03 -0.000000E+00 -0.000000E+00 -2.161783E-02 -3.365314E-04 -1.827596E-02 -3.340106E-04 -0.000000E+00 -0.000000E+00 -3.637583E-02 -7.202075E-04 -5.929600E-03 -3.516015E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.349882E-02 -2.794124E-04 -1.991652E-02 -3.966678E-04 -3.690232E-03 -1.361781E-05 -3.480244E-02 -6.232648E-04 -1.973558E-02 -3.894929E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.014926E-03 -1.611963E-05 -2.233296E-02 -4.987612E-04 -1.655835E-02 -2.741789E-04 -0.000000E+00 -0.000000E+00 -1.298923E-02 -1.687200E-04 -1.225490E-02 -9.257926E-05 -2.969123E-03 -8.815691E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.310198E-03 -8.667980E-05 -2.241816E-02 -5.025737E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.273826E-02 -5.170283E-04 -1.848781E-02 -3.417992E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.616298E-02 -6.845017E-04 -2.783995E-03 -7.750628E-06 -2.993240E-02 -4.963407E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.705304E-02 -7.318672E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.103212E-02 -8.737693E-04 -3.454947E-02 -6.395950E-04 -1.476239E-03 -2.179280E-06 -2.631350E-02 -6.924005E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.813296E-02 -7.488786E-04 -1.150146E-03 -1.322835E-06 -0.000000E+00 -0.000000E+00 -8.473361E-03 -7.179785E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.985404E-03 -2.485425E-05 -0.000000E+00 -0.000000E+00 -2.293169E-02 -4.790237E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.564545E-03 -4.309325E-05 -0.000000E+00 -0.000000E+00 -1.642841E-02 -2.698927E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.041508E-02 -1.084739E-04 -1.872142E-02 -3.504915E-04 -4.201836E-03 -1.765542E-05 -0.000000E+00 -0.000000E+00 -2.494768E-02 -6.223869E-04 -0.000000E+00 -0.000000E+00 -2.630088E-04 -6.917362E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.952720E-02 -3.813114E-04 -2.582846E-02 -6.671093E-04 -8.222055E-03 -6.162640E-05 -0.000000E+00 -0.000000E+00 -4.111592E-02 -9.592563E-04 -2.156382E-02 -4.178815E-04 -0.000000E+00 -0.000000E+00 -3.077065E-03 -9.468328E-06 -3.174197E-02 -5.438564E-04 -6.451599E-03 -4.162314E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.989772E-02 -1.591828E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.115799E-02 -4.476606E-04 -9.599575E-03 -9.215184E-05 -0.000000E+00 -0.000000E+00 -1.764513E-02 -3.113507E-04 -2.303668E-02 -2.914406E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.920843E-03 -5.145277E-05 -1.628053E-02 -2.650555E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.267840E-02 -2.956815E-04 -2.131581E-02 -4.543639E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.437863E-02 -5.943177E-04 -1.244256E-03 -1.548174E-06 -2.452714E-02 -6.015808E-04 -0.000000E+00 -0.000000E+00 -1.446335E-02 -2.091885E-04 -1.456619E-02 -1.211898E-04 -2.427522E-02 -5.892863E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.930343E-03 -1.544760E-05 -8.945522E-03 -8.002236E-05 -0.000000E+00 -0.000000E+00 -1.490420E-03 -2.221351E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.268970E-02 -1.610285E-04 -2.241816E-02 -5.025737E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.027115E-02 -4.109196E-04 -3.849791E-02 -7.551064E-04 -6.812524E-03 -4.641048E-05 -2.548748E-03 -6.496114E-06 -2.524100E-02 -6.371078E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.909784E-03 -8.466841E-06 -1.945952E-02 -3.786728E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.186038E-02 -4.778760E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.347835E-02 -5.512330E-04 -0.000000E+00 -0.000000E+00 -8.950272E-03 -8.010737E-05 -1.595150E-02 -2.544504E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.676807E-03 -4.457975E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.770795E-02 -3.135715E-04 -6.969937E-03 -4.858002E-05 -2.532875E-02 -6.415453E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.087263E-02 -8.225934E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.021082E-03 -3.625342E-05 -1.813282E-02 -3.287991E-04 -9.217641E-03 -8.496490E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.068594E-02 -5.279156E-04 -2.138418E-02 -4.572831E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.721641E-02 -1.788283E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.472761E-03 -6.114549E-06 -3.329332E-02 -1.108445E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.897689E-02 -3.601223E-04 -5.626331E-03 -3.165561E-05 -0.000000E+00 -0.000000E+00 -8.612011E-03 -7.416673E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.742334E-02 -3.035727E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.049796E-02 -2.263917E-04 -4.544831E-03 -2.065549E-05 -1.424894E-05 -2.030322E-10 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.543311E-02 -2.381809E-04 -0.000000E+00 -0.000000E+00 -2.428098E-02 -5.895660E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.593748E-02 -2.540032E-04 -1.595037E-02 -2.544142E-04 -2.880580E-02 -8.297742E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.993671E-02 -3.974725E-04 -0.000000E+00 -0.000000E+00 -1.219389E-02 -1.486909E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.413656E-04 -8.861691E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.027115E-02 -4.109196E-04 -1.629920E-02 -2.656639E-04 -2.901123E-02 -5.793980E-04 -0.000000E+00 -0.000000E+00 -3.621256E-03 -1.311350E-05 -2.416849E-02 -5.841157E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.236930E-02 -5.003856E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.425632E-03 -1.173495E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.206052E-02 -1.454560E-04 -1.141784E-02 -1.303670E-04 -0.000000E+00 -0.000000E+00 -2.249774E-02 -5.061483E-04 -2.404034E-03 -5.779379E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.843474E-02 -3.398398E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.407967E-03 -1.943017E-05 -8.822362E-03 -7.783407E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.372903E-02 -5.630669E-04 -0.000000E+00 -0.000000E+00 -1.451080E-02 -2.105632E-04 -1.209842E-02 -1.463717E-04 -0.000000E+00 -0.000000E+00 -8.128789E-03 -6.607721E-05 -1.699068E-02 -1.455906E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.131766E-02 -1.280895E-04 -9.142882E-03 -8.359228E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.546445E-02 -1.579151E-04 -2.235882E-02 -4.999168E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.163445E-02 -1.000739E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.679579E-02 -2.820984E-04 -1.653088E-03 -2.732699E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.839123E-03 -6.145185E-05 -1.306490E-02 -1.706917E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.925889E-02 -3.709049E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.441919E-03 -1.973064E-05 -0.000000E+00 -0.000000E+00 -1.696490E-03 -2.878077E-06 -1.188102E-02 -1.411586E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.647024E-02 -2.712688E-04 -1.447624E-02 -2.095615E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.027115E-02 -4.109196E-04 -0.000000E+00 -0.000000E+00 -1.220227E-02 -8.388744E-05 -1.513623E-02 -2.291055E-04 -0.000000E+00 -0.000000E+00 -4.693765E-03 -2.203143E-05 -2.309598E-02 -5.334242E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.896430E-03 -3.596447E-06 -1.797193E-02 -3.229902E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.165452E-03 -1.735099E-05 -3.978577E-02 -8.171648E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.623932E-03 -6.885018E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.186038E-02 -4.778760E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.227784E-02 -4.963022E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.485032E-03 -5.602571E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.532875E-02 -6.415453E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.624400E-02 -2.638675E-04 -0.000000E+00 -0.000000E+00 -2.205166E-02 -4.862755E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.741186E-02 -3.031728E-04 -1.866250E-02 -1.752786E-04 -3.291961E-03 -1.083700E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.776803E-03 -1.426424E-05 -9.793825E-03 -9.591902E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.534928E-03 -1.249572E-05 -2.004150E-02 -4.016618E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.138556E-03 -4.573422E-06 -2.536426E-02 -6.433459E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.229453E-02 -1.511554E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.438471E-02 -5.946143E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.320156E-03 -5.383124E-06 -2.309308E-02 -5.332904E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.027115E-02 -4.109196E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.335984E-02 -5.456821E-04 -5.005121E-05 -2.505124E-09 -0.000000E+00 -0.000000E+00 -5.766274E-03 -3.324992E-05 -2.202347E-02 -4.850332E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.190054E-02 -4.796338E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.664785E-02 -5.186916E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.560194E-03 -3.091576E-05 -5.012432E-03 -2.512448E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.078818E-03 -1.663676E-05 -1.512098E-02 -2.286441E-04 -0.000000E+00 -0.000000E+00 -1.114343E-02 -1.241761E-04 -1.375834E-02 -1.892919E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.128775E-02 -1.274133E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.512973E-03 -2.289086E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.099115E-02 -4.406282E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.181004E-02 -1.394771E-04 -1.200573E-02 -1.441375E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.737885E-03 -7.496015E-06 -0.000000E+00 -0.000000E+00 -2.582846E-02 -6.671093E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.669493E-02 -7.126192E-04 -1.193971E-02 -9.099511E-05 -9.937766E-03 -9.875918E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.044477E-02 -1.090932E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.437034E-02 -2.065067E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.337119E-02 -5.462125E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.140183E-03 -3.770184E-05 diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test.py b/tests/regression_tests/unstructured_mesh/source_sampling/test.py deleted file mode 100644 index d6f16315a..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test.py +++ /dev/null @@ -1,121 +0,0 @@ -from itertools import product -from pathlib import Path - -import pytest -import numpy as np -import openmc -import openmc.lib - -from tests import cdtemp -from tests.testing_harness import PyAPITestHarness - - -TETS_PER_VOXEL = 12 - -# This test uses a geometry file with cells that match a regular mesh. Each cell -# in the geometry corresponds to 12 tetrahedra in the unstructured mesh file. -@pytest.fixture -def model(): - openmc.reset_auto_ids() - - ### Materials ### - materials = openmc.Materials() - - water_mat = openmc.Material(name="water") - water_mat.add_nuclide("H1", 2.0) - water_mat.add_nuclide("O16", 1.0) - water_mat.set_density("atom/b-cm", 0.07416) - materials.append(water_mat) - - ### Geometry ### - # create a regular mesh that matches the superimposed mesh - regular_mesh = openmc.RegularMesh(mesh_id=10) - regular_mesh.lower_left = (-10, -10, -10) - regular_mesh.dimension = (10, 10, 10) - regular_mesh.width = (2, 2, 2) - - root_cell, _ = regular_mesh.build_cells(bc=['vacuum']*6) - - geometry = openmc.Geometry([root_cell]) - - ### Tallies ### - - # create a mesh flux tally - tally = openmc.Tally() - tally.filters.append(openmc.MeshFilter(regular_mesh)) - tally.scores = ['flux'] - tallies = openmc.Tallies([tally]) - - ### Settings ### - settings = openmc.Settings() - settings.run_mode = 'fixed source' - settings.particles = 100 - settings.batches = 2 - - mesh_filename = "test_mesh_tets.e" - uscd_mesh = openmc.UnstructuredMesh(mesh_filename, 'libmesh') - - # subtract one to account for root cell - n_cells = len(geometry.get_all_cells()) - 1 - - # set source weights manually so the C++ that checks the - # size of the array is executed - vol_norm = False - strengths = np.zeros(n_cells*TETS_PER_VOXEL) - # set non-zero strengths only for the tets corresponding to the - # first two geometric hex cells - strengths[:TETS_PER_VOXEL] = 10 - - strengths[TETS_PER_VOXEL:2*TETS_PER_VOXEL] = 2 - - # create the spatial distribution based on the mesh - space = openmc.stats.MeshSpatial(uscd_mesh, strengths, vol_norm) - - energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0]) - source = openmc.Source(space=space, energy=energy) - settings.source = source - return openmc.model.Model(geometry=geometry, - materials=materials, - settings=settings, - tallies=tallies) - - -test_cases = [ - {'library': lib, 'inputs_true': f'inputs_true{i}.dat'} - for i, lib in enumerate(('libmesh', 'moab')) -] - - -@pytest.mark.parametrize("test_cases", test_cases, ids=lambda p: p['library']) -def test_unstructured_mesh_sampling(model, test_cases): - # skip the test if the library is not enabled - if test_cases['library'] == 'moab' and not openmc.lib._dagmc_enabled(): - pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") - - if test_cases['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): - pytest.skip("LibMesh is not enabled in this build.") - - model.settings.source[0].space.mesh.library = test_cases['library'] - - harness = PyAPITestHarness('statepoint.2.h5', model, test_cases['inputs_true']) - harness.main() - - -def test_strengths_size_failure(request, model): - mesh_source = model.settings.source[0] - - # skip the test if unstructured mesh is not available - if not openmc.lib._libmesh_enabled(): - if openmc.lib._dagmc_enabled(): - mesh_source.space.mesh.library = 'moab' - else: - pytest.skip("Unstructured mesh support unavailable.") - - # make sure that an incorrrectly sized strengths array causes a failure - mesh_source.space.strengths = mesh_source.space.strengths[:-1] - - mesh_filename = Path(request.fspath).parent / mesh_source.space.mesh.filename - - with pytest.raises(RuntimeError, match=r'strengths array'), cdtemp([mesh_filename]): - model.export_to_xml() - openmc.run() diff --git a/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e b/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e deleted file mode 120000 index 0aa0d1a23..000000000 --- a/tests/regression_tests/unstructured_mesh/source_sampling/test_mesh_tets.e +++ /dev/null @@ -1 +0,0 @@ -../test_mesh_tets.e \ No newline at end of file From 368525f3db2503af4e48bdcbd9841f9d07af4d31 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 22 Jan 2023 10:07:18 -0500 Subject: [PATCH 1515/2654] multipole documentation typo fix --- openmc/data/multipole.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/data/multipole.py b/openmc/data/multipole.py index 0be70cdba..642f2cb43 100644 --- a/openmc/data/multipole.py +++ b/openmc/data/multipole.py @@ -1154,8 +1154,8 @@ class WindowedMultipole(EqualityMixin): Returns ------- 3-tuple of Real - Total, absorption, and fission microscopic cross sections at the - given energy and temperature. + Scattering, absorption, and fission microscopic cross sections + at the given energy and temperature. """ @@ -1248,8 +1248,8 @@ class WindowedMultipole(EqualityMixin): Returns ------- 3-tuple of Real or 3-tuple of numpy.ndarray - Total, absorption, and fission microscopic cross sections at the - given energy and temperature. + Scattering, absorption, and fission microscopic cross sections + at the given energy and temperature. """ From afbbc3d8457854114fb75d73e884251c8522e410 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 24 Jan 2023 23:00:27 -0500 Subject: [PATCH 1516/2654] try to constrain triangulation --- openmc/model/surface_composite.py | 54 +++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 002fad9d9..e44b81ac4 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -670,10 +670,11 @@ class Polygon(CompositeSurface): check_length('points', points, 3) # Order the points counter-clockwise (necessary for offset method) - self._points = self._make_ccw(points) + points = self._make_ccw(points) - # Create a triangulation of the points. - self._tri = Delaunay(self._points, qhull_options='QJ') + # Create a constrained triangulation of the points. + # The constrained triangulation is set to _tri attribute + self._constrain_triangulation(points) # Decompose the polygon into groups of simplices forming convex subsets # and get the sets of (surface, operator) pairs defining the polygon @@ -723,7 +724,7 @@ class Polygon(CompositeSurface): @property def points(self): - return self._points + return self._tri.points @property def basis(self): @@ -738,7 +739,7 @@ class Polygon(CompositeSurface): # Get the unit vectors that point from one point in the polygon to the # next given that they are ordered counterclockwise and that the final # point is connected to the first point - tangents = np.diff(self._points, axis=0, append=[self._points[0, :]]) + tangents = np.diff(self.points, axis=0, append=[self.points[0, :]]) tangents /= np.linalg.norm(tangents, axis=-1, keepdims=True) # Rotate the tangent vectors clockwise by 90 degrees, which for a # counter-clockwise ordered polygon will produce the outward normal @@ -783,6 +784,41 @@ class Polygon(CompositeSurface): return points[::-1, :] + def _constrain_triangulation(self, points): + """Generate a constrained triangulation. + + Parameters + ---------- + points : np.ndarray (Nx2) + An Nx2 array of coordinate pairs describing the vertices. These + points represent a planar straight line graph. + + Returns + ------- + None + """ + + tri = Delaunay(points, qhull_options='QJ') + # Loop through the boundary edges of the polygon. If an edge is not + # included in the triangulation, break it into two line segments. + n = len(points) + new_pts = [] + for i, j in zip(range(n), range(1, n +1)): + # If both vertices of any edge are not found in any simplex, insert + # a new point between them + if not any([i in s and j % n in s for s in tri.simplices]): + newpt = (points[i, :] + points[j % n, :]) / 2 + new_pts.append((j, newpt)) + + # If all the edges are included in the triangulation set it, otherwise + # try again with additional points inserted on offending edges + if not new_pts: + self._tri = tri + else: + for i, pt in new_pts[::-1]: + points = np.insert(points, i, pt, axis=0) + self._constrain_triangulation(points) + def _group_simplices(self, neighbor_map, group=None): """Generate a convex grouping of simplices. @@ -819,7 +855,7 @@ class Polygon(CompositeSurface): continue test_group = group + [n] test_point_idx = np.unique(self._tri.simplices[test_group, :]) - test_points = self._tri.points[test_point_idx] + test_points = self.points[test_point_idx] # If test_points are convex keep adding to this group if len(test_points) == len(ConvexHull(test_points).vertices): group = self._group_simplices(neighbor_map, group=test_group) @@ -902,8 +938,8 @@ class Polygon(CompositeSurface): # Get centroids of all the simplices and determine if they are inside # the polygon defined by input vertices or not. - centroids = np.mean(self._points[self._tri.simplices], axis=1) - in_polygon = Path(self._points).contains_points(centroids) + centroids = np.mean(self.points[self._tri.simplices], axis=1) + in_polygon = Path(self.points).contains_points(centroids) self._in_polygon = in_polygon # Build a map with keys of simplex indices inside the polygon whose @@ -931,7 +967,7 @@ class Polygon(CompositeSurface): # generate the convex hull and find the resulting surfaces and # unary operators that represent this convex subset of the polygon. idx = np.unique(self._tri.simplices[group, :]) - qhull = ConvexHull(self._tri.points[idx, :]) + qhull = ConvexHull(self.points[idx, :]) surf_ops = self._get_convex_hull_surfs(qhull) surfsets.append(surf_ops) return surfsets From 4fade673a74681e51e0ed198ac0f4f7bcd24fc26 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Wed, 25 Jan 2023 16:27:12 -0500 Subject: [PATCH 1517/2654] refactor to single validate_points method --- openmc/model/surface_composite.py | 63 +++++++++++++++++++------------ 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index e44b81ac4..04e0c4d80 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -659,22 +659,10 @@ class Polygon(CompositeSurface): def __init__(self, points, basis='rz'): check_value('basis', basis, ('xy', 'yz', 'xz', 'rz')) self._basis = basis - points = np.asarray(points, dtype=float) - check_iterable_type('points', points, float, min_depth=2, max_depth=2) - check_length('points', points[0, :], 2, 2) - # If the last point is the same as the first, remove it and make sure - # there are still at least 3 points for a valid polygon. - if np.allclose(points[0, :], points[-1, :]): - points = points[:-1, :] - check_length('points', points, 3) - - # Order the points counter-clockwise (necessary for offset method) - points = self._make_ccw(points) - - # Create a constrained triangulation of the points. - # The constrained triangulation is set to _tri attribute - self._constrain_triangulation(points) + # Create a constrained triangulation of the validated points. + # The constrained triangulation is set to the _tri attribute + self._constrain_triangulation(self._validate_points(points)) # Decompose the polygon into groups of simplices forming convex subsets # and get the sets of (surface, operator) pairs defining the polygon @@ -762,8 +750,9 @@ class Polygon(CompositeSurface): def region(self): return self._region - def _make_ccw(self, points): - """Order a set of points counter-clockwise. + def _validate_points(self, points): + """Ensure the closed path defined by points does not intersect and is + oriented counter-clockwise. Parameters ---------- @@ -774,18 +763,40 @@ class Polygon(CompositeSurface): ------- ordered_points : the input points ordered counter-clockwise """ + points = np.asarray(points, dtype=float) + check_iterable_type('points', points, float, min_depth=2, max_depth=2) + check_length('points', points[0, :], 2, 2) + + # If the last point is the same as the first, remove it and make sure + # there are still at least 3 points for a valid polygon. + if np.allclose(points[0, :], points[-1, :]): + points = points[:-1, :] + check_length('points', points, 3) + + # Check if polygon is self-intersecting by comparing edges pairwise + n = len(points) + is_self_intersecting = False + for i in range(n): + p1x, p1y = points[i, :] + p2x, p2y = points[(i + 1) % n, :] + for j in range(i, n): + p3x, p3y = points[j, :] + p4x, p4y = points[(j + 1) % n, :] + + + # Order the points counter-clockwise (necessary for offset method) # Calculates twice the signed area of the polygon using the "Shoelace # Formula" https://en.wikipedia.org/wiki/Shoelace_formula - xpts, ypts = points.T - # If signed area is positive the curve is oriented counter-clockwise + xpts, ypts = points.T if np.sum(ypts*(np.roll(xpts, 1) - np.roll(xpts, -1))) > 0: return points return points[::-1, :] - def _constrain_triangulation(self, points): - """Generate a constrained triangulation. + def _constrain_triangulation(self, points, depth=0): + """Generate a constrained triangulation by ensuring all edges of the + Polygon are contained within the simplices. Parameters ---------- @@ -797,6 +808,10 @@ class Polygon(CompositeSurface): ------- None """ + # Only attempt the triangulation up to 3 times. + if depth > 2: + raise RuntimeError('Could not create a valid triangulation after 3' + ' attempts') tri = Delaunay(points, qhull_options='QJ') # Loop through the boundary edges of the polygon. If an edge is not @@ -805,19 +820,19 @@ class Polygon(CompositeSurface): new_pts = [] for i, j in zip(range(n), range(1, n +1)): # If both vertices of any edge are not found in any simplex, insert - # a new point between them + # a new point between them. if not any([i in s and j % n in s for s in tri.simplices]): newpt = (points[i, :] + points[j % n, :]) / 2 new_pts.append((j, newpt)) # If all the edges are included in the triangulation set it, otherwise - # try again with additional points inserted on offending edges + # try again with additional points inserted on offending edges. if not new_pts: self._tri = tri else: for i, pt in new_pts[::-1]: points = np.insert(points, i, pt, axis=0) - self._constrain_triangulation(points) + self._constrain_triangulation(points, depth=depth + 1) def _group_simplices(self, neighbor_map, group=None): """Generate a convex grouping of simplices. From 396ecdf02cb13eed34940c84606f4d8d890790b7 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Thu, 26 Jan 2023 13:55:22 -0500 Subject: [PATCH 1518/2654] added test that cathces the bug --- tests/unit_tests/test_mesh.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/unit_tests/test_mesh.py diff --git a/tests/unit_tests/test_mesh.py b/tests/unit_tests/test_mesh.py new file mode 100644 index 000000000..08dd65e33 --- /dev/null +++ b/tests/unit_tests/test_mesh.py @@ -0,0 +1,9 @@ +import openmc +import pytest + +def test_raises_error_when_flat(): + with pytest.raises(ValueError): + mesh = openmc.RegularMesh() + mesh.dimension = [50, 50, 1] + mesh.lower_left = [-25, -25, 0] + mesh.upper_right = [25, 25, 0] \ No newline at end of file From 91ebcdb21e80174bba37a6284c73a8972be0e114 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Thu, 26 Jan 2023 14:05:23 -0500 Subject: [PATCH 1519/2654] better test --- tests/unit_tests/test_mesh.py | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tests/unit_tests/test_mesh.py b/tests/unit_tests/test_mesh.py index 08dd65e33..129e8e21b 100644 --- a/tests/unit_tests/test_mesh.py +++ b/tests/unit_tests/test_mesh.py @@ -1,9 +1,34 @@ import openmc import pytest -def test_raises_error_when_flat(): +@pytest.mark.parametrize("val_left,val_right", [(0, 0), (-1., -1.), (2.0, 2)]) +def test_raises_error_when_flat(val_left, val_right): + """Checks that an error is raised when a mesh is flat""" + mesh = openmc.RegularMesh() + + # Same X with pytest.raises(ValueError): - mesh = openmc.RegularMesh() - mesh.dimension = [50, 50, 1] - mesh.lower_left = [-25, -25, 0] - mesh.upper_right = [25, 25, 0] \ No newline at end of file + mesh.lower_left = [val_left, -25, -25] + mesh.upper_right = [val_right, 25, 25] + + with pytest.raises(ValueError): + mesh.upper_right = [val_right, 25, 25] + mesh.lower_left = [val_left, -25, -25] + + # Same Y + with pytest.raises(ValueError): + mesh.lower_left = [-25, val_left, -25] + mesh.upper_right = [25, val_right, 25] + + with pytest.raises(ValueError): + mesh.upper_right = [25, val_right, 25] + mesh.lower_left = [-25, val_left, -25] + + # Same Z + with pytest.raises(ValueError): + mesh.lower_left = [-25, -25, val_left] + mesh.upper_right = [25, 25, val_right] + + with pytest.raises(ValueError): + mesh.upper_right = [25, 25, val_right] + mesh.lower_left = [-25, -25, val_left] From a9767035561f347053ac0e89b4a2be56233b88dc Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Thu, 26 Jan 2023 14:06:48 -0500 Subject: [PATCH 1520/2654] Raise error if mesh is flat --- openmc/mesh.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 157e78263..962751f9b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -433,6 +433,9 @@ class RegularMesh(StructuredMesh): cv.check_length('mesh lower_left', lower_left, 1, 3) self._lower_left = lower_left + if self.is_flat(): + raise ValueError("mesh cannot be flat") + @upper_right.setter def upper_right(self, upper_right): cv.check_type('mesh upper_right', upper_right, Iterable, Real) @@ -442,6 +445,9 @@ class RegularMesh(StructuredMesh): if self._width is not None: self._width = None warnings.warn("Unsetting width attribute.") + + if self.is_flat(): + raise ValueError("mesh cannot be flat") @width.setter def width(self, width): @@ -786,6 +792,16 @@ class RegularMesh(StructuredMesh): volume_normalization=volume_normalization ) + def is_flat(self): + """Returns True if the mesh is flat + """ + if None in [self.lower_left, self.upper_right]: + return False + + for val1, val2 in zip(self.lower_left, self.upper_right): + if val1 == val2: + return True + def Mesh(*args, **kwargs): warnings.warn("Mesh has been renamed RegularMesh. Future versions of " "OpenMC will not accept the name Mesh.") From 11eee756dd953d2490fa8b2975341e7f64328f79 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 26 Jan 2023 14:13:39 -0600 Subject: [PATCH 1521/2654] Corrections to application of origin for sphere and cyl mesh --- include/openmc/mesh.h | 3 +-- src/mesh.cpp | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index c690dc4fe..9554a5143 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -241,6 +241,7 @@ public: xt::xtensor lower_left_; //!< Lower-left coordinates of mesh xt::xtensor upper_right_; //!< Upper-right coordinates of mesh std::array shape_; //!< Number of mesh elements in each dimension + Position origin_ {0.0, 0.0, 0.0}; protected: }; @@ -359,7 +360,6 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - Position origin_; int set_grid(); @@ -414,7 +414,6 @@ public: void to_hdf5(hid_t group) const override; array, 3> grid_; - Position origin_; int set_grid(); diff --git a/src/mesh.cpp b/src/mesh.cpp index 82644db08..e0fa305ed 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -412,7 +412,6 @@ template void StructuredMesh::raytrace_mesh( Position r0, Position r1, const Direction& u, T tally) const { - // TODO: when c++-17 is available, use "if constexpr ()" to compile-time // enable/disable tally calls for now, T template type needs to provide both // surface and track methods, which might be empty. modern optimizing @@ -445,6 +444,11 @@ void StructuredMesh::raytrace_mesh( return; } + // translate start and end positions, + // this needs to come after the get_indices call because it does its own translation + r0 -= origin_; + r1 -= origin_; + // Calculate initial distances to next surfaces in all three dimensions std::array distances; for (int k = 0; k < n; ++k) { @@ -972,13 +976,12 @@ std::string CylindricalMesh::get_mesh_type() const StructuredMesh::MeshIndex CylindricalMesh::get_indices( Position r, bool& in_mesh) const { - Position mapped_r; + r -= origin_; + Position mapped_r; mapped_r[0] = std::hypot(r.x, r.y); mapped_r[2] = r[2]; - mapped_r -= origin_; - if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; } else { @@ -1090,22 +1093,23 @@ StructuredMesh::MeshDistance CylindricalMesh::distance_to_grid_boundary( const MeshIndex& ijk, int i, const Position& r0, const Direction& u, double l) const { + Position r = r0 - origin_; if (i == 0) { return std::min( - MeshDistance(ijk[i] + 1, true, find_r_crossing(r0, u, l, ijk[i])), - MeshDistance(ijk[i] - 1, false, find_r_crossing(r0, u, l, ijk[i] - 1))); + MeshDistance(ijk[i] + 1, true, find_r_crossing(r, u, l, ijk[i])), + MeshDistance(ijk[i] - 1, false, find_r_crossing(r, u, l, ijk[i] - 1))); } else if (i == 1) { return std::min(MeshDistance(sanitize_phi(ijk[i] + 1), true, - find_phi_crossing(r0, u, l, ijk[i])), + find_phi_crossing(r, u, l, ijk[i])), MeshDistance(sanitize_phi(ijk[i] - 1), false, - find_phi_crossing(r0, u, l, ijk[i] - 1))); + find_phi_crossing(r, u, l, ijk[i] - 1))); } else { - return find_z_crossing(r0, u, l, ijk[i]); + return find_z_crossing(r, u, l, ijk[i]); } } @@ -1209,12 +1213,11 @@ std::string SphericalMesh::get_mesh_type() const StructuredMesh::MeshIndex SphericalMesh::get_indices( Position r, bool& in_mesh) const { + r -= origin_; + Position mapped_r; - mapped_r[0] = r.norm(); - mapped_r -= origin_; - if (mapped_r[0] < FP_PRECISION) { mapped_r[1] = 0.0; mapped_r[2] = 0.0; From b22c7e8353781552d1cedddd05b83ad2543c5714 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 26 Jan 2023 14:14:06 -0600 Subject: [PATCH 1522/2654] Adding test cases for cylindrical mesh --- tests/unit_tests/test_cylindrical_mesh.py | 88 ++++++++++++++++++++--- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index 952e8cf5a..e67f21b15 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -1,16 +1,42 @@ +from itertools import product, permutations + import openmc import numpy as np -def test_origin_read_write_to_xml(): - """Tests that the origin attribute can be written and read back to XML - """ +import pytest + +geom_size = 5 + +@pytest.fixture() +def model(): + openmc.reset_auto_ids() + + water = openmc.Material(name='water') + water.add_element('H', 2.0) + water.add_element('O', 1.0) + water.set_density('g/cc', 1.0) + + rpp = openmc.model.RectangularParallelepiped(*([-geom_size, geom_size] * 3), + boundary_type='vacuum') + + cell = openmc.Cell(region=-rpp, fill=water) + + geom = openmc.Geometry([cell]) + + source = openmc.Source() + source.space = openmc.stats.Point() + source.energy = openmc.stats.Discrete([10000], [1.0]) + + settings = openmc.Settings() + settings.particles = 1000 + settings.batches = 10 + settings.run_mode = 'fixed source' + # build mesh = openmc.CylindricalMesh() - mesh.phi_grid = [1, 2, 3] - mesh.z_grid = [1, 2, 3] - mesh.r_grid = [1, 2, 3] - - mesh.origin = [0.1, 0.2, 0.3] + mesh.phi_grid = np.linspace(0, 2*np.pi, 21) + mesh.z_grid = np.linspace(-geom_size, geom_size, 11) + mesh.r_grid = np.linspace(0, geom_size, geom_size) tally = openmc.Tally() @@ -21,10 +47,52 @@ def test_origin_read_write_to_xml(): tallies = openmc.Tallies([tally]) - tallies.export_to_xml() + return openmc.Model(geometry=geom, settings=settings, tallies=tallies) + +def test_origin_read_write_to_xml(run_in_tmpdir, model): + """Tests that the origin attribute can be written and read back to XML + """ + mesh = model.tallies[0].filters[0].mesh + mesh.origin = [0.1, 0.2, 0.3] + model.tallies.export_to_xml() # read back new_tallies = openmc.Tallies.from_xml() new_tally = new_tallies[0] new_mesh = new_tally.filters[0].mesh - assert np.allclose(new_mesh.origin, mesh.origin) \ No newline at end of file + np.testing.assert_equal(new_mesh.origin, mesh.origin) + +estimators = ('tracklength', 'collision') +origins = permutations([-geom_size, 0, 0]) + +test_cases = product(estimators, origins) + +def label(p): + if isinstance(p, tuple): + return f'origin:{p}' + if isinstance(p, str): + return f'estimator:{p}' + +@pytest.mark.parametrize('estimator,origin', test_cases, ids=label) +def test_offset_mesh(model, estimator, origin): + """Tests that the mesh has been moved based on tally results + """ + mesh = model.tallies[0].filters[0].mesh + model.tallies[0].estimator = estimator + # move the center of the cylinder mesh upwards + mesh.origin = origin + + sp_filename = model.run() + + with openmc.StatePoint(sp_filename) as sp: + tally = sp.tallies[1] + + # we've translated half of the cylinder mesh above the model, + # so ensure that half of the bins are populated + assert np.count_nonzero(tally.mean) == tally.mean.size / 2 + + # check that the lower half of the mesh contains a tally result + # and that the upper half is zero + mean = tally.mean.reshape(mesh.dimension[::-1]).T + # assert np.count_nonzero(mean[:, :, :5]) == mean.size / 2 + # assert np.count_nonzero(mean[:, :, 5:]) == 0 From 3703fdbdd746675203e1c5477a29b521cdb9a827 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 26 Jan 2023 14:15:08 -0600 Subject: [PATCH 1523/2654] Adding origin to sphere and cyl mesh str --- openmc/mesh.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 307d9d952..47d34ebe2 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1119,6 +1119,7 @@ class CylindricalMesh(StructuredMesh): fmt = '{0: <16}{1}{2}\n' string = super().__repr__() string += fmt.format('\tDimensions', '=\t', self.n_dimension) + string += fmt.format('\tOrigin', '=\t', self.origin) r_grid_str = str(self._r_grid) if self._r_grid is None else len(self._r_grid) string += fmt.format('\tN R pnts:', '=\t', r_grid_str) if self._r_grid is not None: @@ -1445,6 +1446,7 @@ class SphericalMesh(StructuredMesh): fmt = '{0: <16}{1}{2}\n' string = super().__repr__() string += fmt.format('\tDimensions', '=\t', self.n_dimension) + string += fmt.format('\tOrigin', '=\t', self.origin) r_grid_str = str(self._r_grid) if self._r_grid is None else len(self._r_grid) string += fmt.format('\tN R pnts:', '=\t', r_grid_str) if self._r_grid is not None: From ba1cd67d52425820d318d618faf9d5bf06f62e95 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 27 Jan 2023 08:32:02 -0500 Subject: [PATCH 1524/2654] added test to catch bug + fix --- openmc/mesh.py | 2 +- tests/unit_tests/test_mesh.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 962751f9b..3cdfc87f3 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -795,7 +795,7 @@ class RegularMesh(StructuredMesh): def is_flat(self): """Returns True if the mesh is flat """ - if None in [self.lower_left, self.upper_right]: + if self.lower_left is None or self.upper_right is None: return False for val1, val2 in zip(self.lower_left, self.upper_right): diff --git a/tests/unit_tests/test_mesh.py b/tests/unit_tests/test_mesh.py index 129e8e21b..8bc00a276 100644 --- a/tests/unit_tests/test_mesh.py +++ b/tests/unit_tests/test_mesh.py @@ -1,5 +1,6 @@ import openmc import pytest +import numpy as np @pytest.mark.parametrize("val_left,val_right", [(0, 0), (-1., -1.), (2.0, 2)]) def test_raises_error_when_flat(val_left, val_right): @@ -32,3 +33,25 @@ def test_raises_error_when_flat(val_left, val_right): with pytest.raises(ValueError): mesh.upper_right = [25, 25, val_right] mesh.lower_left = [-25, -25, val_left] + + +def test_corner_none_returns_false(): + """Checks mesh is not considered flat when one + corner is None + """ + mesh = openmc.RegularMesh() + mesh.lower_left = [-25, -25, -25] + assert not mesh.is_flat() + + mesh = openmc.RegularMesh() + mesh.upper_right = [-25, -25, -25] + assert not mesh.is_flat() + + # test with np array + mesh = openmc.RegularMesh() + mesh.lower_left = np.array([-25, -25, -25]) + assert not mesh.is_flat() + + mesh = openmc.RegularMesh() + mesh.upper_right = np.array([-25, -25, -25]) + assert not mesh.is_flat() \ No newline at end of file From c84336878bdfb38c261094205ab5360949d6743d Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 27 Jan 2023 08:58:10 -0500 Subject: [PATCH 1525/2654] replace is_flat by a one-line check --- openmc/mesh.py | 18 ++++-------------- tests/unit_tests/test_mesh.py | 22 ---------------------- 2 files changed, 4 insertions(+), 36 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 3cdfc87f3..60c5ade40 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -433,8 +433,8 @@ class RegularMesh(StructuredMesh): cv.check_length('mesh lower_left', lower_left, 1, 3) self._lower_left = lower_left - if self.is_flat(): - raise ValueError("mesh cannot be flat") + if self.upper_right is not None and any(np.isclose(self.upper_right, lower_left)): + raise ValueError("mesh cannot have zero thickness is any dimension") @upper_right.setter def upper_right(self, upper_right): @@ -446,8 +446,8 @@ class RegularMesh(StructuredMesh): self._width = None warnings.warn("Unsetting width attribute.") - if self.is_flat(): - raise ValueError("mesh cannot be flat") + if self.lower_left is not None and any(np.isclose(self.lower_left, upper_right)): + raise ValueError("mesh cannot have zero thickness is any dimension") @width.setter def width(self, width): @@ -792,16 +792,6 @@ class RegularMesh(StructuredMesh): volume_normalization=volume_normalization ) - def is_flat(self): - """Returns True if the mesh is flat - """ - if self.lower_left is None or self.upper_right is None: - return False - - for val1, val2 in zip(self.lower_left, self.upper_right): - if val1 == val2: - return True - def Mesh(*args, **kwargs): warnings.warn("Mesh has been renamed RegularMesh. Future versions of " "OpenMC will not accept the name Mesh.") diff --git a/tests/unit_tests/test_mesh.py b/tests/unit_tests/test_mesh.py index 8bc00a276..0f9b96b0b 100644 --- a/tests/unit_tests/test_mesh.py +++ b/tests/unit_tests/test_mesh.py @@ -33,25 +33,3 @@ def test_raises_error_when_flat(val_left, val_right): with pytest.raises(ValueError): mesh.upper_right = [25, 25, val_right] mesh.lower_left = [-25, -25, val_left] - - -def test_corner_none_returns_false(): - """Checks mesh is not considered flat when one - corner is None - """ - mesh = openmc.RegularMesh() - mesh.lower_left = [-25, -25, -25] - assert not mesh.is_flat() - - mesh = openmc.RegularMesh() - mesh.upper_right = [-25, -25, -25] - assert not mesh.is_flat() - - # test with np array - mesh = openmc.RegularMesh() - mesh.lower_left = np.array([-25, -25, -25]) - assert not mesh.is_flat() - - mesh = openmc.RegularMesh() - mesh.upper_right = np.array([-25, -25, -25]) - assert not mesh.is_flat() \ No newline at end of file From 2dbb0c7523c535f8a3f202609ad820cef54556c0 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 27 Jan 2023 14:26:56 +0000 Subject: [PATCH 1526/2654] allowing materials.xml to be specified --- openmc/deplete/results.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 9552a6ba6..b8b383a0e 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -375,7 +375,8 @@ class Results(list): def export_to_materials( self, burnup_index: int, - nuc_with_data: Optional[Iterable[str]] = None + nuc_with_data: Optional[Iterable[str]] = None, + path: PathLike = 'materials.xml' ) -> Materials: """Return openmc.Materials object based on results at a given step @@ -394,6 +395,8 @@ class Results(list): If not provided, nuclides from the cross_sections element of materials.xml will be used. If that element is not present, nuclides from openmc.config['cross_sections'] will be used. + path : PathLike + Path to file to write. Defaults to 'materials.xml'. Returns ------- @@ -407,7 +410,7 @@ class Results(list): # updated. If for some reason you have modified OpenMC to produce # new materials as depletion takes place, this method will not # work as expected and leave out that material. - mat_file = Materials.from_xml("materials.xml") + mat_file = Materials.from_xml(path) # Only nuclides with valid transport data will be written to # the new materials XML file. The precedence of nuclides to select From ec5f0e54f4e764dd5a5cb52e8cd5d8e725856abd Mon Sep 17 00:00:00 2001 From: Patrick A Myers Date: Fri, 27 Jan 2023 10:22:27 -0500 Subject: [PATCH 1527/2654] Restored init_alias and changed constructor definitions --- include/openmc/distribution.h | 2 +- src/distribution.cpp | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 8563ee031..4fc0db2e0 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -60,7 +60,7 @@ private: void normalize(); //! Initialize alias tables for distribution - void init_alias(); + void init_alias(vector& x, vector& p); }; //============================================================================== diff --git a/src/distribution.cpp b/src/distribution.cpp index 50913dfe4..4b4ebd69d 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -27,20 +27,27 @@ Discrete::Discrete(pugi::xml_node node) auto params = get_node_array(node, "parameters"); std::size_t n = params.size(); - double x[n / 2], p[n / 2]; + std::vector x_vec(params.begin(), params.begin() + n / 2); + std::vector p_vec(params.begin() + n / 2, params.end()); - std::copy(params.begin(), params.begin() + n / 2, x); - std::copy(params.begin() + n / 2, params.end(), p); - - new (this) Discrete(x, p, n / 2); + this->init_alias(x_vec, p_vec); } Discrete::Discrete(const double* x, const double* p, int n) - : x_ {x, x + n}, prob_ {p, p + n} { + std::vector x_vec(x, x + n); + std::vector p_vec(p, p + n); + + this->init_alias(x_vec, p_vec); +} + +void Discrete::init_alias(vector& x, vector& p) +{ + x_ = x; + prob_ = p; normalize(); - // The initialization and sampling method is base on Vose + // The initialization and sampling method is based on Vose // (DOI: 10.1109/32.92917) // Vectors for large and small probabilities based on 1/n vector large; From ca1f9a69654b5c0bc99afa58efb801b7bea5988f Mon Sep 17 00:00:00 2001 From: Patrick A Myers Date: Fri, 27 Jan 2023 11:31:37 -0500 Subject: [PATCH 1528/2654] updated test for counter --- tests/cpp_unit_tests/test_distribution.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/cpp_unit_tests/test_distribution.cpp b/tests/cpp_unit_tests/test_distribution.cpp index a5166fb25..e1a212db5 100644 --- a/tests/cpp_unit_tests/test_distribution.cpp +++ b/tests/cpp_unit_tests/test_distribution.cpp @@ -1,7 +1,8 @@ #include "openmc/distribution.h" #include "openmc/random_lcg.h" #include -#include +#include +#include #include TEST_CASE("Test alias method sampling of a discrete distribution") @@ -42,9 +43,10 @@ TEST_CASE("Test alias method sampling of a discrete distribution") // expected mean REQUIRE(std::abs(dist_mean - mean) < 4 * std); - // Require counter of number of x[0] is within 4 standard deviations of - // 200,000 - REQUIRE(std::abs(counter - n_samples * p[0]) < 4 * std); + // Require counter of number of x[0] is within the 95% confidence interval + // assuming a Poisson distribution of 200,000 + REQUIRE(std::abs((double)counter / n_samples - p[0]) < + 1.96 * std::sqrt(p[0] / n_samples)); } TEST_CASE("Test alias sampling method for pugixml constructor") @@ -72,7 +74,8 @@ TEST_CASE("Test alias sampling method for pugixml constructor") for (size_t i = 0; i < 3; i++) { REQUIRE(dist.x()[i] == correct_x[i]); - REQUIRE(dist.prob()[i] == Catch::Approx(correct_prob[i]).epsilon(1e-12)); + REQUIRE_THAT( + dist.prob()[i], Catch::Matchers::WithinAbs(correct_prob[i], 1e-12)); REQUIRE(dist.alias()[i] == correct_alias[i]); } } From 198b5bdad44557beaf8ed27b7bc5bac529252528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Sat, 28 Jan 2023 08:50:39 -0500 Subject: [PATCH 1529/2654] Update openmc/mesh.py Co-authored-by: Paul Romano --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 60c5ade40..84350afd3 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -434,7 +434,7 @@ class RegularMesh(StructuredMesh): self._lower_left = lower_left if self.upper_right is not None and any(np.isclose(self.upper_right, lower_left)): - raise ValueError("mesh cannot have zero thickness is any dimension") + raise ValueError("Mesh cannot have zero thickness in any dimension") @upper_right.setter def upper_right(self, upper_right): From a51d31ec78d6c9bebb99fb7b92a68ab145da56fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Sat, 28 Jan 2023 08:50:45 -0500 Subject: [PATCH 1530/2654] Update openmc/mesh.py Co-authored-by: Paul Romano --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 84350afd3..dda7257f4 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -447,7 +447,7 @@ class RegularMesh(StructuredMesh): warnings.warn("Unsetting width attribute.") if self.lower_left is not None and any(np.isclose(self.lower_left, upper_right)): - raise ValueError("mesh cannot have zero thickness is any dimension") + raise ValueError("Mesh cannot have zero thickness in any dimension") @width.setter def width(self, width): From 60f33d460736e3d22ed7eae633fd7a38cbd48984 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Sat, 28 Jan 2023 17:18:35 +0000 Subject: [PATCH 1531/2654] Review improvement from @paulromano --- openmc/deplete/results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index b8b383a0e..3602d6918 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -396,7 +396,7 @@ class Results(list): materials.xml will be used. If that element is not present, nuclides from openmc.config['cross_sections'] will be used. path : PathLike - Path to file to write. Defaults to 'materials.xml'. + Path to materials XML file to read. Defaults to 'materials.xml'. Returns ------- From dd60c1583f6fede09c8fed5029f0ce216c5a0f10 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sun, 29 Jan 2023 17:47:54 +0000 Subject: [PATCH 1532/2654] updated checkout action to v3 --- .github/workflows/ci.yml | 2 +- .github/workflows/dockerhub-publish-release-dagmc-libmesh.yml | 2 +- .github/workflows/dockerhub-publish-release-dagmc.yml | 2 +- .github/workflows/dockerhub-publish-release-libmesh.yml | 2 +- .github/workflows/dockerhub-publish-release.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 321f18874..2c2ab7004 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,7 +84,7 @@ jobs: LIBMESH: ${{ matrix.libmesh }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 diff --git a/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml b/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml index b8a152aef..3dd830a26 100644 --- a/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml +++ b/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml @@ -8,7 +8,7 @@ jobs: main: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set env run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - diff --git a/.github/workflows/dockerhub-publish-release-dagmc.yml b/.github/workflows/dockerhub-publish-release-dagmc.yml index 927e91212..d7cfff019 100644 --- a/.github/workflows/dockerhub-publish-release-dagmc.yml +++ b/.github/workflows/dockerhub-publish-release-dagmc.yml @@ -8,7 +8,7 @@ jobs: main: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set env run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - diff --git a/.github/workflows/dockerhub-publish-release-libmesh.yml b/.github/workflows/dockerhub-publish-release-libmesh.yml index 1907eef46..d2fdbc469 100644 --- a/.github/workflows/dockerhub-publish-release-libmesh.yml +++ b/.github/workflows/dockerhub-publish-release-libmesh.yml @@ -8,7 +8,7 @@ jobs: main: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set env run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - diff --git a/.github/workflows/dockerhub-publish-release.yml b/.github/workflows/dockerhub-publish-release.yml index c94a50c0d..4e3ad4177 100644 --- a/.github/workflows/dockerhub-publish-release.yml +++ b/.github/workflows/dockerhub-publish-release.yml @@ -8,7 +8,7 @@ jobs: main: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set env run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - From 17d88d8c845bb84cfbda4f674ea0919d64b79154 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 30 Jan 2023 13:57:44 -0500 Subject: [PATCH 1533/2654] added tests for spherical mesh --- tests/unit_tests/test_spherical_mesh.py | 88 ++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index 4d389a6bd..711570fb3 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -1,16 +1,42 @@ +from itertools import product, permutations + import openmc import numpy as np -def test_origin_read_write_to_xml(): - """Tests that the origin attribute can be written and read back to XML - """ +import pytest + +geom_size = 5 + +@pytest.fixture() +def model(): + openmc.reset_auto_ids() + + water = openmc.Material(name='water') + water.add_element('H', 2.0) + water.add_element('O', 1.0) + water.set_density('g/cc', 1.0) + + rpp = openmc.model.RectangularParallelepiped(*([-geom_size, geom_size] * 3), + boundary_type='vacuum') + + cell = openmc.Cell(region=-rpp, fill=water) + + geom = openmc.Geometry([cell]) + + source = openmc.Source() + source.space = openmc.stats.Point() + source.energy = openmc.stats.Discrete([10000], [1.0]) + + settings = openmc.Settings() + settings.particles = 1000 + settings.batches = 10 + settings.run_mode = 'fixed source' + # build mesh = openmc.SphericalMesh() - mesh.phi_grid = [1, 2, 3] - mesh.theta_grid = [1, 2, 3] - mesh.r_grid = [1, 2, 3] - - mesh.origin = [0.1, 0.2, 0.3] + mesh.phi_grid = np.linspace(0, 2*np.pi, 21) + mesh.theta_grid = np.linspace(0, 2*np.pi, 11) + mesh.r_grid = np.linspace(0, geom_size, geom_size) tally = openmc.Tally() @@ -21,10 +47,52 @@ def test_origin_read_write_to_xml(): tallies = openmc.Tallies([tally]) - tallies.export_to_xml() + return openmc.Model(geometry=geom, settings=settings, tallies=tallies) + +def test_origin_read_write_to_xml(run_in_tmpdir, model): + """Tests that the origin attribute can be written and read back to XML + """ + mesh = model.tallies[0].filters[0].mesh + mesh.origin = [0.1, 0.2, 0.3] + model.tallies.export_to_xml() # read back new_tallies = openmc.Tallies.from_xml() new_tally = new_tallies[0] new_mesh = new_tally.filters[0].mesh - assert np.allclose(new_mesh.origin, mesh.origin) \ No newline at end of file + np.testing.assert_equal(new_mesh.origin, mesh.origin) + +estimators = ('tracklength', 'collision') +origins = permutations([-geom_size, 0, 0]) + +test_cases = product(estimators, origins) + +def label(p): + if isinstance(p, tuple): + return f'origin:{p}' + if isinstance(p, str): + return f'estimator:{p}' + +@pytest.mark.parametrize('estimator,origin', test_cases, ids=label) +def test_offset_mesh(model, estimator, origin): + """Tests that the mesh has been moved based on tally results + """ + mesh = model.tallies[0].filters[0].mesh + model.tallies[0].estimator = estimator + # move the center of the spherical mesh upwards + mesh.origin = origin + + sp_filename = model.run() + + with openmc.StatePoint(sp_filename) as sp: + tally = sp.tallies[1] + + # we've translated half of the spherical mesh above the model, + # so ensure that half of the bins are populated + assert np.count_nonzero(tally.mean) == tally.mean.size / 2 + + # check that the lower half of the mesh contains a tally result + # and that the upper half is zero + mean = tally.mean.reshape(mesh.dimension[::-1]).T + # assert np.count_nonzero(mean[:, :, :5]) == mean.size / 2 + # assert np.count_nonzero(mean[:, :, 5:]) == 0 From e20e648690b33923e280476f97efd041f63e1435 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 30 Jan 2023 19:40:00 -0500 Subject: [PATCH 1534/2654] check for duplicate points --- openmc/model/surface_composite.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 04e0c4d80..a570ec15d 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -773,13 +773,16 @@ class Polygon(CompositeSurface): points = points[:-1, :] check_length('points', points, 3) + if len(points) != len(np.unique(points, axis=0)): + raise ValueError('Duplicate points were detected in the Polygon input') + # Check if polygon is self-intersecting by comparing edges pairwise n = len(points) is_self_intersecting = False for i in range(n): p1x, p1y = points[i, :] p2x, p2y = points[(i + 1) % n, :] - for j in range(i, n): + for j in range(i + 1, n): p3x, p3y = points[j, :] p4x, p4y = points[(j + 1) % n, :] From f45b431a2118c9a53e9eeffd1fb678f7a907309b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 30 Jan 2023 23:18:07 -0600 Subject: [PATCH 1535/2654] Use --no-build-isolation to get around parallel h5py install issue See https://github.com/h5py/h5py/issues/2222 --- tools/ci/gha-install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index 4042977c9..7854a9dfc 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -43,7 +43,8 @@ if [[ $MPI == 'y' ]]; then export CC=mpicc export HDF5_MPI=ON export HDF5_DIR=/usr/lib/x86_64-linux-gnu/hdf5/mpich - pip install --no-binary=h5py h5py + pip install wheel cython + pip install --no-binary=h5py --no-build-isolation h5py fi # Build and install OpenMC executable From e9866b4d66d7896214d6b695b8a663a8c14c135c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 31 Jan 2023 13:20:31 +0000 Subject: [PATCH 1536/2654] added get_tabular metho to energyfilters --- openmc/filter.py | 29 +++++++++++++++++++++++++++++ tests/unit_tests/test_filters.py | 17 +++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/openmc/filter.py b/openmc/filter.py index 99b005351..1bb5f9b14 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1332,6 +1332,35 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) + def get_tabular(self, values, interpolation='histogram'): + """Creates a openmc.stats.Tabular distribution using the EnergyFilter + bins and the provided values. Intended use is to help convert a + spectrum tally into a source energy. + + Parameters + ---------- + values : np.array + Array of numeric values, typically a tally.mean from a spectrum tally + interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'} + Indicate whether the density function is constant between tabulated + points or linearly-interpolated. Defaults to 'histogram'. + + Returns + ------- + openmc.stats.Tabular + Tabular distribution with histogram interpolation + """ + + probabilities = values / sum(values) + + probability_per_ev = probabilities / np.diff(self.bins).flatten() + + return openmc.stats.Tabular( + x=self.bins, + p=probability_per_ev, + interpolation=interpolation + ) + @property def lethargy_bin_width(self): """Calculates the base 10 log width of energy bins which is useful when diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 8a6f095ef..485926f19 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -269,3 +269,20 @@ def test_energyfunc(): np.testing.assert_allclose(f.energy, new_f.energy) np.testing.assert_allclose(f.y, new_f.y) assert f.interpolation == new_f.interpolation + + +def test_tabular_from_energyfilter(): + efilter = openmc.EnergyFilter([0.0, 10.0, 20.0, 25.0]) + tab = efilter.get_tabular(values=np.array([5, 10, 10])) + + assert tab.x.tolist() == [[0.0, 10.0], [10.0, 20.0], [20.0, 25.0]] + + # combination of different values passed into get_tabular and different + # width energy bins results in a doubling value for each p value + assert tab.p.tolist() == [0.02, 0.04, 0.08] + + # 'histogram' is the default + assert tab.interpolation == 'histogram' + + tab = efilter.get_tabular(values=np.array([10, 10, 5]), interpolation='linear-linear') + assert tab.interpolation == 'linear-linear' From 1e94a0c7d7126dc68e0dfdda933a9142e8cd1f42 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Thu, 2 Feb 2023 09:39:23 -0500 Subject: [PATCH 1537/2654] fixed theta_grid spherical mesh --- tests/unit_tests/test_spherical_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index 711570fb3..d6ac435c2 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -35,7 +35,7 @@ def model(): # build mesh = openmc.SphericalMesh() mesh.phi_grid = np.linspace(0, 2*np.pi, 21) - mesh.theta_grid = np.linspace(0, 2*np.pi, 11) + mesh.theta_grid = np.linspace(0, np.pi, 11) mesh.r_grid = np.linspace(0, geom_size, geom_size) tally = openmc.Tally() From dbbad687eba3357d8f6b69bec71bb119d4113e29 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 3 Feb 2023 08:32:05 -0600 Subject: [PATCH 1538/2654] Don't call normalize inside Tabular.mean --- openmc/stats/univariate.py | 11 +++++++---- tests/unit_tests/test_stats.py | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index de8d08ded..64627a4e1 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -857,7 +857,6 @@ class Tabular(Univariate): 'or linear-linear interpolation.') if self.interpolation == 'linear-linear': mean = 0.0 - self.normalize() for i in range(1, len(self.x)): y_min = self.p[i-1] y_max = self.p[i] @@ -872,9 +871,13 @@ class Tabular(Univariate): mean += exp_val elif self.interpolation == 'histogram': - mean = 0.5 * (self.x[:-1] + self.x[1:]) - mean *= np.diff(self.cdf()) - mean = sum(mean) + x_l = self.x[:-1] + x_r = self.x[1:] + p_l = self.p[:-1] + mean = (0.5 * (x_l + x_r) * (x_r - x_l) * p_l).sum() + + # Normalize for when integral of distribution is not 1 + mean /= self.integral() return mean diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 378e1fc0b..ea8898c1a 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -166,7 +166,7 @@ def test_watt(): def test_tabular(): x = np.array([0.0, 5.0, 7.0]) - p = np.array([0.1, 0.2, 0.05]) + p = np.array([10.0, 20.0, 5.0]) d = openmc.stats.Tabular(x, p, 'linear-linear') elem = d.to_xml_element('distribution') @@ -178,19 +178,22 @@ def test_tabular(): # test linear-linear sampling d = openmc.stats.Tabular(x, p) - n_samples = 100_000 samples = d.sample(n_samples) assert_sample_mean(samples, d.mean()) - # test histogram sampling - d = openmc.stats.Tabular(x, p, interpolation='histogram') + # test linear-linear normalization d.normalize() assert d.integral() == pytest.approx(1.0) + # test histogram sampling + d = openmc.stats.Tabular(x, p, interpolation='histogram') samples = d.sample(n_samples) assert_sample_mean(samples, d.mean()) + d.normalize() + assert d.integral() == pytest.approx(1.0) + def test_legendre(): # Pu239 elastic scattering at 100 keV From cf8cd62961bbb8b6de52f4e944d725c90072ab05 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 3 Feb 2023 19:32:41 -0600 Subject: [PATCH 1539/2654] Update tests/unit_tests/test_source_mesh.py Co-authored-by: Paul Romano --- tests/unit_tests/test_source_mesh.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index dc4cbf06c..e6074cb23 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -1,15 +1,14 @@ from itertools import product - from pathlib import Path +from subprocess import call + import pytest import numpy as np - import openmc import openmc.lib from tests import cdtemp from tests.regression_tests import config -from subprocess import call TETS_PER_VOXEL = 12 From fc67b38ba4ee4895529bbfce1ad94e4bdc7adeed Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 3 Feb 2023 20:11:25 -0600 Subject: [PATCH 1540/2654] Adding roundtrip test for mesh sampling --- openmc/mesh.py | 13 +++++++++++ openmc/settings.py | 19 ++++------------ openmc/source.py | 7 ++++-- openmc/stats/multivariate.py | 19 +++++++++------- tests/unit_tests/test_source_mesh.py | 34 ++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 29 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index e314aab3e..a3452b846 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod from collections.abc import Iterable +from collections import OrderedDict from math import pi from numbers import Real, Integral from pathlib import Path @@ -1937,3 +1938,15 @@ class UnstructuredMesh(MeshBase): length_multiplier = float(get_text(elem, 'length_multiplier', 1.0)) return cls(filename, library, mesh_id, '', length_multiplier) + + +def read_meshes(tree): + """Reads all mesh nodes under an XML tree + """ + out = OrderedDict() + root = tree.getroot() + for mesh_elem in root.iter('mesh'): + mesh = MeshBase.from_xml_element(mesh_elem) + out[mesh.id] = mesh + + return out \ No newline at end of file diff --git a/openmc/settings.py b/openmc/settings.py index 129ae2655..a219f8aa2 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -16,7 +16,7 @@ from openmc.stats.multivariate import MeshSpatial from . import RegularMesh, Source, VolumeCalculation, WeightWindows from ._xml import clean_indentation, get_text, reorder_attributes from openmc.checkvalue import PathLike -from .mesh import MeshBase +from .mesh import MeshBase, read_meshes class RunMode(Enum): @@ -1328,19 +1328,7 @@ class Settings: def _source_from_xml_element(self, root, meshes=None): for elem in root.findall('source'): - src = Source.from_xml_element(elem) - if isinstance(src.space, MeshSpatial): - mesh_id = int(get_text(elem, 'mesh')) - if mesh_id not in meshes: - path = f"./mesh[@id='{mesh_id}']" - mesh_elem = root.find(path) - if mesh_elem is not None: - mesh = MeshBase.from_xml_element(mesh_elem) - meshes[mesh.id] = mesh - try: - src.space.mesh = meshes[mesh_id] - except KeyError as e: - raise e(f'Mesh with ID {mesh_id} was not found.') + src = Source.from_xml_element(elem, meshes) # add newly constructed source object to the list self.source.append(src) @@ -1774,4 +1762,5 @@ class Settings: """ tree = ET.parse(path) root = tree.getroot() - return cls.from_xml_element(root) + meshes = read_meshes(tree) + return cls.from_xml_element(root, meshes) diff --git a/openmc/source.py b/openmc/source.py index 9293a5953..7f88bcd52 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -258,13 +258,16 @@ class Source: return element @classmethod - def from_xml_element(cls, elem: ET.Element) -> 'openmc.Source': + def from_xml_element(cls, elem: ET.Element, meshes=None) -> 'openmc.Source': """Generate source from an XML element Parameters ---------- elem : xml.etree.ElementTree.Element XML element + meshes : dict + Dictionary with mesh IDs as keys and openmc.MeshBase instaces as + values Returns ------- @@ -313,7 +316,7 @@ class Source: space = elem.find('space') if space is not None: - source.space = Spatial.from_xml_element(space) + source.space = Spatial.from_xml_element(space, meshes) angle = elem.find('angle') if angle is not None: diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index db13b9bc9..7372020b0 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -262,7 +262,7 @@ class Spatial(ABC): @classmethod @abstractmethod - def from_xml_element(cls, elem): + def from_xml_element(cls, elem, meshes=None): distribution = get_text(elem, 'type') if distribution == 'cartesian': return CartesianIndependent.from_xml_element(elem) @@ -275,7 +275,7 @@ class Spatial(ABC): elif distribution == 'point': return Point.from_xml_element(elem) elif distribution == 'mesh': - return MeshSpatial.from_xml_element(elem) + return MeshSpatial.from_xml_element(elem, meshes) class CartesianIndependent(Spatial): @@ -714,13 +714,16 @@ class MeshSpatial(Spatial): return element @classmethod - def from_xml_element(cls, elem): + def from_xml_element(cls, elem, meshes): """Generate spatial distribution from an XML element Parameters ---------- elem : xml.etree.ElementTree.Element XML element + meshes : dict + A dictionary with mesh IDs as keys and openmc.MeshBase instances as + values Returns ------- @@ -732,16 +735,16 @@ class MeshSpatial(Spatial): mesh_id = int(elem.get('mesh_id')) # check if this mesh has been read in from another location already - if mesh_id not in MESHES: + if mesh_id not in meshes: raise RuntimeError(f'Could not locate mesh with ID "{mesh_id}"') volume_normalized = elem.get("volume_normalized") volume_normalized = get_text(elem, 'volume_normalized').lower() == 'true' - if elem.get('strengths') is not None: + strengths = get_text(elem, 'strengths') + if strengths is not None: strengths = [float(b) for b in get_text(elem, 'strengths').split()] - else: - strengths = None - return cls(MESHES[mesh_id], strengths, volume_normalized) + + return cls(meshes[mesh_id], strengths, volume_normalized) class Box(Spatial): diff --git a/tests/unit_tests/test_source_mesh.py b/tests/unit_tests/test_source_mesh.py index e6074cb23..596b22f9a 100644 --- a/tests/unit_tests/test_source_mesh.py +++ b/tests/unit_tests/test_source_mesh.py @@ -106,10 +106,8 @@ def test_unstructured_mesh_sampling(model, request, test_cases): cell_counts = np.zeros((n_cells, n_measurements)) # This model contains 1000 geometry cells. Each cell is a hex - # corresponding to 12 of the tets. This test runs 10000 particles. This + # corresponding to 12 of the tets. This test runs 1000 samples. This # results in the following average for each cell - average_in_hex = n_samples / n_cells - openmc.lib.init([]) # perform many sets of samples and track counts for each cell @@ -174,4 +172,32 @@ def test_strengths_size_failure(request, model): with pytest.raises(RuntimeError, match=r'strengths array'), cdtemp([mesh_filename]): model.export_to_xml() - openmc.run() \ No newline at end of file + openmc.run() + +def test_roundtrip(run_in_tmpdir, model, request): + if not openmc.lib._libmesh_enabled() and not openmc.lib._dagmc_enabled(): + pytest.skip("Unstructured mesh is not enabled in this build.") + + mesh_filename = Path(request.fspath).parent / 'test_mesh_tets.e' + ucd_mesh = openmc.UnstructuredMesh(mesh_filename, library='libmesh') + + if not openmc.lib._libmesh_enabled(): + ucd_mesh.library = 'moab' + + n_cells = len(model.geometry.get_all_cells()) + + space_out = openmc.MeshSpatial(ucd_mesh) + space_out.strengths = np.random.rand(n_cells*TETS_PER_VOXEL) + model.settings.source = openmc.Source(space=space_out) + + # write out the model + model.export_to_xml() + + model_in = openmc.Model.from_xml() + + space_in = model_in.settings.source[0].space + + np.testing.assert_equal(space_out.strengths, space_in.strengths) + + assert space_in.mesh.id == space_out.mesh.id + assert space_in.volume_normalized == space_out.volume_normalized From 283e3ee6aa5db3012a118cd300bf3b6f9388c2ac Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 3 Feb 2023 22:51:51 -0600 Subject: [PATCH 1541/2654] Adjust the read_meshes function to search only for mesh elements directly below the element passed in --- openmc/mesh.py | 18 ++++++++++++++---- openmc/settings.py | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index a3452b846..b2114525f 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1940,12 +1940,22 @@ class UnstructuredMesh(MeshBase): return cls(filename, library, mesh_id, '', length_multiplier) -def read_meshes(tree): - """Reads all mesh nodes under an XML tree +def read_meshes(elem): + """Reads all mesh nodes under a a given XML node + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + XML element + + Returns + ------- + OrderedDict + An ordered dictionary with mesh IDs as keys and openmc.MeshBase + instanaces as values """ out = OrderedDict() - root = tree.getroot() - for mesh_elem in root.iter('mesh'): + for mesh_elem in elem.findall('mesh'): mesh = MeshBase.from_xml_element(mesh_elem) out[mesh.id] = mesh diff --git a/openmc/settings.py b/openmc/settings.py index a219f8aa2..ff35a90cf 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1762,5 +1762,5 @@ class Settings: """ tree = ET.parse(path) root = tree.getroot() - meshes = read_meshes(tree) + meshes = read_meshes(root) return cls.from_xml_element(root, meshes) From 78b0fbaa27b98410ecd0a5103a6aa27fdf1705e4 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sun, 5 Feb 2023 22:02:14 -0500 Subject: [PATCH 1542/2654] finished polygon self-intersection check --- openmc/model/surface_composite.py | 91 ++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 15 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index a570ec15d..047cfe7fc 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -776,26 +776,87 @@ class Polygon(CompositeSurface): if len(points) != len(np.unique(points, axis=0)): raise ValueError('Duplicate points were detected in the Polygon input') - # Check if polygon is self-intersecting by comparing edges pairwise - n = len(points) - is_self_intersecting = False - for i in range(n): - p1x, p1y = points[i, :] - p2x, p2y = points[(i + 1) % n, :] - for j in range(i + 1, n): - p3x, p3y = points[j, :] - p4x, p4y = points[(j + 1) % n, :] - - # Order the points counter-clockwise (necessary for offset method) # Calculates twice the signed area of the polygon using the "Shoelace # Formula" https://en.wikipedia.org/wiki/Shoelace_formula - # If signed area is positive the curve is oriented counter-clockwise + # If signed area is positive the curve is oriented counter-clockwise. + # If the signed area is negative the curve is oriented clockwise. xpts, ypts = points.T - if np.sum(ypts*(np.roll(xpts, 1) - np.roll(xpts, -1))) > 0: - return points + if np.sum(ypts*(np.roll(xpts, 1) - np.roll(xpts, -1))) < 0: + points = points[::-1, :] - return points[::-1, :] + + # Check if polygon is self-intersecting by comparing edges pairwise + n = len(points) + for i in range(n): + p0 = points[i, :] + p1 = points[(i + 1) % n, :] + for j in range(i + 1, n): + p2 = points[j, :] + p3 = points[(j + 1) % n, :] + # Compute orientation of p0 wrt p2->p3 line segment + cp0 = np.cross(p3-p0, p2-p0) + # Compute orientation of p1 wrt p2->p3 line segment + cp1 = np.cross(p3-p1, p2-p1) + # Compute orientation of p2 wrt p0->p1 line segment + cp2 = np.cross(p1-p2, p0-p2) + # Compute orientation of p3 wrt p0->p1 line segment + cp3 = np.cross(p1-p3, p0-p3) + + # Group cross products in an array and find out how many are 0 + cross_products = np.array([[cp0, cp1], [cp2, cp3]]) + cps_near_zero = np.isclose(cross_products, 0).astype(int) + num_zeros = np.sum(cps_near_zero) + + # Topologies of 2 finite line segments categorized by the number + # of zero-valued cross products: + # + # 0: No 3 points lie on the same line + # 1: 1 point lies on the same line defined by the other line + # segment, but is not coincident with either of the points + # 2: 2 points are coincident, but the line segments are not + # collinear which guarantees no intersection + # 3: not possible + # 4: Both line segments are collinear, simply need to check if + # they overlap or not + + if num_zeros == 0: + # If the orientations of p0 and p1 have opposite signs + # and the orientations of p2 and p3 have opposite signs + # then there is an intersection. + if all(np.prod(cross_products, axis=-1) < 0): + raise ValueError('Polygon cannot be self-intersecting') + continue + + elif num_zeros == 1: + # determine which line segment has 2 out of the 3 collinear + # points + idx = np.argwhere(np.sum(cps_near_zero, axis=-1) == 0) + if np.prod(cross_products[idx, :]) < 0: + raise ValueError('Polygon cannot be self-intersecting') + continue + + elif num_zeros == 2: + continue + + elif num_zeros == 4: + # Determine number of unique points, x span and y span for + # both line segments + #unique_pts = np.unique(np.vstack((p0, p1, p2, p3)), axis=0) + xmin1, xmax1 = min(p0[0], p1[0]), max(p0[0], p1[0]) + ymin1, ymax1 = min(p0[1], p1[1]), max(p0[1], p1[1]) + xmin2, xmax2 = min(p2[0], p3[0]), max(p2[0], p3[0]) + ymin2, ymax2 = min(p2[1], p3[1]), max(p2[1], p3[1]) + xlap = xmin1 < xmax2 and xmin2 < xmax1 + ylap = ymin1 < ymax2 and ymin2 < ymax1 + if xlap or ylap: + raise ValueError('Polygon cannot be self-intersecting') + continue + + else: + warnings.warn('Unclear if Polygon is self-intersecting') + + return points def _constrain_triangulation(self, points, depth=0): """Generate a constrained triangulation by ensuring all edges of the From c07386fc62bcfea422a03889821b9b3f053d546f Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Sun, 5 Feb 2023 22:15:10 -0500 Subject: [PATCH 1543/2654] added more tests for Polygon class --- tests/unit_tests/test_surface_composite.py | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index dbfaa62b1..3f94893ed 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -339,3 +339,57 @@ def test_polygon(): offset_star = star_poly.offset(.6) assert (0, 0, 0) in -offset_star assert any([(0, 0, 0) in reg for reg in offset_star.regions]) + + # check invalid Polygon input points + # duplicate points not just at start and end + rz_points = np.array([[6.88, 3.02], + [6.88, 2.72], + [6.88, 3.02], + [7.63, 0.0], + [5.75, 0.0], + [5.75, 1.22], + [7.63, 0.0], + [6.30, 1.22], + [6.30, 3.02], + [6.88, 3.02]]) + with pytest.raises(ValueError): + openmc.model.Polygon(rz_points) + + # segment traces back on previous segment + rz_points = np.array([[6.88, 3.02], + [6.88, 2.72], + [6.88, 2.32], + [6.88, 2.52], + [7.63, 0.0], + [5.75, 0.0], + [6.75, 0.0], + [5.75, 1.22], + [6.30, 1.22], + [6.30, 3.02], + [6.88, 3.02]]) + with pytest.raises(ValueError): + openmc.model.Polygon(rz_points) + + # segments intersect (line-line) + rz_points = np.array([[6.88, 3.02], + [5.88, 2.32], + [7.63, 0.0], + [5.75, 0.0], + [5.75, 1.22], + [6.30, 1.22], + [6.30, 3.02], + [6.88, 3.02]]) + with pytest.raises(ValueError): + openmc.model.Polygon(rz_points) + + # segments intersect (line-point) + rz_points = np.array([[6.88, 3.02], + [6.3, 2.32], + [7.63, 0.0], + [5.75, 0.0], + [5.75, 1.22], + [6.30, 1.22], + [6.30, 3.02], + [6.88, 3.02]]) + with pytest.raises(ValueError): + openmc.model.Polygon(rz_points) From 6d69c782ae333dae580a5734896efd311aab71ac Mon Sep 17 00:00:00 2001 From: josh Date: Mon, 6 Feb 2023 17:45:18 +0000 Subject: [PATCH 1544/2654] abstract _partial_deepcopy and reformat docstrings --- openmc/universe.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 8babddfeb..3b8d0fe51 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -111,11 +111,16 @@ class UniverseBase(ABC, IDManagerMixin): """ - def _deepcopy_universe_for_clone(self): - """Deepcopy an openmc.UniverseBase object. This is a paceholder for any future classes inherited from this one. - This should only to be used within the openmc.UniverseBase.clone() context. + @abstractmethod + def _partial_deepcopy(self): + """Deepcopy all parameters of an openmc.UniverseBase object except its cells. + This should only be used from the openmc.UniverseBase.clone() context. + + Returns + ------- + None + """ - return deepcopy(self) def clone(self, clone_materials=True, clone_regions=True, memo=None): """Create a copy of this universe with a new unique ID, and clones @@ -144,7 +149,7 @@ class UniverseBase(ABC, IDManagerMixin): # If no memoize'd clone exists, instantiate one if self not in memo: - clone = self._deepcopy_universe_for_clone() + clone = self._partial_deepcopy() # Clone all cells for the universe clone clone._cells = OrderedDict() @@ -616,9 +621,10 @@ class Universe(UniverseBase): if not instances_only: cell._paths.append(cell_path) - def _deepcopy_universe_for_clone(self): - """Clone all of the openmc.Universe object's attributes except for its cells, as they will be handled within the clone function. - This should only to be used within the openmc.UniverseBase.clone() context and is more performant than a deepcopy. + def _partial_deepcopy(self): + """Clone all of the openmc.Universe object's attributes except for its cells, + as they are copied within the clone function. This should only to be + used within the openmc.UniverseBase.clone() context. """ clone = openmc.Universe(name=self.name) clone.volume = self.volume @@ -961,9 +967,10 @@ class DAGMCUniverse(UniverseBase): return out - def _deepcopy_universe_for_clone(self): - """Clone all of the openmc.DAGMCUniverse object's attributes except for its cells, as they will be handled within the clone function. - This should only to be used within the openmc.UniverseBase.clone() context and is more performant than a deepcopy. + def _partial_deepcopy(self): + """Clone all of the openmc.DAGMCUniverse object's attributes except for + its cells, as they are copied within the clone function. This should + only to be used within the openmc.UniverseBase.clone() context. """ clone = openmc.DAGMCUniverse(name=self.name, filename=self.filename) clone.volume = self.volume From 637080a0c2b33f93f26c6647977aef6d99daf849 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 6 Feb 2023 15:52:46 -0500 Subject: [PATCH 1545/2654] address comments from @hassec review --- openmc/model/surface_composite.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 047cfe7fc..044ecf61e 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -816,9 +816,14 @@ class Polygon(CompositeSurface): # segment, but is not coincident with either of the points # 2: 2 points are coincident, but the line segments are not # collinear which guarantees no intersection - # 3: not possible + # 3: not possible, except maybe floating point issues? # 4: Both line segments are collinear, simply need to check if # they overlap or not + # adapted from algorithm linked below and modified to only + # consider intersections on the interior of line segments as + # proper intersections: i.e. segments sharing end points do not + # count as intersections. + # https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ if num_zeros == 0: # If the orientations of p0 and p1 have opposite signs @@ -839,7 +844,12 @@ class Polygon(CompositeSurface): elif num_zeros == 2: continue - elif num_zeros == 4: + elif num_zeros == 3: + warnings.warn('Unclear if Polygon is self-intersecting') + continue + + else: + # All 4 cross products are zero # Determine number of unique points, x span and y span for # both line segments #unique_pts = np.unique(np.vstack((p0, p1, p2, p3)), axis=0) @@ -853,9 +863,6 @@ class Polygon(CompositeSurface): raise ValueError('Polygon cannot be self-intersecting') continue - else: - warnings.warn('Unclear if Polygon is self-intersecting') - return points def _constrain_triangulation(self, points, depth=0): From 5470ec75b4215faa296bec05a203dcfb9d89d30e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 6 Feb 2023 21:49:43 -0600 Subject: [PATCH 1546/2654] Avoid out-of-bounds access on index_inelastic_scatter_ --- src/physics.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/physics.cpp b/src/physics.cpp index 7cb8040f6..d924b72be 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -705,17 +705,10 @@ void scatter(Particle& p, int i_nuclide) // ======================================================================= // INELASTIC SCATTERING - int j = 0; + int n = nuc->index_inelastic_scatter_.size(); int i = 0; - while (prob < cutoff) { + for (int j = 0; j < n && prob < cutoff; ++j) { i = nuc->index_inelastic_scatter_[j]; - ++j; - - // Check to make sure inelastic scattering reaction sampled - if (i >= nuc->reactions_.size()) { - p.write_restart(); - fatal_error("Did not sample any reaction for nuclide " + nuc->name_); - } // add to cumulative probability prob += nuc->reactions_[i]->xs(micro); From ecebe25f367e9482b8c475f9484c32cddd2be338 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 7 Feb 2023 10:23:28 +0000 Subject: [PATCH 1547/2654] making error message more helpful with material name --- openmc/deplete/openmc_operator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index b00d83127..6233322ab 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -223,8 +223,9 @@ class OpenMCOperator(TransportOperator): if mat.depletable: burnable_mats.add(str(mat.id)) if mat.volume is None: - raise RuntimeError("Volume not specified for depletable " - "material with ID={}.".format(mat.id)) + msh = ("Volume not specified for depletable material with " + f"ID={mat.id}. Name={mat.name}") + raise RuntimeError(msh) volume[str(mat.id)] = mat.volume self.heavy_metal += mat.fissionable_mass @@ -242,7 +243,6 @@ class OpenMCOperator(TransportOperator): for nuc in model_nuclides: if nuc not in nuclides: nuclides.append(nuc) - return burnable_mats, volume, nuclides def _load_previous_results(self): From 016a5e5b3c3fdfe90bb9413958e2df0f371861a5 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 7 Feb 2023 10:24:39 +0000 Subject: [PATCH 1548/2654] moved full stop --- openmc/deplete/openmc_operator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 6233322ab..874a1da23 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -224,7 +224,7 @@ class OpenMCOperator(TransportOperator): burnable_mats.add(str(mat.id)) if mat.volume is None: msh = ("Volume not specified for depletable material with " - f"ID={mat.id}. Name={mat.name}") + f"ID={mat.id} Name={mat.name}.") raise RuntimeError(msh) volume[str(mat.id)] = mat.volume self.heavy_metal += mat.fissionable_mass From 0d4227fa1f1baaee6116973a12072ba53ac6631f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 7 Feb 2023 12:26:11 +0000 Subject: [PATCH 1549/2654] added volume information to material repr --- openmc/material.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmc/material.py b/openmc/material.py index a213a53fd..28d38cb90 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -143,6 +143,9 @@ class Material(IDManagerMixin): string += '{: <16}=\t{}'.format('\tDensity', self._density) string += f' [{self._density_units}]\n' + string += '{: <16}=\t{}'.format('\tVolume', self._volume) + string += ' [cm3]\n' + string += '{: <16}\n'.format('\tS(a,b) Tables') if self._ncrystal_cfg: From 5f0e3e14fbf131c8bcf0ec0cf60ddf05bb7c8294 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 31 Oct 2022 12:18:09 -0400 Subject: [PATCH 1550/2654] added default filter shape and mesh filter shape --- openmc/filter.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openmc/filter.py b/openmc/filter.py index 99b005351..bcd3dbc36 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -102,6 +102,8 @@ class Filter(IDManagerMixin, metaclass=FilterMeta): Unique identifier for the filter num_bins : Integral The number of filter bins + shape : tuple + The shape of the filter """ @@ -205,6 +207,10 @@ class Filter(IDManagerMixin, metaclass=FilterMeta): def num_bins(self): return len(self.bins) + @property + def shape(self): + return (self.num_bins,) + def check_bins(self, bins): """Make sure given bins are valid for this filter. @@ -839,6 +845,10 @@ class MeshFilter(Filter): else: self.bins = list(mesh.indices) + @property + def shape(self): + return self.mesh.dimension + @property def translation(self): return self._translation From 512c7e6556b37b45cd7e93eb04c1b1260f14c59c Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 31 Oct 2022 12:47:13 -0400 Subject: [PATCH 1551/2654] modified get_reshaped_data --- openmc/tallies.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index b22cc4cf0..33a14974c 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1440,11 +1440,23 @@ class Tally(IDManagerMixin): data = self.get_values(value=value) # Build a new array shape with one dimension per filter - new_shape = tuple(f.num_bins for f in self.filters) + new_shape = tuple() + idx0 = None + for i, f in enumerate(self.filters): + # Mesh filter indices are backwards so we need to flip them + if isinstance(f, openmc.MeshFilter): + fshape = f.shape[::-1] + new_shape += fshape + idx0, idx1 = i, i + len(fshape) - 1 + else: + new_shape += f.shape + new_shape += (self.num_nuclides, self.num_scores) # Reshape the data with one dimension for each filter data = np.reshape(data, new_shape) + if idx0 is not None: + data = np.swapaxes(data, idx0, idx1) return data def hybrid_product(self, other, binary_op, filter_product=None, From 61efad0a8d63884f535fa4adce4e04b846f8c714 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Fri, 11 Nov 2022 12:10:10 -0500 Subject: [PATCH 1552/2654] added test and expand_dims kwarg --- openmc/tallies.py | 39 +++++++++++++++------- tests/unit_tests/test_filter_mesh.py | 48 ++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 33a14974c..688369de0 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1405,7 +1405,7 @@ class Tally(IDManagerMixin): return df - def get_reshaped_data(self, value='mean'): + def get_reshaped_data(self, value='mean', expand_dims=False): """Returns an array of tally data with one dimension per filter. The tally data in OpenMC is stored as a 3D array with the dimensions @@ -1417,17 +1417,24 @@ class Tally(IDManagerMixin): This builds and returns a reshaped version of the tally data array with unique dimensions corresponding to each tally filter. For example, - suppose this tally has arrays of data with shape (8,5,5) corresponding - to two filters (2 and 4 bins, respectively), five nuclides and five + suppose this tally has arrays of data with shape (30,5,5) corresponding + to two filters (2 and 15 bins, respectively), five nuclides and five scores. This method will return a version of the data array with the - with a new shape of (2,4,5,5) such that the first two dimensions - correspond directly to the two filters with two and four bins. + with a new shape of (2,15,5,5) such that the first two dimensions + correspond directly to the two filters with two and fifteen bins. If + expand_dims is True and our filter above with 15 bins is an instance of + :class:`openmc.MeshFilter` with a shape of (3,5,1). The resulting tally + data array will have a new shape of (2,3,5,1,5,5). Parameters ---------- value : str A string for the type of value to return - 'mean' (default), 'std_dev', 'rel_err', 'sum', or 'sum_sq' are accepted + expand_dims : bool, optional + Whether or not to expand the dimensions of filters with multiple + dimensions. This will result in more than one dimension per filter + for the returned data array. Returns ------- @@ -1439,24 +1446,32 @@ class Tally(IDManagerMixin): # Get the 3D array of data in filters, nuclides and scores data = self.get_values(value=value) - # Build a new array shape with one dimension per filter + # Build a new array shape with one dimension per filter or expand + # multidimensional filters if desired new_shape = tuple() idx0 = None for i, f in enumerate(self.filters): - # Mesh filter indices are backwards so we need to flip them - if isinstance(f, openmc.MeshFilter): - fshape = f.shape[::-1] - new_shape += fshape - idx0, idx1 = i, i + len(fshape) - 1 + if expand_dims: + # Mesh filter indices are backwards so we need to flip them + if isinstance(f, openmc.MeshFilter): + fshape = f.shape[::-1] + new_shape += fshape + idx0, idx1 = i, i + len(fshape) - 1 + else: + new_shape += f.shape else: - new_shape += f.shape + new_shape += (np.prod(f.shape),) new_shape += (self.num_nuclides, self.num_scores) # Reshape the data with one dimension for each filter data = np.reshape(data, new_shape) + + # If we had a MeshFilter we should swap the axes to have the same shape + # for the data and the filter if idx0 is not None: data = np.swapaxes(data, idx0, idx1) + return data def hybrid_product(self, other, binary_op, filter_product=None, diff --git a/tests/unit_tests/test_filter_mesh.py b/tests/unit_tests/test_filter_mesh.py index 265642360..3bb836e46 100644 --- a/tests/unit_tests/test_filter_mesh.py +++ b/tests/unit_tests/test_filter_mesh.py @@ -1,7 +1,10 @@ +import math + import numpy as np -import openmc from uncertainties import unumpy +import openmc + def test_spherical_mesh_estimators(run_in_tmpdir): """Test that collision/tracklength estimators agree for SphericalMesh""" @@ -62,7 +65,8 @@ def test_cylindrical_mesh_estimators(run_in_tmpdir): mat.add_nuclide('U235', 1.0) mat.set_density('g/cm3', 10.0) - cyl = openmc.model.RightCircularCylinder((0., 0., -5.), 10., 10.0, boundary_type='vacuum') + cyl = openmc.model.RightCircularCylinder((0., 0., -5.), 10., 10.0, + boundary_type='vacuum') cell = openmc.Cell(fill=mat, region=-cyl) model = openmc.Model() model.geometry = openmc.Geometry([cell]) @@ -107,3 +111,43 @@ def test_cylindrical_mesh_estimators(run_in_tmpdir): diff = unumpy.nominal_values(delta) std_dev = unumpy.std_devs(delta) assert np.all(diff < 3*std_dev) + +def test_get_reshaped_data(run_in_tmpdir): + """Test that expanding MeshFilter dimensions works as expected""" + + mat = openmc.Material() + mat.add_nuclide('U235', 1.0) + mat.set_density('g/cm3', 10.0) + + sphere = openmc.Sphere(r=10.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sphere) + model = openmc.Model() + model.geometry = openmc.Geometry([cell]) + model.settings.particles = 1_000 + model.settings.inactive = 10 + model.settings.batches = 20 + + sph_mesh = openmc.SphericalMesh() + sph_mesh.r_grid = np.linspace(0.0, 5.0**3, 20)**(1/3) + sph_mesh.theta_grid = np.linspace(0, math.pi, 4) + sph_mesh.phi_grid = np.linspace(0, 2*math.pi, 3) + tally1 = openmc.Tally() + efilter = openmc.EnergyFilter([0, 1e5, 1e8]) + meshfilter = openmc.MeshFilter(sph_mesh) + assert meshfilter.shape == (19, 3, 2) + tally1.filters = [efilter, meshfilter] + tally1.scores = ['flux'] + + model.tallies = openmc.Tallies([tally1]) + + # Run OpenMC + sp_filename = model.run() + + # Get flux tally as reshaped data + with openmc.StatePoint(sp_filename) as sp: + t1 = sp.tallies[tally1.id] + data1 = t1.get_reshaped_data() + data2 = t1.get_reshaped_data(expand_dims=True) + + assert data1.shape == (2, 19*3*2, 1, 1) + assert data2.shape == (2, 19, 3, 2, 1, 1) From 653bec5fd8955ba4522d6b0f5a9542ebbe802c34 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Fri, 11 Nov 2022 13:20:14 -0500 Subject: [PATCH 1553/2654] added shape to aggregate filter --- openmc/arithmetic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmc/arithmetic.py b/openmc/arithmetic.py index 618c7c4a1..3655ef2a3 100644 --- a/openmc/arithmetic.py +++ b/openmc/arithmetic.py @@ -604,6 +604,10 @@ class AggregateFilter: def num_bins(self): return len(self.bins) if self.aggregate_filter else 0 + @property + def shape(self): + return (self.num_bins,) + @type.setter def type(self, filter_type): if filter_type not in _FILTER_TYPES: From 63b826133653c5310635d2c924885f7b07fbc48c Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 14 Nov 2022 20:33:59 -0500 Subject: [PATCH 1554/2654] treat MeshSurfaceFilter differently --- openmc/filter.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index bcd3dbc36..17678e026 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -847,6 +847,8 @@ class MeshFilter(Filter): @property def shape(self): + if isinstance(self, MeshSurfaceFilter): + return (self.num_bins,) return self.mesh.dimension @property @@ -968,8 +970,6 @@ class MeshSurfaceFilter(MeshFilter): Attributes ---------- - bins : Integral - The mesh ID mesh : openmc.MeshBase The mesh object that events will be tallied onto translation : Iterable of float @@ -978,10 +978,8 @@ class MeshSurfaceFilter(MeshFilter): id : int Unique identifier for the filter bins : list of tuple - A list of mesh indices / surfaces for each filter bin, e.g. [(1, 1, 'x-min out'), (1, 1, 'x-min in'), ...] - num_bins : Integral The number of filter bins From af16239684024712beec6ace9b74e3024ad34b20 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 8 Feb 2023 10:17:59 -0600 Subject: [PATCH 1555/2654] Updating mesh centre tests. --- tests/unit_tests/test_cylindrical_mesh.py | 21 ++++++++++----- tests/unit_tests/test_spherical_mesh.py | 31 +++++++++++++++-------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index e67f21b15..a9d3fd56a 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -28,7 +28,7 @@ def model(): source.energy = openmc.stats.Discrete([10000], [1.0]) settings = openmc.Settings() - settings.particles = 1000 + settings.particles = 2000 settings.batches = 10 settings.run_mode = 'fixed source' @@ -43,7 +43,7 @@ def model(): mesh_filter = openmc.MeshFilter(mesh) tally.filters.append(mesh_filter) - tally.scores.append("heating") + tally.scores.append("flux") tallies = openmc.Tallies([tally]) @@ -63,7 +63,8 @@ def test_origin_read_write_to_xml(run_in_tmpdir, model): np.testing.assert_equal(new_mesh.origin, mesh.origin) estimators = ('tracklength', 'collision') -origins = permutations([-geom_size, 0, 0]) +origins = set(permutations((-geom_size, 0, 0))) +origins |= set(permutations((geom_size, 0, 0))) test_cases = product(estimators, origins) @@ -91,8 +92,14 @@ def test_offset_mesh(model, estimator, origin): # so ensure that half of the bins are populated assert np.count_nonzero(tally.mean) == tally.mean.size / 2 - # check that the lower half of the mesh contains a tally result - # and that the upper half is zero + # check that the half of the mesh that is outside of the geometry + # contains the zero values mean = tally.mean.reshape(mesh.dimension[::-1]).T - # assert np.count_nonzero(mean[:, :, :5]) == mean.size / 2 - # assert np.count_nonzero(mean[:, :, 5:]) == 0 + centroids = mesh.centroids + for ijk in mesh.indices: + i, j, k = np.array(ijk) - 1 + print(centroids[:, i, j, k]) + if model.geometry.find(centroids[:, i, j, k]): + mean[i, j, k] == 0.0 + else: + mean[i, j, k] != 0.0 diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index d6ac435c2..3cd8bbc5d 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -28,14 +28,14 @@ def model(): source.energy = openmc.stats.Discrete([10000], [1.0]) settings = openmc.Settings() - settings.particles = 1000 + settings.particles = 2000 settings.batches = 10 settings.run_mode = 'fixed source' # build mesh = openmc.SphericalMesh() - mesh.phi_grid = np.linspace(0, 2*np.pi, 21) - mesh.theta_grid = np.linspace(0, np.pi, 11) + mesh.phi_grid = np.linspace(0, 2*np.pi, 13) + mesh.theta_grid = np.linspace(0, np.pi, 7) mesh.r_grid = np.linspace(0, geom_size, geom_size) tally = openmc.Tally() @@ -43,7 +43,7 @@ def model(): mesh_filter = openmc.MeshFilter(mesh) tally.filters.append(mesh_filter) - tally.scores.append("heating") + tally.scores.append("flux") tallies = openmc.Tallies([tally]) @@ -63,7 +63,12 @@ def test_origin_read_write_to_xml(run_in_tmpdir, model): np.testing.assert_equal(new_mesh.origin, mesh.origin) estimators = ('tracklength', 'collision') -origins = permutations([-geom_size, 0, 0]) +# TODO: determine why this is needed for spherical mesh +# but not cylindrical mesh +offset = geom_size + 0.001 + +origins = set(permutations((-offset, 0, 0))) +origins |= set(permutations((offset, 0, 0))) test_cases = product(estimators, origins) @@ -79,7 +84,7 @@ def test_offset_mesh(model, estimator, origin): """ mesh = model.tallies[0].filters[0].mesh model.tallies[0].estimator = estimator - # move the center of the spherical mesh upwards + # move the center of the spherical mesh mesh.origin = origin sp_filename = model.run() @@ -91,8 +96,14 @@ def test_offset_mesh(model, estimator, origin): # so ensure that half of the bins are populated assert np.count_nonzero(tally.mean) == tally.mean.size / 2 - # check that the lower half of the mesh contains a tally result - # and that the upper half is zero + # check that the half of the mesh that is outside of the geometry + # contains the zero values mean = tally.mean.reshape(mesh.dimension[::-1]).T - # assert np.count_nonzero(mean[:, :, :5]) == mean.size / 2 - # assert np.count_nonzero(mean[:, :, 5:]) == 0 + centroids = mesh.centroids + for ijk in mesh.indices: + i, j, k = np.array(ijk) - 1 + print(centroids[:, i, j, k]) + if model.geometry.find(centroids[:, i, j, k]): + mean[i, j, k] == 0.0 + else: + mean[i, j, k] != 0.0 From 8a5a5201063b2b6a29e56ab92c6c983cec98aac3 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 17:38:33 +0000 Subject: [PATCH 1556/2654] code review improvments from @paulromano Co-authored-by: Paul Romano --- openmc/filter.py | 31 +++++++++++++++---------------- tests/unit_tests/test_filters.py | 2 +- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 1bb5f9b14..e1c8611f9 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1332,18 +1332,19 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) - def get_tabular(self, values, interpolation='histogram'): - """Creates a openmc.stats.Tabular distribution using the EnergyFilter - bins and the provided values. Intended use is to help convert a - spectrum tally into a source energy. + def get_tabular(self, values, **kwargs): + """Create a tabulated distribution based on tally results with an energy filter + + This method provides an easy way to create a distribution in energy + (e.g., a source spectrum) based on tally results that were obtained from + using an :class:`~openmc.EnergyFilter`. Parameters ---------- - values : np.array - Array of numeric values, typically a tally.mean from a spectrum tally - interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'} - Indicate whether the density function is constant between tabulated - points or linearly-interpolated. Defaults to 'histogram'. + values : iterable of float + Array of numeric values, typically from a tally result + **kwargs + Keyword arguments passed to :class:`openmc.stats.Tabular` Returns ------- @@ -1351,15 +1352,13 @@ class EnergyFilter(RealFilter): Tabular distribution with histogram interpolation """ - probabilities = values / sum(values) + probabilities = np.array(values) + probabilities /= probabilities.sum() - probability_per_ev = probabilities / np.diff(self.bins).flatten() + probability_per_ev = probabilities / np.diff(self.values) - return openmc.stats.Tabular( - x=self.bins, - p=probability_per_ev, - interpolation=interpolation - ) + kwargs.setdefault('interpolation', 'histogram') + return openmc.stats.Tabular(self.bins, probability_per_ev, **kwargs) @property def lethargy_bin_width(self): diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 485926f19..afe85cdde 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -273,7 +273,7 @@ def test_energyfunc(): def test_tabular_from_energyfilter(): efilter = openmc.EnergyFilter([0.0, 10.0, 20.0, 25.0]) - tab = efilter.get_tabular(values=np.array([5, 10, 10])) + tab = efilter.get_tabular(values=[5, 10, 10]) assert tab.x.tolist() == [[0.0, 10.0], [10.0, 20.0], [20.0, 25.0]] From b41c8330f19923be3f59dd01bb3b8a5f4f13f526 Mon Sep 17 00:00:00 2001 From: Josh May Date: Thu, 9 Feb 2023 09:41:23 -0800 Subject: [PATCH 1557/2654] Update openmc/universe.py Co-authored-by: Paul Romano --- openmc/universe.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 3b8d0fe51..c56cce7ca 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -116,10 +116,6 @@ class UniverseBase(ABC, IDManagerMixin): """Deepcopy all parameters of an openmc.UniverseBase object except its cells. This should only be used from the openmc.UniverseBase.clone() context. - Returns - ------- - None - """ def clone(self, clone_materials=True, clone_regions=True, memo=None): From e6d8e3f4a74f1be2db6b22d11575c0951372090e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 17:53:04 +0000 Subject: [PATCH 1558/2654] avoiding true divide erorr --- openmc/filter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index e1c8611f9..d646cc019 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1352,8 +1352,7 @@ class EnergyFilter(RealFilter): Tabular distribution with histogram interpolation """ - probabilities = np.array(values) - probabilities /= probabilities.sum() + probabilities = np.array(values) / sum(values) probability_per_ev = probabilities / np.diff(self.values) From b559d32d6849f8ef680a935afd33012c2a593490 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 9 Feb 2023 19:47:29 +0000 Subject: [PATCH 1559/2654] custom error message for name is None --- openmc/deplete/openmc_operator.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 874a1da23..9122b93d3 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -223,9 +223,11 @@ class OpenMCOperator(TransportOperator): if mat.depletable: burnable_mats.add(str(mat.id)) if mat.volume is None: - msh = ("Volume not specified for depletable material with " - f"ID={mat.id} Name={mat.name}.") - raise RuntimeError(msh) + msg = ("Volume not specified for depletable material with " + f"ID={mat.id}.") + if mat.name is not None: + msg = f"{msg[:-1]} Name={mat.name}." + raise RuntimeError(msg) volume[str(mat.id)] = mat.volume self.heavy_metal += mat.fissionable_mass From 853ef5ea49862f9c545948b4c8ecf18c3c228c41 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 19:51:46 +0000 Subject: [PATCH 1560/2654] 2nd round of review improvments from paulromano Co-authored-by: Paul Romano --- openmc/filter.py | 7 +++++-- tests/unit_tests/test_filters.py | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index d646cc019..cb1b57ed0 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1352,12 +1352,15 @@ class EnergyFilter(RealFilter): Tabular distribution with histogram interpolation """ - probabilities = np.array(values) / sum(values) + probabilities = np.array(values, dtype=float) + probabilities /= probabilities.sum() + # Determine probability per eV, adding extra 0 at the end since it is a histogram probability_per_ev = probabilities / np.diff(self.values) + probability_per_ev = np.append(probability_per_ev, 0.0) kwargs.setdefault('interpolation', 'histogram') - return openmc.stats.Tabular(self.bins, probability_per_ev, **kwargs) + return openmc.stats.Tabular(self.values, probability_per_ev, **kwargs) @property def lethargy_bin_width(self): diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index afe85cdde..d4f0edbf9 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -275,12 +275,15 @@ def test_tabular_from_energyfilter(): efilter = openmc.EnergyFilter([0.0, 10.0, 20.0, 25.0]) tab = efilter.get_tabular(values=[5, 10, 10]) - assert tab.x.tolist() == [[0.0, 10.0], [10.0, 20.0], [20.0, 25.0]] + assert tab.x.tolist() == [0.0, 10.0, 20.0, 25.0] # combination of different values passed into get_tabular and different # width energy bins results in a doubling value for each p value assert tab.p.tolist() == [0.02, 0.04, 0.08] + # distribution should integrate to unity + assert tab.integral() == approx(1.0) + # 'histogram' is the default assert tab.interpolation == 'histogram' From eaddf91b6538e58c079d9eaca6f558db344fd644 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 21:19:11 +0000 Subject: [PATCH 1561/2654] Adding zero to end of test results Co-authored-by: Paul Romano --- tests/unit_tests/test_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index d4f0edbf9..0d34bfee3 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -279,7 +279,7 @@ def test_tabular_from_energyfilter(): # combination of different values passed into get_tabular and different # width energy bins results in a doubling value for each p value - assert tab.p.tolist() == [0.02, 0.04, 0.08] + assert tab.p.tolist() == [0.02, 0.04, 0.08, 0.0] # distribution should integrate to unity assert tab.integral() == approx(1.0) From c0391781ca8268989b064d71b2850246d12bf9c9 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 10 Feb 2023 09:22:10 +0000 Subject: [PATCH 1562/2654] changed error message to preferred option --- openmc/deplete/openmc_operator.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index 9122b93d3..8a13bff7f 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -223,10 +223,12 @@ class OpenMCOperator(TransportOperator): if mat.depletable: burnable_mats.add(str(mat.id)) if mat.volume is None: - msg = ("Volume not specified for depletable material with " - f"ID={mat.id}.") - if mat.name is not None: - msg = f"{msg[:-1]} Name={mat.name}." + if mat.name is None: + msg = ("Volume not specified for depletable material " + f"with ID={mat.id}.") + else: + msg = ("Volume not specified for depletable material " + f"with ID={mat.id} Name={mat.name}.") raise RuntimeError(msg) volume[str(mat.id)] = mat.volume self.heavy_metal += mat.fissionable_mass From 9c646b3f323ad0b52f8cfd35dfd35f6e2a3a2d10 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 27 Dec 2022 22:09:43 -0600 Subject: [PATCH 1563/2654] Fix CMFDMesh.grid setter --- openmc/cmfd.py | 6 ++---- tests/regression_tests/cmfd_feed/test.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/openmc/cmfd.py b/openmc/cmfd.py index 54c43f333..85550c495 100644 --- a/openmc/cmfd.py +++ b/openmc/cmfd.py @@ -246,7 +246,7 @@ class CMFDMesh: Real) check_greater_than('CMFD mesh {}-grid length'.format(dims[i]), len(grid[i]), 1) - self._grid = np.array(grid) + self._grid = [np.array(g) for g in grid] self._display_mesh_warning('rectilinear', 'CMFD mesh grid') def _display_mesh_warning(self, mesh_type, variable_label): @@ -1382,9 +1382,7 @@ class CMFDRun: """ # Write each element in vector to file - with open(base_filename+'.dat', 'w') as fh: - for val in vector: - fh.write('{:0.8f}\n'.format(val)) + np.savetxt(f'{base_filename}.dat', vector, fmt='%.8f') # Save as numpy format np.save(base_filename, vector) diff --git a/tests/regression_tests/cmfd_feed/test.py b/tests/regression_tests/cmfd_feed/test.py index fa22b0fe3..d513dee2a 100644 --- a/tests/regression_tests/cmfd_feed/test.py +++ b/tests/regression_tests/cmfd_feed/test.py @@ -111,7 +111,7 @@ def test_cmfd_write_matrices(): # Load flux vector from numpy output file flux_np = np.load('fluxvec.npy') # Load flux from data file - flux_dat = np.loadtxt("fluxvec.dat", delimiter='\n') + flux_dat = np.loadtxt("fluxvec.dat") # Compare flux from numpy file, .dat file, and from simulation assert(np.all(np.isclose(flux_np, cmfd_run._phi))) From 990b5449f537139c93b0c0ed77610379cc8ece18 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 27 Dec 2022 22:10:33 -0600 Subject: [PATCH 1564/2654] Avoid use of np.float and np.int --- openmc/filter.py | 2 +- openmc/mgxs/groups.py | 2 +- openmc/mgxs/mdgxs.py | 4 ++-- openmc/mgxs/mgxs.py | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 4d40117fe..11462a7fe 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1741,7 +1741,7 @@ class DistribcellFilter(Filter): # Concatenate with DataFrame of distribcell instance IDs if level_df is not None: level_df = level_df.dropna(axis=1, how='all') - level_df = level_df.astype(np.int) + level_df = level_df.astype(int) df = pd.concat([level_df, df], axis=1) return df diff --git a/openmc/mgxs/groups.py b/openmc/mgxs/groups.py index f26218e03..d49f2d651 100644 --- a/openmc/mgxs/groups.py +++ b/openmc/mgxs/groups.py @@ -164,7 +164,7 @@ class EnergyGroups: if groups == 'all': return np.arange(self.num_groups) else: - indices = np.zeros(len(groups), dtype=np.int) + indices = np.zeros(len(groups), dtype=int) for i, group in enumerate(groups): cv.check_greater_than('group', group, 0) diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 287a2961d..96192323e 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -586,7 +586,7 @@ class MDGXS(MGXS): if not isinstance(subdomains, str): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) + subdomains = np.arange(self.num_subdomains, dtype=int) elif self.domain_type == 'mesh': xyz = [range(1, x + 1) for x in self.domain.dimension] subdomains = list(itertools.product(*xyz)) @@ -2473,7 +2473,7 @@ class MatrixMDGXS(MDGXS): if not isinstance(subdomains, str): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) + subdomains = np.arange(self.num_subdomains, dtype=int) elif self.domain_type == 'mesh': xyz = [range(1, x + 1) for x in self.domain.dimension] subdomains = list(itertools.product(*xyz)) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index c93b42b88..1077896cc 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -918,7 +918,7 @@ class MGXS: # Sum the atomic number densities for all nuclides if nuclides == 'sum': nuclides = self.get_nuclides() - densities = np.zeros(1, dtype=np.float) + densities = np.zeros(1, dtype=float) for nuclide in nuclides: densities[0] += self.get_nuclide_density(nuclide) @@ -931,7 +931,7 @@ class MGXS: # Tabulate the atomic number densities for each specified nuclide else: - densities = np.zeros(len(nuclides), dtype=np.float) + densities = np.zeros(len(nuclides), dtype=float) for i, nuclide in enumerate(nuclides): densities[i] = self.get_nuclide_density(nuclide) @@ -1720,7 +1720,7 @@ class MGXS: if not isinstance(subdomains, str): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) + subdomains = np.arange(self.num_subdomains, dtype=int) elif self.domain_type == 'mesh': subdomains = list(self.domain.indices) else: @@ -1887,7 +1887,7 @@ class MGXS: if not isinstance(subdomains, str): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) + subdomains = np.arange(self.num_subdomains, dtype=int) elif self.domain_type == 'sum(distribcell)': domain_filter = self.xs_tally.find_filter('sum(distribcell)') subdomains = domain_filter.bins @@ -1900,7 +1900,7 @@ class MGXS: if self.by_nuclide: if nuclides == 'all': nuclides = self.get_nuclides() - densities = np.zeros(len(nuclides), dtype=np.float) + densities = np.zeros(len(nuclides), dtype=float) elif nuclides == 'sum': nuclides = ['sum'] else: @@ -2447,7 +2447,7 @@ class MatrixMGXS(MGXS): if not isinstance(subdomains, str): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) + subdomains = np.arange(self.num_subdomains, dtype=int) elif self.domain_type == 'mesh': subdomains = list(self.domain.indices) else: @@ -4785,7 +4785,7 @@ class ScatterMatrixXS(MatrixMGXS): if not isinstance(subdomains, str): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) + subdomains = np.arange(self.num_subdomains, dtype=int) elif self.domain_type == 'mesh': subdomains = list(self.domain.indices) else: From 956e3f43414e57b0034764973b9ac3486bf02418 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 30 Nov 2022 14:21:21 -0600 Subject: [PATCH 1565/2654] Make sure correct direction is applied when fission neutrons are anisotropic --- include/openmc/physics.h | 4 ++-- src/physics.cpp | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/openmc/physics.h b/include/openmc/physics.h index 6e7327d38..f62f43a02 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -87,8 +87,8 @@ Direction sample_target_velocity(const Nuclide& nuc, double E, Direction u, Direction sample_cxs_target_velocity( double awr, double E, Direction u, double kT, uint64_t* seed); -void sample_fission_neutron(int i_nuclide, const Reaction& rx, double E_in, - SourceSite* site, uint64_t* seed); +void sample_fission_neutron( + int i_nuclide, const Reaction& rx, SourceSite* site, Particle& p); //! handles all reactions with a single secondary neutron (other than fission), //! i.e. level scattering, (n,np), (n,na), etc. diff --git a/src/physics.cpp b/src/physics.cpp index 7cb8040f6..2b3f534a1 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -212,7 +212,7 @@ void create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx) site.surf_id = 0; // Sample delayed group and angle/energy for fission reaction - sample_fission_neutron(i_nuclide, rx, p.E(), &site, p.current_seed()); + sample_fission_neutron(i_nuclide, rx, &site, p); // Store fission site in bank if (use_fission_bank) { @@ -1031,9 +1031,13 @@ Direction sample_cxs_target_velocity( return vt * rotate_angle(u, mu, nullptr, seed); } -void sample_fission_neutron(int i_nuclide, const Reaction& rx, double E_in, - SourceSite* site, uint64_t* seed) +void sample_fission_neutron( + int i_nuclide, const Reaction& rx, SourceSite* site, Particle& p) { + // Get attributes of particle + double E_in = p.E(); + uint64_t* seed = p.current_seed(); + // Determine total nu, delayed nu, and delayed neutron fraction const auto& nuc {data::nuclides[i_nuclide]}; double nu_t = nuc->nu(E_in, Nuclide::EmissionMode::total); @@ -1096,9 +1100,7 @@ void sample_fission_neutron(int i_nuclide, const Reaction& rx, double E_in, } // Sample azimuthal angle uniformly in [0, 2*pi) and assign angle - // TODO: account for dependence on incident neutron? - Direction ref(1., 0., 0.); - site->u = rotate_angle(ref, mu, nullptr, seed); + site->u = rotate_angle(p.u(), mu, nullptr, seed); } void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p) From 6a790df0bef2a4fbb66bfc2d7253d2a59ee71a3b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 27 Dec 2022 22:43:42 -0600 Subject: [PATCH 1566/2654] Update micro_xs regression test with update option --- tests/regression_tests/microxs/test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/microxs/test.py b/tests/regression_tests/microxs/test.py index dbfe3357b..f92f61479 100644 --- a/tests/regression_tests/microxs/test.py +++ b/tests/regression_tests/microxs/test.py @@ -4,9 +4,10 @@ from pathlib import Path import numpy as np import pytest import openmc - from openmc.deplete import MicroXS +from tests.regression_tests import config + CHAIN_FILE = Path(__file__).parents[2] / "chain_simple.xml" @pytest.fixture(scope="module") @@ -46,7 +47,10 @@ def model(): def test_from_model(model): - ref_xs = MicroXS.from_csv('test_reference.csv') test_xs = MicroXS.from_model(model, model.materials[0], CHAIN_FILE) + if config['update']: + test_xs.to_csv('test_reference.csv') + + ref_xs = MicroXS.from_csv('test_reference.csv') np.testing.assert_allclose(test_xs, ref_xs, rtol=1e-11) From fcdac0759ef109b37e318bca4ff31363d00e138b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 27 Dec 2022 22:51:31 -0600 Subject: [PATCH 1567/2654] Remove numpy version hardcoding in pyproject.toml / GHA --- pyproject.toml | 2 +- tools/ci/gha-install.sh | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ac6735593..d5970617a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,2 @@ [build-system] -requires = ["setuptools", "wheel", "numpy<1.22", "cython"] +requires = ["setuptools", "wheel", "numpy", "cython"] diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index 7854a9dfc..fb81fcea2 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -2,12 +2,9 @@ set -ex # Upgrade pip, pytest, numpy before doing anything else. -# TODO: numpy 1.22 results in several failing tests, so we force a lower version -# for now (similar change made in pyproject.toml). When this is removed, those -# tests will need to be updated. pip install --upgrade pip pip install --upgrade pytest -pip install --upgrade "numpy<1.22" +pip install --upgrade numpy # Install NJOY 2016 ./tools/ci/gha-install-njoy.sh From 091241070f33916208d732dab41d84ab73ca24fd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 23 Dec 2022 10:48:00 -0600 Subject: [PATCH 1568/2654] Update test results with numpy 1.24 and anisotropic fission --- .../adj_cell_rotation/results_true.dat | 2 +- .../asymmetric_lattice/results_true.dat | 2 +- .../cmfd_feed/results_true.dat | 614 +- .../cmfd_feed_2g/results_true.dat | 536 +- .../results_true.dat | 564 +- .../cmfd_feed_ng/results_true.dat | 708 +- .../cmfd_feed_rectlin/results_true.dat | 780 +- .../cmfd_feed_ref_d/results_true.dat | 564 +- .../cmfd_feed_rolling_window/results_true.dat | 564 +- .../cmfd_nofeed/results_true.dat | 614 +- .../cmfd_restart/results_true.dat | 614 +- .../complex_cell/results_true.dat | 18 +- .../confidence_intervals/results_true.dat | 6 +- .../dagmc/external/results_true.dat | 6 +- .../dagmc/legacy/results_true.dat | 6 +- .../dagmc/refl/results_true.dat | 6 +- .../dagmc/universes/results_true.dat | 2 +- .../regression_tests/density/results_true.dat | 2 +- .../last_step_reference_materials.xml | 1296 +- .../deplete_with_transport/test_reference.h5 | Bin 163736 -> 163736 bytes .../diff_tally/results_true.dat | 220 +- .../distribmat/results_true.dat | 2 +- .../eigenvalue_genperbatch/results_true.dat | 6 +- .../eigenvalue_no_inactive/results_true.dat | 2 +- .../energy_grid/results_true.dat | 2 +- .../regression_tests/entropy/results_true.dat | 20 +- .../filter_cellinstance/results_true.dat | 162 +- .../case-3/results_true.dat | 2 +- .../filter_mesh/results_true.dat | 2 +- .../filter_translations/results_true.dat | 674 +- .../infinite_cell/results_true.dat | 2 +- .../iso_in_lab/results_true.dat | 2 +- .../regression_tests/lattice/results_true.dat | 2 +- .../lattice_hex/results_true.dat | 2 +- .../lattice_hex_coincident/results_true.dat | 2 +- .../lattice_hex_x/results_true.dat | 2 +- .../lattice_multiple/results_true.dat | 2 +- .../lattice_rotated/results_true.dat | 2 +- .../mgxs_library_ce_to_mg/results_true.dat | 2 +- .../results_true.dat | 2 +- .../mgxs_library_condense/results_true.dat | 604 +- .../mgxs_library_correction/results_true.dat | 80 +- .../mgxs_library_distribcell/results_true.dat | 126 +- .../mgxs_library_hdf5/results_true.dat | 274 +- .../mgxs_library_histogram/results_true.dat | 672 +- .../mgxs_library_mesh/results_true.dat | 542 +- .../mgxs_library_no_nuclides/results_true.dat | 858 +- .../mgxs_library_nuclides/results_true.dat | 2 +- .../microxs/test_reference.csv | 24 +- .../multipole/results_true.dat | 54 +- .../regression_tests/output/results_true.dat | 2 +- .../periodic/results_true.dat | 2 +- .../periodic_6fold/results_true.dat | 2 +- .../periodic_hex/results_true.dat | 2 +- .../results_true.dat | 58 +- .../ptables_off/results_true.dat | 2 +- .../quadric_surfaces/results_true.dat | 2 +- .../reflective_plane/results_true.dat | 2 +- .../resonance_scattering/results_true.dat | 2 +- .../rotation/results_true.dat | 2 +- .../salphabeta/results_true.dat | 2 +- .../score_current/results_true.dat | 3178 +- tests/regression_tests/seed/results_true.dat | 2 +- .../regression_tests/source/results_true.dat | 2 +- .../source_file/results_true.dat | 2 +- .../source_mcpl_file/results_true.dat | 2 +- .../sourcepoint_batch/results_true.dat | 4 +- .../sourcepoint_latest/results_true.dat | 2 +- .../sourcepoint_restart/results_true.dat | 1472 +- .../statepoint_batch/results_true.dat | 2 +- .../statepoint_restart/results_true.dat | 2146 +- .../statepoint_sourcesep/results_true.dat | 2 +- .../surface_source/surface_source_true.h5 | Bin 106144 -> 106144 bytes .../surface_tally/results_true.dat | 84 +- .../survival_biasing/results_true.dat | 34 +- .../regression_tests/tallies/results_true.dat | 2 +- .../tally_aggregation/results_true.dat | 194 +- .../tally_arithmetic/results_true.dat | 98 +- .../tally_assumesep/results_true.dat | 14 +- .../tally_nuclides/results_true.dat | 50 +- .../tally_slice_merge/results_true.dat | 104 +- tests/regression_tests/torus/results_true.dat | 2 +- tests/regression_tests/trace/results_true.dat | 2 +- .../track_output/results_true.dat | 194 +- .../translation/results_true.dat | 2 +- .../trigger_batch_interval/results_true.dat | 50 +- .../results_true.dat | 50 +- .../trigger_no_status/results_true.dat | 50 +- .../results_true.dat | 6 +- .../trigger_tallies/results_true.dat | 50 +- tests/regression_tests/triso/results_true.dat | 2 +- .../uniform_fs/results_true.dat | 2 +- .../universe/results_true.dat | 2 +- .../unstructured_mesh/results_true.dat | 30000 +++------------- .../white_plane/results_true.dat | 2 +- tests/unit_tests/test_deplete_resultslist.py | 10 +- 96 files changed, 13550 insertions(+), 35598 deletions(-) diff --git a/tests/regression_tests/adj_cell_rotation/results_true.dat b/tests/regression_tests/adj_cell_rotation/results_true.dat index 2bdfe4330..b3df12e71 100644 --- a/tests/regression_tests/adj_cell_rotation/results_true.dat +++ b/tests/regression_tests/adj_cell_rotation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.381997E-01 1.286263E-03 +4.403987E-01 1.514158E-03 diff --git a/tests/regression_tests/asymmetric_lattice/results_true.dat b/tests/regression_tests/asymmetric_lattice/results_true.dat index 66ee9cdd2..741327d80 100644 --- a/tests/regression_tests/asymmetric_lattice/results_true.dat +++ b/tests/regression_tests/asymmetric_lattice/results_true.dat @@ -1 +1 @@ -73bae264aaca0988fd2ae207722461d161ddbcf9aef083b99a2efc536b09665bbe839d6cae89b32ebab3089a820a2c35ae63a88d5869f0c91b0d6c2f2e090e55 \ No newline at end of file +b0ca1fb0436732188b1a199b3250ca9a33782f8fc379b0f7ff9c582e0c794b0a0470df063cafd0b05e802b26f61eaaf9ff5c0a8a672a933246acf49eed3ebf9f \ No newline at end of file diff --git a/tests/regression_tests/cmfd_feed/results_true.dat b/tests/regression_tests/cmfd_feed/results_true.dat index 90d8820d0..f5f22d9ac 100644 --- a/tests/regression_tests/cmfd_feed/results_true.dat +++ b/tests/regression_tests/cmfd_feed/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.159021E+00 8.924006E-03 +1.164262E+00 9.207592E-03 tally 1: -1.140162E+01 -1.306940E+01 -2.093739E+01 -4.404780E+01 -2.914408E+01 -8.521010E+01 -3.483677E+01 -1.216824E+02 -3.778463E+01 -1.429632E+02 -3.810371E+01 -1.455108E+02 -3.465248E+01 -1.207868E+02 -2.862033E+01 -8.218833E+01 -2.086025E+01 -4.365941E+01 -1.130798E+01 -1.286509E+01 +1.156972E+01 +1.339924E+01 +2.136306E+01 +4.567185E+01 +2.859527E+01 +8.195821E+01 +3.470754E+01 +1.207851E+02 +3.766403E+01 +1.422263E+02 +3.778821E+01 +1.432660E+02 +3.573197E+01 +1.278854E+02 +2.849979E+01 +8.135515E+01 +2.073803E+01 +4.303374E+01 +1.112117E+01 +1.242944E+01 tally 2: -2.234393E+01 -2.516414E+01 -1.555024E+01 -1.218205E+01 -4.087743E+01 -8.401702E+01 -2.883717E+01 -4.185393E+01 -5.635166E+01 -1.595225E+02 -3.998857E+01 -8.040398E+01 -6.887126E+01 -2.379185E+02 -4.903103E+01 -1.206174E+02 -7.452051E+01 -2.785675E+02 -5.295380E+01 -1.406900E+02 -7.495422E+01 -2.819070E+02 -5.333191E+01 -1.427474E+02 -6.921815E+01 -2.408568E+02 -4.928246E+01 -1.221076E+02 -5.668548E+01 -1.612556E+02 -4.035856E+01 -8.181159E+01 -4.259952E+01 -9.112630E+01 -3.026717E+01 -4.600625E+01 -2.310563E+01 -2.688378E+01 -1.615934E+01 -1.315528E+01 +2.388054E+01 +2.875255E+01 +1.667791E+01 +1.403426E+01 +4.224771E+01 +8.942109E+01 +2.993088E+01 +4.490335E+01 +5.689839E+01 +1.625557E+02 +4.043633E+01 +8.212299E+01 +6.764024E+01 +2.297126E+02 +4.807902E+01 +1.161468E+02 +7.314835E+01 +2.684645E+02 +5.203584E+01 +1.359261E+02 +7.375727E+01 +2.733105E+02 +5.252944E+01 +1.386205E+02 +6.909571E+01 +2.397721E+02 +4.922548E+01 +1.217465E+02 +5.685978E+01 +1.621746E+02 +4.051938E+01 +8.237277E+01 +4.185562E+01 +8.784067E+01 +2.983570E+01 +4.467414E+01 +2.238373E+01 +2.520356E+01 +1.566758E+01 +1.234103E+01 tally 3: -1.496375E+01 -1.128154E+01 -9.905641E-01 -5.125710E-02 -2.774937E+01 -3.877241E+01 -1.786861E+00 -1.627655E-01 -3.849739E+01 -7.453828E+01 -2.494135E+00 -3.158098E-01 -4.724085E+01 -1.119901E+02 -3.031174E+00 -4.653741E-01 -5.096719E+01 -1.303552E+02 -3.254375E+00 -5.351020E-01 -5.133808E+01 -1.322892E+02 -3.383595E+00 -5.798798E-01 -4.756072E+01 -1.137527E+02 -3.001917E+00 -4.558247E-01 -3.887437E+01 -7.593416E+01 -2.517908E+00 -3.221926E-01 -2.910687E+01 -4.255173E+01 -1.817765E+00 -1.678763E-01 -1.557241E+01 -1.222026E+01 -9.852737E-01 -5.002659E-02 +1.609520E+01 +1.307542E+01 +1.033429E+00 +5.510889E-02 +2.877073E+01 +4.149542E+01 +1.964219E+00 +1.954692E-01 +3.896816E+01 +7.629752E+01 +2.484053E+00 +3.103733E-01 +4.634285E+01 +1.079367E+02 +2.974750E+00 +4.468223E-01 +5.007964E+01 +1.259202E+02 +3.181802E+00 +5.103621E-01 +5.058915E+01 +1.286193E+02 +3.249442E+00 +5.337712E-01 +4.744464E+01 +1.131026E+02 +3.067644E+00 +4.736335E-01 +3.900632E+01 +7.634433E+01 +2.443552E+00 +3.028060E-01 +2.874166E+01 +4.146375E+01 +1.810421E+00 +1.671667E-01 +1.509222E+01 +1.145579E+01 +1.014919E+00 +5.391053E-02 tally 4: -3.047490E+00 -4.661458E-01 +3.148231E+00 +4.974555E-01 0.000000E+00 0.000000E+00 -2.635775E+00 -3.524426E-01 -5.357229E+00 -1.440049E+00 +2.805439E+00 +3.982239E-01 +5.574031E+00 +1.561105E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.357229E+00 -1.440049E+00 -2.635775E+00 -3.524426E-01 -4.982072E+00 -1.251449E+00 -7.228146E+00 -2.620353E+00 +5.574031E+00 +1.561105E+00 +2.805439E+00 +3.982239E-01 +5.171038E+00 +1.344877E+00 +7.372031E+00 +2.725420E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.228146E+00 -2.620353E+00 -4.982072E+00 -1.251449E+00 -7.082265E+00 -2.520047E+00 -8.736529E+00 -3.831244E+00 +7.372031E+00 +2.725420E+00 +5.171038E+00 +1.344877E+00 +6.946847E+00 +2.424850E+00 +8.496610E+00 +3.627542E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.736529E+00 -3.831244E+00 -7.082265E+00 -2.520047E+00 -8.474631E+00 -3.607043E+00 -9.346623E+00 -4.390819E+00 +8.496610E+00 +3.627542E+00 +6.946847E+00 +2.424850E+00 +8.479501E+00 +3.607280E+00 +9.261869E+00 +4.305912E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.346623E+00 -4.390819E+00 -8.474631E+00 -3.607043E+00 -9.496684E+00 -4.522478E+00 -9.532822E+00 -4.559003E+00 +9.261869E+00 +4.305912E+00 +8.479501E+00 +3.607280E+00 +9.232858E+00 +4.278432E+00 +9.306384E+00 +4.348594E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.532822E+00 -4.559003E+00 -9.496684E+00 -4.522478E+00 -9.404949E+00 -4.446260E+00 -8.550930E+00 -3.668401E+00 +9.306384E+00 +4.348594E+00 +9.232858E+00 +4.278432E+00 +9.299764E+00 +4.347828E+00 +8.511976E+00 +3.639893E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.550930E+00 -3.668401E+00 -9.404949E+00 -4.446260E+00 -8.785273E+00 -3.874792E+00 -7.128863E+00 -2.554326E+00 +8.511976E+00 +3.639893E+00 +9.299764E+00 +4.347828E+00 +8.726086E+00 +3.819567E+00 +7.147277E+00 +2.562747E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.128863E+00 -2.554326E+00 -8.785273E+00 -3.874792E+00 -7.408549E+00 -2.755885E+00 -5.094992E+00 -1.305737E+00 +7.147277E+00 +2.562747E+00 +8.726086E+00 +3.819567E+00 +7.218790E+00 +2.612243E+00 +5.018287E+00 +1.263077E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.094992E+00 -1.305737E+00 -7.408549E+00 -2.755885E+00 -5.532149E+00 -1.537289E+00 -2.812344E+00 -3.997146E-01 +5.018287E+00 +1.263077E+00 +7.218790E+00 +2.612243E+00 +5.443494E+00 +1.487018E+00 +2.732334E+00 +3.773047E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.812344E+00 -3.997146E-01 -5.532149E+00 -1.537289E+00 -3.063251E+00 -4.728672E-01 +2.732334E+00 +3.773047E-01 +5.443494E+00 +1.487018E+00 +3.044773E+00 +4.655756E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,144 +345,144 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -1.496000E+01 -1.127586E+01 -2.280081E+00 -2.675609E-01 -2.774503E+01 -3.876011E+01 -3.908836E+00 -7.703029E-01 -3.848706E+01 -7.449836E+01 -5.299924E+00 -1.422782E+00 -4.723172E+01 -1.119459E+02 -6.450156E+00 -2.105590E+00 -5.095931E+01 -1.303132E+02 -7.050681E+00 -2.515092E+00 -5.133412E+01 -1.322694E+02 -6.853429E+00 -2.384127E+00 -4.754621E+01 -1.136848E+02 -6.370026E+00 -2.058896E+00 -3.886829E+01 -7.591042E+01 -5.266816E+00 -1.400495E+00 -2.910277E+01 -4.253981E+01 -4.090844E+00 -8.442500E-01 -1.556949E+01 -1.221526E+01 -2.266123E+00 -2.641551E-01 +1.609029E+01 +1.306718E+01 +2.230601E+00 +2.559496E-01 +2.876780E+01 +4.148686E+01 +3.835952E+00 +7.456562E-01 +3.895738E+01 +7.625344E+01 +4.841024E+00 +1.197335E+00 +4.633595E+01 +1.079043E+02 +6.236821E+00 +1.963311E+00 +5.007472E+01 +1.258967E+02 +6.749745E+00 +2.297130E+00 +5.058336E+01 +1.285894E+02 +6.727612E+00 +2.315656E+00 +4.743869E+01 +1.130735E+02 +6.338193E+00 +2.042159E+00 +3.899838E+01 +7.631289E+01 +5.187573E+00 +1.359733E+00 +2.873434E+01 +4.144233E+01 +3.815610E+00 +7.367619E-01 +1.509020E+01 +1.145268E+01 +2.125767E+00 +2.341894E-01 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.161531E+00 -1.182724E+00 -1.169653E+00 -1.164722E+00 -1.164583E+00 -1.162952E+00 -1.167024E+00 -1.164509E+00 -1.165693E+00 -1.170623E+00 -1.166618E+00 -1.170805E+00 -1.170962E+00 -1.170964E+00 -1.168224E+00 -1.169864E+00 +1.129918E+00 +1.143848E+00 +1.147976E+00 +1.151534E+00 +1.152378E+00 +1.148219E+00 +1.150402E+00 +1.154647E+00 +1.156159E+00 +1.160048E+00 +1.167441E+00 +1.168163E+00 +1.168629E+00 +1.164120E+00 +1.165051E+00 +1.169177E+00 cmfd entropy -3.206619E+00 -3.205815E+00 -3.208678E+00 -3.210820E+00 -3.217023E+00 -3.215014E+00 -3.214592E+00 -3.215913E+00 -3.214998E+00 -3.213644E+00 -3.210755E+00 -3.210496E+00 -3.212488E+00 -3.211553E+00 -3.212999E+00 -3.214052E+00 +3.224769E+00 +3.225945E+00 +3.227421E+00 +3.226174E+00 +3.224429E+00 +3.227049E+00 +3.230710E+00 +3.230315E+00 +3.226825E+00 +3.226655E+00 +3.226588E+00 +3.224155E+00 +3.223246E+00 +3.222640E+00 +3.223920E+00 +3.222838E+00 cmfd balance -4.99833E-03 -5.64677E-03 -3.62795E-03 -3.91962E-03 -3.87172E-03 -2.48450E-03 -3.15554E-03 -2.49335E-03 -2.31973E-03 -2.19156E-03 -2.31352E-03 -2.03401E-03 -1.80242E-03 -1.65868E-03 -1.47543E-03 -1.49706E-03 +3.90454E-03 +4.08089E-03 +3.46511E-03 +4.09535E-03 +2.62009E-03 +2.23559E-03 +2.54033E-03 +2.12799E-03 +2.25864E-03 +1.85766E-03 +1.49916E-03 +1.63471E-03 +1.48377E-03 +1.59800E-03 +1.37354E-03 +1.32853E-03 cmfd dominance ratio -5.283E-01 -5.289E-01 -5.305E-01 -5.327E-01 -5.377E-01 -5.360E-01 -5.353E-01 -4.983E-01 -5.379E-01 -5.370E-01 -5.359E-01 -5.349E-01 -5.364E-01 -5.347E-01 -5.360E-01 -5.378E-01 +5.539E-01 +5.537E-01 +5.536E-01 +5.515E-01 +5.512E-01 +5.514E-01 +5.518E-01 +5.507E-01 +5.500E-01 +5.497E-01 +5.477E-01 +5.461E-01 +5.444E-01 +5.445E-01 +5.454E-01 +5.441E-01 cmfd openmc source comparison -1.291827E-02 -1.027137E-02 -8.738370E-03 -6.854409E-03 -4.188357E-03 -4.941359E-03 -5.139239E-03 -4.244784E-03 -4.240559E-03 -3.375424E-03 -3.716858E-03 -3.595700E-03 -3.626952E-03 -3.999302E-03 -2.431760E-03 -1.673200E-03 +9.875240E-03 +1.106163E-02 +9.847628E-03 +6.065921E-03 +5.772039E-03 +4.615656E-03 +4.244331E-03 +3.694299E-03 +3.545814E-03 +3.213063E-03 +3.467537E-03 +3.383489E-03 +3.697591E-03 +3.937358E-03 +3.369124E-03 +3.190359E-03 cmfd source -4.185460E-02 -7.636314E-02 -1.075536E-01 -1.307167E-01 -1.400879E-01 -1.459944E-01 -1.297413E-01 -1.084649E-01 -7.772031E-02 -4.150306E-02 +4.360494E-02 +8.397599E-02 +1.074181E-01 +1.294531E-01 +1.385611E-01 +1.407934E-01 +1.325191E-01 +1.044311E-01 +7.660359E-02 +4.263941E-02 diff --git a/tests/regression_tests/cmfd_feed_2g/results_true.dat b/tests/regression_tests/cmfd_feed_2g/results_true.dat index d27e291e7..2b61d9f4e 100644 --- a/tests/regression_tests/cmfd_feed_2g/results_true.dat +++ b/tests/regression_tests/cmfd_feed_2g/results_true.dat @@ -1,112 +1,112 @@ k-combined: -1.021592E+00 7.184545E-03 +1.035567E+00 9.463160E-03 tally 1: -1.158654E+02 -1.342707E+03 -1.151877E+02 -1.327269E+03 -1.153781E+02 -1.331661E+03 -1.151151E+02 -1.325578E+03 +1.146535E+02 +1.315267E+03 +1.157458E+02 +1.340166E+03 +1.140491E+02 +1.301364E+03 +1.146589E+02 +1.315433E+03 tally 2: -4.299142E+01 -9.258204E+01 -6.324043E+01 -2.003732E+02 -1.860419E+02 -1.731270E+03 -1.037502E+02 -5.383979E+02 -4.229132E+01 -8.952923E+01 -6.264581E+01 -1.965074E+02 -1.838340E+02 -1.690620E+03 -1.029415E+02 -5.299801E+02 -4.314759E+01 -9.337463E+01 -6.404361E+01 -2.056541E+02 -1.836548E+02 -1.687065E+03 -1.028141E+02 -5.287334E+02 -4.256836E+01 -9.079806E+01 -6.336524E+01 -2.012627E+02 -1.837730E+02 -1.689124E+03 -1.021852E+02 -5.222598E+02 +4.319968E+01 +9.360083E+01 +6.373035E+01 +2.038056E+02 +1.889646E+02 +1.812892E+03 +1.024866E+02 +5.254528E+02 +4.323262E+01 +9.360200E+01 +6.363111E+01 +2.028178E+02 +1.849746E+02 +1.711533E+03 +1.034532E+02 +5.352768E+02 +4.296541E+01 +9.249656E+01 +6.346919E+01 +2.018659E+02 +1.888697E+02 +1.812037E+03 +1.025707E+02 +5.262261E+02 +4.691085E+01 +1.269707E+02 +6.299377E+01 +1.990497E+02 +1.853864E+02 +1.719984E+03 +1.023015E+02 +5.235858E+02 tally 3: -5.973628E+01 -1.787876E+02 +6.034963E+01 +1.827718E+02 0.000000E+00 0.000000E+00 -1.724004E-02 -2.766372E-05 -4.379655E+00 -9.682433E-01 -3.484795E+00 -6.104792E-01 +1.865665E-02 +4.244195E-05 +4.170941E+00 +8.769372E-01 +3.453368E+00 +5.989168E-01 0.000000E+00 0.000000E+00 -9.874445E+01 -4.877157E+02 -8.886034E-01 -4.009294E-02 -5.923584E+01 -1.757014E+02 +9.743205E+01 +4.749420E+02 +8.570316E-01 +3.807993E-02 +6.005903E+01 +1.807233E+02 0.000000E+00 0.000000E+00 -1.733168E-02 -3.950365E-05 -4.212697E+00 -8.996477E-01 -3.503046E+00 -6.150657E-01 +1.885450E-02 +3.653402E-05 +4.323863E+00 +9.447512E-01 +3.465465E+00 +6.022861E-01 0.000000E+00 0.000000E+00 -9.780995E+01 -4.784706E+02 -8.648283E-01 -3.899383E-02 -6.057017E+01 -1.839745E+02 +9.843481E+01 +4.846158E+02 +9.048150E-01 +4.205551E-02 +5.996660E+01 +1.802150E+02 0.000000E+00 0.000000E+00 -2.056597E-02 -3.726744E-05 -4.280120E+00 -9.288225E-01 -3.378205E+00 -5.730279E-01 +1.221444E-02 +2.263445E-05 +4.301287E+00 +9.309882E-01 +3.456076E+00 +5.992144E-01 0.000000E+00 0.000000E+00 -9.790474E+01 -4.794523E+02 -9.073765E-01 -4.204720E-02 -5.990874E+01 -1.799224E+02 +9.761231E+01 +4.765834E+02 +8.434644E-01 +3.728180E-02 +5.961891E+01 +1.783106E+02 0.000000E+00 0.000000E+00 -1.881508E-02 -4.239902E-05 -4.206916E+00 -8.926965E-01 -3.478009E+00 -6.067461E-01 +1.500709E-02 +3.541280E-05 +4.155669E+00 +8.713442E-01 +3.455342E+00 +6.006426E-01 0.000000E+00 0.000000E+00 -9.715787E+01 -4.721453E+02 -8.602457E-01 -3.786346E-02 +9.726798E+01 +4.733393E+02 +9.202611E-01 +4.390503E-02 tally 4: 0.000000E+00 0.000000E+00 @@ -116,14 +116,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.735001E+00 -3.821211E+00 -3.708124E+01 -6.880811E+01 -8.713175E+00 -3.807176E+00 -3.703536E+01 -6.862245E+01 +8.943264E+00 +4.008855E+00 +3.661063E+01 +6.704808E+01 +8.945553E+00 +4.011707E+00 +3.696832E+01 +6.835286E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -132,14 +132,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.851322E+00 -3.930766E+00 -3.716154E+01 -6.908449E+01 -8.892499E+00 -3.970458E+00 -3.718644E+01 -6.918810E+01 +8.844569E+00 +3.924591E+00 +3.666726E+01 +6.726522E+01 +8.769637E+00 +3.855006E+00 +3.654115E+01 +6.680777E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -156,14 +156,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.713175E+00 -3.807176E+00 -3.703536E+01 -6.862245E+01 -8.735001E+00 -3.821211E+00 -3.708124E+01 -6.880811E+01 +8.945553E+00 +4.011707E+00 +3.696832E+01 +6.835286E+01 +8.943264E+00 +4.008855E+00 +3.661063E+01 +6.704808E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -180,14 +180,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.915310E+00 -3.982710E+00 -3.682783E+01 -6.786998E+01 -8.800405E+00 -3.881868E+00 -3.692302E+01 -6.819716E+01 +8.648474E+00 +3.752219E+00 +3.689442E+01 +6.808997E+01 +8.757378E+00 +3.850408E+00 +3.716920E+01 +6.909715E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -212,22 +212,22 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.659918E+00 -3.761908E+00 -3.709957E+01 -6.884298E+01 -8.796329E+00 -3.881588E+00 -3.693599E+01 -6.825932E+01 -8.892499E+00 -3.970458E+00 -3.718644E+01 -6.918810E+01 -8.851322E+00 -3.930766E+00 -3.716154E+01 -6.908449E+01 +8.783669E+00 +3.870748E+00 +3.687358E+01 +6.802581E+01 +8.755250E+00 +3.846298E+00 +3.660278E+01 +6.704349E+01 +8.769637E+00 +3.855006E+00 +3.654115E+01 +6.680777E+01 +8.844569E+00 +3.924591E+00 +3.666726E+01 +6.726522E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -252,14 +252,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.796329E+00 -3.881588E+00 -3.693599E+01 -6.825932E+01 -8.659918E+00 -3.761908E+00 -3.709957E+01 -6.884298E+01 +8.755250E+00 +3.846298E+00 +3.660278E+01 +6.704349E+01 +8.783669E+00 +3.870748E+00 +3.687358E+01 +6.802581E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -268,14 +268,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.800405E+00 -3.881868E+00 -3.692302E+01 -6.819716E+01 -8.915310E+00 -3.982710E+00 -3.682783E+01 -6.786998E+01 +8.757378E+00 +3.850408E+00 +3.716920E+01 +6.909715E+01 +8.648474E+00 +3.752219E+00 +3.689442E+01 +6.808997E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -301,133 +301,133 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -5.975352E+01 -1.788900E+02 -1.022213E+02 -5.226556E+02 -1.378440E+01 -9.544964E+00 -4.668065E+01 -1.090372E+02 -5.925317E+01 -1.758044E+02 -1.013043E+02 -5.132587E+02 -1.356187E+01 -9.210736E+00 -4.606346E+01 -1.061497E+02 -6.059074E+01 -1.840993E+02 -1.012721E+02 -5.130091E+02 -1.356441E+01 -9.262377E+00 -4.634250E+01 -1.074283E+02 -5.992755E+01 -1.800342E+02 -1.006299E+02 -5.065012E+02 -1.370402E+01 -9.450980E+00 -4.575433E+01 -1.047310E+02 +6.036829E+01 +1.828885E+02 +1.008777E+02 +5.091033E+02 +1.353211E+01 +9.188155E+00 +4.618716E+01 +1.067410E+02 +6.007789E+01 +1.808371E+02 +1.018892E+02 +5.192269E+02 +1.357961E+01 +9.247052E+00 +4.618560E+01 +1.067058E+02 +5.997882E+01 +1.802895E+02 +1.010597E+02 +5.108478E+02 +1.374955E+01 +9.502494E+00 +4.619500E+01 +1.067547E+02 +5.963392E+01 +1.783999E+02 +1.007134E+02 +5.074700E+02 +1.319398E+01 +8.734106E+00 +4.586295E+01 +1.052870E+02 cmfd indices 2.000000E+00 2.000000E+00 1.000000E+00 2.000000E+00 k cmfd -1.037231E+00 -1.035671E+00 -1.042384E+00 -1.033525E+00 -1.031304E+00 -1.029654E+00 -1.031704E+00 -1.032213E+00 -1.030500E+00 -1.036227E+00 -1.034924E+00 -1.035753E+00 -1.034679E+00 -1.035096E+00 -1.033818E+00 -1.030023E+00 +1.018115E+00 +1.022665E+00 +1.020323E+00 +1.020653E+00 +1.021036E+00 +1.020623E+00 +1.021482E+00 +1.025450E+00 +1.027292E+00 +1.028065E+00 +1.027065E+00 +1.024275E+00 +1.025309E+00 +1.026039E+00 +1.026700E+00 +1.023865E+00 cmfd entropy -1.999702E+00 -1.999790E+00 -1.999713E+00 -1.999852E+00 -1.999820E+00 -1.999667E+00 -1.999553E+00 -1.999649E+00 -1.999398E+00 -1.999527E+00 -1.999648E+00 -1.999607E+00 +1.998965E+00 +1.999214E+00 +1.999348E+00 +1.999366E+00 +1.999564E+00 +1.999453E+00 1.999533E+00 -1.999684E+00 -1.999714E+00 -1.999812E+00 +1.999630E+00 +1.999739E+00 +1.999588E+00 +1.999581E+00 +1.999719E+00 +1.999773E+00 +1.999764E+00 +1.999821E+00 +1.999843E+00 cmfd balance -7.33587E-04 -1.00987E-03 -8.26985E-04 -5.20809E-04 -6.47932E-04 -9.69990E-04 -8.62860E-04 -4.92175E-04 -5.80764E-04 -4.49167E-04 -4.05541E-04 -4.13811E-04 -4.27271E-04 -3.64944E-04 -3.43522E-04 -2.82842E-04 +5.73174E-04 +7.55398E-04 +1.46671E-03 +6.39625E-04 +8.19008E-04 +1.93449E-03 +1.15900E-03 +1.01690E-03 +5.62788E-04 +6.90450E-04 +6.01060E-04 +5.73418E-04 +4.37190E-04 +4.82966E-04 +4.09700E-04 +3.45096E-04 cmfd dominance ratio -6.259E-03 -6.252E-03 -6.292E-03 -6.347E-03 -6.360E-03 -6.403E-03 -6.375E-03 -6.400E-03 -6.374E-03 -6.343E-03 -6.331E-03 -6.312E-03 -6.305E-03 -6.271E-03 -6.267E-03 -6.265E-03 +6.264E-03 +6.142E-03 +5.987E-03 +6.082E-03 +5.895E-03 +5.939E-03 +5.910E-03 +5.948E-03 +6.013E-03 +6.017E-03 +6.024E-03 +6.008E-03 +5.976E-03 +5.987E-03 +5.967E-03 +5.929E-03 cmfd openmc source comparison -7.908947E-05 -7.452591E-05 -9.249409E-05 -8.223037E-05 -7.355125E-05 -8.926808E-05 -9.363510E-05 -7.628519E-05 -9.019193E-05 -7.130550E-05 -5.947633E-05 -5.744157E-05 -6.093797E-05 -4.505304E-05 -4.430670E-05 -3.019083E-05 +4.832872E-05 +6.552342E-05 +7.516800E-05 +7.916087E-05 +9.022260E-05 +8.574478E-05 +7.891622E-05 +7.281636E-05 +7.750571E-05 +6.565408E-05 +6.078665E-05 +5.834343E-05 +4.758176E-05 +5.723990E-05 +4.994116E-05 +4.116808E-05 cmfd source -2.557606E-01 -2.464707E-01 -2.518098E-01 -2.459589E-01 +2.455663E-01 +2.553511E-01 +2.512257E-01 +2.478570E-01 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat b/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat index a235a9f6f..8fd8cdbb8 100644 --- a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat +++ b/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.184725E+00 9.808181E-03 +1.167865E+00 7.492213E-03 tally 1: -1.121111E+01 -1.261033E+01 -2.101271E+01 -4.433294E+01 -2.782926E+01 -7.776546E+01 -3.351044E+01 -1.125084E+02 -3.625691E+01 -1.319666E+02 -3.741881E+01 -1.403776E+02 -3.538049E+01 -1.255798E+02 -3.030311E+01 -9.228152E+01 -2.188389E+01 -4.811272E+01 -1.172417E+01 -1.379179E+01 +1.146860E+01 +1.318884E+01 +2.161527E+01 +4.685283E+01 +2.951158E+01 +8.733566E+01 +3.521610E+01 +1.242821E+02 +3.774236E+01 +1.426501E+02 +3.727918E+01 +1.391158E+02 +3.377176E+01 +1.143839E+02 +2.904497E+01 +8.452907E+01 +2.090871E+01 +4.384549E+01 +1.078642E+01 +1.168086E+01 tally 2: -1.146940E+00 -1.315471E+00 -8.068187E-01 -6.509564E-01 -2.070090E+00 -4.285274E+00 -1.469029E+00 -2.158045E+00 -2.703224E+00 -7.307421E+00 -1.895589E+00 -3.593259E+00 -3.567634E+00 -1.272801E+01 -2.541493E+00 -6.459185E+00 -3.937463E+00 -1.550361E+01 -2.770463E+00 -7.675465E+00 -3.960472E+00 -1.568534E+01 -2.792668E+00 -7.798997E+00 -3.243459E+00 -1.052002E+01 -2.296673E+00 -5.274706E+00 -2.794726E+00 -7.810492E+00 -1.953143E+00 -3.814769E+00 -2.187302E+00 -4.784292E+00 -1.544500E+00 -2.385481E+00 -1.199609E+00 -1.439061E+00 -8.356062E-01 -6.982377E-01 +1.136810E+00 +1.292338E+00 +7.987303E-01 +6.379700E-01 +2.266938E+00 +5.139009E+00 +1.613483E+00 +2.603328E+00 +3.046349E+00 +9.280239E+00 +2.182459E+00 +4.763126E+00 +3.568068E+00 +1.273111E+01 +2.532456E+00 +6.413333E+00 +3.989504E+00 +1.591614E+01 +2.848301E+00 +8.112818E+00 +3.853133E+00 +1.484663E+01 +2.718493E+00 +7.390202E+00 +3.478138E+00 +1.209745E+01 +2.467281E+00 +6.087476E+00 +2.952220E+00 +8.715605E+00 +2.103261E+00 +4.423706E+00 +1.917459E+00 +3.676649E+00 +1.378369E+00 +1.899902E+00 +1.048240E+00 +1.098807E+00 +7.511947E-01 +5.642934E-01 tally 3: -7.817522E-01 -6.111366E-01 -5.930056E-02 -3.516556E-03 -1.426374E+00 -2.034542E+00 -8.539281E-02 -7.291931E-03 -1.815687E+00 -3.296718E+00 -1.221592E-01 -1.492286E-02 -2.447191E+00 -5.988744E+00 -1.624835E-01 -2.640090E-02 -2.670084E+00 -7.129351E+00 -1.838317E-01 -3.379411E-02 -2.683007E+00 -7.198528E+00 -1.719716E-01 -2.957424E-02 -2.215446E+00 -4.908202E+00 -1.707856E-01 -2.916773E-02 -1.872330E+00 -3.505620E+00 -1.209731E-01 -1.463450E-02 -1.484167E+00 -2.202752E+00 -1.114851E-01 -1.242892E-02 -8.018653E-01 -6.429879E-01 -5.692854E-02 -3.240858E-03 +7.701233E-01 +5.930898E-01 +4.481585E-02 +2.008461E-03 +1.547307E+00 +2.394158E+00 +1.226539E-01 +1.504398E-02 +2.106373E+00 +4.436806E+00 +1.450618E-01 +2.104294E-02 +2.437654E+00 +5.942157E+00 +1.521380E-01 +2.314598E-02 +2.754639E+00 +7.588038E+00 +1.745460E-01 +3.046629E-02 +2.623852E+00 +6.884601E+00 +1.851602E-01 +3.428432E-02 +2.376886E+00 +5.649588E+00 +1.615729E-01 +2.610582E-02 +2.021856E+00 +4.087900E+00 +1.533174E-01 +2.350622E-02 +1.333190E+00 +1.777397E+00 +7.076188E-02 +5.007243E-03 +7.258527E-01 +5.268622E-01 +3.656030E-02 +1.336656E-03 tally 4: -1.404203E-01 -1.971786E-02 +1.667432E-01 +2.780328E-02 0.000000E+00 0.000000E+00 -1.383954E-01 -1.915329E-02 -2.626162E-01 -6.896729E-02 +1.292567E-01 +1.670730E-02 +2.813370E-01 +7.915052E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.626162E-01 -6.896729E-02 -1.383954E-01 -1.915329E-02 -2.300607E-01 -5.292793E-02 -3.213893E-01 -1.032911E-01 +2.813370E-01 +7.915052E-02 +1.292567E-01 +1.670730E-02 +2.670549E-01 +7.131835E-02 +4.055324E-01 +1.644566E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.213893E-01 -1.032911E-01 -2.300607E-01 -5.292793E-02 -3.621797E-01 -1.311741E-01 -4.326081E-01 -1.871498E-01 +4.055324E-01 +1.644566E-01 +2.670549E-01 +7.131835E-02 +3.848125E-01 +1.480807E-01 +4.809430E-01 +2.313062E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.326081E-01 -1.871498E-01 -3.621797E-01 -1.311741E-01 -4.274873E-01 -1.827454E-01 -4.701391E-01 -2.210307E-01 +4.809430E-01 +2.313062E-01 +3.848125E-01 +1.480807E-01 +4.543918E-01 +2.064719E-01 +5.106133E-01 +2.607260E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.701391E-01 -2.210307E-01 -4.274873E-01 -1.827454E-01 -4.867763E-01 -2.369512E-01 -5.027339E-01 -2.527413E-01 +5.106133E-01 +2.607260E-01 +4.543918E-01 +2.064719E-01 +4.543120E-01 +2.063994E-01 +4.626328E-01 +2.140291E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.027339E-01 -2.527413E-01 -4.867763E-01 -2.369512E-01 -4.679231E-01 -2.189520E-01 -4.504626E-01 -2.029166E-01 +4.626328E-01 +2.140291E-01 +4.543120E-01 +2.063994E-01 +4.827759E-01 +2.330726E-01 +4.442622E-01 +1.973689E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.504626E-01 -2.029166E-01 -4.679231E-01 -2.189520E-01 -4.340994E-01 -1.884423E-01 -3.622741E-01 -1.312425E-01 +4.442622E-01 +1.973689E-01 +4.827759E-01 +2.330726E-01 +4.630420E-01 +2.144079E-01 +3.886524E-01 +1.510507E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.622741E-01 -1.312425E-01 -4.340994E-01 -1.884423E-01 -3.743415E-01 -1.401316E-01 -2.666952E-01 -7.112632E-02 +3.886524E-01 +1.510507E-01 +4.630420E-01 +2.144079E-01 +3.535870E-01 +1.250237E-01 +2.530312E-01 +6.402478E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.666952E-01 -7.112632E-02 -3.743415E-01 -1.401316E-01 -2.832774E-01 -8.024609E-02 -1.469617E-01 -2.159775E-02 +2.530312E-01 +6.402478E-02 +3.535870E-01 +1.250237E-01 +2.465524E-01 +6.078808E-02 +1.197152E-01 +1.433173E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.469617E-01 -2.159775E-02 -2.832774E-01 -8.024609E-02 -1.514998E-01 -2.295220E-02 +1.197152E-01 +1.433173E-02 +2.465524E-01 +6.078808E-02 +1.369631E-01 +1.875888E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,119 +345,119 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -7.817522E-01 -6.111366E-01 -1.254009E-01 -1.572539E-02 -1.426374E+00 -2.034542E+00 -2.208879E-01 -4.879148E-02 -1.815687E+00 -3.296718E+00 -2.598747E-01 -6.753484E-02 -2.446236E+00 -5.984069E+00 -3.067269E-01 -9.408137E-02 -2.670084E+00 -7.129351E+00 -3.358701E-01 -1.128087E-01 -2.682078E+00 -7.193544E+00 -3.021763E-01 -9.131050E-02 -2.215446E+00 -4.908202E+00 -3.092066E-01 -9.560869E-02 -1.871260E+00 -3.501614E+00 -2.400592E-01 -5.762841E-02 -1.483097E+00 -2.199577E+00 -2.197780E-01 -4.830237E-02 -8.009060E-01 -6.414504E-01 -1.023121E-01 -1.046776E-02 +7.701233E-01 +5.930898E-01 +1.386250E-01 +1.921688E-02 +1.547307E+00 +2.394158E+00 +2.630277E-01 +6.918357E-02 +2.106373E+00 +4.436806E+00 +2.807880E-01 +7.884187E-02 +2.435849E+00 +5.933361E+00 +3.322060E-01 +1.103608E-01 +2.753634E+00 +7.582501E+00 +3.825922E-01 +1.463768E-01 +2.623852E+00 +6.884601E+00 +3.888710E-01 +1.512206E-01 +2.376886E+00 +5.649588E+00 +3.196217E-01 +1.021581E-01 +2.021856E+00 +4.087900E+00 +2.897881E-01 +8.397715E-02 +1.333190E+00 +1.777397E+00 +1.627110E-01 +2.647486E-02 +7.258527E-01 +5.268622E-01 +9.348666E-02 +8.739755E-03 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.165553E+00 -1.179705E+00 -1.191818E+00 -1.207372E+00 -1.203745E+00 -1.208055E+00 -1.208191E+00 -1.201797E+00 -1.201945E+00 -1.203753E+00 -1.209025E+00 +1.149077E+00 +1.156751E+00 +1.158648E+00 +1.159506E+00 +1.156567E+00 +1.160259E+00 +1.150345E+00 +1.149846E+00 +1.151606E+00 +1.164544E+00 +1.174648E+00 cmfd entropy -3.217557E+00 -3.209881E+00 -3.204672E+00 -3.212484E+00 -3.217253E+00 -3.216845E+00 -3.219057E+00 -3.217057E+00 -3.223643E+00 -3.230985E+00 -3.230377E+00 +3.216173E+00 +3.228717E+00 +3.220402E+00 +3.214352E+00 +3.215636E+00 +3.213599E+00 +3.212854E+00 +3.213131E+00 +3.213196E+00 +3.205474E+00 +3.202869E+00 cmfd balance -1.65304E-03 -2.29940E-03 -1.63416E-03 -1.39975E-03 -1.91312E-03 -1.62824E-03 -1.95516E-03 -2.02934E-03 -1.92846E-03 -2.33117E-03 -2.29845E-03 +3.08825E-03 +1.42345E-03 +1.21253E-03 +1.17694E-03 +1.05901E-03 +9.29611E-04 +1.35587E-03 +1.13579E-03 +1.14964E-03 +1.29313E-03 +1.46566E-03 cmfd dominance ratio -5.465E-01 -5.481E-01 -5.432E-01 -5.459E-01 -5.463E-01 -5.486E-01 -5.515E-01 -5.493E-01 -5.511E-01 -5.518E-01 -5.499E-01 +5.524E-01 +5.614E-01 +5.522E-01 +5.487E-01 +5.482E-01 +5.446E-01 +5.437E-01 +5.429E-01 +5.407E-01 +5.380E-01 +5.377E-01 cmfd openmc source comparison -6.499546E-03 -3.419761E-03 -4.342514E-03 -7.229618E-03 -9.943057E-03 -1.050086E-02 -1.055060E-02 -6.562146E-03 -7.232860E-03 -4.424331E-03 -2.531323E-03 +1.586045E-02 +6.953134E-03 +6.860419E-03 +6.198467E-03 +5.142854E-03 +4.373354E-03 +5.564831E-03 +4.184765E-03 +1.867780E-03 +2.734784E-03 +2.523985E-03 cmfd source -4.224785E-02 -7.504165E-02 -1.009909E-01 -1.238160E-01 -1.301409E-01 -1.425954E-01 -1.353275E-01 -1.134617E-01 -8.830470E-02 -4.807346E-02 +4.241440E-02 +8.226026E-02 +1.180811E-01 +1.328433E-01 +1.412410E-01 +1.424902E-01 +1.269340E-01 +1.096490E-01 +6.953251E-02 +3.455422E-02 diff --git a/tests/regression_tests/cmfd_feed_ng/results_true.dat b/tests/regression_tests/cmfd_feed_ng/results_true.dat index 722cb16c8..153238bfe 100644 --- a/tests/regression_tests/cmfd_feed_ng/results_true.dat +++ b/tests/regression_tests/cmfd_feed_ng/results_true.dat @@ -1,208 +1,208 @@ k-combined: -1.027584E+00 1.502267E-02 +1.005987E+00 1.354263E-02 tally 1: -1.148263E+02 -1.318910E+03 -1.144863E+02 -1.311468E+03 -1.163124E+02 -1.353643E+03 -1.149445E+02 -1.321759E+03 +1.140273E+02 +1.301245E+03 +1.147962E+02 +1.319049E+03 +1.151426E+02 +1.326442E+03 +1.149265E+02 +1.321518E+03 tally 2: -3.397796E+01 -7.265736E+01 -5.019405E+01 -1.585764E+02 -1.053191E+01 -6.978659E+00 -8.739144E+00 -4.800811E+00 -1.368395E+02 -1.172003E+03 -7.370695E+01 -3.398875E+02 -3.374845E+01 -7.161454E+01 -5.011266E+01 -1.580982E+02 -1.014814E+01 -6.486800E+00 -8.590537E+00 -4.639730E+00 -1.379236E+02 -1.198395E+03 -7.277377E+01 -3.313373E+02 -3.554441E+01 -7.913690E+01 -5.224651E+01 -1.709692E+02 -1.050466E+01 -6.961148E+00 -8.866162E+00 -4.951519E+00 -1.388541E+02 -1.206000E+03 -7.399637E+01 -3.423642E+02 -3.479281E+01 -7.602778E+01 -5.139230E+01 -1.659298E+02 -1.026632E+01 -6.621042E+00 -8.649433E+00 -4.697954E+00 -1.402563E+02 -1.235504E+03 -7.374718E+01 -3.400080E+02 +3.462748E+01 +7.542476E+01 +5.129219E+01 +1.658142E+02 +1.034704E+01 +6.730603E+00 +8.672967E+00 +4.715295E+00 +1.344669E+02 +1.132019E+03 +7.262519E+01 +3.300787E+02 +3.447358E+01 +7.459545E+01 +5.075836E+01 +1.619570E+02 +1.080516E+01 +7.366369E+00 +8.908065E+00 +4.991975E+00 +1.354224E+02 +1.146824E+03 +7.300078E+01 +3.332531E+02 +3.432298E+01 +7.388666E+01 +5.096378E+01 +1.627979E+02 +1.053664E+01 +7.029789E+00 +8.826624E+00 +4.904429E+00 +1.388389E+02 +1.207280E+03 +7.376623E+01 +3.403211E+02 +4.383841E+01 +1.943331E+02 +5.165881E+01 +1.675923E+02 +1.059646E+01 +7.048052E+00 +8.763673E+00 +4.823505E+00 +1.378179E+02 +1.188104E+03 +7.431708E+01 +3.453746E+02 tally 3: -4.748159E+01 -1.419494E+02 +4.858880E+01 +1.488705E+02 0.000000E+00 0.000000E+00 -8.132630E-03 -1.326503E-05 +8.148667E-03 +1.337050E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.299481E+00 -6.900644E-01 -2.429296E+00 -3.713869E-01 +3.347376E+00 +7.045574E-01 +2.433484E+00 +3.727266E-01 0.000000E+00 0.000000E+00 -6.175576E+00 -2.403118E+00 +6.095478E+00 +2.332622E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -7.020357E-02 -6.481773E-04 -3.097931E-01 -6.853044E-03 +1.235421E-01 +1.205155E-03 +3.647699E-01 +8.953589E-03 0.000000E+00 0.000000E+00 -2.592969E+00 -4.215508E-01 +2.673965E+00 +4.517972E-01 0.000000E+00 0.000000E+00 -6.972257E+01 -3.041404E+02 -5.792796E-01 -2.191871E-02 -4.745221E+01 -1.418371E+02 +6.841105E+01 +2.929195E+02 +5.902473E-01 +2.307683E-02 +4.792291E+01 +1.444397E+02 0.000000E+00 0.000000E+00 -1.507569E-02 -3.140047E-05 +2.183275E-02 +8.061011E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.307769E+00 -6.924370E-01 -2.473164E+00 -3.840166E-01 +3.435826E+00 +7.480244E-01 +2.450829E+00 +3.800327E-01 0.000000E+00 0.000000E+00 -5.967063E+00 -2.251947E+00 +6.331358E+00 +2.530492E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.143833E-02 -8.020544E-04 +1.012941E-01 +8.217580E-04 +2.981274E-01 +5.863186E-03 +0.000000E+00 +0.000000E+00 +2.535628E+00 +4.048310E-01 +0.000000E+00 +0.000000E+00 +6.912003E+01 +2.987684E+02 +5.984862E-01 +2.386115E-02 +4.822881E+01 +1.458309E+02 +0.000000E+00 +0.000000E+00 +1.525590E-02 +3.794082E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.314494E+00 +6.944527E-01 +2.424209E+00 +3.691360E-01 +0.000000E+00 +0.000000E+00 +6.254897E+00 +2.474317E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.112542E-01 +1.051688E-03 3.234880E-01 -7.219562E-03 +7.156753E-03 0.000000E+00 0.000000E+00 -2.477436E+00 -3.882619E-01 +2.474142E+00 +3.837496E-01 0.000000E+00 0.000000E+00 -6.888326E+01 -2.968630E+02 -5.925099E-01 -2.344632E-02 -4.946736E+01 -1.533087E+02 +6.987095E+01 +3.053358E+02 +5.928782E-01 +2.368116E-02 +4.885415E+01 +1.499856E+02 0.000000E+00 0.000000E+00 -1.369119E-02 -3.099298E-05 +1.262416E-02 +2.486286E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.513467E+00 -7.852189E-01 -2.483110E+00 -3.901527E-01 +3.426826E+00 +7.480396E-01 +2.487209E+00 +3.903882E-01 0.000000E+00 0.000000E+00 -6.238898E+00 -2.455700E+00 +6.127303E+00 +2.364605E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.032973E-02 -6.677512E-04 -2.816159E-01 -5.349737E-03 +9.439007E-02 +1.082564E-03 +2.963491E-01 +5.652952E-03 0.000000E+00 0.000000E+00 -2.620828E+00 -4.350795E-01 +2.620696E+00 +4.311792E-01 0.000000E+00 0.000000E+00 -6.992910E+01 -3.057653E+02 -5.890670E-01 -2.307978E-02 -4.853121E+01 -1.480132E+02 -0.000000E+00 -0.000000E+00 -1.719291E-02 -4.141727E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.490129E+00 -7.743548E-01 -2.381968E+00 -3.564896E-01 -0.000000E+00 -0.000000E+00 -6.151693E+00 -2.382656E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.653178E-02 -5.524601E-04 -3.307211E-01 -7.362512E-03 -0.000000E+00 -0.000000E+00 -2.566722E+00 -4.136929E-01 -0.000000E+00 -0.000000E+00 -6.968935E+01 -3.036323E+02 -6.295592E-01 -2.609911E-02 +7.030725E+01 +3.091241E+02 +5.986966E-01 +2.352487E-02 tally 4: 0.000000E+00 0.000000E+00 @@ -216,18 +216,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -6.910417E+00 -3.013908E+00 -2.099086E+00 -2.794191E-01 -2.725309E+01 -4.645663E+01 -7.076086E+00 -3.154776E+00 -2.051075E+00 -2.671542E-01 -2.737348E+01 -4.686718E+01 +7.028624E+00 +3.105990E+00 +2.154648E+00 +2.948865E-01 +2.714077E+01 +4.607926E+01 +7.035506E+00 +3.118549E+00 +2.085916E+00 +2.730884E-01 +2.750091E+01 +4.731304E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -240,18 +240,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.215131E+00 -3.265328E+00 -2.066108E+00 -2.704238E-01 -2.755564E+01 -4.753705E+01 -7.022836E+00 -3.102535E+00 -2.076586E+00 -2.741254E-01 -2.756981E+01 -4.756632E+01 +7.170567E+00 +3.240715E+00 +2.131758E+00 +2.862355E-01 +2.747702E+01 +4.722977E+01 +7.068817E+00 +3.139275E+00 +2.095865E+00 +2.762179E-01 +2.737835E+01 +4.688689E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -276,18 +276,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.076086E+00 -3.154776E+00 -2.051075E+00 -2.671542E-01 -2.737348E+01 -4.686718E+01 -6.910417E+00 -3.013908E+00 -2.099086E+00 -2.794191E-01 -2.725309E+01 -4.645663E+01 +7.035506E+00 +3.118549E+00 +2.085916E+00 +2.730884E-01 +2.750091E+01 +4.731304E+01 +7.028624E+00 +3.105990E+00 +2.154648E+00 +2.948865E-01 +2.714077E+01 +4.607926E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -312,18 +312,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.008937E+00 -3.087084E+00 -2.040640E+00 -2.622272E-01 -2.705295E+01 -4.578207E+01 -7.038404E+00 -3.111878E+00 -2.123591E+00 -2.840551E-01 -2.708214E+01 -4.588834E+01 +7.103896E+00 +3.171147E+00 +2.095666E+00 +2.756673E-01 +2.711842E+01 +4.600196E+01 +7.197270E+00 +3.255501E+00 +2.046179E+00 +2.630301E-01 +2.729901E+01 +4.662030E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -360,30 +360,30 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.286308E+00 -3.346248E+00 -2.108252E+00 -2.794781E-01 -2.738387E+01 -4.689407E+01 -7.108444E+00 -3.172810E+00 -2.111474E+00 -2.804633E-01 -2.737249E+01 -4.687424E+01 -7.022836E+00 -3.102535E+00 -2.076586E+00 -2.741254E-01 -2.756981E+01 -4.756632E+01 -7.215131E+00 -3.265328E+00 -2.066108E+00 -2.704238E-01 -2.755564E+01 -4.753705E+01 +7.240906E+00 +3.296285E+00 +2.130816E+00 +2.850713E-01 +2.761433E+01 +4.771548E+01 +7.126427E+00 +3.199209E+00 +2.177254E+00 +2.998765E-01 +2.754936E+01 +4.748447E+01 +7.068817E+00 +3.139275E+00 +2.095865E+00 +2.762179E-01 +2.737835E+01 +4.688689E+01 +7.170567E+00 +3.240715E+00 +2.131758E+00 +2.862355E-01 +2.747702E+01 +4.722977E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -420,18 +420,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.108444E+00 -3.172810E+00 -2.111474E+00 -2.804633E-01 -2.737249E+01 -4.687424E+01 -7.286308E+00 -3.346248E+00 -2.108252E+00 -2.794781E-01 -2.738387E+01 -4.689407E+01 +7.126427E+00 +3.199209E+00 +2.177254E+00 +2.998765E-01 +2.754936E+01 +4.748447E+01 +7.240906E+00 +3.296285E+00 +2.130816E+00 +2.850713E-01 +2.761433E+01 +4.771548E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -444,18 +444,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.038404E+00 -3.111878E+00 -2.123591E+00 -2.840551E-01 -2.708214E+01 -4.588834E+01 -7.008937E+00 -3.087084E+00 -2.040640E+00 -2.622272E-01 -2.705295E+01 -4.578207E+01 +7.197270E+00 +3.255501E+00 +2.046179E+00 +2.630301E-01 +2.729901E+01 +4.662030E+01 +7.103896E+00 +3.171147E+00 +2.095666E+00 +2.756673E-01 +2.711842E+01 +4.600196E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -493,124 +493,124 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -4.748972E+01 -1.419968E+02 -8.604872E+00 -4.655596E+00 -7.261430E+01 -3.298767E+02 -1.092092E+01 -7.540081E+00 -3.984923E+00 -1.000404E+00 -3.294804E+01 -6.794642E+01 -4.746728E+01 -1.419250E+02 -8.440227E+00 -4.478243E+00 -7.167598E+01 -3.214310E+02 -1.073385E+01 -7.257545E+00 -3.904158E+00 -9.587510E-01 -3.253492E+01 -6.626202E+01 -4.948105E+01 -1.533940E+02 -8.722008E+00 -4.791509E+00 -7.283154E+01 -3.316829E+02 -1.138387E+01 -8.162117E+00 -4.131397E+00 -1.078045E+00 -3.254336E+01 -6.624925E+01 -4.854840E+01 -1.481182E+02 -8.533661E+00 -4.573316E+00 -7.258180E+01 -3.293419E+02 -1.053673E+01 -7.002045E+00 -3.988151E+00 -1.001884E+00 -3.284213E+01 -6.749116E+01 +4.859695E+01 +1.489217E+02 +8.528963E+00 +4.561881E+00 +7.144500E+01 +3.194467E+02 +1.120265E+01 +7.944038E+00 +4.009821E+00 +1.012575E+00 +3.235456E+01 +6.558658E+01 +4.794474E+01 +1.445671E+02 +8.782187E+00 +4.852477E+00 +7.195036E+01 +3.237389E+02 +1.075572E+01 +7.333822E+00 +4.084680E+00 +1.054714E+00 +3.267154E+01 +6.675266E+01 +4.824407E+01 +1.459220E+02 +8.679106E+00 +4.742342E+00 +7.266858E+01 +3.302641E+02 +1.094872E+01 +7.536318E+00 +3.935828E+00 +9.749543E-01 +3.319517E+01 +6.894791E+01 +4.886677E+01 +1.500624E+02 +8.614512E+00 +4.662618E+00 +7.321408E+01 +3.352172E+02 +1.095123E+01 +7.574359E+00 +3.885927E+00 +9.539315E-01 +3.334065E+01 +6.953215E+01 cmfd indices 2.000000E+00 2.000000E+00 1.000000E+00 3.000000E+00 k cmfd -1.026167E+00 -1.026753E+00 -1.034560E+00 -1.028298E+00 -1.029032E+00 -1.033531E+00 -1.034902E+00 -1.029837E+00 -1.025313E+00 -1.019855E+00 -1.021235E+00 +1.026473E+00 +1.024183E+00 +1.023151E+00 +1.025047E+00 +1.019801E+00 +1.020492E+00 +1.015249E+00 +1.016714E+00 +1.016047E+00 +1.019687E+00 +1.020955E+00 cmfd entropy -1.998818E+00 -1.998853E+00 -1.999048E+00 -1.998864E+00 -1.998999E+00 -1.998789E+00 -1.998670E+00 -1.998822E+00 -1.998782E+00 -1.999027E+00 -1.999420E+00 +1.999640E+00 +1.999556E+00 +1.999484E+00 +1.999718E+00 +1.999697E+00 +1.999657E+00 +1.999883E+00 +1.999902E+00 +1.999977E+00 +1.999977E+00 +1.999906E+00 cmfd balance -1.00064E-03 -6.95941E-04 -5.74967E-04 -4.34776E-04 -4.03288E-04 -4.32457E-04 -4.49075E-04 -3.57342E-04 -3.62891E-04 -2.86133E-04 -2.08678E-04 +8.10090E-04 +1.28103E-03 +7.97200E-04 +5.82188E-04 +7.20670E-04 +7.31475E-04 +5.71904E-04 +6.14057E-04 +6.00142E-04 +5.47870E-04 +3.53604E-04 cmfd dominance ratio -3.759E-03 -3.706E-03 -3.719E-03 -3.796E-03 -3.724E-03 -3.809E-03 -3.792E-03 -3.782E-03 -3.841E-03 +3.977E-03 +4.018E-03 +3.950E-03 3.866E-03 -3.868E-03 +3.840E-03 +3.888E-03 +3.867E-03 +3.896E-03 +3.924E-03 +3.885E-03 +3.913E-03 cmfd openmc source comparison -8.283222E-05 -6.636005E-05 -5.320110E-05 -4.474530E-05 -4.409263E-05 -4.914331E-05 -4.834447E-05 -4.040592E-05 -4.173469E-05 -3.118350E-05 -1.667967E-05 +4.787501E-05 +4.450525E-05 +2.532345E-05 +3.844307E-05 +4.821504E-05 +4.840760E-05 +3.739246E-05 +3.957960E-05 +4.521480E-05 +4.072007E-05 +2.532636E-05 cmfd source -2.416781E-01 -2.442811E-01 -2.566121E-01 -2.574288E-01 +2.486236E-01 +2.531628E-01 +2.460219E-01 +2.521918E-01 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/regression_tests/cmfd_feed_rectlin/results_true.dat b/tests/regression_tests/cmfd_feed_rectlin/results_true.dat index 1a9c3f4e4..600b5d152 100644 --- a/tests/regression_tests/cmfd_feed_rectlin/results_true.dat +++ b/tests/regression_tests/cmfd_feed_rectlin/results_true.dat @@ -1,149 +1,149 @@ k-combined: -1.167761E+00 4.293426E-03 +1.160561E+00 1.029736E-02 tally 1: -1.202277E+01 -1.452746E+01 -2.195725E+01 -4.835710E+01 -2.862021E+01 -8.215585E+01 -3.453333E+01 -1.196497E+02 -3.756803E+01 -1.414919E+02 -3.739045E+01 -1.403446E+02 -3.361501E+01 -1.134271E+02 -2.819861E+01 -7.968185E+01 -2.111919E+01 -4.472336E+01 -1.129975E+01 -1.280982E+01 +1.089904E+01 +1.193573E+01 +2.026534E+01 +4.113383E+01 +2.723584E+01 +7.440537E+01 +3.309956E+01 +1.101184E+02 +3.659327E+01 +1.341221E+02 +3.780158E+01 +1.430045E+02 +3.520883E+01 +1.241772E+02 +2.961801E+01 +8.784675E+01 +2.182029E+01 +4.781083E+01 +1.180347E+01 +1.399970E+01 tally 2: -8.743037E+00 -3.861220E+00 -6.027264E+00 -1.836570E+00 -3.366159E+01 -5.708871E+01 -2.367086E+01 -2.824484E+01 -2.348709E+01 -2.777633E+01 -1.668756E+01 -1.403629E+01 -5.609969E+01 -1.580739E+02 -3.985682E+01 -7.985715E+01 -3.319543E+01 -5.528370E+01 -2.358360E+01 -2.791829E+01 -7.132407E+01 -2.550603E+02 -5.083603E+01 -1.296049E+02 -3.801086E+01 -7.257141E+01 -2.709688E+01 -3.686995E+01 -3.751307E+01 -7.073318E+01 -2.660859E+01 -3.559134E+01 -7.258292E+01 -2.644619E+02 -5.168044E+01 -1.340982E+02 -3.304423E+01 -5.486256E+01 -2.335526E+01 -2.742989E+01 -5.655005E+01 -1.603926E+02 -4.014572E+01 -8.087797E+01 -2.351019E+01 -2.776367E+01 -1.670083E+01 -1.401374E+01 -3.451886E+01 -5.983149E+01 -2.443300E+01 -2.997375E+01 -8.551177E+00 -3.691263E+00 -5.916124E+00 -1.768556E+00 +8.794706E+00 +3.939413E+00 +6.131113E+00 +1.913116E+00 +3.265522E+01 +5.364042E+01 +2.304238E+01 +2.672742E+01 +2.250225E+01 +2.541491E+01 +1.601668E+01 +1.288405E+01 +5.525355E+01 +1.531915E+02 +3.929637E+01 +7.748545E+01 +3.222711E+01 +5.216630E+01 +2.285375E+01 +2.623641E+01 +7.051908E+01 +2.495413E+02 +5.010064E+01 +1.259701E+02 +3.728726E+01 +6.974440E+01 +2.652872E+01 +3.530919E+01 +3.747306E+01 +7.058235E+01 +2.681415E+01 +3.613314E+01 +7.296802E+01 +2.669214E+02 +5.202502E+01 +1.356733E+02 +3.333947E+01 +5.579355E+01 +2.361733E+01 +2.800800E+01 +5.785916E+01 +1.680561E+02 +4.093282E+01 +8.410711E+01 +2.377151E+01 +2.842464E+01 +1.681789E+01 +1.423646E+01 +3.422028E+01 +5.880493E+01 +2.415199E+01 +2.930240E+01 +8.890608E+00 +3.986356E+00 +6.140159E+00 +1.897764E+00 tally 3: -5.799161E+00 -1.702117E+00 -3.588837E-01 -7.127789E-03 -2.273477E+01 -2.606361E+01 -1.586822E+00 -1.296956E-01 -1.606466E+01 -1.300770E+01 -1.018209E+00 -5.281297E-02 -3.840128E+01 -7.415483E+01 -2.383738E+00 -2.877855E-01 -2.268388E+01 -2.583457E+01 -1.485208E+00 -1.122747E-01 -4.899435E+01 -1.204028E+02 -3.203505E+00 -5.163235E-01 -2.610714E+01 -3.423244E+01 -1.707156E+00 -1.476400E-01 -2.559242E+01 -3.293100E+01 -1.761813E+00 -1.597786E-01 -4.985698E+01 -1.248029E+02 -3.081386E+00 -4.824389E-01 -2.245777E+01 -2.536963E+01 -1.447127E+00 -1.065745E-01 -3.869628E+01 -7.516217E+01 -2.545419E+00 -3.270790E-01 -1.610401E+01 -1.303231E+01 -1.011897E+00 -5.274155E-02 -2.353410E+01 -2.781055E+01 -1.517873E+00 -1.184503E-01 -5.687356E+00 -1.636570E+00 -3.728435E-01 -7.203797E-03 +5.925339E+00 +1.788596E+00 +3.912632E-01 +8.061838E-03 +2.215544E+01 +2.471404E+01 +1.465191E+00 +1.092622E-01 +1.542988E+01 +1.195626E+01 +1.022876E+00 +5.356825E-02 +3.792029E+01 +7.218149E+01 +2.370476E+00 +2.839465E-01 +2.200154E+01 +2.432126E+01 +1.360836E+00 +9.402424E-02 +4.824980E+01 +1.168447E+02 +3.124366E+00 +4.907460E-01 +2.557420E+01 +3.282066E+01 +1.725855E+00 +1.519830E-01 +2.577963E+01 +3.341077E+01 +1.654042E+00 +1.386845E-01 +5.008220E+01 +1.257610E+02 +3.223857E+00 +5.237360E-01 +2.273380E+01 +2.595325E+01 +1.438369E+00 +1.050840E-01 +3.938822E+01 +7.789691E+01 +2.648324E+00 +3.559703E-01 +1.623604E+01 +1.327214E+01 +1.058882E+00 +5.680630E-02 +2.325730E+01 +2.717892E+01 +1.584276E+00 +1.275868E-01 +5.937929E+00 +1.774847E+00 +3.866918E-01 +7.994353E-03 tally 4: -3.060660E+00 -4.703581E-01 +3.063235E+00 +4.714106E-01 0.000000E+00 0.000000E+00 -1.451637E+00 -1.081522E-01 -4.402560E+00 -9.746218E-01 +1.425705E+00 +1.043616E-01 +4.355515E+00 +9.538346E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -160,14 +160,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.402560E+00 -9.746218E-01 -1.451637E+00 -1.081522E-01 -3.903491E+00 -7.713768E-01 -6.448935E+00 -2.089570E+00 +4.355515E+00 +9.538346E-01 +1.425705E+00 +1.043616E-01 +3.859174E+00 +7.519499E-01 +6.350310E+00 +2.024214E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -184,14 +184,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -6.448935E+00 -2.089570E+00 -3.903491E+00 -7.713768E-01 -5.075609E+00 -1.297182E+00 -7.371853E+00 -2.729133E+00 +6.350310E+00 +2.024214E+00 +3.859174E+00 +7.519499E-01 +4.993073E+00 +1.258264E+00 +7.194275E+00 +2.596886E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -208,14 +208,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.371853E+00 -2.729133E+00 -5.075609E+00 -1.297182E+00 -7.015514E+00 -2.477295E+00 -8.723726E+00 -3.828466E+00 +7.194275E+00 +2.596886E+00 +4.993073E+00 +1.258264E+00 +6.786617E+00 +2.312259E+00 +8.306978E+00 +3.459668E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -232,14 +232,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.723726E+00 -3.828466E+00 -7.015514E+00 -2.477295E+00 -7.735344E+00 -3.007547E+00 -9.106625E+00 -4.165807E+00 +8.306978E+00 +3.459668E+00 +6.786617E+00 +2.312259E+00 +7.603410E+00 +2.905228E+00 +8.791222E+00 +3.882935E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -256,14 +256,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.106625E+00 -4.165807E+00 -7.735344E+00 -3.007547E+00 -9.026526E+00 -4.098261E+00 -9.551542E+00 -4.586695E+00 +8.791222E+00 +3.882935E+00 +7.603410E+00 +2.905228E+00 +8.867113E+00 +3.938503E+00 +9.302808E+00 +4.340042E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -280,14 +280,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.551542E+00 -4.586695E+00 -9.026526E+00 -4.098261E+00 -9.344096E+00 -4.384840E+00 -9.405215E+00 -4.441966E+00 +9.302808E+00 +4.340042E+00 +8.867113E+00 +3.938503E+00 +9.270113E+00 +4.306513E+00 +9.263471E+00 +4.302184E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -304,14 +304,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.405215E+00 -4.441966E+00 -9.344096E+00 -4.384840E+00 -9.390313E+00 -4.435716E+00 -9.011690E+00 -4.080913E+00 +9.263471E+00 +4.302184E+00 +9.270113E+00 +4.306513E+00 +9.348712E+00 +4.388570E+00 +8.977713E+00 +4.047349E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -328,14 +328,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.011690E+00 -4.080913E+00 -9.390313E+00 -4.435716E+00 -9.140785E+00 -4.195868E+00 -8.003067E+00 -3.218771E+00 +8.977713E+00 +4.047349E+00 +9.348712E+00 +4.388570E+00 +9.234380E+00 +4.280666E+00 +8.036978E+00 +3.239853E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -352,14 +352,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.003067E+00 -3.218771E+00 -9.140785E+00 -4.195868E+00 -8.629258E+00 -3.736554E+00 -7.133986E+00 -2.557637E+00 +8.036978E+00 +3.239853E+00 +9.234380E+00 +4.280666E+00 +8.713633E+00 +3.808850E+00 +7.160878E+00 +2.572915E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -376,14 +376,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.133986E+00 -2.557637E+00 -8.629258E+00 -3.736554E+00 -7.284136E+00 -2.659936E+00 -5.069993E+00 -1.289638E+00 +7.160878E+00 +2.572915E+00 +8.713633E+00 +3.808850E+00 +7.378538E+00 +2.732122E+00 +5.145728E+00 +1.329190E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -400,14 +400,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.069993E+00 -1.289638E+00 -7.284136E+00 -2.659936E+00 -6.585377E+00 -2.178573E+00 -4.109746E+00 -8.535283E-01 +5.145728E+00 +1.329190E+00 +7.378538E+00 +2.732122E+00 +6.660125E+00 +2.228506E+00 +4.087925E+00 +8.435381E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -424,14 +424,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.109746E+00 -8.535283E-01 -6.585377E+00 -2.178573E+00 -4.394913E+00 -9.694834E-01 -1.455260E+00 -1.073327E-01 +4.087925E+00 +8.435381E-01 +6.660125E+00 +2.228506E+00 +4.466295E+00 +1.002320E+00 +1.468481E+00 +1.099604E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -448,12 +448,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.455260E+00 -1.073327E-01 -4.394913E+00 -9.694834E-01 -3.054512E+00 -4.687172E-01 +1.468481E+00 +1.099604E-01 +4.466295E+00 +1.002320E+00 +3.139355E+00 +4.955456E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -473,164 +473,164 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -5.798163E+00 -1.701480E+00 -7.719076E-01 -3.205800E-02 -2.272861E+01 -2.604939E+01 -3.183925E+00 -5.123120E-01 -1.606367E+01 -1.300597E+01 -2.209506E+00 -2.514085E-01 -3.839444E+01 -7.412912E+01 -5.235063E+00 -1.389014E+00 -2.268086E+01 -2.582733E+01 -3.074902E+00 -4.810618E-01 -4.898566E+01 -1.203589E+02 -6.606838E+00 -2.201101E+00 -2.609836E+01 -3.420917E+01 -3.518842E+00 -6.264238E-01 -2.558605E+01 -3.291399E+01 -3.686659E+00 -6.942431E-01 -4.984902E+01 -1.247644E+02 -6.876822E+00 -2.400434E+00 -2.245394E+01 -2.536044E+01 -3.098158E+00 -4.940204E-01 -3.868744E+01 -7.512715E+01 -5.302748E+00 -1.428609E+00 -1.610093E+01 -1.302770E+01 -2.252209E+00 -2.578778E-01 -2.352951E+01 -2.779963E+01 -3.249775E+00 -5.380883E-01 -5.685356E+00 -1.635162E+00 -7.886630E-01 -3.440650E-02 +5.925339E+00 +1.788596E+00 +8.954773E-01 +4.217679E-02 +2.215054E+01 +2.470273E+01 +2.944747E+00 +4.443186E-01 +1.542658E+01 +1.195085E+01 +1.950262E+00 +1.946340E-01 +3.791137E+01 +7.214779E+01 +4.955741E+00 +1.254830E+00 +2.200054E+01 +2.431894E+01 +3.031040E+00 +4.685971E-01 +4.823946E+01 +1.167941E+02 +6.226321E+00 +1.956308E+00 +2.556930E+01 +3.280828E+01 +3.582546E+00 +6.505962E-01 +2.577249E+01 +3.339204E+01 +3.316825E+00 +5.676842E-01 +5.007249E+01 +1.257124E+02 +6.462364E+00 +2.120157E+00 +2.273285E+01 +2.595106E+01 +2.960964E+00 +4.496277E-01 +3.937362E+01 +7.783849E+01 +5.339336E+00 +1.449257E+00 +1.623315E+01 +1.326746E+01 +2.289661E+00 +2.698618E-01 +2.325250E+01 +2.716827E+01 +3.253010E+00 +5.413837E-01 +5.937929E+00 +1.774847E+00 +9.208589E-01 +4.421403E-02 cmfd indices 1.400000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.154550E+00 -1.172635E+00 -1.171962E+00 -1.174888E+00 -1.182656E+00 -1.190779E+00 -1.200964E+00 -1.196775E+00 -1.190049E+00 -1.181514E+00 -1.180749E+00 -1.179370E+00 -1.177279E+00 -1.178924E+00 -1.177106E+00 -1.179987E+00 +1.125528E+00 +1.145509E+00 +1.158948E+00 +1.171983E+00 +1.180649E+00 +1.184072E+00 +1.188112E+00 +1.183095E+00 +1.182269E+00 +1.175467E+00 +1.175184E+00 +1.172637E+00 +1.171593E+00 +1.175439E+00 +1.174650E+00 +1.176474E+00 cmfd entropy -3.598911E+00 -3.600560E+00 -3.599978E+00 -3.601027E+00 -3.599502E+00 -3.598849E+00 -3.601916E+00 -3.605728E+00 -3.607212E+00 -3.612277E+00 -3.615627E+00 -3.618446E+00 -3.615292E+00 -3.612951E+00 -3.610620E+00 -3.607388E+00 +3.607059E+00 +3.604890E+00 +3.601329E+00 +3.597776E+00 +3.597360E+00 +3.597387E+00 +3.595379E+00 +3.596995E+00 +3.600901E+00 +3.601832E+00 +3.601426E+00 +3.604521E+00 +3.602848E+00 +3.603875E+00 +3.605213E+00 +3.606699E+00 cmfd balance -6.80696E-03 -7.03786E-03 -5.33837E-03 -5.39054E-03 -4.82209E-03 -4.46014E-03 -4.48076E-03 -3.31344E-03 -2.71476E-03 -2.03403E-03 -1.68070E-03 -1.38975E-03 -1.30457E-03 -1.29678E-03 -1.34009E-03 -1.43023E-03 +4.46212E-03 +4.66648E-03 +5.04274E-03 +5.21553E-03 +3.92498E-03 +2.97185E-03 +2.79785E-03 +2.66951E-03 +2.17472E-03 +1.98009E-03 +1.77035E-03 +1.51281E-03 +1.52807E-03 +1.33341E-03 +1.18155E-03 +1.07752E-03 cmfd dominance ratio -5.913E-01 -5.946E-01 -5.961E-01 -5.995E-01 -6.024E-01 -6.050E-01 -6.056E-01 -6.062E-01 -6.064E-01 -6.087E-01 -6.117E-01 -6.120E-01 +6.136E-01 +6.127E-01 +6.137E-01 +6.102E-01 +6.067E-01 +6.061E-01 +6.031E-01 +6.046E-01 +6.071E-01 6.089E-01 -6.074E-01 -6.052E-01 -6.030E-01 +6.073E-01 +6.080E-01 +6.080E-01 +6.090E-01 +6.092E-01 +6.094E-01 cmfd openmc source comparison -1.274461E-02 -9.191627E-03 -7.371466E-03 -4.977614E-03 -4.481864E-03 -3.396798E-03 -2.167863E-03 -4.137274E-03 -4.692749E-03 -2.955754E-03 -2.656269E-03 -2.241441E-03 -4.127496E-03 -3.040657E-03 -3.925292E-03 -3.183157E-03 +1.043027E-02 +1.278226E-02 +1.184867E-02 +1.017186E-02 +1.099696E-02 +7.955341E-03 +8.360344E-03 +6.875508E-03 +4.824018E-03 +4.915363E-03 +5.371647E-03 +4.593100E-03 +4.894955E-03 +4.928253E-03 +4.292171E-03 +4.018545E-03 cmfd source -1.525739E-02 -6.776716E-02 -4.352345E-02 -1.020209E-01 -6.379967E-02 -1.378464E-01 -7.334653E-02 -7.562170E-02 -1.318340E-01 -6.145426E-02 -1.073314E-01 -4.229800E-02 -6.258388E-02 -1.531527E-02 +1.600876E-02 +6.000305E-02 +4.248071E-02 +9.935789E-02 +5.768092E-02 +1.338593E-01 +7.417398E-02 +7.102984E-02 +1.382563E-01 +6.181889E-02 +1.142473E-01 +4.571447E-02 +6.864655E-02 +1.672206E-02 diff --git a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat b/tests/regression_tests/cmfd_feed_ref_d/results_true.dat index cf1e165b2..9cc26b8cf 100644 --- a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat +++ b/tests/regression_tests/cmfd_feed_ref_d/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.184724E+00 9.807415E-03 +1.167869E+00 7.492916E-03 tally 1: -1.121178E+01 -1.261180E+01 -2.101384E+01 -4.433764E+01 -2.783041E+01 -7.777181E+01 -3.351124E+01 -1.125137E+02 -3.625716E+01 -1.319682E+02 -3.741849E+01 -1.403752E+02 -3.537964E+01 -1.255737E+02 -3.030185E+01 -9.227364E+01 -2.188275E+01 -4.810760E+01 -1.172353E+01 -1.379028E+01 +1.146821E+01 +1.318787E+01 +2.161476E+01 +4.685066E+01 +2.951084E+01 +8.733116E+01 +3.521523E+01 +1.242762E+02 +3.774181E+01 +1.426460E+02 +3.727924E+01 +1.391162E+02 +3.377236E+01 +1.143877E+02 +2.904590E+01 +8.453427E+01 +2.090941E+01 +4.384824E+01 +1.078680E+01 +1.168172E+01 tally 2: -1.146903E+00 -1.315387E+00 -8.067939E-01 -6.509164E-01 -2.070041E+00 -4.285068E+00 -1.468994E+00 -2.157944E+00 -2.703198E+00 -7.307278E+00 -1.895572E+00 -3.593192E+00 -3.567627E+00 -1.272796E+01 -2.541486E+00 -6.459152E+00 -3.937479E+00 -1.550374E+01 -2.770473E+00 -7.675520E+00 -3.960493E+00 -1.568551E+01 -2.792683E+00 -7.799079E+00 -3.243496E+00 -1.052027E+01 -2.296698E+00 -5.274821E+00 -2.794771E+00 -7.810744E+00 -1.953175E+00 -3.814893E+00 -2.187333E+00 -4.784426E+00 -1.544523E+00 -2.385551E+00 -1.199628E+00 -1.439107E+00 -8.356207E-01 -6.982620E-01 +1.136805E+00 +1.292326E+00 +7.987282E-01 +6.379667E-01 +2.266961E+00 +5.139112E+00 +1.613498E+00 +2.603376E+00 +3.046379E+00 +9.280427E+00 +2.182480E+00 +4.763219E+00 +3.568101E+00 +1.273134E+01 +2.532478E+00 +6.413444E+00 +3.989532E+00 +1.591637E+01 +2.848319E+00 +8.112921E+00 +3.853139E+00 +1.484668E+01 +2.718497E+00 +7.390223E+00 +3.478134E+00 +1.209742E+01 +2.467279E+00 +6.087465E+00 +2.952214E+00 +8.715569E+00 +2.103257E+00 +4.423688E+00 +1.917446E+00 +3.676599E+00 +1.378361E+00 +1.899878E+00 +1.048230E+00 +1.098785E+00 +7.511876E-01 +5.642828E-01 tally 3: -7.817283E-01 -6.110991E-01 -5.930048E-02 -3.516547E-03 -1.426340E+00 -2.034446E+00 -8.539269E-02 -7.291911E-03 -1.815669E+00 -3.296655E+00 -1.221590E-01 -1.492282E-02 -2.447185E+00 -5.988716E+00 -1.624833E-01 -2.640082E-02 -2.670094E+00 -7.129404E+00 -1.838315E-01 -3.379401E-02 -2.683021E+00 -7.198600E+00 -1.719714E-01 -2.957416E-02 -2.215470E+00 -4.908307E+00 -1.707854E-01 -2.916764E-02 -1.872360E+00 -3.505733E+00 -1.209730E-01 -1.463446E-02 -1.484189E+00 -2.202817E+00 -1.114849E-01 -1.242888E-02 -8.018794E-01 -6.430105E-01 -5.692846E-02 -3.240849E-03 +7.701212E-01 +5.930866E-01 +4.481580E-02 +2.008456E-03 +1.547321E+00 +2.394203E+00 +1.226538E-01 +1.504395E-02 +2.106393E+00 +4.436893E+00 +1.450617E-01 +2.104289E-02 +2.437675E+00 +5.942260E+00 +1.521379E-01 +2.314593E-02 +2.754657E+00 +7.588135E+00 +1.745458E-01 +3.046622E-02 +2.623856E+00 +6.884619E+00 +1.851600E-01 +3.428423E-02 +2.376884E+00 +5.649579E+00 +1.615728E-01 +2.610576E-02 +2.021851E+00 +4.087882E+00 +1.533172E-01 +2.350617E-02 +1.333182E+00 +1.777374E+00 +7.076179E-02 +5.007231E-03 +7.258458E-01 +5.268521E-01 +3.656026E-02 +1.336653E-03 tally 4: -1.404164E-01 -1.971677E-02 +1.667426E-01 +2.780308E-02 0.000000E+00 0.000000E+00 -1.383903E-01 -1.915186E-02 -2.626104E-01 -6.896424E-02 +1.292556E-01 +1.670700E-02 +2.813401E-01 +7.915227E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.626104E-01 -6.896424E-02 -1.383903E-01 -1.915186E-02 -2.300555E-01 -5.292554E-02 -3.213857E-01 -1.032888E-01 +2.813401E-01 +7.915227E-02 +1.292556E-01 +1.670700E-02 +2.670582E-01 +7.132006E-02 +4.055365E-01 +1.644599E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.213857E-01 -1.032888E-01 -2.300555E-01 -5.292554E-02 -3.621759E-01 -1.311714E-01 -4.326073E-01 -1.871490E-01 +4.055365E-01 +1.644599E-01 +2.670582E-01 +7.132006E-02 +3.848164E-01 +1.480837E-01 +4.809472E-01 +2.313102E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.326073E-01 -1.871490E-01 -3.621759E-01 -1.311714E-01 -4.274871E-01 -1.827452E-01 -4.701411E-01 -2.210326E-01 +4.809472E-01 +2.313102E-01 +3.848164E-01 +1.480837E-01 +4.543959E-01 +2.064756E-01 +5.106174E-01 +2.607301E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.701411E-01 -2.210326E-01 -4.274871E-01 -1.827452E-01 -4.867793E-01 -2.369540E-01 -5.027352E-01 -2.527427E-01 +5.106174E-01 +2.607301E-01 +4.543959E-01 +2.064756E-01 +4.543155E-01 +2.064026E-01 +4.626331E-01 +2.140294E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.027352E-01 -2.527427E-01 -4.867793E-01 -2.369540E-01 -4.679247E-01 -2.189535E-01 -4.504680E-01 -2.029214E-01 +4.626331E-01 +2.140294E-01 +4.543155E-01 +2.064026E-01 +4.827763E-01 +2.330729E-01 +4.442611E-01 +1.973679E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.504680E-01 -2.029214E-01 -4.679247E-01 -2.189535E-01 -4.341058E-01 -1.884478E-01 -3.622812E-01 -1.312477E-01 +4.442611E-01 +1.973679E-01 +4.827763E-01 +2.330729E-01 +4.630415E-01 +2.144074E-01 +3.886521E-01 +1.510505E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.622812E-01 -1.312477E-01 -4.341058E-01 -1.884478E-01 -3.743485E-01 -1.401368E-01 -2.666983E-01 -7.112801E-02 +3.886521E-01 +1.510505E-01 +4.630415E-01 +2.144074E-01 +3.535862E-01 +1.250232E-01 +2.530293E-01 +6.402384E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.666983E-01 -7.112801E-02 -3.743485E-01 -1.401368E-01 -2.832798E-01 -8.024744E-02 -1.469655E-01 -2.159885E-02 +2.530293E-01 +6.402384E-02 +3.535862E-01 +1.250232E-01 +2.465508E-01 +6.078730E-02 +1.197139E-01 +1.433141E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.469655E-01 -2.159885E-02 -2.832798E-01 -8.024744E-02 -1.515017E-01 -2.295275E-02 +1.197139E-01 +1.433141E-02 +2.465508E-01 +6.078730E-02 +1.369614E-01 +1.875841E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,119 +345,119 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -7.817283E-01 -6.110991E-01 -1.253966E-01 -1.572431E-02 -1.426340E+00 -2.034446E+00 -2.208824E-01 -4.878905E-02 -1.815669E+00 -3.296655E+00 -2.598719E-01 -6.753342E-02 -2.446230E+00 -5.984040E+00 -3.067264E-01 -9.408108E-02 -2.670094E+00 -7.129404E+00 -3.358723E-01 -1.128102E-01 -2.682092E+00 -7.193615E+00 -3.021784E-01 -9.131179E-02 -2.215470E+00 -4.908307E+00 -3.092112E-01 -9.561158E-02 -1.871290E+00 -3.501727E+00 -2.400626E-01 -5.763006E-02 -1.483119E+00 -2.199642E+00 -2.197799E-01 -4.830323E-02 -8.009200E-01 -6.414728E-01 -1.023113E-01 -1.046761E-02 +7.701212E-01 +5.930866E-01 +1.386254E-01 +1.921700E-02 +1.547321E+00 +2.394203E+00 +2.630318E-01 +6.918571E-02 +2.106393E+00 +4.436893E+00 +2.807911E-01 +7.884363E-02 +2.435870E+00 +5.933464E+00 +3.322093E-01 +1.103630E-01 +2.753652E+00 +7.582597E+00 +3.825961E-01 +1.463797E-01 +2.623856E+00 +6.884619E+00 +3.888719E-01 +1.512213E-01 +2.376884E+00 +5.649579E+00 +3.196211E-01 +1.021576E-01 +2.021851E+00 +4.087882E+00 +2.897873E-01 +8.397667E-02 +1.333182E+00 +1.777374E+00 +1.627096E-01 +2.647441E-02 +7.258458E-01 +5.268521E-01 +9.348575E-02 +8.739586E-03 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.165539E+00 -1.179703E+00 -1.191810E+00 -1.207373E+00 -1.203749E+00 -1.208059E+00 -1.208191E+00 -1.201767E+00 -1.201921E+00 -1.203758E+00 -1.209018E+00 +1.149087E+00 +1.156777E+00 +1.158641E+00 +1.159507E+00 +1.156564E+00 +1.160257E+00 +1.150344E+00 +1.149854E+00 +1.151616E+00 +1.164575E+00 +1.174683E+00 cmfd entropy -3.217563E+00 -3.209882E+00 -3.204676E+00 -3.212483E+00 -3.217256E+00 -3.216849E+00 -3.219070E+00 -3.217085E+00 -3.223663E+00 -3.230980E+00 -3.230377E+00 +3.216202E+00 +3.228703E+00 +3.220414E+00 +3.214361E+00 +3.215642E+00 +3.213607E+00 +3.212862E+00 +3.213128E+00 +3.213189E+00 +3.205465E+00 +3.202859E+00 cmfd balance -1.65304E-03 -2.29951E-03 -1.63426E-03 -1.40012E-03 -1.91396E-03 -1.62948E-03 -1.95633E-03 -2.03045E-03 -1.93004E-03 -2.33201E-03 -2.29894E-03 +3.08825E-03 +1.42554E-03 +1.21448E-03 +1.17859E-03 +1.06034E-03 +9.30949E-04 +1.35713E-03 +1.13694E-03 +1.14938E-03 +1.29296E-03 +1.46518E-03 cmfd dominance ratio -5.460E-01 -5.473E-01 -5.415E-01 -5.446E-01 -5.451E-01 -5.475E-01 -5.502E-01 -5.474E-01 -5.498E-01 -5.502E-01 -5.483E-01 +5.503E-01 +5.596E-01 +5.505E-01 +5.471E-01 +5.468E-01 +5.427E-01 +5.421E-01 +5.412E-01 +5.389E-01 +5.371E-01 +5.329E-01 cmfd openmc source comparison -6.484315E-03 -3.411419E-03 -4.321857E-03 -7.194272E-03 -9.907101E-03 -1.046661E-02 -1.050754E-02 -6.523687E-03 -7.212189E-03 -4.425062E-03 -2.540177E-03 +1.571006E-02 +6.945629E-03 +6.838511E-03 +6.183655E-03 +5.138825E-03 +4.362701E-03 +5.558586E-03 +4.188314E-03 +1.837101E-03 +2.737321E-03 +2.529244E-03 cmfd source -4.224343E-02 -7.503541E-02 -1.009853E-01 -1.238103E-01 -1.301388E-01 -1.425912E-01 -1.353339E-01 -1.134730E-01 -8.830826E-02 -4.808031E-02 +4.240947E-02 +8.226746E-02 +1.180848E-01 +1.328470E-01 +1.412449E-01 +1.424870E-01 +1.269297E-01 +1.096476E-01 +6.953001E-02 +3.455212E-02 diff --git a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat b/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat index a065289ec..5ff4a132f 100644 --- a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat +++ b/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.169526E+00 5.973537E-03 +1.173626E+00 1.098719E-02 tally 1: -1.115884E+01 -1.253283E+01 -2.176964E+01 -4.753045E+01 -2.988209E+01 -8.948736E+01 -3.426842E+01 -1.176956E+02 -3.817775E+01 -1.464502E+02 -3.802079E+01 -1.449155E+02 -3.407399E+01 -1.166067E+02 -2.938579E+01 -8.673128E+01 -2.126809E+01 -4.540856E+01 -1.105934E+01 -1.229825E+01 +1.101892E+01 +1.218768E+01 +2.036233E+01 +4.152577E+01 +2.937587E+01 +8.637268E+01 +3.502389E+01 +1.231700E+02 +3.804803E+01 +1.453948E+02 +3.822561E+01 +1.465677E+02 +3.456290E+01 +1.198651E+02 +2.904088E+01 +8.470264E+01 +2.111529E+01 +4.463713E+01 +1.147633E+01 +1.326012E+01 tally 2: -1.064631E+00 -1.133439E+00 -7.584662E-01 -5.752710E-01 -1.898252E+00 -3.603361E+00 -1.330629E+00 -1.770573E+00 -2.737585E+00 -7.494369E+00 -1.949437E+00 -3.800303E+00 -3.313845E+00 -1.098157E+01 -2.356303E+00 -5.552166E+00 -3.735566E+00 -1.395445E+01 -2.657859E+00 -7.064213E+00 -4.052274E+00 -1.642093E+01 -2.864885E+00 -8.207568E+00 -3.385112E+00 -1.145899E+01 -2.358075E+00 -5.560519E+00 -2.776429E+00 -7.708560E+00 -1.960468E+00 -3.843434E+00 -2.240243E+00 -5.018688E+00 -1.549641E+00 -2.401386E+00 -1.092006E+00 -1.192478E+00 -7.441585E-01 -5.537719E-01 +1.010478E+00 +1.021066E+00 +6.902031E-01 +4.763804E-01 +1.899891E+00 +3.609584E+00 +1.322615E+00 +1.749312E+00 +2.756419E+00 +7.597845E+00 +1.955934E+00 +3.825676E+00 +3.818740E+00 +1.458278E+01 +2.704746E+00 +7.315652E+00 +3.920857E+00 +1.537312E+01 +2.843144E+00 +8.083470E+00 +3.835060E+00 +1.470768E+01 +2.728705E+00 +7.445831E+00 +3.510590E+00 +1.232424E+01 +2.497237E+00 +6.236191E+00 +2.717388E+00 +7.384198E+00 +1.903638E+00 +3.623837E+00 +2.207863E+00 +4.874659E+00 +1.563588E+00 +2.444808E+00 +1.289027E+00 +1.661591E+00 +9.022714E-01 +8.140937E-01 tally 3: -7.295798E-01 -5.322866E-01 -4.986135E-02 -2.486155E-03 -1.280099E+00 -1.638654E+00 -9.022531E-02 -8.140606E-03 -1.859202E+00 -3.456630E+00 -1.234662E-01 -1.524390E-02 -2.274313E+00 -5.172502E+00 -1.234662E-01 -1.524390E-02 -2.548554E+00 -6.495129E+00 -1.531456E-01 -2.345357E-02 -2.773126E+00 -7.690228E+00 -1.733276E-01 -3.004244E-02 -2.270798E+00 -5.156524E+00 -1.673917E-01 -2.801998E-02 -1.887286E+00 -3.561849E+00 -1.507712E-01 -2.273196E-02 -1.480414E+00 -2.191625E+00 -1.127816E-01 -1.271970E-02 -7.126366E-01 -5.078509E-01 -6.054593E-02 -3.665809E-03 +6.593197E-01 +4.347024E-01 +5.216387E-02 +2.721069E-03 +1.266446E+00 +1.603885E+00 +8.298797E-02 +6.887003E-03 +1.888709E+00 +3.567222E+00 +1.398940E-01 +1.957033E-02 +2.616078E+00 +6.843867E+00 +1.588627E-01 +2.523735E-02 +2.733300E+00 +7.470927E+00 +1.944290E-01 +3.780262E-02 +2.643656E+00 +6.988917E+00 +1.612338E-01 +2.599633E-02 +2.410643E+00 +5.811199E+00 +1.754603E-01 +3.078631E-02 +1.838012E+00 +3.378288E+00 +1.126265E-01 +1.268473E-02 +1.500033E+00 +2.250100E+00 +1.102554E-01 +1.215626E-02 +8.750096E-01 +7.656418E-01 +6.757592E-02 +4.566505E-03 tally 4: -1.416041E-01 -2.005172E-02 +1.490605E-01 +2.221904E-02 0.000000E+00 0.000000E+00 -1.118431E-01 -1.250887E-02 -2.419761E-01 -5.855243E-02 +1.139233E-01 +1.297851E-02 +2.549497E-01 +6.499934E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.419761E-01 -5.855243E-02 -1.118431E-01 -1.250887E-02 -2.383966E-01 -5.683292E-02 -3.454391E-01 -1.193281E-01 +2.549497E-01 +6.499934E-02 +1.139233E-01 +1.297851E-02 +2.191337E-01 +4.801958E-02 +3.295187E-01 +1.085826E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.454391E-01 -1.193281E-01 -2.383966E-01 -5.683292E-02 -3.449676E-01 -1.190027E-01 -4.324309E-01 -1.869965E-01 +3.295187E-01 +1.085826E-01 +2.191337E-01 +4.801958E-02 +3.872400E-01 +1.499548E-01 +4.595835E-01 +2.112170E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.324309E-01 -1.869965E-01 -3.449676E-01 -1.190027E-01 -4.410209E-01 -1.944994E-01 -4.785286E-01 -2.289896E-01 +4.595835E-01 +2.112170E-01 +3.872400E-01 +1.499548E-01 +4.668106E-01 +2.179121E-01 +5.112307E-01 +2.613569E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.785286E-01 -2.289896E-01 -4.410209E-01 -1.944994E-01 -5.038795E-01 -2.538945E-01 -5.028063E-01 -2.528142E-01 +5.112307E-01 +2.613569E-01 +4.668106E-01 +2.179121E-01 +4.716605E-01 +2.224636E-01 +4.916148E-01 +2.416851E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.028063E-01 -2.528142E-01 -5.038795E-01 -2.538945E-01 -4.780368E-01 -2.285192E-01 -4.303602E-01 -1.852099E-01 +4.916148E-01 +2.416851E-01 +4.716605E-01 +2.224636E-01 +4.696777E-01 +2.205972E-01 +4.365150E-01 +1.905453E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.303602E-01 -1.852099E-01 -4.780368E-01 -2.285192E-01 -4.183673E-01 -1.750312E-01 -3.317104E-01 -1.100318E-01 +4.365150E-01 +1.905453E-01 +4.696777E-01 +2.205972E-01 +4.179902E-01 +1.747158E-01 +3.350564E-01 +1.122628E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.317104E-01 -1.100318E-01 -4.183673E-01 -1.750312E-01 -3.797671E-01 -1.442230E-01 -2.636003E-01 -6.948514E-02 +3.350564E-01 +1.122628E-01 +4.179902E-01 +1.747158E-01 +3.743487E-01 +1.401370E-01 +2.400661E-01 +5.763172E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.636003E-01 -6.948514E-02 -3.797671E-01 -1.442230E-01 -2.686240E-01 -7.215888E-02 -1.324766E-01 -1.755005E-02 +2.400661E-01 +5.763172E-02 +3.743487E-01 +1.401370E-01 +3.063657E-01 +9.385994E-02 +1.605078E-01 +2.576275E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.324766E-01 -1.755005E-02 -2.686240E-01 -7.215888E-02 -1.444839E-01 -2.087560E-02 +1.605078E-01 +2.576275E-02 +3.063657E-01 +9.385994E-02 +1.700639E-01 +2.892174E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,119 +345,119 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -7.285713E-01 -5.308161E-01 -1.056136E-01 -1.115423E-02 -1.280099E+00 -1.638654E+00 -1.717497E-01 -2.949797E-02 -1.859202E+00 -3.456630E+00 -2.285372E-01 -5.222927E-02 -2.274313E+00 -5.172502E+00 -2.636808E-01 -6.952757E-02 -2.547588E+00 -6.490203E+00 -2.914026E-01 -8.491545E-02 -2.773126E+00 -7.690228E+00 -3.908576E-01 -1.527696E-01 -2.269831E+00 -5.152135E+00 -3.279256E-01 -1.075352E-01 -1.886272E+00 -3.558024E+00 -2.679083E-01 -7.177487E-02 -1.479436E+00 -2.188731E+00 -2.362981E-01 -5.583681E-02 -7.126366E-01 -5.078509E-01 -1.015892E-01 -1.032038E-02 +6.593197E-01 +4.347024E-01 +1.314196E-01 +1.727112E-02 +1.266446E+00 +1.603885E+00 +2.002491E-01 +4.009970E-02 +1.888709E+00 +3.567222E+00 +2.444522E-01 +5.975686E-02 +2.616078E+00 +6.843867E+00 +3.234935E-01 +1.046481E-01 +2.733300E+00 +7.470927E+00 +3.309500E-01 +1.095279E-01 +2.643656E+00 +6.988917E+00 +4.025014E-01 +1.620074E-01 +2.410643E+00 +5.811199E+00 +3.050040E-01 +9.302747E-02 +1.838012E+00 +3.378288E+00 +2.800764E-01 +7.844279E-02 +1.500033E+00 +2.250100E+00 +2.324765E-01 +5.404531E-02 +8.750096E-01 +7.656418E-01 +1.256919E-01 +1.579844E-02 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.188625E+00 -1.172261E+00 -1.172154E+00 -1.176234E+00 -1.161072E+00 -1.174217E+00 -1.176208E+00 -1.183067E+00 -1.208406E+00 -1.220367E+00 -1.208889E+00 +1.166297E+00 +1.148237E+00 +1.162472E+00 +1.187078E+00 +1.188411E+00 +1.194879E+00 +1.216739E+00 +1.216829E+00 +1.196596E+00 +1.199223E+00 +1.211817E+00 cmfd entropy -3.216548E+00 -3.213244E+00 -3.220132E+00 -3.216556E+00 -3.218184E+00 -3.208592E+00 -3.220641E+00 -3.217076E+00 -3.216257E+00 -3.212578E+00 -3.230102E+00 +3.215349E+00 +3.225577E+00 +3.223357E+00 +3.208828E+00 +3.211072E+00 +3.206578E+00 +3.195799E+00 +3.198236E+00 +3.220074E+00 +3.230249E+00 +3.238015E+00 cmfd balance -1.65186E-03 -1.76715E-03 -2.25997E-03 -2.27924E-03 -1.67354E-03 -1.72671E-03 -1.79744E-03 -1.99065E-03 -2.56417E-03 -2.45718E-03 -3.26245E-03 +2.07468E-03 +2.39687E-03 +1.51020E-03 +2.07618E-03 +1.89367E-03 +2.00902E-03 +2.54856E-03 +2.43636E-03 +2.48527E-03 +3.07775E-03 +3.37967E-03 cmfd dominance ratio -5.445E-01 -5.466E-01 -5.539E-01 -5.547E-01 -5.569E-01 -5.518E-01 -5.553E-01 -5.544E-01 -5.474E-01 -5.355E-01 -5.460E-01 +5.505E-01 +5.558E-01 +5.584E-01 +5.477E-01 +5.477E-01 +5.426E-01 +5.335E-01 +5.305E-01 +5.427E-01 +5.484E-01 +5.465E-01 cmfd openmc source comparison -5.662096E-03 -3.660183E-03 -4.806643E-03 -2.475327E-03 -6.166988E-03 -2.205088E-03 -4.010491E-03 -6.270883E-03 -3.070427E-03 -5.679208E-03 -1.488803E-02 +5.598628E-03 +1.162952E-02 +1.083004E-02 +1.037470E-02 +5.649750E-03 +5.137914E-03 +3.868209E-03 +1.208756E-02 +5.398131E-03 +8.119598E-03 +4.573105E-03 cmfd source -4.111004E-02 -7.023296E-02 -1.023250E-01 -1.185886E-01 -1.386562E-01 -1.392823E-01 -1.290017E-01 -1.147469E-01 -9.733704E-02 -4.871933E-02 +4.219187E-02 +8.692096E-02 +1.061389E-01 +1.199181E-01 +1.377328E-01 +1.326161E-01 +1.345872E-01 +1.112871E-01 +7.569533E-02 +5.291175E-02 diff --git a/tests/regression_tests/cmfd_nofeed/results_true.dat b/tests/regression_tests/cmfd_nofeed/results_true.dat index dac35871c..756aa4570 100644 --- a/tests/regression_tests/cmfd_nofeed/results_true.dat +++ b/tests/regression_tests/cmfd_nofeed/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.170405E+00 1.487119E-02 +1.172893E+00 8.095197E-03 tally 1: -1.172722E+01 -1.378635E+01 -2.122139E+01 -4.511390E+01 -2.936481E+01 -8.649521E+01 -3.553909E+01 -1.265901E+02 -3.862903E+01 -1.497314E+02 -3.683895E+01 -1.358679E+02 -3.373597E+01 -1.140439E+02 -2.810435E+01 -7.932253E+01 -2.098314E+01 -4.409819E+01 -1.105096E+01 -1.224007E+01 +1.156995E+01 +1.347019E+01 +2.120053E+01 +4.531200E+01 +2.995993E+01 +8.997889E+01 +3.498938E+01 +1.226414E+02 +3.794510E+01 +1.442188E+02 +3.798115E+01 +1.446436E+02 +3.415954E+01 +1.171635E+02 +2.960329E+01 +8.785532E+01 +2.182231E+01 +4.782353E+01 +1.147379E+01 +1.321150E+01 tally 2: -2.275408E+01 -2.603315E+01 -1.590700E+01 -1.273395E+01 -4.112322E+01 -8.498758E+01 -2.911800E+01 -4.264070E+01 -5.707453E+01 -1.638375E+02 -4.069300E+01 -8.336155E+01 -6.915962E+01 -2.399628E+02 -4.926800E+01 -1.218497E+02 -7.521027E+01 -2.842789E+02 -5.357900E+01 -1.443468E+02 -7.387401E+01 -2.738660E+02 -5.263400E+01 -1.390611E+02 -6.871266E+01 -2.368771E+02 -4.902000E+01 -1.205569E+02 -5.632046E+01 -1.592677E+02 -3.999300E+01 -8.035469E+01 -4.291289E+01 -9.245946E+01 -3.046000E+01 -4.661878E+01 -2.273666E+01 -2.598211E+01 -1.590800E+01 -1.271433E+01 +2.345900E+01 +2.783672E+01 +1.627300E+01 +1.339749E+01 +4.127267E+01 +8.563716E+01 +2.934800E+01 +4.334439E+01 +5.742644E+01 +1.658158E+02 +4.092600E+01 +8.423842E+01 +6.740126E+01 +2.279288E+02 +4.796500E+01 +1.154602E+02 +7.340327E+01 +2.701349E+02 +5.235900E+01 +1.374186E+02 +7.387392E+01 +2.740829E+02 +5.277400E+01 +1.398425E+02 +6.733428E+01 +2.274414E+02 +4.800100E+01 +1.156206E+02 +5.794970E+01 +1.685421E+02 +4.124600E+01 +8.540686E+01 +4.257013E+01 +9.092401E+01 +3.014500E+01 +4.566369E+01 +2.300274E+01 +2.659051E+01 +1.613400E+01 +1.307448E+01 tally 3: -1.529800E+01 -1.178010E+01 -1.016076E+00 -5.280687E-02 -2.803900E+01 -3.955010E+01 -1.861024E+00 -1.765351E-01 -3.919400E+01 -7.734526E+01 -2.540695E+00 -3.268959E-01 -4.749400E+01 -1.132677E+02 -3.087604E+00 -4.837647E-01 -5.156500E+01 -1.337335E+02 -3.371014E+00 -5.734875E-01 -5.070500E+01 -1.290569E+02 -3.292766E+00 -5.489854E-01 -4.723400E+01 -1.119247E+02 -2.949932E+00 -4.381745E-01 -3.847900E+01 -7.441953E+01 -2.522868E+00 -3.218962E-01 -2.933900E+01 -4.325593E+01 -1.818016E+00 -1.672765E-01 -1.534700E+01 -1.183573E+01 -9.564025E-01 -4.735079E-02 +1.564900E+01 +1.239852E+01 +1.086873E+00 +6.047264E-02 +2.821700E+01 +4.006730E+01 +1.855830E+00 +1.755984E-01 +3.946300E+01 +7.833997E+01 +2.523142E+00 +3.210725E-01 +4.622500E+01 +1.072588E+02 +2.919735E+00 +4.340292E-01 +5.033400E+01 +1.270010E+02 +3.243022E+00 +5.318534E-01 +5.082400E+01 +1.297502E+02 +3.313898E+00 +5.546608E-01 +4.623700E+01 +1.072944E+02 +2.887766E+00 +4.203084E-01 +3.975000E+01 +7.934279E+01 +2.567158E+00 +3.333121E-01 +2.903500E+01 +4.237270E+01 +1.852070E+00 +1.733821E-01 +1.557800E+01 +1.219084E+01 +9.951884E-01 +5.121758E-02 tally 4: -3.092000E+00 -4.809100E-01 +3.111000E+00 +4.872850E-01 0.000000E+00 0.000000E+00 -2.628000E+00 -3.509980E-01 -5.388000E+00 -1.458946E+00 +2.794000E+00 +3.972060E-01 +5.520000E+00 +1.535670E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.388000E+00 -1.458946E+00 -2.628000E+00 -3.509980E-01 -5.063000E+00 -1.292417E+00 -7.312000E+00 -2.686738E+00 +5.520000E+00 +1.535670E+00 +2.794000E+00 +3.972060E-01 +5.071000E+00 +1.305697E+00 +7.303000E+00 +2.685365E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.312000E+00 -2.686738E+00 -5.063000E+00 -1.292417E+00 -7.115000E+00 -2.542363E+00 -8.719000E+00 -3.819081E+00 +7.303000E+00 +2.685365E+00 +5.071000E+00 +1.305697E+00 +7.015000E+00 +2.471981E+00 +8.545000E+00 +3.670539E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.719000E+00 -3.819081E+00 -7.115000E+00 -2.542363E+00 -8.483000E+00 -3.615549E+00 -9.255000E+00 -4.303287E+00 +8.545000E+00 +3.670539E+00 +7.015000E+00 +2.471981E+00 +8.431000E+00 +3.570057E+00 +9.224000E+00 +4.268004E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.255000E+00 -4.303287E+00 -8.483000E+00 -3.615549E+00 -9.375000E+00 -4.416751E+00 -9.330000E+00 -4.375230E+00 +9.224000E+00 +4.268004E+00 +8.431000E+00 +3.570057E+00 +9.217000E+00 +4.259749E+00 +9.305000E+00 +4.340149E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.330000E+00 -4.375230E+00 -9.375000E+00 -4.416751E+00 -9.346000E+00 -4.379220E+00 -8.458000E+00 -3.585930E+00 +9.305000E+00 +4.340149E+00 +9.217000E+00 +4.259749E+00 +9.374000E+00 +4.415290E+00 +8.611000E+00 +3.718227E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.458000E+00 -3.585930E+00 -9.346000E+00 -4.379220E+00 -8.671000E+00 -3.770383E+00 -7.062000E+00 -2.505966E+00 +8.611000E+00 +3.718227E+00 +9.374000E+00 +4.415290E+00 +8.515000E+00 +3.639945E+00 +7.056000E+00 +2.501658E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.062000E+00 -2.505966E+00 -8.671000E+00 -3.770383E+00 -7.279000E+00 -2.663587E+00 -4.994000E+00 -1.261468E+00 +7.056000E+00 +2.501658E+00 +8.515000E+00 +3.639945E+00 +7.385000E+00 +2.737677E+00 +5.194000E+00 +1.356022E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.994000E+00 -1.261468E+00 -7.279000E+00 -2.663587E+00 -5.492000E+00 -1.515002E+00 -2.772000E+00 -3.896040E-01 +5.194000E+00 +1.356022E+00 +7.385000E+00 +2.737677E+00 +5.436000E+00 +1.481654E+00 +2.756000E+00 +3.843860E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.772000E+00 -3.896040E-01 -5.492000E+00 -1.515002E+00 -3.022000E+00 -4.608940E-01 +2.756000E+00 +3.843860E-01 +5.436000E+00 +1.481654E+00 +3.030000E+00 +4.643920E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,144 +345,144 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -1.529600E+01 -1.177689E+01 -2.229624E+00 -2.514699E-01 -2.803300E+01 -3.953329E+01 -3.889856E+00 -7.678274E-01 -3.918900E+01 -7.732686E+01 -5.211188E+00 -1.378173E+00 -4.748700E+01 -1.132339E+02 -6.595911E+00 -2.211528E+00 -5.155000E+01 -1.336522E+02 -6.673103E+00 -2.248462E+00 -5.069800E+01 -1.290196E+02 -6.907470E+00 -2.412919E+00 -4.722500E+01 -1.118824E+02 -6.200070E+00 -1.954544E+00 -3.847200E+01 -7.439145E+01 -5.385095E+00 -1.462192E+00 -2.933600E+01 -4.324744E+01 -4.014057E+00 -8.142088E-01 -1.534200E+01 -1.182781E+01 -2.076271E+00 -2.273431E-01 +1.564300E+01 +1.238861E+01 +2.090227E+00 +2.262627E-01 +2.821400E+01 +4.005826E+01 +3.870834E+00 +7.614623E-01 +3.945400E+01 +7.830326E+01 +5.290557E+00 +1.422339E+00 +4.621500E+01 +1.072116E+02 +6.144745E+00 +1.903309E+00 +5.032900E+01 +1.269756E+02 +6.867524E+00 +2.373593E+00 +5.081000E+01 +1.296784E+02 +6.456283E+00 +2.130767E+00 +4.623000E+01 +1.072613E+02 +5.931623E+00 +1.776451E+00 +3.974500E+01 +7.932288E+01 +5.339603E+00 +1.456812E+00 +2.902800E+01 +4.235232E+01 +4.102240E+00 +8.519551E-01 +1.557800E+01 +1.219084E+01 +2.137954E+00 +2.347770E-01 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.161531E+00 -1.181707E+00 -1.176063E+00 -1.168433E+00 -1.173170E+00 -1.174671E+00 -1.176457E+00 -1.177540E+00 -1.180826E+00 -1.174158E+00 -1.171305E+00 -1.172618E+00 -1.170171E+00 -1.173235E+00 -1.172599E+00 -1.177343E+00 +1.129918E+00 +1.148352E+00 +1.143137E+00 +1.145795E+00 +1.147285E+00 +1.148588E+00 +1.148151E+00 +1.162118E+00 +1.165380E+00 +1.162851E+00 +1.163379E+00 +1.166986E+00 +1.167838E+00 +1.171743E+00 +1.170398E+00 +1.169773E+00 cmfd entropy -3.206619E+00 -3.207385E+00 -3.208853E+00 -3.210825E+00 -3.214820E+00 -3.213490E+00 -3.212717E+00 -3.210590E+00 -3.211948E+00 -3.212156E+00 -3.212900E+00 -3.212275E+00 -3.212766E+00 -3.214205E+00 -3.212717E+00 -3.214169E+00 +3.224769E+00 +3.222795E+00 +3.221174E+00 +3.222164E+00 +3.221025E+00 +3.220967E+00 +3.223497E+00 +3.219213E+00 +3.221679E+00 +3.222084E+00 +3.222281E+00 +3.222540E+00 +3.224614E+00 +3.224193E+00 +3.224925E+00 +3.224367E+00 cmfd balance -4.99833E-03 -5.81289E-03 -3.45193E-03 -2.84521E-03 -3.72331E-03 -3.07942E-03 -2.58676E-03 -2.19354E-03 -2.11522E-03 -2.02671E-03 -1.71439E-03 -1.62909E-03 -1.43261E-03 -1.26201E-03 -1.40167E-03 -1.26141E-03 +3.90454E-03 +4.33180E-03 +3.77057E-03 +3.16391E-03 +3.11765E-03 +2.59886E-03 +2.81060E-03 +3.25473E-03 +2.68544E-03 +2.01716E-03 +1.89350E-03 +1.79159E-03 +1.51353E-03 +1.48514E-03 +1.50207E-03 +1.44045E-03 cmfd dominance ratio -5.283E-01 -5.304E-01 -5.310E-01 -5.324E-01 -5.372E-01 -5.369E-01 -5.367E-01 -5.341E-01 -5.353E-01 -5.375E-01 -5.379E-01 -5.372E-01 -5.379E-01 -5.393E-01 -5.384E-01 -5.382E-01 +5.539E-01 +5.522E-01 +5.491E-01 +5.511E-01 +5.506E-01 +5.523E-01 +5.523E-01 +5.473E-01 +5.478E-01 +5.461E-01 +5.462E-01 +5.459E-01 +5.475E-01 +5.463E-01 +5.466E-01 +5.469E-01 cmfd openmc source comparison -1.291827E-02 -9.488059E-03 -8.538280E-03 -6.820006E-03 -4.300032E-03 -5.486871E-03 -4.493389E-03 -4.913340E-03 -5.132196E-03 -3.342331E-03 -3.094995E-03 -3.553279E-03 -3.284811E-03 -2.492272E-03 -3.062765E-03 -2.632092E-03 +9.875240E-03 +1.119358E-02 +8.513903E-03 +7.728971E-03 +5.993771E-03 +5.837301E-03 +4.861789E-03 +5.624038E-03 +4.297229E-03 +4.029732E-03 +3.669197E-03 +3.598834E-03 +3.023310E-03 +3.347346E-03 +2.943658E-03 +2.764986E-03 cmfd source -4.280100E-02 -7.944783E-02 -1.091569E-01 -1.329540E-01 -1.451697E-01 -1.413526E-01 -1.258514E-01 -1.067698E-01 -7.656551E-02 -3.993138E-02 +4.561921E-02 +7.896381E-02 +1.084687E-01 +1.264057E-01 +1.408942E-01 +1.438180E-01 +1.247333E-01 +1.100896E-01 +7.897187E-02 +4.203556E-02 diff --git a/tests/regression_tests/cmfd_restart/results_true.dat b/tests/regression_tests/cmfd_restart/results_true.dat index 90d8820d0..f5f22d9ac 100644 --- a/tests/regression_tests/cmfd_restart/results_true.dat +++ b/tests/regression_tests/cmfd_restart/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.159021E+00 8.924006E-03 +1.164262E+00 9.207592E-03 tally 1: -1.140162E+01 -1.306940E+01 -2.093739E+01 -4.404780E+01 -2.914408E+01 -8.521010E+01 -3.483677E+01 -1.216824E+02 -3.778463E+01 -1.429632E+02 -3.810371E+01 -1.455108E+02 -3.465248E+01 -1.207868E+02 -2.862033E+01 -8.218833E+01 -2.086025E+01 -4.365941E+01 -1.130798E+01 -1.286509E+01 +1.156972E+01 +1.339924E+01 +2.136306E+01 +4.567185E+01 +2.859527E+01 +8.195821E+01 +3.470754E+01 +1.207851E+02 +3.766403E+01 +1.422263E+02 +3.778821E+01 +1.432660E+02 +3.573197E+01 +1.278854E+02 +2.849979E+01 +8.135515E+01 +2.073803E+01 +4.303374E+01 +1.112117E+01 +1.242944E+01 tally 2: -2.234393E+01 -2.516414E+01 -1.555024E+01 -1.218205E+01 -4.087743E+01 -8.401702E+01 -2.883717E+01 -4.185393E+01 -5.635166E+01 -1.595225E+02 -3.998857E+01 -8.040398E+01 -6.887126E+01 -2.379185E+02 -4.903103E+01 -1.206174E+02 -7.452051E+01 -2.785675E+02 -5.295380E+01 -1.406900E+02 -7.495422E+01 -2.819070E+02 -5.333191E+01 -1.427474E+02 -6.921815E+01 -2.408568E+02 -4.928246E+01 -1.221076E+02 -5.668548E+01 -1.612556E+02 -4.035856E+01 -8.181159E+01 -4.259952E+01 -9.112630E+01 -3.026717E+01 -4.600625E+01 -2.310563E+01 -2.688378E+01 -1.615934E+01 -1.315528E+01 +2.388054E+01 +2.875255E+01 +1.667791E+01 +1.403426E+01 +4.224771E+01 +8.942109E+01 +2.993088E+01 +4.490335E+01 +5.689839E+01 +1.625557E+02 +4.043633E+01 +8.212299E+01 +6.764024E+01 +2.297126E+02 +4.807902E+01 +1.161468E+02 +7.314835E+01 +2.684645E+02 +5.203584E+01 +1.359261E+02 +7.375727E+01 +2.733105E+02 +5.252944E+01 +1.386205E+02 +6.909571E+01 +2.397721E+02 +4.922548E+01 +1.217465E+02 +5.685978E+01 +1.621746E+02 +4.051938E+01 +8.237277E+01 +4.185562E+01 +8.784067E+01 +2.983570E+01 +4.467414E+01 +2.238373E+01 +2.520356E+01 +1.566758E+01 +1.234103E+01 tally 3: -1.496375E+01 -1.128154E+01 -9.905641E-01 -5.125710E-02 -2.774937E+01 -3.877241E+01 -1.786861E+00 -1.627655E-01 -3.849739E+01 -7.453828E+01 -2.494135E+00 -3.158098E-01 -4.724085E+01 -1.119901E+02 -3.031174E+00 -4.653741E-01 -5.096719E+01 -1.303552E+02 -3.254375E+00 -5.351020E-01 -5.133808E+01 -1.322892E+02 -3.383595E+00 -5.798798E-01 -4.756072E+01 -1.137527E+02 -3.001917E+00 -4.558247E-01 -3.887437E+01 -7.593416E+01 -2.517908E+00 -3.221926E-01 -2.910687E+01 -4.255173E+01 -1.817765E+00 -1.678763E-01 -1.557241E+01 -1.222026E+01 -9.852737E-01 -5.002659E-02 +1.609520E+01 +1.307542E+01 +1.033429E+00 +5.510889E-02 +2.877073E+01 +4.149542E+01 +1.964219E+00 +1.954692E-01 +3.896816E+01 +7.629752E+01 +2.484053E+00 +3.103733E-01 +4.634285E+01 +1.079367E+02 +2.974750E+00 +4.468223E-01 +5.007964E+01 +1.259202E+02 +3.181802E+00 +5.103621E-01 +5.058915E+01 +1.286193E+02 +3.249442E+00 +5.337712E-01 +4.744464E+01 +1.131026E+02 +3.067644E+00 +4.736335E-01 +3.900632E+01 +7.634433E+01 +2.443552E+00 +3.028060E-01 +2.874166E+01 +4.146375E+01 +1.810421E+00 +1.671667E-01 +1.509222E+01 +1.145579E+01 +1.014919E+00 +5.391053E-02 tally 4: -3.047490E+00 -4.661458E-01 +3.148231E+00 +4.974555E-01 0.000000E+00 0.000000E+00 -2.635775E+00 -3.524426E-01 -5.357229E+00 -1.440049E+00 +2.805439E+00 +3.982239E-01 +5.574031E+00 +1.561105E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.357229E+00 -1.440049E+00 -2.635775E+00 -3.524426E-01 -4.982072E+00 -1.251449E+00 -7.228146E+00 -2.620353E+00 +5.574031E+00 +1.561105E+00 +2.805439E+00 +3.982239E-01 +5.171038E+00 +1.344877E+00 +7.372031E+00 +2.725420E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.228146E+00 -2.620353E+00 -4.982072E+00 -1.251449E+00 -7.082265E+00 -2.520047E+00 -8.736529E+00 -3.831244E+00 +7.372031E+00 +2.725420E+00 +5.171038E+00 +1.344877E+00 +6.946847E+00 +2.424850E+00 +8.496610E+00 +3.627542E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.736529E+00 -3.831244E+00 -7.082265E+00 -2.520047E+00 -8.474631E+00 -3.607043E+00 -9.346623E+00 -4.390819E+00 +8.496610E+00 +3.627542E+00 +6.946847E+00 +2.424850E+00 +8.479501E+00 +3.607280E+00 +9.261869E+00 +4.305912E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.346623E+00 -4.390819E+00 -8.474631E+00 -3.607043E+00 -9.496684E+00 -4.522478E+00 -9.532822E+00 -4.559003E+00 +9.261869E+00 +4.305912E+00 +8.479501E+00 +3.607280E+00 +9.232858E+00 +4.278432E+00 +9.306384E+00 +4.348594E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.532822E+00 -4.559003E+00 -9.496684E+00 -4.522478E+00 -9.404949E+00 -4.446260E+00 -8.550930E+00 -3.668401E+00 +9.306384E+00 +4.348594E+00 +9.232858E+00 +4.278432E+00 +9.299764E+00 +4.347828E+00 +8.511976E+00 +3.639893E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.550930E+00 -3.668401E+00 -9.404949E+00 -4.446260E+00 -8.785273E+00 -3.874792E+00 -7.128863E+00 -2.554326E+00 +8.511976E+00 +3.639893E+00 +9.299764E+00 +4.347828E+00 +8.726086E+00 +3.819567E+00 +7.147277E+00 +2.562747E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.128863E+00 -2.554326E+00 -8.785273E+00 -3.874792E+00 -7.408549E+00 -2.755885E+00 -5.094992E+00 -1.305737E+00 +7.147277E+00 +2.562747E+00 +8.726086E+00 +3.819567E+00 +7.218790E+00 +2.612243E+00 +5.018287E+00 +1.263077E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.094992E+00 -1.305737E+00 -7.408549E+00 -2.755885E+00 -5.532149E+00 -1.537289E+00 -2.812344E+00 -3.997146E-01 +5.018287E+00 +1.263077E+00 +7.218790E+00 +2.612243E+00 +5.443494E+00 +1.487018E+00 +2.732334E+00 +3.773047E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.812344E+00 -3.997146E-01 -5.532149E+00 -1.537289E+00 -3.063251E+00 -4.728672E-01 +2.732334E+00 +3.773047E-01 +5.443494E+00 +1.487018E+00 +3.044773E+00 +4.655756E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,144 +345,144 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -1.496000E+01 -1.127586E+01 -2.280081E+00 -2.675609E-01 -2.774503E+01 -3.876011E+01 -3.908836E+00 -7.703029E-01 -3.848706E+01 -7.449836E+01 -5.299924E+00 -1.422782E+00 -4.723172E+01 -1.119459E+02 -6.450156E+00 -2.105590E+00 -5.095931E+01 -1.303132E+02 -7.050681E+00 -2.515092E+00 -5.133412E+01 -1.322694E+02 -6.853429E+00 -2.384127E+00 -4.754621E+01 -1.136848E+02 -6.370026E+00 -2.058896E+00 -3.886829E+01 -7.591042E+01 -5.266816E+00 -1.400495E+00 -2.910277E+01 -4.253981E+01 -4.090844E+00 -8.442500E-01 -1.556949E+01 -1.221526E+01 -2.266123E+00 -2.641551E-01 +1.609029E+01 +1.306718E+01 +2.230601E+00 +2.559496E-01 +2.876780E+01 +4.148686E+01 +3.835952E+00 +7.456562E-01 +3.895738E+01 +7.625344E+01 +4.841024E+00 +1.197335E+00 +4.633595E+01 +1.079043E+02 +6.236821E+00 +1.963311E+00 +5.007472E+01 +1.258967E+02 +6.749745E+00 +2.297130E+00 +5.058336E+01 +1.285894E+02 +6.727612E+00 +2.315656E+00 +4.743869E+01 +1.130735E+02 +6.338193E+00 +2.042159E+00 +3.899838E+01 +7.631289E+01 +5.187573E+00 +1.359733E+00 +2.873434E+01 +4.144233E+01 +3.815610E+00 +7.367619E-01 +1.509020E+01 +1.145268E+01 +2.125767E+00 +2.341894E-01 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.161531E+00 -1.182724E+00 -1.169653E+00 -1.164722E+00 -1.164583E+00 -1.162952E+00 -1.167024E+00 -1.164509E+00 -1.165693E+00 -1.170623E+00 -1.166618E+00 -1.170805E+00 -1.170962E+00 -1.170964E+00 -1.168224E+00 -1.169864E+00 +1.129918E+00 +1.143848E+00 +1.147976E+00 +1.151534E+00 +1.152378E+00 +1.148219E+00 +1.150402E+00 +1.154647E+00 +1.156159E+00 +1.160048E+00 +1.167441E+00 +1.168163E+00 +1.168629E+00 +1.164120E+00 +1.165051E+00 +1.169177E+00 cmfd entropy -3.206619E+00 -3.205815E+00 -3.208678E+00 -3.210820E+00 -3.217023E+00 -3.215014E+00 -3.214592E+00 -3.215913E+00 -3.214998E+00 -3.213644E+00 -3.210755E+00 -3.210496E+00 -3.212488E+00 -3.211553E+00 -3.212999E+00 -3.214052E+00 +3.224769E+00 +3.225945E+00 +3.227421E+00 +3.226174E+00 +3.224429E+00 +3.227049E+00 +3.230710E+00 +3.230315E+00 +3.226825E+00 +3.226655E+00 +3.226588E+00 +3.224155E+00 +3.223246E+00 +3.222640E+00 +3.223920E+00 +3.222838E+00 cmfd balance -4.99833E-03 -5.64677E-03 -3.62795E-03 -3.91962E-03 -3.87172E-03 -2.48450E-03 -3.15554E-03 -2.49335E-03 -2.31973E-03 -2.19156E-03 -2.31352E-03 -2.03401E-03 -1.80242E-03 -1.65868E-03 -1.47543E-03 -1.49706E-03 +3.90454E-03 +4.08089E-03 +3.46511E-03 +4.09535E-03 +2.62009E-03 +2.23559E-03 +2.54033E-03 +2.12799E-03 +2.25864E-03 +1.85766E-03 +1.49916E-03 +1.63471E-03 +1.48377E-03 +1.59800E-03 +1.37354E-03 +1.32853E-03 cmfd dominance ratio -5.283E-01 -5.289E-01 -5.305E-01 -5.327E-01 -5.377E-01 -5.360E-01 -5.353E-01 -4.983E-01 -5.379E-01 -5.370E-01 -5.359E-01 -5.349E-01 -5.364E-01 -5.347E-01 -5.360E-01 -5.378E-01 +5.539E-01 +5.537E-01 +5.536E-01 +5.515E-01 +5.512E-01 +5.514E-01 +5.518E-01 +5.507E-01 +5.500E-01 +5.497E-01 +5.477E-01 +5.461E-01 +5.444E-01 +5.445E-01 +5.454E-01 +5.441E-01 cmfd openmc source comparison -1.291827E-02 -1.027137E-02 -8.738370E-03 -6.854409E-03 -4.188357E-03 -4.941359E-03 -5.139239E-03 -4.244784E-03 -4.240559E-03 -3.375424E-03 -3.716858E-03 -3.595700E-03 -3.626952E-03 -3.999302E-03 -2.431760E-03 -1.673200E-03 +9.875240E-03 +1.106163E-02 +9.847628E-03 +6.065921E-03 +5.772039E-03 +4.615656E-03 +4.244331E-03 +3.694299E-03 +3.545814E-03 +3.213063E-03 +3.467537E-03 +3.383489E-03 +3.697591E-03 +3.937358E-03 +3.369124E-03 +3.190359E-03 cmfd source -4.185460E-02 -7.636314E-02 -1.075536E-01 -1.307167E-01 -1.400879E-01 -1.459944E-01 -1.297413E-01 -1.084649E-01 -7.772031E-02 -4.150306E-02 +4.360494E-02 +8.397599E-02 +1.074181E-01 +1.294531E-01 +1.385611E-01 +1.407934E-01 +1.325191E-01 +1.044311E-01 +7.660359E-02 +4.263941E-02 diff --git a/tests/regression_tests/complex_cell/results_true.dat b/tests/regression_tests/complex_cell/results_true.dat index 927a7a519..3ce3d7cbc 100644 --- a/tests/regression_tests/complex_cell/results_true.dat +++ b/tests/regression_tests/complex_cell/results_true.dat @@ -1,11 +1,11 @@ k-combined: -2.490321E-01 1.083676E-03 +2.564169E-01 4.095378E-03 tally 1: -2.617769E+00 -1.371478E+00 -2.716496E+00 -1.476169E+00 -1.005297E+00 -2.026100E-01 -1.075286E-01 -2.316593E-03 +2.607144E+00 +1.360414E+00 +2.681079E+00 +1.439354E+00 +9.627534E-01 +1.855496E-01 +1.123751E-01 +2.530233E-03 diff --git a/tests/regression_tests/confidence_intervals/results_true.dat b/tests/regression_tests/confidence_intervals/results_true.dat index cb6c6f00a..6a906d07e 100644 --- a/tests/regression_tests/confidence_intervals/results_true.dat +++ b/tests/regression_tests/confidence_intervals/results_true.dat @@ -1,5 +1,5 @@ k-combined: -2.679617E-01 1.158917E-02 +2.759923E-01 6.988588E-03 tally 1: -6.693704E+01 -5.643483E+02 +6.167984E+01 +4.772717E+02 diff --git a/tests/regression_tests/dagmc/external/results_true.dat b/tests/regression_tests/dagmc/external/results_true.dat index e5127c827..cda656937 100644 --- a/tests/regression_tests/dagmc/external/results_true.dat +++ b/tests/regression_tests/dagmc/external/results_true.dat @@ -1,5 +1,5 @@ k-combined: -8.426936E-01 5.715847E-02 +9.118190E-01 3.615552E-02 tally 1: -8.093843E+00 -1.328829E+01 +8.430103E+00 +1.442878E+01 diff --git a/tests/regression_tests/dagmc/legacy/results_true.dat b/tests/regression_tests/dagmc/legacy/results_true.dat index e5127c827..cda656937 100644 --- a/tests/regression_tests/dagmc/legacy/results_true.dat +++ b/tests/regression_tests/dagmc/legacy/results_true.dat @@ -1,5 +1,5 @@ k-combined: -8.426936E-01 5.715847E-02 +9.118190E-01 3.615552E-02 tally 1: -8.093843E+00 -1.328829E+01 +8.430103E+00 +1.442878E+01 diff --git a/tests/regression_tests/dagmc/refl/results_true.dat b/tests/regression_tests/dagmc/refl/results_true.dat index bd1169835..533c62a90 100644 --- a/tests/regression_tests/dagmc/refl/results_true.dat +++ b/tests/regression_tests/dagmc/refl/results_true.dat @@ -1,5 +1,5 @@ k-combined: -2.130286E+00 2.412252E-02 +2.035173E+00 3.967029E-02 tally 1: -1.177815E+01 -2.806871E+01 +1.064492E+01 +2.301019E+01 diff --git a/tests/regression_tests/dagmc/universes/results_true.dat b/tests/regression_tests/dagmc/universes/results_true.dat index 0dc1789d4..f7bd016c1 100644 --- a/tests/regression_tests/dagmc/universes/results_true.dat +++ b/tests/regression_tests/dagmc/universes/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.436168E-01 2.905559E-02 +9.156561E-01 4.398617E-02 diff --git a/tests/regression_tests/density/results_true.dat b/tests/regression_tests/density/results_true.dat index 17d0730df..c8e3b1ede 100644 --- a/tests/regression_tests/density/results_true.dat +++ b/tests/regression_tests/density/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.097336E+00 2.305434E-02 +1.110057E+00 1.303260E-02 diff --git a/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml b/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml index b81856683..d38e8f96f 100644 --- a/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml +++ b/tests/regression_tests/deplete_with_transport/last_step_reference_materials.xml @@ -4,1001 +4,1001 @@ - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/tests/regression_tests/deplete_with_transport/test_reference.h5 b/tests/regression_tests/deplete_with_transport/test_reference.h5 index 952994b86b468a550adcd787666582a53897167c..af0e3ff46f630056ab9141b30ddc2e0433473cc7 100644 GIT binary patch literal 163736 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 diff --git a/tests/regression_tests/surface_tally/results_true.dat b/tests/regression_tests/surface_tally/results_true.dat index cfd70a013..8b27fa192 100644 --- a/tests/regression_tests/surface_tally/results_true.dat +++ b/tests/regression_tests/surface_tally/results_true.dat @@ -1,52 +1,52 @@ mean,std. dev. -1.9600000e-02,1.5719768e-03 -7.3700000e-02,1.9382122e-03 -1.7130000e-01,4.0907755e-03 -6.3490000e-01,8.8197380e-03 -2.5000000e-03,5.2174919e-04 -6.0000000e-03,1.6799471e-03 -1.0600000e-02,1.8749815e-03 -4.0200000e-02,1.6852300e-03 -1.9600000e-02,1.5719768e-03 -7.3700000e-02,1.9382122e-03 -1.7130000e-01,4.0907755e-03 -6.3490000e-01,8.8197380e-03 -2.5000000e-03,5.2174919e-04 -6.0000000e-03,1.6799471e-03 -1.0600000e-02,1.8749815e-03 -4.0200000e-02,1.6852300e-03 -4.7000000e-03,9.1954095e-04 -4.5400000e-02,2.4413111e-03 -4.2800000e-02,2.2150997e-03 -4.2460000e-01,7.3017502e-03 +2.1200000e-02,1.8366636e-03 +7.4900000e-02,2.2083176e-03 +1.6220000e-01,2.8079253e-03 +6.4010000e-01,8.6838931e-03 +2.1000000e-03,3.7859389e-04 +5.6000000e-03,6.8637534e-04 +1.1700000e-02,1.4456832e-03 +4.1700000e-02,2.7041121e-03 +2.1200000e-02,1.8366636e-03 +7.4900000e-02,2.2083176e-03 +1.6220000e-01,2.8079253e-03 +6.4010000e-01,8.6838931e-03 +2.1000000e-03,3.7859389e-04 +5.6000000e-03,6.8637534e-04 +1.1700000e-02,1.4456832e-03 +4.1700000e-02,2.7041121e-03 +5.2000000e-03,5.9254629e-04 +3.9200000e-02,2.5508169e-03 +4.0200000e-02,1.9310331e-03 +4.1360000e-01,8.0072190e-03 0.0000000e+00,0.0000000e+00 -1.6000000e-03,2.6666667e-04 -4.0000000e-04,1.6329932e-04 -1.5700000e-02,1.1551816e-03 --4.7000000e-03,9.1954095e-04 --4.5400000e-02,2.4413111e-03 --4.2800000e-02,2.2150997e-03 --4.2460000e-01,7.3017502e-03 +1.9000000e-03,3.7859389e-04 +1.0000000e-04,1.0000000e-04 +1.6400000e-02,1.2840907e-03 +-5.2000000e-03,5.9254629e-04 +-3.9200000e-02,2.5508169e-03 +-4.0200000e-02,1.9310331e-03 +-4.1360000e-01,8.0072190e-03 0.0000000e+00,0.0000000e+00 --1.6000000e-03,2.6666667e-04 --4.0000000e-04,1.6329932e-04 --1.5700000e-02,1.1551816e-03 -1.4900000e-02,1.5235193e-03 -2.8300000e-02,2.0925795e-03 -1.2850000e-01,4.0613353e-03 -2.1030000e-01,5.4955538e-03 -2.5000000e-03,5.2174919e-04 -4.4000000e-03,1.4847372e-03 -1.0200000e-02,1.8903263e-03 -2.4500000e-02,1.7966017e-03 +-1.9000000e-03,3.7859389e-04 +-1.0000000e-04,1.0000000e-04 +-1.6400000e-02,1.2840907e-03 +1.6000000e-02,2.1602469e-03 +3.5700000e-02,2.9441090e-03 +1.2200000e-01,3.5932035e-03 +2.2650000e-01,9.2463206e-03 +2.1000000e-03,3.7859389e-04 +3.7000000e-03,8.1717671e-04 +1.1600000e-02,1.4772347e-03 +2.5300000e-02,1.9723083e-03 0.0000000e+00,0.0000000e+00 --3.0900000e-02,2.0518285e-03 +-2.9700000e-02,2.4587711e-03 0.0000000e+00,0.0000000e+00 --3.4370000e-01,4.5093730e-03 +-3.5090000e-01,3.7161808e-03 0.0000000e+00,0.0000000e+00 --2.9000000e-03,8.0897741e-04 +-2.1000000e-03,4.8189441e-04 0.0000000e+00,0.0000000e+00 --2.2200000e-02,2.0210009e-03 +-2.1400000e-02,1.7397318e-03 0.0000000e+00,0.0000000e+00 0.0000000e+00,0.0000000e+00 0.0000000e+00,0.0000000e+00 diff --git a/tests/regression_tests/survival_biasing/results_true.dat b/tests/regression_tests/survival_biasing/results_true.dat index edd968340..740272201 100644 --- a/tests/regression_tests/survival_biasing/results_true.dat +++ b/tests/regression_tests/survival_biasing/results_true.dat @@ -1,20 +1,20 @@ k-combined: -9.826269E-01 1.626276E-02 +9.879232E-01 8.097582E-03 tally 1: -4.209907E+01 -3.546281E+02 -1.759415E+01 -6.197412E+01 -2.165888E+00 -9.392975E-01 -1.873459E+00 -7.025989E-01 -4.850267E+00 -4.708899E+00 -3.397795E-02 -2.310621E-04 -3.628554E+08 -2.635633E+16 +4.295331E+01 +3.691096E+02 +1.802724E+01 +6.501934E+01 +2.193500E+00 +9.627609E-01 +1.893529E+00 +7.174104E-01 +4.902380E+00 +4.808570E+00 +3.418014E-02 +2.337353E-04 +3.667128E+08 +2.690758E+16 tally 2: -1.759415E+01 -6.197412E+01 +1.802724E+01 +6.501934E+01 diff --git a/tests/regression_tests/tallies/results_true.dat b/tests/regression_tests/tallies/results_true.dat index 6739f5348..6a58c1725 100644 --- a/tests/regression_tests/tallies/results_true.dat +++ b/tests/regression_tests/tallies/results_true.dat @@ -1 +1 @@ -ad28e723270c25dc46f27f1482052e381c802cb111ea8224368d4ea3d903eeaba1a3dce541957f24ec0634ed2ada6f20f97c0270c269b9bcae4b34a1b317a165 \ No newline at end of file +6b1d8d6f4d7a70af6c39cc76b9267a61ba9a9d0c14b75a4df6f83e72a2bfaf1533caaf936c2185f0a158443eb9da266bd5a77b7996020fd638551ea841d821e0 \ No newline at end of file diff --git a/tests/regression_tests/tally_aggregation/results_true.dat b/tests/regression_tests/tally_aggregation/results_true.dat index a86eff895..172adbfe1 100644 --- a/tests/regression_tests/tally_aggregation/results_true.dat +++ b/tests/regression_tests/tally_aggregation/results_true.dat @@ -1,97 +1,97 @@ -[[1.6100557e-05 5.2845844e-04] - [3.1178030e-01 1.6963068e-01] - [1.8103970e-02 7.1792000e-01]], [[1.6327747e-05 5.3562414e-04] - [3.2299959e-01 1.7506573e-01] - [1.8518775e-02 7.2159429e-01]], [[1.5779072e-05 5.7847880e-04] - [3.1206099e-01 1.6937953e-01] - [1.7615699e-02 6.9887963e-01]], [[1.6129040e-05 5.2214564e-04] - [3.3116549e-01 1.7924984e-01] - [1.8339236e-02 7.1809645e-01]][[2.5070599e-07 4.1541177e-05] - [8.8868371e-03 4.3482360e-03] - [4.2929455e-04 5.1166511e-03]], [[2.6348920e-07 4.0911978e-05] - [9.5560259e-03 4.6948487e-03] - [5.1500008e-04 8.2022796e-03]], [[2.8482730e-07 5.2369388e-05] - [5.9366950e-03 2.9803949e-03] - [3.5036278e-04 7.1193378e-03]], [[4.9529279e-07 5.2183723e-05] - [1.1645140e-02 5.7325245e-03] - [9.3005699e-04 9.2536054e-03]][[1.0276552e-06 8.0660598e-04] - [1.1192721e+00 5.5462743e-01] - [1.3911834e-06 5.0699881e-01]], [[1.9629638e-06 1.0409504e-03] - [1.4059305e-01 9.8087142e-02] - [2.9492646e-05 7.8705320e-01]], [[1.5107402e-05 2.2995488e-04] - [1.3135825e-02 2.9816182e-02] - [3.2964785e-04 1.1215217e+00]], [[4.6238395e-05 8.7195730e-05] - [5.0054342e-03 1.0795027e-02] - [7.2217149e-02 4.4091666e-01]][[1.6532673e-08 1.2337935e-05] - [1.8386631e-02 9.0206165e-03] - [2.1821704e-08 6.5857974e-03]], [[1.4398993e-07 9.3322326e-05] - [1.7502917e-03 1.1333022e-03] - [1.2352929e-05 1.0990819e-02]], [[2.0866393e-07 1.5849226e-06] - [1.0531329e-04 1.2841877e-04] - [5.5780807e-06 5.5626593e-03]], [[6.2783320e-07 1.1660991e-06] - [6.5703644e-05 1.4478948e-04] - [1.1987891e-03 5.8870776e-03]][[0.2726472 0.2604765]], [[0.2826295 0.2668458]], [[0.2735803 0.2601036]], [[0.2904175 0.2750069]], [[0.0346119 0.2258269]], [[0.0357798 0.2250003]], [[0.0340719 0.2185953]], [[0.0361609 0.2167588]], [[0.0033548 0.2889666]], [[0.0034114 0.2907593]], [[0.003291 0.2797162]], [[0.0034234 0.2921258]], [[0.0192865 0.1128092]], [[0.0197139 0.1145903]], [[0.0187492 0.1104225]], [[0.0195192 0.1139769]][[0.0088278 0.0052328]], [[0.0095476 0.0057391]], [[0.0058888 0.003768 ]], [[0.0115889 0.007087 ]], [[0.0010202 0.0025054]], [[0.0003997 0.00688 ]], [[0.0007498 0.0052687]], [[0.0011406 0.0063813]], [[6.0992197e-05 2.7321486e-03]], [[3.8711312e-05 2.3727208e-03]], [[5.9558150e-05 3.2498217e-03]], [[4.8541326e-05 2.7025714e-03]], [[0.00043 0.0019911]], [[0.0005155 0.001849 ]], [[0.0003513 0.0026556]], [[0.0009313 0.0044993]][[1.9753031e-04] - [4.0779730e-01] - [1.2512884e-01]], [[2.0324106e-04] - [4.2264184e-01] - [1.2663026e-01]], [[1.9762520e-04] - [4.0915145e-01] - [1.2433487e-01]], [[2.0923706e-04] - [4.3430891e-01] - [1.3090624e-01]], [[0.0002534] - [0.0589558] - [0.2012296]], [[0.0002515] - [0.0604991] - [0.2000296]], [[0.0003047] - [0.0579695] - [0.1943931]], [[0.0002334] - [0.0612558] - [0.1914305]], [[6.0316499e-05] - [1.0710899e-02] - [2.8155013e-01]], [[6.3374666e-05] - [1.0915514e-02] - [2.8319179e-01]], [[5.9392082e-05] - [1.0461186e-02] - [2.7248670e-01]], [[6.1979034e-05] - [1.0864408e-02] - [2.8462272e-01]], [[3.3331895e-05] - [3.9469598e-03] - [1.2811544e-01]], [[3.3851214e-05] - [4.0088932e-03] - [1.3026145e-01]], [[3.2587500e-05] - [3.8583992e-03] - [1.2528067e-01]], [[3.3663516e-05] - [3.9862087e-03] - [1.2947625e-01]][[5.9589021e-06] - [9.8268994e-03] - [2.9572748e-03]], [[6.3833088e-06] - [1.0635294e-02] - [3.3142463e-03]], [[4.0655901e-06] - [6.5668548e-03] - [2.3984140e-03]], [[7.7097818e-06] - [1.2908862e-02] - [4.2297322e-03]], [[4.1105542e-05] - [1.1418202e-03] - [2.4520182e-03]], [[4.0406959e-05] - [4.9407982e-04] - [6.8737413e-03]], [[5.2191221e-05] - [9.9374825e-04] - [5.2279051e-03]], [[5.1601995e-05] - [1.3462879e-03] - [6.3408638e-03]], [[5.9462092e-07] - [9.1472877e-05] - [2.7312979e-03]], [[4.5487504e-07] - [5.5343645e-05] - [2.3723911e-03]], [[1.3568221e-06] - [1.0496033e-04] - [3.2486719e-03]], [[3.9251575e-07] - [7.1661652e-05] - [2.7020572e-03]], [[4.5230086e-07] - [5.4399064e-05] - [2.0363096e-03]], [[4.2836596e-07] - [5.0791493e-05] - [1.9188091e-03]], [[5.8337236e-07] - [7.0477126e-05] - [2.6777741e-03]], [[1.0127017e-06] - [1.2155206e-04] - [4.5930293e-03]] \ No newline at end of file +[[1.6001087e-05 5.4190949e-04] + [3.2669968e-01 1.7730523e-01] + [1.8149266e-02 7.1525113e-01]], [[1.6239097e-05 5.7499676e-04] + [3.1268633e-01 1.7004165e-01] + [1.8873778e-02 7.0217885e-01]], [[1.6693071e-05 5.4106379e-04] + [3.3370208e-01 1.8051505e-01] + [1.9081306e-02 7.3647547e-01]], [[1.6725399e-05 5.1680146e-04] + [3.2854628e-01 1.7757185e-01] + [1.9529646e-02 7.1005198e-01]][[2.4751834e-07 4.3304565e-05] + [8.6840718e-03 4.3442535e-03] + [3.7054051e-04 6.5678133e-03]], [[4.0830852e-07 4.9612204e-05] + [1.2104241e-02 5.9708675e-03] + [7.1398189e-04 8.2408482e-03]], [[2.6546344e-07 2.5234256e-05] + [6.5083211e-03 3.2185071e-03] + [4.2935150e-04 5.1707774e-03]], [[2.7845203e-07 3.4453402e-05] + [3.3125427e-03 1.7749508e-03] + [6.0407731e-04 7.5353872e-03]][[1.0455251e-06 8.1938339e-04] + [1.1392765e+00 5.6434761e-01] + [1.4142831e-06 5.1213654e-01]], [[2.2009815e-06 1.0418935e-03] + [1.4422554e-01 1.0070647e-01] + [3.9488382e-05 7.9236390e-01]], [[1.4606612e-05 2.2374470e-04] + [1.2962842e-02 2.9268594e-02] + [3.1339824e-04 1.1056439e+00]], [[4.7805535e-05 8.9749934e-05] + [5.1694597e-03 1.1111105e-02] + [7.5279695e-02 4.5381305e-01]][[1.4955183e-08 1.1461548e-05] + [1.6454649e-02 8.1236707e-03] + [2.0028007e-08 6.8264819e-03]], [[1.6334486e-07 7.7617340e-05] + [2.1161584e-03 1.4078445e-03] + [1.4742097e-05 6.9350862e-03]], [[1.7444757e-07 1.9026095e-06] + [1.4084092e-04 2.0345990e-04] + [5.9546175e-06 8.6038812e-03]], [[5.6449127e-07 1.0110585e-06] + [5.9158873e-05 1.2485325e-04] + [1.0936497e-03 5.0836702e-03]][[0.2866239 0.2725595]], [[0.2729156 0.258831 ]], [[0.2920724 0.2755922]], [[0.287667 0.2703207]], [[0.035617 0.2232707]], [[0.0353082 0.2224423]], [[0.0370072 0.2288263]], [[0.0363348 0.219573 ]], [[0.0033013 0.2850034]], [[0.0032726 0.2771099]], [[0.0034234 0.2951295]], [[0.0032935 0.2778935]], [[0.0193227 0.1122647]], [[0.0200799 0.1144123]], [[0.0202971 0.1179836]], [[0.0207973 0.1203534]][[0.0086351 0.0061876]], [[0.0120688 0.0074831]], [[0.0064221 0.0035246]], [[0.0030483 0.0024267]], [[0.0009185 0.0033896]], [[0.0009223 0.0039584]], [[0.0010541 0.0038599]], [[0.0012934 0.0028331]], [[6.5126963e-05 2.8486593e-03]], [[7.1110242e-05 4.3424340e-03]], [[5.8911409e-05 2.4296178e-03]], [[8.4278765e-05 6.4182190e-03]], [[0.0003712 0.0020298]], [[0.0007152 0.0036115]], [[0.0004298 0.0019677]], [[0.0006046 0.0021965]][[2.0694650e-04] + [4.2868191e-01] + [1.3029457e-01]], [[1.9694048e-04] + [4.0809445e-01] + [1.2345525e-01]], [[2.1012645e-04] + [4.3670571e-01] + [1.3074883e-01]], [[2.0641548e-04] + [4.3014207e-01] + [1.2763930e-01]], [[0.0002584] + [0.0608867] + [0.1977426]], [[0.0003026] + [0.0602368] + [0.1972111]], [[0.0002509] + [0.0624699] + [0.2031126]], [[0.0002322] + [0.0613385] + [0.1943371]], [[5.9349736e-05] + [1.0506741e-02] + [2.7773865e-01]], [[5.7855564e-05] + [1.0389781e-02] + [2.6993483e-01]], [[6.1819700e-05] + [1.0910874e-02] + [2.8758020e-01]], [[5.9326317e-05] + [1.0424040e-02] + [2.7070367e-01]], [[3.3192167e-05] + [3.9295320e-03] + [1.2762462e-01]], [[3.3882691e-05] + [4.0069157e-03] + [1.3045143e-01]], [[3.4882103e-05] + [4.1306182e-03] + [1.3411514e-01]], [[3.5598508e-05] + [4.2134987e-03] + [1.3690156e-01]][[6.4505980e-06] + [9.6369034e-03] + [4.4700460e-03]], [[8.2880772e-06] + [1.3456171e-02] + [4.5368708e-03]], [[3.9384462e-06] + [7.1570638e-03] + [1.5629142e-03]], [[2.3565894e-06] + [3.4040401e-03] + [1.8956916e-03]], [[4.2806047e-05] + [1.1841015e-03] + [3.3058802e-03]], [[4.8905696e-05] + [1.0360139e-03] + [3.9298937e-03]], [[2.4911390e-05] + [1.2173305e-03] + [3.8114473e-03]], [[3.4347869e-05] + [1.5820360e-03] + [2.6824612e-03]], [[1.0809230e-06] + [1.0316180e-04] + [2.8475354e-03]], [[6.4150814e-07] + [1.1179425e-04] + [4.3415770e-03]], [[7.3848139e-07] + [9.3111666e-05] + [2.4285475e-03]], [[1.2349384e-06] + [1.7152843e-04] + [6.4164799e-03]], [[4.5871493e-07] + [5.4732075e-05] + [2.0627309e-03]], [[8.1649994e-07] + [9.7699188e-05] + [3.6803256e-03]], [[4.5174850e-07] + [5.3913784e-05] + [2.0133571e-03]], [[5.0962865e-07] + [6.0338032e-05] + [2.2773911e-03]] \ No newline at end of file diff --git a/tests/regression_tests/tally_arithmetic/results_true.dat b/tests/regression_tests/tally_arithmetic/results_true.dat index 473dd5ee7..143930dd4 100644 --- a/tests/regression_tests/tally_arithmetic/results_true.dat +++ b/tests/regression_tests/tally_arithmetic/results_true.dat @@ -1,49 +1,49 @@ -[2.18485e-07 1.40714e-13 1.90835e-04 1.22906e-10 2.14194e-07 1.70920e-07 - 1.87087e-04 1.49289e-04 5.77324e-03 3.71823e-09 2.98131e-03 1.92010e-09 - 5.65986e-03 4.51638e-03 2.92276e-03 2.33227e-03 1.77087e-07 1.04308e-13 - 1.54676e-04 9.11076e-11 1.53337e-07 1.20737e-07 1.33931e-04 1.05457e-04 - 4.67935e-03 2.75624e-09 2.41642e-03 1.42333e-09 4.05176e-03 3.19035e-03 - 2.09234e-03 1.64750e-03 2.32566e-07 1.53743e-13 2.03133e-04 1.34286e-10 - 2.42559e-07 1.94114e-07 2.11862e-04 1.69548e-04 6.14530e-03 4.06249e-09 - 3.17345e-03 2.09788e-09 6.40937e-03 5.12926e-03 3.30981e-03 2.64876e-03 - 2.15237e-07 1.23240e-13 1.87998e-04 1.07643e-10 1.85758e-07 1.46699e-07 - 1.62249e-04 1.28134e-04 5.68742e-03 3.25649e-09 2.93699e-03 1.68166e-09 - 4.90845e-03 3.87638e-03 2.53473e-03 2.00177e-03 2.47477e-03 4.87068e-05 - 1.06189e-02 2.08993e-04 1.26298e-04 3.02426e-05 5.41924e-04 1.29766e-04 - 2.77770e-02 5.46688e-04 4.83214e-02 9.51031e-04 1.41757e-03 3.39445e-04 - 2.46604e-03 5.90506e-04 2.31220e-03 4.16752e-05 9.92129e-03 1.78822e-04 - 1.15514e-04 2.68262e-05 4.95652e-04 1.15107e-04 2.59523e-02 4.67766e-04 - 4.51471e-02 8.13735e-04 1.29654e-03 3.01100e-04 2.25548e-03 5.23800e-04 - 2.30792e-03 4.67592e-05 9.90296e-03 2.00637e-04 1.15169e-04 2.57221e-05 - 4.94175e-04 1.10370e-04 2.59043e-02 5.24828e-04 4.50637e-02 9.13003e-04 - 1.29267e-03 2.88707e-04 2.24876e-03 5.02241e-04 2.35337e-03 4.59723e-05 - 1.00979e-02 1.97260e-04 1.17182e-04 2.59928e-05 5.02809e-04 1.11531e-04 - 2.64144e-02 5.15997e-04 4.59510e-02 8.97639e-04 1.31526e-03 2.91745e-04 - 2.28805e-03 5.07527e-04][2.18485e-07 1.40714e-13 1.90835e-04 1.22906e-10 2.14194e-07 1.70920e-07 - 1.87087e-04 1.49289e-04 5.77324e-03 3.71823e-09 2.98131e-03 1.92010e-09 - 5.65986e-03 4.51638e-03 2.92276e-03 2.33227e-03 1.77087e-07 1.04308e-13 - 1.54676e-04 9.11076e-11 1.53337e-07 1.20737e-07 1.33931e-04 1.05457e-04 - 4.67935e-03 2.75624e-09 2.41642e-03 1.42333e-09 4.05176e-03 3.19035e-03 - 2.09234e-03 1.64750e-03 2.32566e-07 1.53743e-13 2.03133e-04 1.34286e-10 - 2.42559e-07 1.94114e-07 2.11862e-04 1.69548e-04 6.14530e-03 4.06249e-09 - 3.17345e-03 2.09788e-09 6.40937e-03 5.12926e-03 3.30981e-03 2.64876e-03 - 2.15237e-07 1.23240e-13 1.87998e-04 1.07643e-10 1.85758e-07 1.46699e-07 - 1.62249e-04 1.28134e-04 5.68742e-03 3.25649e-09 2.93699e-03 1.68166e-09 - 4.90845e-03 3.87638e-03 2.53473e-03 2.00177e-03 2.47477e-03 4.87068e-05 - 1.06189e-02 2.08993e-04 1.26298e-04 3.02426e-05 5.41924e-04 1.29766e-04 - 2.77770e-02 5.46688e-04 4.83214e-02 9.51031e-04 1.41757e-03 3.39445e-04 - 2.46604e-03 5.90506e-04 2.31220e-03 4.16752e-05 9.92129e-03 1.78822e-04 - 1.15514e-04 2.68262e-05 4.95652e-04 1.15107e-04 2.59523e-02 4.67766e-04 - 4.51471e-02 8.13735e-04 1.29654e-03 3.01100e-04 2.25548e-03 5.23800e-04 - 2.30792e-03 4.67592e-05 9.90296e-03 2.00637e-04 1.15169e-04 2.57221e-05 - 4.94175e-04 1.10370e-04 2.59043e-02 5.24828e-04 4.50637e-02 9.13003e-04 - 1.29267e-03 2.88707e-04 2.24876e-03 5.02241e-04 2.35337e-03 4.59723e-05 - 1.00979e-02 1.97260e-04 1.17182e-04 2.59928e-05 5.02809e-04 1.11531e-04 - 2.64144e-02 5.15997e-04 4.59510e-02 8.97639e-04 1.31526e-03 2.91745e-04 - 2.28805e-03 5.07527e-04][0.00566 0.00452 0.00292 0.00233 0.00405 0.00319 0.00209 0.00165 0.00641 - 0.00513 0.00331 0.00265 0.00491 0.00388 0.00253 0.002 0.00142 0.00034 - 0.00247 0.00059 0.0013 0.0003 0.00226 0.00052 0.00129 0.00029 0.00225 - 0.0005 0.00132 0.00029 0.00229 0.00051][0.00019 0.00019 0.00298 0.00292 0.00015 0.00013 0.00242 0.00209 0.0002 - 0.00021 0.00317 0.00331 0.00019 0.00016 0.00294 0.00253 0.01062 0.00054 - 0.04832 0.00247 0.00992 0.0005 0.04515 0.00226 0.0099 0.00049 0.04506 - 0.00225 0.0101 0.0005 0.04595 0.00229][0.00292 0.00209 0.00331 0.00253 0.00247 0.00226 0.00225 0.00229] \ No newline at end of file +[2.04229e-07 1.28343e-13 1.79333e-04 1.12698e-10 1.89952e-07 1.51210e-07 + 1.66796e-04 1.32777e-04 6.13215e-03 3.85362e-09 3.14746e-03 1.97795e-09 + 5.70345e-03 4.54021e-03 2.92742e-03 2.33037e-03 2.10575e-07 1.28419e-13 + 1.84905e-04 1.12764e-10 1.89188e-07 1.50221e-07 1.66125e-04 1.31908e-04 + 6.32269e-03 3.85587e-09 3.24526e-03 1.97911e-09 5.68054e-03 4.51051e-03 + 2.91566e-03 2.31512e-03 1.96696e-07 1.26388e-13 1.72718e-04 1.10981e-10 + 1.91283e-07 1.53449e-07 1.67964e-04 1.34743e-04 5.90596e-03 3.79491e-09 + 3.03136e-03 1.94782e-09 5.74342e-03 4.60742e-03 2.94794e-03 2.36486e-03 + 2.06016e-07 1.35264e-13 1.80901e-04 1.18775e-10 2.05873e-07 1.65814e-07 + 1.80776e-04 1.45600e-04 6.18579e-03 4.06142e-09 3.17499e-03 2.08461e-09 + 6.18150e-03 4.97869e-03 3.17279e-03 2.55542e-03 2.36089e-03 4.46651e-05 + 1.02263e-02 1.93469e-04 1.18179e-04 2.62375e-05 5.11897e-04 1.13649e-04 + 2.56040e-02 4.84394e-04 4.55595e-02 8.61927e-04 1.28165e-03 2.84546e-04 + 2.28056e-03 5.06320e-04 2.29877e-03 4.53056e-05 9.95724e-03 1.96244e-04 + 1.14803e-04 2.57898e-05 4.97276e-04 1.11710e-04 2.49302e-02 4.91340e-04 + 4.43606e-02 8.74289e-04 1.24504e-03 2.79691e-04 2.21542e-03 4.97680e-04 + 2.31940e-03 4.34238e-05 1.00466e-02 1.88093e-04 1.17620e-04 2.69280e-05 + 5.09479e-04 1.16640e-04 2.51540e-02 4.70932e-04 4.47588e-02 8.37974e-04 + 1.27560e-03 2.92034e-04 2.26979e-03 5.19644e-04 2.19212e-03 4.53914e-05 + 9.49530e-03 1.96615e-04 1.09609e-04 2.41615e-05 4.74778e-04 1.04657e-04 + 2.37736e-02 4.92271e-04 4.23026e-02 8.75944e-04 1.18871e-03 2.62032e-04 + 2.11519e-03 4.66257e-04][2.04229e-07 1.28343e-13 1.79333e-04 1.12698e-10 1.89952e-07 1.51210e-07 + 1.66796e-04 1.32777e-04 6.13215e-03 3.85362e-09 3.14746e-03 1.97795e-09 + 5.70345e-03 4.54021e-03 2.92742e-03 2.33037e-03 2.10575e-07 1.28419e-13 + 1.84905e-04 1.12764e-10 1.89188e-07 1.50221e-07 1.66125e-04 1.31908e-04 + 6.32269e-03 3.85587e-09 3.24526e-03 1.97911e-09 5.68054e-03 4.51051e-03 + 2.91566e-03 2.31512e-03 1.96696e-07 1.26388e-13 1.72718e-04 1.10981e-10 + 1.91283e-07 1.53449e-07 1.67964e-04 1.34743e-04 5.90596e-03 3.79491e-09 + 3.03136e-03 1.94782e-09 5.74342e-03 4.60742e-03 2.94794e-03 2.36486e-03 + 2.06016e-07 1.35264e-13 1.80901e-04 1.18775e-10 2.05873e-07 1.65814e-07 + 1.80776e-04 1.45600e-04 6.18579e-03 4.06142e-09 3.17499e-03 2.08461e-09 + 6.18150e-03 4.97869e-03 3.17279e-03 2.55542e-03 2.36089e-03 4.46651e-05 + 1.02263e-02 1.93469e-04 1.18179e-04 2.62375e-05 5.11897e-04 1.13649e-04 + 2.56040e-02 4.84394e-04 4.55595e-02 8.61927e-04 1.28165e-03 2.84546e-04 + 2.28056e-03 5.06320e-04 2.29877e-03 4.53056e-05 9.95724e-03 1.96244e-04 + 1.14803e-04 2.57898e-05 4.97276e-04 1.11710e-04 2.49302e-02 4.91340e-04 + 4.43606e-02 8.74289e-04 1.24504e-03 2.79691e-04 2.21542e-03 4.97680e-04 + 2.31940e-03 4.34238e-05 1.00466e-02 1.88093e-04 1.17620e-04 2.69280e-05 + 5.09479e-04 1.16640e-04 2.51540e-02 4.70932e-04 4.47588e-02 8.37974e-04 + 1.27560e-03 2.92034e-04 2.26979e-03 5.19644e-04 2.19212e-03 4.53914e-05 + 9.49530e-03 1.96615e-04 1.09609e-04 2.41615e-05 4.74778e-04 1.04657e-04 + 2.37736e-02 4.92271e-04 4.23026e-02 8.75944e-04 1.18871e-03 2.62032e-04 + 2.11519e-03 4.66257e-04][0.0057 0.00454 0.00293 0.00233 0.00568 0.00451 0.00292 0.00232 0.00574 + 0.00461 0.00295 0.00236 0.00618 0.00498 0.00317 0.00256 0.00128 0.00028 + 0.00228 0.00051 0.00125 0.00028 0.00222 0.0005 0.00128 0.00029 0.00227 + 0.00052 0.00119 0.00026 0.00212 0.00047][0.00018 0.00017 0.00315 0.00293 0.00018 0.00017 0.00325 0.00292 0.00017 + 0.00017 0.00303 0.00295 0.00018 0.00018 0.00317 0.00317 0.01023 0.00051 + 0.04556 0.00228 0.00996 0.0005 0.04436 0.00222 0.01005 0.00051 0.04476 + 0.00227 0.0095 0.00047 0.0423 0.00212][0.00293 0.00292 0.00295 0.00317 0.00228 0.00222 0.00227 0.00212] \ No newline at end of file diff --git a/tests/regression_tests/tally_assumesep/results_true.dat b/tests/regression_tests/tally_assumesep/results_true.dat index 5728cfc04..9d7cbf9c3 100644 --- a/tests/regression_tests/tally_assumesep/results_true.dat +++ b/tests/regression_tests/tally_assumesep/results_true.dat @@ -1,11 +1,11 @@ k-combined: -6.353587E-01 1.925016E-02 +5.683578E-01 1.129170E-02 tally 1: -7.878503E+00 -1.242768E+01 +6.753950E+00 +9.188305E+00 tally 2: -2.687214E-01 -1.487262E-02 +2.278558E-01 +1.052944E-02 tally 3: -1.344654E+01 -3.630145E+01 +1.179091E+01 +2.795539E+01 diff --git a/tests/regression_tests/tally_nuclides/results_true.dat b/tests/regression_tests/tally_nuclides/results_true.dat index ad385b82a..7f9641fc8 100644 --- a/tests/regression_tests/tally_nuclides/results_true.dat +++ b/tests/regression_tests/tally_nuclides/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.655280E-01 1.463557E-02 +1.132463E+00 5.721067E-02 tally 1: -6.932814E+00 -9.650528E+00 -1.591338E+00 -5.075076E-01 -1.541515E+00 -4.761914E-01 -5.341475E+00 -5.732892E+00 -6.932814E+00 -9.650528E+00 -1.591338E+00 -5.075076E-01 -1.541515E+00 -4.761914E-01 -5.341475E+00 -5.732892E+00 +7.310528E+00 +1.080411E+01 +1.664215E+00 +5.567756E-01 +1.609340E+00 +5.205634E-01 +5.646313E+00 +6.459724E+00 +7.310528E+00 +1.080411E+01 +1.664215E+00 +5.567756E-01 +1.609340E+00 +5.205634E-01 +5.646313E+00 +6.459724E+00 tally 2: -6.932814E+00 -9.650528E+00 -1.591338E+00 -5.075076E-01 -1.541515E+00 -4.761914E-01 -5.341475E+00 -5.732892E+00 +7.310528E+00 +1.080411E+01 +1.664215E+00 +5.567756E-01 +1.609340E+00 +5.205634E-01 +5.646313E+00 +6.459724E+00 diff --git a/tests/regression_tests/tally_slice_merge/results_true.dat b/tests/regression_tests/tally_slice_merge/results_true.dat index 84b296d64..58b15fc18 100644 --- a/tests/regression_tests/tally_slice_merge/results_true.dat +++ b/tests/regression_tests/tally_slice_merge/results_true.dat @@ -1,45 +1,45 @@ cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 fission 1.77e-01 1.81e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 nu-fission 4.32e-01 4.42e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U238 fission 2.43e-07 2.40e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U238 nu-fission 6.07e-07 5.97e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U235 fission 3.03e-02 1.93e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U235 nu-fission 7.41e-02 4.67e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U238 fission 1.65e-02 1.61e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U238 nu-fission 4.61e-02 4.87e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U235 fission 1.31e-01 2.54e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U235 nu-fission 3.18e-01 6.19e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U238 fission 1.80e-07 3.46e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U238 nu-fission 4.49e-07 8.62e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U235 fission 2.34e-02 1.23e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U235 nu-fission 5.72e-02 2.99e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U238 fission 1.24e-02 9.35e-04 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U238 nu-fission 3.44e-02 2.73e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 fission 1.77e-01 1.81e-02 -1 21 0.00e+00 6.25e-01 U235 nu-fission 4.32e-01 4.42e-02 -2 21 0.00e+00 6.25e-01 U238 fission 2.43e-07 2.40e-08 -3 21 0.00e+00 6.25e-01 U238 nu-fission 6.07e-07 5.97e-08 -4 21 6.25e-01 2.00e+07 U235 fission 3.03e-02 1.93e-03 -5 21 6.25e-01 2.00e+07 U235 nu-fission 7.41e-02 4.67e-03 -6 21 6.25e-01 2.00e+07 U238 fission 1.65e-02 1.61e-03 -7 21 6.25e-01 2.00e+07 U238 nu-fission 4.61e-02 4.87e-03 -8 27 0.00e+00 6.25e-01 U235 fission 1.31e-01 2.54e-02 -9 27 0.00e+00 6.25e-01 U235 nu-fission 3.18e-01 6.19e-02 -10 27 0.00e+00 6.25e-01 U238 fission 1.80e-07 3.46e-08 -11 27 0.00e+00 6.25e-01 U238 nu-fission 4.49e-07 8.62e-08 -12 27 6.25e-01 2.00e+07 U235 fission 2.34e-02 1.23e-03 -13 27 6.25e-01 2.00e+07 U235 nu-fission 5.72e-02 2.99e-03 -14 27 6.25e-01 2.00e+07 U238 fission 1.24e-02 9.35e-04 -15 27 6.25e-01 2.00e+07 U238 nu-fission 3.44e-02 2.73e-03 +0 21 0.00e+00 6.25e-01 U235 fission 1.75e-01 1.20e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U235 nu-fission 4.26e-01 2.92e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U238 fission 2.41e-07 1.61e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U238 nu-fission 6.00e-07 4.01e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U235 fission 2.89e-02 2.07e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U235 nu-fission 7.07e-02 5.06e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U238 fission 1.41e-02 5.76e-04 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U238 nu-fission 3.95e-02 1.90e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U235 fission 1.51e-01 1.17e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U235 nu-fission 3.69e-01 2.86e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U238 fission 2.07e-07 1.47e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U238 nu-fission 5.17e-07 3.66e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U235 fission 2.57e-02 2.43e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U235 nu-fission 6.30e-02 5.92e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U238 fission 1.47e-02 1.41e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U238 nu-fission 4.12e-02 4.02e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U235 fission 1.75e-01 1.20e-02 +1 21 0.00e+00 6.25e-01 U235 nu-fission 4.26e-01 2.92e-02 +2 21 0.00e+00 6.25e-01 U238 fission 2.41e-07 1.61e-08 +3 21 0.00e+00 6.25e-01 U238 nu-fission 6.00e-07 4.01e-08 +4 21 6.25e-01 2.00e+07 U235 fission 2.89e-02 2.07e-03 +5 21 6.25e-01 2.00e+07 U235 nu-fission 7.07e-02 5.06e-03 +6 21 6.25e-01 2.00e+07 U238 fission 1.41e-02 5.76e-04 +7 21 6.25e-01 2.00e+07 U238 nu-fission 3.95e-02 1.90e-03 +8 27 0.00e+00 6.25e-01 U235 fission 1.51e-01 1.17e-02 +9 27 0.00e+00 6.25e-01 U235 nu-fission 3.69e-01 2.86e-02 +10 27 0.00e+00 6.25e-01 U238 fission 2.07e-07 1.47e-08 +11 27 0.00e+00 6.25e-01 U238 nu-fission 5.17e-07 3.66e-08 +12 27 6.25e-01 2.00e+07 U235 fission 2.57e-02 2.43e-03 +13 27 6.25e-01 2.00e+07 U235 nu-fission 6.30e-02 5.92e-03 +14 27 6.25e-01 2.00e+07 U238 fission 1.47e-02 1.41e-03 +15 27 6.25e-01 2.00e+07 U238 nu-fission 4.12e-02 4.02e-03 sum(distribcell) energy low [eV] energy high [eV] nuclide score mean std. dev. 0 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 1 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 2 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 3 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U238 nu-fission 0.00e+00 0.00e+00 -4 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 fission 0.00e+00 0.00e+00 -5 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 nu-fission 0.00e+00 0.00e+00 -6 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 fission 0.00e+00 0.00e+00 -7 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 nu-fission 0.00e+00 0.00e+00 +4 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 fission 9.53e-07 9.53e-07 +5 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 nu-fission 2.37e-06 2.37e-06 +6 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 fission 1.25e-08 1.25e-08 +7 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 nu-fission 3.15e-08 3.15e-08 8 (500, 5000, 50000) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 9 (500, 5000, 50000) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 10 (500, 5000, 50000) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 @@ -49,19 +49,19 @@ 14 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 fission 0.00e+00 0.00e+00 15 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 nu-fission 0.00e+00 0.00e+00 sum(mesh) energy low [eV] energy high [eV] nuclide score mean std. dev. -0 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 fission 2.75e-02 4.32e-03 -1 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 nu-fission 6.71e-02 1.05e-02 -2 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 fission 3.78e-08 5.83e-09 -3 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 nu-fission 9.42e-08 1.45e-08 -4 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 fission 3.96e-03 7.84e-04 -5 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 nu-fission 9.71e-03 1.91e-03 -6 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 fission 3.92e-03 8.53e-04 -7 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 nu-fission 1.08e-02 2.25e-03 -8 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 fission 5.42e-02 2.50e-02 -9 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 nu-fission 1.32e-01 6.10e-02 -10 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 fission 7.47e-08 3.42e-08 -11 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 nu-fission 1.86e-07 8.53e-08 -12 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 fission 6.58e-03 2.03e-03 -13 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 nu-fission 1.61e-02 4.95e-03 -14 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 fission 3.74e-03 1.12e-03 -15 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 nu-fission 1.05e-02 3.20e-03 +0 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 fission 6.73e-03 3.04e-03 +1 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 nu-fission 1.64e-02 7.40e-03 +2 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 fission 8.80e-09 3.84e-09 +3 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 nu-fission 2.19e-08 9.56e-09 +4 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 fission 9.89e-04 3.53e-04 +5 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 nu-fission 2.42e-03 8.60e-04 +6 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 fission 5.01e-04 2.13e-04 +7 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 nu-fission 1.36e-03 5.86e-04 +8 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 fission 1.63e-02 4.21e-03 +9 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 nu-fission 3.98e-02 1.02e-02 +10 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 fission 2.28e-08 5.90e-09 +11 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 nu-fission 5.67e-08 1.47e-08 +12 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 fission 1.79e-03 4.31e-04 +13 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 nu-fission 4.37e-03 1.05e-03 +14 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 fission 7.51e-04 2.51e-04 +15 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 nu-fission 2.02e-03 6.71e-04 diff --git a/tests/regression_tests/torus/results_true.dat b/tests/regression_tests/torus/results_true.dat index 42444ad09..42fb209cc 100644 --- a/tests/regression_tests/torus/results_true.dat +++ b/tests/regression_tests/torus/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.628424E-01 2.557300E-02 +7.667201E-01 1.136882E-02 diff --git a/tests/regression_tests/trace/results_true.dat b/tests/regression_tests/trace/results_true.dat index fe46748c8..bbf03de94 100644 --- a/tests/regression_tests/trace/results_true.dat +++ b/tests/regression_tests/trace/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.987050E-01 1.827430E-03 +3.070134E-01 3.900396E-03 diff --git a/tests/regression_tests/track_output/results_true.dat b/tests/regression_tests/track_output/results_true.dat index 756226d10..37f4a0f98 100644 --- a/tests/regression_tests/track_output/results_true.dat +++ b/tests/regression_tests/track_output/results_true.dat @@ -143,124 +143,76 @@ ParticleType.NEUTRON [((-9.469716e-01, -2.580266e-01, 1.414357e-01), (1.438873e- ((-3.920090e+00, -9.211794e-01, 2.908406e+00), (9.094673e-01, -3.659267e-01, -1.974002e-01), 9.547085e+00, 1.260840e-07, 1.000000e+00, 23, 2387, 1) ((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 2387, 1) ((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 2387, 1)] -ParticleType.NEUTRON [((6.474155e+00, -5.192870e+00, 5.413003e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2367, 2) - ((6.467293e+00, -5.416535e+00, 5.441544e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450870e-05, 1.000000e+00, 22, 2367, 3) - ((6.464574e+00, -5.505149e+00, 5.452851e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450874e-05, 1.000000e+00, 23, 2367, 1) - ((6.461877e+00, -5.593034e+00, 5.464065e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450879e-05, 1.000000e+00, 23, 2367, 1) - ((6.570892e+00, -5.725160e+00, 5.464970e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450891e-05, 1.000000e+00, 32, 7, 1) - ((6.821003e+00, -6.028296e+00, 5.467047e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450917e-05, 1.000000e+00, 31, 7, 4) - ((7.101210e+00, -6.367908e+00, 5.469374e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450947e-05, 1.000000e+00, 32, 7, 1) - ((7.360920e+00, -6.682677e+00, 5.471531e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450975e-05, 1.000000e+00, 23, 2353, 1) - ((7.833926e+00, -7.255962e+00, 5.475459e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451025e-05, 1.000000e+00, 23, 2353, 1) - ((8.142528e+00, -7.144944e+00, 5.464309e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451091e-05, 1.000000e+00, 22, 2353, 3) - ((8.590199e+00, -6.983897e+00, 5.448136e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451187e-05, 1.000000e+00, 23, 2353, 1) - ((8.682515e+00, -6.950687e+00, 5.444801e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451207e-05, 1.000000e+00, 23, 2353, 1) - ((8.996680e+00, -6.629985e+00, 5.450966e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451307e-05, 1.000000e+00, 23, 2354, 1) - ((9.231138e+00, -6.390649e+00, 5.455567e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451382e-05, 1.000000e+00, 22, 2354, 3) - ((9.650189e+00, -5.962879e+00, 5.463790e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451516e-05, 1.000000e+00, 23, 2354, 1) - ((9.721007e+00, -5.890588e+00, 5.465180e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451539e-05, 1.000000e+00, 23, 2354, 1) - ((9.939012e+00, -5.953026e+00, 5.222655e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451775e-05, 1.000000e+00, 22, 2354, 3) - ((1.002133e+01, -5.976602e+00, 5.131083e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451864e-05, 1.000000e+00, 23, 2354, 1) - ((1.020258e+01, -6.028514e+00, 4.929446e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452060e-05, 1.000000e+00, 23, 2354, 1) - ((1.063244e+01, -6.047973e+00, 4.703991e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452432e-05, 1.000000e+00, 23, 2355, 1) - ((1.084241e+01, -6.057477e+00, 4.593868e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452614e-05, 1.000000e+00, 23, 2355, 1) - ((1.107130e+01, -6.074053e+00, 4.699070e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452930e-05, 1.000000e+00, 22, 2355, 3) - ((1.121611e+01, -6.084540e+00, 4.765623e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453130e-05, 1.000000e+00, 21, 2355, 2) - ((1.174815e+01, -6.123069e+00, 5.010155e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453866e-05, 1.000000e+00, 22, 2355, 3) - ((1.189296e+01, -6.133556e+00, 5.076709e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.454067e-05, 1.000000e+00, 23, 2355, 1) - ((1.221698e+01, -6.157021e+00, 5.225634e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454515e-05, 1.000000e+00, 23, 2355, 1) - ((1.226820e+01, -6.225607e+00, 5.179351e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454893e-05, 1.000000e+00, 23, 2519, 1) - ((1.230378e+01, -6.273253e+00, 5.147199e+00), (9.203567e-01, -2.667811e-01, -2.859569e-01), 2.269067e+02, 4.455157e-05, 1.000000e+00, 23, 2519, 1) - ((1.237909e+01, -6.295083e+00, 5.123800e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.455549e-05, 1.000000e+00, 23, 2519, 1) - ((1.250758e+01, -6.372926e+00, 5.147974e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456396e-05, 1.000000e+00, 22, 2519, 3) - ((1.258603e+01, -6.420455e+00, 5.162734e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456914e-05, 1.000000e+00, 21, 2519, 2) - ((1.264082e+01, -6.453648e+00, 5.173042e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.457275e-05, 1.000000e+00, 21, 2519, 2) - ((1.288240e+01, -7.015898e+00, 5.025449e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.460837e-05, 1.000000e+00, 22, 2519, 3) - ((1.292943e+01, -7.125332e+00, 4.996722e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.461530e-05, 1.000000e+00, 23, 2519, 1) - ((1.303065e+01, -7.360920e+00, 4.934879e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.463022e-05, 1.000000e+00, 23, 2520, 1) - ((1.309295e+01, -7.505897e+00, 4.896822e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.463941e-05, 1.000000e+00, 23, 2520, 1) - ((1.311741e+01, -7.576618e+00, 4.913644e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.464426e-05, 1.000000e+00, 22, 2520, 3) - ((1.314895e+01, -7.667795e+00, 4.935331e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.465052e-05, 1.000000e+00, 21, 2520, 2) - ((1.345125e+01, -8.541749e+00, 5.143210e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471053e-05, 1.000000e+00, 22, 2520, 3) - ((1.348278e+01, -8.632925e+00, 5.164897e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471679e-05, 1.000000e+00, 23, 2520, 1) - ((1.356121e+01, -8.859646e+00, 5.218825e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.473236e-05, 1.000000e+00, 23, 2520, 1) - ((1.361604e+01, -8.996680e+00, 5.275368e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.474248e-05, 1.000000e+00, 23, 2521, 1) - ((1.390396e+01, -9.716172e+00, 5.572247e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.479558e-05, 1.000000e+00, 23, 2536, 1) - ((1.399742e+01, -9.949713e+00, 5.668611e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.481282e-05, 1.000000e+00, 23, 2536, 1) - ((1.390396e+01, -1.004824e+01, 5.750282e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.483180e-05, 1.000000e+00, 23, 2521, 1) - ((1.334984e+01, -1.063244e+01, 6.234531e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.494435e-05, 1.000000e+00, 23, 2522, 1) - ((1.317711e+01, -1.081455e+01, 6.385480e+00), (-4.211158e-01, -4.515418e-01, 7.866203e-01), 3.302717e+01, 4.497943e-05, 1.000000e+00, 23, 2522, 1) - ((1.316679e+01, -1.082561e+01, 6.404749e+00), (-5.182259e-01, 3.860612e-01, 7.631505e-01), 1.437084e+01, 4.498251e-05, 1.000000e+00, 23, 2522, 1) - ((1.292206e+01, -1.064329e+01, 6.765147e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.507257e-05, 1.000000e+00, 23, 2522, 1) - ((1.286229e+01, -1.063244e+01, 6.805923e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.508772e-05, 1.000000e+00, 23, 2521, 1) - ((1.284917e+01, -1.063006e+01, 6.814880e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509105e-05, 1.000000e+00, 23, 2521, 1) - ((1.284547e+01, -1.063244e+01, 6.820442e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509285e-05, 1.000000e+00, 23, 2522, 1) - ((1.249929e+01, -1.085555e+01, 7.341246e+00), (-1.520079e-01, -3.513652e-01, 9.238161e-01), 7.069024e+00, 4.526201e-05, 1.000000e+00, 23, 2522, 1) - ((1.240103e+01, -1.108268e+01, 7.938428e+00), (-7.405967e-01, -3.230926e-01, 5.891754e-01), 4.460475e+00, 4.543779e-05, 1.000000e+00, 23, 2522, 1) - ((1.229354e+01, -1.112958e+01, 8.023945e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.548748e-05, 1.000000e+00, 23, 2522, 1) - ((1.226820e+01, -1.110933e+01, 8.041241e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.550624e-05, 1.000000e+00, 23, 2314, 1) - ((1.198501e+01, -1.088299e+01, 8.234567e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.571593e-05, 1.000000e+00, 23, 2314, 1) - ((1.156403e+01, -1.063244e+01, 8.480859e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.600087e-05, 1.000000e+00, 23, 2329, 1) - ((1.150264e+01, -1.059590e+01, 8.516776e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.604243e-05, 1.000000e+00, 23, 2329, 1) - ((1.121659e+01, -1.063244e+01, 8.744860e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.623561e-05, 1.000000e+00, 23, 2314, 1) - ((1.063244e+01, -1.070706e+01, 9.210632e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.663011e-05, 1.000000e+00, 23, 2313, 1) - ((1.035391e+01, -1.074263e+01, 9.432717e+00), (-4.847677e-01, -8.685325e-01, -1.032060e-01), 5.647686e-01, 4.681821e-05, 1.000000e+00, 23, 2313, 1) - ((1.031409e+01, -1.081397e+01, 9.424239e+00), (-4.227592e-01, -9.022601e-01, -8.486053e-02), 5.651902e-01, 4.689723e-05, 1.000000e+00, 23, 2313, 1) - ((1.028497e+01, -1.087614e+01, 9.418392e+00), (1.549579e-01, -4.270887e-01, 8.908329e-01), 5.395517e-01, 4.696349e-05, 1.000000e+00, 23, 2313, 1) - ((1.034128e+01, -1.103135e+01, 9.742126e+00), (5.631544e-01, 4.925564e-01, 6.635098e-01), 2.637257e-01, 4.732118e-05, 1.000000e+00, 23, 2313, 1) - ((1.044415e+01, -1.094137e+01, 9.863334e+00), (-1.034377e-01, 7.912271e-01, 6.027108e-01), 1.474934e-01, 4.757836e-05, 1.000000e+00, 23, 2313, 1) - ((1.043959e+01, -1.090643e+01, 9.889950e+00), (1.163182e-01, 9.160889e-01, -3.837331e-01), 1.522434e-01, 4.766149e-05, 1.000000e+00, 23, 2313, 1) - ((1.045733e+01, -1.076664e+01, 9.831395e+00), (-8.136862e-01, 9.805444e-02, -5.729748e-01), 3.341488e-02, 4.794423e-05, 1.000000e+00, 23, 2313, 1) - ((1.044231e+01, -1.076483e+01, 9.820815e+00), (-8.437241e-01, 5.222731e-01, -1.239373e-01), 3.874838e-02, 4.801727e-05, 1.000000e+00, 23, 2313, 1) - ((1.028725e+01, -1.066884e+01, 9.798037e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.869227e-05, 1.000000e+00, 23, 2313, 1) - ((1.021310e+01, -1.063244e+01, 9.757708e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.902498e-05, 1.000000e+00, 23, 2328, 1) - ((1.012717e+01, -1.059025e+01, 9.710967e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 4.941058e-05, 1.000000e+00, 23, 2328, 1) - ((1.001043e+01, -1.038486e+01, 9.645483e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 5.039049e-05, 1.000000e+00, 22, 2328, 3) - ((9.971285e+00, -1.031600e+01, 9.623530e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.071901e-05, 1.000000e+00, 22, 2328, 3) - ((1.002723e+01, -1.037881e+01, 9.564267e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.116633e-05, 1.000000e+00, 23, 2328, 1) - ((1.025152e+01, -1.063060e+01, 9.326683e+00), (-8.159392e-01, -4.792697e-03, 5.781179e-01), 2.920905e-02, 5.295966e-05, 1.000000e+00, 23, 2328, 1) - ((1.000779e+01, -1.063203e+01, 9.499373e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422329e-05, 1.000000e+00, 23, 2328, 1) - ((1.000721e+01, -1.063244e+01, 9.498835e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422746e-05, 1.000000e+00, 23, 2313, 1) - ((9.852478e+00, -1.074269e+01, 9.354584e+00), (-6.686452e-01, -2.988396e-01, 6.808880e-01), 2.993224e-02, 5.534454e-05, 1.000000e+00, 23, 2313, 1) - ((9.765042e+00, -1.078177e+01, 9.443621e+00), (7.712484e-01, -5.215773e-01, 3.648739e-01), 3.590785e-02, 5.589099e-05, 1.000000e+00, 23, 2313, 1) - ((9.798992e+00, -1.080472e+01, 9.459682e+00), (-4.563170e-01, 8.081811e-01, -3.723144e-01), 2.674168e-02, 5.605894e-05, 1.000000e+00, 23, 2313, 1) - ((9.792857e+00, -1.079386e+01, 9.454677e+00), (-9.080336e-01, 4.172659e-01, 3.693418e-02), 9.753404e-03, 5.611838e-05, 1.000000e+00, 23, 2313, 1) - ((9.653805e+00, -1.072996e+01, 9.460332e+00), (-3.727950e-01, 2.889342e-01, -8.817828e-01), 1.781716e-02, 5.723944e-05, 1.000000e+00, 23, 2313, 1) - ((9.628677e+00, -1.071048e+01, 9.400895e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.760453e-05, 1.000000e+00, 23, 2313, 1) - ((9.563380e+00, -1.063244e+01, 9.395105e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.815928e-05, 1.000000e+00, 23, 2328, 1) - ((9.411305e+00, -1.045068e+01, 9.381621e+00), (3.205568e-01, -1.311309e-02, -9.471385e-01), 2.153422e-02, 5.945128e-05, 1.000000e+00, 23, 2328, 1) - ((9.860026e+00, -1.046903e+01, 8.055798e+00), (6.278124e-01, 1.023095e-01, -7.716115e-01), 2.013742e-02, 6.634788e-05, 1.000000e+00, 23, 2328, 1) - ((1.007604e+01, -1.043383e+01, 7.790303e+00), (6.790346e-01, 5.167838e-01, 5.213891e-01), 1.340865e-02, 6.810089e-05, 1.000000e+00, 23, 2328, 1) - ((1.008869e+01, -1.042421e+01, 7.800011e+00), (2.792456e-01, 1.367953e-01, 9.504257e-01), 8.576635e-03, 6.821715e-05, 1.000000e+00, 23, 2328, 1) - ((1.017046e+01, -1.038415e+01, 8.078330e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.050324e-05, 1.000000e+00, 23, 2328, 1) - ((1.008276e+01, -1.035463e+01, 8.083559e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.070353e-05, 1.000000e+00, 22, 2328, 3) - ((9.952201e+00, -1.031068e+01, 8.091343e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.100170e-05, 1.000000e+00, 21, 2328, 2) - ((9.404929e+00, -1.012646e+01, 8.123973e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.225157e-05, 1.000000e+00, 22, 2328, 3) - ((9.274369e+00, -1.008251e+01, 8.131758e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.254974e-05, 1.000000e+00, 23, 2328, 1) - ((9.126730e+00, -1.003281e+01, 8.140560e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.288692e-05, 1.000000e+00, 23, 2328, 1) - ((8.996680e+00, -1.006767e+01, 8.217365e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.321528e-05, 1.000000e+00, 23, 2327, 1) - ((8.694758e+00, -1.014859e+01, 8.395674e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.397758e-05, 1.000000e+00, 23, 2327, 1) - ((8.996680e+00, -9.720167e+00, 8.656770e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.511228e-05, 1.000000e+00, 23, 2328, 1) - ((9.263031e+00, -9.342216e+00, 8.887105e+00), (5.734531e-01, -5.017666e-01, 6.475970e-01), 9.798082e-02, 7.611330e-05, 1.000000e+00, 23, 2328, 1) - ((9.334809e+00, -9.405021e+00, 8.968164e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.640240e-05, 1.000000e+00, 23, 2328, 1) - ((9.335117e+00, -9.448857e+00, 8.932084e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.651925e-05, 1.000000e+00, 22, 2328, 3) - ((9.336345e+00, -9.623801e+00, 8.788098e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.698556e-05, 1.000000e+00, 21, 2328, 2) - ((9.339070e+00, -1.001201e+01, 8.468584e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.802034e-05, 1.000000e+00, 22, 2328, 3) - ((9.340298e+00, -1.018696e+01, 8.324598e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.848665e-05, 1.000000e+00, 23, 2328, 1) - ((9.343193e+00, -1.059945e+01, 7.985097e+00), (1.798796e-01, 3.522536e-02, -9.830577e-01), 1.283272e-01, 7.958616e-05, 1.000000e+00, 23, 2328, 1) - ((9.397753e+00, -1.058877e+01, 7.686922e+00), (6.459563e-01, 7.279465e-03, -7.633397e-01), 1.319449e-01, 8.019832e-05, 1.000000e+00, 23, 2328, 1) - ((9.462343e+00, -1.058804e+01, 7.610595e+00), (-5.748716e-01, 5.760301e-01, -5.811299e-01), 8.880732e-02, 8.039733e-05, 1.000000e+00, 23, 2328, 1) - ((9.287877e+00, -1.041322e+01, 7.434230e+00), (-4.932135e-03, 1.668926e-01, 9.859627e-01), 3.503028e-02, 8.113361e-05, 1.000000e+00, 23, 2328, 1) - ((9.286930e+00, -1.038117e+01, 7.623600e+00), (-9.325544e-02, -9.933000e-01, -6.825369e-02), 3.173764e-02, 8.187553e-05, 1.000000e+00, 23, 2328, 1) - ((9.283901e+00, -1.041342e+01, 7.621384e+00), (-4.235208e-01, -5.129112e-01, 7.466942e-01), 4.258127e-02, 8.200731e-05, 1.000000e+00, 23, 2328, 1) - ((9.264517e+00, -1.043690e+01, 7.655560e+00), (-7.165846e-01, 3.926265e-01, 5.764988e-01), 4.485063e-02, 8.216767e-05, 1.000000e+00, 23, 2328, 1) - ((9.256348e+00, -1.043242e+01, 7.662132e+00), (1.703748e-01, -9.175599e-01, -3.592441e-01), 3.521226e-02, 8.220659e-05, 1.000000e+00, 23, 2328, 1) - ((9.284015e+00, -1.058143e+01, 7.603793e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.283227e-05, 1.000000e+00, 23, 2328, 1) - ((9.309126e+00, -1.063244e+01, 7.631745e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.309804e-05, 1.000000e+00, 23, 2313, 1) - ((9.317824e+00, -1.065011e+01, 7.641427e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.319011e-05, 1.000000e+00, 23, 2313, 1) - ((9.459378e+00, -1.063244e+01, 7.505770e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.403060e-05, 1.000000e+00, 23, 2328, 1) - ((9.492454e+00, -1.062831e+01, 7.474071e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.422700e-05, 1.000000e+00, 23, 2328, 1) - ((9.492472e+00, -1.063244e+01, 7.472688e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.424159e-05, 1.000000e+00, 23, 2313, 1) - ((9.492761e+00, -1.069927e+01, 7.450302e+00), (9.457151e-01, -1.928731e-01, 2.615777e-01), 4.542312e-02, 8.447773e-05, 1.000000e+00, 23, 2313, 1) - ((9.890524e+00, -1.078039e+01, 7.560320e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.590450e-05, 1.000000e+00, 23, 2313, 1) - ((1.004645e+01, -1.080498e+01, 7.439717e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.651090e-05, 0.000000e+00, 23, 2313, 1)] +ParticleType.NEUTRON [((6.474155e+00, -5.192870e+00, 5.413003e+00), (-9.112559e-01, 3.950037e-01, 1.165536e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2367, 2) + ((6.037250e+00, -5.003484e+00, 5.468885e+00), (-9.112559e-01, 3.950037e-01, 1.165536e-01), 2.052226e+06, 4.450883e-05, 1.000000e+00, 22, 2367, 3) + ((5.942573e+00, -4.962444e+00, 5.480995e+00), (-9.112559e-01, 3.950037e-01, 1.165536e-01), 2.052226e+06, 4.450888e-05, 1.000000e+00, 23, 2367, 1) + ((5.861800e+00, -4.927431e+00, 5.491326e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450892e-05, 1.000000e+00, 23, 2367, 1) + ((5.725160e+00, -4.971424e+00, 5.491002e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450902e-05, 1.000000e+00, 23, 2366, 1) + ((5.494150e+00, -5.045802e+00, 5.490454e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450919e-05, 1.000000e+00, 22, 2366, 3) + ((5.392865e+00, -5.078412e+00, 5.490213e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450926e-05, 1.000000e+00, 21, 2366, 2) + ((4.612759e+00, -5.329579e+00, 5.488362e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450981e-05, 1.000000e+00, 22, 2366, 3) + ((4.511474e+00, -5.362189e+00, 5.488121e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450989e-05, 1.000000e+00, 23, 2366, 1) + ((4.089400e+00, -5.498082e+00, 5.487119e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451019e-05, 1.000000e+00, 23, 2365, 1) + ((3.384113e+00, -5.725160e+00, 5.485445e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451069e-05, 1.000000e+00, 23, 2351, 1) + ((2.453640e+00, -6.024740e+00, 5.483237e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451135e-05, 1.000000e+00, 23, 2350, 1) + ((2.086813e+00, -6.142846e+00, 5.482366e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451161e-05, 1.000000e+00, 22, 2350, 3) + ((1.993594e+00, -6.172859e+00, 5.482145e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451168e-05, 1.000000e+00, 21, 2350, 2) + ((1.325704e+00, -6.387896e+00, 5.480560e+00), (8.986086e-01, -4.380574e-01, -2.466265e-02), 9.775839e+05, 4.451215e-05, 1.000000e+00, 21, 2350, 2) + ((2.061403e+00, -6.746538e+00, 5.460368e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451275e-05, 1.000000e+00, 21, 2350, 2) + ((1.122794e+00, -6.498940e+00, 4.743664e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451374e-05, 1.000000e+00, 22, 2350, 3) + ((1.036483e+00, -6.476172e+00, 4.677758e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451383e-05, 1.000000e+00, 23, 2350, 1) + ((8.178800e-01, -6.418507e+00, 4.510837e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451406e-05, 1.000000e+00, 23, 2349, 1) + ((5.725264e-01, -6.353784e+00, 4.323490e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451432e-05, 1.000000e+00, 22, 2349, 3) + ((4.668297e-01, -6.325902e+00, 4.242782e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451443e-05, 1.000000e+00, 21, 2349, 2) + ((-2.989816e-01, -6.123888e+00, 3.658023e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451524e-05, 1.000000e+00, 22, 2349, 3) + ((-4.046782e-01, -6.096006e+00, 3.577315e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451535e-05, 1.000000e+00, 23, 2349, 1) + ((-8.040445e-01, -5.990656e+00, 3.272367e+00), (-7.989001e-01, -1.890553e-01, -5.709787e-01), 6.637114e+05, 4.451577e-05, 1.000000e+00, 23, 2349, 1) + ((-8.178800e-01, -5.993930e+00, 3.262478e+00), (-7.989001e-01, -1.890553e-01, -5.709787e-01), 6.637114e+05, 4.451578e-05, 1.000000e+00, 23, 2348, 1) + ((-1.077910e+00, -6.055465e+00, 3.076633e+00), (-4.487118e-01, 1.670254e-01, -8.779295e-01), 4.550608e+05, 4.451607e-05, 1.000000e+00, 23, 2348, 1) + ((-1.215611e+00, -6.004208e+00, 2.807214e+00), (7.872329e-01, 4.481433e-01, -4.235941e-01), 3.544207e+03, 4.451640e-05, 1.000000e+00, 23, 2348, 1) + ((-1.100296e+00, -5.938564e+00, 2.745166e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.451818e-05, 1.000000e+00, 23, 2348, 1) + ((-8.178800e-01, -5.761448e+00, 2.754541e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.452273e-05, 1.000000e+00, 23, 2349, 1) + ((-7.600184e-01, -5.725160e+00, 2.756462e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.452366e-05, 1.000000e+00, 23, 2363, 1) + ((-2.947156e-01, -5.433347e+00, 2.771908e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.453115e-05, 1.000000e+00, 22, 2363, 3) + ((-2.073333e-01, -5.378546e+00, 2.774809e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.453255e-05, 1.000000e+00, 21, 2363, 2) + ((-1.746705e-01, -5.358062e+00, 2.775893e+00), (5.278774e-01, 5.459205e-01, 6.506276e-01), 2.806481e+03, 4.453308e-05, 1.000000e+00, 21, 2363, 2) + ((-8.681718e-02, -5.267205e+00, 2.884176e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.453535e-05, 1.000000e+00, 21, 2363, 2) + ((-3.684221e-01, -5.266924e+00, 2.745840e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.453967e-05, 1.000000e+00, 22, 2363, 3) + ((-4.840903e-01, -5.266809e+00, 2.689019e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.454144e-05, 1.000000e+00, 23, 2363, 1) + ((-8.178800e-01, -5.266475e+00, 2.525049e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.454655e-05, 1.000000e+00, 23, 2362, 1) + ((-1.151175e+00, -5.266142e+00, 2.361321e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.455166e-05, 1.000000e+00, 22, 2362, 3) + ((-1.266464e+00, -5.266027e+00, 2.304687e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.455342e-05, 1.000000e+00, 21, 2362, 2) + ((-2.005772e+00, -5.265288e+00, 1.941509e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.456475e-05, 1.000000e+00, 22, 2362, 3) + ((-2.121061e+00, -5.265173e+00, 1.884875e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.456651e-05, 1.000000e+00, 23, 2362, 1) + ((-2.393759e+00, -5.264900e+00, 1.750915e+00), (-9.607392e-01, -1.749373e-01, 2.153533e-01), 1.619469e+03, 4.457069e-05, 1.000000e+00, 23, 2362, 1) + ((-2.453640e+00, -5.275804e+00, 1.764337e+00), (-9.607392e-01, -1.749373e-01, 2.153533e-01), 1.619469e+03, 4.457181e-05, 1.000000e+00, 23, 2361, 1) + ((-2.470658e+00, -5.278903e+00, 1.768152e+00), (-6.728606e-01, -2.916408e-01, -6.798561e-01), 4.873672e+02, 4.457213e-05, 1.000000e+00, 23, 2361, 1) + ((-3.463692e+00, -5.709318e+00, 7.647939e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.462046e-05, 1.000000e+00, 23, 2361, 1) + ((-3.467511e+00, -5.725160e+00, 7.600247e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.462138e-05, 1.000000e+00, 23, 2347, 1) + ((-3.533785e+00, -6.000066e+00, 6.772677e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.463730e-05, 1.000000e+00, 22, 2347, 3) + ((-3.562245e+00, -6.118119e+00, 6.417291e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.464413e-05, 1.000000e+00, 21, 2347, 2) + ((-3.723934e+00, -6.788806e+00, 4.398272e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.468297e-05, 1.000000e+00, 22, 2347, 3) + ((-3.752394e+00, -6.906859e+00, 4.042885e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.468980e-05, 1.000000e+00, 23, 2347, 1) + ((-3.848515e+00, -7.305571e+00, 2.842613e-01), (6.498448e-01, -3.243413e-01, -6.873896e-01), 2.328979e+01, 4.471289e-05, 1.000000e+00, 23, 2347, 1) + ((-3.737619e+00, -7.360920e+00, 1.669579e-01), (6.498448e-01, -3.243413e-01, -6.873896e-01), 2.328979e+01, 4.473846e-05, 1.000000e+00, 11, 1750, 1) + ((-3.574308e+00, -7.442429e+00, -5.788041e-03), (6.794505e-01, 3.157106e-01, -6.623246e-01), 1.590416e+01, 4.477610e-05, 1.000000e+00, 11, 1750, 1) + ((-3.398889e+00, -7.360920e+00, -1.767852e-01), (6.794505e-01, 3.157106e-01, -6.623246e-01), 1.590416e+01, 4.482291e-05, 1.000000e+00, 23, 2347, 1) + ((-2.904712e+00, -7.131298e+00, -6.585068e-01), (-4.836985e-02, -2.819627e-01, -9.582053e-01), 2.610202e+00, 4.495476e-05, 1.000000e+00, 23, 2347, 1) + ((-2.923579e+00, -7.241285e+00, -1.032280e+00), (-6.089807e-01, -2.347428e-01, -7.576532e-01), 1.671268e+00, 4.512932e-05, 1.000000e+00, 23, 2347, 1) + ((-3.012516e+00, -7.275567e+00, -1.142930e+00), (3.221931e-01, -5.406104e-01, -7.771306e-01), 1.275709e-01, 4.521100e-05, 1.000000e+00, 23, 2347, 1) + ((-2.984032e+00, -7.323360e+00, -1.211633e+00), (-8.629564e-01, -1.719529e-01, -4.751195e-01), 1.897424e-02, 4.538995e-05, 1.000000e+00, 23, 2347, 1) + ((-3.172528e+00, -7.360920e+00, -1.315413e+00), (-8.629564e-01, -1.719529e-01, -4.751195e-01), 1.897424e-02, 4.653641e-05, 1.000000e+00, 11, 1750, 1) + ((-3.602328e+00, -7.446562e+00, -1.552049e+00), (-1.530190e-01, -7.092235e-01, 6.881767e-01), 1.306951e-02, 4.915052e-05, 1.000000e+00, 11, 1750, 1) + ((-3.625236e+00, -7.552741e+00, -1.449021e+00), (-1.976867e-01, 2.826475e-01, 9.386322e-01), 2.145548e-02, 5.009730e-05, 1.000000e+00, 11, 1750, 1) + ((-3.636290e+00, -7.536936e+00, -1.396537e+00), (1.266676e-01, 2.265353e-01, -9.657314e-01), 1.815564e-02, 5.037329e-05, 1.000000e+00, 11, 1750, 1) + ((-3.621792e+00, -7.511008e+00, -1.507069e+00), (-4.275550e-01, 8.441443e-01, 3.234457e-01), 1.848049e-02, 5.098741e-05, 1.000000e+00, 11, 1750, 1) + ((-3.697811e+00, -7.360920e+00, -1.449560e+00), (-4.275550e-01, 8.441443e-01, 3.234457e-01), 1.848049e-02, 5.193299e-05, 1.000000e+00, 23, 2347, 1) + ((-3.703436e+00, -7.349814e+00, -1.445305e+00), (-7.832167e-01, 5.713670e-01, 2.451762e-01), 1.861705e-02, 5.200296e-05, 1.000000e+00, 23, 2347, 1) + ((-3.823243e+00, -7.262414e+00, -1.407801e+00), (-9.917106e-01, 5.069164e-02, 1.180695e-01), 4.703334e-02, 5.281350e-05, 1.000000e+00, 23, 2347, 1) + ((-4.089400e+00, -7.248809e+00, -1.376113e+00), (-9.917106e-01, 5.069164e-02, 1.180695e-01), 4.703334e-02, 5.370820e-05, 1.000000e+00, 23, 2346, 1) + ((-4.131081e+00, -7.246679e+00, -1.371151e+00), (9.108632e-01, -4.018526e-01, 9.403556e-02), 8.057393e-02, 5.384831e-05, 1.000000e+00, 23, 2346, 1) + ((-4.089400e+00, -7.265067e+00, -1.366848e+00), (9.108632e-01, -4.018526e-01, 9.403556e-02), 8.057393e-02, 5.396486e-05, 1.000000e+00, 23, 2347, 1) + ((-3.872134e+00, -7.360920e+00, -1.344418e+00), (9.108632e-01, -4.018526e-01, 9.403556e-02), 8.057393e-02, 5.457239e-05, 1.000000e+00, 11, 1750, 1) + ((-3.673062e+00, -7.448746e+00, -1.323866e+00), (2.976906e-01, 8.174443e-01, -4.931178e-01), 5.538060e-02, 5.512905e-05, 1.000000e+00, 11, 1750, 1) + ((-3.658580e+00, -7.408978e+00, -1.347855e+00), (-5.409120e-01, 8.345378e-01, -1.046943e-01), 8.122576e-02, 5.527851e-05, 1.000000e+00, 11, 1750, 1) + ((-3.682981e+00, -7.371331e+00, -1.352578e+00), (-5.409120e-01, 8.345378e-01, -1.046943e-01), 8.122576e-02, 5.539294e-05, 0.000000e+00, 11, 1750, 1)] diff --git a/tests/regression_tests/translation/results_true.dat b/tests/regression_tests/translation/results_true.dat index 32897b8e7..f832aa296 100644 --- a/tests/regression_tests/translation/results_true.dat +++ b/tests/regression_tests/translation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.003951E-01 7.739871E-03 +4.087580E-01 4.466279E-03 diff --git a/tests/regression_tests/trigger_batch_interval/results_true.dat b/tests/regression_tests/trigger_batch_interval/results_true.dat index 2fcfaa10a..0571d6c4f 100644 --- a/tests/regression_tests/trigger_batch_interval/results_true.dat +++ b/tests/regression_tests/trigger_batch_interval/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.764624E-01 8.747085E-03 +9.767929E-01 5.327552E-03 tally 1: -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 tally 2: -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 diff --git a/tests/regression_tests/trigger_no_batch_interval/results_true.dat b/tests/regression_tests/trigger_no_batch_interval/results_true.dat index 2fcfaa10a..0571d6c4f 100644 --- a/tests/regression_tests/trigger_no_batch_interval/results_true.dat +++ b/tests/regression_tests/trigger_no_batch_interval/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.764624E-01 8.747085E-03 +9.767929E-01 5.327552E-03 tally 1: -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 tally 2: -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 diff --git a/tests/regression_tests/trigger_no_status/results_true.dat b/tests/regression_tests/trigger_no_status/results_true.dat index e95f05ccb..fb6c0086a 100644 --- a/tests/regression_tests/trigger_no_status/results_true.dat +++ b/tests/regression_tests/trigger_no_status/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.688702E-01 2.263104E-02 +9.682315E-01 3.302924E-03 tally 1: -7.069810E+00 -1.000691E+01 -1.597648E+00 -5.109653E-01 -1.547262E+00 -4.792189E-01 -5.472161E+00 -5.995488E+00 -7.069810E+00 -1.000691E+01 -1.597648E+00 -5.109653E-01 -1.547262E+00 -4.792189E-01 -5.472161E+00 -5.995488E+00 +7.046510E+00 +9.932168E+00 +1.591675E+00 +5.067777E-01 +1.541572E+00 +4.753743E-01 +5.454835E+00 +5.951990E+00 +7.046510E+00 +9.932168E+00 +1.591675E+00 +5.067777E-01 +1.541572E+00 +4.753743E-01 +5.454835E+00 +5.951990E+00 tally 2: -7.069810E+00 -1.000691E+01 -1.597648E+00 -5.109653E-01 -1.547262E+00 -4.792189E-01 -5.472161E+00 -5.995488E+00 +7.046510E+00 +9.932168E+00 +1.591675E+00 +5.067777E-01 +1.541572E+00 +4.753743E-01 +5.454835E+00 +5.951990E+00 diff --git a/tests/regression_tests/trigger_statepoint_restart/results_true.dat b/tests/regression_tests/trigger_statepoint_restart/results_true.dat index 3ab555d73..3e6619d74 100644 --- a/tests/regression_tests/trigger_statepoint_restart/results_true.dat +++ b/tests/regression_tests/trigger_statepoint_restart/results_true.dat @@ -1,5 +1,5 @@ k-combined: -2.963805E-01 2.986351E-03 +3.014717E-01 2.864764E-03 tally 1: -8.017826E+01 -6.436316E+02 +8.946107E+01 +7.281263E+02 diff --git a/tests/regression_tests/trigger_tallies/results_true.dat b/tests/regression_tests/trigger_tallies/results_true.dat index 2fcfaa10a..0571d6c4f 100644 --- a/tests/regression_tests/trigger_tallies/results_true.dat +++ b/tests/regression_tests/trigger_tallies/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.764624E-01 8.747085E-03 +9.767929E-01 5.327552E-03 tally 1: -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 tally 2: -1.408588E+01 -1.985937E+01 -3.194837E+00 -1.021391E+00 -3.096170E+00 -9.592197E-01 -1.089104E+01 -1.187349E+01 +1.405471E+01 +1.976444E+01 +3.186139E+00 +1.015515E+00 +3.088643E+00 +9.542994E-01 +1.086857E+01 +1.182011E+01 diff --git a/tests/regression_tests/triso/results_true.dat b/tests/regression_tests/triso/results_true.dat index 279094ab3..fa1842e54 100644 --- a/tests/regression_tests/triso/results_true.dat +++ b/tests/regression_tests/triso/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.406055E+00 9.581396E-02 +1.716873E+00 5.266107E-02 diff --git a/tests/regression_tests/uniform_fs/results_true.dat b/tests/regression_tests/uniform_fs/results_true.dat index ebf06a8d3..46654b49b 100644 --- a/tests/regression_tests/uniform_fs/results_true.dat +++ b/tests/regression_tests/uniform_fs/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.643255E-01 1.041799E-02 +3.685309E-01 1.861720E-03 diff --git a/tests/regression_tests/universe/results_true.dat b/tests/regression_tests/universe/results_true.dat index fe46748c8..bbf03de94 100644 --- a/tests/regression_tests/universe/results_true.dat +++ b/tests/regression_tests/universe/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.987050E-01 1.827430E-03 +3.070134E-01 3.900396E-03 diff --git a/tests/regression_tests/unstructured_mesh/results_true.dat b/tests/regression_tests/unstructured_mesh/results_true.dat index c93eadfdb..a6cad647c 100644 --- a/tests/regression_tests/unstructured_mesh/results_true.dat +++ b/tests/regression_tests/unstructured_mesh/results_true.dat @@ -1,26002 +1,4002 @@ tally 1: -4.873713E-02 -2.881006E-04 -7.388548E-02 -6.421281E-04 -8.309847E-02 -8.079791E-04 -8.802030E-02 -8.590396E-04 -6.935977E-02 -5.711723E-04 -7.203243E-02 -5.847086E-04 -8.146742E-02 -8.422730E-04 -7.112287E-02 -5.331461E-04 -6.944025E-02 -6.220640E-04 -4.605581E-02 -3.052058E-04 -7.341445E-02 -6.319466E-04 -9.013420E-02 -1.083246E-03 -1.221831E-01 -1.761591E-03 -1.244445E-01 -1.714565E-03 -1.324446E-01 -2.041161E-03 -1.110879E-01 -1.399393E-03 -1.484356E-01 -2.412924E-03 -1.243711E-01 -1.740278E-03 -1.011503E-01 -1.167740E-03 -6.361036E-02 -4.887610E-04 -6.774704E-02 -6.414084E-04 -8.554708E-02 -9.422426E-04 -1.400424E-01 -2.238846E-03 -1.573053E-01 -2.687261E-03 -1.640744E-01 -2.864310E-03 -1.305526E-01 -1.848808E-03 -1.688498E-01 -3.171592E-03 -1.886270E-01 -3.972143E-03 -1.198794E-01 -1.610468E-03 -7.781359E-02 -8.133302E-04 -8.003923E-02 -7.488868E-04 -1.533578E-01 -2.662538E-03 -2.008234E-01 -4.137147E-03 -2.073409E-01 -4.520687E-03 -1.975748E-01 -4.160887E-03 -2.267844E-01 -5.491338E-03 -1.881489E-01 -3.776524E-03 -1.546827E-01 -2.713647E-03 -1.390602E-01 -2.088805E-03 -9.507737E-02 -1.035204E-03 -9.443902E-02 -9.783367E-04 -1.528603E-01 -2.521963E-03 -2.009995E-01 -4.414632E-03 -2.303894E-01 -5.751985E-03 -2.273601E-01 -5.379286E-03 -2.086601E-01 -4.747259E-03 -1.587188E-01 -2.863534E-03 -1.656423E-01 -2.826265E-03 -1.358638E-01 -2.045306E-03 -9.729054E-02 -1.078500E-03 -1.007280E-01 -1.185702E-03 -1.587021E-01 -2.754745E-03 -1.900019E-01 -3.874093E-03 -1.874138E-01 -4.177562E-03 -2.233840E-01 -5.748107E-03 -2.044120E-01 -4.806449E-03 -1.840480E-01 -3.872224E-03 -2.000442E-01 -4.610770E-03 -1.260142E-01 -1.809723E-03 -8.400216E-02 -8.434010E-04 -5.900093E-02 -3.850176E-04 -1.411568E-01 -2.471608E-03 -1.744586E-01 -3.239802E-03 -1.834956E-01 -3.972256E-03 -2.120173E-01 -4.965877E-03 -1.896203E-01 -3.727876E-03 -1.768841E-01 -3.517246E-03 -1.329247E-01 -1.981664E-03 -9.206320E-02 -1.061169E-03 -8.660878E-02 -8.546437E-04 -7.697726E-02 -7.926443E-04 -1.161555E-01 -1.548200E-03 -1.386967E-01 -2.047818E-03 -1.482373E-01 -2.537385E-03 -1.929067E-01 -4.259826E-03 -1.371938E-01 -1.949236E-03 -1.308202E-01 -2.027747E-03 -1.135428E-01 -1.560189E-03 -1.215934E-01 -1.672414E-03 -4.697342E-02 -3.377074E-04 -4.963529E-02 -3.397352E-04 -8.476039E-02 -8.774056E-04 -1.108440E-01 -1.411371E-03 -1.054914E-01 -1.252891E-03 -1.453762E-01 -2.358977E-03 -9.293716E-02 -9.683367E-04 -1.224872E-01 -1.612325E-03 -8.334352E-02 -7.907688E-04 -7.546069E-02 -7.025010E-04 -5.962134E-02 -6.951755E-04 -3.107769E-02 -1.723123E-04 -8.479467E-02 -9.620488E-04 -8.295926E-02 -7.769636E-04 -8.805824E-02 -8.500302E-04 -8.616294E-02 -8.661213E-04 -7.861089E-02 -6.835617E-04 -7.593919E-02 -7.633339E-04 -7.303400E-02 -6.464593E-04 -7.512486E-02 -6.007484E-04 -5.595863E-02 -4.403603E-04 -6.015811E-02 -4.297440E-04 -8.867588E-02 -8.521129E-04 -1.103542E-01 -1.469796E-03 -1.153731E-01 -1.606650E-03 -1.280835E-01 -1.791883E-03 -1.434578E-01 -2.215626E-03 -1.104920E-01 -1.470286E-03 -9.385805E-02 -1.114787E-03 -1.169307E-01 -1.600595E-03 -6.083594E-02 -4.303510E-04 -8.816849E-02 -8.791686E-04 -1.350912E-01 -2.127521E-03 -2.026574E-01 -4.456203E-03 -2.082171E-01 -4.587768E-03 -2.291899E-01 -5.560114E-03 -2.040384E-01 -4.355166E-03 -2.081784E-01 -5.172938E-03 -1.958644E-01 -4.308708E-03 -1.535028E-01 -2.754667E-03 -6.265531E-02 -4.662647E-04 -1.239416E-01 -1.608329E-03 -1.655136E-01 -3.098331E-03 -2.152185E-01 -5.116031E-03 -2.663061E-01 -7.502107E-03 -3.072160E-01 -9.873652E-03 -2.453306E-01 -6.585229E-03 -2.577460E-01 -6.982524E-03 -2.470375E-01 -6.761678E-03 -1.492132E-01 -2.465269E-03 -1.115903E-01 -1.444496E-03 -8.901752E-02 -9.826260E-04 -1.849459E-01 -3.824332E-03 -3.139129E-01 -1.040826E-02 -3.209843E-01 -1.072304E-02 -3.074029E-01 -9.805249E-03 -3.289037E-01 -1.137280E-02 -3.333668E-01 -1.140301E-02 -2.305636E-01 -5.572002E-03 -1.911618E-01 -3.897249E-03 -1.239342E-01 -1.745528E-03 -1.463546E-01 -2.897280E-03 -2.041194E-01 -4.264966E-03 -2.781505E-01 -8.222869E-03 -3.535732E-01 -1.290897E-02 -3.736359E-01 -1.424372E-02 -3.507573E-01 -1.268186E-02 -3.537878E-01 -1.317025E-02 -2.797764E-01 -8.141471E-03 -2.257660E-01 -5.307299E-03 -1.248875E-01 -1.867307E-03 -1.334027E-01 -1.952356E-03 -2.190936E-01 -5.220949E-03 -2.880627E-01 -9.292540E-03 -3.683567E-01 -1.398170E-02 -3.451428E-01 -1.245893E-02 -3.602954E-01 -1.357760E-02 -3.363047E-01 -1.177859E-02 -2.658735E-01 -8.042327E-03 -1.720687E-01 -3.616340E-03 -9.348145E-02 -9.216558E-04 -1.303415E-01 -2.064085E-03 -1.757103E-01 -3.440908E-03 -2.442374E-01 -6.810297E-03 -2.858542E-01 -8.698701E-03 -3.349866E-01 -1.174757E-02 -2.840415E-01 -8.265549E-03 -2.763234E-01 -8.045873E-03 -2.478361E-01 -6.589169E-03 -1.766169E-01 -3.338895E-03 -1.236805E-01 -1.649583E-03 -1.307918E-01 -1.796440E-03 -1.756810E-01 -3.938136E-03 -2.071625E-01 -4.889011E-03 -2.332393E-01 -5.650908E-03 -2.524899E-01 -7.236764E-03 -2.393364E-01 -5.985752E-03 -2.142983E-01 -4.994425E-03 -2.132056E-01 -4.981318E-03 -1.437349E-01 -2.274574E-03 -1.142901E-01 -1.631508E-03 -7.809219E-02 -7.844820E-04 -1.076778E-01 -1.505283E-03 -1.787646E-01 -3.437697E-03 -1.664344E-01 -2.938475E-03 -1.868305E-01 -3.942399E-03 -2.065932E-01 -4.503697E-03 -1.644873E-01 -3.015461E-03 -1.553155E-01 -2.637052E-03 -1.523517E-01 -2.641268E-03 -8.646767E-02 -8.586764E-04 -4.575304E-02 -2.880831E-04 -8.659752E-02 -1.007122E-03 -1.086638E-01 -1.418859E-03 -1.206844E-01 -1.631006E-03 -1.553521E-01 -2.699733E-03 -1.023448E-01 -1.229544E-03 -1.236892E-01 -1.719554E-03 -1.059603E-01 -1.474144E-03 -9.843445E-02 -1.147384E-03 -6.598215E-02 -6.724344E-04 -8.999660E-02 -1.129810E-03 -1.016655E-01 -1.128618E-03 -1.115822E-01 -1.437827E-03 -1.649326E-01 -3.015499E-03 -1.937529E-01 -4.048175E-03 -1.852317E-01 -3.668098E-03 -1.620688E-01 -2.937845E-03 -1.290063E-01 -1.922280E-03 -1.208701E-01 -1.669032E-03 -4.421440E-02 -2.483126E-04 -1.159755E-01 -1.426808E-03 -1.459714E-01 -2.613102E-03 -1.778589E-01 -3.427022E-03 -2.346134E-01 -5.940704E-03 -3.063520E-01 -1.009182E-02 -2.950770E-01 -9.132939E-03 -2.583166E-01 -7.253540E-03 -2.101808E-01 -5.272950E-03 -1.850368E-01 -3.730831E-03 -7.244837E-02 -5.806488E-04 -1.441504E-01 -2.203647E-03 -2.206693E-01 -5.103470E-03 -3.047901E-01 -9.751684E-03 -3.531926E-01 -1.351362E-02 -3.945357E-01 -1.624582E-02 -4.621245E-01 -2.215536E-02 -4.200516E-01 -1.926381E-02 -3.397496E-01 -1.264644E-02 -2.045791E-01 -4.443989E-03 -1.132779E-01 -1.665634E-03 -1.168744E-01 -1.466979E-03 -2.665743E-01 -7.799994E-03 -4.108479E-01 -1.764683E-02 -5.099245E-01 -2.656607E-02 -5.375292E-01 -2.986206E-02 -5.477580E-01 -3.184925E-02 -5.060566E-01 -2.644067E-02 -3.917491E-01 -1.649179E-02 -2.631839E-01 -7.172646E-03 -1.393797E-01 -2.179333E-03 -1.415608E-01 -2.582853E-03 -2.695963E-01 -8.100051E-03 -4.591315E-01 -2.150436E-02 -5.838830E-01 -3.565296E-02 -6.933462E-01 -4.933765E-02 -6.498992E-01 -4.329824E-02 -5.274087E-01 -2.893644E-02 -4.644714E-01 -2.208542E-02 -2.784825E-01 -8.228619E-03 -1.756971E-01 -3.435838E-03 -1.841108E-01 -3.753742E-03 -2.556216E-01 -6.993979E-03 -4.539882E-01 -2.105903E-02 -5.644697E-01 -3.353269E-02 -6.477708E-01 -4.262528E-02 -6.274586E-01 -4.094566E-02 -4.871803E-01 -2.460107E-02 -3.651460E-01 -1.537598E-02 -2.377974E-01 -6.036841E-03 -1.492687E-01 -2.421537E-03 -1.449703E-01 -2.190902E-03 -2.414255E-01 -6.387083E-03 -4.115719E-01 -1.783179E-02 -4.694990E-01 -2.282330E-02 -5.311416E-01 -2.970750E-02 -5.218655E-01 -2.795428E-02 -4.993270E-01 -2.574782E-02 -3.564483E-01 -1.422766E-02 -2.266457E-01 -5.534879E-03 -1.952576E-01 -4.177312E-03 -1.042590E-01 -1.176129E-03 -1.697991E-01 -3.286179E-03 -2.717221E-01 -8.156353E-03 -3.954295E-01 -1.626070E-02 -3.609317E-01 -1.316825E-02 -4.028309E-01 -1.737150E-02 -3.598743E-01 -1.378511E-02 -2.960368E-01 -9.045648E-03 -1.916245E-01 -4.182938E-03 -1.400504E-01 -2.146240E-03 -7.940300E-02 -7.986853E-04 -1.200054E-01 -1.726710E-03 -2.148774E-01 -4.835765E-03 -2.268851E-01 -5.713301E-03 -3.111988E-01 -1.041879E-02 -2.623195E-01 -7.661642E-03 -2.331769E-01 -5.928043E-03 -2.156752E-01 -5.033537E-03 -1.882320E-01 -3.956427E-03 -9.864956E-02 -1.084355E-03 -6.087770E-02 -5.179666E-04 -1.086978E-01 -1.313619E-03 -1.344587E-01 -1.970449E-03 -1.740701E-01 -3.313694E-03 -1.804922E-01 -3.525957E-03 -1.724149E-01 -3.543590E-03 -1.399028E-01 -2.273390E-03 -1.456847E-01 -2.524033E-03 -1.194497E-01 -1.524909E-03 -6.585025E-02 -6.225934E-04 -8.228757E-02 -8.696950E-04 -9.653270E-02 -9.897964E-04 -1.628236E-01 -3.163363E-03 -2.294784E-01 -5.585206E-03 -2.013744E-01 -4.481916E-03 -1.904412E-01 -4.042826E-03 -1.614976E-01 -2.818448E-03 -1.577143E-01 -2.732044E-03 -1.102866E-01 -1.529048E-03 -7.446456E-02 -6.633761E-04 -1.435986E-01 -2.237722E-03 -1.897248E-01 -4.132042E-03 -2.294338E-01 -5.931694E-03 -3.421437E-01 -1.221982E-02 -3.839244E-01 -1.553491E-02 -3.266968E-01 -1.088442E-02 -3.198477E-01 -1.080985E-02 -2.628059E-01 -7.789175E-03 -1.734962E-01 -3.443215E-03 -1.286647E-01 -1.955856E-03 -1.691938E-01 -3.460989E-03 -2.825603E-01 -8.930867E-03 -3.393298E-01 -1.245987E-02 -4.719879E-01 -2.299342E-02 -5.453030E-01 -3.116166E-02 -5.283745E-01 -2.875357E-02 -4.717010E-01 -2.274570E-02 -3.543923E-01 -1.356917E-02 -2.286992E-01 -5.495781E-03 -1.503321E-01 -2.412737E-03 -1.914802E-01 -4.228512E-03 -2.663347E-01 -7.478291E-03 -4.945846E-01 -2.581416E-02 -7.132283E-01 -5.214747E-02 -8.772549E-01 -8.070787E-02 -9.215230E-01 -8.643514E-02 -7.136543E-01 -5.309880E-02 -4.683027E-01 -2.335474E-02 -2.848724E-01 -8.819567E-03 -1.962746E-01 -4.034279E-03 -1.963942E-01 -4.150202E-03 -3.081918E-01 -1.036112E-02 -5.313924E-01 -2.943772E-02 -8.980200E-01 -8.439371E-02 -1.404070E+00 -1.986543E-01 -1.242684E+00 -1.571634E-01 -8.663320E-01 -7.587086E-02 -5.654541E-01 -3.252262E-02 -3.281152E-01 -1.090032E-02 -2.044034E-01 -4.517108E-03 -2.006195E-01 -4.176414E-03 -3.100848E-01 -1.042288E-02 -5.422115E-01 -3.004711E-02 -9.330393E-01 -8.964243E-02 -1.277607E+00 -1.657398E-01 -1.173275E+00 -1.409364E-01 -8.049595E-01 -6.791702E-02 -4.739057E-01 -2.461174E-02 -3.052609E-01 -9.872506E-03 -2.088298E-01 -4.793522E-03 -2.133326E-01 -4.862481E-03 -2.680060E-01 -7.625628E-03 -4.610074E-01 -2.155754E-02 -6.717074E-01 -4.626196E-02 -8.563743E-01 -7.430382E-02 -8.419238E-01 -7.436332E-02 -6.475334E-01 -4.244410E-02 -4.496406E-01 -2.101233E-02 -3.081348E-01 -1.046704E-02 -1.619249E-01 -3.062437E-03 -1.415369E-01 -2.255371E-03 -2.064850E-01 -4.712501E-03 -3.464136E-01 -1.293262E-02 -4.719265E-01 -2.272450E-02 -6.461406E-01 -4.354686E-02 -5.185955E-01 -2.909923E-02 -4.946850E-01 -2.606769E-02 -3.812863E-01 -1.500761E-02 -2.715616E-01 -7.844887E-03 -1.440914E-01 -2.297969E-03 -1.220110E-01 -1.727820E-03 -1.988195E-01 -4.845577E-03 -2.623807E-01 -7.651539E-03 -3.140727E-01 -1.024276E-02 -3.576120E-01 -1.349203E-02 -3.350431E-01 -1.214172E-02 -3.623127E-01 -1.392899E-02 -2.727478E-01 -8.086348E-03 -2.149275E-01 -5.361115E-03 -1.314584E-01 -1.963133E-03 -9.162433E-02 -9.983184E-04 -1.361470E-01 -2.027658E-03 -1.761731E-01 -3.389541E-03 -1.989963E-01 -4.594834E-03 -1.950142E-01 -4.102131E-03 -2.134629E-01 -4.672913E-03 -1.986280E-01 -4.090736E-03 -1.587464E-01 -2.850886E-03 -1.139834E-01 -1.491308E-03 -9.993253E-02 -1.150993E-03 -7.801279E-02 -7.470217E-04 -1.374998E-01 -1.969932E-03 -1.804494E-01 -3.568829E-03 -2.466413E-01 -6.594134E-03 -2.341345E-01 -5.848688E-03 -1.995756E-01 -4.362592E-03 -1.602288E-01 -3.066421E-03 -1.562435E-01 -2.552603E-03 -1.104688E-01 -1.359308E-03 -1.007842E-01 -1.139355E-03 -1.261199E-01 -1.847741E-03 -1.775287E-01 -3.680466E-03 -2.767100E-01 -8.008082E-03 -3.400792E-01 -1.195930E-02 -3.935631E-01 -1.640831E-02 -3.523748E-01 -1.302259E-02 -2.906020E-01 -9.059548E-03 -2.537932E-01 -6.876862E-03 -1.861336E-01 -3.787655E-03 -1.313071E-01 -2.065327E-03 -1.591139E-01 -2.819971E-03 -2.386577E-01 -6.457612E-03 -3.911616E-01 -1.594274E-02 -5.394472E-01 -3.061236E-02 -6.866890E-01 -4.817139E-02 -6.283365E-01 -4.055448E-02 -5.748601E-01 -3.459526E-02 -4.435554E-01 -2.009979E-02 -3.296444E-01 -1.154923E-02 -1.967361E-01 -4.169679E-03 -1.739968E-01 -3.208983E-03 -3.082977E-01 -9.811520E-03 -5.382503E-01 -3.058501E-02 -8.367621E-01 -7.291096E-02 -1.211062E+00 -1.496807E-01 -1.258748E+00 -1.608596E-01 -9.427524E-01 -9.038319E-02 -6.071099E-01 -3.854873E-02 -3.709298E-01 -1.478349E-02 -2.098170E-01 -4.835442E-03 -2.119024E-01 -4.712157E-03 -3.552855E-01 -1.323431E-02 -6.321647E-01 -4.077718E-02 -1.246141E+00 -1.565725E-01 -4.380951E+00 -1.942648E+00 -4.247605E+00 -1.810085E+00 -1.281712E+00 -1.683930E-01 -6.221859E-01 -3.919458E-02 -3.675010E-01 -1.432994E-02 -1.841643E-01 -3.510340E-03 -2.146914E-01 -5.048810E-03 -3.256950E-01 -1.139212E-02 -6.810729E-01 -4.813808E-02 -1.247489E+00 -1.574970E-01 -4.442262E+00 -1.985510E+00 -4.257415E+00 -1.821021E+00 -1.235711E+00 -1.535743E-01 -6.900244E-01 -4.832224E-02 -3.697406E-01 -1.425051E-02 -2.012083E-01 -4.510582E-03 -1.912047E-01 -4.273539E-03 -3.451744E-01 -1.225531E-02 -5.600376E-01 -3.307491E-02 -8.544790E-01 -7.409781E-02 -1.325242E+00 -1.782579E-01 -1.346957E+00 -1.841487E-01 -9.214797E-01 -8.688521E-02 -4.797898E-01 -2.328018E-02 -3.426011E-01 -1.225085E-02 -1.774389E-01 -3.518562E-03 -1.554220E-01 -2.654272E-03 -2.668481E-01 -7.631552E-03 -4.104944E-01 -1.755636E-02 -5.095732E-01 -2.660987E-02 -6.919120E-01 -4.918083E-02 -7.159855E-01 -5.218821E-02 -6.006622E-01 -3.710972E-02 -4.366095E-01 -2.004334E-02 -2.694762E-01 -7.978724E-03 -1.656914E-01 -3.089952E-03 -1.756674E-01 -3.399731E-03 -2.115494E-01 -4.962007E-03 -2.931609E-01 -9.634091E-03 -3.427335E-01 -1.230723E-02 -3.926075E-01 -1.686560E-02 -4.266016E-01 -1.861013E-02 -3.380544E-01 -1.177601E-02 -3.203345E-01 -1.042122E-02 -2.107818E-01 -4.975737E-03 -1.190587E-01 -1.667581E-03 -1.043469E-01 -1.388459E-03 -1.409254E-01 -2.165664E-03 -1.158111E-01 -1.584653E-03 -2.204672E-01 -5.077689E-03 -2.548870E-01 -6.790565E-03 -2.560290E-01 -6.703128E-03 -2.273470E-01 -5.548064E-03 -1.544622E-01 -2.859247E-03 -1.514176E-01 -2.580868E-03 -9.401839E-02 -9.957536E-04 -8.183741E-02 -1.018095E-03 -1.494302E-01 -2.610469E-03 -1.724667E-01 -3.163766E-03 -1.906518E-01 -3.886725E-03 -2.093021E-01 -4.547285E-03 -2.192608E-01 -5.381555E-03 -2.142120E-01 -5.229554E-03 -1.818979E-01 -3.730168E-03 -1.593537E-01 -2.930097E-03 -1.006301E-01 -1.243388E-03 -1.363959E-01 -2.201651E-03 -1.921074E-01 -4.287698E-03 -2.807569E-01 -8.586780E-03 -3.032112E-01 -9.281779E-03 -3.488735E-01 -1.290376E-02 -3.912428E-01 -1.651860E-02 -4.032276E-01 -1.745809E-02 -2.909627E-01 -9.146241E-03 -1.775633E-01 -3.593723E-03 -1.331733E-01 -1.922430E-03 -1.524251E-01 -2.694091E-03 -2.697127E-01 -7.768392E-03 -4.166062E-01 -1.776536E-02 -5.663715E-01 -3.298425E-02 -6.244007E-01 -3.998959E-02 -6.599368E-01 -4.570158E-02 -5.685603E-01 -3.382373E-02 -3.800938E-01 -1.547625E-02 -2.603056E-01 -7.053095E-03 -1.706694E-01 -3.148614E-03 -1.731386E-01 -3.384991E-03 -3.109075E-01 -1.033479E-02 -5.771187E-01 -3.413152E-02 -8.606415E-01 -7.510241E-02 -1.294303E+00 -1.706906E-01 -1.313399E+00 -1.767631E-01 -7.817706E-01 -6.342406E-02 -5.927279E-01 -3.756882E-02 -3.708410E-01 -1.458571E-02 -1.723505E-01 -3.356435E-03 -2.304233E-01 -5.998040E-03 -3.750987E-01 -1.501277E-02 -6.734152E-01 -4.746505E-02 -1.310995E+00 -1.732589E-01 -4.421199E+00 -1.964531E+00 -4.214183E+00 -1.786748E+00 -1.223434E+00 -1.530503E-01 -5.926626E-01 -3.641847E-02 -3.153714E-01 -1.019858E-02 -2.037244E-01 -4.381188E-03 -1.863505E-01 -3.684332E-03 -3.648623E-01 -1.378365E-02 -6.164882E-01 -3.893164E-02 -1.178969E+00 -1.417606E-01 -4.221345E+00 -1.789744E+00 -4.317433E+00 -1.872379E+00 -1.243011E+00 -1.581634E-01 -6.866745E-01 -4.754022E-02 -3.586774E-01 -1.301597E-02 -2.322214E-01 -5.492154E-03 -1.791966E-01 -3.463117E-03 -3.076717E-01 -9.716616E-03 -4.906144E-01 -2.470769E-02 -8.471037E-01 -7.406279E-02 -1.363587E+00 -1.889087E-01 -1.335963E+00 -1.803764E-01 -8.600227E-01 -7.530944E-02 -5.437258E-01 -3.114706E-02 -3.713934E-01 -1.456554E-02 -1.995931E-01 -4.422520E-03 -1.343031E-01 -2.012284E-03 -2.572828E-01 -6.840867E-03 -4.435747E-01 -2.050887E-02 -5.766007E-01 -3.437038E-02 -7.346272E-01 -5.540755E-02 -7.053071E-01 -5.111709E-02 -6.063267E-01 -3.981091E-02 -4.094521E-01 -1.801684E-02 -2.832627E-01 -8.238241E-03 -1.618924E-01 -3.067045E-03 -1.257079E-01 -1.802188E-03 -2.209365E-01 -5.343615E-03 -2.538278E-01 -7.109201E-03 -3.620261E-01 -1.396948E-02 -4.303042E-01 -1.872503E-02 -4.036624E-01 -1.774648E-02 -3.185915E-01 -1.192555E-02 -2.959360E-01 -9.265211E-03 -2.254861E-01 -5.671747E-03 -1.339005E-01 -2.034506E-03 -1.251282E-01 -1.754100E-03 -1.155042E-01 -1.606166E-03 -1.603827E-01 -2.694604E-03 -2.425425E-01 -6.218648E-03 -2.827714E-01 -8.247692E-03 -2.354428E-01 -5.778596E-03 -1.964531E-01 -4.365869E-03 -1.620035E-01 -3.000138E-03 -1.402609E-01 -2.252442E-03 -7.770439E-02 -7.584947E-04 -8.904883E-02 -9.832411E-04 -1.364994E-01 -2.060968E-03 -1.556202E-01 -3.013917E-03 -1.794759E-01 -3.609302E-03 -2.027676E-01 -4.271217E-03 -1.910134E-01 -3.830997E-03 -2.102956E-01 -4.746179E-03 -2.069806E-01 -4.732181E-03 -1.280198E-01 -1.803469E-03 -8.851884E-02 -1.050264E-03 -1.411243E-01 -2.309051E-03 -2.058752E-01 -4.840657E-03 -2.589000E-01 -7.354104E-03 -2.346176E-01 -5.819008E-03 -3.064791E-01 -9.995356E-03 -3.537650E-01 -1.318436E-02 -3.442248E-01 -1.225618E-02 -2.856280E-01 -9.047308E-03 -1.556316E-01 -2.976492E-03 -9.305931E-02 -9.568946E-04 -1.918345E-01 -3.871787E-03 -3.083654E-01 -1.109476E-02 -4.076303E-01 -1.807424E-02 -4.595063E-01 -2.220396E-02 -5.684770E-01 -3.345901E-02 -5.734059E-01 -3.325457E-02 -4.719375E-01 -2.393976E-02 -3.033874E-01 -1.029056E-02 -2.394489E-01 -6.540160E-03 -1.431584E-01 -2.691530E-03 -1.857128E-01 -3.720812E-03 -3.401652E-01 -1.213267E-02 -4.998027E-01 -2.627877E-02 -6.660538E-01 -4.542647E-02 -8.594730E-01 -7.625343E-02 -8.531451E-01 -7.416582E-02 -6.787742E-01 -4.744554E-02 -4.724654E-01 -2.328201E-02 -3.030469E-01 -9.464288E-03 -1.840238E-01 -3.680486E-03 -2.172436E-01 -4.932506E-03 -3.724089E-01 -1.512940E-02 -5.834908E-01 -3.595138E-02 -8.787419E-01 -7.754496E-02 -1.235501E+00 -1.556040E-01 -1.186802E+00 -1.419219E-01 -8.626663E-01 -7.644446E-02 -5.366263E-01 -2.954661E-02 -3.177208E-01 -1.051791E-02 -1.844215E-01 -3.676916E-03 -1.932190E-01 -4.023337E-03 -3.693850E-01 -1.452218E-02 -5.443615E-01 -3.020527E-02 -8.889578E-01 -8.111822E-02 -1.273207E+00 -1.655818E-01 -1.247526E+00 -1.585006E-01 -8.324980E-01 -7.213823E-02 -4.899464E-01 -2.450485E-02 -3.370823E-01 -1.208260E-02 -1.809043E-01 -3.714864E-03 -1.615415E-01 -2.906239E-03 -2.937828E-01 -9.651929E-03 -4.913048E-01 -2.639344E-02 -6.850176E-01 -4.797579E-02 -8.755910E-01 -7.958162E-02 -8.703001E-01 -7.730840E-02 -6.973913E-01 -5.089360E-02 -4.203999E-01 -1.844697E-02 -3.140340E-01 -1.039993E-02 -1.441709E-01 -2.488125E-03 -1.350197E-01 -2.064659E-03 -2.543930E-01 -7.177543E-03 -3.348117E-01 -1.259149E-02 -4.679892E-01 -2.273369E-02 -6.434887E-01 -4.331187E-02 -5.381700E-01 -2.974074E-02 -4.555945E-01 -2.167655E-02 -3.401588E-01 -1.191694E-02 -2.681734E-01 -7.550804E-03 -1.704519E-01 -3.365024E-03 -9.745304E-02 -1.232312E-03 -1.678994E-01 -3.221936E-03 -2.605430E-01 -7.393204E-03 -3.128187E-01 -1.138967E-02 -3.712111E-01 -1.460808E-02 -3.609117E-01 -1.331179E-02 -3.321706E-01 -1.170549E-02 -2.480901E-01 -6.266952E-03 -2.002359E-01 -4.338795E-03 -1.162468E-01 -1.536532E-03 -7.239001E-02 -5.815144E-04 -1.163546E-01 -1.453456E-03 -1.636165E-01 -3.201377E-03 -1.973025E-01 -4.660155E-03 -2.100585E-01 -5.039148E-03 -2.171398E-01 -5.070524E-03 -1.995065E-01 -4.193481E-03 -1.813545E-01 -3.549108E-03 -1.365406E-01 -2.182883E-03 -8.101165E-02 -7.758114E-04 -7.133170E-02 -5.967128E-04 -1.319234E-01 -1.933536E-03 -1.445023E-01 -2.409485E-03 -1.495938E-01 -2.481635E-03 -1.801306E-01 -3.481001E-03 -1.733442E-01 -3.171024E-03 -1.725688E-01 -3.165238E-03 -1.518925E-01 -2.585745E-03 -1.077414E-01 -1.395636E-03 -7.934204E-02 -7.147327E-04 -1.062269E-01 -1.354440E-03 -1.751122E-01 -3.623982E-03 -2.203107E-01 -5.413498E-03 -2.341057E-01 -5.605200E-03 -2.669322E-01 -7.526239E-03 -2.746743E-01 -7.646941E-03 -2.389916E-01 -6.235257E-03 -1.587546E-01 -2.827472E-03 -1.498724E-01 -2.673613E-03 -1.051763E-01 -1.391507E-03 -1.424360E-01 -2.468775E-03 -2.608608E-01 -7.055429E-03 -3.154162E-01 -1.024928E-02 -3.674104E-01 -1.418521E-02 -3.976162E-01 -1.732640E-02 -4.746502E-01 -2.349709E-02 -3.662445E-01 -1.447515E-02 -2.506236E-01 -6.593606E-03 -2.161204E-01 -4.801367E-03 -1.306963E-01 -1.975560E-03 -1.770351E-01 -3.932818E-03 -2.635109E-01 -7.772472E-03 -4.024536E-01 -1.731960E-02 -4.701442E-01 -2.265515E-02 -5.561475E-01 -3.235124E-02 -5.523785E-01 -3.142962E-02 -5.071292E-01 -2.592728E-02 -3.746613E-01 -1.518899E-02 -2.620776E-01 -7.439402E-03 -1.561701E-01 -2.901626E-03 -1.722037E-01 -3.249117E-03 -2.729386E-01 -8.041848E-03 -4.157578E-01 -1.761081E-02 -5.608817E-01 -3.221445E-02 -7.027459E-01 -5.154772E-02 -6.902150E-01 -4.817212E-02 -5.174043E-01 -2.771951E-02 -4.297342E-01 -1.970980E-02 -2.927718E-01 -9.421566E-03 -1.860039E-01 -3.719139E-03 -1.510489E-01 -2.673423E-03 -2.992366E-01 -9.425407E-03 -4.569637E-01 -2.187717E-02 -5.810709E-01 -3.569290E-02 -6.664391E-01 -4.607395E-02 -6.898814E-01 -4.853841E-02 -5.306547E-01 -2.907467E-02 -4.138514E-01 -1.844067E-02 -2.836181E-01 -9.090950E-03 -1.827952E-01 -3.670505E-03 -1.339105E-01 -1.976730E-03 -2.247962E-01 -5.455936E-03 -3.775577E-01 -1.529613E-02 -4.605234E-01 -2.228303E-02 -5.731045E-01 -3.426291E-02 -5.698592E-01 -3.415653E-02 -4.700203E-01 -2.298571E-02 -3.419079E-01 -1.254302E-02 -2.594048E-01 -7.486049E-03 -1.403745E-01 -2.288996E-03 -1.307053E-01 -2.306039E-03 -2.305399E-01 -5.746901E-03 -2.866663E-01 -8.437990E-03 -3.547902E-01 -1.415343E-02 -3.903305E-01 -1.721878E-02 -3.995569E-01 -1.663856E-02 -3.597994E-01 -1.369907E-02 -3.084707E-01 -1.005451E-02 -1.929703E-01 -4.111212E-03 -1.226805E-01 -1.616264E-03 -9.707080E-02 -1.277801E-03 -1.349714E-01 -2.412097E-03 -1.706592E-01 -3.112630E-03 -2.431900E-01 -6.662780E-03 -2.719484E-01 -7.972869E-03 -2.782047E-01 -8.195264E-03 -2.198394E-01 -5.159833E-03 -1.847153E-01 -3.606258E-03 -1.655937E-01 -3.412468E-03 -1.132640E-01 -1.342051E-03 -6.977329E-02 -6.061071E-04 -8.063628E-02 -7.877860E-04 -1.369291E-01 -2.216310E-03 -1.527061E-01 -2.661389E-03 -1.808807E-01 -3.626051E-03 -1.723708E-01 -3.227953E-03 -1.570487E-01 -2.824199E-03 -1.402935E-01 -2.196525E-03 -1.046978E-01 -1.394771E-03 -7.765529E-02 -6.990073E-04 -5.309912E-02 -4.179704E-04 -8.113995E-02 -8.093210E-04 -1.004879E-01 -1.274755E-03 -1.474015E-01 -2.957775E-03 -1.227188E-01 -1.661445E-03 -1.367411E-01 -2.049836E-03 -1.257025E-01 -1.739859E-03 -9.595806E-02 -1.143520E-03 -5.932828E-02 -4.443026E-04 -6.214003E-02 -4.698384E-04 -1.047908E-01 -1.265030E-03 -1.389236E-01 -2.066555E-03 -1.441238E-01 -2.187643E-03 -1.954745E-01 -4.024829E-03 -2.018960E-01 -4.436820E-03 -2.304400E-01 -5.702269E-03 -1.889259E-01 -3.911134E-03 -1.651129E-01 -2.907211E-03 -1.266147E-01 -1.798632E-03 -9.726395E-02 -1.038410E-03 -1.239366E-01 -2.020884E-03 -1.692392E-01 -3.039249E-03 -2.262593E-01 -5.810761E-03 -2.371783E-01 -6.148422E-03 -2.724207E-01 -7.965467E-03 -2.754620E-01 -8.212118E-03 -2.616121E-01 -7.738784E-03 -2.416846E-01 -6.508644E-03 -1.823329E-01 -4.244589E-03 -1.153662E-01 -1.541320E-03 -1.498687E-01 -2.427094E-03 -2.294988E-01 -5.678440E-03 -2.337590E-01 -6.042902E-03 -3.165064E-01 -1.047831E-02 -3.372589E-01 -1.176332E-02 -3.369130E-01 -1.214308E-02 -3.077673E-01 -9.854791E-03 -2.727368E-01 -8.153505E-03 -2.291204E-01 -5.762201E-03 -1.449108E-01 -2.631818E-03 -1.222645E-01 -1.652033E-03 -2.342919E-01 -6.080976E-03 -2.867658E-01 -9.143890E-03 -3.284926E-01 -1.110468E-02 -3.721608E-01 -1.458209E-02 -3.943281E-01 -1.624417E-02 -3.127115E-01 -1.090060E-02 -2.181120E-01 -5.081861E-03 -2.038850E-01 -4.541180E-03 -1.471756E-01 -2.612669E-03 -1.356517E-01 -2.315498E-03 -2.039418E-01 -4.569034E-03 -2.379673E-01 -6.028728E-03 -2.912334E-01 -8.794159E-03 -3.675708E-01 -1.388797E-02 -3.830007E-01 -1.493415E-02 -3.497252E-01 -1.323190E-02 -2.129266E-01 -5.366850E-03 -2.051774E-01 -5.235913E-03 -1.495687E-01 -2.578269E-03 -1.007903E-01 -1.213029E-03 -1.942201E-01 -4.152027E-03 -2.691558E-01 -7.844599E-03 -2.833552E-01 -8.562033E-03 -3.539964E-01 -1.296456E-02 -3.313330E-01 -1.152405E-02 -2.882665E-01 -9.275609E-03 -2.606018E-01 -7.326373E-03 -2.170792E-01 -5.088581E-03 -1.175397E-01 -1.425662E-03 -9.291662E-02 -1.030694E-03 -1.502293E-01 -2.605564E-03 -1.683973E-01 -3.164858E-03 -2.300104E-01 -5.597737E-03 -2.921841E-01 -9.137452E-03 -3.105624E-01 -1.077940E-02 -2.457323E-01 -6.748662E-03 -1.935480E-01 -4.153509E-03 -1.781340E-01 -3.735545E-03 -8.549182E-02 -7.932774E-04 -7.995611E-02 -6.914994E-04 -1.120022E-01 -1.608931E-03 -1.666393E-01 -3.351392E-03 -1.763892E-01 -3.781795E-03 -2.215879E-01 -5.446848E-03 -1.973224E-01 -4.088057E-03 -1.807076E-01 -3.807788E-03 -1.497413E-01 -2.510679E-03 -1.258135E-01 -1.824079E-03 -7.256548E-02 -6.032346E-04 -5.802787E-02 -4.068274E-04 -8.087439E-02 -8.125859E-04 -9.445601E-02 -1.220157E-03 -1.278262E-01 -1.976480E-03 -1.447187E-01 -2.496284E-03 -1.492610E-01 -2.453885E-03 -1.294170E-01 -1.822523E-03 -8.046777E-02 -7.104920E-04 -8.863832E-02 -9.206404E-04 -4.044133E-02 -2.016136E-04 -3.647497E-02 -1.736207E-04 -7.726524E-02 -7.189629E-04 -6.850678E-02 -5.399094E-04 -7.120540E-02 -6.049792E-04 -9.914070E-02 -1.178916E-03 -9.212489E-02 -1.014142E-03 -8.081211E-02 -7.572737E-04 -6.454690E-02 -5.539457E-04 -4.993214E-02 -3.161361E-04 -3.464406E-02 -1.743401E-04 -5.195266E-02 -3.077352E-04 -1.032248E-01 -1.231336E-03 -1.140722E-01 -1.517037E-03 -9.270288E-02 -1.194042E-03 -1.199421E-01 -1.713870E-03 -1.129313E-01 -1.491867E-03 -1.104339E-01 -1.526039E-03 -1.080665E-01 -1.372021E-03 -8.160995E-02 -6.843931E-04 -6.342734E-02 -5.271807E-04 -9.331087E-02 -1.097048E-03 -1.185250E-01 -1.534560E-03 -1.349132E-01 -2.447610E-03 -1.304714E-01 -2.217664E-03 -1.581891E-01 -2.862519E-03 -1.584546E-01 -2.780212E-03 -1.538480E-01 -2.634437E-03 -1.637997E-01 -2.992391E-03 -1.181898E-01 -1.765232E-03 -8.541970E-02 -8.382310E-04 -9.823634E-02 -1.116285E-03 -1.486333E-01 -2.343453E-03 -1.631008E-01 -2.995222E-03 -1.755338E-01 -3.448102E-03 -1.754730E-01 -3.227041E-03 -1.842652E-01 -3.637768E-03 -1.577573E-01 -2.654428E-03 -1.401177E-01 -2.280343E-03 -1.341096E-01 -1.900302E-03 -8.035023E-02 -8.312873E-04 -1.063904E-01 -1.375093E-03 -1.216848E-01 -1.721657E-03 -2.004753E-01 -4.510521E-03 -1.889712E-01 -3.847826E-03 -2.081610E-01 -4.756630E-03 -2.301263E-01 -5.717347E-03 -2.048600E-01 -4.561616E-03 -1.542754E-01 -2.639748E-03 -1.321829E-01 -1.993402E-03 -9.014640E-02 -9.359911E-04 -7.974780E-02 -8.078227E-04 -1.252435E-01 -1.711334E-03 -1.570584E-01 -2.959866E-03 -2.039016E-01 -4.591866E-03 -2.189983E-01 -5.090456E-03 -2.191556E-01 -5.055427E-03 -2.006583E-01 -4.702936E-03 -1.427473E-01 -2.173216E-03 -1.024856E-01 -1.223983E-03 -8.494077E-02 -9.050889E-04 -1.043652E-01 -1.259550E-03 -1.135027E-01 -1.445575E-03 -1.600726E-01 -2.607556E-03 -1.831531E-01 -4.043413E-03 -2.007142E-01 -4.477475E-03 -1.767643E-01 -3.298936E-03 -1.522826E-01 -2.841107E-03 -1.288167E-01 -1.944141E-03 -1.129177E-01 -1.466746E-03 -9.166114E-02 -1.059245E-03 -7.278205E-02 -7.174163E-04 -1.368554E-01 -2.140442E-03 -1.576875E-01 -2.802493E-03 -1.490721E-01 -2.494952E-03 -2.062740E-01 -4.926381E-03 -1.707643E-01 -3.221954E-03 -1.793503E-01 -3.661578E-03 -1.255583E-01 -1.994441E-03 -1.011375E-01 -1.127338E-03 -5.944771E-02 -5.079367E-04 -6.143141E-02 -4.850205E-04 -8.747215E-02 -9.029610E-04 -1.135806E-01 -1.572457E-03 -1.258766E-01 -1.776739E-03 -1.460430E-01 -2.470050E-03 -1.449479E-01 -2.231440E-03 -1.295714E-01 -1.929423E-03 -1.137994E-01 -1.612784E-03 -8.730775E-02 -8.683726E-04 -6.186674E-02 -4.521535E-04 -4.404648E-02 -3.596329E-04 -6.609800E-02 -5.725272E-04 -8.204018E-02 -7.710094E-04 -9.063221E-02 -1.005713E-03 -9.594152E-02 -1.071929E-03 -8.648906E-02 -9.624176E-04 -6.818770E-02 -5.453348E-04 -5.887333E-02 -4.783382E-04 -6.201530E-02 -4.304358E-04 -4.838730E-02 -3.281581E-04 +2.084815E-02 +1.082750E-04 +6.381818E-02 +9.439513E-04 +1.155641E-01 +2.178751E-03 +6.865908E-02 +7.355866E-04 +6.720820E-02 +7.310529E-04 +9.537792E-02 +1.957273E-03 +1.007744E-01 +1.573169E-03 +9.409645E-02 +1.796197E-03 +7.113698E-02 +8.980335E-04 +2.405019E-02 +9.740436E-05 +6.040159E-02 +7.575405E-04 +1.050048E-01 +2.108780E-03 +1.307457E-01 +2.170448E-03 +9.988454E-02 +1.092936E-03 +1.547083E-01 +3.688477E-03 +8.157999E-02 +1.133034E-03 +1.368232E-01 +2.667957E-03 +1.444186E-01 +3.197937E-03 +1.049316E-01 +1.560309E-03 +7.358073E-02 +1.128410E-03 +4.923095E-02 +6.563588E-04 +9.650255E-02 +1.789194E-03 +1.467738E-01 +3.481509E-03 +1.687123E-01 +5.414669E-03 +1.873036E-01 +4.734353E-03 +1.130087E-01 +1.673004E-03 +1.695614E-01 +3.526426E-03 +2.591168E-01 +8.231726E-03 +1.260152E-01 +2.175978E-03 +6.288783E-02 +9.200482E-04 +8.362502E-02 +1.022521E-03 +1.456806E-01 +3.692821E-03 +1.468696E-01 +3.582954E-03 +1.848215E-01 +5.256814E-03 +2.212472E-01 +5.760540E-03 +2.169211E-01 +5.946348E-03 +1.919182E-01 +7.063068E-03 +1.588234E-01 +3.825511E-03 +1.149909E-01 +1.553531E-03 +8.539019E-02 +1.065672E-03 +1.458566E-01 +4.113559E-03 +2.049774E-01 +6.265197E-03 +2.166930E-01 +7.983860E-03 +1.757110E-01 +5.024516E-03 +2.353728E-01 +7.533032E-03 +1.280409E-01 +2.167446E-03 +1.648011E-01 +3.936025E-03 +1.599354E-01 +3.980976E-03 +1.679361E-01 +3.415565E-03 +6.849881E-02 +7.535621E-04 +8.785791E-02 +1.103156E-03 +1.709025E-01 +4.264016E-03 +1.929437E-01 +4.281538E-03 +1.711011E-01 +3.912611E-03 +1.562002E-01 +3.325900E-03 +2.153821E-01 +5.848786E-03 +1.610373E-01 +3.861192E-03 +2.389629E-01 +8.850896E-03 +1.539258E-01 +3.811869E-03 +7.844092E-02 +1.163579E-03 +2.298462E-02 +1.395953E-04 +1.570027E-01 +4.835079E-03 +1.123717E-01 +1.760314E-03 +1.821249E-01 +6.802302E-03 +2.461041E-01 +7.613043E-03 +1.904001E-01 +4.047242E-03 +2.024477E-01 +5.524067E-03 +1.167011E-01 +2.057180E-03 +8.780067E-02 +1.080238E-03 +5.397296E-02 +5.850746E-04 +5.037871E-02 +5.560040E-04 +8.289459E-02 +1.268000E-03 +1.469691E-01 +4.146173E-03 +1.075211E-01 +1.625602E-03 +2.187908E-01 +6.919967E-03 +1.278025E-01 +2.170886E-03 +9.950167E-02 +1.901085E-03 +1.104557E-01 +2.248074E-03 +1.262151E-01 +2.266348E-03 +5.580544E-02 +9.620095E-04 +5.104294E-02 +5.268938E-04 +9.139465E-02 +1.164619E-03 +7.378130E-02 +1.282188E-03 +8.021098E-02 +7.940912E-04 +1.290978E-01 +2.526036E-03 +9.365705E-02 +1.199392E-03 +6.078377E-02 +5.442247E-04 +7.556566E-02 +8.976997E-04 +6.453527E-02 +1.173497E-03 +4.302808E-02 +5.599709E-04 +3.878239E-02 +5.236943E-04 +6.099196E-02 +1.095513E-03 +9.150086E-02 +1.624380E-03 +5.728387E-02 +5.659010E-04 +9.405318E-02 +1.606034E-03 +8.619696E-02 +1.337493E-03 +1.055978E-01 +2.086153E-03 +8.890472E-02 +1.315673E-03 +6.441028E-02 +7.477974E-04 +6.069918E-02 +6.588335E-04 +1.095224E-01 +2.675022E-03 +1.096306E-01 +2.122353E-03 +1.342330E-01 +3.619967E-03 +1.114064E-01 +1.730639E-03 +1.074251E-01 +1.586218E-03 +1.408447E-01 +2.389426E-03 +1.301662E-01 +3.969782E-03 +7.949674E-02 +1.090923E-03 +1.074998E-01 +3.217694E-03 +3.528248E-02 +2.289672E-04 +9.882155E-02 +1.696404E-03 +1.354820E-01 +2.909227E-03 +1.599751E-01 +2.957031E-03 +2.280781E-01 +6.081628E-03 +2.100930E-01 +5.450110E-03 +2.732779E-01 +8.620164E-03 +1.993743E-01 +5.362856E-03 +2.198036E-01 +5.376103E-03 +1.502824E-01 +2.786908E-03 +4.996523E-02 +5.024077E-04 +1.680575E-01 +3.208887E-03 +1.422788E-01 +4.002215E-03 +1.762382E-01 +4.255455E-03 +2.502725E-01 +7.152209E-03 +3.414429E-01 +1.411003E-02 +2.636737E-01 +9.397976E-03 +2.247647E-01 +7.123896E-03 +3.224482E-01 +1.294508E-02 +1.622669E-01 +3.583977E-03 +1.248655E-01 +2.516158E-03 +6.877708E-02 +1.029829E-03 +1.976808E-01 +6.130857E-03 +3.144113E-01 +1.232063E-02 +3.018257E-01 +1.124658E-02 +2.619717E-01 +8.351589E-03 +3.672028E-01 +1.638863E-02 +3.059552E-01 +1.103037E-02 +2.486122E-01 +8.141595E-03 +1.750139E-01 +3.956566E-03 +1.436264E-01 +3.567607E-03 +1.239696E-01 +2.379611E-03 +2.163287E-01 +5.949023E-03 +2.072743E-01 +5.179000E-03 +3.646146E-01 +1.695667E-02 +3.486264E-01 +1.301568E-02 +3.563685E-01 +1.447225E-02 +2.970379E-01 +1.009480E-02 +2.762591E-01 +9.482575E-03 +2.499264E-01 +7.462884E-03 +6.344775E-02 +6.567949E-04 +1.086029E-01 +1.976496E-03 +2.603220E-01 +8.391117E-03 +2.841149E-01 +1.105366E-02 +3.965469E-01 +1.974149E-02 +3.901607E-01 +1.960621E-02 +3.509285E-01 +1.478774E-02 +2.714593E-01 +8.321432E-03 +2.293816E-01 +7.685918E-03 +1.265740E-01 +2.312172E-03 +1.103539E-01 +2.077575E-03 +1.262352E-01 +2.754572E-03 +2.213458E-01 +6.719185E-03 +3.023706E-01 +1.146381E-02 +3.282506E-01 +1.233694E-02 +2.853774E-01 +1.070129E-02 +2.848374E-01 +9.701790E-03 +3.176142E-01 +1.194832E-02 +2.880766E-01 +1.175767E-02 +1.572435E-01 +3.553858E-03 +1.501104E-01 +2.820093E-03 +1.273408E-01 +2.552547E-03 +1.499070E-01 +3.571856E-03 +2.199953E-01 +7.783541E-03 +2.453178E-01 +7.052370E-03 +2.643229E-01 +9.900690E-03 +2.574947E-01 +8.333501E-03 +2.455689E-01 +8.366273E-03 +1.782866E-01 +3.900659E-03 +1.384975E-01 +2.258716E-03 +8.944673E-02 +1.404954E-03 +5.659795E-02 +4.694852E-04 +9.581840E-02 +1.386427E-03 +2.009835E-01 +6.159157E-03 +1.897439E-01 +7.235399E-03 +1.830639E-01 +5.540521E-03 +1.520639E-01 +2.752778E-03 +2.084599E-01 +5.955188E-03 +1.319666E-01 +2.817088E-03 +1.693010E-01 +3.303866E-03 +7.800745E-02 +8.928402E-04 +4.749930E-02 +5.129237E-04 +6.919528E-02 +9.104379E-04 +1.119151E-01 +2.477462E-03 +1.102521E-01 +1.584592E-03 +1.564084E-01 +3.266574E-03 +1.198104E-01 +2.580046E-03 +1.828790E-01 +4.860390E-03 +7.542042E-02 +1.053718E-03 +1.099096E-01 +1.964225E-03 +6.193848E-02 +6.865448E-04 +5.105046E-02 +5.591936E-04 +5.609383E-02 +5.921134E-04 +9.705482E-02 +1.351531E-03 +1.601898E-01 +3.408525E-03 +1.711068E-01 +3.795257E-03 +2.205615E-01 +7.391402E-03 +1.668188E-01 +3.216331E-03 +1.359445E-01 +2.208925E-03 +9.194982E-02 +1.221828E-03 +3.090110E-02 +1.871704E-04 +1.137084E-01 +1.891251E-03 +1.350332E-01 +3.254232E-03 +1.906275E-01 +4.961645E-03 +2.657405E-01 +8.636878E-03 +3.845292E-01 +1.700936E-02 +2.839796E-01 +9.879629E-03 +2.593192E-01 +7.387676E-03 +1.606576E-01 +4.742954E-03 +1.870343E-01 +4.582302E-03 +8.524427E-02 +1.055424E-03 +1.918440E-01 +4.887813E-03 +2.109751E-01 +5.543123E-03 +2.472924E-01 +8.124732E-03 +4.210681E-01 +1.934743E-02 +3.735043E-01 +1.670088E-02 +4.705633E-01 +2.767424E-02 +4.105274E-01 +2.102523E-02 +4.139000E-01 +1.844845E-02 +2.302657E-01 +6.040845E-03 +1.013844E-01 +1.496233E-03 +1.060074E-01 +1.569679E-03 +3.421581E-01 +1.371034E-02 +4.542071E-01 +2.517473E-02 +5.784381E-01 +3.768770E-02 +4.172596E-01 +1.856012E-02 +5.299200E-01 +3.825470E-02 +5.178634E-01 +3.589903E-02 +4.185970E-01 +1.861497E-02 +2.546343E-01 +8.375242E-03 +1.304944E-01 +1.999316E-03 +1.290019E-01 +2.856345E-03 +2.844146E-01 +9.114045E-03 +4.560916E-01 +2.713184E-02 +7.260552E-01 +5.922762E-02 +7.310584E-01 +6.237152E-02 +6.478348E-01 +5.416126E-02 +4.846913E-01 +3.277993E-02 +4.849197E-01 +2.856176E-02 +2.465437E-01 +7.303148E-03 +1.744812E-01 +4.301498E-03 +1.796564E-01 +4.684076E-03 +2.812314E-01 +1.216852E-02 +4.240103E-01 +2.176819E-02 +5.209518E-01 +3.000472E-02 +6.504938E-01 +4.819256E-02 +5.990305E-01 +4.159076E-02 +5.121545E-01 +3.102991E-02 +3.470484E-01 +1.737934E-02 +2.216267E-01 +5.579967E-03 +1.708599E-01 +4.101306E-03 +1.374646E-01 +2.373831E-03 +2.399512E-01 +9.436021E-03 +4.641786E-01 +2.746647E-02 +4.258629E-01 +2.112979E-02 +6.864289E-01 +5.425243E-02 +6.579119E-01 +5.051533E-02 +4.223368E-01 +2.321407E-02 +4.058385E-01 +2.310793E-02 +2.072746E-01 +5.809548E-03 +2.339589E-01 +7.282388E-03 +9.714578E-02 +1.698684E-03 +1.688968E-01 +3.770170E-03 +2.795405E-01 +9.154147E-03 +3.109678E-01 +1.173563E-02 +3.911757E-01 +1.773775E-02 +4.374549E-01 +2.366240E-02 +4.611865E-01 +2.432741E-02 +2.516503E-01 +7.415388E-03 +1.292894E-01 +2.441647E-03 +2.226852E-01 +6.770128E-03 +8.639730E-02 +1.201841E-03 +1.449879E-01 +2.972972E-03 +1.801392E-01 +3.863618E-03 +1.936577E-01 +4.483865E-03 +2.453357E-01 +9.056291E-03 +2.480125E-01 +8.275523E-03 +2.448524E-01 +6.977697E-03 +2.436311E-01 +7.489666E-03 +2.248261E-01 +6.983599E-03 +6.717077E-02 +9.275956E-04 +4.731066E-02 +3.124630E-04 +8.581231E-02 +1.170765E-03 +2.015455E-01 +5.727404E-03 +1.747214E-01 +3.928453E-03 +1.459763E-01 +2.610376E-03 +1.928041E-01 +5.431526E-03 +1.326436E-01 +2.700926E-03 +1.950403E-01 +6.678626E-03 +1.195635E-01 +1.740482E-03 +8.319821E-02 +2.457105E-03 +5.199084E-02 +8.828006E-04 +9.589097E-02 +1.548067E-03 +1.287095E-01 +3.340920E-03 +2.500082E-01 +7.508730E-03 +1.935346E-01 +5.219674E-03 +1.617078E-01 +3.813457E-03 +1.854527E-01 +4.327935E-03 +1.469009E-01 +2.610026E-03 +1.461825E-01 +3.217211E-03 +6.828427E-02 +8.825134E-04 +1.130324E-01 +1.720356E-03 +2.114890E-01 +6.553709E-03 +1.990033E-01 +5.173772E-03 +3.695621E-01 +1.648852E-02 +3.985679E-01 +1.776400E-02 +4.317996E-01 +1.968661E-02 +4.168039E-01 +1.881861E-02 +3.168143E-01 +1.633856E-02 +1.765576E-01 +5.283407E-03 +1.593152E-01 +4.604144E-03 +1.293622E-01 +1.916729E-03 +2.979566E-01 +1.047393E-02 +3.451328E-01 +1.555073E-02 +4.833176E-01 +2.633603E-02 +5.627698E-01 +3.356380E-02 +6.205981E-01 +4.614253E-02 +5.667030E-01 +4.186377E-02 +3.633926E-01 +1.532926E-02 +1.863158E-01 +4.282436E-03 +1.141892E-01 +2.085004E-03 +1.558106E-01 +2.875549E-03 +2.977518E-01 +1.072036E-02 +6.281147E-01 +4.728417E-02 +6.712593E-01 +4.960413E-02 +1.056883E+00 +1.367649E-01 +9.587365E-01 +1.078758E-01 +7.458883E-01 +6.448193E-02 +5.376124E-01 +3.468394E-02 +3.326626E-01 +1.382728E-02 +1.715305E-01 +3.663437E-03 +1.682990E-01 +3.326460E-03 +2.809424E-01 +1.063357E-02 +3.850550E-01 +2.020363E-02 +8.686055E-01 +8.923119E-02 +1.305252E+00 +2.173314E-01 +1.246711E+00 +1.850981E-01 +8.484663E-01 +8.472718E-02 +6.548499E-01 +4.947625E-02 +2.303342E-01 +5.911752E-03 +2.386545E-01 +6.839411E-03 +1.627119E-01 +2.886284E-03 +3.438278E-01 +1.334226E-02 +4.891845E-01 +3.041285E-02 +8.909073E-01 +9.620969E-02 +1.255312E+00 +1.734311E-01 +1.169852E+00 +1.621969E-01 +9.218086E-01 +9.573599E-02 +5.068244E-01 +3.491193E-02 +3.003659E-01 +9.829990E-03 +1.957695E-01 +5.152593E-03 +1.886300E-01 +4.844638E-03 +2.305332E-01 +6.488165E-03 +4.823482E-01 +2.794296E-02 +7.462144E-01 +6.544856E-02 +9.896232E-01 +1.097631E-01 +9.014297E-01 +9.720847E-02 +6.453827E-01 +4.960136E-02 +4.680612E-01 +2.551940E-02 +2.958141E-01 +1.060228E-02 +1.573863E-01 +3.574829E-03 +1.346274E-01 +2.606991E-03 +2.151576E-01 +5.865290E-03 +3.725391E-01 +1.667519E-02 +4.869630E-01 +2.818017E-02 +6.480100E-01 +5.048920E-02 +6.074075E-01 +5.206769E-02 +4.501793E-01 +2.531848E-02 +3.790470E-01 +1.851680E-02 +2.452106E-01 +7.276116E-03 +1.402939E-01 +2.997945E-03 +1.577787E-01 +2.960256E-03 +1.659923E-01 +3.686020E-03 +2.064830E-01 +6.139283E-03 +3.154830E-01 +1.105998E-02 +4.082087E-01 +1.828447E-02 +3.712626E-01 +1.597510E-02 +3.971745E-01 +1.721238E-02 +3.019064E-01 +1.052699E-02 +1.828928E-01 +4.248902E-03 +1.233601E-01 +2.166273E-03 +8.357176E-02 +1.039130E-03 +1.492118E-01 +3.605953E-03 +1.685975E-01 +3.436440E-03 +1.741635E-01 +4.786790E-03 +1.890091E-01 +4.516094E-03 +2.283632E-01 +6.314480E-03 +2.656566E-01 +8.538973E-03 +1.402148E-01 +3.495565E-03 +8.649749E-02 +1.100158E-03 +8.813243E-02 +1.064695E-03 +4.555958E-02 +6.107386E-04 +1.309527E-01 +2.731943E-03 +1.264672E-01 +2.142006E-03 +3.000507E-01 +1.065688E-02 +3.237002E-01 +1.209173E-02 +2.307443E-01 +7.102755E-03 +1.661595E-01 +4.258378E-03 +1.386893E-01 +3.229314E-03 +8.165890E-02 +9.243538E-04 +9.523925E-02 +1.956679E-03 +1.141044E-01 +2.428038E-03 +1.740908E-01 +3.775648E-03 +1.944806E-01 +4.977204E-03 +2.742895E-01 +8.190026E-03 +4.026905E-01 +1.975388E-02 +4.110115E-01 +1.874949E-02 +2.531408E-01 +7.828810E-03 +2.295291E-01 +6.890997E-03 +2.221209E-01 +6.094039E-03 +1.321954E-01 +2.553334E-03 +1.666256E-01 +4.426400E-03 +2.171404E-01 +6.076897E-03 +3.633640E-01 +1.502241E-02 +5.792842E-01 +3.974284E-02 +6.573016E-01 +5.041895E-02 +5.370335E-01 +3.858979E-02 +6.553493E-01 +5.021005E-02 +4.574564E-01 +2.381874E-02 +3.948129E-01 +1.754777E-02 +1.514078E-01 +3.617861E-03 +1.672928E-01 +3.337911E-03 +2.716967E-01 +8.803461E-03 +5.682403E-01 +3.764689E-02 +8.144576E-01 +8.737915E-02 +1.222427E+00 +1.615304E-01 +1.406450E+00 +2.161620E-01 +9.190365E-01 +9.711802E-02 +5.724671E-01 +3.647197E-02 +3.613345E-01 +1.386290E-02 +1.868095E-01 +3.836399E-03 +2.244663E-01 +5.650733E-03 +3.340151E-01 +1.419108E-02 +5.201277E-01 +3.061828E-02 +1.212509E+00 +1.609699E-01 +4.267920E+00 +1.910806E+00 +4.227114E+00 +1.859722E+00 +1.233210E+00 +1.636276E-01 +6.793213E-01 +5.401213E-02 +3.156364E-01 +1.221711E-02 +1.862610E-01 +4.406388E-03 +2.147662E-01 +5.433421E-03 +3.138361E-01 +1.254893E-02 +6.467791E-01 +4.949991E-02 +1.292908E+00 +1.841406E-01 +4.571133E+00 +2.199170E+00 +4.304366E+00 +1.934972E+00 +1.361497E+00 +2.027947E-01 +6.505924E-01 +4.666856E-02 +3.615811E-01 +1.447718E-02 +2.447963E-01 +7.854969E-03 +1.654784E-01 +4.247475E-03 +2.649194E-01 +1.051513E-02 +6.278811E-01 +4.683999E-02 +8.592361E-01 +8.990276E-02 +1.382839E+00 +2.107838E-01 +1.135130E+00 +1.382627E-01 +9.661898E-01 +1.164265E-01 +5.142024E-01 +3.024987E-02 +2.975162E-01 +9.543763E-03 +1.876877E-01 +4.835176E-03 +1.730644E-01 +3.300158E-03 +2.265572E-01 +7.086879E-03 +4.539714E-01 +2.260730E-02 +4.526763E-01 +2.455356E-02 +8.380497E-01 +7.969257E-02 +6.097070E-01 +3.995479E-02 +6.978494E-01 +5.538934E-02 +4.583192E-01 +2.651122E-02 +2.487859E-01 +6.745574E-03 +2.135994E-01 +7.272300E-03 +2.313010E-01 +7.739556E-03 +2.374439E-01 +8.831961E-03 +2.928583E-01 +1.186840E-02 +2.940020E-01 +9.794156E-03 +4.513060E-01 +2.594396E-02 +3.408815E-01 +1.439810E-02 +3.106891E-01 +1.144803E-02 +3.403069E-01 +1.268580E-02 +1.465408E-01 +2.813252E-03 +1.367546E-01 +2.740789E-03 +1.174094E-01 +2.667947E-03 +1.443079E-01 +2.844402E-03 +9.912399E-02 +1.868517E-03 +2.216936E-01 +5.865658E-03 +2.574848E-01 +7.753799E-03 +2.423469E-01 +6.852465E-03 +2.550700E-01 +1.011995E-02 +1.640218E-01 +3.672006E-03 +1.871862E-01 +4.742433E-03 +1.058744E-01 +2.396856E-03 +7.436797E-02 +1.038777E-03 +1.410499E-01 +3.203643E-03 +9.735284E-02 +1.185189E-03 +1.816982E-01 +4.474357E-03 +2.007849E-01 +5.112077E-03 +1.416364E-01 +2.343860E-03 +2.097978E-01 +8.245740E-03 +2.159614E-01 +6.154601E-03 +2.038247E-01 +5.452430E-03 +9.120379E-02 +1.840216E-03 +1.349742E-01 +2.504188E-03 +1.795569E-01 +4.117727E-03 +2.675136E-01 +8.973198E-03 +3.044579E-01 +1.168982E-02 +3.003136E-01 +1.182153E-02 +4.441106E-01 +2.285936E-02 +3.907089E-01 +1.770627E-02 +3.345364E-01 +1.299223E-02 +1.614780E-01 +3.943314E-03 +1.518321E-01 +3.298050E-03 +1.476469E-01 +3.292917E-03 +2.898729E-01 +1.012881E-02 +3.831674E-01 +1.706626E-02 +5.444391E-01 +3.551092E-02 +5.883316E-01 +3.857351E-02 +8.055244E-01 +7.407530E-02 +5.029322E-01 +3.156083E-02 +4.112561E-01 +2.349214E-02 +2.865882E-01 +9.222808E-03 +1.315274E-01 +2.025984E-03 +1.692347E-01 +5.943449E-03 +2.561683E-01 +9.086015E-03 +6.853967E-01 +5.662300E-02 +7.696698E-01 +7.205977E-02 +1.205382E+00 +1.530951E-01 +1.516911E+00 +2.710712E-01 +6.441196E-01 +4.644860E-02 +5.631822E-01 +4.613548E-02 +4.366129E-01 +2.169977E-02 +1.360192E-01 +2.392896E-03 +2.663718E-01 +9.395499E-03 +3.537282E-01 +1.600143E-02 +7.998053E-01 +7.670496E-02 +1.124722E+00 +1.372134E-01 +4.114708E+00 +1.791984E+00 +3.713956E+00 +1.432033E+00 +1.553058E+00 +2.512378E-01 +6.135941E-01 +4.664131E-02 +2.960858E-01 +1.062685E-02 +2.126076E-01 +6.791986E-03 +1.776585E-01 +4.588826E-03 +4.009987E-01 +1.935283E-02 +6.974237E-01 +5.462807E-02 +1.172320E+00 +1.490257E-01 +4.632606E+00 +2.269726E+00 +4.302933E+00 +1.909275E+00 +1.441901E+00 +2.253633E-01 +6.946025E-01 +5.477741E-02 +3.028572E-01 +9.995543E-03 +2.664800E-01 +8.114532E-03 +1.790515E-01 +4.363179E-03 +3.219591E-01 +1.154933E-02 +4.766048E-01 +2.623379E-02 +6.590219E-01 +5.182644E-02 +1.344103E+00 +1.870469E-01 +1.520658E+00 +2.437423E-01 +8.249516E-01 +8.014323E-02 +4.799528E-01 +2.728872E-02 +3.338091E-01 +1.258397E-02 +1.726451E-01 +3.517931E-03 +1.903056E-01 +5.121011E-03 +2.235869E-01 +6.195184E-03 +4.092350E-01 +1.860896E-02 +6.443407E-01 +4.753054E-02 +7.434275E-01 +6.152443E-02 +6.963186E-01 +5.524192E-02 +7.270762E-01 +6.487099E-02 +4.104319E-01 +2.113108E-02 +2.610332E-01 +8.341277E-03 +2.276467E-01 +7.079821E-03 +1.199303E-01 +2.107276E-03 +2.344765E-01 +7.515146E-03 +2.451220E-01 +8.310971E-03 +3.329565E-01 +1.431369E-02 +4.870420E-01 +2.883252E-02 +4.388732E-01 +2.334318E-02 +2.729832E-01 +1.331202E-02 +2.744247E-01 +9.030846E-03 +1.839791E-01 +4.150617E-03 +1.213890E-01 +3.277981E-03 +1.343672E-01 +2.619580E-03 +1.130422E-01 +2.462443E-03 +1.459336E-01 +2.484655E-03 +2.470614E-01 +7.228380E-03 +3.720114E-01 +1.471500E-02 +1.858744E-01 +4.441917E-03 +1.994268E-01 +4.419502E-03 +1.569202E-01 +3.503970E-03 +1.060675E-01 +1.816154E-03 +7.163514E-02 +8.735272E-04 +1.348760E-01 +3.157312E-03 +1.387692E-01 +2.620702E-03 +1.253738E-01 +2.347752E-03 +1.537875E-01 +3.483744E-03 +2.131755E-01 +5.511261E-03 +1.743480E-01 +3.911447E-03 +2.494725E-01 +7.777487E-03 +2.239382E-01 +7.615366E-03 +1.303960E-01 +2.333665E-03 +5.381387E-02 +3.817146E-04 +1.241519E-01 +2.433480E-03 +2.044311E-01 +4.786937E-03 +2.139543E-01 +6.602658E-03 +1.648073E-01 +3.517309E-03 +2.594795E-01 +9.019644E-03 +3.528032E-01 +1.338298E-02 +3.380248E-01 +1.227721E-02 +2.624372E-01 +8.835121E-03 +1.442538E-01 +3.516238E-03 +8.640530E-02 +1.102412E-03 +2.318335E-01 +6.603252E-03 +3.742742E-01 +1.745484E-02 +5.122567E-01 +3.062512E-02 +4.337463E-01 +2.546284E-02 +5.554541E-01 +3.321204E-02 +5.067434E-01 +2.756649E-02 +4.865666E-01 +2.851594E-02 +3.170831E-01 +1.371214E-02 +2.129101E-01 +6.053342E-03 +2.128070E-01 +7.648402E-03 +1.255629E-01 +1.948581E-03 +3.102388E-01 +1.048609E-02 +5.023490E-01 +3.068085E-02 +7.297304E-01 +6.002099E-02 +7.643998E-01 +7.101610E-02 +8.513612E-01 +8.749837E-02 +6.346410E-01 +4.868689E-02 +3.918803E-01 +2.306037E-02 +3.228690E-01 +1.113733E-02 +1.888798E-01 +5.346454E-03 +2.238570E-01 +5.467591E-03 +2.966176E-01 +1.248345E-02 +5.167505E-01 +3.402812E-02 +8.408580E-01 +7.498379E-02 +1.177612E+00 +1.493796E-01 +1.213429E+00 +1.710532E-01 +7.914586E-01 +8.003283E-02 +6.569462E-01 +4.890438E-02 +4.014122E-01 +1.892526E-02 +1.741005E-01 +3.674254E-03 +1.958982E-01 +5.115746E-03 +3.647228E-01 +1.505221E-02 +5.296653E-01 +2.974185E-02 +8.741589E-01 +8.241692E-02 +1.160357E+00 +1.460044E-01 +1.242926E+00 +1.872176E-01 +7.404224E-01 +7.498948E-02 +4.157637E-01 +2.024853E-02 +3.331424E-01 +1.418197E-02 +1.662525E-01 +3.292552E-03 +1.756303E-01 +4.247818E-03 +3.095415E-01 +1.142281E-02 +4.457274E-01 +2.647548E-02 +8.198863E-01 +7.837270E-02 +8.282276E-01 +7.382650E-02 +9.034572E-01 +9.315387E-02 +6.713558E-01 +6.787067E-02 +4.095750E-01 +1.979096E-02 +4.342550E-01 +2.175150E-02 +1.322553E-01 +2.335662E-03 +7.877879E-02 +1.036092E-03 +2.712902E-01 +1.019092E-02 +3.167190E-01 +1.335793E-02 +5.158618E-01 +3.370797E-02 +5.676681E-01 +3.856145E-02 +4.544440E-01 +2.549015E-02 +4.432888E-01 +2.126301E-02 +3.161041E-01 +1.234645E-02 +2.562026E-01 +7.985736E-03 +1.563374E-01 +3.245008E-03 +8.863898E-02 +1.306731E-03 +1.548733E-01 +3.412279E-03 +3.079218E-01 +1.069274E-02 +3.174567E-01 +1.269551E-02 +3.884142E-01 +1.709017E-02 +3.349271E-01 +1.222785E-02 +3.044983E-01 +1.423699E-02 +2.903925E-01 +9.489097E-03 +1.487595E-01 +2.773453E-03 +1.494058E-01 +2.846313E-03 +4.625762E-02 +6.009114E-04 +8.974298E-02 +9.375211E-04 +1.601786E-01 +4.585595E-03 +1.785646E-01 +4.336702E-03 +2.477972E-01 +7.750073E-03 +2.297032E-01 +6.245973E-03 +1.883691E-01 +4.541820E-03 +1.590142E-01 +3.260631E-03 +1.554108E-01 +4.270743E-03 +7.224886E-02 +8.834373E-04 +9.019638E-02 +1.611295E-03 +1.303901E-01 +2.764679E-03 +1.222936E-01 +2.240408E-03 +1.581304E-01 +3.695801E-03 +1.808779E-01 +3.998170E-03 +1.889571E-01 +4.444562E-03 +1.943967E-01 +4.459891E-03 +1.426015E-01 +2.562593E-03 +9.883790E-02 +1.983226E-03 +7.007983E-02 +7.319313E-04 +1.280076E-01 +2.520103E-03 +2.289759E-01 +6.569922E-03 +2.383089E-01 +6.703841E-03 +2.643140E-01 +9.790031E-03 +2.811310E-01 +8.775540E-03 +2.387165E-01 +7.680438E-03 +2.082093E-01 +4.991376E-03 +1.666022E-01 +5.373828E-03 +1.149541E-01 +1.639607E-03 +1.220668E-01 +2.216590E-03 +1.340186E-01 +2.951310E-03 +2.402611E-01 +6.073468E-03 +2.713634E-01 +8.566663E-03 +3.660427E-01 +1.616450E-02 +3.595602E-01 +1.586479E-02 +4.709360E-01 +2.736173E-02 +3.929542E-01 +1.710164E-02 +2.484219E-01 +8.065603E-03 +1.636269E-01 +3.625941E-03 +1.083314E-01 +1.503478E-03 +1.510553E-01 +3.275953E-03 +2.604648E-01 +7.914689E-03 +4.659340E-01 +2.706966E-02 +4.604958E-01 +2.466857E-02 +6.423896E-01 +5.370929E-02 +4.993435E-01 +3.139490E-02 +4.512831E-01 +2.316067E-02 +3.742188E-01 +1.866260E-02 +2.498718E-01 +9.012857E-03 +1.514092E-01 +3.487353E-03 +1.216650E-01 +2.493133E-03 +3.141187E-01 +1.212145E-02 +3.573130E-01 +1.672769E-02 +4.548534E-01 +2.472124E-02 +6.482388E-01 +4.852353E-02 +7.058570E-01 +5.448241E-02 +6.148571E-01 +4.270398E-02 +4.455893E-01 +2.579049E-02 +3.074559E-01 +1.128795E-02 +1.589893E-01 +3.478790E-03 +1.619699E-01 +3.585731E-03 +3.432049E-01 +1.277974E-02 +3.770375E-01 +1.987838E-02 +4.941913E-01 +2.727393E-02 +7.067789E-01 +5.775428E-02 +6.507162E-01 +4.675889E-02 +4.514535E-01 +2.501083E-02 +4.060220E-01 +1.794153E-02 +2.870835E-01 +9.368435E-03 +2.032184E-01 +5.194567E-03 +1.500232E-01 +3.209360E-03 +2.247567E-01 +6.429339E-03 +4.176628E-01 +2.402640E-02 +4.329508E-01 +2.267303E-02 +6.043048E-01 +3.982372E-02 +5.849860E-01 +3.657295E-02 +3.903656E-01 +2.120434E-02 +3.543847E-01 +1.568913E-02 +2.824890E-01 +9.829374E-03 +1.446874E-01 +3.872867E-03 +9.609740E-02 +1.572744E-03 +3.043448E-01 +1.189455E-02 +3.284045E-01 +1.210523E-02 +3.703590E-01 +1.909858E-02 +3.991370E-01 +1.981940E-02 +3.532581E-01 +1.465522E-02 +3.160296E-01 +1.372436E-02 +3.333697E-01 +1.223435E-02 +2.249296E-01 +6.801086E-03 +1.628327E-01 +3.377881E-03 +7.079336E-02 +8.561171E-04 +1.105650E-01 +1.955407E-03 +1.589050E-01 +3.902915E-03 +2.414331E-01 +7.590068E-03 +2.176293E-01 +5.727003E-03 +2.726467E-01 +9.337718E-03 +1.818539E-01 +3.576974E-03 +2.180168E-01 +6.336070E-03 +1.903736E-01 +5.558784E-03 +1.433931E-01 +2.788824E-03 +8.437203E-02 +1.544760E-03 +1.159951E-01 +1.971890E-03 +1.542921E-01 +2.942637E-03 +1.798106E-01 +4.414091E-03 +2.351155E-01 +6.895402E-03 +1.878790E-01 +5.021441E-03 +1.615985E-01 +3.901096E-03 +1.133366E-01 +1.754982E-03 +8.959341E-02 +1.548148E-03 +4.455245E-02 +4.150367E-04 +9.594518E-02 +1.952932E-03 +6.555887E-02 +7.561836E-04 +1.323975E-01 +2.792090E-03 +1.823800E-01 +6.046172E-03 +1.840112E-01 +5.611376E-03 +1.405650E-01 +4.207768E-03 +9.692459E-02 +1.219361E-03 +6.977514E-02 +7.637517E-04 +5.313139E-02 +5.751260E-04 +4.631552E-02 +5.181770E-04 +9.495661E-02 +1.419966E-03 +1.200447E-01 +2.077537E-03 +1.952442E-01 +4.590395E-03 +1.471117E-01 +3.028305E-03 +1.514228E-01 +2.942798E-03 +3.062551E-01 +1.122418E-02 +1.534497E-01 +2.980148E-03 +1.773128E-01 +4.163631E-03 +1.581280E-01 +3.230054E-03 +1.026207E-01 +1.722791E-03 +9.727136E-02 +1.353541E-03 +1.833104E-01 +4.064796E-03 +1.726271E-01 +3.698889E-03 +2.777797E-01 +1.009800E-02 +2.297180E-01 +6.584276E-03 +3.227158E-01 +1.178834E-02 +2.630960E-01 +9.478703E-03 +2.057216E-01 +5.184325E-03 +1.381855E-01 +3.483987E-03 +1.207644E-01 +2.491839E-03 +1.020355E-01 +1.285191E-03 +2.413347E-01 +7.206284E-03 +1.830190E-01 +4.936379E-03 +2.466750E-01 +7.737265E-03 +3.667100E-01 +1.823639E-02 +3.886601E-01 +1.908900E-02 +3.063991E-01 +1.145076E-02 +3.179609E-01 +1.267020E-02 +2.640979E-01 +8.849372E-03 +1.324137E-01 +3.423783E-03 +1.674432E-01 +3.867189E-03 +2.387486E-01 +7.617983E-03 +2.702949E-01 +9.072068E-03 +3.509396E-01 +1.367373E-02 +4.669900E-01 +2.481995E-02 +4.539417E-01 +2.445131E-02 +2.804180E-01 +9.256761E-03 +2.204163E-01 +5.757785E-03 +1.688854E-01 +3.626841E-03 +1.799124E-01 +4.569449E-03 +1.357315E-01 +3.117868E-03 +1.939662E-01 +4.609676E-03 +1.811233E-01 +4.001677E-03 +3.023547E-01 +1.006813E-02 +3.852946E-01 +1.646521E-02 +3.947190E-01 +1.652818E-02 +3.308085E-01 +1.319117E-02 +2.203472E-01 +7.096957E-03 +2.084519E-01 +6.333576E-03 +1.446787E-01 +3.971664E-03 +8.614610E-02 +1.069819E-03 +2.193677E-01 +8.326726E-03 +2.076369E-01 +4.682464E-03 +1.696243E-01 +3.956462E-03 +3.992762E-01 +1.931929E-02 +3.307711E-01 +1.232965E-02 +2.639926E-01 +8.553712E-03 +2.907994E-01 +1.195800E-02 +2.069794E-01 +4.706478E-03 +9.533912E-02 +1.278173E-03 +1.053247E-01 +1.903155E-03 +1.837208E-01 +5.173191E-03 +1.636891E-01 +4.284691E-03 +2.284680E-01 +8.035892E-03 +2.300168E-01 +5.784482E-03 +2.519821E-01 +8.684849E-03 +2.271669E-01 +6.331342E-03 +2.491848E-01 +7.449392E-03 +2.027002E-01 +4.880471E-03 +9.012995E-02 +1.564717E-03 +9.958124E-02 +1.614296E-03 +1.735102E-01 +5.642665E-03 +1.785074E-01 +4.132173E-03 +1.933132E-01 +5.239277E-03 +2.139676E-01 +6.356521E-03 +2.015977E-01 +5.099277E-03 +2.039189E-01 +7.545412E-03 +2.075736E-01 +7.064068E-03 +1.061529E-01 +1.352122E-03 +3.214966E-02 +1.717861E-04 +3.339740E-02 +2.480850E-04 +1.110320E-01 +2.164188E-03 +9.636462E-02 +1.094431E-03 +1.497850E-01 +5.420438E-03 +1.496108E-01 +2.948765E-03 +1.408888E-01 +2.897433E-03 +1.338729E-01 +2.922319E-03 +5.711633E-02 +4.306501E-04 +7.981911E-02 +8.325283E-04 +5.180954E-02 +5.871992E-04 +3.142337E-02 +2.743459E-04 +7.558078E-02 +1.440107E-03 +6.749596E-02 +7.121686E-04 +4.742528E-02 +3.421264E-04 +1.152645E-01 +2.543824E-03 +1.034826E-01 +1.553063E-03 +7.780836E-02 +1.674226E-03 +2.486040E-02 +1.152553E-04 +5.118031E-02 +4.782731E-04 +6.164448E-02 +1.090465E-03 +5.579780E-02 +5.469202E-04 +9.835519E-02 +1.561650E-03 +1.590188E-01 +3.559315E-03 +9.123141E-02 +1.186111E-03 +9.257051E-02 +1.160366E-03 +1.595071E-01 +3.372622E-03 +8.648914E-02 +1.391423E-03 +9.915992E-02 +1.496092E-03 +6.159336E-02 +7.871872E-04 +7.703115E-02 +8.995936E-04 +8.644781E-02 +1.794389E-03 +8.281040E-02 +1.022772E-03 +1.198087E-01 +2.578187E-03 +1.046543E-01 +2.073804E-03 +1.485974E-01 +3.372341E-03 +1.899240E-01 +5.053348E-03 +1.495518E-01 +3.346868E-03 +1.523611E-01 +2.626194E-03 +1.483976E-01 +3.461823E-03 +1.189640E-01 +2.194057E-03 +7.910820E-02 +1.021972E-03 +1.408445E-01 +2.513931E-03 +1.785598E-01 +6.539443E-03 +1.627058E-01 +4.133768E-03 +1.417975E-01 +2.575062E-03 +1.453104E-01 +3.242010E-03 +1.545322E-01 +2.888223E-03 +2.238452E-01 +8.182427E-03 +1.208627E-01 +2.044210E-03 +8.317750E-02 +1.508722E-03 +9.945978E-02 +1.606528E-03 +1.100115E-01 +1.679926E-03 +1.682495E-01 +3.387004E-03 +2.038347E-01 +5.001616E-03 +1.661126E-01 +3.716273E-03 +1.719126E-01 +4.353756E-03 +2.127676E-01 +7.068298E-03 +1.596044E-01 +3.435511E-03 +9.171613E-02 +1.258097E-03 +7.909923E-02 +1.167334E-03 +8.070294E-02 +1.198068E-03 +9.480490E-02 +1.184376E-03 +1.091868E-01 +1.673174E-03 +1.686522E-01 +3.814685E-03 +2.045902E-01 +4.997184E-03 +2.218509E-01 +5.932778E-03 +2.568657E-01 +9.334526E-03 +1.632220E-01 +4.266101E-03 +8.403406E-02 +1.398023E-03 +8.197852E-02 +9.887532E-04 +7.879086E-02 +1.433937E-03 +1.228523E-01 +2.416939E-03 +1.862098E-01 +4.308366E-03 +2.142186E-01 +8.247066E-03 +2.268010E-01 +6.502538E-03 +1.402457E-01 +2.618558E-03 +1.260213E-01 +2.059778E-03 +1.505995E-01 +2.876582E-03 +5.116714E-02 +3.766772E-04 +1.268702E-01 +2.695645E-03 +5.638152E-02 +5.767254E-04 +1.619056E-01 +3.154405E-03 +2.354666E-01 +1.065017E-02 +1.278153E-01 +2.300850E-03 +1.582320E-01 +3.193514E-03 +1.851274E-01 +5.144918E-03 +1.462501E-01 +3.549186E-03 +1.385494E-01 +3.784085E-03 +6.277077E-02 +8.146319E-04 +7.619565E-02 +1.435724E-03 +1.261746E-01 +3.287745E-03 +5.858084E-02 +5.268907E-04 +1.326578E-01 +2.611109E-03 +1.378942E-01 +2.421025E-03 +1.281363E-01 +1.960588E-03 +1.071155E-01 +1.748974E-03 +1.014830E-01 +1.540688E-03 +1.167308E-01 +3.039772E-03 +8.499870E-02 +1.048605E-03 +5.967367E-02 +1.011919E-03 +6.384520E-02 +1.050476E-03 +5.379547E-02 +4.842685E-04 +9.714870E-02 +1.167567E-03 +1.193232E-01 +2.711280E-03 +6.956983E-02 +7.545215E-04 +1.085462E-01 +2.036623E-03 +6.352672E-02 +7.273361E-04 +3.554724E-02 +4.034308E-04 +1.147332E-01 +3.617311E-03 +8.657826E-02 +1.515787E-03 tally 2: -2.393627E-03 -2.636290E-06 -2.222156E-03 -1.516148E-06 -2.867439E-03 -2.178580E-06 -7.923009E-03 -1.131939E-05 -3.986634E-03 -4.120137E-06 -7.826419E-03 -1.381669E-05 -6.138176E-03 -7.147428E-06 -3.876880E-03 -2.697208E-06 -2.980562E-03 -3.407321E-06 -1.774473E-03 -8.936196E-07 -2.805366E-03 -2.770194E-06 -3.942385E-03 -3.541964E-06 -4.287920E-03 -3.508749E-06 -7.477034E-03 -1.023581E-05 -1.829256E-03 -9.746709E-07 -5.062973E-03 -5.540060E-06 -4.594275E-03 -5.704022E-06 -3.405515E-03 -3.312460E-06 -9.423220E-03 -1.189576E-05 -1.066888E-02 -2.047020E-05 -7.596120E-03 -1.097485E-05 -5.727684E-03 -9.708804E-06 -4.299383E-03 -3.708395E-06 -9.513211E-03 -1.464618E-05 -5.378401E-03 -5.129879E-06 -5.096252E-03 -3.430859E-06 -7.146855E-03 -1.124612E-05 -6.572738E-03 -7.596525E-06 -7.380131E-03 -9.633384E-06 -6.219137E-03 -8.163623E-06 -6.908868E-03 -8.615668E-06 -7.350963E-03 -1.116403E-05 -5.438361E-03 -6.022683E-06 -4.233493E-03 -5.102016E-06 -9.383252E-03 -1.536263E-05 -1.199002E-02 -2.034238E-05 -7.934135E-03 -8.959239E-06 -8.511914E-03 -1.022394E-05 -6.162682E-03 -4.504202E-06 -6.648149E-03 -5.723838E-06 -7.264317E-03 -8.981506E-06 -1.037779E-02 -1.703942E-05 -4.759363E-03 -3.403173E-06 -9.522407E-03 -1.428157E-05 -7.387030E-03 -1.550312E-05 -4.844392E-03 -8.366311E-06 -6.843631E-03 -8.685895E-06 -7.764489E-03 -8.325268E-06 -5.854513E-03 -5.702341E-06 -7.087671E-03 -1.025951E-05 -2.415844E-03 -2.739481E-06 -3.086207E-03 -1.914733E-06 -3.654957E-03 -3.442162E-06 -4.643653E-03 -7.197439E-06 -1.156734E-02 -1.759634E-05 -7.348653E-03 -9.450024E-06 -7.852217E-03 -9.889996E-06 -4.188787E-03 -2.746400E-06 -4.526053E-03 -3.421811E-06 -7.133876E-03 -5.514540E-06 -7.642743E-03 -1.296144E-05 -3.436567E-03 -5.211995E-06 -2.358938E-03 -1.100467E-06 -4.225043E-03 -3.484328E-06 -6.975938E-03 -1.402542E-05 -2.948552E-03 -2.413285E-06 -7.430097E-03 -9.911242E-06 -9.344383E-03 -1.730038E-05 -5.155130E-03 -4.067305E-06 -9.223392E-03 -1.460017E-05 -6.706254E-03 -1.105767E-05 -6.585388E-03 -9.369522E-06 -5.779745E-03 -9.335364E-06 -8.502853E-03 -1.535431E-05 -3.196086E-03 -2.721454E-06 -4.062636E-03 -4.530161E-06 -4.949408E-03 -4.754719E-06 -8.697214E-03 -1.269695E-05 -7.720575E-03 -1.111572E-05 -9.096811E-03 -1.174536E-05 -8.395332E-03 -1.344990E-05 -4.327467E-03 -4.178301E-06 -8.098133E-03 -2.129072E-05 -8.641159E-03 -1.993637E-05 -4.910339E-03 -4.798040E-06 -9.222729E-03 -1.731644E-05 -2.362293E-03 -1.920887E-06 -6.474215E-03 -7.989801E-06 -5.093903E-03 -4.638782E-06 -5.190870E-03 -4.064962E-06 -9.156062E-03 -1.062935E-05 -8.084833E-03 -1.278518E-05 -6.006837E-03 -5.037849E-06 -2.770574E-03 -1.880169E-06 -8.452309E-03 -1.160057E-05 -3.397900E-03 -2.727237E-06 -2.289237E-03 -1.800828E-06 -4.695731E-03 -3.765699E-06 -4.924545E-03 -5.339278E-06 -3.924491E-03 -3.534032E-06 -5.847744E-03 -5.832921E-06 -5.289218E-03 -4.574845E-06 -6.846305E-03 -7.758157E-06 -1.047199E-02 -2.215876E-05 -4.108674E-03 -4.661482E-06 -3.645438E-03 -3.482466E-06 -7.403892E-03 -9.076272E-06 -9.992980E-03 -1.850054E-05 -5.443023E-03 -6.695689E-06 -3.847833E-03 -4.206098E-06 -2.277807E-03 -2.917797E-06 -3.224646E-03 -2.590833E-06 -2.712146E-03 -1.564363E-06 -2.511703E-03 -2.073210E-06 -2.851624E-03 -2.406321E-06 -6.419364E-03 -8.208048E-06 -3.583974E-03 -2.129485E-06 -4.071264E-03 -3.984855E-06 -4.533579E-03 -3.713304E-06 -4.578848E-03 -5.079242E-06 -5.611098E-03 -6.817450E-06 -5.466353E-03 -4.988832E-06 -6.854470E-03 -7.459449E-06 -1.157268E-02 -2.134366E-05 -7.273077E-03 -9.732982E-06 -8.349702E-03 -1.250149E-05 -5.050822E-03 -6.018695E-06 -2.514025E-03 -1.130420E-06 -3.427587E-03 -3.225038E-06 -3.873162E-03 -2.996903E-06 -7.323374E-03 -8.254236E-06 -6.098103E-03 -7.253404E-06 -6.739636E-03 -8.349945E-06 -9.485072E-03 -1.713563E-05 -5.984992E-03 -9.163531E-06 -8.834991E-03 -1.335810E-05 -4.066934E-03 -3.579803E-06 -1.652658E-02 -4.834880E-05 -7.000637E-03 -1.069231E-05 -7.937972E-03 -1.290117E-05 -3.766475E-03 -2.867345E-06 -2.461271E-03 -1.788656E-06 -7.788544E-03 -1.121555E-05 -9.541095E-03 -2.231145E-05 -7.679962E-03 -9.840343E-06 -5.742139E-03 -4.940156E-06 -5.062263E-03 -4.779159E-06 -1.289208E-02 -2.955604E-05 -1.544740E-02 -3.866639E-05 -1.954402E-02 -4.721734E-05 -9.149250E-03 -1.133509E-05 -1.090073E-02 -2.153530E-05 -4.758115E-03 -3.459784E-06 -6.236554E-03 -7.454691E-06 -1.032788E-02 -1.596371E-05 -1.444275E-02 -3.574908E-05 -6.464816E-03 -6.384836E-06 -8.737589E-03 -1.139821E-05 -1.522241E-02 -3.688054E-05 -1.106278E-02 -2.001640E-05 -1.657751E-03 -7.896422E-07 -9.985083E-03 -2.005574E-05 -1.652296E-02 -4.365058E-05 -1.302377E-02 -2.178742E-05 -9.435666E-03 -1.687352E-05 -6.711506E-03 -6.885294E-06 -1.142166E-02 -1.609449E-05 -1.419856E-02 -2.849773E-05 -8.442366E-03 -1.011801E-05 -1.071637E-02 -1.610076E-05 -4.476911E-03 -3.961715E-06 -7.809454E-03 -1.419144E-05 -1.181657E-02 -2.104822E-05 -1.373873E-02 -2.251824E-05 -8.797909E-03 -9.748724E-06 -1.504789E-02 -4.195617E-05 -7.006137E-03 -6.669697E-06 -9.537389E-03 -1.849189E-05 -1.780900E-02 -4.302041E-05 -1.724591E-02 -3.993250E-05 -9.881865E-03 -1.435848E-05 -1.212976E-02 -2.281306E-05 -1.155598E-02 -2.437179E-05 -1.323280E-02 -2.884432E-05 -8.626223E-03 -1.632385E-05 -8.459408E-03 -1.577691E-05 -5.796477E-03 -8.302775E-06 -7.329870E-03 -9.181815E-06 -5.899442E-03 -9.585863E-06 -3.270135E-03 -2.283602E-06 -1.256169E-02 -2.107461E-05 -1.234423E-02 -1.770300E-05 -7.478528E-03 -9.995232E-06 -9.809248E-03 -1.705587E-05 -1.508701E-02 -4.933892E-05 -9.484511E-03 -1.383716E-05 -9.906783E-03 -1.637085E-05 -1.682365E-02 -3.925758E-05 -1.258622E-02 -2.571505E-05 -1.501752E-02 -3.834255E-05 -8.820664E-03 -1.146570E-05 -9.142316E-03 -1.367354E-05 -1.607994E-02 -3.440957E-05 -1.819921E-02 -4.213322E-05 -1.049376E-02 -1.508696E-05 -1.125487E-02 -1.829361E-05 -1.255946E-02 -2.400912E-05 -1.494753E-02 -2.880665E-05 -9.906163E-03 -1.714469E-05 -9.801065E-03 -1.600484E-05 -9.144471E-03 -1.267827E-05 -9.284445E-03 -1.370415E-05 -7.423687E-03 -7.432654E-06 -5.839529E-03 -7.346711E-06 -1.203215E-02 -1.827698E-05 -1.168395E-02 -2.279351E-05 -8.086186E-03 -1.615505E-05 -7.899387E-03 -1.190799E-05 -1.297481E-02 -2.625448E-05 -1.012733E-02 -1.604797E-05 -7.655395E-03 -8.264047E-06 -6.482761E-03 -7.546581E-06 -9.071892E-03 -1.344566E-05 -1.012199E-02 -1.652283E-05 -9.504897E-03 -1.476924E-05 -5.662581E-03 -5.323904E-06 -7.382282E-03 -1.000786E-05 -6.180783E-03 -7.844120E-06 -2.197420E-03 -1.391522E-06 -6.007425E-03 -7.959122E-06 -7.715644E-03 -1.608319E-05 -5.247749E-03 -7.416762E-06 -1.694277E-03 -6.578326E-07 -5.339576E-03 -5.097832E-06 -6.019786E-03 -5.618274E-06 -4.786336E-03 -7.186037E-06 -6.122950E-03 -5.610674E-06 -8.057029E-03 -1.204366E-05 -6.301473E-03 -6.965375E-06 -4.120695E-03 -3.695383E-06 -5.874479E-03 -6.599197E-06 -6.691277E-03 -7.819406E-06 -5.109849E-03 -6.563614E-06 -8.391296E-03 -9.940452E-06 -5.839507E-03 -5.521558E-06 -4.596793E-03 -4.130860E-06 -5.374245E-03 -1.030905E-05 -1.632711E-03 -8.301397E-07 -3.126223E-03 -2.656593E-06 -3.937711E-03 -3.000478E-06 -1.156184E-02 -2.627381E-05 -5.611109E-03 -6.000471E-06 -6.252306E-03 -8.525688E-06 -9.821256E-03 -2.080867E-05 -6.202478E-03 -9.705719E-06 -9.744072E-03 -1.419879E-05 -4.563774E-03 -5.256907E-06 -8.587477E-03 -1.097640E-05 -7.671018E-03 -1.047414E-05 -7.311535E-03 -8.520205E-06 -5.701036E-03 -7.538301E-06 -2.627195E-03 -1.584039E-06 -9.969461E-03 -1.489942E-05 -7.095469E-03 -8.576195E-06 -1.168498E-02 -2.716853E-05 -1.070319E-02 -2.148367E-05 -1.016441E-02 -1.786630E-05 -1.292596E-02 -2.389182E-05 -1.217737E-02 -2.769412E-05 -1.181009E-02 -2.340802E-05 -1.574105E-02 -3.124980E-05 -1.232805E-02 -2.754960E-05 -1.188839E-02 -2.281613E-05 -6.603428E-03 -7.994872E-06 -9.606012E-03 -1.590439E-05 -1.440947E-02 -3.393244E-05 -1.302185E-02 -2.781063E-05 -1.299900E-02 -2.077190E-05 -9.475720E-03 -1.345778E-05 -1.146355E-02 -2.243784E-05 -1.349840E-02 -2.573754E-05 -7.739444E-03 -8.409802E-06 -1.466716E-02 -2.433264E-05 -1.806287E-02 -4.053139E-05 -8.810509E-03 -1.132204E-05 -1.024195E-02 -1.779935E-05 -2.025420E-02 -5.383414E-05 -1.707065E-02 -3.895805E-05 -1.038874E-02 -1.447558E-05 -1.204454E-02 -2.594328E-05 -1.354337E-02 -2.168067E-05 -1.483635E-02 -2.755558E-05 -1.192445E-02 -3.329659E-05 -2.158708E-02 -6.668840E-05 -1.234119E-02 -2.669020E-05 -1.410581E-02 -3.302957E-05 -8.354805E-03 -9.152126E-06 -9.135582E-03 -1.272798E-05 -1.639890E-02 -3.260235E-05 -1.941356E-02 -4.768472E-05 -9.432927E-03 -1.518984E-05 -8.177517E-03 -1.165366E-05 -9.416129E-03 -1.296249E-05 -8.128386E-03 -8.608672E-06 -1.105831E-02 -1.814734E-05 -1.401062E-02 -3.340952E-05 -1.142672E-02 -2.129460E-05 -9.161476E-03 -1.306319E-05 -9.794446E-03 -1.416201E-05 -9.135097E-03 -1.706236E-05 -1.853399E-02 -3.920131E-05 -1.227701E-02 -2.106422E-05 -1.056602E-02 -2.102108E-05 -8.267866E-03 -1.184427E-05 -1.303652E-02 -3.007847E-05 -1.109107E-02 -1.508434E-05 -1.255273E-02 -3.715445E-05 -1.568071E-02 -3.587957E-05 -1.697298E-02 -4.299097E-05 -2.038316E-02 -6.095075E-05 -1.285306E-02 -2.307142E-05 -1.201762E-02 -3.129200E-05 -1.499546E-02 -3.208959E-05 -2.043263E-02 -5.689094E-05 -1.189038E-02 -2.042718E-05 -1.950482E-02 -5.269872E-05 -1.134487E-02 -2.521302E-05 -1.878263E-02 -4.929885E-05 -1.873654E-02 -5.934321E-05 -1.419859E-02 -2.646755E-05 -1.651980E-02 -4.148598E-05 -1.314908E-02 -2.182046E-05 -1.021903E-02 -1.717431E-05 -1.208532E-02 -2.496385E-05 -1.982124E-02 -4.519007E-05 -2.237475E-02 -7.384327E-05 -1.168783E-02 -2.197925E-05 -1.121917E-02 -1.848105E-05 -1.176886E-02 -1.989856E-05 -1.028612E-02 -2.002048E-05 -6.441121E-03 -1.208678E-05 -9.334858E-03 -1.685718E-05 -1.221526E-02 -2.734816E-05 -8.109247E-03 -1.518336E-05 -8.368313E-03 -1.063729E-05 -8.855930E-03 -1.170749E-05 -1.172890E-02 -1.956774E-05 -9.863812E-03 -1.315788E-05 -5.592525E-03 -6.344568E-06 -8.987555E-03 -2.234382E-05 -3.266822E-03 -2.479505E-06 -6.189326E-03 -8.824564E-06 -5.844977E-03 -5.169490E-06 -7.046630E-03 -1.052376E-05 -6.579857E-03 -8.415446E-06 -1.093757E-02 -1.570418E-05 -1.534199E-03 -4.843955E-07 -3.972367E-03 -3.930212E-06 -9.061215E-03 -1.261741E-05 -8.800538E-03 -1.921110E-05 -3.225443E-03 -3.493463E-06 -5.742921E-03 -7.524467E-06 -8.894549E-03 -9.527470E-06 -1.014672E-02 -2.120305E-05 -5.364672E-03 -6.378322E-06 -1.066153E-02 -1.712472E-05 -6.130226E-03 -6.243703E-06 -4.018022E-03 -2.930167E-06 -4.956188E-03 -4.356249E-06 -6.252583E-03 -6.885470E-06 -8.007253E-03 -8.821722E-06 -6.639119E-03 -8.933356E-06 -1.463344E-02 -3.442332E-05 -1.038024E-02 -1.880148E-05 -1.206043E-02 -2.558498E-05 -4.570005E-03 -3.726957E-06 -1.242332E-02 -2.230997E-05 -1.977578E-02 -4.435986E-05 -1.061292E-02 -2.445701E-05 -1.424423E-02 -3.432092E-05 -9.396166E-03 -1.401917E-05 -1.392713E-02 -2.180224E-05 -1.424206E-02 -2.481086E-05 -1.709208E-02 -4.686642E-05 -1.878028E-02 -4.097819E-05 -1.586170E-02 -3.899306E-05 -1.186469E-02 -2.666019E-05 -1.771802E-02 -4.244451E-05 -2.012793E-02 -4.893656E-05 -1.650347E-02 -3.934790E-05 -1.148512E-02 -1.454575E-05 -1.749383E-02 -5.245021E-05 -1.225617E-02 -3.059339E-05 -1.346221E-02 -2.189743E-05 -2.304004E-02 -5.757458E-05 -2.222990E-02 -5.924120E-05 -1.952055E-02 -4.455112E-05 -2.382543E-02 -8.732633E-05 -1.530886E-02 -4.091608E-05 -1.339459E-02 -2.841021E-05 -1.625542E-02 -3.786269E-05 -2.338447E-02 -6.870429E-05 -1.490538E-02 -3.792400E-05 -1.790848E-02 -4.535348E-05 -1.122685E-02 -2.253480E-05 -1.330235E-02 -2.292380E-05 -2.135308E-02 -5.586248E-05 -1.695542E-02 -3.629907E-05 -1.155426E-02 -1.914452E-05 -1.571691E-02 -3.489736E-05 -1.572803E-02 -4.611373E-05 -1.284552E-02 -2.456383E-05 -1.901269E-02 -4.808607E-05 -2.485036E-02 -8.880235E-05 -1.465112E-02 -3.185430E-05 -2.020800E-02 -4.881856E-05 -1.401589E-02 -2.430294E-05 -9.002706E-03 -1.229314E-05 -1.992235E-02 -4.240852E-05 -2.006701E-02 -4.842321E-05 -1.641971E-02 -4.817406E-05 -1.595751E-02 -4.338042E-05 -1.853727E-02 -4.393578E-05 -2.192942E-02 -6.739913E-05 -1.867919E-02 -5.139172E-05 -2.177355E-02 -5.751645E-05 -1.184805E-02 -2.240654E-05 -2.099274E-02 -5.999346E-05 -1.322643E-02 -2.131002E-05 -1.656305E-02 -4.169252E-05 -2.381731E-02 -9.074804E-05 -2.704019E-02 -1.044920E-04 -1.801171E-02 -4.035920E-05 -1.967092E-02 -5.363932E-05 -1.168953E-02 -1.754128E-05 -1.832249E-02 -3.962019E-05 -1.704595E-02 -3.468261E-05 -1.265896E-02 -2.389931E-05 -1.393723E-02 -3.209713E-05 -1.201908E-02 -2.196652E-05 -1.121588E-02 -1.970440E-05 -1.427491E-02 -2.765834E-05 -2.153384E-02 -5.860763E-05 -1.776842E-02 -3.609550E-05 -7.672472E-03 -1.269710E-05 -1.265904E-02 -2.534380E-05 -1.278354E-02 -2.508897E-05 -1.391779E-02 -4.666810E-05 -2.101476E-02 -6.314023E-05 -1.153450E-02 -1.634642E-05 -7.257174E-03 -7.518882E-06 -1.927707E-02 -5.477085E-05 -9.781524E-03 -2.152387E-05 -9.945925E-03 -2.025565E-05 -1.389600E-02 -2.298270E-05 -1.494296E-02 -3.352071E-05 -1.367151E-02 -2.896436E-05 -1.028864E-02 -1.588654E-05 -1.473101E-02 -2.707095E-05 -1.455944E-02 -2.781560E-05 -9.476864E-03 -1.561347E-05 -1.102794E-02 -1.772767E-05 -9.572498E-03 -1.064449E-05 -1.064989E-02 -1.750406E-05 -6.954816E-03 -6.367916E-06 -7.557762E-03 -9.032801E-06 -1.211805E-02 -1.920718E-05 -1.845178E-02 -5.873218E-05 -7.793790E-03 -1.112683E-05 -5.371627E-03 -5.960823E-06 -1.235046E-02 -2.103259E-05 -9.750089E-03 -1.543672E-05 -8.995748E-03 -1.080595E-05 -5.259436E-03 -1.260414E-05 -4.013446E-03 -6.247425E-06 -8.493091E-03 -1.154191E-05 -8.658736E-03 -1.173196E-05 -5.707568E-03 -4.449143E-06 -6.897118E-03 -1.114446E-05 -1.178625E-02 -1.974305E-05 -9.315402E-03 -1.290580E-05 -8.406166E-03 -1.025434E-05 -9.901055E-03 -1.667960E-05 -1.146925E-02 -2.215717E-05 -5.969641E-03 -6.447141E-06 -5.949865E-03 -8.960001E-06 -6.092588E-03 -5.866966E-06 -5.286804E-03 -4.484612E-06 -4.962451E-03 -8.039594E-06 -9.068920E-03 -1.020218E-05 -8.393955E-03 -1.320876E-05 -9.622928E-03 -1.423650E-05 -8.529527E-03 -9.768501E-06 -1.200903E-02 -2.384159E-05 -1.259390E-02 -2.566463E-05 -1.039659E-02 -1.406860E-05 -1.729423E-02 -3.541882E-05 -1.557253E-02 -3.014897E-05 -1.194539E-02 -2.560525E-05 -9.677750E-03 -1.383701E-05 -1.167374E-02 -1.893076E-05 -1.273338E-02 -2.292756E-05 -1.535190E-02 -3.729267E-05 -1.508233E-02 -2.812628E-05 -1.684483E-02 -3.431291E-05 -2.196642E-02 -6.517979E-05 -1.835655E-02 -4.270904E-05 -1.427403E-02 -2.810685E-05 -1.296891E-02 -3.425248E-05 -1.678523E-02 -5.402550E-05 -1.824967E-02 -5.634714E-05 -1.959838E-02 -4.878209E-05 -1.406357E-02 -2.175952E-05 -1.401524E-02 -2.275436E-05 -1.788740E-02 -3.919852E-05 -1.598923E-02 -2.974737E-05 -1.525101E-02 -3.383079E-05 -2.077298E-02 -5.733559E-05 -1.623945E-02 -5.546589E-05 -1.233338E-02 -2.483742E-05 -2.022717E-02 -5.714772E-05 -2.102155E-02 -5.635658E-05 -2.171802E-02 -5.725283E-05 -2.133014E-02 -5.962681E-05 -1.179614E-02 -2.066294E-05 -1.970629E-02 -4.561315E-05 -2.645275E-02 -9.399736E-05 -2.354050E-02 -6.803919E-05 -1.525552E-02 -2.858970E-05 -2.070256E-02 -5.101418E-05 -1.947053E-02 -4.695688E-05 -2.302697E-02 -7.365548E-05 -1.913354E-02 -4.496174E-05 -2.105937E-02 -5.760147E-05 -1.965231E-02 -4.417453E-05 -1.995841E-02 -5.444455E-05 -1.084572E-02 -1.610270E-05 -1.332954E-02 -2.257737E-05 -2.183162E-02 -5.722081E-05 -2.309396E-02 -6.057606E-05 -9.499018E-03 -1.386623E-05 -1.726231E-02 -3.538973E-05 -1.918548E-02 -5.089001E-05 -1.973649E-02 -5.391374E-05 -1.451999E-02 -3.154997E-05 -1.853969E-02 -4.789122E-05 -1.931149E-02 -4.543759E-05 -1.524463E-02 -3.367646E-05 -1.366351E-02 -2.193771E-05 -1.277601E-02 -2.556554E-05 -2.419813E-02 -6.652057E-05 -2.472332E-02 -7.514840E-05 -1.216343E-02 -1.994778E-05 -1.684175E-02 -4.956582E-05 -1.339179E-02 -2.283730E-05 -1.780869E-02 -4.714950E-05 -1.281070E-02 -3.243018E-05 -1.377308E-02 -3.117101E-05 -5.215885E-03 -4.980057E-06 -8.389167E-03 -9.063809E-06 -9.223056E-03 -1.174158E-05 -1.034179E-02 -1.248975E-05 -1.925913E-02 -6.207101E-05 -1.950035E-02 -4.864558E-05 -7.340878E-03 -8.419462E-06 -1.607559E-02 -3.378180E-05 -1.350363E-02 -2.299601E-05 -1.775362E-02 -4.047509E-05 -9.317817E-03 -1.104227E-05 -1.531705E-02 -4.269706E-05 -1.565342E-02 -3.305222E-05 -1.391485E-02 -2.938257E-05 -1.313236E-02 -2.426377E-05 -1.070285E-02 -1.778239E-05 -1.570769E-02 -2.778648E-05 -1.722250E-02 -3.454670E-05 -1.045335E-02 -1.595923E-05 -9.750797E-03 -1.489157E-05 -8.756572E-03 -1.522794E-05 -1.314662E-02 -2.457130E-05 -1.370416E-02 -3.418084E-05 -1.098248E-02 -2.064375E-05 -9.200090E-03 -1.182484E-05 -1.567874E-02 -3.315221E-05 -6.763240E-03 -8.877038E-06 -8.410342E-03 -8.599497E-06 -1.335894E-02 -2.549323E-05 -1.565848E-02 -3.152726E-05 -4.913273E-03 -5.986876E-06 -9.624242E-03 -1.314215E-05 -7.547191E-03 -9.843029E-06 -9.081341E-03 -1.527721E-05 -5.698591E-03 -6.688189E-06 -9.964477E-03 -1.260472E-05 -9.144787E-03 -1.380216E-05 -2.922066E-03 -3.175247E-06 -6.106620E-03 -6.365824E-06 -4.141014E-03 -5.277155E-06 -1.500883E-02 -2.794044E-05 -1.313811E-02 -2.817445E-05 -5.537395E-03 -6.121500E-06 -6.214355E-03 -7.107250E-06 -9.970886E-03 -1.328943E-05 -1.158117E-02 -2.364707E-05 -8.759169E-03 -1.211573E-05 -1.307338E-02 -2.576745E-05 -6.194517E-03 -9.257741E-06 -8.087970E-03 -1.366458E-05 -8.727779E-03 -1.125895E-05 -7.481614E-03 -9.784879E-06 -7.811272E-03 -1.168412E-05 -7.288542E-03 -8.415727E-06 -1.395237E-02 -3.211289E-05 -1.345304E-02 -2.404425E-05 -1.075854E-02 -1.527000E-05 -9.524531E-03 -1.516407E-05 -1.703097E-02 -3.823359E-05 -1.787871E-02 -5.611642E-05 -1.180236E-02 -1.719343E-05 -1.146997E-02 -2.095613E-05 -1.152446E-02 -1.653464E-05 -1.398187E-02 -2.396242E-05 -1.526339E-02 -3.893414E-05 -1.206190E-02 -2.128747E-05 -1.578188E-02 -3.704679E-05 -1.775426E-02 -3.663474E-05 -1.962916E-02 -5.493244E-05 -1.511991E-02 -3.404611E-05 -1.133202E-02 -2.452193E-05 -1.623663E-02 -3.459453E-05 -1.586922E-02 -3.841963E-05 -1.786175E-02 -4.289114E-05 -1.326353E-02 -2.595816E-05 -1.445145E-02 -2.990583E-05 -1.509105E-02 -2.887493E-05 -1.761108E-02 -3.799916E-05 -1.671644E-02 -3.638132E-05 -1.692226E-02 -3.667379E-05 -1.123264E-02 -2.662808E-05 -1.119900E-02 -1.598286E-05 -1.930512E-02 -4.893797E-05 -2.291023E-02 -7.500981E-05 -1.093046E-02 -2.227226E-05 -2.121672E-02 -7.861749E-05 -9.618950E-03 -1.801199E-05 -1.213716E-02 -2.201469E-05 -1.856853E-02 -4.365656E-05 -1.665627E-02 -3.787320E-05 -1.301603E-02 -3.128189E-05 -1.971201E-02 -6.183556E-05 -2.240750E-02 -7.011853E-05 -2.216291E-02 -6.809313E-05 -1.153008E-02 -2.676316E-05 -1.676451E-02 -4.351892E-05 -2.591571E-02 -8.037903E-05 -2.037389E-02 -4.959375E-05 -1.495140E-02 -2.829832E-05 -1.051363E-02 -2.065167E-05 -1.979307E-02 -5.604015E-05 -2.624329E-02 -8.019430E-05 -1.335982E-02 -2.844614E-05 -1.612983E-02 -6.010017E-05 -1.728825E-02 -4.711910E-05 -2.429057E-02 -7.415431E-05 -1.616100E-02 -3.084388E-05 -1.338558E-02 -3.228322E-05 -1.340928E-02 -3.387569E-05 -1.708924E-02 -4.087477E-05 -1.336049E-02 -2.477778E-05 -1.587999E-02 -3.626669E-05 -1.935273E-02 -4.723278E-05 -2.470520E-02 -7.859676E-05 -1.475079E-02 -3.640394E-05 -1.679996E-02 -3.695619E-05 -1.042709E-02 -1.967458E-05 -1.968690E-02 -5.949834E-05 -1.327946E-02 -2.828789E-05 -2.199912E-02 -6.466489E-05 -1.849493E-02 -3.808605E-05 -1.601814E-02 -3.868414E-05 -8.360208E-03 -8.722194E-06 -1.048244E-02 -1.553938E-05 -1.355191E-02 -3.191766E-05 -2.019710E-02 -5.689596E-05 -1.515848E-02 -3.149152E-05 -2.234350E-02 -6.679195E-05 -2.213825E-02 -7.381934E-05 -1.917888E-02 -4.731955E-05 -1.084756E-02 -1.986509E-05 -1.609220E-02 -3.078859E-05 -1.473280E-02 -3.933279E-05 -1.529880E-02 -3.127194E-05 -1.639564E-02 -4.529775E-05 -1.443123E-02 -3.075459E-05 -1.882187E-02 -5.273612E-05 -1.460498E-02 -3.301670E-05 -1.236974E-02 -2.302425E-05 -1.547979E-02 -5.040930E-05 -8.943072E-03 -1.146125E-05 -1.038577E-02 -2.359524E-05 -9.957494E-03 -1.246302E-05 -8.165810E-03 -1.286712E-05 -9.730475E-03 -1.696051E-05 -1.144342E-02 -1.696256E-05 -1.018757E-02 -1.502940E-05 -6.455273E-03 -6.892868E-06 -1.173241E-02 -1.925350E-05 -1.116334E-02 -1.482619E-05 -5.399877E-03 -4.405606E-06 -3.959202E-03 -4.471062E-06 -9.736729E-03 -1.616042E-05 -4.414460E-03 -5.308331E-06 -5.659090E-03 -4.225962E-06 -4.260578E-03 -3.519428E-06 -1.063057E-02 -2.671737E-05 -9.252412E-03 -1.335948E-05 -7.509662E-03 -1.033233E-05 -5.631650E-03 -4.603917E-06 -7.374915E-03 -9.613999E-06 -1.017301E-02 -1.890382E-05 -4.657208E-03 -4.110749E-06 -8.263045E-03 -9.144029E-06 -5.083557E-03 -3.617645E-06 -5.753770E-03 -6.399330E-06 -3.157208E-03 -2.023717E-06 -2.929392E-03 -1.415512E-06 -3.306531E-03 -3.326325E-06 -7.308585E-03 -7.051788E-06 -2.131441E-03 -3.159885E-06 -6.056253E-03 -6.146480E-06 -3.197345E-03 -1.906328E-06 -7.156591E-03 -8.158604E-06 -1.008394E-02 -1.612226E-05 -1.360120E-02 -3.007127E-05 -1.087460E-02 -1.978085E-05 -8.751267E-03 -1.202395E-05 -1.327913E-02 -2.254308E-05 -1.549315E-02 -3.493369E-05 -1.276663E-02 -2.254426E-05 -1.422943E-02 -3.266120E-05 -7.543284E-03 -8.425611E-06 -1.148895E-02 -2.316672E-05 -1.075957E-02 -1.733122E-05 -1.228568E-02 -2.274310E-05 -1.298949E-02 -3.103013E-05 -1.687551E-02 -3.373288E-05 -1.174671E-02 -1.478816E-05 -1.298113E-02 -2.280689E-05 -1.375075E-02 -3.564635E-05 -1.865407E-02 -4.650386E-05 -1.316565E-02 -3.034949E-05 -1.644195E-02 -3.039939E-05 -1.167304E-02 -1.910205E-05 -1.119646E-02 -2.041134E-05 -2.051982E-02 -5.295597E-05 -1.446398E-02 -2.483661E-05 -1.663221E-02 -4.310298E-05 -1.774865E-02 -3.613160E-05 -1.551828E-02 -3.922463E-05 -1.987068E-02 -5.088653E-05 -1.111420E-02 -2.006407E-05 -1.756540E-02 -4.468660E-05 -1.151848E-02 -1.953188E-05 -1.430522E-02 -3.322674E-05 -8.678157E-03 -1.516243E-05 -1.189921E-02 -1.954174E-05 -1.667314E-02 -5.548567E-05 -2.197194E-02 -6.943126E-05 -2.047457E-02 -4.730016E-05 -2.145796E-02 -5.503501E-05 -1.433861E-02 -3.407856E-05 -1.789249E-02 -4.132722E-05 -1.497597E-02 -3.790603E-05 -1.784518E-02 -5.989398E-05 -1.348223E-02 -2.451114E-05 -1.850761E-02 -4.354345E-05 -9.460668E-03 -1.235477E-05 -1.608153E-02 -3.627464E-05 -2.158938E-02 -7.192126E-05 -2.591114E-02 -7.881538E-05 -1.615323E-02 -3.735540E-05 -1.456875E-02 -2.959443E-05 -1.713879E-02 -3.971707E-05 -2.011125E-02 -5.426015E-05 -1.600843E-02 -3.860238E-05 -2.349989E-02 -6.721393E-05 -9.675390E-03 -1.720621E-05 -1.321534E-02 -2.201319E-05 -1.388877E-02 -3.752647E-05 -9.338560E-03 -1.222660E-05 -1.872993E-02 -4.179060E-05 -1.729197E-02 -4.763909E-05 -1.433923E-02 -3.648874E-05 -1.982945E-02 -5.208569E-05 -9.529878E-03 -1.355652E-05 -1.902053E-02 -4.097824E-05 -9.167842E-03 -1.041942E-05 -1.571952E-02 -4.188405E-05 -9.716564E-03 -2.414735E-05 -1.423573E-02 -3.524484E-05 -1.148788E-02 -2.604718E-05 -1.545038E-02 -3.289072E-05 -1.724229E-02 -4.091912E-05 -2.114484E-02 -5.448881E-05 -1.201008E-02 -1.761314E-05 -1.049205E-02 -1.851795E-05 -1.007470E-02 -1.508850E-05 -1.216162E-02 -1.779226E-05 -9.172443E-03 -1.542767E-05 -1.158129E-02 -2.700118E-05 -8.634939E-03 -1.235312E-05 -9.968731E-03 -1.636632E-05 -8.806160E-03 -1.312756E-05 -7.282738E-03 -7.675380E-06 -1.501313E-02 -3.403794E-05 -1.772683E-02 -3.946856E-05 -6.797082E-03 -6.826066E-06 -6.203754E-03 -6.576663E-06 -1.255269E-02 -2.273841E-05 -9.325891E-03 -1.968887E-05 -5.665941E-03 -7.672343E-06 -9.482040E-03 -1.321433E-05 -5.895438E-03 -7.290209E-06 -4.028986E-03 -3.562047E-06 -9.179212E-03 -1.479180E-05 -5.065510E-03 -7.876080E-06 -9.623638E-03 -1.331451E-05 -8.243023E-03 -1.155595E-05 -6.785547E-03 -8.869686E-06 -6.830346E-03 -6.869962E-06 -5.952624E-03 -7.591589E-06 -1.262730E-02 -2.795731E-05 -7.222793E-03 -7.969191E-06 -7.364474E-03 -9.912407E-06 -4.073203E-03 -3.221529E-06 -6.307497E-03 -8.387738E-06 -6.770719E-03 -9.965921E-06 -7.935928E-03 -9.247514E-06 -8.991810E-03 -1.001059E-05 -5.746536E-03 -5.204627E-06 -4.632325E-03 -3.055561E-06 -7.410656E-03 -9.676112E-06 -7.030579E-03 -9.078592E-06 -9.940893E-03 -2.033444E-05 -4.593423E-03 -3.918985E-06 -3.958315E-03 -2.344423E-06 -4.956734E-03 -6.309001E-06 -7.499601E-03 -8.403664E-06 -4.748645E-03 -4.199540E-06 -5.390021E-03 -5.915551E-06 -8.712210E-03 -1.738886E-05 -8.103852E-03 -9.180564E-06 -1.025459E-02 -1.310828E-05 -1.184291E-02 -1.833442E-05 -5.755536E-03 -5.404194E-06 -8.221201E-03 -9.335727E-06 -9.828395E-03 -1.545245E-05 -1.152575E-02 -1.759013E-05 -5.829495E-03 -7.232703E-06 -1.218356E-02 -2.664254E-05 -6.170466E-03 -7.308485E-06 -7.313197E-03 -7.829261E-06 -1.367693E-02 -3.155396E-05 -1.355349E-02 -2.093247E-05 -1.169703E-02 -1.533618E-05 -1.225998E-02 -3.530234E-05 -1.125463E-02 -1.795265E-05 -9.696736E-03 -1.412411E-05 -1.093214E-02 -1.673039E-05 -1.278387E-02 -2.130505E-05 -8.880561E-03 -1.364130E-05 -1.181523E-02 -1.870304E-05 -9.189492E-03 -1.453491E-05 -9.455271E-03 -1.423365E-05 -1.776658E-02 -4.257355E-05 -1.296514E-02 -2.121667E-05 -1.003865E-02 -1.487795E-05 -1.359312E-02 -2.765495E-05 -1.162264E-02 -2.140342E-05 -1.033131E-02 -1.304998E-05 -1.542205E-02 -3.650649E-05 -1.535565E-02 -3.683101E-05 -9.763595E-03 -1.309061E-05 -1.726548E-02 -4.632789E-05 -1.043992E-02 -1.651951E-05 -6.110039E-03 -6.694762E-06 -1.985635E-02 -6.510789E-05 -8.438493E-03 -9.248252E-06 -1.851818E-02 -4.904640E-05 -1.995254E-02 -5.020531E-05 -1.335907E-02 -2.466345E-05 -1.649899E-02 -3.318908E-05 -1.452837E-02 -3.635670E-05 -1.935287E-02 -5.575704E-05 -1.319131E-02 -2.791021E-05 -1.492064E-02 -3.073511E-05 -1.131605E-02 -2.493004E-05 -1.462680E-02 -2.849063E-05 -1.962759E-02 -5.083607E-05 -1.701425E-02 -4.167266E-05 -7.965972E-03 -1.229258E-05 -1.458100E-02 -2.718206E-05 -1.026138E-02 -2.113714E-05 -1.308429E-02 -2.003268E-05 -9.038340E-03 -9.340773E-06 -1.586616E-02 -3.218048E-05 -6.515114E-03 -9.139171E-06 -1.003265E-02 -1.250538E-05 -7.477346E-03 -9.170786E-06 -8.376990E-03 -1.161182E-05 -1.829624E-02 -3.702430E-05 -1.569831E-02 -2.881524E-05 -1.105450E-02 -2.103495E-05 -1.042629E-02 -1.723138E-05 -9.998085E-03 -1.227071E-05 -1.516738E-02 -3.324549E-05 -1.090125E-02 -1.985519E-05 -1.432278E-02 -3.386798E-05 -8.418229E-03 -1.050672E-05 -1.108353E-02 -1.739127E-05 -7.787352E-03 -1.084467E-05 -6.757477E-03 -8.314301E-06 -1.266965E-02 -2.014700E-05 -1.223368E-02 -1.816810E-05 -1.000405E-02 -2.132755E-05 -1.260170E-02 -2.392494E-05 -9.344763E-03 -1.208588E-05 -1.243003E-02 -2.215004E-05 -8.842577E-03 -1.468191E-05 -1.171609E-02 -2.634512E-05 -7.361574E-03 -1.005220E-05 -4.937175E-03 -3.421412E-06 -8.801345E-03 -1.258402E-05 -8.660082E-03 -1.317890E-05 -1.066110E-02 -2.285362E-05 -8.182265E-03 -1.352232E-05 -1.194368E-02 -2.542532E-05 -5.247990E-03 -7.113477E-06 -1.329855E-02 -2.805232E-05 -1.667204E-02 -4.715717E-05 -5.516192E-03 -4.861602E-06 -8.032885E-03 -9.526962E-06 -8.923177E-03 -1.221885E-05 -7.273785E-03 -7.646285E-06 -9.997748E-03 -1.389196E-05 -1.049460E-02 -1.325998E-05 -1.231591E-02 -1.779583E-05 -1.187687E-02 -1.777669E-05 -4.027367E-03 -5.095043E-06 -5.883273E-03 -1.010000E-05 -5.881059E-03 -5.701541E-06 -6.065490E-03 -8.604636E-06 -1.853273E-03 -1.189336E-06 -4.775189E-03 -6.494172E-06 -4.633358E-03 -4.183400E-06 -4.180683E-03 -5.129026E-06 -4.541541E-03 -5.646520E-06 -7.074233E-04 -2.834238E-07 -2.724695E-03 -2.217855E-06 -1.700068E-03 -8.357081E-07 -3.833078E-03 -2.656428E-06 -6.572586E-03 -8.866295E-06 -5.292952E-03 -3.867444E-06 -3.517788E-03 -2.530088E-06 -2.740599E-03 -2.004521E-06 -5.438345E-03 -8.165786E-06 -3.641025E-03 -3.113878E-06 -4.966383E-03 -7.623277E-06 -3.292270E-03 -2.722033E-06 -4.468651E-03 -5.017784E-06 -2.625164E-03 -1.543702E-06 -3.246447E-03 -2.141940E-06 -6.765655E-03 -9.017921E-06 -6.472797E-03 -5.971218E-06 -5.166553E-03 -3.916196E-06 -4.715011E-03 -4.421483E-06 -8.868545E-03 -1.033407E-05 -9.454655E-03 -1.287272E-05 -7.378309E-03 -9.793455E-06 -8.294983E-03 -1.242029E-05 -9.030433E-03 -1.660734E-05 -5.691832E-03 -4.629989E-06 -6.844709E-03 -1.039079E-05 -6.076908E-03 -6.364980E-06 -1.018307E-02 -1.478904E-05 -8.398207E-03 -1.353213E-05 -1.038657E-02 -1.650576E-05 -1.318384E-02 -2.408888E-05 -8.015055E-03 -1.126916E-05 -1.030145E-02 -1.582573E-05 -6.890267E-03 -8.319222E-06 -7.150937E-03 -7.850470E-06 -4.889144E-03 -3.720968E-06 -8.323465E-03 -1.115383E-05 -9.054557E-03 -1.439423E-05 -1.406749E-02 -2.792472E-05 -1.188336E-02 -2.280525E-05 -1.029778E-02 -1.535135E-05 -6.586615E-03 -8.689373E-06 -6.989279E-03 -6.602524E-06 -8.696264E-03 -1.699910E-05 -1.215054E-02 -1.809626E-05 -9.660496E-03 -1.576109E-05 -6.998390E-03 -6.984012E-06 -4.566410E-03 -4.700686E-06 -7.914312E-03 -8.046281E-06 -1.119024E-02 -1.682956E-05 -8.557711E-03 -1.169180E-05 -1.116108E-02 -2.002096E-05 -1.596243E-02 -3.319159E-05 -1.417800E-02 -2.698476E-05 -1.370714E-02 -3.345511E-05 -6.571905E-03 -1.170061E-05 -9.528663E-03 -1.906413E-05 -1.285473E-02 -1.987588E-05 -1.051645E-02 -2.095546E-05 -6.496841E-03 -6.085712E-06 -1.535496E-02 -3.318420E-05 -1.422914E-02 -2.578886E-05 -1.481483E-02 -2.681040E-05 -3.973095E-03 -3.122718E-06 -1.132021E-02 -1.735904E-05 -3.004322E-03 -4.387582E-06 -7.360833E-03 -1.310893E-05 -1.047617E-02 -1.750773E-05 -1.122781E-02 -2.131611E-05 -5.694910E-03 -7.234627E-06 -7.668968E-03 -8.067750E-06 -4.449311E-03 -4.768775E-06 -3.787286E-03 -2.624668E-06 -1.002060E-02 -1.749285E-05 -1.395365E-02 -2.967710E-05 -8.499007E-03 -1.449296E-05 -9.187712E-03 -1.502460E-05 -9.842313E-03 -1.218596E-05 -1.196667E-02 -1.597317E-05 -9.851299E-03 -1.503088E-05 -7.735045E-03 -9.286037E-06 -1.079491E-02 -1.766380E-05 -1.091930E-02 -1.648255E-05 -1.108268E-02 -1.578770E-05 -8.120340E-03 -1.291411E-05 -1.246096E-02 -2.528446E-05 -1.202701E-02 -1.816947E-05 -8.319659E-03 -1.340429E-05 -6.275166E-03 -6.982397E-06 -9.030250E-03 -1.174300E-05 -8.187094E-03 -1.235622E-05 -5.549210E-03 -5.420156E-06 -6.789734E-03 -7.904257E-06 -4.425697E-03 -3.919582E-06 -6.512926E-03 -7.118649E-06 -6.535547E-03 -1.403886E-05 -7.543231E-03 -1.205568E-05 -7.377749E-03 -1.142071E-05 -6.797258E-03 -7.523771E-06 -7.181352E-03 -8.290755E-06 -7.045510E-03 -1.013770E-05 -8.236912E-03 -1.265044E-05 -7.857392E-03 -1.143180E-05 -2.604005E-03 -2.317099E-06 -6.968220E-03 -1.347326E-05 -6.200344E-03 -7.619475E-06 -6.667622E-03 -1.088132E-05 -2.645846E-03 -1.854304E-06 -5.207931E-03 -4.574122E-06 -5.239891E-03 -5.012226E-06 -9.605662E-03 -1.784435E-05 -4.891233E-03 -6.117222E-06 -6.504651E-03 -1.229520E-05 -4.837232E-03 -6.126627E-06 -5.744494E-03 -9.825890E-06 -4.153989E-03 -5.541638E-06 -2.163062E-03 -2.727406E-06 -7.562241E-03 -1.683819E-05 -4.906111E-03 -7.696070E-06 -4.582205E-03 -7.559853E-06 -4.360889E-03 -6.753941E-06 -2.573412E-03 -2.074263E-06 -7.341817E-03 -1.510923E-05 -1.348516E-04 -1.818494E-08 -2.140265E-03 -2.186708E-06 -5.132621E-03 -6.802003E-06 -3.951538E-03 -5.966124E-06 -3.677707E-03 -4.225767E-06 -1.976184E-03 -9.056492E-07 -4.382040E-04 -1.920227E-07 -1.818577E-03 -1.643089E-06 -1.584983E-03 -1.096049E-06 -3.083453E-03 -3.167381E-06 -2.957748E-03 -3.417374E-06 -4.181554E-03 -3.122268E-06 -8.205844E-03 -1.339216E-05 -8.373927E-03 -1.673225E-05 -4.491527E-03 -6.082578E-06 -6.731608E-03 -1.117129E-05 -4.850830E-03 -4.259080E-06 -7.231407E-03 -8.438356E-06 -5.959383E-03 -1.199394E-05 -8.812537E-03 -1.137742E-05 -5.064971E-03 -5.265762E-06 -6.088263E-03 -5.366214E-06 -1.231967E-02 -2.529922E-05 -6.664708E-03 -6.756574E-06 -7.146824E-03 -6.992158E-06 -7.597362E-03 -8.315013E-06 -8.302133E-03 -1.025085E-05 -7.908279E-03 -8.283137E-06 -4.910695E-03 -4.757721E-06 -7.465751E-03 -1.337654E-05 -6.657558E-03 -7.888053E-06 -5.401779E-03 -5.483988E-06 -3.267001E-03 -2.915272E-06 -6.045569E-03 -6.294647E-06 -1.070370E-02 -1.951887E-05 -7.552609E-03 -7.432950E-06 -8.877234E-03 -1.068410E-05 -1.075436E-02 -1.493748E-05 -5.659998E-03 -5.370515E-06 -8.655450E-03 -1.139402E-05 -6.300286E-03 -8.630445E-06 -8.360752E-03 -1.357159E-05 -5.594374E-03 -5.201663E-06 -5.933381E-03 -5.223719E-06 -5.436755E-03 -5.337268E-06 -5.498344E-03 -4.605588E-06 -1.006944E-02 -1.688863E-05 -6.917860E-03 -8.432437E-06 -1.165526E-02 -1.802342E-05 -1.077532E-02 -2.444899E-05 -4.239569E-03 -2.886382E-06 -6.796744E-03 -5.792939E-06 -6.662910E-03 -5.729331E-06 -7.255977E-03 -1.065759E-05 -2.894086E-03 -1.903304E-06 -6.311066E-03 -4.912946E-06 -1.099018E-02 -2.054283E-05 -7.241143E-03 -7.442478E-06 -4.567091E-03 -3.071464E-06 -6.773593E-03 -5.905000E-06 -8.327525E-03 -9.451448E-06 -1.069359E-02 -1.514720E-05 -3.670959E-03 -3.304885E-06 -9.124065E-03 -1.471763E-05 -3.861446E-03 -3.151454E-06 -6.221877E-03 -1.027786E-05 -5.254419E-03 -6.135711E-06 -7.702917E-03 -1.051860E-05 -5.115541E-03 -6.357416E-06 -5.321924E-03 -4.501815E-06 -7.639895E-03 -1.792277E-05 -5.676732E-03 -4.933198E-06 -7.917058E-03 -1.103359E-05 -6.987672E-03 -8.124731E-06 -7.605775E-03 -1.154995E-05 -1.077244E-02 -2.439257E-05 -5.513601E-03 -7.937817E-06 -8.315505E-03 -9.181773E-06 -5.719492E-03 -6.912423E-06 -4.809607E-03 -6.393160E-06 -5.490138E-03 -6.557157E-06 -2.585724E-03 -1.337147E-06 -3.578006E-03 -2.074822E-06 -6.644166E-03 -9.849481E-06 -5.073345E-03 -6.101950E-06 -8.583604E-03 -1.928242E-05 -6.278182E-03 -8.352587E-06 -7.476949E-03 -1.201282E-05 -4.477112E-03 -4.894391E-06 -9.059255E-03 -1.429652E-05 -3.030949E-03 -1.590060E-06 -5.686827E-03 -5.262592E-06 -4.734421E-03 -6.896077E-06 -2.912353E-03 -1.875480E-06 -6.517175E-03 -6.330268E-06 -9.203829E-03 -1.181214E-05 -5.012765E-03 -5.129300E-06 -7.823830E-03 -1.330136E-05 -5.110174E-03 -4.376566E-06 -7.379964E-03 -8.333357E-06 -5.468869E-03 -6.083600E-06 -7.519458E-03 -1.048700E-05 -4.611391E-03 -3.814525E-06 -7.062996E-03 -1.181993E-05 -3.837864E-03 -3.789477E-06 -6.759816E-03 -8.026354E-06 -5.672758E-03 -4.924437E-06 -8.864970E-03 -1.097704E-05 -5.305515E-03 -6.789690E-06 -4.264513E-03 -5.260234E-06 -5.512145E-03 -8.119123E-06 -5.053780E-03 -5.404719E-06 -7.029594E-03 -9.741504E-06 -2.374002E-03 -1.449069E-06 -2.256464E-03 -1.391425E-06 -4.548643E-03 -7.978885E-06 -2.810872E-03 -2.456200E-06 -4.084882E-03 -6.257623E-06 -6.517591E-03 -9.674764E-06 -6.200630E-03 -9.438817E-06 -2.745907E-03 -1.809511E-06 -3.972065E-03 -3.245352E-06 -5.942817E-03 -7.352165E-06 -3.263414E-03 -3.353913E-06 -8.153438E-03 -1.079966E-05 -7.165596E-03 -1.017019E-05 -4.251216E-03 -2.817736E-06 -8.011851E-03 -1.068301E-05 -9.752890E-04 -7.589177E-07 -3.469946E-03 -2.493177E-06 -6.811986E-03 -8.722919E-06 -5.394586E-03 -6.424939E-06 -5.872081E-03 -8.499852E-06 -8.818832E-03 -1.189657E-05 -7.866284E-03 -8.632785E-06 -8.116334E-03 -1.347044E-05 -2.423674E-03 -2.219673E-06 -7.457717E-03 -9.186735E-06 -6.773921E-03 -1.764821E-05 -6.930098E-03 -1.011624E-05 -8.618704E-03 -1.022187E-05 -1.184609E-02 -2.438262E-05 -8.878289E-03 -1.326793E-05 -5.073855E-03 -4.038299E-06 -9.760737E-03 -1.548967E-05 -7.965991E-03 -1.151518E-05 -5.975862E-03 -1.006202E-05 -7.122347E-03 -8.079230E-06 -7.180618E-03 -7.951754E-06 -5.027224E-03 -6.787710E-06 -1.109603E-02 -1.848734E-05 -1.295024E-02 -3.036716E-05 -8.023705E-03 -8.286741E-06 -1.144577E-02 -2.665312E-05 -1.019084E-02 -1.881473E-05 -1.361484E-02 -2.576942E-05 -9.013737E-03 -1.466391E-05 -1.147532E-02 -2.462687E-05 -1.225257E-02 -2.181790E-05 -8.159645E-03 -1.259135E-05 -4.127139E-03 -2.557351E-06 -5.325669E-03 -6.365360E-06 -1.347774E-02 -2.661460E-05 -7.265261E-03 -1.252096E-05 -1.373140E-02 -2.385999E-05 -1.262611E-02 -2.245356E-05 -9.465554E-03 -2.262286E-05 -8.452943E-03 -1.155915E-05 -4.998547E-03 -7.068774E-06 -7.648621E-03 -9.105026E-06 -9.203837E-03 -1.311626E-05 -1.107019E-02 -1.950577E-05 -1.315936E-02 -2.410764E-05 -7.844275E-03 -9.659512E-06 -9.825100E-03 -1.724414E-05 -1.047811E-02 -1.262306E-05 -1.207238E-02 -2.752816E-05 -1.085843E-02 -1.470096E-05 -1.594894E-02 -4.046810E-05 -1.497569E-02 -2.863883E-05 -1.030144E-02 -2.348225E-05 -6.125370E-03 -7.226790E-06 -1.405421E-02 -4.764046E-05 -1.625035E-02 -3.353624E-05 -9.577818E-03 -1.794568E-05 -1.448263E-02 -2.770743E-05 -1.029916E-02 -1.861537E-05 -9.183850E-03 -1.591847E-05 -9.237708E-03 -1.576843E-05 -1.079813E-02 -1.581077E-05 -1.260676E-02 -3.554547E-05 -2.054039E-02 -5.879657E-05 -7.345172E-03 -8.644617E-06 -9.151035E-03 -1.651766E-05 -1.271524E-02 -2.302768E-05 -1.487615E-02 -3.960752E-05 -7.259983E-03 -1.107807E-05 -5.855371E-03 -4.857225E-06 -7.570428E-03 -9.406879E-06 -5.643592E-03 -7.265176E-06 -1.113252E-02 -1.652636E-05 -1.101056E-02 -1.732233E-05 -7.781992E-03 -7.475792E-06 -1.014997E-02 -1.698223E-05 -7.547933E-03 -1.219150E-05 -4.922153E-03 -4.916764E-06 -6.063790E-03 -7.031316E-06 -8.119766E-03 -1.484039E-05 -5.084706E-03 -4.983059E-06 -5.431730E-03 -5.048229E-06 -8.720640E-03 -1.061184E-05 -8.480299E-03 -1.325453E-05 -1.209019E-02 -2.053697E-05 -1.028370E-02 -2.394843E-05 -8.037695E-03 -1.000534E-05 -9.075446E-03 -1.720138E-05 -5.348851E-03 -5.241839E-06 -6.061215E-03 -7.799859E-06 -9.501216E-03 -1.498369E-05 -1.649742E-02 -3.974159E-05 -8.337027E-03 -1.677761E-05 -1.156020E-02 -1.673947E-05 -1.046774E-02 -2.653737E-05 -7.675581E-03 -8.456541E-06 -9.617224E-03 -1.794211E-05 -1.268842E-02 -2.897864E-05 -9.844835E-03 -1.818849E-05 -9.330947E-03 -1.549578E-05 -5.838065E-03 -7.948493E-06 -8.798788E-03 -1.342636E-05 -9.306629E-03 -1.318598E-05 -4.920602E-03 -4.823960E-06 -1.710686E-03 -7.729255E-07 -2.859179E-03 -1.745176E-06 -4.456373E-03 -4.366517E-06 -2.395798E-03 -1.736746E-06 -7.027745E-03 -1.682294E-05 -4.030298E-03 -4.530935E-06 -2.803361E-03 -2.792072E-06 -6.688412E-03 -1.091671E-05 -7.703157E-03 -8.772855E-06 -4.949493E-03 -3.982137E-06 -7.365244E-03 -1.073387E-05 -9.386372E-03 -1.134513E-05 -9.003757E-03 -1.332391E-05 -7.974051E-03 -1.354602E-05 -1.137434E-02 -1.857838E-05 -1.143520E-02 -2.117358E-05 -3.030499E-03 -2.165815E-06 -4.867784E-03 -3.911154E-06 -5.246175E-03 -6.161091E-06 -5.832426E-03 -5.525543E-06 -7.382520E-03 -9.067048E-06 -1.188676E-02 -1.778783E-05 -1.199313E-02 -2.082141E-05 -1.266957E-02 -1.962424E-05 -1.533876E-02 -3.337162E-05 -7.389726E-03 -1.341338E-05 -7.529503E-03 -1.564696E-05 -1.491955E-02 -2.945644E-05 -1.074068E-02 -1.373117E-05 -1.472706E-02 -3.572507E-05 -1.199986E-02 -3.422317E-05 -8.514133E-03 -1.135618E-05 -1.634996E-02 -4.087320E-05 -1.955740E-02 -5.492009E-05 -1.126909E-02 -1.541148E-05 -1.586435E-02 -3.446303E-05 -1.700178E-02 -4.898376E-05 -1.703540E-02 -3.720395E-05 -1.967755E-02 -4.525544E-05 -1.330271E-02 -2.702604E-05 -1.888903E-02 -4.979443E-05 -2.004837E-02 -5.083025E-05 -1.435878E-02 -3.285995E-05 -1.930301E-02 -5.509308E-05 -1.628120E-02 -3.580789E-05 -1.727344E-02 -4.342335E-05 -1.216615E-02 -1.983233E-05 -1.700189E-02 -4.670523E-05 -1.269439E-02 -2.172602E-05 -2.010215E-02 -5.553642E-05 -2.319103E-02 -6.565091E-05 -1.414047E-02 -3.346494E-05 -2.027618E-02 -5.626720E-05 -1.646954E-02 -3.312557E-05 -2.251086E-02 -5.995831E-05 -1.610985E-02 -3.156849E-05 -1.377020E-02 -2.853634E-05 -1.669701E-02 -3.307612E-05 -1.159986E-02 -1.816147E-05 -1.261975E-02 -1.769023E-05 -2.134097E-02 -5.752884E-05 -1.841902E-02 -4.295167E-05 -2.422207E-02 -7.083744E-05 -1.543392E-02 -4.221173E-05 -2.157215E-02 -6.548409E-05 -2.644384E-02 -8.410907E-05 -2.311629E-02 -6.681868E-05 -2.395484E-02 -6.437514E-05 -1.922089E-02 -4.174544E-05 -1.663494E-02 -3.328109E-05 -9.964643E-03 -1.255907E-05 -1.150794E-02 -1.961340E-05 -1.939308E-02 -4.712734E-05 -1.787616E-02 -4.675712E-05 -2.319516E-02 -6.969066E-05 -1.741640E-02 -5.935363E-05 -1.789596E-02 -4.474293E-05 -2.512717E-02 -7.989830E-05 -1.220933E-02 -1.607761E-05 -1.359674E-02 -2.403775E-05 -1.590621E-02 -4.874402E-05 -1.664365E-02 -3.902009E-05 -1.028716E-02 -1.812738E-05 -1.543365E-02 -3.451753E-05 -1.719718E-02 -5.881162E-05 -1.666983E-02 -4.833689E-05 -1.586040E-02 -3.290082E-05 -1.592280E-02 -2.852261E-05 -2.560930E-02 -8.694469E-05 -2.095050E-02 -5.412080E-05 -1.939382E-02 -4.569593E-05 -1.830391E-02 -4.667520E-05 -1.549161E-02 -4.356136E-05 -1.284248E-02 -2.163546E-05 -1.082843E-02 -1.936706E-05 -1.108300E-02 -2.032165E-05 -1.963227E-02 -5.789246E-05 -1.883825E-02 -5.273957E-05 -1.630332E-02 -3.434978E-05 -1.574688E-02 -3.564693E-05 -1.794394E-02 -3.918955E-05 -2.060232E-02 -5.819679E-05 -1.732204E-02 -4.346625E-05 -1.922985E-02 -4.636825E-05 -1.116057E-02 -1.992936E-05 -1.216817E-02 -1.947069E-05 -8.811885E-03 -1.441275E-05 -1.603072E-02 -3.965729E-05 -1.459394E-02 -2.864759E-05 -1.150127E-02 -2.431776E-05 -1.146459E-02 -2.593052E-05 -1.120930E-02 -2.027939E-05 -1.077685E-02 -1.909421E-05 -1.564605E-02 -5.177856E-05 -1.438847E-02 -2.596269E-05 -1.575101E-02 -2.945546E-05 -5.164090E-03 -4.380072E-06 -5.313984E-03 -4.984595E-06 -3.270078E-03 -3.714857E-06 -4.763025E-03 -5.471147E-06 -5.854797E-03 -4.013420E-06 -7.497916E-03 -9.530633E-06 -4.307122E-03 -4.511481E-06 -2.673595E-03 -1.496751E-06 -7.668976E-03 -1.208726E-05 -6.666645E-03 -9.107345E-06 -4.278473E-03 -3.613729E-06 -5.196607E-03 -6.165915E-06 -9.012663E-03 -1.072065E-05 -7.125950E-03 -1.021884E-05 -1.110525E-02 -1.609758E-05 -6.452393E-03 -6.522408E-06 -1.614916E-02 -2.933964E-05 -1.252957E-02 -2.095707E-05 -9.931672E-03 -1.358529E-05 -1.307449E-02 -2.442977E-05 -5.859693E-03 -6.187229E-06 -6.811267E-03 -6.011900E-06 -1.636036E-02 -4.227062E-05 -9.529154E-03 -1.673527E-05 -9.884570E-03 -1.607810E-05 -1.162560E-02 -2.293323E-05 -6.582499E-03 -8.254458E-06 -1.846807E-02 -3.840513E-05 -9.921319E-03 -1.528378E-05 -1.451278E-02 -3.842835E-05 -1.536970E-02 -4.453795E-05 -1.597714E-02 -3.763051E-05 -1.416499E-02 -2.488034E-05 -1.579940E-02 -3.618366E-05 -1.729494E-02 -4.587947E-05 -1.591255E-02 -3.608980E-05 -1.155321E-02 -2.053226E-05 -1.599423E-02 -3.545225E-05 -1.125966E-02 -2.267289E-05 -2.172447E-02 -5.857701E-05 -1.372075E-02 -3.321713E-05 -1.816373E-02 -4.485596E-05 -1.857039E-02 -4.872304E-05 -1.742011E-02 -3.730490E-05 -1.568977E-02 -3.029088E-05 -2.829373E-02 -1.168965E-04 -2.157357E-02 -7.579178E-05 -2.125484E-02 -6.473902E-05 -2.196378E-02 -7.339057E-05 -1.819373E-02 -4.494748E-05 -2.152003E-02 -5.928285E-05 -1.856070E-02 -4.410267E-05 -2.207371E-02 -6.449028E-05 -2.386394E-02 -6.969242E-05 -2.457216E-02 -1.102599E-04 -2.058268E-02 -5.017858E-05 -1.907854E-02 -4.286270E-05 -2.340706E-02 -8.278475E-05 -2.388190E-02 -6.533857E-05 -2.860789E-02 -9.992731E-05 -1.998933E-02 -5.361464E-05 -2.707938E-02 -9.662902E-05 -2.019340E-02 -5.415561E-05 -3.109482E-02 -1.022004E-04 -2.253924E-02 -7.055172E-05 -2.374030E-02 -6.831307E-05 -2.529035E-02 -8.295294E-05 -2.739289E-02 -8.546620E-05 -2.273185E-02 -6.442166E-05 -2.785353E-02 -8.812366E-05 -3.191849E-02 -1.234987E-04 -2.739246E-02 -9.446447E-05 -1.372157E-02 -2.877717E-05 -1.714263E-02 -4.531432E-05 -1.958677E-02 -4.920099E-05 -1.932218E-02 -4.756040E-05 -1.938252E-02 -5.565524E-05 -2.128472E-02 -6.581062E-05 -1.818983E-02 -4.440473E-05 -2.522476E-02 -9.504815E-05 -2.108060E-02 -6.460391E-05 -2.301325E-02 -6.325908E-05 -2.425505E-02 -7.889282E-05 -2.312674E-02 -8.098059E-05 -1.450662E-02 -3.120847E-05 -1.518342E-02 -2.854939E-05 -2.375891E-02 -6.170759E-05 -2.191567E-02 -5.656277E-05 -1.717224E-02 -4.219605E-05 -1.584923E-02 -2.801671E-05 -2.292044E-02 -6.761182E-05 -2.565035E-02 -9.677221E-05 -1.979804E-02 -4.912546E-05 -2.534051E-02 -8.007940E-05 -3.425993E-02 -1.487128E-04 -2.139063E-02 -5.051176E-05 -1.422774E-02 -2.343122E-05 -2.541660E-02 -8.204787E-05 -1.717071E-02 -3.842694E-05 -1.456931E-02 -2.599937E-05 -2.407397E-02 -7.826348E-05 -2.982739E-02 -1.099192E-04 -1.812330E-02 -4.520557E-05 -1.506065E-02 -3.120742E-05 -1.957887E-02 -5.130992E-05 -2.577824E-02 -8.648590E-05 -1.959134E-02 -6.907548E-05 -2.361937E-02 -6.849830E-05 -1.277061E-02 -2.340598E-05 -1.244142E-02 -2.267140E-05 -9.333247E-03 -1.041879E-05 -7.908182E-03 -9.293981E-06 -1.463279E-02 -3.362978E-05 -1.366375E-02 -2.733021E-05 -1.213165E-02 -1.941620E-05 -1.142127E-02 -1.911366E-05 -1.101989E-02 -1.602290E-05 -1.634784E-02 -3.444363E-05 -1.399007E-02 -2.474094E-05 -1.355244E-02 -2.255801E-05 -8.699738E-03 -1.229441E-05 -6.242338E-03 -7.967030E-06 -1.101667E-02 -2.565058E-05 -8.204914E-03 -1.826875E-05 -1.073981E-02 -1.693632E-05 -1.272259E-02 -2.077325E-05 -3.495009E-03 -2.520678E-06 -8.225887E-03 -1.254359E-05 -1.009530E-02 -1.562680E-05 -1.178865E-02 -2.042891E-05 -8.663517E-03 -1.609834E-05 -1.169582E-02 -2.164100E-05 -7.396443E-03 -1.192095E-05 -3.652278E-03 -3.129723E-06 -1.045202E-02 -2.112608E-05 -1.037936E-02 -1.718392E-05 -4.516079E-03 -3.575143E-06 -1.095270E-02 -1.774093E-05 -4.883767E-03 -5.927447E-06 -6.503683E-03 -7.716956E-06 -4.663924E-03 -5.713440E-06 -6.283619E-03 -4.627844E-06 -1.015268E-02 -1.309267E-05 -9.180971E-03 -1.527190E-05 -1.951120E-02 -4.198333E-05 -1.915689E-02 -5.707669E-05 -1.373893E-02 -2.451846E-05 -1.700799E-02 -4.037549E-05 -8.089066E-03 -1.170312E-05 -1.428411E-02 -2.720105E-05 -1.592720E-02 -3.708704E-05 -1.631763E-02 -3.412617E-05 -1.129445E-02 -1.941873E-05 -1.915612E-02 -4.735245E-05 -1.422466E-02 -3.019642E-05 -1.623769E-02 -4.050190E-05 -3.000266E-02 -1.011980E-04 -2.431859E-02 -7.075474E-05 -1.997843E-02 -5.249597E-05 -2.330404E-02 -6.963217E-05 -2.446833E-02 -7.157726E-05 -2.086381E-02 -6.071597E-05 -2.692405E-02 -8.142503E-05 -3.334489E-02 -1.331416E-04 -2.459016E-02 -7.539450E-05 -2.490317E-02 -6.829414E-05 -3.465734E-02 -1.336723E-04 -2.655747E-02 -8.402121E-05 -2.461979E-02 -7.593460E-05 -2.071273E-02 -5.109741E-05 -1.963799E-02 -4.721624E-05 -2.830417E-02 -1.108014E-04 -2.011415E-02 -4.210370E-05 -2.710260E-02 -9.007571E-05 -2.284700E-02 -6.898714E-05 -3.401467E-02 -1.508203E-04 -3.114460E-02 -1.181041E-04 -3.240556E-02 -1.301155E-04 -2.879980E-02 -1.090167E-04 -3.128129E-02 -1.046425E-04 -1.710639E-02 -3.063073E-05 -2.380055E-02 -6.611900E-05 -2.461530E-02 -6.805558E-05 -2.334066E-02 -6.791023E-05 -2.377977E-02 -7.167847E-05 -3.617503E-02 -1.573371E-04 -1.872815E-02 -5.621939E-05 -1.775203E-02 -4.642358E-05 -2.771547E-02 -8.299647E-05 -3.061731E-02 -1.020731E-04 -2.507147E-02 -7.334317E-05 -3.870082E-02 -1.721376E-04 -2.186224E-02 -6.325183E-05 -2.007397E-02 -5.062141E-05 -1.912434E-02 -4.450748E-05 -3.143924E-02 -1.217065E-04 -2.928610E-02 -1.369102E-04 -2.498862E-02 -9.234430E-05 -3.196385E-02 -1.380535E-04 -2.888275E-02 -9.066905E-05 -2.680537E-02 -9.933885E-05 -3.510043E-02 -1.418994E-04 -2.849205E-02 -9.541143E-05 -3.088469E-02 -1.124620E-04 -2.410541E-02 -7.456599E-05 -2.652028E-02 -7.737605E-05 -3.100674E-02 -1.204077E-04 -2.627656E-02 -7.414914E-05 -3.172017E-02 -1.179298E-04 -3.654420E-02 -1.501200E-04 -2.437387E-02 -8.465163E-05 -2.329587E-02 -8.609453E-05 -2.851454E-02 -9.764789E-05 -2.727184E-02 -1.020548E-04 -2.887669E-02 -9.379474E-05 -2.486065E-02 -6.980906E-05 -1.336139E-02 -3.237058E-05 -1.783830E-02 -4.308671E-05 -1.984536E-02 -4.793066E-05 -1.663979E-02 -3.245507E-05 -1.629628E-02 -3.780856E-05 -2.783691E-02 -9.185991E-05 -1.901340E-02 -4.331876E-05 -1.589227E-02 -3.023585E-05 -1.511908E-02 -3.924720E-05 -2.103836E-02 -5.685631E-05 -1.846361E-02 -5.596947E-05 -2.921881E-02 -1.027479E-04 -1.582650E-02 -2.965346E-05 -1.468540E-02 -2.895302E-05 -9.775043E-03 -1.581144E-05 -1.531973E-02 -3.646605E-05 -1.629584E-02 -4.077722E-05 -1.301406E-02 -2.211695E-05 -1.400095E-02 -2.464499E-05 -1.812501E-02 -5.136800E-05 -1.883997E-02 -4.846725E-05 -1.310098E-02 -2.076611E-05 -1.641887E-02 -3.214577E-05 -2.575947E-02 -7.664609E-05 -1.393085E-02 -2.533855E-05 -1.176890E-02 -1.965214E-05 -1.001319E-02 -1.752840E-05 -5.440474E-03 -5.776297E-06 -1.602659E-02 -3.187961E-05 -1.220713E-02 -2.605586E-05 -7.910828E-03 -1.235157E-05 -6.370403E-03 -7.314863E-06 -1.200010E-02 -2.093134E-05 -1.051384E-02 -2.114633E-05 -8.728632E-03 -1.217334E-05 -9.023232E-03 -1.429000E-05 -9.324890E-03 -1.238002E-05 -9.724819E-03 -1.340545E-05 -7.999095E-03 -1.507108E-05 -1.196325E-02 -2.492866E-05 -1.708992E-02 -4.187497E-05 -1.252870E-02 -2.576528E-05 -1.245286E-02 -2.205925E-05 -1.710226E-02 -4.820652E-05 -1.077670E-02 -2.779337E-05 -8.954749E-03 -1.459088E-05 -1.587508E-02 -5.891538E-05 -1.256231E-02 -3.626849E-05 -1.456161E-02 -2.677457E-05 -1.442492E-02 -2.873208E-05 -1.513933E-02 -2.781837E-05 -1.983944E-02 -4.742520E-05 -1.796161E-02 -5.099223E-05 -1.372378E-02 -2.143333E-05 -2.054995E-02 -5.149337E-05 -1.901284E-02 -4.203203E-05 -1.545044E-02 -3.240467E-05 -1.613542E-02 -3.093719E-05 -1.748080E-02 -3.676025E-05 -1.983930E-02 -5.826899E-05 -2.077484E-02 -5.311470E-05 -2.156771E-02 -7.349191E-05 -1.910656E-02 -5.646548E-05 -2.216856E-02 -5.896630E-05 -2.363877E-02 -6.273768E-05 -2.287745E-02 -6.142836E-05 -2.078760E-02 -5.965409E-05 -2.096805E-02 -6.106318E-05 -2.748905E-02 -8.547689E-05 -3.051782E-02 -1.062831E-04 -2.439885E-02 -6.963272E-05 -2.385521E-02 -7.024650E-05 -2.722803E-02 -8.442159E-05 -2.779212E-02 -9.251750E-05 -3.008247E-02 -1.087302E-04 -2.911535E-02 -9.162499E-05 -2.377217E-02 -6.480525E-05 -2.478405E-02 -8.301183E-05 -2.916643E-02 -1.151040E-04 -3.299041E-02 -1.251473E-04 -3.387553E-02 -1.275181E-04 -3.185326E-02 -1.151563E-04 -2.738559E-02 -8.510575E-05 -3.552781E-02 -1.467678E-04 -2.050637E-02 -4.879306E-05 -2.837699E-02 -8.517767E-05 -2.623559E-02 -7.322670E-05 -3.299486E-02 -1.475369E-04 -2.852314E-02 -1.058243E-04 -3.897511E-02 -1.782398E-04 -3.453237E-02 -1.467871E-04 -2.695630E-02 -9.399806E-05 -2.993587E-02 -1.069727E-04 -3.357367E-02 -1.220837E-04 -3.533685E-02 -1.307797E-04 -3.768880E-02 -1.706168E-04 -2.378269E-02 -8.193354E-05 -2.476389E-02 -6.667890E-05 -1.835306E-02 -3.678306E-05 -2.760875E-02 -1.044222E-04 -3.364777E-02 -1.294893E-04 -2.689602E-02 -8.234805E-05 -2.994600E-02 -1.038678E-04 -3.354397E-02 -1.250106E-04 -2.806016E-02 -1.032022E-04 -3.628839E-02 -1.512597E-04 -3.254567E-02 -1.229982E-04 -3.532092E-02 -1.401948E-04 -2.079706E-02 -5.214734E-05 -2.220721E-02 -6.771925E-05 -2.792774E-02 -9.954429E-05 -2.945320E-02 -1.043290E-04 -3.367757E-02 -1.278353E-04 -3.498071E-02 -1.439058E-04 -3.069969E-02 -1.094894E-04 -2.802931E-02 -9.732849E-05 -3.379486E-02 -1.251030E-04 -3.112018E-02 -1.419631E-04 -2.905240E-02 -9.457676E-05 -3.204785E-02 -1.232863E-04 -2.256002E-02 -6.449945E-05 -2.013216E-02 -4.579187E-05 -2.378756E-02 -7.502656E-05 -1.850227E-02 -4.559569E-05 -2.577098E-02 -8.077705E-05 -2.622626E-02 -8.900068E-05 -2.011102E-02 -5.119938E-05 -1.881459E-02 -5.303212E-05 -2.333357E-02 -8.135744E-05 -2.169922E-02 -5.260477E-05 -2.865567E-02 -1.072530E-04 -3.018313E-02 -1.180560E-04 -1.619341E-02 -3.631507E-05 -2.048742E-02 -6.014736E-05 -1.648517E-02 -3.461260E-05 -2.016257E-02 -5.377223E-05 -1.821956E-02 -4.021256E-05 -2.158168E-02 -6.922336E-05 -1.520759E-02 -3.087500E-05 -1.460640E-02 -2.484693E-05 -2.423578E-02 -9.468824E-05 -1.422992E-02 -2.626671E-05 -2.233711E-02 -6.453963E-05 -2.201935E-02 -6.607908E-05 -9.865297E-03 -1.253449E-05 -1.407603E-02 -2.374027E-05 -1.554488E-02 -3.357059E-05 -1.104207E-02 -1.800945E-05 -1.152633E-02 -1.752515E-05 -1.628689E-02 -3.825834E-05 -1.961306E-03 -1.509555E-06 -7.317970E-03 -1.170313E-05 -8.045927E-03 -1.128636E-05 -7.690351E-03 -9.455253E-06 -1.305182E-02 -2.924924E-05 -8.478606E-03 -1.183524E-05 -8.368030E-03 -9.397112E-06 -6.954808E-03 -5.988757E-06 -1.478825E-02 -2.903770E-05 -1.329221E-02 -2.352890E-05 -1.153738E-02 -2.279952E-05 -1.243207E-02 -2.027409E-05 -9.794691E-03 -2.519096E-05 -1.301443E-02 -2.673139E-05 -7.744527E-03 -8.512395E-06 -1.094360E-02 -1.898404E-05 -1.322530E-02 -2.416304E-05 -1.130737E-02 -2.067371E-05 -1.475002E-02 -2.641761E-05 -1.707041E-02 -4.061788E-05 -1.873188E-02 -3.858649E-05 -2.599435E-02 -7.840083E-05 -1.356899E-02 -3.303086E-05 -1.640959E-02 -4.231153E-05 -1.712330E-02 -4.025543E-05 -2.408636E-02 -6.859578E-05 -1.647314E-02 -3.975609E-05 -2.116131E-02 -5.516930E-05 -1.843826E-02 -4.250156E-05 -1.528596E-02 -3.432942E-05 -1.872595E-02 -4.482976E-05 -2.278412E-02 -7.039773E-05 -1.646460E-02 -3.454420E-05 -2.813905E-02 -1.098347E-04 -1.918135E-02 -4.628739E-05 -2.880134E-02 -1.294280E-04 -2.929725E-02 -1.035423E-04 -2.521557E-02 -8.873832E-05 -1.598874E-02 -3.488466E-05 -2.763380E-02 -9.554358E-05 -2.869939E-02 -9.202942E-05 -2.713151E-02 -8.978531E-05 -1.987710E-02 -4.592695E-05 -2.437199E-02 -8.143180E-05 -2.321959E-02 -6.492177E-05 -3.341995E-02 -1.498991E-04 -3.725498E-02 -1.896851E-04 -2.546980E-02 -7.669037E-05 -3.217017E-02 -1.220964E-04 -3.340259E-02 -1.408478E-04 -2.814856E-02 -9.960802E-05 -3.512673E-02 -1.528623E-04 -3.192684E-02 -1.177255E-04 -4.396846E-02 -2.179530E-04 -2.532908E-02 -9.266623E-05 -2.547875E-02 -7.493150E-05 -2.198311E-02 -5.696022E-05 -2.752789E-02 -8.630574E-05 -2.765173E-02 -8.761218E-05 -2.779760E-02 -1.213200E-04 -3.155525E-02 -1.104115E-04 -3.217963E-02 -1.396421E-04 -2.812793E-02 -1.067509E-04 -3.145703E-02 -1.323921E-04 -3.473095E-02 -1.271199E-04 -3.132386E-02 -1.050335E-04 -2.550248E-02 -7.173055E-05 -2.519509E-02 -8.292973E-05 -2.719586E-02 -9.875000E-05 -3.129909E-02 -1.364716E-04 -2.405862E-02 -6.392928E-05 -3.794317E-02 -1.796683E-04 -2.411060E-02 -7.563523E-05 -3.925533E-02 -1.941205E-04 -2.464678E-02 -8.141818E-05 -2.681802E-02 -8.985410E-05 -4.257422E-02 -2.011050E-04 -3.169616E-02 -1.228099E-04 -2.070267E-02 -8.295562E-05 -1.875182E-02 -4.519138E-05 -2.746689E-02 -8.527112E-05 -3.193689E-02 -1.260160E-04 -3.274412E-02 -1.277208E-04 -3.159605E-02 -1.244039E-04 -2.739115E-02 -9.148770E-05 -2.496372E-02 -7.319379E-05 -2.543741E-02 -8.751995E-05 -3.092377E-02 -1.322133E-04 -3.099099E-02 -1.159996E-04 -3.339925E-02 -1.244687E-04 -1.992237E-02 -5.132256E-05 -2.014907E-02 -4.750167E-05 -2.144112E-02 -6.724888E-05 -3.234934E-02 -1.819994E-04 -2.676069E-02 -9.670530E-05 -2.163370E-02 -5.007717E-05 -1.255610E-02 -2.744980E-05 -1.686689E-02 -4.406712E-05 -2.491027E-02 -8.641625E-05 -2.180394E-02 -5.962243E-05 -2.074450E-02 -7.196276E-05 -2.673557E-02 -9.943740E-05 -1.141559E-02 -2.064868E-05 -1.086445E-02 -1.772569E-05 -1.994739E-02 -6.095357E-05 -1.294529E-02 -2.949692E-05 -1.279449E-02 -2.013615E-05 -1.695923E-02 -5.267358E-05 -1.003362E-02 -1.892494E-05 -1.177407E-02 -3.074621E-05 -1.427717E-02 -3.062012E-05 -1.772566E-02 -4.566137E-05 -1.448022E-02 -2.786842E-05 -1.885150E-02 -4.869026E-05 -6.234737E-03 -6.766915E-06 -8.586280E-03 -1.484755E-05 -6.177392E-03 -1.214223E-05 -5.323791E-03 -4.680794E-06 -1.176080E-02 -2.484279E-05 -1.114881E-02 -1.645519E-05 -6.273419E-03 -6.143891E-06 -5.166701E-03 -3.867691E-06 -8.069436E-03 -1.040414E-05 -4.713136E-03 -5.175457E-06 -1.199780E-02 -1.859984E-05 -8.029148E-03 -8.699198E-06 -5.632949E-03 -5.837510E-06 -9.206218E-03 -1.575125E-05 -9.680753E-03 -1.846461E-05 -1.155184E-02 -2.188509E-05 -1.074904E-02 -1.891184E-05 -1.181458E-02 -2.456277E-05 -1.127047E-02 -2.593399E-05 -1.356860E-02 -2.814265E-05 -5.544832E-03 -6.946307E-06 -9.942970E-03 -1.675490E-05 -1.631004E-02 -3.536433E-05 -1.506925E-02 -2.482344E-05 -1.182795E-02 -1.897537E-05 -1.482385E-02 -3.899302E-05 -1.209032E-02 -1.754837E-05 -1.195251E-02 -2.049614E-05 -1.038664E-02 -1.424835E-05 -1.422392E-02 -2.932993E-05 -1.541884E-02 -3.247431E-05 -1.631665E-02 -4.604922E-05 -1.384486E-02 -3.663157E-05 -1.878261E-02 -4.189792E-05 -1.586209E-02 -3.733994E-05 -2.018001E-02 -5.531326E-05 -1.737200E-02 -4.051342E-05 -1.867979E-02 -4.835331E-05 -1.873274E-02 -7.026344E-05 -3.092919E-02 -1.440764E-04 -1.756290E-02 -4.330757E-05 -1.677922E-02 -3.960529E-05 -1.917939E-02 -5.218395E-05 -2.058760E-02 -5.104735E-05 -1.950686E-02 -4.503102E-05 -1.898111E-02 -5.123138E-05 -2.095898E-02 -6.978821E-05 -2.496761E-02 -7.344351E-05 -2.216966E-02 -6.981877E-05 -1.539258E-02 -3.355552E-05 -2.090036E-02 -5.893204E-05 -2.830594E-02 -9.908163E-05 -2.079711E-02 -5.700234E-05 -2.438388E-02 -7.315541E-05 -2.071811E-02 -5.920090E-05 -3.238056E-02 -1.338963E-04 -1.998547E-02 -4.982584E-05 -2.456523E-02 -7.090598E-05 -3.010218E-02 -9.569115E-05 -2.615311E-02 -8.034083E-05 -2.193093E-02 -6.501139E-05 -2.230235E-02 -6.810904E-05 -2.787441E-02 -9.364266E-05 -3.363819E-02 -1.294292E-04 -2.455137E-02 -7.174173E-05 -2.515678E-02 -6.839428E-05 -2.184998E-02 -5.948214E-05 -3.240910E-02 -1.297175E-04 -2.930001E-02 -9.691693E-05 -2.531952E-02 -7.468705E-05 -3.926456E-02 -1.746326E-04 -3.138940E-02 -1.141098E-04 -2.053774E-02 -4.616986E-05 -1.863850E-02 -5.063978E-05 -2.488227E-02 -8.135984E-05 -2.946035E-02 -9.621222E-05 -1.816353E-02 -4.227005E-05 -2.739033E-02 -9.425769E-05 -2.235176E-02 -7.322516E-05 -2.512226E-02 -7.712444E-05 -2.093974E-02 -5.655060E-05 -1.951079E-02 -4.907052E-05 -3.008712E-02 -9.648471E-05 -2.695713E-02 -8.322148E-05 -2.032086E-02 -4.478975E-05 -1.588968E-02 -3.284638E-05 -2.795370E-02 -9.478738E-05 -3.242775E-02 -1.467751E-04 -1.851414E-02 -5.030367E-05 -1.699040E-02 -4.048405E-05 -2.381562E-02 -8.005819E-05 -2.396088E-02 -7.106899E-05 -1.334683E-02 -2.033683E-05 -2.683684E-02 -9.730671E-05 -3.212945E-02 -1.268600E-04 -2.413721E-02 -7.785437E-05 -1.278877E-02 -2.285665E-05 -2.017408E-02 -5.101405E-05 -2.425974E-02 -8.238864E-05 -1.559733E-02 -4.134474E-05 -2.323747E-02 -5.912862E-05 -3.185441E-02 -1.214009E-04 -1.297541E-02 -3.542303E-05 -1.620965E-02 -3.785927E-05 -2.077217E-02 -5.048348E-05 -2.084714E-02 -5.308615E-05 -2.198650E-02 -6.677202E-05 -2.713339E-02 -7.996952E-05 -1.008900E-02 -1.493544E-05 -7.515252E-03 -6.938048E-06 -1.725580E-02 -4.511463E-05 -1.861578E-02 -4.706579E-05 -1.192562E-02 -1.706496E-05 -1.539067E-02 -3.704392E-05 -1.563574E-02 -3.149768E-05 -1.617709E-02 -3.434601E-05 -1.421795E-02 -2.693384E-05 -9.544761E-03 -1.420198E-05 -1.920816E-02 -4.315771E-05 -2.104112E-02 -6.953280E-05 -8.386327E-03 -1.191493E-05 -8.722802E-03 -1.610480E-05 -1.338316E-02 -2.795188E-05 -1.139681E-02 -2.426741E-05 -1.023902E-02 -1.793399E-05 -1.031055E-02 -1.727351E-05 -7.202274E-03 -8.248223E-06 -5.930048E-03 -5.651618E-06 -7.496873E-03 -1.049976E-05 -1.159952E-02 -1.637372E-05 -1.149358E-02 -2.129416E-05 -1.751957E-02 -3.876503E-05 -1.304134E-02 -2.268145E-05 -6.423719E-03 -1.030715E-05 -1.229584E-02 -1.921824E-05 -1.597047E-02 -2.887519E-05 -7.728575E-03 -8.694018E-06 -1.102992E-02 -1.663289E-05 -9.958745E-03 -1.518594E-05 -9.321102E-03 -1.260439E-05 -9.226395E-03 -1.473519E-05 -1.071198E-02 -1.716096E-05 -1.209027E-02 -2.012204E-05 -1.299345E-02 -2.535948E-05 -1.377877E-02 -2.712220E-05 -1.505661E-02 -3.492299E-05 -1.496534E-02 -3.555281E-05 -1.674256E-02 -3.935472E-05 -9.494973E-03 -1.562850E-05 -9.878116E-03 -1.686202E-05 -1.512689E-02 -2.756935E-05 -2.271723E-02 -7.190876E-05 -1.204699E-02 -2.702913E-05 -1.339825E-02 -2.817955E-05 -1.767135E-02 -4.942115E-05 -1.480386E-02 -6.975977E-05 -1.636386E-02 -3.439959E-05 -1.220265E-02 -2.153744E-05 -1.347844E-02 -2.910724E-05 -1.359228E-02 -3.101663E-05 -9.728835E-03 -1.507092E-05 -1.528103E-02 -3.443965E-05 -2.096063E-02 -6.754181E-05 -2.094364E-02 -6.023053E-05 -1.266226E-02 -2.412451E-05 -2.535680E-02 -7.344640E-05 -2.598994E-02 -9.953050E-05 -2.060213E-02 -7.034543E-05 -1.788607E-02 -3.674071E-05 -1.148154E-02 -1.909188E-05 -2.245671E-02 -6.003250E-05 -2.763268E-02 -9.551846E-05 -2.267967E-02 -6.032826E-05 -1.916473E-02 -4.604843E-05 -1.294451E-02 -1.970613E-05 -1.934618E-02 -4.918252E-05 -2.293529E-02 -7.197108E-05 -1.496065E-02 -2.444659E-05 -2.226558E-02 -5.644756E-05 -1.948569E-02 -4.450894E-05 -2.081785E-02 -5.246988E-05 -1.522522E-02 -3.455714E-05 -2.719218E-02 -8.650624E-05 -3.018717E-02 -1.279696E-04 -1.871704E-02 -6.935361E-05 -2.067645E-02 -5.026583E-05 -2.040699E-02 -4.591994E-05 -2.662203E-02 -8.511265E-05 -1.360877E-02 -2.453053E-05 -2.047026E-02 -5.992658E-05 -2.099358E-02 -6.877382E-05 -1.757234E-02 -4.380517E-05 -2.023155E-02 -5.570688E-05 -1.620245E-02 -3.127153E-05 -2.718760E-02 -1.061924E-04 -1.747980E-02 -4.190787E-05 -1.548489E-02 -3.376610E-05 -2.645660E-02 -9.074843E-05 -1.786629E-02 -4.215277E-05 -1.474131E-02 -2.581817E-05 -1.388717E-02 -2.989188E-05 -2.441704E-02 -7.084896E-05 -2.104368E-02 -5.681421E-05 -2.433800E-02 -7.895153E-05 -1.597437E-02 -3.483039E-05 -1.412656E-02 -2.566245E-05 -1.687717E-02 -3.771639E-05 -2.190482E-02 -8.253917E-05 -1.386107E-02 -3.378072E-05 -1.256494E-02 -2.033235E-05 -1.458675E-02 -2.616735E-05 -1.633493E-02 -3.166210E-05 -2.288089E-02 -6.714973E-05 -2.398060E-02 -7.693950E-05 -1.834264E-02 -4.444484E-05 -2.286357E-02 -5.661515E-05 -1.648013E-02 -4.331697E-05 -1.300614E-02 -2.342646E-05 -1.426626E-02 -2.966175E-05 -2.218616E-02 -7.311082E-05 -1.244578E-02 -2.216996E-05 -2.287835E-02 -6.924841E-05 -1.752439E-02 -4.165478E-05 -2.103286E-02 -5.842027E-05 -1.533084E-02 -3.870604E-05 -1.829172E-02 -5.193773E-05 -1.756896E-02 -4.997547E-05 -2.219401E-02 -5.804587E-05 -1.083994E-02 -1.562087E-05 -1.144466E-02 -2.086121E-05 -1.743653E-02 -3.615221E-05 -9.676259E-03 -1.226729E-05 -1.296315E-02 -2.293653E-05 -1.353945E-02 -3.069949E-05 -7.066700E-03 -7.777520E-06 -8.915397E-03 -1.286545E-05 -1.337770E-02 -2.968336E-05 -1.210357E-02 -2.373080E-05 -1.021357E-02 -1.742336E-05 -1.615799E-02 -4.003564E-05 -9.037428E-03 -1.958275E-05 -3.183370E-03 -2.393571E-06 -8.515537E-03 -1.434148E-05 -8.594763E-03 -1.144929E-05 -6.557583E-03 -6.809462E-06 -9.324712E-03 -1.284671E-05 -6.075741E-03 -8.217443E-06 -7.732948E-03 -1.254995E-05 -9.364155E-03 -1.391050E-05 -1.033625E-02 -1.710810E-05 -1.643522E-02 -5.092731E-05 -1.913240E-02 -5.188056E-05 -4.699889E-03 -4.253342E-06 -3.667145E-03 -3.051204E-06 -6.956946E-03 -7.413590E-06 -9.143993E-03 -1.510114E-05 -5.630486E-03 -7.481628E-06 -8.090881E-03 -1.407277E-05 -6.451248E-03 -9.019754E-06 -8.432893E-03 -1.236291E-05 -7.535742E-03 -9.713557E-06 -4.055813E-03 -2.764876E-06 -6.361136E-03 -7.935395E-06 -7.066013E-03 -9.687252E-06 -8.347614E-03 -1.322030E-05 -5.583607E-03 -6.318991E-06 -9.734817E-03 -1.915868E-05 -9.117770E-03 -1.299951E-05 -5.466583E-03 -5.814486E-06 -6.377661E-03 -5.982386E-06 -1.066356E-02 -1.915872E-05 -1.205945E-02 -1.894758E-05 -9.934821E-03 -1.678379E-05 -1.138156E-02 -2.321476E-05 -1.063324E-02 -1.739239E-05 -8.377153E-03 -1.072894E-05 -1.600249E-02 -3.173041E-05 -1.442818E-02 -3.650694E-05 -1.643458E-02 -2.935759E-05 -1.937762E-02 -5.539763E-05 -8.400592E-03 -1.059830E-05 -1.497133E-02 -3.316378E-05 -1.469275E-02 -3.001660E-05 -1.502203E-02 -2.852008E-05 -9.750216E-03 -1.395013E-05 -1.497859E-02 -2.421550E-05 -2.111839E-02 -6.023324E-05 -1.358782E-02 -2.820256E-05 -1.250078E-02 -2.294909E-05 -1.058650E-02 -1.688760E-05 -1.488385E-02 -2.666627E-05 -1.927781E-02 -5.429379E-05 -1.208022E-02 -2.250992E-05 -1.497153E-02 -2.676884E-05 -1.244590E-02 -2.756211E-05 -9.989045E-03 -1.303571E-05 -8.894574E-03 -1.174122E-05 -1.938283E-02 -4.239857E-05 -1.804394E-02 -3.515511E-05 -1.337739E-02 -2.482975E-05 -1.487943E-02 -3.347708E-05 -1.110033E-02 -2.136237E-05 -1.333452E-02 -2.308294E-05 -1.635319E-02 -3.229248E-05 -8.693802E-03 -1.542452E-05 -1.031414E-02 -2.112585E-05 -1.838966E-02 -4.539908E-05 -2.354073E-02 -7.698141E-05 -1.080321E-02 -1.831625E-05 -2.112481E-02 -6.253585E-05 -2.050287E-02 -5.388829E-05 -1.779381E-02 -3.937477E-05 -1.477468E-02 -2.411115E-05 -1.293051E-02 -2.250585E-05 -1.609738E-02 -3.396791E-05 -2.681377E-02 -8.749523E-05 -1.670204E-02 -4.359534E-05 -2.206205E-02 -6.377754E-05 -1.873639E-02 -5.703093E-05 -1.889950E-02 -5.052682E-05 -1.824219E-02 -6.072963E-05 -9.270805E-03 -9.959479E-06 -1.684688E-02 -3.370730E-05 -1.521705E-02 -2.961236E-05 -1.701708E-02 -4.241891E-05 -1.338529E-02 -2.440114E-05 -2.037312E-02 -5.462555E-05 -1.229143E-02 -1.878363E-05 -1.429618E-02 -3.043241E-05 -1.452304E-02 -3.335612E-05 -1.081202E-02 -1.892516E-05 -1.166461E-02 -2.163556E-05 -9.237578E-03 -1.212749E-05 -1.315603E-02 -2.637907E-05 -1.701531E-02 -4.938074E-05 -1.071566E-02 -1.400306E-05 -6.882737E-03 -1.095801E-05 -9.693556E-03 -1.516152E-05 -1.473076E-02 -4.380304E-05 -1.172802E-02 -2.661846E-05 -1.044100E-02 -1.616180E-05 -1.321485E-02 -2.517015E-05 -1.034434E-02 -2.118831E-05 -1.604723E-02 -3.547683E-05 -1.309313E-02 -2.716364E-05 -1.410482E-02 -2.701123E-05 -1.932682E-02 -4.094043E-05 -1.570824E-02 -3.228547E-05 -1.071500E-02 -2.525484E-05 -9.230951E-03 -1.398163E-05 -1.889558E-02 -4.381257E-05 -1.401925E-02 -2.692560E-05 -9.335801E-03 -1.384367E-05 -1.635939E-02 -3.876884E-05 -9.920998E-03 -1.367019E-05 -1.029500E-02 -1.637783E-05 -8.294680E-03 -1.093734E-05 -1.266183E-02 -2.587245E-05 -1.407777E-02 -2.856187E-05 -1.854542E-02 -4.825382E-05 -5.748894E-03 -8.790611E-06 -6.718806E-03 -1.183924E-05 -8.894787E-03 -1.306300E-05 -9.405707E-03 -1.288762E-05 -8.792692E-03 -1.122248E-05 -1.103181E-02 -1.580934E-05 -2.659005E-03 -1.548241E-06 -7.016434E-03 -7.516622E-06 -7.803753E-03 -1.013698E-05 -5.086094E-03 -7.063507E-06 -6.912737E-03 -6.574511E-06 -6.396947E-03 -6.066584E-06 -3.808735E-03 -2.749937E-06 -1.756683E-03 -8.375727E-07 -5.851836E-03 -1.028488E-05 -4.947448E-03 -5.127717E-06 -2.630989E-03 -1.428143E-06 -2.910935E-03 -1.681876E-06 -1.838842E-03 -8.992911E-07 -1.293684E-03 -6.685764E-07 -3.339457E-03 -3.028553E-06 -4.580626E-03 -4.624997E-06 -8.307235E-03 -1.674431E-05 -4.486573E-03 -3.705825E-06 -1.144529E-02 -2.352240E-05 -4.880878E-03 -3.852879E-06 -1.005985E-02 -1.391072E-05 -5.741160E-03 -7.136284E-06 -3.844734E-03 -3.016161E-06 -4.765015E-03 -4.225164E-06 -9.903891E-03 -1.243668E-05 -6.186072E-03 -7.288467E-06 -5.025861E-03 -4.672189E-06 -9.762213E-03 -1.357133E-05 -7.207433E-03 -1.732068E-05 -7.775127E-03 -1.904290E-05 -8.549835E-03 -9.367660E-06 -7.175698E-03 -7.187069E-06 -9.296385E-03 -1.322855E-05 -1.130874E-02 -1.956313E-05 -6.989995E-03 -7.487382E-06 -9.825026E-03 -1.567524E-05 -8.647918E-03 -1.652352E-05 -1.087355E-02 -1.533263E-05 -8.616514E-03 -1.142788E-05 -7.352790E-03 -1.365573E-05 -1.138586E-02 -2.265717E-05 -8.641472E-03 -1.322858E-05 -1.041352E-02 -1.315105E-05 -7.829927E-03 -1.004051E-05 -1.425328E-02 -2.580893E-05 -8.892806E-03 -1.300336E-05 -7.287566E-03 -1.259700E-05 -1.443032E-02 -3.334244E-05 -1.017849E-02 -1.483161E-05 -1.467996E-02 -3.045887E-05 -5.224154E-03 -5.244222E-06 -9.725108E-03 -1.589220E-05 -7.665836E-03 -1.588331E-05 -1.010342E-02 -1.784078E-05 -9.419018E-03 -1.369817E-05 -8.670373E-03 -1.032775E-05 -1.138937E-02 -1.811885E-05 -1.798735E-02 -4.793175E-05 -1.065784E-02 -1.799829E-05 -1.308082E-02 -2.484335E-05 -1.240918E-02 -2.570768E-05 -1.745339E-02 -5.770116E-05 -9.113925E-03 -1.349884E-05 -1.402932E-02 -2.482802E-05 -1.888352E-02 -4.563824E-05 -1.225796E-02 -2.638006E-05 -6.431220E-03 -8.855282E-06 -4.770081E-03 -4.250052E-06 -1.089652E-02 -1.611332E-05 -8.433574E-03 -1.309921E-05 -8.737584E-03 -1.411637E-05 -1.265065E-02 -2.849634E-05 -6.191713E-03 -9.561153E-06 -1.006364E-02 -1.497675E-05 -5.975885E-03 -7.218506E-06 -8.088755E-03 -1.058200E-05 -1.148407E-02 -1.800324E-05 -8.621138E-03 -1.060417E-05 -6.466931E-03 -5.559033E-06 -5.921299E-03 -7.337435E-06 -1.106199E-02 -1.985630E-05 -1.358816E-02 -2.266472E-05 -9.249095E-03 -1.326487E-05 -1.231097E-02 -2.413051E-05 -1.262777E-02 -2.135896E-05 -1.340058E-02 -2.838546E-05 -5.482441E-03 -5.699830E-06 -9.399780E-03 -1.217503E-05 -1.326355E-02 -3.084524E-05 -1.091665E-02 -1.571125E-05 -9.066945E-03 -1.253097E-05 -1.007715E-02 -1.495997E-05 -1.420187E-02 -3.247816E-05 -8.867918E-03 -1.783720E-05 -1.035797E-02 -1.618714E-05 -1.051439E-02 -1.905852E-05 -9.663711E-03 -1.733227E-05 -6.083326E-03 -8.227985E-06 -8.498983E-03 -1.203506E-05 -6.305066E-03 -7.288313E-06 -7.022938E-03 -1.842350E-05 -5.300040E-03 -6.674218E-06 -1.192288E-02 -2.251146E-05 -1.268268E-02 -2.376464E-05 -1.105252E-02 -1.907200E-05 -1.141409E-02 -2.122429E-05 -6.863367E-03 -9.680619E-06 -9.454583E-03 -1.410784E-05 -6.678539E-03 -7.419299E-06 -5.435679E-03 -5.223001E-06 -5.839983E-03 -7.472675E-06 -4.126792E-03 -4.743950E-06 -6.770400E-03 -9.680068E-06 -6.192936E-03 -7.071171E-06 -5.115501E-03 -7.222293E-06 -9.291347E-03 -2.204886E-05 -9.263101E-03 -2.093887E-05 -4.871234E-03 -4.945479E-06 -7.362790E-03 -1.225470E-05 -4.662289E-03 -6.432463E-06 -3.023591E-03 -2.882907E-06 -3.141104E-03 -2.308920E-06 -4.357737E-03 -7.258711E-06 -6.160322E-03 -8.985831E-06 -2.171491E-03 -1.749207E-06 -6.561643E-03 -8.803272E-06 -7.571781E-03 -1.203184E-05 -7.440169E-03 -1.110403E-05 -5.648646E-03 -5.494924E-06 -5.357281E-03 -6.204706E-06 -1.090071E-02 -2.058466E-05 -8.383241E-03 -1.206302E-05 -5.676127E-03 -7.724753E-06 -7.425364E-03 -1.054573E-05 -5.486371E-03 -8.048247E-06 -8.635014E-03 -1.394706E-05 -9.041685E-03 -1.478222E-05 -8.430211E-03 -1.309974E-05 -9.019663E-03 -1.451788E-05 -1.031929E-02 -1.746481E-05 -8.473885E-03 -1.174896E-05 -7.773439E-03 -1.036634E-05 -6.249343E-03 -6.064341E-06 -7.095661E-03 -1.120516E-05 -8.128270E-03 -7.992625E-06 -8.497285E-03 -1.303653E-05 -9.777637E-03 -1.235924E-05 -9.741495E-03 -1.557086E-05 -7.393292E-03 -1.285346E-05 -9.196281E-03 -1.458607E-05 -8.847877E-03 -1.117609E-05 -9.688267E-03 -1.592845E-05 -8.380207E-03 -9.989138E-06 -6.280642E-03 -9.051451E-06 -5.915732E-03 -6.877346E-06 -7.178298E-03 -7.637799E-06 -1.393362E-02 -3.213127E-05 -1.124851E-02 -1.946971E-05 -7.778231E-03 -8.216708E-06 -1.100977E-02 -1.616695E-05 -9.914677E-03 -1.920656E-05 -1.140639E-02 -1.803697E-05 -9.289048E-03 -2.453446E-05 -1.333524E-02 -2.981179E-05 -1.511863E-02 -3.813471E-05 -1.309031E-02 -3.606896E-05 -9.646063E-03 -1.776204E-05 -1.508239E-02 -3.051447E-05 -1.260645E-02 -2.587693E-05 -1.462482E-02 -3.353264E-05 -1.521268E-02 -3.209409E-05 -1.468435E-02 -2.541208E-05 -1.071159E-02 -1.974334E-05 -2.153100E-02 -5.966820E-05 -1.732644E-02 -4.011287E-05 -1.667843E-02 -3.822452E-05 -1.463217E-02 -3.010523E-05 -1.656645E-02 -5.475637E-05 -1.067989E-02 -1.830023E-05 -8.824628E-03 -1.045690E-05 -2.286417E-02 -6.960907E-05 -1.839696E-02 -4.509087E-05 -1.925060E-02 -3.941153E-05 -2.258451E-02 -6.336171E-05 -1.439116E-02 -3.414902E-05 -1.155750E-02 -1.864626E-05 -1.259396E-02 -2.399348E-05 -1.558812E-02 -4.045055E-05 -1.722120E-02 -4.143410E-05 -1.762002E-02 -3.632759E-05 -7.874101E-03 -8.254184E-06 -1.768575E-02 -3.461006E-05 -1.146683E-02 -1.794910E-05 -9.688500E-03 -1.346720E-05 -2.241492E-02 -6.339022E-05 -1.934312E-02 -4.482690E-05 -1.794148E-02 -3.870190E-05 -1.579372E-02 -3.004235E-05 -1.087259E-02 -1.529755E-05 -1.257568E-02 -2.258086E-05 -1.388017E-02 -3.225403E-05 -1.427934E-02 -2.832685E-05 -1.576751E-02 -4.828020E-05 -9.333555E-03 -1.323683E-05 -1.295220E-02 -2.221784E-05 -1.292944E-02 -2.650558E-05 -1.321910E-02 -2.608639E-05 -1.867794E-02 -5.342650E-05 -1.187778E-02 -2.004699E-05 -1.570348E-02 -3.839194E-05 -7.349983E-03 -1.280817E-05 -1.048335E-02 -1.591520E-05 -1.281254E-02 -2.311657E-05 -9.441415E-03 -1.884897E-05 -7.817420E-03 -1.075829E-05 -7.050894E-03 -8.992796E-06 -1.439696E-02 -2.646431E-05 -9.666048E-03 -1.691859E-05 -1.384058E-02 -2.171361E-05 -1.483968E-02 -2.360714E-05 -6.696329E-03 -8.201920E-06 -1.461109E-02 -3.484250E-05 -1.152968E-02 -2.487151E-05 -1.235571E-02 -1.863282E-05 -1.071843E-02 -2.007060E-05 -1.192423E-02 -2.405436E-05 -5.175335E-03 -5.686680E-06 -6.167308E-03 -6.085033E-06 -6.512706E-03 -7.423219E-06 -1.084502E-02 -2.042988E-05 -1.426237E-02 -3.199412E-05 -9.833550E-03 -1.401763E-05 -1.066371E-02 -2.034673E-05 -1.088205E-02 -1.432050E-05 -1.322884E-03 -6.133009E-07 -3.131323E-03 -2.085873E-06 -7.577039E-03 -1.169415E-05 -3.697020E-03 -2.265535E-06 -8.463691E-04 -7.163407E-07 -4.936343E-03 -4.470816E-06 -2.785210E-03 -2.057770E-06 -4.647148E-03 -1.334765E-05 -4.739139E-03 -4.910528E-06 -2.212737E-03 -9.823784E-07 -3.179311E-03 -2.106597E-06 -5.139877E-03 -6.883127E-06 -6.756613E-03 -1.192459E-05 -9.019603E-03 -1.454516E-05 -7.170921E-03 -1.179166E-05 -1.332204E-02 -2.272315E-05 -1.045555E-02 -1.579302E-05 -1.471762E-02 -2.957336E-05 -6.940743E-03 -6.167781E-06 -9.285093E-03 -1.234474E-05 -5.274768E-03 -9.733764E-06 -9.363326E-03 -1.064273E-05 -1.124025E-02 -1.812349E-05 -1.242897E-02 -2.335802E-05 -1.381362E-02 -3.426304E-05 -9.040314E-03 -1.768352E-05 -8.800291E-03 -1.233677E-05 -6.219799E-03 -6.238154E-06 -9.482593E-03 -1.409322E-05 -1.380779E-02 -2.529043E-05 -1.200427E-02 -2.953271E-05 -1.419132E-02 -3.098266E-05 -1.353906E-02 -2.607804E-05 -1.431241E-02 -2.799048E-05 -1.223915E-02 -2.748804E-05 -1.852083E-02 -5.311250E-05 -1.887810E-02 -5.774443E-05 -1.277722E-02 -2.643979E-05 -8.077414E-03 -1.128725E-05 -1.339142E-02 -2.294610E-05 -1.301300E-02 -2.073634E-05 -1.397830E-02 -3.029223E-05 -1.892762E-02 -4.920518E-05 -1.535394E-02 -4.149745E-05 -1.298011E-02 -2.187906E-05 -1.905806E-02 -4.036737E-05 -1.706919E-02 -3.990119E-05 -1.435454E-02 -2.543584E-05 -1.937779E-02 -5.201021E-05 -2.323117E-02 -6.155812E-05 -1.994685E-02 -5.377319E-05 -1.320573E-02 -2.175679E-05 -1.591133E-02 -3.535892E-05 -2.108852E-02 -6.407539E-05 -1.839423E-02 -4.410414E-05 -2.011863E-02 -4.580140E-05 -1.883453E-02 -4.495207E-05 -2.134485E-02 -5.276746E-05 -1.725640E-02 -4.465566E-05 -2.590341E-02 -8.438375E-05 -2.198626E-02 -5.942456E-05 -1.721832E-02 -3.710932E-05 -1.867389E-02 -4.165207E-05 -2.535786E-02 -8.231711E-05 -2.435788E-02 -7.524302E-05 -2.417986E-02 -7.690249E-05 -3.527942E-02 -1.503529E-04 -2.545610E-02 -7.903560E-05 -2.898461E-02 -1.038511E-04 -2.650130E-02 -7.765544E-05 -3.220034E-02 -1.339104E-04 -2.615617E-02 -8.054223E-05 -1.575566E-02 -3.464485E-05 -1.721242E-02 -3.933144E-05 -2.529147E-02 -7.224719E-05 -2.161550E-02 -5.729706E-05 -3.254276E-02 -1.237101E-04 -2.601524E-02 -7.880812E-05 -2.030934E-02 -5.449343E-05 -2.529817E-02 -7.746587E-05 -2.459558E-02 -7.049178E-05 -2.743013E-02 -1.051976E-04 -2.818835E-02 -9.687328E-05 -3.082240E-02 -1.199245E-04 -1.534318E-02 -3.153431E-05 -1.798131E-02 -4.183178E-05 -1.329898E-02 -2.483181E-05 -1.519124E-02 -3.090643E-05 -2.253493E-02 -6.110325E-05 -1.932903E-02 -5.403216E-05 -2.343651E-02 -6.986521E-05 -1.851194E-02 -4.830851E-05 -2.854734E-02 -1.149020E-04 -3.554508E-02 -1.594168E-04 -2.420896E-02 -8.063001E-05 -2.438815E-02 -6.949914E-05 -1.424242E-02 -3.042725E-05 -1.883095E-02 -4.453941E-05 -1.803807E-02 -5.353218E-05 -1.472433E-02 -2.708169E-05 -2.645673E-02 -1.277462E-04 -1.659156E-02 -4.460790E-05 -1.884914E-02 -5.255122E-05 -1.323181E-02 -3.012118E-05 -2.078655E-02 -7.250952E-05 -1.929529E-02 -4.896056E-05 -1.365072E-02 -2.296122E-05 -1.548320E-02 -3.361702E-05 -1.963984E-02 -5.182163E-05 -1.938728E-02 -4.745111E-05 -1.852813E-02 -4.964750E-05 -1.254203E-02 -2.416303E-05 -1.598636E-02 -3.867130E-05 -1.557994E-02 -3.560554E-05 -8.834017E-03 -1.069678E-05 -9.484032E-03 -1.565529E-05 -1.303143E-02 -2.234676E-05 -2.200867E-02 -5.927220E-05 -1.598709E-02 -2.961814E-05 -1.402800E-02 -2.779038E-05 -4.378255E-03 -4.055161E-06 -6.657558E-03 -8.689849E-06 -5.742424E-03 -6.994090E-06 -1.690917E-03 -9.618234E-07 -6.422205E-03 -6.220083E-06 -1.098008E-02 -1.552449E-05 -4.852648E-03 -6.005700E-06 -4.131316E-03 -2.940200E-06 -5.377384E-03 -9.958808E-06 -7.493944E-03 -1.136740E-05 -5.679683E-03 -5.334788E-06 -9.041948E-03 -1.233892E-05 -1.621598E-02 -3.896922E-05 -9.707536E-03 -1.580953E-05 -9.796285E-03 -1.170913E-05 -1.038632E-02 -1.400251E-05 -1.854616E-02 -3.938948E-05 -1.637195E-02 -3.459637E-05 -1.090541E-02 -1.920540E-05 -1.554833E-02 -3.590212E-05 -4.272073E-03 -3.682734E-06 -9.074265E-03 -9.996509E-06 -1.177873E-02 -2.562780E-05 -1.154733E-02 -1.708677E-05 -2.122244E-02 -5.095551E-05 -1.703089E-02 -4.517001E-05 -1.005035E-02 -1.266093E-05 -1.780384E-02 -3.747413E-05 -1.376515E-02 -3.253018E-05 -1.530894E-02 -2.892052E-05 -2.606504E-02 -7.859853E-05 -2.255541E-02 -6.286365E-05 -1.918774E-02 -4.676979E-05 -2.519231E-02 -7.640422E-05 -1.664088E-02 -4.401309E-05 -1.584636E-02 -3.452858E-05 -2.616309E-02 -8.630269E-05 -2.255699E-02 -5.940173E-05 -2.236967E-02 -6.994996E-05 -2.248979E-02 -5.377855E-05 -2.341480E-02 -6.489990E-05 -2.206893E-02 -5.500117E-05 -3.339387E-02 -1.332827E-04 -2.791990E-02 -9.540192E-05 -2.717893E-02 -9.827563E-05 -2.822648E-02 -9.247065E-05 -2.172258E-02 -6.122060E-05 -2.728508E-02 -9.267319E-05 -2.826253E-02 -1.031269E-04 -2.187117E-02 -5.283388E-05 -2.020422E-02 -6.258085E-05 -2.760119E-02 -8.854689E-05 -2.549801E-02 -7.868954E-05 -3.220341E-02 -1.492987E-04 -3.173533E-02 -1.221411E-04 -3.585220E-02 -1.462868E-04 -2.903224E-02 -9.451319E-05 -3.829574E-02 -1.873248E-04 -3.086935E-02 -1.256218E-04 -3.176725E-02 -1.374912E-04 -2.621060E-02 -7.855573E-05 -3.291329E-02 -1.248943E-04 -2.777869E-02 -9.696220E-05 -2.695184E-02 -8.169195E-05 -3.242055E-02 -1.203522E-04 -3.779282E-02 -1.712919E-04 -3.692252E-02 -1.722327E-04 -2.748845E-02 -9.639756E-05 -3.175151E-02 -1.162038E-04 -3.286221E-02 -1.232662E-04 -3.712727E-02 -1.594838E-04 -4.431598E-02 -2.588766E-04 -2.816960E-02 -9.502113E-05 -2.976286E-02 -1.142861E-04 -2.180841E-02 -6.585707E-05 -2.719208E-02 -8.542344E-05 -3.801560E-02 -1.668348E-04 -3.413937E-02 -1.429112E-04 -3.175514E-02 -1.235214E-04 -4.203652E-02 -2.192502E-04 -4.877746E-02 -2.744258E-04 -5.692679E-02 -3.692246E-04 -4.818489E-02 -2.687441E-04 -5.535578E-02 -3.290118E-04 -3.156612E-02 -1.123567E-04 -2.679829E-02 -7.787807E-05 -2.954264E-02 -1.270123E-04 -2.476226E-02 -8.030343E-05 -3.814973E-02 -1.578272E-04 -4.016143E-02 -2.884730E-04 -4.229195E-02 -2.061337E-04 -2.947005E-02 -1.041482E-04 -3.357567E-02 -1.360735E-04 -4.664871E-02 -2.552612E-04 -4.112621E-02 -2.176987E-04 -3.595856E-02 -1.956542E-04 -1.913431E-02 -5.063581E-05 -2.330523E-02 -6.230393E-05 -2.045993E-02 -5.592751E-05 -2.473756E-02 -7.625570E-05 -3.674309E-02 -1.672365E-04 -3.204595E-02 -1.157121E-04 -2.629494E-02 -8.519728E-05 -3.002442E-02 -1.205283E-04 -3.236353E-02 -1.309526E-04 -3.239381E-02 -1.479481E-04 -2.659107E-02 -1.086535E-04 -3.565570E-02 -1.622239E-04 -1.031682E-02 -1.492807E-05 -1.580618E-02 -2.893579E-05 -1.666675E-02 -4.393186E-05 -2.024456E-02 -4.734254E-05 -1.651767E-02 -4.977631E-05 -1.887559E-02 -4.409518E-05 -1.508773E-02 -4.644738E-05 -1.388725E-02 -2.554677E-05 -2.369485E-02 -7.387938E-05 -1.868167E-02 -4.664973E-05 -1.516685E-02 -3.321346E-05 -1.963316E-02 -4.662537E-05 -7.052241E-03 -1.080582E-05 -1.204334E-02 -2.356212E-05 -7.618798E-03 -1.308303E-05 -1.218334E-02 -2.230559E-05 -1.192185E-02 -2.127660E-05 -1.044557E-02 -1.520178E-05 -4.348002E-03 -4.867274E-06 -9.181379E-03 -1.456359E-05 -8.481267E-03 -1.556887E-05 -5.867984E-03 -5.323949E-06 -1.523208E-02 -3.002171E-05 -8.902081E-03 -1.728737E-05 -1.212351E-02 -2.267329E-05 -1.158769E-02 -1.826918E-05 -5.557893E-03 -6.873951E-06 -1.030077E-02 -1.814127E-05 -1.216476E-02 -2.168097E-05 -1.280341E-02 -2.462766E-05 -7.553244E-03 -7.549456E-06 -9.275611E-03 -9.489655E-06 -7.606773E-03 -8.958010E-06 -9.160622E-03 -1.424787E-05 -1.133109E-02 -1.611610E-05 -7.409008E-03 -1.208115E-05 -2.084102E-02 -5.449907E-05 -2.465743E-02 -1.037751E-04 -2.310657E-02 -6.292924E-05 -2.801769E-02 -8.512445E-05 -2.049117E-02 -6.630728E-05 -1.395829E-02 -3.118581E-05 -2.735901E-02 -9.218170E-05 -2.177632E-02 -5.817883E-05 -1.932991E-02 -6.388604E-05 -2.326591E-02 -8.330336E-05 -2.546379E-02 -9.605909E-05 -1.830716E-02 -5.090147E-05 -3.960142E-02 -1.859660E-04 -2.348343E-02 -6.600054E-05 -2.909393E-02 -1.040812E-04 -3.586926E-02 -1.451039E-04 -2.269127E-02 -6.430762E-05 -2.691696E-02 -8.449728E-05 -4.229624E-02 -2.362055E-04 -4.471419E-02 -2.231402E-04 -3.407449E-02 -1.370223E-04 -3.586700E-02 -1.483496E-04 -3.803403E-02 -1.652852E-04 -3.820565E-02 -1.619415E-04 -2.921534E-02 -1.128913E-04 -4.098638E-02 -1.981151E-04 -3.611801E-02 -1.596274E-04 -4.036543E-02 -1.787815E-04 -3.018584E-02 -1.080246E-04 -4.026732E-02 -1.932383E-04 -4.637639E-02 -3.369042E-04 -4.901208E-02 -2.912517E-04 -5.221514E-02 -2.936532E-04 -5.298382E-02 -3.167761E-04 -4.141488E-02 -1.913012E-04 -5.078383E-02 -2.957356E-04 -3.104830E-02 -1.114729E-04 -4.570836E-02 -2.306958E-04 -2.697314E-02 -8.551540E-05 -3.590745E-02 -1.369825E-04 -4.416767E-02 -2.348955E-04 -3.878026E-02 -1.683331E-04 -3.635274E-02 -1.469492E-04 -5.095760E-02 -3.033151E-04 -5.419363E-02 -3.231656E-04 -6.111133E-02 -4.092896E-04 -5.080100E-02 -2.813520E-04 -6.152776E-02 -4.073105E-04 -3.751766E-02 -1.468483E-04 -3.277827E-02 -1.186335E-04 -3.710633E-02 -1.751177E-04 -5.323020E-02 -3.420073E-04 -3.201431E-02 -1.550803E-04 -5.882138E-02 -4.307388E-04 -4.562728E-02 -2.741025E-04 -4.436946E-02 -2.582142E-04 -4.128151E-02 -1.889531E-04 -5.761773E-02 -4.256437E-04 -4.986009E-02 -2.652036E-04 -5.753376E-02 -3.668636E-04 -3.464308E-02 -1.308318E-04 -3.597366E-02 -1.880711E-04 -3.783475E-02 -1.677422E-04 -4.507477E-02 -2.257889E-04 -3.512550E-02 -1.623708E-04 -4.440361E-02 -2.237977E-04 -4.763862E-02 -2.507592E-04 -4.245582E-02 -2.037194E-04 -3.865696E-02 -1.809637E-04 -4.216341E-02 -1.962900E-04 -5.099828E-02 -2.952246E-04 -5.108812E-02 -2.920996E-04 -2.655713E-02 -8.104377E-05 -3.189652E-02 -1.226231E-04 -3.163248E-02 -1.587616E-04 -2.509589E-02 -9.570491E-05 -4.297892E-02 -2.277676E-04 -3.642828E-02 -1.647058E-04 -3.007066E-02 -1.231652E-04 -3.132243E-02 -1.486680E-04 -3.188231E-02 -1.196363E-04 -4.753178E-02 -2.731076E-04 -2.908004E-02 -1.035304E-04 -2.727262E-02 -9.600226E-05 -1.855747E-02 -5.837677E-05 -2.435306E-02 -7.097335E-05 -2.204917E-02 -6.488149E-05 -2.268670E-02 -6.926881E-05 -2.470896E-02 -8.507493E-05 -2.736268E-02 -9.366711E-05 -1.453619E-02 -2.821293E-05 -1.989468E-02 -5.291966E-05 -2.569258E-02 -8.578609E-05 -2.226465E-02 -6.565828E-05 -2.252517E-02 -7.081452E-05 -1.855256E-02 -4.738776E-05 -1.203698E-02 -2.579555E-05 -1.218962E-02 -2.270495E-05 -1.171765E-02 -2.354905E-05 -8.779187E-03 -1.212571E-05 -1.425888E-02 -2.553189E-05 -1.169957E-02 -2.644501E-05 -1.052860E-02 -1.949914E-05 -5.907471E-03 -5.068540E-06 -1.275403E-02 -2.624760E-05 -1.148436E-02 -1.794213E-05 -1.018673E-02 -1.501340E-05 -1.783660E-02 -4.785080E-05 -1.016197E-02 -2.293166E-05 -8.941927E-03 -1.192991E-05 -6.602581E-03 -1.272161E-05 -1.174062E-02 -2.147543E-05 -1.526300E-02 -3.260204E-05 -1.686817E-02 -4.102027E-05 -1.467939E-02 -2.968059E-05 -1.601430E-02 -4.562808E-05 -9.165391E-03 -2.688624E-05 -9.663957E-03 -1.372277E-05 -1.287992E-02 -2.365195E-05 -9.579531E-03 -1.375180E-05 -2.469585E-02 -8.049487E-05 -2.845287E-02 -1.112732E-04 -1.767051E-02 -4.658157E-05 -2.485448E-02 -9.432058E-05 -1.238872E-02 -2.846828E-05 -1.889711E-02 -4.468197E-05 -3.099403E-02 -1.059405E-04 -2.259916E-02 -7.077471E-05 -2.695314E-02 -9.575430E-05 -2.211342E-02 -5.413822E-05 -2.224612E-02 -7.249655E-05 -1.773084E-02 -4.592694E-05 -3.194210E-02 -1.064003E-04 -2.971760E-02 -9.736956E-05 -3.499652E-02 -1.826230E-04 -4.850239E-02 -2.738683E-04 -3.305773E-02 -1.168139E-04 -3.506155E-02 -1.587282E-04 -3.676758E-02 -1.484870E-04 -4.676291E-02 -2.525569E-04 -3.590431E-02 -1.478484E-04 -3.835973E-02 -1.689943E-04 -4.592471E-02 -2.353405E-04 -4.213441E-02 -2.024568E-04 -4.148586E-02 -1.780338E-04 -4.501161E-02 -2.189422E-04 -4.546973E-02 -2.294416E-04 -5.445339E-02 -3.211478E-04 -4.091696E-02 -1.919828E-04 -4.547941E-02 -2.523329E-04 -5.386399E-02 -3.097517E-04 -5.805028E-02 -3.886410E-04 -4.323647E-02 -2.210891E-04 -5.481511E-02 -3.380385E-04 -5.588950E-02 -3.728116E-04 -4.521068E-02 -2.655202E-04 -4.323965E-02 -1.976109E-04 -4.853174E-02 -2.734839E-04 -5.925107E-02 -4.092840E-04 -6.126965E-02 -3.889545E-04 -5.496039E-02 -3.536070E-04 -5.043703E-02 -3.116190E-04 -5.642187E-02 -3.765290E-04 -6.063856E-02 -4.379295E-04 -5.195487E-02 -3.214080E-04 -6.938655E-02 -5.412456E-04 -6.384563E-02 -4.345441E-04 -7.340916E-02 -5.829419E-04 -4.160832E-02 -1.915303E-04 -4.400244E-02 -2.364017E-04 -5.387088E-02 -3.278923E-04 -5.794972E-02 -3.768932E-04 -4.823866E-02 -2.869653E-04 -5.581812E-02 -3.628216E-04 -5.507172E-02 -3.230172E-04 -6.302356E-02 -4.527401E-04 -5.707918E-02 -3.888513E-04 -4.754358E-02 -2.594617E-04 -6.541199E-02 -4.781326E-04 -6.028104E-02 -4.146449E-04 -3.451579E-02 -1.431485E-04 -3.241942E-02 -1.223581E-04 -4.685494E-02 -2.525308E-04 -4.111890E-02 -2.121316E-04 -4.153961E-02 -1.996497E-04 -5.816750E-02 -3.609870E-04 -3.677652E-02 -1.668470E-04 -4.696518E-02 -2.600495E-04 -3.377120E-02 -1.501347E-04 -4.376838E-02 -2.325356E-04 -5.222808E-02 -3.054620E-04 -5.928320E-02 -4.267763E-04 -2.991812E-02 -1.056949E-04 -3.616946E-02 -1.524179E-04 -3.177703E-02 -1.168362E-04 -4.705585E-02 -2.646056E-04 -3.665252E-02 -1.695105E-04 -4.766781E-02 -2.674389E-04 -3.202832E-02 -1.073493E-04 -2.751650E-02 -9.309837E-05 -4.818224E-02 -2.392320E-04 -3.403290E-02 -1.418131E-04 -4.574016E-02 -2.354785E-04 -4.773050E-02 -2.476124E-04 -1.973857E-02 -5.421533E-05 -2.110340E-02 -6.009155E-05 -2.365572E-02 -6.648519E-05 -2.131581E-02 -5.365256E-05 -2.548189E-02 -8.296044E-05 -2.738380E-02 -8.103041E-05 -1.857273E-02 -4.206503E-05 -2.430428E-02 -7.766038E-05 -1.413939E-02 -2.821225E-05 -2.111430E-02 -5.198944E-05 -2.690085E-02 -9.577166E-05 -3.477173E-02 -1.518451E-04 -1.694126E-02 -4.610916E-05 -1.802237E-02 -4.677578E-05 -1.547843E-02 -3.071140E-05 -1.258621E-02 -2.676730E-05 -1.480772E-02 -2.870448E-05 -1.612853E-02 -3.275094E-05 -1.269558E-02 -2.294471E-05 -1.222544E-02 -1.845380E-05 -1.456829E-02 -3.311358E-05 -9.857513E-03 -1.669207E-05 -1.626604E-02 -4.458605E-05 -1.611973E-02 -3.998382E-05 -1.971005E-02 -6.046116E-05 -1.431380E-02 -2.594436E-05 -1.824132E-02 -5.495026E-05 -1.868711E-02 -5.257059E-05 -1.452558E-02 -2.646510E-05 -1.767521E-02 -4.157062E-05 -1.224286E-02 -2.048681E-05 -1.303634E-02 -2.950766E-05 -1.330541E-02 -2.767230E-05 -1.068270E-02 -1.441894E-05 -1.784826E-02 -4.556976E-05 -1.384211E-02 -2.825659E-05 -1.729138E-02 -3.675164E-05 -2.243899E-02 -6.004831E-05 -2.715655E-02 -9.746046E-05 -2.570504E-02 -8.920071E-05 -1.697516E-02 -3.974905E-05 -1.660121E-02 -3.254815E-05 -2.224450E-02 -5.768880E-05 -2.530951E-02 -9.164893E-05 -1.840321E-02 -4.291921E-05 -2.017760E-02 -6.034117E-05 -2.049468E-02 -4.717679E-05 -2.282381E-02 -6.631028E-05 -2.767431E-02 -8.578573E-05 -3.024946E-02 -1.035261E-04 -3.587885E-02 -1.385980E-04 -4.511890E-02 -2.188810E-04 -2.993143E-02 -1.172685E-04 -4.054681E-02 -1.947113E-04 -3.798858E-02 -1.756458E-04 -4.431323E-02 -2.215003E-04 -3.189602E-02 -1.184446E-04 -3.858052E-02 -1.789441E-04 -4.477428E-02 -2.243938E-04 -4.703586E-02 -2.423313E-04 -3.435009E-02 -1.302766E-04 -4.912269E-02 -2.876019E-04 -3.586050E-02 -1.601671E-04 -5.202288E-02 -2.962633E-04 -4.354503E-02 -2.302813E-04 -4.484413E-02 -2.193914E-04 -4.626090E-02 -2.295773E-04 -5.272085E-02 -3.140576E-04 -4.016476E-02 -1.851520E-04 -4.698312E-02 -2.700090E-04 -7.091623E-02 -6.301431E-04 -4.767851E-02 -2.507174E-04 -4.786618E-02 -2.609399E-04 -4.038170E-02 -1.767402E-04 -4.773992E-02 -2.552553E-04 -6.553326E-02 -4.533702E-04 -4.409668E-02 -2.246932E-04 -5.516788E-02 -3.459366E-04 -5.575453E-02 -3.327095E-04 -6.234876E-02 -4.350389E-04 -4.468174E-02 -2.279110E-04 -5.066531E-02 -2.919067E-04 -7.038547E-02 -5.211120E-04 -6.314941E-02 -4.264819E-04 -4.552569E-02 -2.253455E-04 -4.441783E-02 -2.383583E-04 -5.471130E-02 -3.515655E-04 -5.570461E-02 -3.610859E-04 -4.732130E-02 -2.515536E-04 -5.830395E-02 -4.045076E-04 -4.928927E-02 -2.534507E-04 -4.443354E-02 -2.155311E-04 -4.739067E-02 -2.296684E-04 -4.805589E-02 -2.422571E-04 -6.278404E-02 -4.449155E-04 -6.952048E-02 -5.145532E-04 -2.516418E-02 -7.500451E-05 -3.118980E-02 -1.112167E-04 -4.421923E-02 -2.460515E-04 -4.297090E-02 -2.413819E-04 -3.779702E-02 -1.857046E-04 -5.299210E-02 -3.257368E-04 -4.026655E-02 -1.807099E-04 -4.206085E-02 -2.256535E-04 -4.079656E-02 -1.987081E-04 -3.610266E-02 -1.649391E-04 -4.381846E-02 -2.263935E-04 -4.980200E-02 -2.864882E-04 -2.860174E-02 -1.712915E-04 -2.445643E-02 -1.020759E-04 -3.878477E-02 -2.026049E-04 -2.480236E-02 -6.838491E-05 -2.734325E-02 -9.461308E-05 -3.693833E-02 -1.822458E-04 -2.490103E-02 -7.329360E-05 -2.677818E-02 -8.305017E-05 -3.264724E-02 -1.437491E-04 -3.715999E-02 -2.239488E-04 -2.373224E-02 -6.329401E-05 -3.900048E-02 -1.863015E-04 -1.125664E-02 -2.181811E-05 -2.161924E-02 -7.195899E-05 -1.744174E-02 -4.273755E-05 -1.238666E-02 -2.145334E-05 -2.141496E-02 -5.796334E-05 -3.027096E-02 -9.721558E-05 -2.034339E-02 -5.581306E-05 -1.730093E-02 -4.542569E-05 -2.661993E-02 -8.452374E-05 -2.161864E-02 -5.465888E-05 -1.450249E-02 -2.452960E-05 -2.302180E-02 -6.121219E-05 -6.340596E-03 -5.499932E-06 -9.140384E-03 -1.585008E-05 -1.397492E-02 -2.598945E-05 -1.189682E-02 -2.167082E-05 -1.311861E-02 -2.016097E-05 -1.750898E-02 -4.671329E-05 -9.795781E-03 -1.975542E-05 -1.094278E-02 -1.976709E-05 -1.639501E-02 -3.446322E-05 -7.320291E-03 -7.206036E-06 -1.849111E-02 -4.335473E-05 -1.434342E-02 -2.991316E-05 -1.167361E-02 -1.759595E-05 -9.859610E-03 -1.289330E-05 -1.133762E-02 -1.561793E-05 -1.865540E-02 -4.343736E-05 -1.350518E-02 -2.129333E-05 -1.358916E-02 -2.271382E-05 -9.345990E-03 -1.288554E-05 -1.065558E-02 -1.661140E-05 -8.770677E-03 -1.373474E-05 -1.321675E-02 -2.139500E-05 -1.306520E-02 -2.539346E-05 -1.129556E-02 -2.247168E-05 -2.256971E-02 -6.489740E-05 -2.030940E-02 -5.625582E-05 -2.024779E-02 -5.494975E-05 -1.906346E-02 -4.047418E-05 -2.207434E-02 -6.757473E-05 -1.730595E-02 -3.788068E-05 -2.519625E-02 -9.116269E-05 -2.094102E-02 -5.386236E-05 -2.252706E-02 -7.123740E-05 -2.249589E-02 -6.348244E-05 -1.677894E-02 -4.502916E-05 -1.191569E-02 -2.092636E-05 -3.193092E-02 -1.066907E-04 -3.474315E-02 -1.354003E-04 -3.428457E-02 -1.357392E-04 -5.095478E-02 -3.135854E-04 -2.785938E-02 -1.094102E-04 -2.524070E-02 -7.421058E-05 -3.410453E-02 -1.325498E-04 -4.419349E-02 -2.287531E-04 -3.121966E-02 -1.145504E-04 -3.172565E-02 -1.576778E-04 -3.732684E-02 -1.794004E-04 -2.798822E-02 -9.904213E-05 -3.829890E-02 -1.745254E-04 -3.669187E-02 -1.481631E-04 -3.831832E-02 -1.640348E-04 -4.717292E-02 -2.431524E-04 -3.246900E-02 -1.090875E-04 -3.181397E-02 -1.110646E-04 -3.422430E-02 -1.455143E-04 -4.595899E-02 -2.593546E-04 -2.943781E-02 -1.144304E-04 -4.083225E-02 -2.153138E-04 -4.861114E-02 -2.668189E-04 -4.566953E-02 -2.275971E-04 -4.762605E-02 -2.702276E-04 -3.885235E-02 -1.678236E-04 -4.746492E-02 -2.732016E-04 -6.187919E-02 -3.977228E-04 -3.385168E-02 -1.655806E-04 -3.779606E-02 -1.742919E-04 -4.344441E-02 -2.144777E-04 -4.983722E-02 -2.780628E-04 -3.805659E-02 -1.869986E-04 -3.881150E-02 -1.693755E-04 -5.243613E-02 -3.131126E-04 -4.108551E-02 -1.935253E-04 -3.562260E-02 -1.423362E-04 -3.787549E-02 -1.654425E-04 -4.885818E-02 -2.578691E-04 -5.332653E-02 -3.213342E-04 -4.348495E-02 -2.331286E-04 -4.663540E-02 -2.474672E-04 -3.285731E-02 -1.375774E-04 -4.576846E-02 -2.311007E-04 -3.184404E-02 -1.192332E-04 -3.998156E-02 -1.844262E-04 -5.607513E-02 -3.422109E-04 -4.953587E-02 -2.676057E-04 -3.693477E-02 -1.700381E-04 -2.948894E-02 -1.003101E-04 -5.540578E-02 -3.851845E-04 -5.314370E-02 -3.109412E-04 -4.109329E-02 -1.998923E-04 -5.093669E-02 -3.059425E-04 -4.209028E-02 -2.361378E-04 -4.465662E-02 -2.120794E-04 -2.708725E-02 -9.631361E-05 -3.635562E-02 -1.595262E-04 -4.238804E-02 -1.947726E-04 -3.974596E-02 -1.806688E-04 -2.982744E-02 -1.207685E-04 -3.283297E-02 -1.354648E-04 -3.271957E-02 -1.397951E-04 -2.724542E-02 -1.015777E-04 -3.609538E-02 -1.698517E-04 -3.335710E-02 -1.624664E-04 -2.079895E-02 -5.610101E-05 -2.603309E-02 -9.493586E-05 -2.597898E-02 -9.783976E-05 -3.135251E-02 -1.402609E-04 -2.775791E-02 -9.666104E-05 -3.244893E-02 -1.414683E-04 -1.736161E-02 -4.120267E-05 -2.103660E-02 -6.662057E-05 -2.254942E-02 -6.127994E-05 -2.617237E-02 -9.655322E-05 -1.879302E-02 -4.046759E-05 -2.239207E-02 -7.270900E-05 -1.582884E-02 -3.421542E-05 -1.701627E-02 -3.287993E-05 -1.586730E-02 -3.071759E-05 -1.637662E-02 -4.285548E-05 -1.575516E-02 -2.967636E-05 -1.749637E-02 -4.429182E-05 -1.377991E-02 -2.869990E-05 -1.666042E-02 -3.900259E-05 -1.590173E-02 -4.041443E-05 -1.533466E-02 -3.740187E-05 -1.242820E-02 -2.230617E-05 -2.005763E-02 -5.559139E-05 -1.888435E-02 -5.293569E-05 -1.437606E-02 -2.992754E-05 -1.160735E-02 -2.488650E-05 -1.903862E-02 -4.929965E-05 -1.792944E-02 -4.623131E-05 -1.925927E-02 -4.967790E-05 -1.197483E-02 -1.865556E-05 -7.572584E-03 -1.282465E-05 -1.344056E-02 -2.673348E-05 -1.049282E-02 -1.487580E-05 -1.018581E-02 -1.491092E-05 -9.650534E-03 -1.458568E-05 -7.696745E-03 -8.956471E-06 -6.117465E-03 -6.145859E-06 -7.711888E-03 -1.379326E-05 -7.178538E-03 -8.529096E-06 -7.013352E-03 -9.358596E-06 -5.223833E-03 -4.743484E-06 -1.958755E-02 -5.840140E-05 -1.514889E-02 -3.048083E-05 -1.420009E-02 -3.392782E-05 -1.779423E-02 -4.000672E-05 -9.916829E-03 -1.600897E-05 -1.084516E-02 -1.883449E-05 -1.721403E-02 -3.892250E-05 -1.697631E-02 -5.336366E-05 -1.126561E-02 -1.779695E-05 -1.183784E-02 -2.042908E-05 -1.279900E-02 -2.278884E-05 -1.221352E-02 -2.185990E-05 -2.126137E-02 -5.259427E-05 -1.948422E-02 -7.413728E-05 -2.691940E-02 -7.987754E-05 -2.366460E-02 -7.849119E-05 -1.493129E-02 -3.458121E-05 -2.528845E-02 -7.805956E-05 -1.941301E-02 -4.532019E-05 -3.315469E-02 -1.407045E-04 -1.764622E-02 -4.338977E-05 -1.952377E-02 -5.147550E-05 -2.600704E-02 -9.058738E-05 -2.442799E-02 -7.377464E-05 -2.298511E-02 -6.212241E-05 -2.519641E-02 -9.638931E-05 -3.975880E-02 -1.694798E-04 -3.835063E-02 -1.723954E-04 -2.433477E-02 -7.177972E-05 -2.711003E-02 -1.279711E-04 -3.083661E-02 -1.018837E-04 -4.207502E-02 -2.089394E-04 -2.844391E-02 -9.560578E-05 -2.835547E-02 -8.648090E-05 -5.190679E-02 -2.829647E-04 -3.607591E-02 -1.406622E-04 -2.726024E-02 -9.295552E-05 -2.334992E-02 -7.837059E-05 -2.556006E-02 -8.066549E-05 -3.157571E-02 -1.018377E-04 -2.717890E-02 -9.754656E-05 -3.812328E-02 -1.529731E-04 -3.196833E-02 -1.246738E-04 -3.749985E-02 -1.546562E-04 -1.861417E-02 -4.193655E-05 -2.827800E-02 -8.681001E-05 -3.521111E-02 -1.537273E-04 -3.631214E-02 -1.510528E-04 -3.010902E-02 -1.101278E-04 -2.898513E-02 -1.002289E-04 -3.759216E-02 -1.686797E-04 -3.924809E-02 -1.926092E-04 -3.000742E-02 -1.032469E-04 -3.063104E-02 -1.058005E-04 -3.016836E-02 -1.406736E-04 -3.811226E-02 -2.142070E-04 -3.067660E-02 -1.137129E-04 -2.919174E-02 -9.744001E-05 -4.351818E-02 -2.481411E-04 -3.459089E-02 -1.418237E-04 -2.354519E-02 -7.125933E-05 -2.341512E-02 -7.530145E-05 -3.423411E-02 -1.362388E-04 -3.807351E-02 -1.835906E-04 -3.060066E-02 -1.306426E-04 -3.887634E-02 -1.767107E-04 -2.972630E-02 -1.452173E-04 -2.761804E-02 -8.313790E-05 -2.564981E-02 -1.041595E-04 -2.302814E-02 -5.748532E-05 -3.430159E-02 -1.266003E-04 -3.080546E-02 -1.097842E-04 -1.862840E-02 -4.692046E-05 -2.212362E-02 -5.769304E-05 -3.055531E-02 -1.529521E-04 -2.289574E-02 -8.233761E-05 -2.656172E-02 -8.446802E-05 -3.583300E-02 -1.541747E-04 -2.557682E-02 -7.916517E-05 -2.097606E-02 -5.055022E-05 -2.228757E-02 -5.988269E-05 -1.816051E-02 -3.901578E-05 -2.325555E-02 -7.127170E-05 -2.918248E-02 -1.039399E-04 -1.305527E-02 -2.604090E-05 -1.318002E-02 -2.893713E-05 -1.574393E-02 -3.521171E-05 -1.414192E-02 -3.552473E-05 -1.633140E-02 -3.849962E-05 -1.643542E-02 -4.093687E-05 -1.215108E-02 -2.596067E-05 -1.663208E-02 -4.623828E-05 -1.519499E-02 -2.784484E-05 -1.392851E-02 -2.190759E-05 -2.267580E-02 -6.466320E-05 -2.215409E-02 -7.872980E-05 -1.106097E-02 -1.935578E-05 -1.318957E-02 -2.458468E-05 -1.432387E-02 -2.771689E-05 -1.302310E-02 -2.533330E-05 -1.818189E-02 -4.776340E-05 -1.401528E-02 -2.698770E-05 -3.589051E-03 -3.157955E-06 -9.717553E-03 -1.921247E-05 -8.432737E-03 -1.168760E-05 -8.867899E-03 -2.125223E-05 -1.176987E-02 -2.796774E-05 -1.387858E-02 -2.900888E-05 -7.333775E-03 -9.493537E-06 -5.494780E-03 -7.270347E-06 -8.505259E-03 -1.106187E-05 -5.349113E-03 -6.272249E-06 -7.278213E-03 -7.362414E-06 -8.521400E-03 -1.020574E-05 -8.308309E-03 -1.075116E-05 -8.167064E-03 -1.109423E-05 -5.533013E-03 -6.466675E-06 -5.112442E-03 -8.851249E-06 -5.870076E-03 -6.648936E-06 -3.929558E-03 -2.494118E-06 -1.248728E-02 -2.662149E-05 -7.689572E-03 -1.632791E-05 -1.064286E-02 -1.731638E-05 -8.865827E-03 -2.182318E-05 -1.060594E-02 -1.974250E-05 -1.107000E-02 -1.741690E-05 -1.046576E-02 -1.304525E-05 -8.923758E-03 -1.382295E-05 -6.048588E-03 -6.515013E-06 -1.140457E-02 -1.772344E-05 -1.071605E-02 -2.320839E-05 -1.108521E-02 -2.146136E-05 -1.372658E-02 -3.150815E-05 -1.185879E-02 -2.592177E-05 -1.328057E-02 -2.007755E-05 -2.366818E-02 -6.240710E-05 -1.310524E-02 -2.483124E-05 -1.756288E-02 -3.846799E-05 -1.953925E-02 -4.224682E-05 -2.714173E-02 -9.200317E-05 -2.089836E-02 -5.417932E-05 -1.880252E-02 -4.633361E-05 -1.825440E-02 -4.676871E-05 -1.703893E-02 -3.290578E-05 -1.536560E-02 -2.501324E-05 -1.723409E-02 -4.375407E-05 -2.378506E-02 -6.856927E-05 -2.116439E-02 -5.565273E-05 -1.694042E-02 -5.241605E-05 -1.860566E-02 -4.783232E-05 -1.867229E-02 -4.443429E-05 -2.347238E-02 -6.225289E-05 -1.240017E-02 -2.472321E-05 -1.834566E-02 -5.076889E-05 -2.345212E-02 -6.899204E-05 -1.744726E-02 -4.012671E-05 -2.139472E-02 -5.719986E-05 -2.881782E-02 -1.041089E-04 -2.249258E-02 -6.622191E-05 -3.099210E-02 -1.124327E-04 -2.723683E-02 -1.077003E-04 -2.961326E-02 -1.107622E-04 -2.886855E-02 -1.209198E-04 -3.359957E-02 -1.450335E-04 -1.842677E-02 -4.144114E-05 -2.067987E-02 -5.241403E-05 -2.384292E-02 -8.392423E-05 -2.523377E-02 -7.399318E-05 -1.482060E-02 -2.934033E-05 -1.685267E-02 -4.268337E-05 -2.474266E-02 -6.858025E-05 -2.464842E-02 -7.502593E-05 -1.931712E-02 -6.623063E-05 -2.571146E-02 -8.499419E-05 -1.919509E-02 -5.019677E-05 -2.194688E-02 -6.974387E-05 -2.021151E-02 -5.705824E-05 -1.939673E-02 -5.393718E-05 -2.366200E-02 -7.358565E-05 -3.181441E-02 -1.136270E-04 -1.839678E-02 -3.699144E-05 -1.988625E-02 -6.005553E-05 -2.730155E-02 -9.038604E-05 -1.977072E-02 -5.242521E-05 -1.499223E-02 -2.966075E-05 -2.040274E-02 -6.508672E-05 -1.411627E-02 -2.586129E-05 -1.706927E-02 -3.713346E-05 -1.171754E-02 -1.971987E-05 -2.013780E-02 -5.939024E-05 -2.029685E-02 -6.146855E-05 -2.908889E-02 -1.037204E-04 -1.740582E-02 -3.597993E-05 -1.564902E-02 -6.335090E-05 -1.991302E-02 -4.746765E-05 -1.756837E-02 -4.867597E-05 -2.061727E-02 -6.000022E-05 -2.574876E-02 -8.243095E-05 -1.191200E-02 -1.934272E-05 -2.009666E-02 -4.813195E-05 -1.746764E-02 -5.388627E-05 -1.239022E-02 -2.424386E-05 -2.173442E-02 -4.983400E-05 -1.517203E-02 -3.068246E-05 -1.329712E-02 -2.150332E-05 -2.354363E-02 -8.627378E-05 -1.532883E-02 -3.270327E-05 -1.472157E-02 -3.319558E-05 -1.938773E-02 -4.827508E-05 -2.165397E-02 -6.469989E-05 -1.271540E-02 -1.967861E-05 -1.665138E-02 -4.718665E-05 -9.283413E-03 -1.143878E-05 -1.046201E-02 -2.072362E-05 -1.673621E-02 -3.707353E-05 -1.445073E-02 -2.924329E-05 -7.634313E-03 -1.179099E-05 -7.070615E-03 -8.043539E-06 -1.155338E-02 -1.871310E-05 -8.618350E-03 -1.431974E-05 -9.424572E-03 -1.207411E-05 -8.545662E-03 -1.247473E-05 -3.838707E-03 -4.805334E-06 -5.882837E-03 -4.922359E-06 -8.145896E-03 -1.250575E-05 -5.962503E-03 -5.532809E-06 -1.116529E-02 -3.223331E-05 -1.080742E-02 -1.791118E-05 -4.327838E-03 -3.722361E-06 -3.132066E-03 -2.831681E-06 -5.985652E-03 -5.243244E-06 -6.402910E-03 -9.755445E-06 -5.996163E-03 -1.017758E-05 -7.516797E-03 -1.133864E-05 -1.109701E-03 -5.874266E-07 -3.145346E-03 -2.131176E-06 -3.071793E-03 -3.203751E-06 -5.112008E-03 -6.623440E-06 -1.057799E-02 -2.219886E-05 -4.499437E-03 -4.252659E-06 -8.765798E-03 -1.784490E-05 -8.921959E-03 -1.351279E-05 -7.502480E-03 -1.202219E-05 -7.196379E-03 -9.204669E-06 -5.832796E-03 -1.016451E-05 -7.038191E-03 -6.254164E-06 -9.382421E-03 -1.566041E-05 -1.345656E-02 -3.028211E-05 -6.337258E-03 -7.407982E-06 -8.543843E-03 -1.265584E-05 -1.381261E-02 -2.802183E-05 -1.190749E-02 -1.793613E-05 -9.437321E-03 -1.194730E-05 -9.732419E-03 -1.651545E-05 -1.500610E-02 -3.340884E-05 -1.678411E-02 -3.491286E-05 -1.028094E-02 -1.374135E-05 -1.485088E-02 -3.057123E-05 -8.964661E-03 -1.485585E-05 -1.226822E-02 -2.015578E-05 -1.042577E-02 -1.589161E-05 -6.708855E-03 -9.646613E-06 -1.277453E-02 -2.203458E-05 -7.224932E-03 -8.275023E-06 -1.255069E-02 -2.759249E-05 -1.234545E-02 -2.557302E-05 -1.676381E-02 -3.443801E-05 -2.225843E-02 -7.382383E-05 -9.664194E-03 -1.388455E-05 -1.384208E-02 -2.485536E-05 -1.170741E-02 -2.722875E-05 -1.298519E-02 -2.278333E-05 -1.219523E-02 -2.170852E-05 -1.455145E-02 -2.652917E-05 -1.803860E-02 -4.551654E-05 -1.716760E-02 -3.418763E-05 -1.512094E-02 -3.308210E-05 -1.040105E-02 -1.595604E-05 -1.796769E-02 -3.949154E-05 -1.872289E-02 -4.103439E-05 -9.077191E-03 -1.199908E-05 -1.631540E-02 -3.369350E-05 -1.526935E-02 -3.456559E-05 -2.236068E-02 -7.214380E-05 -8.845141E-03 -2.279004E-05 -1.352347E-02 -2.540469E-05 -1.484395E-02 -3.807417E-05 -1.804445E-02 -4.342710E-05 -1.007944E-02 -1.452963E-05 -1.467548E-02 -4.429846E-05 -2.042873E-02 -5.671423E-05 -1.758792E-02 -5.925658E-05 -1.761311E-02 -4.685220E-05 -2.004514E-02 -5.536859E-05 -1.238507E-02 -2.340619E-05 -1.046525E-02 -1.737035E-05 -1.444879E-02 -3.355825E-05 -8.277840E-03 -1.437311E-05 -1.079506E-02 -1.848135E-05 -1.561308E-02 -4.224535E-05 -1.137179E-02 -2.608300E-05 -1.280633E-02 -2.210100E-05 -1.162328E-02 -2.231053E-05 -1.296251E-02 -2.730055E-05 -1.389949E-02 -3.026765E-05 -1.411889E-02 -3.201101E-05 -8.232902E-03 -1.404323E-05 -1.242929E-02 -2.465073E-05 -9.545643E-03 -1.867285E-05 -9.740853E-03 -1.452865E-05 -1.306805E-02 -2.407394E-05 -1.010373E-02 -1.920540E-05 -8.546938E-03 -1.818086E-05 -9.873382E-03 -2.146517E-05 -1.643827E-02 -5.513889E-05 -1.117018E-02 -2.390203E-05 -9.216643E-03 -1.323340E-05 -1.434946E-02 -2.862359E-05 -1.245343E-02 -2.322243E-05 -1.212911E-02 -2.285075E-05 -9.836707E-03 -1.645734E-05 -1.201364E-02 -2.024192E-05 -1.596859E-02 -3.442108E-05 -1.368837E-02 -2.688655E-05 -1.015380E-02 -1.592459E-05 -9.892082E-03 -1.321377E-05 -1.360812E-02 -3.262388E-05 -1.003913E-02 -1.400775E-05 -1.478387E-02 -3.871602E-05 -9.205053E-03 -1.179337E-05 -9.383339E-03 -1.300416E-05 -7.080640E-03 -8.203597E-06 -6.507205E-03 -7.055020E-06 -8.843528E-03 -1.233759E-05 -1.087757E-02 -1.436248E-05 -9.075363E-03 -1.538346E-05 -4.079253E-03 -4.032406E-06 -6.146524E-03 -1.072823E-05 -7.605892E-03 -2.021674E-05 -6.737771E-03 -8.340942E-06 -7.791360E-03 -1.322504E-05 -4.367729E-03 -5.871757E-06 -5.112041E-03 -7.704614E-06 -6.685377E-03 -8.598228E-06 -5.332365E-03 -6.964174E-06 -2.025949E-03 -1.106713E-06 -7.308916E-03 -1.083527E-05 -2.657078E-03 -2.018754E-06 -3.845964E-03 -3.282949E-06 -7.906876E-03 -1.309640E-05 -3.020084E-03 -2.116323E-06 -4.987032E-03 -5.707520E-06 -1.202747E-02 -3.060476E-05 -7.093728E-03 -7.508046E-06 -7.422432E-03 -8.656078E-06 -9.077236E-03 -2.478476E-05 -6.891522E-03 -1.220166E-05 -5.076941E-03 -4.237107E-06 -8.523515E-03 -1.390735E-05 -6.414767E-03 -9.365735E-06 -9.380022E-03 -1.462751E-05 -8.456230E-03 -1.199551E-05 -9.158278E-03 -1.192449E-05 -2.298967E-03 -1.013954E-06 -7.058890E-03 -6.383597E-06 -4.876567E-03 -3.760010E-06 -1.316587E-02 -2.644816E-05 -8.359774E-03 -1.081163E-05 -1.469243E-02 -3.486053E-05 -7.460324E-03 -7.746075E-06 -7.025833E-03 -7.150545E-06 -4.599519E-03 -5.621223E-06 -1.754686E-02 -5.599449E-05 -8.496819E-03 -1.519010E-05 -1.334303E-02 -2.243087E-05 -1.273838E-02 -2.372539E-05 -1.041534E-02 -2.066977E-05 -9.140508E-03 -1.075841E-05 -1.657971E-02 -4.469598E-05 -1.247039E-02 -2.906265E-05 -1.297140E-02 -2.473045E-05 -1.664008E-02 -4.158991E-05 -1.836946E-02 -4.883353E-05 -1.411162E-02 -4.313628E-05 -1.406170E-02 -2.454496E-05 -2.270767E-02 -6.143414E-05 -1.567617E-02 -3.204306E-05 -1.611804E-02 -3.752055E-05 -1.312188E-02 -2.232058E-05 -1.726062E-02 -4.888466E-05 -2.260453E-02 -5.912727E-05 -2.295104E-02 -7.305721E-05 -2.082979E-02 -5.212405E-05 -3.139636E-02 -1.124507E-04 -1.701985E-02 -5.917730E-05 -1.573079E-02 -3.833147E-05 -1.648501E-02 -4.521319E-05 -1.295769E-02 -2.000518E-05 -1.538561E-02 -3.581006E-05 -2.113104E-02 -5.954145E-05 -1.269260E-02 -1.914463E-05 -1.597644E-02 -2.898818E-05 -1.749472E-02 -4.995488E-05 -1.170597E-02 -2.494586E-05 -1.972148E-02 -5.486069E-05 -2.930071E-02 -1.089599E-04 -1.284182E-02 -2.296682E-05 -1.568134E-02 -3.876494E-05 -1.557912E-02 -3.819947E-05 -1.760851E-02 -3.904704E-05 -1.450774E-02 -4.086604E-05 -1.375807E-02 -3.319496E-05 -1.290194E-02 -2.142172E-05 -1.402767E-02 -2.932888E-05 -1.769773E-02 -4.995015E-05 -1.419402E-02 -3.040909E-05 -1.675459E-02 -3.235864E-05 -1.976178E-02 -5.009760E-05 -1.675838E-02 -3.910658E-05 -1.689170E-02 -3.464763E-05 -1.284022E-02 -2.649261E-05 -1.316325E-02 -2.377493E-05 -1.455084E-02 -2.510139E-05 -1.102459E-02 -1.885880E-05 -8.350866E-03 -8.396386E-06 -8.651131E-03 -1.124192E-05 -1.376705E-02 -2.764081E-05 -1.428569E-02 -3.790437E-05 -1.724679E-02 -3.366818E-05 -1.584053E-02 -3.651487E-05 -1.193033E-02 -2.181873E-05 -1.984626E-02 -5.592598E-05 -1.214395E-02 -1.945894E-05 -1.365596E-02 -2.557166E-05 -1.898643E-02 -5.157604E-05 -1.455388E-02 -2.799320E-05 -1.182403E-02 -2.115918E-05 -8.626630E-03 -1.007433E-05 -1.197781E-02 -1.983881E-05 -1.005772E-02 -1.640145E-05 -1.873799E-02 -4.930639E-05 -1.693176E-02 -3.650659E-05 -8.818286E-03 -1.286259E-05 -1.139988E-02 -1.621095E-05 -1.028933E-02 -1.453198E-05 -8.404568E-03 -9.460915E-06 -1.275744E-02 -2.774096E-05 -1.168183E-02 -1.973529E-05 -8.454758E-03 -1.146522E-05 -8.323601E-03 -8.829709E-06 -7.495546E-03 -8.715799E-06 -5.296323E-03 -6.046794E-06 -9.891852E-03 -1.398584E-05 -9.955102E-03 -1.943758E-05 -8.059482E-03 -1.695389E-05 -9.676780E-03 -1.658395E-05 -4.834433E-03 -5.897640E-06 -6.636064E-03 -7.609925E-06 -7.619866E-03 -1.212597E-05 -2.894660E-03 -1.856127E-06 -7.553124E-03 -1.223718E-05 -2.300404E-03 -1.121136E-06 -7.327033E-03 -9.105655E-06 -4.846398E-03 -4.166167E-06 -8.315901E-03 -1.319751E-05 -7.221182E-03 -7.485967E-06 -5.462020E-03 -3.502442E-06 -9.453474E-03 -1.071037E-05 -1.293719E-02 -2.483879E-05 -1.321412E-02 -2.574150E-05 -1.359066E-02 -2.348428E-05 -9.882529E-03 -1.691834E-05 -1.409150E-02 -3.523994E-05 -1.070054E-02 -1.906767E-05 -1.266239E-02 -1.972906E-05 -1.432889E-02 -3.545618E-05 -1.011895E-02 -1.360275E-05 -1.025183E-02 -1.608180E-05 -5.529921E-03 -7.911985E-06 -1.629012E-02 -3.223742E-05 -1.114479E-02 -2.101499E-05 -1.215717E-02 -1.846892E-05 -1.689915E-02 -4.620696E-05 -1.139613E-02 -1.742241E-05 -1.213431E-02 -2.199183E-05 -1.846118E-02 -5.474736E-05 -1.709853E-02 -3.678232E-05 -1.735796E-02 -4.553680E-05 -1.853277E-02 -4.646147E-05 -1.763467E-02 -4.466597E-05 -1.818218E-02 -4.824198E-05 -1.872596E-02 -6.942835E-05 -2.022757E-02 -5.512053E-05 -1.699277E-02 -3.870609E-05 -1.055491E-02 -1.687463E-05 -1.377011E-02 -2.394912E-05 -1.684636E-02 -3.614976E-05 -2.147831E-02 -6.616404E-05 -1.730285E-02 -3.913079E-05 -1.957720E-02 -5.565960E-05 -1.855637E-02 -4.612437E-05 -2.805186E-02 -1.029670E-04 -2.418902E-02 -6.781295E-05 -2.188652E-02 -6.579480E-05 -1.771569E-02 -4.195257E-05 -2.256760E-02 -6.456468E-05 -1.918774E-02 -5.286254E-05 -2.960608E-02 -1.004602E-04 -2.712839E-02 -8.980797E-05 -2.794452E-02 -1.254679E-04 -3.008968E-02 -1.089661E-04 -3.649934E-02 -1.734688E-04 -2.937679E-02 -1.082854E-04 -3.282797E-02 -1.345859E-04 -4.521759E-02 -2.543431E-04 -2.398232E-02 -7.384139E-05 -3.254161E-02 -1.265125E-04 -3.001705E-02 -1.111357E-04 -2.399317E-02 -6.646668E-05 -3.503715E-02 -1.480964E-04 -3.148980E-02 -1.398976E-04 -2.604556E-02 -9.628490E-05 -3.036652E-02 -1.264006E-04 -2.939357E-02 -1.170192E-04 -3.743087E-02 -1.775840E-04 -3.085132E-02 -1.134780E-04 -4.147944E-02 -1.996575E-04 -3.527838E-02 -1.521337E-04 -2.366172E-02 -6.804925E-05 -2.713514E-02 -1.027237E-04 -2.174215E-02 -5.749073E-05 -2.675659E-02 -8.382558E-05 -2.359986E-02 -7.430600E-05 -2.367000E-02 -7.298151E-05 -3.227569E-02 -1.232973E-04 -2.733957E-02 -1.003086E-04 -3.002721E-02 -9.578465E-05 -3.707352E-02 -1.507472E-04 -2.382487E-02 -6.891582E-05 -2.959048E-02 -1.054578E-04 -1.869568E-02 -4.658988E-05 -2.597326E-02 -8.064723E-05 -2.153451E-02 -5.840127E-05 -1.628961E-02 -4.271967E-05 -2.741092E-02 -8.522384E-05 -2.733756E-02 -9.324995E-05 -2.864715E-02 -1.013597E-04 -3.455306E-02 -1.448078E-04 -3.347393E-02 -1.327937E-04 -3.527874E-02 -1.637966E-04 -2.441550E-02 -8.480735E-05 -2.623780E-02 -8.256558E-05 -1.716091E-02 -5.253723E-05 -1.324941E-02 -2.243910E-05 -2.246659E-02 -6.057114E-05 -2.192475E-02 -5.668645E-05 -2.272490E-02 -7.122633E-05 -3.254641E-02 -1.485757E-04 -1.504227E-02 -2.731302E-05 -1.654008E-02 -4.044070E-05 -2.442456E-02 -8.014611E-05 -2.260914E-02 -6.419431E-05 -1.988931E-02 -6.266967E-05 -3.422754E-02 -1.464931E-04 -1.176286E-02 -1.819119E-05 -1.090258E-02 -1.835148E-05 -1.428818E-02 -2.432816E-05 -9.647717E-03 -2.418655E-05 -1.343547E-02 -2.294350E-05 -1.672666E-02 -4.724036E-05 -1.498173E-02 -2.999368E-05 -1.209667E-02 -2.648058E-05 -1.777083E-02 -3.928551E-05 -1.906246E-02 -4.800003E-05 -1.227253E-02 -2.454598E-05 -2.054852E-02 -5.627860E-05 -1.401620E-02 -3.395841E-05 -1.618774E-02 -3.315176E-05 -9.366645E-03 -1.322093E-05 -1.271711E-02 -2.946682E-05 -1.514436E-02 -3.698271E-05 -1.357568E-02 -2.661503E-05 -6.059837E-03 -6.072503E-06 -7.510121E-03 -8.006288E-06 -1.105528E-02 -2.101618E-05 -4.887318E-03 -5.427586E-06 -8.183502E-03 -1.217955E-05 -9.960866E-03 -1.427453E-05 -1.302537E-02 -2.752410E-05 -1.432159E-02 -3.046582E-05 -1.362132E-02 -3.362721E-05 -1.728813E-02 -4.356686E-05 -1.882553E-02 -4.115052E-05 -2.022059E-02 -5.094537E-05 -9.935622E-03 -1.476612E-05 -1.423961E-02 -2.791015E-05 -1.078457E-02 -3.254092E-05 -1.010483E-02 -1.743918E-05 -1.145080E-02 -2.471476E-05 -1.537588E-02 -3.948184E-05 -3.025085E-02 -1.211946E-04 -2.522059E-02 -8.250671E-05 -2.231553E-02 -6.323615E-05 -2.348918E-02 -6.900725E-05 -2.273346E-02 -5.949276E-05 -1.817883E-02 -4.693722E-05 -2.354895E-02 -7.506897E-05 -2.667415E-02 -1.051466E-04 -1.923174E-02 -4.215181E-05 -2.251124E-02 -6.197340E-05 -2.212823E-02 -7.382044E-05 -2.627751E-02 -1.262016E-04 -2.639401E-02 -8.435288E-05 -2.355251E-02 -6.467494E-05 -1.824258E-02 -4.508497E-05 -2.658510E-02 -7.928794E-05 -2.675987E-02 -1.019694E-04 -2.294475E-02 -7.019770E-05 -2.982020E-02 -1.172018E-04 -2.650631E-02 -7.994237E-05 -3.317163E-02 -1.365190E-04 -4.086398E-02 -2.004161E-04 -2.796562E-02 -1.066212E-04 -3.652322E-02 -1.878727E-04 -3.754838E-02 -1.647330E-04 -3.743316E-02 -1.789631E-04 -2.670365E-02 -8.773372E-05 -2.985106E-02 -9.743471E-05 -3.608668E-02 -1.610685E-04 -4.205670E-02 -1.842040E-04 -3.922858E-02 -1.953706E-04 -4.448502E-02 -2.469956E-04 -4.693316E-02 -2.454100E-04 -4.848290E-02 -2.671676E-04 -4.023569E-02 -1.713754E-04 -4.294287E-02 -2.063518E-04 -4.004042E-02 -1.923766E-04 -4.357533E-02 -2.186888E-04 -3.728630E-02 -1.990696E-04 -4.083902E-02 -1.919817E-04 -3.857997E-02 -1.821259E-04 -4.901557E-02 -2.767777E-04 -5.790464E-02 -3.872461E-04 -3.900935E-02 -1.730109E-04 -4.875435E-02 -2.872844E-04 -5.468952E-02 -3.456684E-04 -4.179342E-02 -2.001437E-04 -5.381510E-02 -3.724283E-04 -4.237622E-02 -1.941664E-04 -5.150719E-02 -2.908123E-04 -2.903885E-02 -1.031896E-04 -3.589197E-02 -1.392764E-04 -6.487280E-02 -5.024965E-04 -3.912537E-02 -1.856374E-04 -3.458921E-02 -1.576917E-04 -4.382484E-02 -2.169611E-04 -5.176404E-02 -2.803853E-04 -5.379322E-02 -3.067204E-04 -4.070213E-02 -1.816834E-04 -4.088864E-02 -1.878390E-04 -3.237349E-02 -1.191717E-04 -3.712382E-02 -1.504938E-04 -3.997504E-02 -1.782786E-04 -3.267526E-02 -1.297525E-04 -4.125020E-02 -1.924418E-04 -3.958215E-02 -1.901035E-04 -4.006168E-02 -1.832588E-04 -3.769986E-02 -1.717343E-04 -5.100625E-02 -2.898618E-04 -3.840461E-02 -1.682447E-04 -3.871359E-02 -1.824587E-04 -4.283505E-02 -2.070659E-04 -2.126415E-02 -4.973731E-05 -2.889038E-02 -1.088896E-04 -2.104568E-02 -6.548850E-05 -2.848041E-02 -1.298630E-04 -3.029276E-02 -1.138285E-04 -2.862761E-02 -9.675198E-05 -2.647642E-02 -8.418245E-05 -2.861468E-02 -1.081191E-04 -3.468627E-02 -1.277418E-04 -3.349950E-02 -1.317290E-04 -3.982514E-02 -1.794172E-04 -3.268932E-02 -1.255468E-04 -1.912998E-02 -4.577703E-05 -2.085203E-02 -6.226159E-05 -1.828176E-02 -4.944577E-05 -2.381226E-02 -8.891365E-05 -2.311077E-02 -6.656845E-05 -2.473067E-02 -7.334387E-05 -1.375348E-02 -2.283618E-05 -1.804582E-02 -4.143497E-05 -2.006609E-02 -4.873691E-05 -1.884382E-02 -4.819154E-05 -1.080497E-02 -1.376297E-05 -1.726756E-02 -3.375398E-05 -1.609526E-02 -3.821013E-05 -1.411969E-02 -2.227160E-05 -9.192959E-03 -1.631434E-05 -9.217380E-03 -1.968772E-05 -1.468647E-02 -2.623946E-05 -1.488244E-02 -3.525990E-05 -1.269069E-02 -2.294212E-05 -7.765318E-03 -1.103799E-05 -1.558612E-02 -3.323429E-05 -1.740029E-02 -5.933208E-05 -8.717198E-03 -1.192243E-05 -9.978251E-03 -1.485392E-05 -8.720289E-03 -1.149015E-05 -1.020781E-02 -2.305230E-05 -1.149654E-02 -1.940965E-05 -1.788016E-02 -4.220362E-05 -1.110418E-02 -1.718658E-05 -2.482931E-02 -1.001964E-04 -1.645044E-02 -4.054796E-05 -1.894652E-02 -4.678890E-05 -1.434380E-02 -3.165754E-05 -1.258510E-02 -2.725122E-05 -2.869257E-02 -1.023938E-04 -1.622348E-02 -4.537915E-05 -2.185647E-02 -5.507321E-05 -1.954237E-02 -4.309665E-05 -2.035261E-02 -6.714277E-05 -2.087253E-02 -4.818549E-05 -1.582401E-02 -3.291377E-05 -2.671073E-02 -9.777211E-05 -2.512135E-02 -7.547644E-05 -2.506727E-02 -7.485132E-05 -1.404823E-02 -2.446571E-05 -2.280451E-02 -6.346040E-05 -2.677285E-02 -8.686426E-05 -2.736182E-02 -1.019696E-04 -4.245358E-02 -2.031516E-04 -3.781676E-02 -1.657018E-04 -3.988823E-02 -1.948658E-04 -4.639548E-02 -2.606408E-04 -2.998045E-02 -1.078111E-04 -3.116186E-02 -1.123729E-04 -5.002484E-02 -3.007452E-04 -4.018989E-02 -2.134973E-04 -3.706873E-02 -1.705493E-04 -4.841352E-02 -3.006314E-04 -4.754905E-02 -2.640563E-04 -4.364220E-02 -2.190548E-04 -5.500865E-02 -3.565984E-04 -5.532256E-02 -3.576995E-04 -5.047039E-02 -2.937072E-04 -5.060213E-02 -3.044944E-04 -6.416214E-02 -4.414515E-04 -4.420142E-02 -2.374155E-04 -7.189342E-02 -5.468649E-04 -6.014136E-02 -3.940429E-04 -6.349933E-02 -4.207906E-04 -8.074317E-02 -7.419627E-04 -5.500576E-02 -3.305937E-04 -6.217792E-02 -4.170384E-04 -5.168117E-02 -2.909656E-04 -6.458066E-02 -4.333028E-04 -5.398600E-02 -3.328720E-04 -6.745198E-02 -5.123388E-04 -7.585366E-02 -6.172453E-04 -7.667038E-02 -6.845297E-04 -8.031109E-02 -7.564824E-04 -7.073034E-02 -5.458581E-04 -7.573691E-02 -6.181860E-04 -7.610572E-02 -6.320225E-04 -9.472534E-02 -1.007312E-03 -8.942164E-02 -8.735772E-04 -6.678710E-02 -5.406900E-04 -6.813491E-02 -4.871261E-04 -6.435084E-02 -4.334073E-04 -6.618817E-02 -4.692824E-04 -8.000303E-02 -7.136374E-04 -7.211464E-02 -6.123883E-04 -9.166818E-02 -8.952483E-04 -5.925322E-02 -4.492782E-04 -9.608215E-02 -9.616517E-04 -9.591584E-02 -9.489183E-04 -6.551541E-02 -4.745820E-04 -9.550949E-02 -9.531681E-04 -5.425472E-02 -3.720953E-04 -6.247517E-02 -4.393993E-04 -5.896488E-02 -4.002445E-04 -5.123472E-02 -2.943668E-04 -7.803224E-02 -6.809156E-04 -6.717709E-02 -5.320659E-04 -4.752627E-02 -2.528912E-04 -4.731481E-02 -2.339422E-04 -6.377650E-02 -5.060539E-04 -6.343027E-02 -4.521666E-04 -5.104223E-02 -3.253849E-04 -6.842536E-02 -5.197571E-04 -3.944396E-02 -2.024706E-04 -3.774197E-02 -1.745573E-04 -3.016158E-02 -1.057402E-04 -2.940171E-02 -1.161392E-04 -5.428473E-02 -3.726778E-04 -3.466389E-02 -1.374879E-04 -2.493688E-02 -9.144503E-05 -4.409357E-02 -2.282136E-04 -3.898092E-02 -1.692947E-04 -4.161525E-02 -2.078651E-04 -4.453363E-02 -2.219554E-04 -4.844461E-02 -2.561895E-04 -1.992414E-02 -5.397706E-05 -1.350002E-02 -2.916535E-05 -2.067487E-02 -4.903837E-05 -2.325603E-02 -8.788747E-05 -2.013029E-02 -5.389647E-05 -3.203793E-02 -1.247710E-04 -1.965175E-02 -5.312061E-05 -2.463239E-02 -8.315266E-05 -2.236927E-02 -6.414213E-05 -2.615164E-02 -7.702130E-05 -3.011875E-02 -1.090074E-04 -3.242536E-02 -1.289377E-04 -1.086798E-02 -1.760814E-05 -1.502391E-02 -3.139067E-05 -2.028244E-02 -5.583147E-05 -1.735464E-02 -4.295725E-05 -1.595857E-02 -2.787063E-05 -2.051018E-02 -5.355572E-05 -1.177619E-02 -1.717906E-05 -1.084749E-02 -1.707026E-05 -1.825630E-02 -5.376844E-05 -1.670967E-02 -3.402950E-05 -1.517723E-02 -3.554202E-05 -2.351000E-02 -7.935893E-05 -1.408337E-02 -2.327322E-05 -1.414777E-02 -2.697883E-05 -1.345682E-02 -2.740309E-05 -1.807340E-02 -5.667578E-05 -1.943061E-02 -4.787161E-05 -1.781260E-02 -6.060590E-05 -1.822299E-02 -4.962172E-05 -2.071085E-02 -5.813369E-05 -1.228031E-02 -2.872901E-05 -1.195238E-02 -1.942759E-05 -2.092949E-02 -5.642842E-05 -1.529365E-02 -3.149749E-05 -2.339941E-02 -7.277783E-05 -2.913166E-02 -1.578357E-04 -1.733543E-02 -4.484055E-05 -2.332788E-02 -5.763144E-05 -2.815285E-02 -1.152065E-04 -2.037972E-02 -4.949376E-05 -3.118074E-02 -1.103084E-04 -2.652943E-02 -7.950175E-05 -2.821700E-02 -9.085185E-05 -2.985586E-02 -1.075718E-04 -2.519195E-02 -7.329635E-05 -2.548988E-02 -7.800201E-05 -4.334204E-02 -2.354327E-04 -4.370525E-02 -2.090531E-04 -4.006925E-02 -2.178363E-04 -4.954585E-02 -2.700073E-04 -4.092841E-02 -2.238665E-04 -2.776415E-02 -8.914334E-05 -4.493102E-02 -2.333231E-04 -5.357023E-02 -3.291447E-04 -3.963439E-02 -1.816002E-04 -5.209753E-02 -3.068180E-04 -4.986170E-02 -2.874548E-04 -4.594257E-02 -2.466016E-04 -7.630622E-02 -6.261797E-04 -5.881534E-02 -3.747957E-04 -6.780811E-02 -4.976784E-04 -8.984762E-02 -8.898655E-04 -5.491164E-02 -3.345133E-04 -5.735501E-02 -3.771763E-04 -7.877228E-02 -6.794994E-04 -9.906424E-02 -1.046741E-03 -5.785970E-02 -4.133043E-04 -7.848689E-02 -6.870125E-04 -1.047444E-01 -1.223298E-03 -7.404855E-02 -5.854937E-04 -9.032228E-02 -8.427419E-04 -8.401933E-02 -7.146695E-04 -8.655196E-02 -8.118612E-04 -1.130946E-01 -1.398959E-03 -9.597180E-02 -1.024696E-03 -1.173027E-01 -1.427372E-03 -1.057440E-01 -1.169551E-03 -1.236176E-01 -1.570398E-03 -1.126957E-01 -1.332155E-03 -1.492376E-01 -2.275171E-03 -1.540101E-01 -2.443893E-03 -1.715020E-01 -3.018404E-03 -7.291542E-02 -5.897697E-04 -7.660305E-02 -6.300479E-04 -9.197170E-02 -8.994110E-04 -9.982203E-02 -1.045655E-03 -1.033399E-01 -1.152382E-03 -1.139526E-01 -1.408827E-03 -8.350520E-02 -7.494750E-04 -9.839459E-02 -1.011369E-03 -1.077860E-01 -1.279212E-03 -1.228340E-01 -1.621769E-03 -1.144053E-01 -1.334188E-03 -1.571539E-01 -2.565349E-03 -6.233439E-02 -4.263330E-04 -6.563411E-02 -5.048147E-04 -6.507814E-02 -4.812141E-04 -6.362658E-02 -4.417375E-04 -7.986988E-02 -7.190156E-04 -8.970255E-02 -8.714050E-04 -5.717855E-02 -3.416545E-04 -5.668804E-02 -3.415895E-04 -7.197316E-02 -5.676520E-04 -7.136224E-02 -5.599617E-04 -8.054458E-02 -7.445675E-04 -1.023397E-01 -1.107780E-03 -4.458142E-02 -2.130924E-04 -5.439535E-02 -3.275861E-04 -5.080989E-02 -2.798307E-04 -3.946665E-02 -1.879310E-04 -6.271593E-02 -4.257844E-04 -4.965993E-02 -2.741721E-04 -4.221851E-02 -1.992549E-04 -3.585135E-02 -1.543110E-04 -4.558668E-02 -2.566453E-04 -3.888908E-02 -1.783945E-04 -4.502379E-02 -2.492156E-04 -5.625550E-02 -3.626058E-04 -2.128686E-02 -5.310350E-05 -2.848081E-02 -1.032351E-04 -3.198369E-02 -1.191780E-04 -3.220035E-02 -1.276802E-04 -3.463447E-02 -1.270326E-04 -3.109004E-02 -1.168059E-04 -2.332999E-02 -6.452643E-05 -2.117480E-02 -5.228816E-05 -2.838827E-02 -1.161483E-04 -2.329241E-02 -6.809020E-05 -2.459549E-02 -7.138168E-05 -2.765800E-02 -9.045558E-05 -1.370243E-02 -3.338519E-05 -1.582736E-02 -3.857108E-05 -1.914636E-02 -4.789559E-05 -1.905516E-02 -4.419778E-05 -1.810520E-02 -3.877471E-05 -2.115307E-02 -7.229884E-05 -1.882956E-02 -4.805493E-05 -9.281049E-03 -1.409203E-05 -1.706945E-02 -3.299567E-05 -2.172381E-02 -5.595328E-05 -1.104074E-02 -1.584618E-05 -1.946919E-02 -4.863958E-05 -1.238685E-02 -2.066688E-05 -1.378714E-02 -2.843856E-05 -1.670520E-02 -3.555438E-05 -2.766185E-02 -9.046517E-05 -1.691132E-02 -3.290270E-05 -1.927098E-02 -5.061316E-05 -1.202893E-02 -1.958457E-05 -1.922540E-02 -4.323737E-05 -1.274015E-02 -2.175309E-05 -1.524415E-02 -3.024778E-05 -1.567541E-02 -4.050037E-05 -1.898211E-02 -6.605988E-05 -2.223387E-02 -5.741257E-05 -2.452031E-02 -8.066778E-05 -2.491977E-02 -8.109453E-05 -2.610295E-02 -7.731723E-05 -1.803031E-02 -3.613025E-05 -2.184838E-02 -6.008277E-05 -2.576522E-02 -7.561914E-05 -3.038022E-02 -1.150600E-04 -2.471237E-02 -7.123333E-05 -3.173089E-02 -1.261453E-04 -3.197437E-02 -1.411443E-04 -2.786611E-02 -8.928073E-05 -4.565549E-02 -2.352807E-04 -3.535175E-02 -1.583088E-04 -4.110758E-02 -2.035220E-04 -5.345474E-02 -3.515666E-04 -3.820824E-02 -1.563980E-04 -3.254512E-02 -1.163872E-04 -4.763741E-02 -2.544110E-04 -5.216626E-02 -2.867256E-04 -4.162668E-02 -2.258042E-04 -5.349959E-02 -3.167588E-04 -5.268155E-02 -3.037455E-04 -4.827712E-02 -2.530854E-04 -7.203623E-02 -5.807994E-04 -5.256504E-02 -2.870331E-04 -7.227033E-02 -5.557721E-04 -8.778648E-02 -8.961223E-04 -5.726539E-02 -3.647823E-04 -5.856701E-02 -3.711206E-04 -8.418818E-02 -8.420171E-04 -1.110902E-01 -1.311451E-03 -6.849413E-02 -4.990580E-04 -8.795189E-02 -8.053436E-04 -1.002509E-01 -1.136773E-03 -8.057346E-02 -7.326604E-04 -8.129820E-02 -6.905078E-04 -7.847809E-02 -7.619983E-04 -9.737274E-02 -1.035174E-03 -1.154716E-01 -1.385047E-03 -9.040089E-02 -8.570313E-04 -1.211664E-01 -1.547158E-03 -1.031330E-01 -1.146280E-03 -1.249586E-01 -1.649464E-03 -7.259655E-02 -5.736210E-04 -9.951286E-02 -1.046118E-03 -1.634971E-01 -2.756448E-03 -1.297207E-01 -1.735289E-03 -6.477036E-02 -5.010788E-04 -7.479236E-02 -6.145152E-04 -9.983365E-02 -1.091064E-03 -1.057264E-01 -1.249917E-03 -8.524281E-02 -7.807948E-04 -1.159165E-01 -1.434680E-03 -7.914697E-02 -6.791950E-04 -9.369015E-02 -9.476358E-04 -9.819988E-02 -1.022095E-03 -9.686028E-02 -1.016599E-03 -1.294766E-01 -1.810274E-03 -1.296189E-01 -1.785443E-03 -5.535491E-02 -4.100726E-04 -5.475647E-02 -3.309264E-04 -7.075605E-02 -6.187772E-04 -6.387417E-02 -4.196497E-04 -7.578685E-02 -6.019889E-04 -8.903112E-02 -9.119475E-04 -6.385945E-02 -4.650950E-04 -5.390120E-02 -3.165606E-04 -5.744329E-02 -3.580388E-04 -5.920600E-02 -3.893593E-04 -7.525234E-02 -6.092966E-04 -8.573764E-02 -7.942436E-04 -2.797792E-02 -8.517754E-05 -3.790894E-02 -1.764825E-04 -4.239936E-02 -2.094748E-04 -4.003024E-02 -1.918379E-04 -5.137956E-02 -3.003587E-04 -3.883708E-02 -2.005906E-04 -2.858632E-02 -9.126637E-05 -3.012004E-02 -9.617653E-05 -4.160100E-02 -1.981616E-04 -4.247458E-02 -1.951666E-04 -3.989011E-02 -1.920698E-04 -5.270057E-02 -4.088719E-04 -1.934929E-02 -4.412789E-05 -2.359082E-02 -7.371994E-05 -2.394998E-02 -6.675994E-05 -2.637339E-02 -8.517554E-05 -2.328326E-02 -6.212789E-05 -3.651578E-02 -1.464186E-04 -2.140441E-02 -5.613878E-05 -2.241671E-02 -6.918410E-05 -2.337122E-02 -6.432183E-05 -2.144477E-02 -6.203786E-05 -3.024192E-02 -1.083505E-04 -3.331930E-02 -1.347081E-04 -1.564695E-02 -3.553327E-05 -1.812645E-02 -3.940659E-05 -2.235798E-02 -6.269701E-05 -1.419345E-02 -3.096864E-05 -2.228629E-02 -7.578567E-05 -1.860794E-02 -4.332178E-05 -1.533239E-02 -3.896858E-05 -1.580257E-02 -3.874692E-05 -2.185955E-02 -7.842950E-05 -1.195136E-02 -1.715334E-05 -1.691111E-02 -5.345113E-05 -1.575376E-02 -3.654434E-05 -1.594875E-02 -2.957220E-05 -1.223541E-02 -2.476765E-05 -1.370590E-02 -2.764042E-05 -2.661246E-02 -1.016998E-04 -2.080371E-02 -4.813282E-05 -2.468736E-02 -6.974038E-05 -1.405638E-02 -2.572385E-05 -2.459760E-02 -7.159383E-05 -1.228308E-02 -1.773752E-05 -1.017949E-02 -1.885833E-05 -2.024611E-02 -5.718430E-05 -1.797631E-02 -4.281825E-05 -1.570780E-02 -3.056781E-05 -1.271841E-02 -2.456995E-05 -2.932023E-02 -9.261980E-05 -3.237241E-02 -1.211680E-04 -2.105195E-02 -5.549955E-05 -2.483667E-02 -7.162437E-05 -2.011907E-02 -5.130375E-05 -1.983609E-02 -4.987791E-05 -1.492495E-02 -3.087968E-05 -2.870495E-02 -9.962637E-05 -2.722358E-02 -8.845542E-05 -2.118986E-02 -5.204535E-05 -4.348038E-02 -2.209404E-04 -3.712818E-02 -1.689129E-04 -4.138693E-02 -1.981821E-04 -4.470777E-02 -2.289185E-04 -2.764424E-02 -9.090079E-05 -2.655560E-02 -9.474172E-05 -4.524862E-02 -2.292538E-04 -5.164196E-02 -2.774634E-04 -3.466551E-02 -1.631603E-04 -3.563208E-02 -1.379234E-04 -4.211986E-02 -1.930478E-04 -3.079625E-02 -1.135265E-04 -5.465211E-02 -3.301887E-04 -4.860409E-02 -2.888426E-04 -7.075978E-02 -5.108370E-04 -6.867881E-02 -5.424435E-04 -3.427613E-02 -1.426574E-04 -5.955830E-02 -3.940963E-04 -6.828982E-02 -4.738886E-04 -6.525289E-02 -4.898769E-04 -3.737982E-02 -1.638396E-04 -5.286730E-02 -3.082087E-04 -6.158083E-02 -4.216724E-04 -4.980750E-02 -2.726737E-04 -5.696575E-02 -3.692634E-04 -5.058820E-02 -2.744701E-04 -6.726109E-02 -4.926664E-04 -7.839336E-02 -6.590448E-04 -7.010209E-02 -5.719905E-04 -8.384171E-02 -7.652328E-04 -6.937383E-02 -5.168671E-04 -9.468263E-02 -9.868090E-04 -5.004326E-02 -2.785169E-04 -6.606152E-02 -4.541359E-04 -9.675798E-02 -1.063286E-03 -7.230289E-02 -5.573682E-04 -6.543974E-02 -5.078440E-04 -5.267920E-02 -3.176937E-04 -8.194553E-02 -6.982175E-04 -9.613453E-02 -1.079846E-03 -6.113228E-02 -4.004864E-04 -8.522953E-02 -7.810809E-04 -5.316859E-02 -3.091340E-04 -7.827195E-02 -6.540396E-04 -5.463776E-02 -3.503148E-04 -5.071284E-02 -3.191021E-04 -8.557140E-02 -7.639230E-04 -7.700044E-02 -6.547991E-04 -5.105846E-02 -2.888427E-04 -5.004859E-02 -2.887941E-04 -5.147919E-02 -3.256217E-04 -5.538533E-02 -3.360110E-04 -6.140039E-02 -4.129538E-04 -5.936836E-02 -4.315037E-04 -4.930384E-02 -2.889606E-04 -4.619680E-02 -2.419601E-04 -4.445739E-02 -2.331544E-04 -4.824154E-02 -2.469526E-04 -6.974394E-02 -5.056104E-04 -6.084953E-02 -3.932556E-04 -3.577286E-02 -1.452599E-04 -3.166228E-02 -1.303590E-04 -3.862777E-02 -1.632780E-04 -3.916934E-02 -1.779181E-04 -3.625045E-02 -1.745839E-04 -4.231134E-02 -2.225093E-04 -3.359703E-02 -1.419870E-04 -4.006089E-02 -1.707049E-04 -3.658866E-02 -1.730857E-04 -3.341254E-02 -1.297042E-04 -4.263417E-02 -2.215026E-04 -3.955323E-02 -1.921082E-04 -2.174079E-02 -5.222197E-05 -2.442434E-02 -8.243601E-05 -2.914443E-02 -1.214208E-04 -1.824800E-02 -4.893719E-05 -3.091152E-02 -1.051207E-04 -2.972565E-02 -1.063333E-04 -3.002196E-02 -1.026816E-04 -1.967353E-02 -5.819743E-05 -2.921034E-02 -1.035681E-04 -2.329404E-02 -7.915033E-05 -2.537416E-02 -9.811049E-05 -2.636605E-02 -8.177530E-05 -9.035064E-03 -1.555651E-05 -1.655675E-02 -4.002782E-05 -1.372662E-02 -3.244904E-05 -1.311878E-02 -2.619244E-05 -1.611214E-02 -3.084313E-05 -1.574836E-02 -3.450927E-05 -7.693366E-03 -1.606361E-05 -1.135596E-02 -1.801519E-05 -1.342059E-02 -2.516888E-05 -1.160985E-02 -2.390704E-05 -1.383386E-02 -2.800471E-05 -1.971360E-02 -8.842562E-05 -1.183879E-02 -1.932907E-05 -8.105380E-03 -1.234549E-05 -1.271210E-02 -2.405656E-05 -1.537131E-02 -3.137697E-05 -1.591997E-02 -3.769775E-05 -1.088552E-02 -1.713348E-05 -1.515322E-02 -3.039160E-05 -1.275379E-02 -2.585038E-05 -8.475047E-03 -1.032301E-05 -1.017506E-02 -2.019761E-05 -1.192565E-02 -2.149550E-05 -8.221048E-03 -8.986302E-06 -1.307738E-02 -2.107929E-05 -1.086073E-02 -1.558009E-05 -2.199295E-02 -5.739512E-05 -1.994568E-02 -5.494728E-05 -1.534082E-02 -3.625194E-05 -1.764761E-02 -4.067341E-05 -1.796742E-02 -4.680639E-05 -2.032190E-02 -5.017032E-05 -1.749541E-02 -4.866856E-05 -1.732369E-02 -4.955885E-05 -1.681732E-02 -3.837118E-05 -1.769405E-02 -5.487143E-05 -2.888259E-02 -1.026998E-04 -2.098585E-02 -6.932453E-05 -3.313341E-02 -1.351006E-04 -3.207197E-02 -1.295024E-04 -2.459220E-02 -8.336446E-05 -2.450985E-02 -6.648377E-05 -3.117162E-02 -1.195002E-04 -4.003079E-02 -2.123347E-04 -2.176609E-02 -6.269817E-05 -2.994428E-02 -1.235590E-04 -3.524085E-02 -1.599016E-04 -2.408409E-02 -6.486120E-05 -4.186261E-02 -1.804413E-04 -4.461985E-02 -2.229520E-04 -3.815900E-02 -1.674626E-04 -4.651996E-02 -2.353452E-04 -4.372936E-02 -2.126895E-04 -3.471725E-02 -1.536658E-04 -3.777496E-02 -1.682954E-04 -4.542053E-02 -2.887036E-04 -3.302349E-02 -1.252640E-04 -3.007472E-02 -1.103699E-04 -4.167073E-02 -1.843542E-04 -3.435406E-02 -1.576055E-04 -5.142055E-02 -2.840339E-04 -4.459791E-02 -2.437118E-04 -5.240798E-02 -3.061931E-04 -6.184982E-02 -3.987655E-04 -4.185540E-02 -2.035740E-04 -4.274424E-02 -1.929214E-04 -4.853301E-02 -2.820023E-04 -7.063952E-02 -5.492235E-04 -4.633212E-02 -2.687210E-04 -5.821695E-02 -3.976817E-04 -6.625094E-02 -4.940422E-04 -6.129214E-02 -4.099540E-04 -3.772075E-02 -1.660719E-04 -3.714570E-02 -1.541156E-04 -4.493005E-02 -2.310471E-04 -4.557412E-02 -2.432878E-04 -4.065422E-02 -1.871281E-04 -5.417420E-02 -3.505844E-04 -3.708658E-02 -1.717372E-04 -5.130291E-02 -3.077258E-04 -3.417926E-02 -1.492890E-04 -3.377463E-02 -1.256710E-04 -5.369283E-02 -3.432927E-04 -4.836021E-02 -2.588228E-04 -3.269371E-02 -1.286374E-04 -2.896989E-02 -1.123018E-04 -4.848291E-02 -2.612160E-04 -4.333314E-02 -2.292463E-04 -3.759979E-02 -1.680559E-04 -5.061237E-02 -2.724683E-04 -3.926039E-02 -1.797325E-04 -3.938137E-02 -1.851970E-04 -3.570566E-02 -1.506562E-04 -4.159909E-02 -2.157074E-04 -5.099360E-02 -2.844970E-04 -4.605309E-02 -2.508391E-04 -2.500341E-02 -7.363724E-05 -3.039879E-02 -1.123549E-04 -3.534598E-02 -1.698480E-04 -3.702744E-02 -1.486744E-04 -3.410129E-02 -1.365716E-04 -3.991621E-02 -1.846954E-04 -3.186334E-02 -1.158884E-04 -3.268754E-02 -1.178259E-04 -2.428429E-02 -7.876563E-05 -2.495449E-02 -7.906081E-05 -3.551756E-02 -1.519603E-04 -3.018593E-02 -9.724962E-05 -2.032098E-02 -4.781656E-05 -3.017998E-02 -1.313561E-04 -2.424929E-02 -6.480258E-05 -1.950042E-02 -4.417513E-05 -2.943418E-02 -9.948664E-05 -2.707621E-02 -1.035208E-04 -1.957350E-02 -4.711947E-05 -1.583335E-02 -2.891313E-05 -2.972335E-02 -1.047751E-04 -1.739423E-02 -4.376709E-05 -1.705633E-02 -3.892027E-05 -2.121975E-02 -5.891607E-05 -1.002146E-02 -2.339078E-05 -1.405706E-02 -3.175594E-05 -1.011207E-02 -1.585291E-05 -1.573069E-02 -3.554827E-05 -1.518567E-02 -3.047833E-05 -1.617187E-02 -3.397385E-05 -7.920296E-03 -1.026935E-05 -1.007121E-02 -1.858100E-05 -1.510615E-02 -3.313591E-05 -8.793659E-03 -1.446961E-05 -1.205856E-02 -2.648093E-05 -8.862721E-03 -1.309660E-05 -1.096965E-02 -1.673476E-05 -9.547722E-03 -1.233633E-05 -1.206088E-02 -1.968307E-05 -1.373042E-02 -2.332622E-05 -7.956349E-03 -9.952553E-06 -1.135126E-02 -2.254375E-05 -8.206639E-03 -1.278801E-05 -8.323868E-03 -9.465618E-06 -5.007925E-03 -3.901625E-06 -1.175607E-02 -2.482648E-05 -1.115574E-02 -1.628158E-05 -1.194446E-02 -2.092004E-05 -1.597054E-02 -4.823093E-05 -2.068463E-02 -6.502935E-05 -1.091363E-02 -1.741992E-05 -1.977283E-02 -6.091082E-05 -1.302782E-02 -3.043481E-05 -9.410139E-03 -1.600990E-05 -2.280622E-02 -8.006568E-05 -1.891920E-02 -4.976676E-05 -1.429805E-02 -3.039093E-05 -1.718931E-02 -4.113244E-05 -1.888654E-02 -4.574971E-05 -1.694065E-02 -4.597734E-05 -2.282444E-02 -7.094719E-05 -1.988920E-02 -4.882297E-05 -2.742750E-02 -8.906026E-05 -2.101679E-02 -5.924755E-05 -1.895054E-02 -4.827704E-05 -1.764949E-02 -3.979458E-05 -2.040100E-02 -5.014728E-05 -2.987304E-02 -1.026215E-04 -1.943000E-02 -5.159278E-05 -2.438024E-02 -8.804424E-05 -1.861542E-02 -5.122973E-05 -2.192303E-02 -7.333728E-05 -2.042748E-02 -5.322568E-05 -1.860799E-02 -4.480883E-05 -2.511896E-02 -8.995213E-05 -2.543363E-02 -7.306514E-05 -2.559384E-02 -7.149326E-05 -2.813173E-02 -8.655606E-05 -1.981717E-02 -5.094262E-05 -3.244910E-02 -1.169817E-04 -2.278981E-02 -6.510336E-05 -2.089376E-02 -5.410560E-05 -4.419213E-02 -2.403809E-04 -3.061708E-02 -1.062702E-04 -2.717980E-02 -8.418003E-05 -2.722963E-02 -1.052169E-04 -3.623076E-02 -1.607841E-04 -3.979211E-02 -1.939688E-04 -2.474544E-02 -8.590714E-05 -3.372593E-02 -1.249071E-04 -2.961528E-02 -1.048999E-04 -3.445466E-02 -1.406914E-04 -2.454390E-02 -6.874037E-05 -2.368906E-02 -7.545364E-05 -3.410678E-02 -1.304264E-04 -2.229870E-02 -5.686464E-05 -2.886351E-02 -1.132080E-04 -2.149789E-02 -5.426448E-05 -3.009295E-02 -1.146713E-04 -3.196558E-02 -1.284969E-04 -2.870373E-02 -1.154291E-04 -2.864913E-02 -1.010245E-04 -2.270198E-02 -5.519665E-05 -2.760090E-02 -9.328867E-05 -2.484231E-02 -7.506549E-05 -2.750137E-02 -8.791015E-05 -3.435235E-02 -1.548738E-04 -2.827137E-02 -9.747974E-05 -2.704164E-02 -8.477548E-05 -3.021819E-02 -1.103214E-04 -3.294793E-02 -1.535995E-04 -4.645100E-02 -2.665607E-04 -1.872361E-02 -5.132776E-05 -2.760454E-02 -9.345927E-05 -3.258565E-02 -1.242178E-04 -3.666600E-02 -1.621867E-04 -2.545558E-02 -7.466531E-05 -2.185810E-02 -5.238791E-05 -3.105333E-02 -1.301601E-04 -3.170709E-02 -1.068496E-04 -1.858402E-02 -4.089794E-05 -2.136675E-02 -8.120782E-05 -2.443102E-02 -6.744651E-05 -2.220457E-02 -6.176678E-05 -2.702281E-02 -8.511652E-05 -2.446488E-02 -7.312450E-05 -2.589652E-02 -8.029643E-05 -2.337286E-02 -6.920676E-05 -2.906370E-02 -9.769604E-05 -1.361898E-02 -2.599329E-05 -1.718829E-02 -4.532911E-05 -2.553342E-02 -8.882028E-05 -1.945946E-02 -5.218395E-05 -1.097230E-02 -2.337563E-05 -2.298715E-02 -7.077749E-05 -2.181520E-02 -7.357036E-05 -1.664629E-02 -3.440840E-05 -1.886608E-02 -6.788750E-05 -1.789466E-02 -3.954208E-05 -1.813733E-02 -4.477178E-05 -1.319469E-02 -3.100847E-05 -1.940763E-02 -6.158493E-05 -1.149667E-02 -1.737857E-05 -2.405005E-02 -9.854391E-05 -1.421017E-02 -2.890108E-05 -1.029738E-02 -1.683759E-05 -1.065410E-02 -1.640087E-05 -9.811218E-03 -1.720212E-05 -1.158507E-02 -1.760286E-05 -1.432482E-02 -2.834073E-05 -3.465902E-03 -3.161524E-06 -1.038868E-02 -2.168047E-05 -1.116866E-02 -1.793978E-05 -8.524850E-03 -9.322322E-06 -1.237537E-02 -3.617368E-05 -1.465218E-02 -3.350573E-05 -7.514724E-03 -9.368017E-06 -2.560189E-03 -1.617445E-06 -8.383240E-03 -1.252593E-05 -9.446758E-03 -1.648768E-05 -7.696663E-03 -8.060991E-06 -9.311783E-03 -1.189977E-05 -6.939672E-03 -8.850888E-06 -5.252459E-03 -4.564362E-06 -7.234899E-03 -1.328951E-05 -8.665099E-03 -1.300142E-05 -9.793568E-03 -2.082520E-05 -8.825280E-03 -1.579613E-05 -1.194803E-02 -1.908193E-05 -1.074524E-02 -2.172388E-05 -1.481905E-02 -2.964893E-05 -1.294498E-02 -3.011738E-05 -8.115330E-03 -1.173017E-05 -1.093458E-02 -1.599591E-05 -1.415025E-02 -2.928045E-05 -8.999567E-03 -1.238982E-05 -7.873894E-03 -9.521432E-06 -7.526246E-03 -7.594924E-06 -1.349525E-02 -3.958103E-05 -1.459461E-02 -3.194364E-05 -1.198421E-02 -2.138597E-05 -1.015128E-02 -1.539096E-05 -1.747797E-02 -3.561184E-05 -2.401867E-02 -7.148091E-05 -1.586654E-02 -3.323231E-05 -1.800611E-02 -4.401522E-05 -1.463450E-02 -2.989044E-05 -1.683853E-02 -3.902727E-05 -1.359168E-02 -2.739250E-05 -9.625117E-03 -1.469220E-05 -1.294386E-02 -2.799895E-05 -1.103469E-02 -2.133672E-05 -1.869882E-02 -4.772681E-05 -1.503975E-02 -2.896451E-05 -1.677894E-02 -4.314601E-05 -2.258467E-02 -1.041456E-04 -1.878411E-02 -4.558049E-05 -1.310146E-02 -2.541487E-05 -1.653039E-02 -3.204738E-05 -1.927088E-02 -5.304249E-05 -8.390867E-03 -1.408823E-05 -1.750394E-02 -4.947439E-05 -1.909888E-02 -5.305029E-05 -1.321359E-02 -3.195949E-05 -1.767250E-02 -4.284184E-05 -1.766010E-02 -4.445269E-05 -1.752133E-02 -3.470706E-05 -2.024733E-02 -5.360810E-05 -1.219423E-02 -1.890812E-05 -1.433551E-02 -2.552372E-05 -1.488366E-02 -3.633706E-05 -1.309982E-02 -2.303088E-05 -1.409845E-02 -2.964092E-05 -1.364964E-02 -2.674995E-05 -2.346093E-02 -7.742790E-05 -1.619070E-02 -3.640820E-05 -1.814514E-02 -4.174971E-05 -2.088143E-02 -7.915120E-05 -2.104482E-02 -4.999110E-05 -2.108577E-02 -5.080473E-05 -1.346978E-02 -2.428984E-05 -1.812802E-02 -3.900263E-05 -1.634894E-02 -3.058475E-05 -1.823343E-02 -4.657246E-05 -1.701022E-02 -3.432397E-05 -1.436832E-02 -2.643066E-05 -1.883466E-02 -4.651260E-05 -1.591237E-02 -3.845574E-05 -1.590406E-02 -3.248073E-05 -1.054631E-02 -1.655070E-05 -2.057489E-02 -5.055329E-05 -1.697824E-02 -3.893444E-05 -1.770103E-02 -4.383559E-05 -2.134851E-02 -6.780393E-05 -1.403120E-02 -2.708815E-05 -1.449734E-02 -2.419619E-05 -1.239576E-02 -2.043627E-05 -1.415699E-02 -2.224645E-05 -1.888682E-02 -4.935465E-05 -2.160682E-02 -6.329152E-05 -2.247940E-02 -7.810124E-05 -9.606213E-03 -1.667840E-05 -2.476229E-02 -8.144159E-05 -1.725175E-02 -3.611282E-05 -1.207190E-02 -1.626596E-05 -1.353421E-02 -2.329766E-05 -1.059055E-02 -1.677463E-05 -9.737491E-03 -1.431106E-05 -6.593375E-03 -7.399377E-06 -7.039159E-03 -1.176702E-05 -1.413677E-02 -3.138472E-05 -1.094329E-02 -2.263303E-05 -6.672931E-03 -6.045366E-06 -1.032380E-02 -2.352298E-05 -8.848889E-03 -1.498309E-05 -1.268157E-02 -2.766060E-05 -7.349115E-03 -1.091693E-05 -1.228088E-02 -2.189060E-05 -1.067250E-02 -1.715732E-05 -1.212246E-02 -2.269620E-05 -4.674814E-03 -3.219220E-06 -8.219501E-03 -1.509768E-05 -1.073016E-02 -2.022852E-05 -9.406782E-03 -1.697200E-05 -7.646611E-03 -1.456233E-05 -1.080915E-02 -2.357182E-05 -6.308610E-03 -8.327166E-06 -7.590107E-03 -8.423541E-06 -1.348669E-02 -2.807690E-05 -1.095856E-02 -2.888898E-05 -5.395294E-03 -5.989965E-06 -6.079841E-03 -7.580064E-06 -7.505564E-03 -8.646729E-06 -6.201233E-03 -6.428779E-06 -1.063698E-02 -1.939413E-05 -7.313889E-03 -9.141624E-06 -9.430810E-03 -1.648005E-05 -4.842603E-03 -4.844512E-06 -5.427814E-03 -4.345647E-06 -6.437292E-03 -1.207973E-05 -8.251158E-03 -1.318350E-05 -8.809423E-03 -1.058811E-05 -5.856619E-03 -4.969559E-06 -6.991101E-03 -6.849651E-06 -5.629621E-03 -5.550323E-06 -2.585500E-03 -1.553122E-06 -1.066559E-02 -1.715979E-05 -3.085260E-03 -6.253271E-06 -9.034984E-03 -1.521387E-05 -6.190606E-03 -9.176053E-06 -9.871403E-03 -1.358973E-05 -9.739545E-03 -1.286586E-05 -7.798343E-03 -9.886920E-06 -8.149958E-03 -1.041850E-05 -2.102030E-02 -6.158217E-05 -1.435765E-02 -3.237028E-05 -7.642569E-03 -7.907376E-06 -1.123406E-02 -1.955695E-05 -1.457081E-02 -3.914562E-05 -1.788958E-02 -5.996510E-05 -1.769436E-02 -4.502383E-05 -1.240825E-02 -2.303672E-05 -1.715444E-02 -4.328672E-05 -1.566180E-02 -3.978890E-05 -1.487883E-02 -3.400964E-05 -8.561200E-03 -1.036201E-05 -2.295904E-02 -5.920445E-05 -1.388508E-02 -3.937752E-05 -1.678190E-02 -4.497456E-05 -2.154484E-02 -5.386125E-05 -6.765444E-03 -7.415266E-06 -1.215420E-02 -2.091620E-05 -2.017061E-02 -7.287759E-05 -1.909053E-02 -5.506644E-05 -1.735888E-02 -3.831995E-05 -1.991557E-02 -4.972306E-05 -1.790749E-02 -4.112227E-05 -1.407457E-02 -3.094925E-05 -2.974572E-02 -1.118172E-04 -1.708785E-02 -4.386435E-05 -2.659193E-02 -9.219939E-05 -3.035144E-02 -1.010119E-04 -1.546737E-02 -3.391982E-05 -1.887938E-02 -4.714248E-05 -1.653679E-02 -4.949250E-05 -2.110944E-02 -5.597556E-05 -2.409526E-02 -6.448595E-05 -2.230819E-02 -5.707848E-05 -1.670895E-02 -3.363955E-05 -1.501463E-02 -2.702669E-05 -1.631677E-02 -3.749166E-05 -1.693626E-02 -4.121173E-05 -2.622206E-02 -7.529216E-05 -2.377917E-02 -7.407839E-05 -1.384279E-02 -2.857021E-05 -2.126418E-02 -7.856414E-05 -1.911630E-02 -4.652883E-05 -2.184179E-02 -5.852148E-05 -1.866708E-02 -6.033622E-05 -1.172279E-02 -3.314139E-05 -1.311652E-02 -2.727134E-05 -1.670812E-02 -4.624330E-05 -1.830609E-02 -5.348783E-05 -8.513210E-03 -1.188353E-05 -1.897475E-02 -4.496529E-05 -1.598385E-02 -3.154883E-05 -1.811274E-02 -4.681726E-05 -1.851236E-02 -4.861112E-05 -1.207908E-02 -2.020737E-05 -1.762593E-02 -4.600809E-05 -1.426171E-02 -3.389465E-05 -1.390938E-02 -4.304132E-05 -1.119665E-02 -2.002203E-05 -7.985862E-03 -1.299182E-05 -1.682922E-02 -3.705605E-05 -1.031217E-02 -1.306045E-05 -1.806448E-02 -4.605140E-05 -1.608612E-02 -3.278234E-05 -7.379583E-03 -7.040180E-06 -1.449866E-02 -3.734314E-05 -1.126405E-02 -1.862160E-05 -1.434466E-02 -3.067276E-05 -1.321482E-02 -2.270946E-05 -1.175946E-02 -2.009819E-05 -8.940307E-03 -1.544249E-05 -1.025576E-02 -1.330247E-05 -1.007614E-02 -1.877197E-05 -8.436802E-03 -1.196625E-05 -2.085623E-02 -4.953759E-05 -1.670794E-02 -3.716863E-05 -1.187761E-02 -1.890192E-05 -1.850976E-02 -4.429493E-05 -4.944517E-03 -5.165715E-06 -8.128340E-03 -1.296218E-05 -1.004447E-02 -2.214422E-05 -9.963052E-03 -1.184842E-05 -7.100471E-03 -8.005623E-06 -8.470273E-03 -9.214382E-06 -1.033575E-02 -1.452750E-05 -9.624022E-03 -1.558452E-05 -8.869432E-03 -1.517840E-05 -1.644470E-02 -3.397196E-05 -7.598019E-03 -8.133919E-06 -8.945737E-03 -9.377464E-06 -5.254834E-03 -4.575273E-06 -7.542267E-03 -7.505652E-06 -9.629827E-03 -1.342434E-05 -1.060266E-02 -1.838055E-05 -3.984507E-03 -2.782462E-06 -6.823286E-03 -7.715504E-06 -8.192618E-03 -1.009785E-05 -6.740618E-03 -6.753208E-06 -1.002813E-02 -1.566585E-05 -1.402360E-02 -2.627061E-05 -9.551680E-03 -1.549743E-05 -8.410173E-03 -1.532161E-05 -9.576682E-03 -1.926642E-05 -1.644285E-02 -3.894395E-05 -9.352112E-03 -1.947845E-05 -9.522578E-03 -1.480589E-05 -1.000109E-02 -1.623473E-05 -1.271924E-02 -2.496798E-05 -1.245375E-02 -2.043780E-05 -1.519888E-02 -3.853835E-05 -6.618627E-03 -6.345424E-06 -7.617580E-03 -8.381516E-06 -7.713051E-03 -1.245806E-05 -8.903456E-03 -2.254781E-05 -1.402208E-02 -2.721848E-05 -1.177140E-02 -1.953130E-05 -1.553072E-02 -2.893580E-05 -1.482066E-02 -3.081970E-05 -9.853191E-03 -1.543282E-05 -1.186384E-02 -2.281665E-05 -1.908232E-02 -6.119132E-05 -1.778254E-02 -3.849134E-05 -1.611496E-02 -4.189813E-05 -1.421950E-02 -3.103442E-05 -2.000883E-02 -5.088716E-05 -1.245870E-02 -2.904861E-05 -2.474667E-02 -7.684411E-05 -1.941450E-02 -4.850566E-05 -1.968721E-02 -4.734318E-05 -2.432138E-02 -7.957731E-05 -1.944046E-02 -4.206030E-05 -2.088512E-02 -5.312412E-05 -2.457361E-02 -7.162438E-05 -2.803303E-02 -9.243404E-05 -2.233188E-02 -6.441041E-05 -2.574667E-02 -7.744780E-05 -2.097121E-02 -5.650314E-05 -2.655826E-02 -8.660847E-05 -3.014326E-02 -9.991619E-05 -2.918919E-02 -9.452555E-05 -2.056057E-02 -5.184372E-05 -2.990570E-02 -1.037648E-04 -2.737932E-02 -8.833139E-05 -2.356419E-02 -7.644776E-05 -3.458839E-02 -1.364027E-04 -3.248751E-02 -1.186240E-04 -3.228724E-02 -1.162923E-04 -2.982979E-02 -1.051045E-04 -2.749198E-02 -9.013699E-05 -2.265201E-02 -7.821751E-05 -2.861490E-02 -8.974738E-05 -3.877353E-02 -1.862085E-04 -2.264214E-02 -6.419386E-05 -2.565522E-02 -8.379023E-05 -3.327436E-02 -1.251213E-04 -3.365022E-02 -1.304927E-04 -3.331544E-02 -1.267184E-04 -3.940664E-02 -2.082874E-04 -3.417164E-02 -1.331489E-04 -3.695924E-02 -1.695935E-04 -3.660181E-02 -1.980269E-04 -3.049799E-02 -1.104243E-04 -3.359904E-02 -1.326383E-04 -2.972450E-02 -9.587313E-05 -2.323160E-02 -6.471218E-05 -1.839074E-02 -4.208719E-05 -2.714264E-02 -9.372657E-05 -2.872170E-02 -1.078922E-04 -3.679226E-02 -1.459261E-04 -2.377295E-02 -6.705585E-05 -3.481909E-02 -1.319533E-04 -3.638325E-02 -1.510511E-04 -2.047379E-02 -4.974814E-05 -3.932322E-02 -1.843858E-04 -1.516217E-02 -3.326445E-05 -2.722332E-02 -9.017263E-05 -1.892837E-02 -4.765562E-05 -1.649353E-02 -4.048523E-05 -2.604495E-02 -7.686911E-05 -2.994865E-02 -1.202039E-04 -1.882216E-02 -4.312602E-05 -1.766775E-02 -4.354878E-05 -2.897250E-02 -9.600078E-05 -2.918339E-02 -9.787984E-05 -2.599062E-02 -8.583368E-05 -3.616458E-02 -1.785317E-04 -1.716456E-02 -4.424230E-05 -2.976397E-02 -1.196639E-04 -2.137198E-02 -5.435882E-05 -1.498606E-02 -2.867869E-05 -2.026381E-02 -6.453877E-05 -2.108149E-02 -4.938367E-05 -1.505838E-02 -2.707808E-05 -1.913971E-02 -5.184273E-05 -2.583671E-02 -9.189443E-05 -2.089460E-02 -5.910541E-05 -2.539127E-02 -8.107037E-05 -2.284066E-02 -6.852612E-05 -9.835860E-03 -1.246182E-05 -1.766679E-02 -4.158408E-05 -1.105611E-02 -1.647013E-05 -1.530049E-02 -3.919500E-05 -1.429716E-02 -3.352166E-05 -1.357586E-02 -3.091775E-05 -1.403296E-02 -3.179172E-05 -1.978070E-02 -4.850759E-05 -2.453097E-02 -8.428665E-05 -1.939330E-02 -4.556576E-05 -1.086518E-02 -1.408645E-05 -1.579821E-02 -2.749151E-05 -6.361591E-03 -6.898179E-06 -7.702358E-03 -9.157872E-06 -1.066424E-02 -1.306101E-05 -9.634515E-03 -1.294132E-05 -1.081282E-02 -2.088218E-05 -1.644232E-02 -3.681578E-05 -9.494639E-03 -1.279154E-05 -5.636874E-03 -4.703193E-06 -1.434790E-02 -2.701384E-05 -1.369675E-02 -2.567531E-05 -1.234911E-02 -2.590620E-05 -1.416398E-02 -2.960800E-05 -1.122603E-02 -2.610403E-05 -1.184891E-02 -2.685267E-05 -1.469060E-02 -3.133618E-05 -2.298108E-02 -7.360049E-05 -1.696881E-02 -4.073271E-05 -1.829044E-02 -4.488597E-05 -8.021195E-03 -1.042375E-05 -7.483229E-03 -7.662752E-06 -9.938980E-03 -1.473587E-05 -6.186154E-03 -7.146893E-06 -1.873257E-02 -5.084856E-05 -1.274591E-02 -1.901691E-05 -1.717315E-02 -4.508495E-05 -2.587324E-02 -7.720386E-05 -1.352804E-02 -2.480610E-05 -1.759894E-02 -3.784552E-05 -1.498671E-02 -2.624849E-05 -2.471517E-02 -8.403653E-05 -2.938643E-02 -1.151484E-04 -2.091784E-02 -5.415805E-05 -1.642239E-02 -3.265718E-05 -2.253062E-02 -7.550922E-05 -1.773827E-02 -4.843752E-05 -1.778692E-02 -4.982541E-05 -3.337468E-02 -1.392002E-04 -3.682265E-02 -1.607062E-04 -2.911908E-02 -1.003985E-04 -2.664232E-02 -8.588222E-05 -2.953127E-02 -1.183748E-04 -2.406807E-02 -7.188877E-05 -3.628487E-02 -1.515959E-04 -3.071907E-02 -1.118121E-04 -3.755060E-02 -1.884817E-04 -3.845138E-02 -2.043330E-04 -4.208968E-02 -1.887229E-04 -2.650790E-02 -1.045695E-04 -4.879444E-02 -2.746335E-04 -3.995698E-02 -1.935956E-04 -3.437302E-02 -1.339692E-04 -4.424777E-02 -2.155808E-04 -4.000509E-02 -1.787367E-04 -3.942601E-02 -1.823141E-04 -5.484106E-02 -3.357163E-04 -5.027689E-02 -2.971747E-04 -5.028897E-02 -2.941870E-04 -5.290232E-02 -3.200207E-04 -3.871560E-02 -1.936856E-04 -4.561909E-02 -2.445140E-04 -5.329116E-02 -3.392022E-04 -6.411682E-02 -4.525641E-04 -4.491390E-02 -2.298662E-04 -4.543173E-02 -2.388585E-04 -4.973450E-02 -2.830273E-04 -4.837326E-02 -2.678945E-04 -5.988650E-02 -4.209610E-04 -5.451978E-02 -3.358217E-04 -7.335314E-02 -6.137308E-04 -7.801463E-02 -6.544817E-04 -5.589338E-02 -3.522166E-04 -5.916022E-02 -3.858273E-04 -4.698963E-02 -3.027433E-04 -5.895924E-02 -3.790017E-04 -4.172371E-02 -2.119338E-04 -3.894831E-02 -1.648204E-04 -5.343858E-02 -3.103206E-04 -4.977655E-02 -3.012635E-04 -6.585931E-02 -4.493935E-04 -5.729670E-02 -3.590518E-04 -5.609196E-02 -3.629946E-04 -6.500048E-02 -4.440662E-04 -4.327539E-02 -2.067690E-04 -5.097662E-02 -2.815490E-04 -4.628356E-02 -2.348648E-04 -4.666148E-02 -2.514991E-04 -3.669329E-02 -1.552102E-04 -4.034392E-02 -1.825094E-04 -5.718186E-02 -3.730299E-04 -3.997528E-02 -2.286198E-04 -5.850080E-02 -4.179988E-04 -3.979728E-02 -1.855473E-04 -6.121586E-02 -4.774824E-04 -5.116923E-02 -2.889253E-04 -4.642274E-02 -2.436217E-04 -5.061482E-02 -2.853049E-04 -3.070349E-02 -1.198974E-04 -4.050110E-02 -1.836951E-04 -2.876275E-02 -1.060796E-04 -3.061263E-02 -1.137168E-04 -4.146381E-02 -1.869894E-04 -4.129877E-02 -1.932088E-04 -3.448209E-02 -1.434523E-04 -3.610442E-02 -1.605801E-04 -4.093512E-02 -1.814782E-04 -4.568118E-02 -2.299954E-04 -3.364878E-02 -1.376802E-04 -3.936126E-02 -1.675197E-04 -1.952985E-02 -4.623048E-05 -2.129951E-02 -6.166111E-05 -2.459526E-02 -8.426675E-05 -1.884092E-02 -4.164051E-05 -3.428763E-02 -1.417068E-04 -3.407514E-02 -1.241486E-04 -3.064802E-02 -1.103630E-04 -2.019877E-02 -7.059498E-05 -3.794436E-02 -1.883194E-04 -3.266721E-02 -1.280477E-04 -2.490808E-02 -7.281690E-05 -3.064961E-02 -1.125362E-04 -1.514239E-02 -2.910925E-05 -1.569321E-02 -3.950962E-05 -1.817240E-02 -4.154077E-05 -1.593815E-02 -3.459272E-05 -2.573968E-02 -8.029098E-05 -2.193871E-02 -6.210741E-05 -1.234720E-02 -1.843394E-05 -1.130766E-02 -2.245547E-05 -1.418762E-02 -3.357410E-05 -1.391485E-02 -2.559415E-05 -1.331696E-02 -2.115069E-05 -1.903725E-02 -4.411480E-05 -2.293870E-02 -6.557987E-05 -2.241944E-02 -7.768129E-05 -8.399478E-03 -1.343754E-05 -1.217880E-02 -2.018185E-05 -1.416256E-02 -2.227003E-05 -1.520064E-02 -2.978679E-05 -1.664846E-02 -4.183492E-05 -1.339491E-02 -2.674827E-05 -9.628607E-03 -1.279454E-05 -1.158026E-02 -1.554728E-05 -1.367791E-02 -2.379966E-05 -1.376699E-02 -2.264472E-05 -1.833088E-02 -4.495911E-05 -2.473484E-02 -1.122059E-04 -1.980130E-02 -4.468138E-05 -2.937836E-02 -1.114018E-04 -2.021222E-02 -4.559590E-05 -2.115889E-02 -5.272398E-05 -2.751444E-02 -8.716393E-05 -3.118255E-02 -1.201980E-04 -3.295258E-02 -1.221249E-04 -3.264934E-02 -1.357065E-04 -2.388443E-02 -6.703731E-05 -2.649789E-02 -7.940354E-05 -4.696656E-02 -2.514244E-04 -4.553686E-02 -2.438972E-04 -3.908818E-02 -1.840355E-04 -4.402566E-02 -2.377775E-04 -3.875910E-02 -1.778735E-04 -3.543152E-02 -1.527725E-04 -6.193982E-02 -4.578553E-04 -4.402817E-02 -2.274373E-04 -3.677275E-02 -1.884320E-04 -5.902021E-02 -3.951715E-04 -4.943375E-02 -2.711632E-04 -3.724773E-02 -1.641879E-04 -4.993443E-02 -2.771281E-04 -7.563062E-02 -6.734531E-04 -4.553601E-02 -2.283737E-04 -5.336189E-02 -3.085766E-04 -6.930581E-02 -5.723133E-04 -4.674295E-02 -2.785390E-04 -8.412725E-02 -7.467027E-04 -6.681883E-02 -4.824696E-04 -8.430398E-02 -7.823907E-04 -9.943266E-02 -1.106796E-03 -8.916803E-02 -8.767378E-04 -7.239961E-02 -6.787255E-04 -8.722424E-02 -9.332353E-04 -1.031401E-01 -1.218166E-03 -7.299280E-02 -5.585065E-04 -8.196460E-02 -7.464830E-04 -7.514349E-02 -6.162898E-04 -7.409781E-02 -6.092201E-04 -1.155025E-01 -1.496467E-03 -1.069759E-01 -1.259983E-03 -1.226295E-01 -1.569654E-03 -1.503421E-01 -2.355624E-03 -1.080703E-01 -1.309087E-03 -1.129782E-01 -1.371142E-03 -8.048452E-02 -7.348043E-04 -1.058381E-01 -1.164709E-03 -6.615819E-02 -4.794240E-04 -7.980754E-02 -6.987820E-04 -1.120426E-01 -1.285452E-03 -1.016962E-01 -1.116490E-03 -1.045603E-01 -1.203503E-03 -9.692551E-02 -1.029307E-03 -1.510121E-01 -2.326069E-03 -1.459994E-01 -2.277384E-03 -8.473854E-02 -7.832629E-04 -1.294853E-01 -1.741522E-03 -6.032354E-02 -3.886121E-04 -6.987142E-02 -5.446194E-04 -7.739481E-02 -6.779391E-04 -6.202592E-02 -4.288928E-04 -1.105924E-01 -1.283621E-03 -9.239492E-02 -9.223732E-04 -6.604268E-02 -4.595692E-04 -7.012590E-02 -5.276378E-04 -9.125615E-02 -8.968665E-04 -8.440076E-02 -7.298457E-04 -6.290364E-02 -4.350725E-04 -9.542023E-02 -1.023159E-03 -3.785503E-02 -1.773114E-04 -5.510138E-02 -3.186315E-04 -4.425845E-02 -2.296502E-04 -5.216949E-02 -3.102279E-04 -5.711604E-02 -3.708531E-04 -6.348926E-02 -4.437737E-04 -3.531423E-02 -1.381941E-04 -4.676905E-02 -2.710798E-04 -5.132004E-02 -2.836163E-04 -4.379959E-02 -2.484735E-04 -5.314318E-02 -3.059228E-04 -6.677411E-02 -5.104497E-04 -2.953361E-02 -1.221048E-04 -3.348688E-02 -1.218024E-04 -3.189405E-02 -1.283561E-04 -3.066128E-02 -1.074943E-04 -2.627008E-02 -7.434735E-05 -4.099188E-02 -1.844425E-04 -2.657946E-02 -8.006763E-05 -2.677024E-02 -9.837536E-05 -2.297001E-02 -6.348807E-05 -2.847736E-02 -1.016726E-04 -3.650898E-02 -1.905274E-04 -3.678596E-02 -1.737202E-04 -9.741068E-03 -1.427221E-05 -2.112559E-02 -7.299641E-05 -1.626433E-02 -3.325133E-05 -1.556047E-02 -3.623423E-05 -2.005845E-02 -4.817075E-05 -2.235018E-02 -6.309213E-05 -1.555635E-02 -3.399168E-05 -8.473936E-03 -1.206918E-05 -2.003025E-02 -5.771667E-05 -1.619274E-02 -3.694213E-05 -2.398087E-02 -8.309002E-05 -2.048279E-02 -5.775057E-05 -1.959187E-02 -4.755352E-05 -1.817346E-02 -4.751135E-05 -1.533477E-02 -4.769982E-05 -1.889382E-02 -4.706002E-05 -1.855621E-02 -4.644130E-05 -3.121451E-02 -1.173056E-04 -1.135235E-02 -2.022523E-05 -1.457214E-02 -3.250403E-05 -1.330384E-02 -2.287686E-05 -1.426049E-02 -2.827899E-05 -2.255732E-02 -6.597520E-05 -1.409157E-02 -2.947510E-05 -2.387117E-02 -7.502115E-05 -3.498075E-02 -1.588586E-04 -2.661630E-02 -9.051962E-05 -3.141346E-02 -1.130104E-04 -2.363639E-02 -7.247261E-05 -2.949581E-02 -1.015620E-04 -3.405344E-02 -1.368730E-04 -3.067699E-02 -1.186942E-04 -2.860325E-02 -1.027432E-04 -3.136948E-02 -1.261067E-04 -2.884168E-02 -9.121556E-05 -3.172681E-02 -1.271781E-04 -6.082138E-02 -3.967354E-04 -4.665628E-02 -2.447254E-04 -3.873489E-02 -1.666752E-04 -5.112906E-02 -2.817112E-04 -3.867668E-02 -1.713578E-04 -4.211970E-02 -1.934977E-04 -6.886477E-02 -4.937257E-04 -7.019363E-02 -5.620739E-04 -5.569741E-02 -3.372249E-04 -5.856502E-02 -3.766765E-04 -5.390171E-02 -3.381837E-04 -4.680414E-02 -2.500022E-04 -1.026456E-01 -1.147075E-03 -8.535063E-02 -7.808065E-04 -8.630449E-02 -8.031445E-04 -1.052149E-01 -1.184292E-03 -7.701701E-02 -6.253512E-04 -7.834187E-02 -6.672354E-04 -1.359360E-01 -1.907855E-03 -1.460384E-01 -2.190423E-03 -1.080390E-01 -1.234268E-03 -1.317673E-01 -1.856930E-03 -9.690172E-02 -1.006627E-03 -9.258404E-02 -9.457422E-04 -1.832246E-01 -3.427961E-03 -2.054091E-01 -4.398902E-03 -1.593682E-01 -2.662133E-03 -1.880778E-01 -3.629787E-03 -2.013148E-01 -4.265877E-03 -1.990549E-01 -4.200017E-03 -5.469090E-01 -3.082757E-02 -5.552625E-01 -3.233826E-02 -2.571401E-01 -6.723483E-03 -8.548854E-01 -7.413280E-02 -5.209393E-01 -2.787584E-02 -5.093657E-01 -2.715480E-02 -1.566145E-01 -2.600405E-03 -1.993120E-01 -4.010479E-03 -1.707332E-01 -2.996975E-03 -1.840203E-01 -3.525950E-03 -5.686602E-01 -3.269532E-02 -5.046470E-01 -2.580015E-02 -1.740098E-01 -3.137069E-03 -1.748447E-01 -3.287313E-03 -5.281969E-01 -2.835860E-02 -5.218758E-01 -2.764449E-02 -2.811590E-01 -8.077168E-03 -7.835313E-01 -6.174409E-02 -8.916676E-02 -8.704144E-04 -1.147415E-01 -1.428848E-03 -1.059630E-01 -1.142821E-03 -9.640793E-02 -9.919169E-04 -1.380046E-01 -2.013093E-03 -1.453872E-01 -2.230703E-03 -8.067716E-02 -7.607075E-04 -7.414787E-02 -5.831873E-04 -1.108173E-01 -1.334816E-03 -9.716310E-02 -1.050788E-03 -1.058275E-01 -1.176253E-03 -1.234077E-01 -1.611857E-03 -4.645374E-02 -2.489769E-04 -5.612855E-02 -3.674944E-04 -5.305509E-02 -3.127379E-04 -4.929601E-02 -2.809620E-04 -6.549144E-02 -4.537754E-04 -6.303494E-02 -4.236715E-04 -3.880272E-02 -1.704460E-04 -3.861758E-02 -1.663017E-04 -5.862395E-02 -3.858310E-04 -4.737923E-02 -2.823280E-04 -5.280787E-02 -3.043443E-04 -5.249474E-02 -3.019614E-04 -2.485904E-02 -6.701075E-05 -2.926990E-02 -9.417758E-05 -3.125676E-02 -1.037311E-04 -3.289406E-02 -1.368340E-04 -4.071134E-02 -1.830700E-04 -4.109741E-02 -2.038834E-04 -2.347652E-02 -7.157581E-05 -2.072441E-02 -5.807283E-05 -4.102695E-02 -2.107954E-04 -2.166639E-02 -5.788402E-05 -3.219359E-02 -1.250457E-04 -2.832465E-02 -9.610853E-05 -1.624643E-02 -3.730962E-05 -1.725120E-02 -4.481115E-05 -1.578099E-02 -3.024585E-05 -1.571746E-02 -3.035996E-05 -1.731202E-02 -3.502473E-05 -1.643420E-02 -3.632173E-05 -1.040551E-02 -1.294862E-05 -1.127727E-02 -2.039819E-05 -1.438022E-02 -2.857038E-05 -1.260556E-02 -2.928756E-05 -2.034502E-02 -6.038560E-05 -1.640843E-02 -3.872409E-05 -2.122181E-02 -6.703870E-05 -1.545958E-02 -2.933443E-05 -1.550763E-02 -3.859489E-05 -1.928201E-02 -4.243101E-05 -2.196809E-02 -5.810938E-05 -2.193973E-02 -5.702613E-05 -1.517387E-02 -3.300117E-05 -1.732347E-02 -3.857976E-05 -1.415891E-02 -2.906573E-05 -1.407775E-02 -3.402531E-05 -2.277203E-02 -7.764043E-05 -1.580648E-02 -4.707367E-05 -2.763176E-02 -9.424628E-05 -2.372205E-02 -6.537717E-05 -2.585656E-02 -7.555138E-05 -3.438842E-02 -1.498651E-04 -1.953849E-02 -4.797528E-05 -2.039273E-02 -6.513710E-05 -3.691903E-02 -1.454538E-04 -3.217932E-02 -1.398798E-04 -2.774657E-02 -8.279249E-05 -2.820457E-02 -9.228219E-05 -3.106567E-02 -1.239322E-04 -1.804981E-02 -4.099893E-05 -5.969428E-02 -3.940876E-04 -5.835174E-02 -4.018253E-04 -5.448605E-02 -3.344901E-04 -6.458561E-02 -4.749467E-04 -4.505232E-02 -2.290467E-04 -4.529186E-02 -2.210661E-04 -6.923883E-02 -5.074459E-04 -6.905166E-02 -5.269603E-04 -4.247615E-02 -2.080915E-04 -5.430061E-02 -3.320737E-04 -6.603377E-02 -5.144612E-04 -5.251003E-02 -3.190205E-04 -1.030147E-01 -1.109176E-03 -8.155464E-02 -7.067482E-04 -8.922744E-02 -8.197146E-04 -1.284288E-01 -1.811686E-03 -9.277212E-02 -8.820708E-04 -7.960421E-02 -7.018415E-04 -1.101447E-01 -1.238620E-03 -1.594606E-01 -2.631417E-03 -7.676797E-02 -6.249548E-04 -9.678537E-02 -1.039683E-03 -1.315012E-01 -1.823501E-03 -9.822710E-02 -1.049106E-03 -2.200833E-01 -4.944909E-03 -1.814148E-01 -3.455606E-03 -2.808713E-01 -7.998623E-03 -8.607047E-01 -7.471518E-02 -1.510873E-01 -2.350444E-03 -1.952158E-01 -3.987281E-03 -2.563955E-01 -6.736419E-03 -8.288790E-01 -6.935905E-02 -1.663306E-01 -2.909230E-03 -2.069533E-01 -4.392557E-03 -8.171538E-01 -6.926168E-02 -2.771724E-01 -7.947364E-03 -1.718421E-01 -3.078316E-03 -1.912710E-01 -3.901809E-03 -4.978656E-01 -2.591511E-02 -4.943901E-01 -2.504533E-02 -2.519316E-01 -6.571958E-03 -7.930433E-01 -6.483055E-02 -1.486665E-01 -2.270454E-03 -2.161805E-01 -4.796812E-03 -1.737906E-01 -3.149960E-03 -1.909929E-01 -3.837468E-03 -5.280144E-01 -2.824797E-02 -5.994269E-01 -3.679537E-02 -8.367283E-02 -8.246835E-04 -9.345285E-02 -9.180702E-04 -1.084220E-01 -1.234841E-03 -1.132694E-01 -1.417334E-03 -1.213506E-01 -1.536611E-03 -1.485290E-01 -2.261244E-03 -7.557519E-02 -6.112603E-04 -7.935833E-02 -6.583374E-04 -1.009825E-01 -1.083491E-03 -7.954123E-02 -7.044944E-04 -1.118116E-01 -1.371403E-03 -1.197452E-01 -1.570554E-03 -5.190598E-02 -3.551665E-04 -5.730111E-02 -3.980792E-04 -6.248836E-02 -4.466985E-04 -6.019178E-02 -4.124940E-04 -7.202094E-02 -5.415764E-04 -7.189177E-02 -5.472909E-04 -3.981535E-02 -1.797809E-04 -4.820928E-02 -2.773872E-04 -5.050408E-02 -2.801362E-04 -5.149907E-02 -3.058260E-04 -6.167709E-02 -3.980579E-04 -6.251960E-02 -4.234132E-04 -2.843012E-02 -8.808063E-05 -2.337612E-02 -6.606638E-05 -2.936391E-02 -9.914901E-05 -3.131118E-02 -1.224255E-04 -3.590121E-02 -1.554613E-04 -3.734616E-02 -1.611929E-04 -2.718818E-02 -8.275683E-05 -2.355063E-02 -6.269602E-05 -3.417456E-02 -1.470468E-04 -2.761636E-02 -8.857401E-05 -2.817665E-02 -9.358473E-05 -4.330547E-02 -2.125793E-04 -1.281131E-02 -2.508003E-05 -1.558497E-02 -4.131225E-05 -1.604825E-02 -3.789735E-05 -1.198312E-02 -2.201855E-05 -1.841476E-02 -4.406610E-05 -2.191664E-02 -5.706023E-05 -1.037877E-02 -1.403046E-05 -1.142906E-02 -1.784198E-05 -2.165180E-02 -7.328897E-05 -1.781165E-02 -3.964227E-05 -1.706685E-02 -3.626318E-05 -2.611118E-02 -8.937284E-05 -1.889982E-02 -5.096931E-05 -1.354993E-02 -3.469204E-05 -1.092599E-02 -1.697195E-05 -1.380052E-02 -2.909184E-05 -2.326409E-02 -7.737047E-05 -2.386034E-02 -7.722570E-05 -1.642655E-02 -4.387424E-05 -1.696224E-02 -3.657599E-05 -1.094347E-02 -1.803801E-05 -1.156552E-02 -2.421906E-05 -1.583036E-02 -3.257752E-05 -1.517584E-02 -3.200691E-05 -3.827074E-02 -1.889669E-04 -2.449951E-02 -7.459613E-05 -2.623209E-02 -8.154118E-05 -2.849776E-02 -9.089323E-05 -2.334185E-02 -6.201992E-05 -2.654520E-02 -9.694536E-05 -3.237617E-02 -1.167467E-04 -3.675105E-02 -1.763620E-04 -2.004612E-02 -5.066812E-05 -2.903446E-02 -9.486419E-05 -3.334691E-02 -1.228445E-04 -2.623258E-02 -7.799037E-05 -4.888525E-02 -2.729676E-04 -3.600959E-02 -1.553932E-04 -5.438364E-02 -3.353294E-04 -5.232566E-02 -2.992982E-04 -3.034775E-02 -1.324830E-04 -4.164626E-02 -2.036943E-04 -5.059600E-02 -2.935825E-04 -5.879411E-02 -3.888487E-04 -3.938426E-02 -2.093554E-04 -4.838794E-02 -2.715001E-04 -4.972503E-02 -2.740094E-04 -4.955213E-02 -2.667621E-04 -6.113745E-02 -4.048275E-04 -5.341164E-02 -3.153602E-04 -5.975662E-02 -3.838000E-04 -8.595500E-02 -8.321615E-04 -6.107919E-02 -3.898803E-04 -5.530668E-02 -3.235594E-04 -7.580790E-02 -6.272237E-04 -9.941256E-02 -1.054222E-03 -6.091493E-02 -3.907622E-04 -6.317933E-02 -4.235462E-04 -1.014991E-01 -1.038642E-03 -7.701856E-02 -6.147885E-04 -1.112163E-01 -1.265790E-03 -7.536078E-02 -5.769678E-04 -1.302318E-01 -1.742411E-03 -1.635988E-01 -2.867432E-03 -7.255186E-02 -6.284552E-04 -1.087261E-01 -1.292949E-03 -1.071717E-01 -1.182413E-03 -1.275727E-01 -1.701949E-03 -7.308862E-02 -5.588046E-04 -8.677475E-02 -7.923200E-04 -1.598968E-01 -2.752916E-03 -1.090514E-01 -1.267867E-03 -9.373573E-02 -9.468462E-04 -8.656897E-02 -7.993780E-04 -1.556811E-01 -2.570483E-03 -1.563481E-01 -2.547541E-03 -1.019280E-01 -1.066946E-03 -1.407263E-01 -2.139026E-03 -9.439261E-02 -9.727226E-04 -1.162727E-01 -1.469225E-03 -8.572873E-02 -7.472360E-04 -8.412598E-02 -7.378763E-04 -1.184615E-01 -1.447843E-03 -1.129877E-01 -1.387240E-03 -7.089346E-02 -5.210102E-04 -7.106181E-02 -5.601420E-04 -9.767580E-02 -1.010123E-03 -8.639404E-02 -7.865066E-04 -8.288207E-02 -7.425178E-04 -8.992435E-02 -9.501100E-04 -6.866676E-02 -5.516503E-04 -6.325590E-02 -4.342044E-04 -7.431495E-02 -6.348268E-04 -7.599335E-02 -5.991771E-04 -7.274975E-02 -5.571106E-04 -6.766739E-02 -5.249260E-04 -3.181945E-02 -1.159273E-04 -4.099202E-02 -1.863511E-04 -4.739506E-02 -2.375175E-04 -4.566762E-02 -2.462349E-04 -4.309564E-02 -2.169367E-04 -4.968602E-02 -2.836430E-04 -2.554238E-02 -7.130377E-05 -3.399568E-02 -1.313338E-04 -4.489588E-02 -2.608490E-04 -3.609823E-02 -1.664739E-04 -3.688252E-02 -1.524824E-04 -4.371937E-02 -2.194516E-04 -2.432742E-02 -6.816206E-05 -2.481126E-02 -7.715594E-05 -3.225220E-02 -1.297648E-04 -2.820482E-02 -8.756926E-05 -2.911932E-02 -9.466605E-05 -3.374238E-02 -1.328376E-04 -2.602288E-02 -8.674133E-05 -2.044276E-02 -4.796182E-05 -2.621162E-02 -8.521865E-05 -3.451732E-02 -1.272449E-04 -2.497288E-02 -7.862985E-05 -3.797623E-02 -1.934870E-04 -1.693158E-02 -3.957575E-05 -2.516921E-02 -7.540607E-05 -1.916047E-02 -5.115510E-05 -1.903519E-02 -5.491559E-05 -1.655257E-02 -2.970206E-05 -1.806193E-02 -4.421369E-05 -1.074232E-02 -1.704622E-05 -9.240900E-03 -1.255060E-05 -1.183407E-02 -1.748671E-05 -9.219696E-03 -1.609190E-05 -1.034386E-02 -1.462148E-05 -1.114705E-02 -1.850428E-05 -1.297960E-02 -2.423078E-05 -1.184491E-02 -2.140225E-05 -1.658431E-02 -4.388936E-05 -1.318219E-02 -2.389643E-05 -1.560221E-02 -3.262330E-05 -1.536994E-02 -2.967325E-05 -1.474070E-02 -2.850636E-05 -1.423540E-02 -2.724881E-05 -1.128414E-02 -1.691587E-05 -7.509669E-03 -1.138736E-05 -1.063708E-02 -1.760414E-05 -1.145186E-02 -2.083540E-05 -1.762181E-02 -4.474974E-05 -2.084088E-02 -6.507170E-05 -2.057308E-02 -5.516523E-05 -2.241191E-02 -7.120840E-05 -1.269523E-02 -2.005337E-05 -1.660064E-02 -3.697642E-05 -3.182773E-02 -1.204858E-04 -3.242190E-02 -1.182654E-04 -2.434893E-02 -7.105045E-05 -2.652135E-02 -7.481704E-05 -1.907560E-02 -5.087922E-05 -2.190903E-02 -6.429867E-05 -3.105119E-02 -1.183209E-04 -2.464967E-02 -7.797261E-05 -2.817912E-02 -9.460889E-05 -4.586402E-02 -2.494422E-04 -3.145613E-02 -1.306566E-04 -3.581523E-02 -1.371038E-04 -3.824846E-02 -1.899412E-04 -4.263531E-02 -1.873636E-04 -3.042311E-02 -1.167731E-04 -2.732643E-02 -7.846176E-05 -4.050189E-02 -1.908935E-04 -3.434384E-02 -1.361814E-04 -4.495849E-02 -2.646832E-04 -4.092138E-02 -2.017353E-04 -5.344413E-02 -3.250472E-04 -4.697795E-02 -2.453442E-04 -3.679979E-02 -1.575515E-04 -3.908452E-02 -1.742990E-04 -4.284114E-02 -2.154331E-04 -4.380058E-02 -2.263026E-04 -3.985455E-02 -1.829559E-04 -3.394862E-02 -1.228745E-04 -4.744764E-02 -2.814058E-04 -3.949446E-02 -1.946576E-04 -6.109758E-02 -4.065478E-04 -5.344244E-02 -3.173404E-04 -5.996641E-02 -3.831573E-04 -7.955351E-02 -6.865984E-04 -4.384271E-02 -1.999570E-04 -6.435559E-02 -4.377030E-04 -4.969051E-02 -2.811028E-04 -5.599815E-02 -3.868544E-04 -4.163040E-02 -2.191546E-04 -4.845338E-02 -2.687605E-04 -7.016148E-02 -5.682673E-04 -6.371981E-02 -4.441518E-04 -6.553775E-02 -4.702345E-04 -5.818627E-02 -3.716053E-04 -7.301288E-02 -5.661570E-04 -6.855403E-02 -4.925246E-04 -4.751877E-02 -3.119215E-04 -6.178405E-02 -4.942348E-04 -5.778084E-02 -3.682642E-04 -6.794905E-02 -4.813721E-04 -4.580484E-02 -2.283874E-04 -4.833285E-02 -2.496503E-04 -6.283852E-02 -4.289179E-04 -5.868559E-02 -3.829967E-04 -4.942181E-02 -2.770674E-04 -4.633288E-02 -2.530825E-04 -6.521627E-02 -4.531563E-04 -6.926577E-02 -4.930307E-04 -4.947134E-02 -2.743687E-04 -5.599354E-02 -3.625867E-04 -4.586533E-02 -2.169603E-04 -6.057563E-02 -3.949284E-04 -3.269565E-02 -1.324708E-04 -3.688715E-02 -1.561195E-04 -4.607386E-02 -2.561957E-04 -4.286297E-02 -2.186313E-04 -3.835517E-02 -1.807457E-04 -3.101308E-02 -1.258603E-04 -4.256564E-02 -2.156265E-04 -3.995257E-02 -1.962160E-04 -3.999004E-02 -1.700193E-04 -4.593940E-02 -2.325862E-04 -2.746637E-02 -1.056011E-04 -2.945679E-02 -1.039840E-04 -4.237269E-02 -1.976737E-04 -3.339233E-02 -1.438661E-04 -3.371702E-02 -1.468814E-04 -3.238843E-02 -1.164792E-04 -2.064297E-02 -5.618891E-05 -2.155723E-02 -6.462578E-05 -2.273621E-02 -5.819206E-05 -1.964446E-02 -5.147180E-05 -2.401285E-02 -7.795637E-05 -2.729940E-02 -9.076729E-05 -2.213041E-02 -6.949614E-05 -1.338392E-02 -2.465408E-05 -2.431872E-02 -7.724266E-05 -2.524967E-02 -1.026115E-04 -2.737266E-02 -9.841098E-05 -2.112771E-02 -5.889604E-05 -1.496282E-02 -4.007026E-05 -1.889629E-02 -5.468925E-05 -1.783224E-02 -4.566541E-05 -8.331789E-03 -9.954892E-06 -1.796677E-02 -3.918970E-05 -1.970964E-02 -4.450042E-05 -1.137654E-02 -1.965594E-05 -8.407972E-03 -1.166241E-05 -1.447552E-02 -2.605420E-05 -8.376429E-03 -1.246530E-05 -1.335436E-02 -3.392789E-05 -1.200101E-02 -2.280708E-05 -1.602954E-02 -3.739523E-05 -9.669299E-03 -1.679999E-05 -1.566345E-02 -3.502619E-05 -1.588366E-02 -3.186835E-05 -1.901368E-02 -4.343637E-05 -2.267083E-02 -7.178904E-05 -9.004042E-03 -1.176762E-05 -1.804933E-02 -4.338938E-05 -1.071906E-02 -1.634166E-05 -9.615294E-03 -1.267674E-05 -1.558814E-02 -2.851576E-05 -1.376105E-02 -2.761523E-05 -1.902761E-02 -6.150446E-05 -1.854745E-02 -5.066723E-05 -1.702864E-02 -4.027369E-05 -2.099003E-02 -6.424422E-05 -2.011904E-02 -5.529868E-05 -1.661724E-02 -3.837653E-05 -1.373297E-02 -2.945958E-05 -1.569666E-02 -3.146459E-05 -1.202400E-02 -1.784017E-05 -1.532156E-02 -4.083467E-05 -1.855533E-02 -4.148169E-05 -2.388887E-02 -7.104659E-05 -3.029475E-02 -1.112701E-04 -3.479830E-02 -1.457081E-04 -2.993443E-02 -1.034283E-04 -2.618538E-02 -8.150737E-05 -1.973658E-02 -5.388325E-05 -1.908984E-02 -4.925317E-05 -2.558471E-02 -7.645976E-05 -3.057900E-02 -1.526871E-04 -2.038898E-02 -6.028856E-05 -1.936824E-02 -5.652676E-05 -1.860724E-02 -4.433157E-05 -1.859342E-02 -6.046452E-05 -3.104650E-02 -1.107731E-04 -2.791826E-02 -8.517252E-05 -2.550906E-02 -7.911190E-05 -3.228374E-02 -1.235126E-04 -2.983461E-02 -1.169772E-04 -2.340715E-02 -7.962272E-05 -2.472431E-02 -7.854176E-05 -3.116101E-02 -1.113261E-04 -2.726866E-02 -8.448946E-05 -2.872167E-02 -1.004750E-04 -3.032428E-02 -1.229901E-04 -3.053428E-02 -1.122910E-04 -3.083822E-02 -1.483669E-04 -2.064536E-02 -5.782771E-05 -3.181149E-02 -1.187295E-04 -4.583432E-02 -2.558159E-04 -2.666121E-02 -9.350519E-05 -3.358219E-02 -1.192091E-04 -2.369325E-02 -8.059778E-05 -3.102351E-02 -1.289691E-04 -2.820355E-02 -1.068875E-04 -3.480350E-02 -1.443944E-04 -3.560608E-02 -1.469841E-04 -4.990478E-02 -3.032798E-04 -3.784020E-02 -1.765328E-04 -3.316256E-02 -1.290263E-04 -4.033997E-02 -1.799350E-04 -3.929687E-02 -1.626134E-04 -3.235240E-02 -1.382862E-04 -3.388379E-02 -1.425521E-04 -3.879634E-02 -1.814360E-04 -3.990331E-02 -1.937058E-04 -2.486877E-02 -7.060573E-05 -2.847067E-02 -8.714105E-05 -4.490738E-02 -2.182380E-04 -3.277939E-02 -1.222614E-04 -2.300113E-02 -6.725020E-05 -3.241132E-02 -1.183039E-04 -3.117719E-02 -1.083016E-04 -2.675135E-02 -8.558799E-05 -3.944468E-02 -1.742389E-04 -4.399132E-02 -2.295328E-04 -2.087405E-02 -4.684764E-05 -1.956671E-02 -4.488034E-05 -3.135372E-02 -1.064232E-04 -1.852589E-02 -4.046644E-05 -2.367532E-02 -7.100616E-05 -2.728169E-02 -9.976058E-05 -2.896959E-02 -9.844663E-05 -2.865198E-02 -1.092590E-04 -3.163730E-02 -1.082131E-04 -3.268958E-02 -1.309514E-04 -2.046897E-02 -4.893795E-05 -2.472680E-02 -7.874493E-05 -2.926292E-02 -1.081766E-04 -3.002458E-02 -1.013573E-04 -1.360951E-02 -2.635847E-05 -2.311727E-02 -6.168251E-05 -3.020182E-02 -1.206713E-04 -2.697417E-02 -8.378246E-05 -1.334960E-02 -2.306197E-05 -1.590087E-02 -4.689125E-05 -2.011479E-02 -6.965285E-05 -1.633667E-02 -3.972970E-05 -2.002848E-02 -4.881276E-05 -2.201774E-02 -5.990084E-05 -1.590141E-02 -4.489842E-05 -1.287558E-02 -2.913250E-05 -1.902193E-02 -5.067435E-05 -1.740647E-02 -4.536926E-05 -2.127020E-02 -6.939263E-05 -1.655808E-02 -3.850014E-05 -1.186084E-02 -2.566137E-05 -1.183085E-02 -2.088219E-05 -1.691039E-02 -4.357920E-05 -6.413071E-03 -5.791752E-06 -1.069744E-02 -1.593929E-05 -9.843254E-03 -1.483187E-05 -6.822909E-03 -6.785866E-06 -4.540728E-03 -3.073065E-06 -1.381635E-02 -3.287951E-05 -9.881421E-03 -1.765396E-05 -5.794819E-03 -6.579960E-06 -1.064665E-02 -1.825529E-05 -9.708618E-03 -2.420624E-05 -3.867809E-03 -3.463878E-06 -1.036922E-02 -1.880088E-05 -1.209814E-02 -2.247120E-05 -6.289728E-03 -9.053460E-06 -1.121820E-02 -2.376217E-05 -6.107387E-03 -9.842112E-06 -6.679042E-03 -7.917785E-06 -4.610676E-03 -3.822313E-06 -8.094200E-03 -1.556770E-05 -1.289830E-02 -2.263732E-05 -1.240554E-02 -2.182216E-05 -1.709643E-02 -4.443205E-05 -1.240518E-02 -1.925823E-05 -1.427630E-02 -3.038114E-05 -1.316587E-02 -2.528125E-05 -1.051316E-02 -1.998843E-05 -1.171370E-02 -1.977243E-05 -1.035585E-02 -1.603691E-05 -7.844703E-03 -1.578836E-05 -1.090930E-02 -1.495715E-05 -8.811473E-03 -9.095511E-06 -1.164754E-02 -2.113385E-05 -1.218588E-02 -2.577136E-05 -9.989257E-03 -1.768442E-05 -1.346846E-02 -3.232091E-05 -1.442996E-02 -2.734716E-05 -9.319830E-03 -1.357660E-05 -8.976517E-03 -1.130996E-05 -1.111410E-02 -1.774598E-05 -7.097237E-03 -9.606334E-06 -7.668810E-03 -9.333553E-06 -7.744641E-03 -1.065587E-05 -7.076161E-03 -1.063617E-05 -9.841337E-03 -1.147612E-05 -9.084818E-03 -1.406836E-05 -2.026892E-02 -5.186751E-05 -2.132295E-02 -5.072988E-05 -2.033996E-02 -4.765789E-05 -2.446954E-02 -7.232017E-05 -1.029334E-02 -1.244212E-05 -1.235238E-02 -2.298965E-05 -1.681496E-02 -3.708751E-05 -2.101172E-02 -5.242154E-05 -1.722265E-02 -4.432357E-05 -1.352905E-02 -2.104447E-05 -2.195095E-02 -5.623046E-05 -2.089078E-02 -5.825067E-05 -2.311666E-02 -7.574537E-05 -1.562461E-02 -4.452838E-05 -3.307359E-02 -1.363268E-04 -2.572970E-02 -8.059205E-05 -2.345159E-02 -6.488182E-05 -2.554049E-02 -8.362508E-05 -2.006928E-02 -5.496633E-05 -2.259482E-02 -7.740649E-05 -1.761243E-02 -4.766457E-05 -1.125462E-02 -1.662484E-05 -1.806884E-02 -4.002727E-05 -1.875035E-02 -3.963856E-05 -2.507230E-02 -7.918744E-05 -1.948387E-02 -4.675980E-05 -2.102608E-02 -5.253998E-05 -2.725383E-02 -8.911499E-05 -1.527724E-02 -2.634360E-05 -2.318415E-02 -6.853391E-05 -1.953638E-02 -4.357651E-05 -2.681123E-02 -9.518790E-05 -1.619023E-02 -3.280100E-05 -2.160140E-02 -5.673289E-05 -2.207700E-02 -6.204249E-05 -1.851529E-02 -4.084658E-05 -2.064003E-02 -5.523222E-05 -1.936444E-02 -5.709920E-05 -2.135402E-02 -6.226947E-05 -1.913624E-02 -5.176876E-05 -1.979246E-02 -4.760307E-05 -2.697598E-02 -1.023961E-04 -1.163038E-02 -1.840715E-05 -1.922611E-02 -4.751185E-05 -1.370913E-02 -2.686855E-05 -1.541222E-02 -3.013601E-05 -2.247424E-02 -5.214783E-05 -1.763181E-02 -3.495488E-05 -9.375723E-03 -1.593258E-05 -1.436433E-02 -3.431677E-05 -1.300122E-02 -2.534320E-05 -1.428291E-02 -3.109112E-05 -1.320134E-02 -2.937454E-05 -1.496684E-02 -2.934259E-05 -1.257843E-02 -3.153056E-05 -1.573087E-02 -3.089207E-05 -1.074581E-02 -1.656493E-05 -8.983048E-03 -1.169670E-05 -1.588106E-02 -3.644142E-05 -1.135062E-02 -1.548990E-05 -1.342453E-02 -4.068693E-05 -7.143669E-03 -1.309838E-05 -1.911833E-02 -5.539347E-05 -1.578655E-02 -3.784881E-05 -1.010592E-02 -2.000143E-05 -2.107750E-02 -5.152671E-05 -1.352516E-02 -2.742309E-05 -1.298482E-02 -2.958789E-05 -8.061759E-03 -1.027922E-05 -1.145755E-02 -1.975699E-05 -7.630008E-03 -9.001956E-06 -1.110176E-02 -1.756811E-05 -7.622179E-03 -1.192472E-05 -1.157431E-02 -3.153358E-05 -1.329349E-02 -2.758940E-05 -7.723627E-03 -1.213940E-05 -6.430868E-03 -5.865444E-06 -6.666510E-03 -6.225385E-06 -3.314737E-03 -2.247442E-06 -5.145333E-03 -3.979329E-06 -6.496136E-03 -9.042875E-06 -3.832205E-03 -4.079904E-06 -1.091525E-02 -2.123166E-05 -1.100375E-02 -2.753282E-05 -6.452706E-03 -9.971091E-06 -5.931053E-03 -8.601691E-06 -9.574695E-03 -1.435980E-05 -6.378307E-03 -9.114546E-06 -1.035293E-02 -2.113676E-05 -5.515936E-03 -4.201853E-06 -5.579006E-03 -4.124072E-06 -9.045101E-03 -2.746668E-05 -7.146555E-03 -1.150230E-05 -6.281008E-03 -5.825971E-06 -5.295060E-03 -6.107698E-06 -4.285052E-03 -3.897963E-06 -1.261316E-02 -3.054847E-05 -1.248209E-02 -3.143433E-05 -1.216297E-02 -1.827405E-05 -1.257515E-02 -2.571939E-05 -8.877488E-03 -1.136667E-05 -1.224337E-02 -2.556328E-05 -1.610471E-02 -3.359843E-05 -1.376758E-02 -2.898825E-05 -1.066381E-02 -1.891264E-05 -1.370280E-02 -3.200949E-05 -1.218455E-02 -2.842079E-05 -1.205249E-02 -2.816694E-05 -1.292481E-02 -2.311574E-05 -1.500071E-02 -5.524516E-05 -1.629889E-02 -3.414163E-05 -1.715035E-02 -4.138447E-05 -7.880253E-03 -8.429037E-06 -1.066213E-02 -2.491824E-05 -1.071709E-02 -1.648251E-05 -1.278476E-02 -2.151462E-05 -2.029414E-02 -5.704631E-05 -1.835961E-02 -3.756414E-05 -1.086076E-02 -1.970149E-05 -1.953320E-02 -6.822321E-05 -1.727515E-02 -4.272841E-05 -2.113792E-02 -5.363596E-05 -1.255464E-02 -2.618423E-05 -1.849104E-02 -3.910212E-05 -1.080830E-02 -1.627578E-05 -1.065175E-02 -1.245618E-05 -1.729833E-02 -4.769086E-05 -1.229654E-02 -2.017586E-05 -2.000316E-02 -5.539455E-05 -1.490083E-02 -2.662412E-05 -1.257552E-02 -2.450638E-05 -2.265863E-02 -5.948942E-05 -1.592510E-02 -3.967897E-05 -1.671764E-02 -3.518609E-05 -2.134651E-02 -6.970473E-05 -1.145479E-02 -2.341492E-05 -1.110701E-02 -1.473716E-05 -1.365215E-02 -2.532562E-05 -1.569347E-02 -3.022408E-05 -1.740868E-02 -4.263025E-05 -2.046954E-02 -5.236013E-05 -2.088018E-02 -4.754884E-05 -2.143648E-02 -5.630377E-05 -2.321051E-02 -7.417245E-05 -1.393331E-02 -2.372413E-05 -1.272764E-02 -2.686784E-05 -1.996763E-02 -6.034803E-05 -1.543709E-02 -3.597724E-05 -1.374704E-02 -2.238864E-05 -1.485050E-02 -3.200278E-05 -1.630595E-02 -3.026169E-05 -1.885152E-02 -5.848418E-05 -1.903463E-02 -4.081588E-05 -2.873487E-02 -1.002249E-04 -2.191651E-02 -7.843435E-05 -2.375413E-02 -7.774516E-05 -1.237198E-02 -2.127422E-05 -1.942702E-02 -4.732051E-05 -2.103354E-02 -6.483331E-05 -1.285994E-02 -2.290156E-05 -1.249524E-02 -2.455002E-05 -1.236581E-02 -2.393541E-05 -1.379145E-02 -2.529751E-05 -1.562825E-02 -4.587015E-05 -2.641863E-02 -9.120767E-05 -2.733140E-02 -1.071137E-04 -1.919060E-02 -5.181037E-05 -2.129817E-02 -5.796235E-05 -1.260439E-02 -1.817703E-05 -1.848829E-02 -4.798194E-05 -1.216642E-02 -2.707330E-05 -1.410959E-02 -2.525781E-05 -9.453654E-03 -1.551579E-05 -9.766342E-03 -1.477317E-05 -1.836540E-02 -5.242882E-05 -1.804249E-02 -4.602986E-05 -1.853466E-02 -4.366676E-05 -1.525913E-02 -3.246161E-05 -1.673660E-02 -3.399297E-05 -1.837090E-02 -4.346348E-05 -1.396823E-02 -3.367275E-05 -9.246854E-03 -1.212445E-05 -1.410130E-02 -3.106294E-05 -1.307073E-02 -2.149583E-05 -9.704033E-03 -1.660514E-05 -1.044410E-02 -1.303462E-05 -1.166356E-02 -2.043704E-05 -1.318169E-02 -2.754937E-05 -1.812814E-02 -4.404582E-05 -1.552606E-02 -3.211975E-05 -1.585862E-02 -3.414359E-05 -1.446034E-02 -2.967784E-05 -7.649239E-03 -1.381600E-05 -6.893844E-03 -7.460924E-06 -1.354488E-02 -2.777125E-05 -1.007415E-02 -1.536552E-05 -8.075475E-03 -1.134760E-05 -1.130634E-02 -1.578798E-05 -6.590888E-03 -9.273749E-06 -7.448105E-03 -8.982164E-06 -5.823642E-03 -5.865562E-06 -9.093169E-03 -9.535064E-06 -4.848224E-03 -3.763431E-06 -9.282171E-03 -1.433250E-05 -1.127548E-02 -2.124250E-05 -9.878278E-03 -2.325491E-05 -1.039485E-02 -2.066791E-05 -1.155396E-02 -2.135511E-05 -1.450572E-02 -3.456258E-05 -1.246739E-02 -2.299204E-05 -1.290333E-02 -2.343647E-05 -1.121371E-02 -1.743282E-05 -5.468489E-03 -5.451707E-06 -1.180352E-02 -2.521651E-05 -1.416461E-02 -3.062871E-05 -1.076659E-02 -2.220002E-05 -2.448020E-02 -1.177322E-04 -1.517807E-02 -2.911032E-05 -1.031229E-02 -1.643057E-05 -1.200918E-02 -2.501705E-05 -1.613952E-02 -3.362754E-05 -1.378304E-02 -2.726242E-05 -1.857986E-02 -5.056092E-05 -1.576878E-02 -3.540682E-05 -1.910927E-02 -4.403442E-05 -1.829771E-02 -4.616084E-05 -1.164328E-02 -2.237054E-05 -1.680617E-02 -5.383688E-05 -2.087579E-02 -7.699421E-05 -2.381231E-02 -8.579600E-05 -1.885763E-02 -4.911360E-05 -2.649401E-02 -7.833957E-05 -1.350269E-02 -2.364349E-05 -1.757223E-02 -4.850663E-05 -2.411131E-02 -7.298399E-05 -2.774250E-02 -9.193073E-05 -2.282427E-02 -5.981367E-05 -2.721816E-02 -9.146779E-05 -2.832490E-02 -1.002337E-04 -2.942107E-02 -1.083982E-04 -2.629534E-02 -7.761525E-05 -2.690294E-02 -9.295211E-05 -2.031569E-02 -5.738480E-05 -2.590631E-02 -8.501230E-05 -3.031225E-02 -1.054523E-04 -2.423433E-02 -6.759709E-05 -3.382137E-02 -1.369015E-04 -2.496378E-02 -7.510237E-05 -2.672791E-02 -9.783698E-05 -2.507828E-02 -7.618011E-05 -1.769181E-02 -3.552782E-05 -2.096115E-02 -5.131019E-05 -3.063827E-02 -1.178430E-04 -3.120124E-02 -1.130478E-04 -2.031644E-02 -7.092047E-05 -2.760866E-02 -8.532139E-05 -2.786328E-02 -8.451452E-05 -2.700290E-02 -9.059845E-05 -3.660807E-02 -1.468682E-04 -3.105005E-02 -1.103431E-04 -3.734607E-02 -1.551359E-04 -3.447674E-02 -1.455364E-04 -2.264216E-02 -5.558419E-05 -2.211961E-02 -5.818600E-05 -3.130555E-02 -1.297184E-04 -3.457400E-02 -1.544678E-04 -2.687511E-02 -9.290746E-05 -3.047806E-02 -1.034500E-04 -3.560765E-02 -1.552412E-04 -3.095201E-02 -1.306105E-04 -3.230749E-02 -1.340962E-04 -2.928305E-02 -1.168468E-04 -4.265647E-02 -2.076643E-04 -3.298446E-02 -1.507110E-04 -2.986290E-02 -1.139639E-04 -3.435605E-02 -1.436737E-04 -3.052232E-02 -1.060392E-04 -3.396111E-02 -1.269448E-04 -3.167642E-02 -1.425279E-04 -2.821678E-02 -9.529119E-05 -4.113237E-02 -1.985887E-04 -3.525258E-02 -1.581696E-04 -3.297968E-02 -1.288343E-04 -2.799503E-02 -1.215560E-04 -4.104348E-02 -2.019357E-04 -3.825115E-02 -1.695340E-04 -2.776267E-02 -8.959306E-05 -3.443399E-02 -1.543941E-04 -2.347389E-02 -6.957205E-05 -2.325934E-02 -7.017456E-05 -2.441186E-02 -8.613195E-05 -1.983392E-02 -5.161177E-05 -2.710281E-02 -8.919133E-05 -2.744420E-02 -8.533228E-05 -2.193886E-02 -6.175359E-05 -1.830518E-02 -5.544200E-05 -2.341425E-02 -7.903797E-05 -2.450511E-02 -8.157422E-05 -2.452935E-02 -7.643569E-05 -3.274389E-02 -1.348587E-04 -9.730875E-03 -1.447356E-05 -1.623715E-02 -3.017421E-05 -1.516567E-02 -3.422832E-05 -1.065832E-02 -1.723340E-05 -1.938164E-02 -4.958486E-05 -1.489311E-02 -2.833615E-05 -1.617585E-02 -3.768666E-05 -1.471840E-02 -3.108380E-05 -1.804409E-02 -4.531066E-05 -2.150485E-02 -6.386092E-05 -1.088027E-02 -2.181372E-05 -1.017312E-02 -2.124217E-05 -1.432834E-02 -2.609903E-05 -1.583698E-02 -3.341095E-05 -9.743784E-03 -1.280783E-05 -7.846675E-03 -7.302042E-06 -9.804358E-03 -1.279367E-05 -1.297038E-02 -2.247676E-05 -1.204029E-02 -2.186972E-05 -8.944589E-03 -1.610694E-05 -1.437621E-02 -2.903841E-05 -1.162625E-02 -1.600570E-05 -5.705942E-03 -6.026539E-06 -9.949459E-03 -1.121060E-05 -1.355078E-02 -3.639982E-05 -1.253062E-02 -2.184327E-05 -1.128093E-02 -2.186156E-05 -1.351097E-02 -3.128150E-05 -1.302602E-02 -2.954976E-05 -1.581710E-02 -2.880115E-05 -8.299998E-03 -1.148143E-05 -1.419270E-02 -3.823010E-05 -8.195314E-03 -1.206128E-05 -1.089466E-02 -1.659227E-05 -1.434916E-02 -2.871463E-05 -1.677690E-02 -5.753038E-05 -2.577031E-02 -8.627098E-05 -2.327382E-02 -8.071762E-05 -2.476661E-02 -7.787162E-05 -2.107385E-02 -5.721321E-05 -1.990587E-02 -5.438566E-05 -1.715009E-02 -3.760846E-05 -2.840951E-02 -9.042931E-05 -2.308683E-02 -6.425853E-05 -2.068224E-02 -5.497174E-05 -2.518837E-02 -7.159468E-05 -1.844753E-02 -5.256599E-05 -2.195768E-02 -5.682427E-05 -4.576470E-02 -2.500482E-04 -3.107728E-02 -1.163017E-04 -3.132822E-02 -1.179930E-04 -3.352262E-02 -1.295829E-04 -2.943942E-02 -9.539846E-05 -3.672963E-02 -1.518887E-04 -3.639000E-02 -1.578688E-04 -3.932185E-02 -1.696900E-04 -3.126478E-02 -1.158570E-04 -3.784245E-02 -1.552955E-04 -3.346893E-02 -1.329769E-04 -3.045629E-02 -1.110202E-04 -4.501003E-02 -2.328334E-04 -5.330472E-02 -3.651809E-04 -4.289711E-02 -2.197266E-04 -3.259040E-02 -1.193252E-04 -4.449895E-02 -2.225829E-04 -4.124007E-02 -1.878125E-04 -4.737006E-02 -2.432331E-04 -4.433616E-02 -2.209854E-04 -5.530206E-02 -3.206482E-04 -6.256960E-02 -4.281638E-04 -5.285253E-02 -3.112894E-04 -4.439981E-02 -2.141823E-04 -5.016707E-02 -2.707515E-04 -6.882017E-02 -4.979869E-04 -4.465718E-02 -2.306648E-04 -3.888039E-02 -1.657354E-04 -5.385073E-02 -3.147914E-04 -4.640933E-02 -2.345368E-04 -7.051618E-02 -6.268651E-04 -4.375120E-02 -2.369745E-04 -6.068695E-02 -4.021878E-04 -6.068536E-02 -3.839552E-04 -3.602602E-02 -1.670809E-04 -4.995017E-02 -2.763744E-04 -4.392495E-02 -2.564028E-04 -5.093161E-02 -3.505664E-04 -4.432335E-02 -2.193425E-04 -4.855910E-02 -2.650606E-04 -5.176805E-02 -3.189213E-04 -4.890781E-02 -2.548831E-04 -6.554400E-02 -5.204569E-04 -6.588153E-02 -4.746561E-04 -6.675922E-02 -5.163608E-04 -7.271786E-02 -5.798664E-04 -4.837626E-02 -2.803260E-04 -5.224310E-02 -3.238220E-04 -4.580609E-02 -2.616101E-04 -5.119315E-02 -2.907515E-04 -4.372268E-02 -2.158620E-04 -4.124410E-02 -2.181852E-04 -4.882021E-02 -2.584581E-04 -5.914423E-02 -3.994010E-04 -4.163873E-02 -1.967708E-04 -3.798723E-02 -1.675576E-04 -6.178751E-02 -4.293350E-04 -5.052828E-02 -2.945947E-04 -3.889945E-02 -1.723031E-04 -4.778867E-02 -2.787658E-04 -2.556412E-02 -7.318557E-05 -3.450636E-02 -1.552235E-04 -2.997657E-02 -1.090031E-04 -2.250800E-02 -7.954622E-05 -3.846568E-02 -1.836107E-04 -3.701622E-02 -1.828496E-04 -3.972718E-02 -1.850244E-04 -2.403274E-02 -8.024833E-05 -3.407142E-02 -1.362787E-04 -3.563489E-02 -1.418007E-04 -2.285168E-02 -6.135475E-05 -3.573895E-02 -1.429096E-04 -1.944631E-02 -4.643790E-05 -2.223553E-02 -6.647009E-05 -2.178313E-02 -5.702943E-05 -1.885794E-02 -4.219512E-05 -2.626415E-02 -7.357902E-05 -2.590102E-02 -7.754226E-05 -1.790062E-02 -4.192871E-05 -1.566226E-02 -3.285418E-05 -2.611458E-02 -8.677724E-05 -2.644054E-02 -7.951101E-05 -1.688067E-02 -3.275169E-05 -2.281883E-02 -7.048130E-05 -1.383028E-02 -2.557495E-05 -1.750718E-02 -3.486088E-05 -1.458508E-02 -2.726606E-05 -1.229121E-02 -2.297397E-05 -1.858922E-02 -4.177321E-05 -1.787571E-02 -4.327284E-05 -6.566818E-03 -9.185537E-06 -1.448563E-02 -2.622240E-05 -1.621707E-02 -3.406357E-05 -1.085556E-02 -1.536032E-05 -1.333272E-02 -2.646991E-05 -1.453289E-02 -2.893412E-05 -1.518348E-02 -4.580967E-05 -1.404090E-02 -2.660292E-05 -1.349000E-02 -3.442831E-05 -1.633780E-02 -4.356999E-05 -1.600602E-02 -3.943089E-05 -1.590141E-02 -3.641474E-05 -1.086814E-02 -1.688254E-05 -1.698352E-02 -4.714162E-05 -1.318224E-02 -2.638496E-05 -1.119975E-02 -1.718066E-05 -1.575614E-02 -3.441783E-05 -1.418915E-02 -2.794370E-05 -1.971441E-02 -5.386951E-05 -2.749934E-02 -9.685175E-05 -2.450793E-02 -8.361790E-05 -3.096368E-02 -1.517345E-04 -1.966521E-02 -5.193037E-05 -1.488285E-02 -2.767080E-05 -2.628867E-02 -8.549789E-05 -3.222975E-02 -1.197226E-04 -3.578145E-02 -1.651405E-04 -2.717256E-02 -9.455312E-05 -2.846483E-02 -1.022437E-04 -2.373681E-02 -7.165349E-05 -4.893242E-02 -2.730109E-04 -3.477536E-02 -1.404582E-04 -4.928227E-02 -2.924560E-04 -4.544606E-02 -2.179936E-04 -3.160536E-02 -1.247483E-04 -4.089837E-02 -1.816429E-04 -6.363669E-02 -4.595645E-04 -5.951940E-02 -3.700880E-04 -3.810687E-02 -1.688583E-04 -5.679150E-02 -3.460302E-04 -5.729570E-02 -3.719866E-04 -5.082871E-02 -2.938785E-04 -7.469781E-02 -6.673208E-04 -6.652451E-02 -4.877821E-04 -6.401348E-02 -4.744885E-04 -5.622051E-02 -3.395523E-04 -6.073961E-02 -3.833605E-04 -6.232929E-02 -4.148823E-04 -7.969677E-02 -6.803601E-04 -8.037601E-02 -7.230061E-04 -7.865258E-02 -6.933305E-04 -9.845581E-02 -1.080566E-03 -6.878501E-02 -5.274776E-04 -7.015010E-02 -5.143444E-04 -1.156668E-01 -1.410105E-03 -1.192152E-01 -1.498896E-03 -7.577104E-02 -6.219937E-04 -8.184079E-02 -7.335058E-04 -1.139638E-01 -1.401155E-03 -8.075065E-02 -6.916698E-04 -1.437821E-01 -2.126013E-03 -8.850980E-02 -8.276893E-04 -1.464407E-01 -2.249915E-03 -1.357666E-01 -1.907685E-03 -8.903971E-02 -8.785322E-04 -1.035557E-01 -1.229512E-03 -9.987363E-02 -1.066492E-03 -1.408315E-01 -2.126682E-03 -7.775073E-02 -6.482580E-04 -9.217616E-02 -9.279523E-04 -1.346724E-01 -1.896751E-03 -8.733262E-02 -8.612501E-04 -9.983468E-02 -1.028984E-03 -9.096031E-02 -9.623493E-04 -1.646266E-01 -2.794929E-03 -1.304703E-01 -1.750382E-03 -8.811642E-02 -8.019013E-04 -1.067542E-01 -1.239326E-03 -4.255870E-02 -2.117948E-04 -6.657200E-02 -4.734337E-04 -6.716890E-02 -5.510834E-04 -4.697673E-02 -2.522950E-04 -9.074058E-02 -9.095881E-04 -7.248365E-02 -5.562525E-04 -5.894139E-02 -3.919992E-04 -4.322527E-02 -2.007041E-04 -8.846643E-02 -8.126375E-04 -8.094023E-02 -7.286166E-04 -5.884744E-02 -3.735579E-04 -6.484926E-02 -4.588123E-04 -4.890138E-02 -2.886686E-04 -5.972248E-02 -4.039813E-04 -4.560235E-02 -2.196157E-04 -4.488985E-02 -2.203187E-04 -6.734006E-02 -5.380869E-04 -5.510066E-02 -3.247707E-04 -4.520538E-02 -2.496589E-04 -4.217127E-02 -2.278109E-04 -5.551062E-02 -3.500669E-04 -4.092402E-02 -1.766989E-04 -4.298954E-02 -2.252953E-04 -4.437029E-02 -2.305532E-04 -3.704655E-02 -2.009774E-04 -3.598121E-02 -1.524807E-04 -3.045852E-02 -1.197202E-04 -2.601757E-02 -8.242731E-05 -3.357946E-02 -1.363746E-04 -3.932253E-02 -1.907001E-04 -2.390507E-02 -6.834171E-05 -2.346501E-02 -7.056602E-05 -3.597630E-02 -1.581562E-04 -3.090953E-02 -1.047491E-04 -2.070578E-02 -5.748122E-05 -3.347346E-02 -1.259074E-04 -1.513003E-02 -3.897988E-05 -1.367854E-02 -2.775960E-05 -1.645455E-02 -3.040738E-05 -1.324152E-02 -2.645298E-05 -1.588183E-02 -3.062863E-05 -1.734153E-02 -4.637284E-05 -1.634443E-02 -5.133843E-05 -1.119328E-02 -1.753195E-05 -1.323203E-02 -3.022286E-05 -1.135797E-02 -1.802055E-05 -1.090441E-02 -1.701011E-05 -1.759035E-02 -4.033287E-05 -2.242877E-02 -6.151790E-05 -1.946253E-02 -5.767287E-05 -1.450600E-02 -3.658456E-05 -2.053561E-02 -7.347202E-05 -2.172703E-02 -6.439721E-05 -1.970458E-02 -4.600512E-05 -1.750068E-02 -4.248050E-05 -2.615060E-02 -8.063501E-05 -1.471555E-02 -3.115498E-05 -1.390462E-02 -3.029928E-05 -2.277300E-02 -6.669696E-05 -1.701430E-02 -3.723197E-05 -3.366433E-02 -1.230840E-04 -2.650631E-02 -9.335504E-05 -2.977659E-02 -1.071113E-04 -3.153286E-02 -1.137530E-04 -2.593564E-02 -7.559506E-05 -2.027223E-02 -6.394080E-05 -3.666363E-02 -1.619679E-04 -4.008059E-02 -1.775008E-04 -2.019835E-02 -5.995987E-05 -3.269994E-02 -1.328649E-04 -4.298198E-02 -2.261101E-04 -3.478624E-02 -1.430238E-04 -5.024091E-02 -3.090307E-04 -5.399488E-02 -3.370022E-04 -4.802423E-02 -2.449581E-04 -4.962540E-02 -2.661791E-04 -4.714200E-02 -2.609694E-04 -5.413235E-02 -3.323523E-04 -7.865185E-02 -6.448405E-04 -6.245568E-02 -4.162905E-04 -4.774685E-02 -2.886302E-04 -6.062406E-02 -4.267779E-04 -6.732377E-02 -5.175823E-04 -5.345323E-02 -3.251415E-04 -1.081562E-01 -1.271390E-03 -1.021968E-01 -1.089652E-03 -9.531149E-02 -1.008862E-03 -1.099951E-01 -1.318432E-03 -8.728617E-02 -7.926236E-04 -6.759692E-02 -4.951495E-04 -1.622908E-01 -2.679920E-03 -1.297048E-01 -1.704599E-03 -1.105751E-01 -1.365137E-03 -1.338049E-01 -1.961877E-03 -1.135987E-01 -1.340952E-03 -9.047766E-02 -8.460145E-04 -5.706400E-01 -3.358746E-02 -5.767616E-01 -3.370236E-02 -1.875657E-01 -3.661666E-03 -1.871296E-01 -3.729992E-03 -2.210728E-01 -4.924615E-03 -1.665143E-01 -2.811366E-03 -8.372362E-01 -7.140730E-02 -2.631175E-01 -6.985957E-03 -5.750239E-01 -3.400521E-02 -4.828940E-01 -2.485485E-02 -1.859770E-01 -3.523984E-03 -1.672669E-01 -2.904958E-03 -2.375331E-01 -5.780405E-03 -7.840038E-01 -6.231709E-02 -2.132004E-01 -4.651951E-03 -1.326778E-01 -1.947761E-03 -8.211106E-01 -6.821312E-02 -2.477970E-01 -6.338987E-03 -2.133989E-01 -4.688136E-03 -1.689238E-01 -2.975501E-03 -7.799516E-01 -6.145987E-02 -2.571652E-01 -6.720137E-03 -1.616850E-01 -2.755887E-03 -1.967353E-01 -3.935902E-03 -8.257842E-02 -7.608737E-04 -1.275267E-01 -1.697194E-03 -9.926640E-02 -1.068598E-03 -8.218999E-02 -7.531509E-04 -1.532040E-01 -2.576896E-03 -1.294690E-01 -1.713096E-03 -7.154094E-02 -5.360062E-04 -7.586730E-02 -7.229435E-04 -1.259416E-01 -1.689821E-03 -9.056538E-02 -9.471446E-04 -8.469906E-02 -7.604134E-04 -1.005850E-01 -1.057108E-03 -4.463277E-02 -2.328840E-04 -5.523748E-02 -3.372196E-04 -5.232544E-02 -2.999576E-04 -4.417355E-02 -2.638798E-04 -5.782793E-02 -3.530500E-04 -5.944743E-02 -4.220391E-04 -3.657199E-02 -1.400109E-04 -3.808082E-02 -1.658520E-04 -6.410370E-02 -4.501663E-04 -4.310905E-02 -2.075429E-04 -4.755667E-02 -2.801406E-04 -4.959581E-02 -2.962253E-04 -2.252513E-02 -6.049713E-05 -2.991518E-02 -9.529790E-05 -2.664048E-02 -8.582855E-05 -2.475820E-02 -1.017459E-04 -3.488574E-02 -1.383218E-04 -2.890941E-02 -9.208222E-05 -2.098791E-02 -5.427914E-05 -1.943877E-02 -4.588171E-05 -3.481570E-02 -1.557210E-04 -2.398110E-02 -7.150967E-05 -2.011861E-02 -5.252956E-05 -2.839521E-02 -9.935802E-05 -1.502686E-02 -3.105045E-05 -1.609461E-02 -3.412102E-05 -2.098494E-02 -4.964297E-05 -1.885164E-02 -4.396914E-05 -1.991326E-02 -6.264911E-05 -1.856961E-02 -5.669686E-05 -1.440755E-02 -2.776990E-05 -1.370375E-02 -2.537463E-05 -1.757189E-02 -4.061709E-05 -1.902797E-02 -4.188635E-05 -1.135542E-02 -1.840125E-05 -1.821693E-02 -5.706852E-05 -1.966443E-02 -6.182591E-05 -1.098595E-02 -1.890446E-05 -1.880596E-02 -4.985208E-05 -2.224492E-02 -6.056638E-05 -1.938365E-02 -5.095134E-05 -2.004141E-02 -4.931528E-05 -1.584800E-02 -3.117640E-05 -8.716172E-03 -1.000356E-05 -1.306598E-02 -2.437620E-05 -1.303208E-02 -2.038909E-05 -1.496313E-02 -2.545249E-05 -9.598787E-03 -1.772891E-05 -3.131961E-02 -1.312684E-04 -2.918177E-02 -1.061777E-04 -3.088357E-02 -1.333663E-04 -3.322098E-02 -1.522259E-04 -1.912743E-02 -4.246859E-05 -2.493296E-02 -7.677374E-05 -3.831962E-02 -1.658539E-04 -3.935899E-02 -1.741789E-04 -2.392516E-02 -6.888699E-05 -3.042757E-02 -1.017878E-04 -3.071050E-02 -1.067951E-04 -3.345411E-02 -1.329032E-04 -5.446194E-02 -3.217845E-04 -4.790665E-02 -2.591914E-04 -4.370165E-02 -2.303527E-04 -4.427824E-02 -2.343428E-04 -4.182303E-02 -1.991080E-04 -4.098398E-02 -1.789986E-04 -6.431595E-02 -4.788578E-04 -6.788255E-02 -4.777967E-04 -4.412014E-02 -2.235134E-04 -5.533021E-02 -3.194019E-04 -5.464587E-02 -3.422291E-04 -5.703799E-02 -3.461325E-04 -1.119858E-01 -1.361306E-03 -9.089503E-02 -9.100663E-04 -9.511706E-02 -1.044926E-03 -1.074655E-01 -1.234547E-03 -7.705184E-02 -6.240812E-04 -6.897178E-02 -4.976520E-04 -1.412576E-01 -2.058554E-03 -1.216520E-01 -1.524026E-03 -8.791442E-02 -8.344056E-04 -1.037643E-01 -1.183835E-03 -8.708765E-02 -7.895562E-04 -8.580552E-02 -7.861920E-04 -7.918410E-01 -6.387826E-02 -2.447419E-01 -6.181230E-03 -4.587452E-01 -2.121897E-02 -5.203331E-01 -2.787312E-02 -1.850399E-01 -3.508673E-03 -1.651942E-01 -2.817305E-03 -5.838903E-01 -3.492429E-02 -5.155122E-01 -2.720158E-02 -1.904412E-01 -3.741626E-03 -1.981500E-01 -4.136229E-03 -2.022324E-01 -4.246984E-03 -1.652234E-01 -2.873591E-03 -5.115500E-01 -2.708582E-02 -5.791183E-01 -3.432760E-02 -8.107545E-01 -6.659574E-02 -2.634253E-01 -6.999531E-03 -4.915877E-01 -2.533318E-02 -5.693871E-01 -3.325807E-02 -1.791869E-01 -3.312861E-03 -1.858183E-01 -3.543802E-03 -2.123169E-01 -4.557530E-03 -1.672616E-01 -2.835857E-03 -1.711699E-01 -3.060667E-03 -1.758571E-01 -3.190864E-03 -9.235761E-02 -9.669475E-04 -1.140668E-01 -1.438348E-03 -1.377681E-01 -1.929906E-03 -1.011292E-01 -1.113302E-03 -1.364692E-01 -1.951502E-03 -1.414788E-01 -2.087246E-03 -7.454906E-02 -6.183963E-04 -7.314067E-02 -5.725364E-04 -1.053516E-01 -1.161166E-03 -8.265045E-02 -7.800060E-04 -9.317212E-02 -9.511500E-04 -9.087762E-02 -9.141004E-04 -5.226230E-02 -3.109563E-04 -5.578744E-02 -3.618499E-04 -6.973131E-02 -5.043558E-04 -6.157852E-02 -4.070680E-04 -6.811553E-02 -5.258915E-04 -7.611557E-02 -6.131989E-04 -5.088876E-02 -3.182936E-04 -5.436219E-02 -3.078199E-04 -5.597453E-02 -3.396588E-04 -4.107053E-02 -1.911728E-04 -4.290228E-02 -2.123049E-04 -5.788555E-02 -4.117326E-04 -2.353071E-02 -6.995800E-05 -3.463664E-02 -1.422097E-04 -2.918840E-02 -1.004566E-04 -2.736799E-02 -9.048433E-05 -3.463497E-02 -1.286836E-04 -4.726762E-02 -2.541389E-04 -2.411585E-02 -6.917613E-05 -2.704813E-02 -8.764995E-05 -2.810800E-02 -8.757217E-05 -2.291436E-02 -6.377954E-05 -3.013851E-02 -1.161125E-04 -2.972621E-02 -9.625050E-05 -1.751438E-02 -6.055922E-05 -2.205862E-02 -7.232896E-05 -1.960773E-02 -4.550316E-05 -1.937614E-02 -4.905471E-05 -2.518721E-02 -8.112827E-05 -2.590049E-02 -7.419054E-05 -1.339646E-02 -2.029891E-05 -2.067244E-02 -4.823190E-05 -2.295710E-02 -6.620610E-05 -8.933646E-03 -1.197590E-05 -2.088372E-02 -5.448793E-05 -1.573345E-02 -2.834414E-05 -1.618549E-02 -3.394500E-05 -1.562728E-02 -4.232429E-05 -1.762718E-02 -4.646038E-05 -1.691115E-02 -4.088904E-05 -1.778865E-02 -4.585630E-05 -1.699861E-02 -3.633558E-05 -1.474531E-02 -2.687795E-05 -1.191135E-02 -1.966547E-05 -1.368911E-02 -2.475254E-05 -8.726049E-03 -1.080420E-05 -1.855900E-02 -4.086770E-05 -1.042736E-02 -1.532968E-05 -2.750891E-02 -9.887827E-05 -2.557586E-02 -8.191188E-05 -2.651219E-02 -9.860563E-05 -2.544872E-02 -7.883150E-05 -2.096053E-02 -5.337477E-05 -1.819029E-02 -3.850870E-05 -3.202501E-02 -1.153271E-04 -2.876516E-02 -9.848331E-05 -2.271111E-02 -7.379330E-05 -2.854025E-02 -9.337598E-05 -2.824372E-02 -1.030571E-04 -2.318994E-02 -6.966557E-05 -4.138096E-02 -1.938864E-04 -3.680662E-02 -1.462240E-04 -3.808984E-02 -1.773752E-04 -4.968859E-02 -2.697606E-04 -3.120957E-02 -1.068433E-04 -3.625725E-02 -1.561439E-04 -4.266936E-02 -2.044742E-04 -5.527178E-02 -3.492180E-04 -3.492336E-02 -1.434781E-04 -3.345516E-02 -1.260850E-04 -5.316011E-02 -3.146473E-04 -3.770174E-02 -1.639797E-04 -7.987130E-02 -6.938936E-04 -5.700087E-02 -3.483872E-04 -7.902435E-02 -7.070267E-04 -8.115977E-02 -7.037262E-04 -5.028735E-02 -2.816840E-04 -5.862112E-02 -3.890181E-04 -8.026709E-02 -6.991067E-04 -8.844060E-02 -8.768540E-04 -6.027542E-02 -3.820896E-04 -5.955846E-02 -4.114052E-04 -7.223606E-02 -5.860849E-04 -8.036129E-02 -7.080829E-04 -1.251201E-01 -1.753212E-03 -9.518009E-02 -1.007169E-03 -1.499658E-01 -2.357452E-03 -1.582289E-01 -2.673309E-03 -9.723433E-02 -1.085206E-03 -9.223640E-02 -9.320231E-04 -1.244253E-01 -1.604811E-03 -1.389205E-01 -2.073518E-03 -8.898557E-02 -8.481843E-04 -8.699525E-02 -8.194442E-04 -1.194952E-01 -1.512778E-03 -8.679982E-02 -8.002571E-04 -1.529795E-01 -2.441631E-03 -1.087018E-01 -1.206359E-03 -1.572820E-01 -2.488454E-03 -1.378974E-01 -1.949060E-03 -1.016220E-01 -1.073888E-03 -1.189492E-01 -1.535660E-03 -9.307965E-02 -9.698515E-04 -9.538400E-02 -9.813891E-04 -9.106730E-02 -8.805352E-04 -8.371498E-02 -7.560974E-04 -1.021881E-01 -1.077841E-03 -9.309692E-02 -9.810570E-04 -6.954893E-02 -5.308895E-04 -7.248184E-02 -6.039844E-04 -8.357871E-02 -7.377145E-04 -7.117434E-02 -5.362599E-04 -9.546800E-02 -9.918303E-04 -8.154604E-02 -6.899246E-04 -5.541527E-02 -3.261092E-04 -5.781147E-02 -3.640210E-04 -7.071250E-02 -5.530093E-04 -7.012881E-02 -5.436620E-04 -5.986681E-02 -4.315165E-04 -7.228996E-02 -5.573189E-04 -4.764962E-02 -2.567629E-04 -4.978411E-02 -3.039433E-04 -5.251712E-02 -3.236802E-04 -3.942522E-02 -1.927267E-04 -5.510943E-02 -3.217347E-04 -5.118639E-02 -3.171944E-04 -4.252043E-02 -1.916953E-04 -4.412672E-02 -2.246415E-04 -4.088117E-02 -1.787513E-04 -3.610456E-02 -1.564509E-04 -3.814757E-02 -1.686026E-04 -4.627344E-02 -2.494575E-04 -1.994893E-02 -5.126553E-05 -3.216228E-02 -1.182156E-04 -2.950065E-02 -1.138201E-04 -2.866289E-02 -1.160231E-04 -3.983095E-02 -1.721863E-04 -4.012198E-02 -1.784164E-04 -2.106311E-02 -4.994977E-05 -2.781446E-02 -1.039157E-04 -3.488260E-02 -1.405115E-04 -2.875112E-02 -9.762388E-05 -3.224104E-02 -1.323284E-04 -3.641337E-02 -1.501812E-04 -1.480062E-02 -3.027272E-05 -1.408753E-02 -3.690601E-05 -1.944937E-02 -4.432175E-05 -1.283324E-02 -2.250887E-05 -2.073256E-02 -5.466671E-05 -2.186071E-02 -5.661539E-05 -1.133978E-02 -1.956348E-05 -1.049553E-02 -1.718390E-05 -1.539596E-02 -3.369585E-05 -2.039324E-02 -5.820403E-05 -1.043006E-02 -1.903901E-05 -2.777446E-02 -1.204671E-04 -1.484365E-02 -2.996962E-05 -1.109804E-02 -1.818652E-05 -9.835588E-03 -1.388426E-05 -1.478128E-02 -3.969614E-05 -1.020395E-02 -1.717436E-05 -1.487209E-02 -3.915846E-05 -9.230116E-03 -1.588076E-05 -8.372399E-03 -1.186179E-05 -8.663998E-03 -1.212384E-05 -1.164683E-02 -2.389782E-05 -1.148782E-02 -1.884731E-05 -9.267384E-03 -2.342255E-05 -2.492427E-02 -7.177126E-05 -1.937892E-02 -5.238888E-05 -1.533925E-02 -3.007374E-05 -2.897108E-02 -9.563790E-05 -1.504253E-02 -4.162972E-05 -1.506486E-02 -3.027445E-05 -2.421349E-02 -6.937729E-05 -1.981713E-02 -4.308765E-05 -2.688788E-02 -8.996617E-05 -2.298292E-02 -6.356151E-05 -2.521588E-02 -9.500495E-05 -1.944459E-02 -4.357545E-05 -4.894435E-02 -2.638450E-04 -3.864018E-02 -1.798269E-04 -3.849780E-02 -1.779556E-04 -4.806157E-02 -2.545276E-04 -2.419299E-02 -8.084015E-05 -2.835677E-02 -9.629003E-05 -3.964564E-02 -1.838380E-04 -4.177908E-02 -1.949235E-04 -3.068221E-02 -1.216833E-04 -3.203560E-02 -1.147717E-04 -3.493031E-02 -1.439593E-04 -3.780820E-02 -1.626400E-04 -5.390584E-02 -3.457131E-04 -3.911344E-02 -1.787461E-04 -5.600310E-02 -3.942394E-04 -5.721857E-02 -3.841430E-04 -3.425794E-02 -1.301099E-04 -4.896944E-02 -2.649497E-04 -5.468018E-02 -3.296430E-04 -5.960549E-02 -4.028002E-04 -4.289904E-02 -2.047984E-04 -3.417711E-02 -1.286477E-04 -5.147540E-02 -3.225127E-04 -4.429517E-02 -2.370511E-04 -5.333104E-02 -3.409602E-04 -6.102677E-02 -4.290957E-04 -7.075039E-02 -5.312660E-04 -7.760160E-02 -6.260977E-04 -5.110208E-02 -2.931608E-04 -6.284669E-02 -4.546881E-04 -6.386212E-02 -5.062176E-04 -7.791663E-02 -6.553468E-04 -4.847427E-02 -2.698567E-04 -5.036036E-02 -2.562333E-04 -6.628275E-02 -4.863329E-04 -5.107250E-02 -3.360646E-04 -5.438547E-02 -3.250878E-04 -5.955142E-02 -3.888695E-04 -6.613363E-02 -4.562672E-04 -7.873757E-02 -6.608787E-04 -4.633363E-02 -2.332785E-04 -6.000714E-02 -4.102538E-04 -5.607310E-02 -3.721702E-04 -7.224050E-02 -5.754880E-04 -5.604428E-02 -3.636927E-04 -4.542882E-02 -2.350087E-04 -6.010895E-02 -3.888132E-04 -5.026253E-02 -3.056826E-04 -5.083017E-02 -2.951657E-04 -4.774445E-02 -2.553998E-04 -6.166209E-02 -4.248389E-04 -5.750738E-02 -3.545368E-04 -5.475371E-02 -3.742657E-04 -5.136434E-02 -3.013480E-04 -4.625465E-02 -2.735615E-04 -5.057347E-02 -3.133161E-04 -4.695282E-02 -2.640479E-04 -3.979050E-02 -1.911432E-04 -5.106567E-02 -2.846885E-04 -4.782744E-02 -3.086692E-04 -2.945927E-02 -1.037190E-04 -3.548884E-02 -1.667740E-04 -4.339365E-02 -2.324267E-04 -3.578638E-02 -1.439546E-04 -4.531719E-02 -2.379087E-04 -4.291461E-02 -2.163748E-04 -2.831504E-02 -9.351629E-05 -2.425588E-02 -6.929284E-05 -3.519439E-02 -1.401196E-04 -3.174238E-02 -1.187918E-04 -2.505587E-02 -7.333276E-05 -3.252855E-02 -1.518816E-04 -2.315654E-02 -6.200895E-05 -2.574270E-02 -7.613474E-05 -2.520902E-02 -7.303619E-05 -2.985551E-02 -9.745575E-05 -2.508447E-02 -9.702485E-05 -2.448965E-02 -6.790622E-05 -1.765762E-02 -3.709919E-05 -1.979233E-02 -4.686113E-05 -2.477181E-02 -7.217121E-05 -2.046923E-02 -5.529696E-05 -1.619249E-02 -3.536888E-05 -3.084138E-02 -1.038251E-04 -1.430547E-02 -2.813880E-05 -1.024198E-02 -1.564502E-05 -1.440933E-02 -2.677391E-05 -1.139030E-02 -1.562766E-05 -1.706815E-02 -3.602648E-05 -1.960477E-02 -5.223127E-05 -1.075038E-02 -1.946902E-05 -8.176023E-03 -9.795109E-06 -1.400712E-02 -2.798724E-05 -9.098651E-03 -2.320760E-05 -1.621999E-02 -5.890457E-05 -1.662025E-02 -5.381012E-05 -1.501846E-02 -3.187427E-05 -1.115569E-02 -2.112610E-05 -8.934007E-03 -1.127244E-05 -1.053736E-02 -2.738972E-05 -1.687632E-02 -3.758437E-05 -1.176928E-02 -1.998369E-05 -1.090722E-02 -2.070033E-05 -1.922176E-02 -4.611119E-05 -6.410110E-03 -7.146719E-06 -3.860269E-03 -5.922652E-06 -6.045740E-03 -5.074973E-06 -4.971635E-03 -3.431959E-06 -2.426203E-02 -7.370761E-05 -2.680359E-02 -8.998719E-05 -1.630553E-02 -3.567524E-05 -1.914533E-02 -4.240964E-05 -1.508665E-02 -2.912142E-05 -1.672855E-02 -3.656656E-05 -1.451039E-02 -2.817950E-05 -1.687413E-02 -4.142926E-05 -1.597006E-02 -4.478288E-05 -1.688899E-02 -3.586099E-05 -1.833640E-02 -5.132894E-05 -2.002488E-02 -5.326859E-05 -1.914416E-02 -5.599172E-05 -2.207570E-02 -7.740090E-05 -2.366938E-02 -6.568915E-05 -2.649512E-02 -1.020488E-04 -1.483135E-02 -2.984413E-05 -1.887848E-02 -4.268175E-05 -3.001817E-02 -1.047979E-04 -2.212608E-02 -6.788700E-05 -2.058642E-02 -5.920693E-05 -2.072658E-02 -5.071607E-05 -1.860802E-02 -4.555855E-05 -1.666833E-02 -3.918400E-05 -2.410251E-02 -7.518781E-05 -2.431099E-02 -9.040361E-05 -3.409049E-02 -1.428531E-04 -3.176194E-02 -1.054320E-04 -3.008617E-02 -1.140028E-04 -3.827724E-02 -1.656866E-04 -3.578801E-02 -1.469705E-04 -3.205988E-02 -1.211102E-04 -2.718611E-02 -8.166121E-05 -3.164768E-02 -1.161478E-04 -2.324305E-02 -6.697244E-05 -2.947200E-02 -1.259054E-04 -2.746439E-02 -9.282287E-05 -2.653377E-02 -8.108059E-05 -4.445537E-02 -2.152169E-04 -4.052651E-02 -1.733821E-04 -3.053999E-02 -1.118515E-04 -4.177700E-02 -2.106180E-04 -3.721658E-02 -1.614887E-04 -4.250554E-02 -2.125286E-04 -3.259794E-02 -1.259532E-04 -3.279076E-02 -1.281014E-04 -3.769459E-02 -1.592958E-04 -3.620173E-02 -1.496207E-04 -3.630649E-02 -1.531507E-04 -3.419905E-02 -1.389163E-04 -3.811683E-02 -1.632070E-04 -3.778477E-02 -1.788000E-04 -3.255090E-02 -1.292645E-04 -4.054674E-02 -2.009707E-04 -3.396471E-02 -1.380670E-04 -2.970522E-02 -1.194017E-04 -2.926855E-02 -1.209863E-04 -2.414836E-02 -7.131380E-05 -2.902285E-02 -9.925626E-05 -3.804797E-02 -1.754536E-04 -2.561987E-02 -7.861985E-05 -2.621638E-02 -8.635601E-05 -3.392178E-02 -1.612402E-04 -2.949056E-02 -1.075244E-04 -2.861194E-02 -9.347554E-05 -3.281854E-02 -1.750223E-04 -2.528376E-02 -8.170461E-05 -2.855965E-02 -1.276904E-04 -2.210588E-02 -6.285379E-05 -1.501664E-02 -3.174414E-05 -2.485082E-02 -8.044179E-05 -2.609565E-02 -9.700928E-05 -3.800572E-02 -1.865757E-04 -1.880640E-02 -4.090279E-05 -2.909814E-02 -1.043206E-04 -3.180763E-02 -1.216425E-04 -1.518998E-02 -2.699690E-05 -2.630226E-02 -9.511365E-05 -2.282938E-02 -6.428433E-05 -2.493692E-02 -7.780311E-05 -1.137087E-02 -2.156846E-05 -1.680608E-02 -3.976947E-05 -2.724734E-02 -8.526080E-05 -3.353531E-02 -1.249343E-04 -1.997488E-02 -5.686628E-05 -1.952335E-02 -5.168354E-05 -2.332315E-02 -6.296001E-05 -1.903421E-02 -4.970639E-05 -1.988764E-02 -4.758272E-05 -2.237483E-02 -6.308654E-05 -2.024263E-02 -6.708430E-05 -1.794493E-02 -3.980589E-05 -1.605168E-02 -3.661129E-05 -1.264028E-02 -2.003973E-05 -1.316289E-02 -3.041847E-05 -2.132558E-02 -7.506854E-05 -1.515922E-02 -4.400695E-05 -1.165029E-02 -3.144519E-05 -1.431392E-02 -3.510266E-05 -9.378262E-03 -1.745913E-05 -1.348722E-02 -2.279535E-05 -1.219541E-02 -2.124436E-05 -9.186874E-03 -1.308201E-05 -5.510134E-03 -6.127474E-06 -1.018457E-02 -2.037011E-05 -7.480002E-03 -8.821059E-06 -1.284192E-02 -2.896216E-05 -1.251268E-02 -2.241281E-05 -1.134027E-02 -1.937376E-05 -9.348782E-03 -1.387252E-05 -1.595911E-02 -3.477329E-05 -1.611731E-02 -4.121294E-05 -5.771625E-03 -5.262561E-06 -1.339971E-02 -2.328961E-05 -4.724286E-03 -7.486861E-06 -7.887185E-03 -1.309912E-05 -1.017668E-02 -1.329563E-05 -9.929419E-03 -2.048058E-05 -1.172543E-02 -2.164855E-05 -8.748399E-03 -1.455014E-05 -7.388493E-03 -1.213908E-05 -9.357160E-03 -1.459184E-05 -1.182596E-02 -2.754657E-05 -1.376694E-02 -2.808688E-05 -8.736677E-03 -1.261523E-05 -1.058599E-02 -2.132582E-05 -8.904592E-03 -1.412855E-05 -8.871956E-03 -1.042407E-05 -4.818722E-03 -5.533432E-06 -7.132170E-03 -1.066330E-05 -1.265366E-02 -2.062988E-05 -1.146186E-02 -1.978609E-05 -1.727631E-02 -6.317086E-05 -9.722001E-03 -1.628574E-05 -1.808415E-02 -4.814964E-05 -2.313210E-02 -7.257429E-05 -6.096746E-03 -8.507143E-06 -1.095433E-02 -2.574564E-05 -1.144512E-02 -2.130606E-05 -1.709946E-02 -3.435958E-05 -5.794154E-03 -4.298264E-06 -1.345102E-02 -2.470605E-05 -1.674615E-02 -3.806453E-05 -1.058112E-02 -1.675643E-05 -1.487609E-02 -2.876672E-05 -1.727197E-02 -4.888253E-05 -2.720121E-02 -8.232238E-05 -3.268443E-02 -1.194042E-04 -1.427634E-02 -2.639442E-05 -2.055060E-02 -5.261649E-05 -1.637582E-02 -3.886105E-05 -2.416272E-02 -6.712570E-05 -1.431266E-02 -2.383080E-05 -1.632066E-02 -3.444426E-05 -2.435113E-02 -8.254028E-05 -2.015885E-02 -5.481740E-05 -1.973867E-02 -5.116489E-05 -1.865655E-02 -4.752313E-05 -3.165189E-02 -1.474543E-04 -3.338700E-02 -1.226611E-04 -1.856968E-02 -4.098217E-05 -2.747306E-02 -8.290244E-05 -3.019952E-02 -1.096277E-04 -2.941793E-02 -9.471376E-05 -1.359209E-02 -2.775872E-05 -1.604302E-02 -3.176242E-05 -2.130560E-02 -6.015704E-05 -2.273639E-02 -7.032069E-05 -2.128699E-02 -6.074255E-05 -1.492456E-02 -3.510276E-05 -2.424866E-02 -6.867482E-05 -2.858266E-02 -9.553376E-05 -1.423686E-02 -2.731632E-05 -2.183114E-02 -5.075377E-05 -1.790750E-02 -4.419157E-05 -2.189439E-02 -5.678221E-05 -1.528824E-02 -2.994220E-05 -1.591232E-02 -3.345909E-05 -2.006375E-02 -5.328672E-05 -1.926568E-02 -5.794406E-05 -1.995889E-02 -5.771200E-05 -2.190352E-02 -6.226272E-05 -2.344085E-02 -7.170778E-05 -1.490160E-02 -3.189456E-05 -1.964283E-02 -4.674552E-05 -1.729274E-02 -5.276904E-05 -2.041435E-02 -6.736760E-05 -1.278262E-02 -2.244619E-05 -1.454136E-02 -3.039925E-05 -9.619956E-03 -1.773332E-05 -1.228153E-02 -2.003326E-05 -9.672849E-03 -1.662330E-05 -1.711969E-02 -5.651042E-05 -1.584751E-02 -3.641664E-05 -1.935632E-02 -5.597824E-05 -1.126109E-02 -1.753857E-05 -1.782849E-02 -4.695997E-05 -1.381158E-02 -2.666475E-05 -1.219375E-02 -1.818815E-05 -1.066559E-02 -2.272800E-05 -1.442020E-02 -2.898674E-05 -1.020932E-02 -1.446241E-05 -1.118415E-02 -1.992502E-05 -8.105784E-03 -1.344204E-05 -1.498438E-02 -4.583095E-05 -1.019191E-02 -1.878658E-05 -1.933752E-02 -5.597403E-05 -1.355162E-02 -2.693353E-05 -1.009187E-02 -1.416651E-05 -1.762231E-02 -4.342948E-05 -8.265997E-03 -1.115148E-05 -7.740105E-03 -9.350881E-06 -6.132761E-03 -5.990846E-06 -8.311803E-03 -1.337310E-05 -1.148410E-02 -2.801843E-05 -1.254654E-02 -2.859306E-05 -5.729723E-03 -7.417371E-06 -3.329556E-03 -2.852362E-06 -8.995510E-03 -1.519541E-05 -9.885451E-03 -1.504316E-05 -8.000781E-03 -1.318972E-05 -8.116139E-03 -1.599393E-05 -5.483106E-03 -5.909268E-06 -7.119776E-03 -7.398166E-06 -5.696562E-03 -8.267139E-06 -3.253311E-03 -3.490487E-06 -7.617341E-03 -1.591870E-05 -4.477136E-03 -4.507128E-06 -4.186692E-03 -4.522007E-06 -9.913744E-03 -1.537264E-05 -5.097688E-03 -5.151058E-06 -3.958711E-03 -4.681053E-06 -8.278901E-03 -1.024219E-05 -8.835906E-03 -1.016849E-05 -8.456874E-03 -1.177568E-05 -1.261330E-02 -3.084433E-05 -4.949744E-03 -4.615766E-06 -3.553617E-03 -2.732540E-06 -9.121684E-03 -1.577246E-05 -1.008197E-02 -2.084343E-05 -1.384668E-02 -3.110319E-05 -6.699315E-03 -6.544515E-06 -9.247650E-03 -1.217430E-05 -1.382529E-02 -2.309065E-05 -1.239699E-02 -2.979052E-05 -7.678409E-03 -9.823153E-06 -1.313584E-02 -2.664709E-05 -1.402449E-02 -3.295040E-05 -1.404510E-02 -2.328440E-05 -1.395545E-02 -3.064026E-05 -6.468889E-03 -1.142683E-05 -1.117536E-02 -2.247013E-05 -7.150789E-03 -7.587094E-06 -1.607791E-02 -4.401441E-05 -1.397191E-02 -2.767660E-05 -1.377649E-02 -3.853853E-05 -9.740469E-03 -1.610242E-05 -1.439220E-02 -3.310057E-05 -1.312482E-02 -2.812275E-05 -9.319391E-03 -1.598131E-05 -1.513017E-02 -3.596580E-05 -1.246425E-02 -2.621144E-05 -1.701677E-02 -4.718452E-05 -1.345504E-02 -2.750081E-05 -1.915828E-02 -6.206762E-05 -1.487706E-02 -3.498164E-05 -1.808302E-02 -5.043185E-05 -1.413342E-02 -3.559061E-05 -1.138146E-02 -1.786839E-05 -1.140044E-02 -1.941117E-05 -1.554299E-02 -2.899451E-05 -1.350147E-02 -2.424308E-05 -2.075976E-02 -7.307325E-05 -1.356231E-02 -2.080054E-05 -1.518370E-02 -3.316853E-05 -1.189204E-02 -1.901003E-05 -2.058005E-02 -5.143687E-05 -2.045751E-02 -5.497205E-05 -1.513733E-02 -2.666165E-05 -1.753330E-02 -3.936189E-05 -1.683976E-02 -3.581825E-05 -1.511066E-02 -2.645123E-05 -1.175520E-02 -1.609321E-05 -1.932866E-02 -4.358405E-05 -2.152647E-02 -5.525043E-05 -1.359163E-02 -2.720874E-05 -1.591814E-02 -3.441323E-05 -1.498891E-02 -3.242215E-05 -1.394632E-02 -2.541758E-05 -1.898119E-02 -4.729644E-05 -1.689587E-02 -3.933248E-05 -1.435155E-02 -2.582993E-05 -1.316763E-02 -2.353008E-05 -1.157136E-02 -1.833702E-05 -1.655168E-02 -3.162804E-05 -1.516917E-02 -4.365366E-05 -2.271626E-02 -6.252949E-05 -2.415893E-02 -6.451266E-05 -1.132077E-02 -1.979205E-05 -1.218269E-02 -1.887580E-05 -1.457860E-02 -2.603959E-05 -1.799378E-02 -3.831940E-05 -1.973304E-02 -5.131280E-05 -1.650072E-02 -4.421326E-05 -1.309761E-02 -2.093703E-05 -9.968119E-03 -1.734048E-05 -2.388636E-02 -8.126332E-05 -1.459477E-02 -3.488715E-05 -2.918991E-02 -9.400845E-05 -2.039305E-02 -4.974054E-05 -1.348400E-02 -3.490462E-05 -1.687564E-02 -4.279173E-05 -1.513373E-02 -2.823507E-05 -1.994888E-02 -5.071283E-05 -1.764059E-02 -4.346435E-05 -1.859116E-02 -5.299840E-05 -1.380401E-02 -2.348130E-05 -1.635474E-02 -3.937702E-05 -2.064198E-02 -5.607997E-05 -1.842824E-02 -4.282589E-05 -2.078636E-02 -5.236688E-05 -1.710805E-02 -3.985969E-05 -1.543166E-02 -3.277155E-05 -1.311119E-02 -2.103436E-05 -1.223030E-02 -1.772840E-05 -1.428400E-02 -2.879115E-05 -1.711044E-02 -3.871812E-05 -1.431954E-02 -2.831455E-05 -7.837091E-03 -1.187250E-05 -7.756280E-03 -8.554725E-06 -7.995791E-03 -1.095905E-05 -8.605179E-03 -1.177231E-05 -8.958756E-03 -1.332678E-05 -1.034574E-02 -2.171120E-05 -6.001176E-03 -7.941410E-06 -1.257551E-02 -2.312537E-05 -4.129076E-03 -2.677243E-06 -8.501326E-03 -1.658402E-05 -5.816010E-03 -5.905913E-06 -7.839173E-03 -8.421697E-06 -5.918322E-03 -9.025041E-06 -5.736561E-03 -7.633742E-06 -9.243956E-03 -1.198288E-05 -8.562607E-03 -9.900387E-06 -8.517736E-03 -1.400152E-05 -8.058111E-03 -8.346635E-06 -6.429181E-03 -8.483646E-06 -9.766782E-03 -1.860263E-05 -8.854052E-03 -1.734509E-05 -8.929637E-03 -1.491512E-05 -5.233001E-03 -5.925028E-06 -9.295152E-03 -1.768126E-05 -1.257918E-02 -2.632079E-05 -1.127993E-02 -1.815069E-05 -1.522302E-02 -3.459869E-05 -2.039110E-02 -6.104303E-05 -7.018288E-03 -8.011469E-06 -1.296372E-02 -2.439899E-05 -1.344461E-02 -3.144942E-05 -1.591259E-02 -3.662184E-05 -1.592134E-02 -3.534978E-05 -1.397292E-02 -2.673400E-05 -1.387726E-02 -2.413584E-05 -1.403292E-02 -2.450220E-05 -1.623686E-02 -3.934040E-05 -1.455326E-02 -3.956697E-05 -1.848869E-02 -4.594096E-05 -1.562335E-02 -2.895160E-05 -1.934214E-02 -6.527205E-05 -2.762082E-02 -1.002001E-04 -1.646443E-02 -4.757237E-05 -1.974118E-02 -5.871473E-05 -1.812863E-02 -4.571190E-05 -2.841456E-02 -1.256913E-04 -1.572056E-02 -3.604561E-05 -1.479375E-02 -4.114818E-05 -2.139729E-02 -5.158299E-05 -1.827112E-02 -4.755220E-05 -2.918330E-02 -9.121760E-05 -1.800084E-02 -4.226384E-05 -2.357640E-02 -6.593693E-05 -2.849119E-02 -1.014082E-04 -2.107159E-02 -6.738763E-05 -2.185077E-02 -6.120235E-05 -1.870103E-02 -5.126759E-05 -2.228030E-02 -5.885366E-05 -1.218959E-02 -1.923700E-05 -1.518833E-02 -2.980819E-05 -2.131881E-02 -6.164198E-05 -1.857691E-02 -5.149996E-05 -1.967993E-02 -4.929073E-05 -2.037752E-02 -5.254462E-05 -2.428694E-02 -7.415972E-05 -2.311199E-02 -5.830300E-05 -1.781340E-02 -5.016711E-05 -2.109282E-02 -5.439384E-05 -2.646402E-02 -7.981598E-05 -2.872928E-02 -1.157883E-04 -2.296882E-02 -5.600052E-05 -2.145069E-02 -6.153603E-05 -3.194172E-02 -1.130937E-04 -2.556185E-02 -8.976008E-05 -2.450563E-02 -7.657853E-05 -2.632135E-02 -8.318821E-05 -2.937358E-02 -9.572656E-05 -2.779408E-02 -9.729157E-05 -2.029619E-02 -5.815728E-05 -2.107188E-02 -5.405801E-05 -2.864120E-02 -9.187238E-05 -3.189900E-02 -1.158697E-04 -2.174543E-02 -6.126120E-05 -1.866666E-02 -3.831554E-05 -4.074514E-02 -2.019874E-04 -3.077997E-02 -1.155565E-04 -2.845511E-02 -9.760556E-05 -2.358164E-02 -7.014622E-05 -3.662127E-02 -1.520968E-04 -3.309700E-02 -1.256130E-04 -2.775361E-02 -1.078304E-04 -3.177889E-02 -1.327385E-04 -2.523394E-02 -8.921547E-05 -3.189185E-02 -1.647022E-04 -2.967954E-02 -1.071890E-04 -2.119897E-02 -5.752892E-05 -3.434445E-02 -1.342008E-04 -2.714518E-02 -8.681886E-05 -2.897958E-02 -9.065153E-05 -2.696222E-02 -8.540024E-05 -2.987888E-02 -9.648932E-05 -2.811456E-02 -9.230152E-05 -2.638667E-02 -8.721739E-05 -3.440902E-02 -1.421180E-04 -2.352488E-02 -7.481613E-05 -3.172354E-02 -1.853144E-04 -2.170608E-02 -6.022568E-05 -1.913037E-02 -5.905188E-05 -3.295652E-02 -1.433947E-04 -2.543187E-02 -9.035364E-05 -1.729217E-02 -3.824473E-05 -1.983528E-02 -6.034582E-05 -3.265521E-02 -1.315037E-04 -2.437483E-02 -7.364625E-05 -1.554696E-02 -3.206723E-05 -2.145024E-02 -5.715848E-05 -1.057830E-02 -1.743678E-05 -1.046397E-02 -1.560587E-05 -9.479417E-03 -1.712347E-05 -1.254587E-02 -3.235855E-05 -1.579355E-02 -4.509260E-05 -1.484926E-02 -2.799512E-05 -1.228686E-02 -2.031169E-05 -1.212962E-02 -2.512835E-05 -1.657642E-02 -4.655608E-05 -1.385236E-02 -2.324629E-05 -1.422372E-02 -4.206039E-05 -1.285229E-02 -2.234088E-05 -1.063684E-02 -2.048991E-05 -1.054286E-02 -1.650301E-05 -7.250865E-03 -8.349919E-06 -4.846842E-03 -5.611575E-06 -6.655706E-03 -8.978424E-06 -1.009164E-02 -1.254527E-05 -8.369823E-03 -8.564886E-06 -7.078759E-03 -7.850385E-06 -6.511893E-03 -7.778046E-06 -9.070684E-03 -1.106525E-05 -6.662311E-03 -5.901628E-06 -5.341082E-03 -4.512027E-06 -2.019250E-02 -5.835499E-05 -1.804537E-02 -4.752474E-05 -2.143023E-02 -6.883510E-05 -1.472836E-02 -3.235428E-05 -2.050065E-02 -5.392162E-05 -1.244535E-02 -2.314093E-05 -1.512563E-02 -2.709722E-05 -1.844357E-02 -4.096498E-05 -1.230849E-02 -2.204180E-05 -1.094959E-02 -1.878473E-05 -1.443675E-02 -2.665387E-05 -1.322804E-02 -2.121836E-05 -2.663562E-02 -9.639039E-05 -3.653391E-02 -1.705389E-04 -2.009980E-02 -5.226492E-05 -2.269292E-02 -7.235254E-05 -2.630232E-02 -8.600830E-05 -2.058472E-02 -6.670991E-05 -2.641568E-02 -9.197032E-05 -2.754053E-02 -1.038311E-04 -3.121142E-02 -1.199600E-04 -2.717065E-02 -9.654646E-05 -2.242629E-02 -1.009563E-04 -2.075151E-02 -5.816770E-05 -3.942214E-02 -1.987805E-04 -3.882076E-02 -1.939596E-04 -2.920978E-02 -1.084721E-04 -2.600676E-02 -8.334881E-05 -2.923234E-02 -1.017212E-04 -3.586528E-02 -1.334235E-04 -3.797598E-02 -1.702103E-04 -3.232846E-02 -1.218180E-04 -3.377761E-02 -1.378231E-04 -4.192066E-02 -2.072314E-04 -2.738955E-02 -8.865239E-05 -3.568104E-02 -1.804686E-04 -3.548082E-02 -1.615200E-04 -5.031302E-02 -3.122101E-04 -3.009267E-02 -1.144558E-04 -3.199905E-02 -1.145847E-04 -3.777360E-02 -1.663536E-04 -3.384202E-02 -1.350575E-04 -4.560705E-02 -2.708256E-04 -3.136124E-02 -1.138594E-04 -4.666445E-02 -2.341642E-04 -4.832203E-02 -2.735704E-04 -2.846160E-02 -9.724755E-05 -3.958876E-02 -1.723911E-04 -3.564894E-02 -1.460291E-04 -5.846112E-02 -3.948391E-04 -3.546238E-02 -1.608118E-04 -3.537206E-02 -1.460004E-04 -5.554597E-02 -3.566908E-04 -5.109455E-02 -3.208060E-04 -5.520597E-02 -3.527162E-04 -4.201987E-02 -1.917230E-04 -6.660358E-02 -4.711986E-04 -5.432898E-02 -3.242512E-04 -4.089084E-02 -1.879065E-04 -3.784277E-02 -1.557193E-04 -5.046288E-02 -2.834904E-04 -5.513093E-02 -3.595041E-04 -3.711842E-02 -1.494648E-04 -4.392972E-02 -2.015209E-04 -4.988699E-02 -2.634722E-04 -3.989393E-02 -1.816607E-04 -5.144002E-02 -2.769398E-04 -4.565016E-02 -2.355239E-04 -6.482286E-02 -4.539075E-04 -4.470289E-02 -2.139336E-04 -4.617957E-02 -2.463023E-04 -4.418753E-02 -2.283032E-04 -4.649993E-02 -2.511721E-04 -4.930410E-02 -2.838380E-04 -3.882151E-02 -1.837693E-04 -2.680799E-02 -8.238578E-05 -5.755520E-02 -4.130996E-04 -4.496883E-02 -2.557734E-04 -3.602591E-02 -1.512327E-04 -2.530643E-02 -9.160435E-05 -4.057178E-02 -1.911452E-04 -3.912871E-02 -1.943839E-04 -2.823744E-02 -1.084509E-04 -3.870972E-02 -1.741549E-04 -2.669650E-02 -9.821873E-05 -3.580275E-02 -1.589657E-04 -2.195198E-02 -5.837423E-05 -2.079687E-02 -6.448549E-05 -3.002400E-02 -1.160249E-04 -2.957314E-02 -1.189151E-04 -2.377935E-02 -6.808549E-05 -1.839041E-02 -4.555435E-05 -3.430294E-02 -1.387042E-04 -2.592718E-02 -9.050017E-05 -1.535960E-02 -3.794370E-05 -2.078265E-02 -7.317160E-05 -1.576237E-02 -2.996656E-05 -2.216535E-02 -6.517900E-05 -1.811146E-02 -4.238302E-05 -1.455371E-02 -3.667385E-05 -2.634667E-02 -8.364438E-05 -1.996539E-02 -4.953189E-05 -1.816175E-02 -3.710475E-05 -1.218979E-02 -2.484826E-05 -2.442424E-02 -8.794676E-05 -2.372381E-02 -7.702420E-05 -2.231590E-02 -9.784571E-05 -2.172844E-02 -5.916333E-05 -1.145998E-02 -1.962910E-05 -1.702504E-02 -5.111810E-05 -6.914654E-03 -8.875412E-06 -1.075152E-02 -2.522276E-05 -1.773996E-02 -4.090619E-05 -9.269666E-03 -1.495738E-05 -1.266630E-02 -2.461812E-05 -1.423043E-02 -3.464040E-05 -1.459824E-02 -3.078483E-05 -9.387052E-03 -1.202926E-05 -9.667799E-03 -1.454321E-05 -9.447707E-03 -1.271935E-05 -1.549107E-02 -2.931692E-05 -1.961989E-02 -5.758509E-05 -1.679927E-02 -4.376812E-05 -1.729049E-02 -4.546154E-05 -2.214419E-02 -5.744861E-05 -1.574631E-02 -3.404805E-05 -1.512389E-02 -2.852541E-05 -1.564070E-02 -2.961719E-05 -1.156911E-02 -1.664384E-05 -1.199574E-02 -1.963095E-05 -1.575890E-02 -3.865614E-05 -8.533212E-03 -1.165342E-05 -2.974207E-02 -1.029138E-04 -3.078702E-02 -1.267340E-04 -2.895029E-02 -9.417641E-05 -2.705881E-02 -1.080454E-04 -2.385421E-02 -7.531760E-05 -2.083704E-02 -6.502784E-05 -3.429066E-02 -1.504413E-04 -3.503625E-02 -1.408918E-04 -2.706075E-02 -8.947448E-05 -3.189758E-02 -1.230472E-04 -2.544089E-02 -8.519294E-05 -2.520959E-02 -8.797041E-05 -5.070461E-02 -3.189504E-04 -4.884044E-02 -2.572701E-04 -3.547633E-02 -1.862450E-04 -4.388084E-02 -2.567378E-04 -3.492269E-02 -1.420917E-04 -2.806485E-02 -1.009649E-04 -5.059445E-02 -2.907485E-04 -4.808491E-02 -2.424314E-04 -4.942392E-02 -3.097207E-04 -3.897127E-02 -1.994484E-04 -3.839420E-02 -1.746523E-04 -3.244417E-02 -1.184480E-04 -5.623036E-02 -3.492166E-04 -6.425888E-02 -4.935669E-04 -4.877756E-02 -2.579133E-04 -4.955342E-02 -2.926551E-04 -5.396104E-02 -3.055339E-04 -5.871614E-02 -3.961828E-04 -6.708244E-02 -4.826510E-04 -5.278021E-02 -2.835069E-04 -6.918022E-02 -5.087677E-04 -5.576575E-02 -3.607685E-04 -4.871576E-02 -2.820267E-04 -4.103199E-02 -1.970300E-04 -7.773659E-02 -6.470582E-04 -8.599878E-02 -8.479845E-04 -6.886056E-02 -5.267028E-04 -5.721217E-02 -3.681350E-04 -7.713996E-02 -6.425519E-04 -5.865857E-02 -4.103676E-04 -9.128533E-02 -9.001212E-04 -6.876681E-02 -4.977191E-04 -8.130881E-02 -7.186877E-04 -7.550488E-02 -6.383683E-04 -6.074888E-02 -4.148348E-04 -5.625163E-02 -3.768206E-04 -7.967025E-02 -7.546239E-04 -1.062008E-01 -1.178026E-03 -7.335119E-02 -5.749705E-04 -4.820386E-02 -2.843684E-04 -8.285561E-02 -7.331262E-04 -6.377785E-02 -4.639306E-04 -6.793437E-02 -5.094372E-04 -5.119790E-02 -2.807423E-04 -9.613221E-02 -9.824061E-04 -7.536222E-02 -5.822997E-04 -4.761788E-02 -2.477789E-04 -6.084099E-02 -4.333532E-04 -4.906915E-02 -3.040989E-04 -7.222981E-02 -6.031356E-04 -4.171024E-02 -1.905756E-04 -4.528343E-02 -2.268220E-04 -6.279446E-02 -4.327452E-04 -5.128421E-02 -2.753808E-04 -6.231043E-02 -4.457498E-04 -4.764799E-02 -2.670171E-04 -6.361492E-02 -4.379323E-04 -5.965053E-02 -3.939821E-04 -5.490029E-02 -3.380966E-04 -6.827868E-02 -4.968827E-04 -3.309475E-02 -1.331187E-04 -4.603502E-02 -2.672301E-04 -3.793331E-02 -1.804286E-04 -2.266265E-02 -5.756031E-05 -5.949869E-02 -3.999807E-04 -3.963197E-02 -1.762880E-04 -3.899893E-02 -1.642926E-04 -3.082622E-02 -1.074710E-04 -5.463795E-02 -3.382616E-04 -4.577997E-02 -2.244114E-04 -2.946043E-02 -1.104054E-04 -3.390553E-02 -1.311928E-04 -2.012911E-02 -4.877248E-05 -3.010504E-02 -1.111957E-04 -2.530155E-02 -8.217373E-05 -2.188500E-02 -5.370079E-05 -3.794688E-02 -1.630376E-04 -3.361882E-02 -1.162902E-04 -2.106804E-02 -5.229501E-05 -2.245974E-02 -5.982159E-05 -2.505198E-02 -8.478230E-05 -2.287601E-02 -6.940045E-05 -2.246447E-02 -6.064445E-05 -2.014030E-02 -4.596852E-05 -1.547790E-02 -2.802405E-05 -1.827409E-02 -3.706838E-05 -1.250681E-02 -2.504890E-05 -1.523959E-02 -3.397988E-05 -1.959572E-02 -4.638773E-05 -2.192689E-02 -6.243400E-05 -1.209982E-02 -1.817250E-05 -1.262662E-02 -2.516249E-05 -1.684816E-02 -3.966147E-05 -6.158783E-03 -6.145844E-06 -1.336232E-02 -2.474390E-05 -1.990714E-02 -5.523583E-05 -2.459172E-02 -7.004859E-05 -1.772252E-02 -4.853898E-05 -1.485696E-02 -2.873818E-05 -1.413071E-02 -3.178019E-05 -3.091676E-02 -1.063557E-04 -2.309515E-02 -6.359073E-05 -1.550213E-02 -4.421294E-05 -2.192641E-02 -6.676847E-05 -1.438379E-02 -2.502494E-05 -9.323835E-03 -1.058149E-05 -1.950987E-02 -5.777120E-05 -1.128375E-02 -1.672801E-05 -2.835693E-02 -1.026638E-04 -3.616127E-02 -1.505209E-04 -2.584643E-02 -7.628678E-05 -3.372488E-02 -1.431161E-04 -2.972258E-02 -1.013165E-04 -2.718135E-02 -9.239632E-05 -4.046046E-02 -2.091323E-04 -3.184363E-02 -1.406831E-04 -2.906162E-02 -9.931921E-05 -3.473938E-02 -1.672263E-04 -3.247790E-02 -1.200800E-04 -2.283247E-02 -6.591169E-05 -5.157721E-02 -2.857973E-04 -5.318589E-02 -3.355446E-04 -5.396648E-02 -3.222881E-04 -3.455908E-02 -1.577620E-04 -4.000627E-02 -1.811544E-04 -3.827765E-02 -1.701640E-04 -6.111711E-02 -4.195077E-04 -4.813123E-02 -2.551093E-04 -5.248302E-02 -3.053078E-04 -6.395395E-02 -4.882393E-04 -4.085525E-02 -2.131190E-04 -4.537763E-02 -2.817462E-04 -9.621518E-02 -9.753697E-04 -8.338063E-02 -7.366007E-04 -9.141446E-02 -9.402148E-04 -6.429772E-02 -4.457199E-04 -6.537278E-02 -4.627356E-04 -6.465671E-02 -4.504472E-04 -8.801279E-02 -8.983416E-04 -7.192007E-02 -5.371364E-04 -6.236850E-02 -5.079591E-04 -7.006768E-02 -5.856072E-04 -6.331101E-02 -4.271617E-04 -5.772433E-02 -3.721594E-04 -1.415443E-01 -2.106304E-03 -1.333977E-01 -1.819393E-03 -9.668520E-02 -1.012563E-03 -7.876408E-02 -7.180366E-04 -1.082944E-01 -1.226100E-03 -7.858017E-02 -6.820487E-04 -1.233753E-01 -1.710493E-03 -8.940326E-02 -8.711409E-04 -1.097575E-01 -1.284214E-03 -1.079765E-01 -1.255092E-03 -8.764292E-02 -8.394106E-04 -8.007939E-02 -7.022808E-04 -1.214238E-01 -1.596170E-03 -1.421555E-01 -2.105744E-03 -9.333869E-02 -9.022978E-04 -7.506639E-02 -6.221271E-04 -1.304706E-01 -1.799634E-03 -7.986544E-02 -7.526969E-04 -9.702135E-02 -9.836576E-04 -7.294081E-02 -5.906372E-04 -1.297603E-01 -1.782812E-03 -9.082392E-02 -8.669323E-04 -6.578070E-02 -5.122022E-04 -8.815494E-02 -8.142597E-04 -8.155167E-02 -7.217382E-04 -1.018109E-01 -1.086157E-03 -7.197825E-02 -5.331106E-04 -5.627838E-02 -3.449520E-04 -9.010939E-02 -8.605735E-04 -7.405764E-02 -5.833698E-04 -6.370311E-02 -4.307727E-04 -5.655449E-02 -4.002735E-04 -7.828799E-02 -6.754020E-04 -6.189231E-02 -4.227420E-04 -6.662691E-02 -5.039861E-04 -5.981533E-02 -4.042598E-04 -4.616563E-02 -2.512572E-04 -5.126904E-02 -2.954937E-04 -4.940896E-02 -3.013823E-04 -3.651484E-02 -1.509448E-04 -6.169343E-02 -4.343928E-04 -5.276526E-02 -3.035402E-04 -3.757296E-02 -1.669063E-04 -3.701904E-02 -1.472772E-04 -5.041077E-02 -2.708039E-04 -3.789204E-02 -1.599636E-04 -3.750354E-02 -1.758214E-04 -3.841079E-02 -1.623123E-04 -2.067644E-02 -6.321573E-05 -2.854616E-02 -9.473813E-05 -2.444174E-02 -7.627675E-05 -1.711406E-02 -4.015948E-05 -3.249873E-02 -1.518375E-04 -3.257016E-02 -1.207336E-04 -2.196857E-02 -6.460695E-05 -2.336435E-02 -6.693447E-05 -3.087108E-02 -1.244672E-04 -2.930263E-02 -1.042844E-04 -2.973494E-02 -9.755987E-05 -2.663199E-02 -7.916063E-05 -8.110891E-03 -9.147184E-06 -1.596974E-02 -3.945176E-05 -1.126941E-02 -1.972987E-05 -1.498580E-02 -2.597248E-05 -2.296704E-02 -6.870338E-05 -1.864901E-02 -4.568849E-05 -9.655003E-03 -1.218230E-05 -8.917615E-03 -1.497980E-05 -1.991649E-02 -4.425777E-05 -1.938334E-02 -4.450084E-05 -1.468869E-02 -2.783700E-05 -1.990846E-02 -4.552853E-05 -1.774831E-02 -4.009193E-05 -1.266322E-02 -2.320002E-05 -1.658764E-02 -3.986878E-05 -1.698328E-02 -4.091919E-05 -2.128494E-02 -6.048618E-05 -2.030808E-02 -5.574087E-05 -1.270134E-02 -2.233463E-05 -1.683769E-02 -3.536069E-05 -9.809511E-03 -1.445622E-05 -8.599393E-03 -1.081146E-05 -1.931983E-02 -6.640579E-05 -2.037581E-02 -5.286217E-05 -3.532151E-02 -1.703716E-04 -2.959688E-02 -1.000744E-04 -2.794173E-02 -9.833908E-05 -2.721311E-02 -8.705508E-05 -2.259018E-02 -6.498840E-05 -2.999787E-02 -1.185856E-04 -4.036794E-02 -2.072046E-04 -3.144378E-02 -1.169125E-04 -2.933694E-02 -1.105938E-04 -3.942738E-02 -1.729860E-04 -3.260874E-02 -1.481232E-04 -2.353895E-02 -7.836100E-05 -5.876129E-02 -3.975363E-04 -4.766425E-02 -2.519722E-04 -4.033714E-02 -1.807849E-04 -4.729862E-02 -2.401753E-04 -4.304677E-02 -2.096845E-04 -3.822586E-02 -1.740610E-04 -5.685525E-02 -3.389362E-04 -5.053276E-02 -3.049584E-04 -4.125673E-02 -1.768692E-04 -4.228077E-02 -2.108012E-04 -4.501666E-02 -2.298865E-04 -3.308537E-02 -1.337489E-04 -9.085434E-02 -8.630952E-04 -8.043671E-02 -6.998250E-04 -6.790115E-02 -5.151102E-04 -9.822017E-02 -1.054933E-03 -6.615956E-02 -4.705198E-04 -5.651598E-02 -3.870178E-04 -9.749998E-02 -1.051885E-03 -8.349892E-02 -7.963070E-04 -6.591239E-02 -4.655083E-04 -6.485664E-02 -4.646649E-04 -5.727855E-02 -3.614456E-04 -5.982342E-02 -3.951869E-04 -1.437862E-01 -2.121299E-03 -1.381644E-01 -1.981530E-03 -1.258886E-01 -1.695067E-03 -1.148436E-01 -1.441218E-03 -9.597117E-02 -1.101364E-03 -8.065670E-02 -7.548241E-04 -1.190394E-01 -1.472809E-03 -1.202733E-01 -1.590349E-03 -9.488301E-02 -9.917086E-04 -8.590582E-02 -8.395527E-04 -8.538615E-02 -7.662543E-04 -6.840866E-02 -5.508149E-04 -1.309341E-01 -1.788800E-03 -1.431432E-01 -2.124925E-03 -1.253592E-01 -1.673315E-03 -1.027124E-01 -1.115422E-03 -1.257192E-01 -1.618975E-03 -1.009903E-01 -1.140739E-03 -8.317957E-02 -7.328749E-04 -8.230977E-02 -7.081126E-04 -1.122030E-01 -1.312445E-03 -9.156529E-02 -9.645560E-04 -7.593394E-02 -6.433631E-04 -7.347627E-02 -5.887314E-04 -9.176044E-02 -8.793675E-04 -9.196817E-02 -9.288935E-04 -8.602817E-02 -7.934807E-04 -6.540851E-02 -5.134819E-04 -7.784855E-02 -7.374549E-04 -7.145641E-02 -5.431170E-04 -6.586554E-02 -4.742469E-04 -6.889110E-02 -5.369623E-04 -5.852275E-02 -3.823255E-04 -5.130633E-02 -2.938484E-04 -5.009392E-02 -2.807458E-04 -5.334814E-02 -3.079752E-04 -4.264743E-02 -1.994080E-04 -4.606571E-02 -2.446337E-04 -4.932925E-02 -2.518310E-04 -3.172175E-02 -1.173609E-04 -4.799012E-02 -2.513615E-04 -5.034796E-02 -2.882966E-04 -3.398215E-02 -1.394103E-04 -3.801944E-02 -1.702277E-04 -3.688050E-02 -1.492715E-04 -2.945875E-02 -1.064246E-04 -3.293199E-02 -1.292973E-04 -5.057135E-02 -2.972879E-04 -2.902424E-02 -1.009778E-04 -2.994301E-02 -1.055013E-04 -3.820998E-02 -1.811607E-04 -2.790027E-02 -1.186505E-04 -3.074064E-02 -1.078519E-04 -3.248893E-02 -1.169499E-04 -2.353194E-02 -8.076603E-05 -1.809505E-02 -4.072324E-05 -3.396351E-02 -1.453516E-04 -2.286807E-02 -5.496448E-05 -1.987060E-02 -5.376353E-05 -3.044601E-02 -1.115521E-04 -1.248945E-02 -2.198679E-05 -1.803171E-02 -4.771632E-05 -1.378131E-02 -4.134383E-05 -1.555134E-02 -4.721156E-05 -2.534113E-02 -8.351023E-05 -1.500299E-02 -2.635770E-05 -1.071802E-02 -2.136252E-05 -1.137076E-02 -1.975771E-05 -1.456502E-02 -2.501472E-05 -9.727505E-03 -1.483236E-05 -1.454436E-02 -2.710978E-05 -1.978067E-02 -5.285365E-05 -1.360981E-02 -2.336372E-05 -9.847294E-03 -1.509563E-05 -1.524613E-02 -3.552566E-05 -1.773316E-02 -4.971550E-05 -1.867569E-02 -4.914571E-05 -1.751220E-02 -3.467782E-05 -1.304981E-02 -3.349123E-05 -1.082428E-02 -1.865766E-05 -9.584944E-03 -1.325745E-05 -9.180830E-03 -1.262337E-05 -1.640308E-02 -3.160798E-05 -9.874242E-03 -1.450077E-05 -2.800307E-02 -9.021643E-05 -2.465166E-02 -8.472087E-05 -2.134009E-02 -5.841535E-05 -2.840708E-02 -9.453242E-05 -1.817238E-02 -4.004063E-05 -2.108886E-02 -5.388334E-05 -3.062270E-02 -1.286139E-04 -2.538387E-02 -8.871389E-05 -1.989607E-02 -5.232630E-05 -3.196356E-02 -1.567584E-04 -2.768337E-02 -8.817683E-05 -1.657009E-02 -3.128845E-05 -6.221175E-02 -5.006436E-04 -4.068999E-02 -2.287368E-04 -3.891057E-02 -1.725015E-04 -3.661313E-02 -1.700136E-04 -4.325252E-02 -2.377359E-04 -3.132785E-02 -1.053139E-04 -4.447018E-02 -2.340749E-04 -4.887097E-02 -2.828548E-04 -3.659403E-02 -1.932574E-04 -3.839512E-02 -1.702624E-04 -3.434064E-02 -1.413220E-04 -3.562809E-02 -1.569627E-04 -6.182234E-02 -4.171544E-04 -6.100628E-02 -4.051419E-04 -6.647923E-02 -4.900740E-04 -7.287500E-02 -5.551039E-04 -4.730174E-02 -2.512478E-04 -5.228155E-02 -3.234257E-04 -6.367674E-02 -4.355277E-04 -6.127620E-02 -5.160754E-04 -4.996635E-02 -2.866391E-04 -4.386223E-02 -2.253152E-04 -5.319524E-02 -3.262631E-04 -5.127473E-02 -2.891196E-04 -1.048530E-01 -1.182483E-03 -8.170362E-02 -7.286542E-04 -7.965260E-02 -6.956308E-04 -8.522862E-02 -7.597262E-04 -6.792526E-02 -5.514875E-04 -5.653238E-02 -4.231108E-04 -8.040674E-02 -7.324397E-04 -6.538609E-02 -5.208188E-04 -6.236588E-02 -4.356839E-04 -6.164613E-02 -4.180417E-04 -7.331991E-02 -6.180767E-04 -5.657072E-02 -3.533489E-04 -7.827811E-02 -6.870284E-04 -7.791072E-02 -6.465127E-04 -1.083139E-01 -1.260161E-03 -8.407475E-02 -7.634468E-04 -6.669029E-02 -4.841099E-04 -7.629250E-02 -6.708847E-04 -6.145772E-02 -4.524294E-04 -6.227290E-02 -4.295289E-04 -6.532027E-02 -4.771341E-04 -5.543686E-02 -3.242450E-04 -6.507036E-02 -4.562060E-04 -6.918175E-02 -5.208846E-04 -5.915840E-02 -4.026369E-04 -7.574284E-02 -6.257363E-04 -6.443876E-02 -4.697084E-04 -4.704047E-02 -2.420667E-04 -6.871095E-02 -5.703679E-04 -7.652879E-02 -6.996775E-04 -4.488343E-02 -2.199039E-04 -4.340162E-02 -2.117909E-04 -5.505629E-02 -3.299335E-04 -5.395493E-02 -3.792417E-04 -4.982738E-02 -2.664394E-04 -5.864743E-02 -4.020406E-04 -3.700812E-02 -1.675101E-04 -3.590296E-02 -1.636877E-04 -3.701403E-02 -2.028641E-04 -3.559772E-02 -1.412606E-04 -4.420940E-02 -2.126895E-04 -3.967986E-02 -1.668324E-04 -2.751914E-02 -1.031787E-04 -3.350726E-02 -1.282541E-04 -3.400056E-02 -1.396521E-04 -2.928242E-02 -1.253649E-04 -3.696302E-02 -1.675271E-04 -2.971538E-02 -1.050504E-04 -2.147157E-02 -6.672784E-05 -2.068698E-02 -5.314224E-05 -3.024410E-02 -1.161314E-04 -2.564259E-02 -8.893011E-05 -2.244324E-02 -6.402041E-05 -3.352393E-02 -1.269472E-04 -2.503002E-02 -1.001149E-04 -2.271412E-02 -6.142137E-05 -2.662779E-02 -8.519648E-05 -2.760352E-02 -9.770118E-05 -3.168086E-02 -1.170083E-04 -2.636525E-02 -8.041298E-05 -1.168923E-02 -2.309996E-05 -1.341095E-02 -2.785722E-05 -9.527042E-03 -1.301984E-05 -8.579383E-03 -1.158986E-05 -1.770829E-02 -3.709440E-05 -1.285206E-02 -2.277856E-05 -5.715674E-03 -5.170007E-06 -7.751126E-03 -1.014219E-05 -1.566218E-02 -2.874454E-05 -1.550600E-02 -4.482121E-05 -1.310088E-02 -2.996692E-05 -1.266810E-02 -2.452354E-05 -1.328220E-02 -2.441758E-05 -9.553257E-03 -1.316655E-05 -1.072874E-02 -2.962475E-05 -1.419443E-02 -2.691293E-05 -1.389066E-02 -2.460204E-05 -1.520080E-02 -2.942326E-05 -9.725298E-03 -1.180312E-05 -9.645833E-03 -1.760954E-05 -8.964384E-03 -1.441525E-05 -7.797734E-03 -7.875870E-06 -1.222531E-02 -2.143962E-05 -9.811025E-03 -1.223418E-05 -2.347719E-02 -7.632207E-05 -2.624065E-02 -8.577440E-05 -1.872843E-02 -5.642768E-05 -2.884633E-02 -1.120462E-04 -1.331677E-02 -2.169139E-05 -2.073785E-02 -6.410937E-05 -2.069105E-02 -5.558996E-05 -2.409694E-02 -8.187520E-05 -1.689558E-02 -4.223843E-05 -1.624061E-02 -3.418316E-05 -2.151976E-02 -5.877173E-05 -2.360183E-02 -9.731432E-05 -3.349038E-02 -1.331399E-04 -3.071585E-02 -1.134216E-04 -3.064437E-02 -1.380256E-04 -3.411658E-02 -1.385980E-04 -1.902680E-02 -4.966952E-05 -2.548619E-02 -8.563915E-05 -2.627494E-02 -8.806514E-05 -3.156158E-02 -1.348057E-04 -2.555848E-02 -8.827726E-05 -2.109045E-02 -5.840881E-05 -3.141908E-02 -1.092575E-04 -2.542704E-02 -7.869948E-05 -4.409974E-02 -2.370516E-04 -4.511455E-02 -2.385642E-04 -3.493033E-02 -1.329289E-04 -3.573369E-02 -1.645671E-04 -3.658071E-02 -1.701779E-04 -2.875736E-02 -1.063832E-04 -4.612939E-02 -2.341592E-04 -4.488569E-02 -2.371072E-04 -3.283008E-02 -1.266329E-04 -4.421310E-02 -2.144763E-04 -3.688239E-02 -1.597994E-04 -3.783217E-02 -1.715032E-04 -7.381035E-02 -5.788223E-04 -5.920057E-02 -3.764365E-04 -5.566865E-02 -3.245756E-04 -5.294945E-02 -3.171578E-04 -5.308993E-02 -3.020899E-04 -4.015025E-02 -1.763785E-04 -5.449993E-02 -4.477957E-04 -6.098529E-02 -4.698598E-04 -4.562321E-02 -2.217931E-04 -4.372709E-02 -2.205027E-04 -5.027493E-02 -3.024221E-04 -5.350904E-02 -3.184156E-04 -4.989979E-02 -2.950952E-04 -5.166796E-02 -2.972852E-04 -5.157410E-02 -3.015135E-04 -4.679395E-02 -2.264100E-04 -4.534145E-02 -2.596978E-04 -4.610982E-02 -2.659116E-04 -4.420313E-02 -2.280910E-04 -4.382650E-02 -2.133009E-04 -4.090414E-02 -1.993174E-04 -3.320114E-02 -1.287562E-04 -4.502626E-02 -2.259113E-04 -3.962180E-02 -1.762251E-04 -4.967895E-02 -3.145518E-04 -4.494669E-02 -2.411637E-04 -4.339354E-02 -2.011700E-04 -4.176613E-02 -2.014202E-04 -4.442877E-02 -2.331921E-04 -3.398932E-02 -1.379211E-04 -3.482327E-02 -1.541052E-04 -3.556969E-02 -1.558964E-04 -3.691095E-02 -1.643955E-04 -2.226522E-02 -6.975395E-05 -3.915757E-02 -1.657456E-04 -2.866444E-02 -9.309362E-05 -2.855915E-02 -1.131346E-04 -2.537276E-02 -7.948738E-05 -3.789334E-02 -1.685996E-04 -2.751514E-02 -9.186058E-05 -3.178599E-02 -1.355963E-04 -3.907421E-02 -2.055557E-04 -2.791323E-02 -1.069896E-04 -3.339152E-02 -1.362152E-04 -2.050184E-02 -4.863200E-05 -2.291794E-02 -8.183025E-05 -2.124223E-02 -7.063324E-05 -2.399149E-02 -7.407918E-05 -1.796496E-02 -3.936797E-05 -2.078322E-02 -6.098637E-05 -3.024688E-02 -1.288165E-04 -2.239542E-02 -6.306787E-05 -2.616525E-02 -8.655425E-05 -2.919821E-02 -1.113037E-04 -1.673318E-02 -3.601539E-05 -1.608480E-02 -3.314965E-05 -2.821455E-02 -8.921863E-05 -1.974153E-02 -4.431146E-05 -2.003418E-02 -5.758763E-05 -2.061128E-02 -6.512772E-05 -1.559522E-02 -3.594737E-05 -1.934663E-02 -5.001512E-05 -1.075360E-02 -1.792213E-05 -8.194926E-03 -1.028496E-05 -2.034805E-02 -5.444881E-05 -1.609037E-02 -3.970183E-05 -1.347309E-02 -2.123107E-05 -1.407160E-02 -3.569412E-05 -1.624142E-02 -3.714221E-05 -1.299629E-02 -2.459818E-05 -1.122458E-02 -2.237869E-05 -1.211612E-02 -2.219160E-05 -1.408358E-02 -4.218855E-05 -6.735065E-03 -8.482615E-06 -6.793305E-03 -7.845095E-06 -8.478782E-03 -1.709477E-05 -1.133766E-02 -1.980469E-05 -9.653050E-03 -1.415133E-05 -5.831329E-03 -8.381192E-06 -6.218892E-03 -7.102476E-06 -7.592811E-03 -9.310767E-06 -6.506941E-03 -1.095631E-05 -9.452991E-03 -1.264596E-05 -4.768636E-03 -3.507810E-06 -2.077918E-02 -5.890772E-05 -1.762060E-02 -3.525407E-05 -1.205428E-02 -2.724892E-05 -1.469350E-02 -2.710234E-05 -8.551477E-03 -8.546946E-06 -1.223789E-02 -2.595121E-05 -1.076533E-02 -2.013472E-05 -1.864688E-02 -4.804170E-05 -1.271229E-02 -2.770046E-05 -1.016698E-02 -1.439334E-05 -1.713823E-02 -4.788386E-05 -1.253277E-02 -2.231383E-05 -3.154747E-02 -1.214804E-04 -1.749980E-02 -3.647612E-05 -1.830338E-02 -4.569688E-05 -2.308843E-02 -6.321283E-05 -1.594268E-02 -4.383360E-05 -2.466928E-02 -8.077902E-05 -2.901767E-02 -1.088029E-04 -2.554390E-02 -8.895350E-05 -2.146121E-02 -5.921450E-05 -1.943347E-02 -4.952984E-05 -1.991855E-02 -5.703083E-05 -1.411715E-02 -3.539989E-05 -2.706714E-02 -1.408378E-04 -2.476826E-02 -8.960297E-05 -3.280672E-02 -1.342648E-04 -2.769569E-02 -8.949765E-05 -2.254343E-02 -7.118925E-05 -2.821645E-02 -1.008088E-04 -2.332049E-02 -7.198089E-05 -3.472802E-02 -1.359900E-04 -2.098228E-02 -6.775921E-05 -2.011754E-02 -4.899916E-05 -2.887549E-02 -1.210569E-04 -2.169717E-02 -5.971602E-05 -4.083980E-02 -2.063696E-04 -2.682109E-02 -9.162241E-05 -4.087409E-02 -1.874734E-04 -3.397314E-02 -1.355352E-04 -2.503682E-02 -7.832902E-05 -3.341902E-02 -1.279805E-04 -3.470031E-02 -1.457506E-04 -3.434771E-02 -1.308149E-04 -1.924341E-02 -5.117189E-05 -2.610217E-02 -8.124782E-05 -2.672020E-02 -8.422537E-05 -2.913338E-02 -1.020506E-04 -3.799748E-02 -1.583935E-04 -2.396284E-02 -7.323177E-05 -4.085381E-02 -1.817575E-04 -3.429492E-02 -1.389255E-04 -2.955640E-02 -9.833007E-05 -3.550154E-02 -1.507005E-04 -3.041263E-02 -1.000878E-04 -3.068456E-02 -1.089623E-04 -2.480886E-02 -6.953343E-05 -2.214997E-02 -5.427501E-05 -2.822289E-02 -1.091821E-04 -2.246583E-02 -6.845501E-05 -3.548869E-02 -1.564383E-04 -3.342714E-02 -1.555114E-04 -3.584609E-02 -1.533905E-04 -2.543087E-02 -6.947810E-05 -3.395479E-02 -1.360453E-04 -3.067172E-02 -1.109996E-04 -2.290343E-02 -6.048129E-05 -1.985458E-02 -4.438216E-05 -3.051514E-02 -1.050122E-04 -2.086630E-02 -6.348306E-05 -2.009163E-02 -5.579571E-05 -2.312023E-02 -7.424842E-05 -2.349909E-02 -7.517591E-05 -2.465382E-02 -7.402420E-05 -2.149996E-02 -6.067745E-05 -2.388756E-02 -6.487269E-05 -1.918145E-02 -4.328933E-05 -1.951810E-02 -4.931597E-05 -1.743909E-02 -3.923120E-05 -1.959452E-02 -4.325142E-05 -1.836248E-02 -3.960818E-05 -1.633324E-02 -3.551742E-05 -1.863545E-02 -4.322646E-05 -2.548530E-02 -8.566650E-05 -1.370389E-02 -3.068862E-05 -1.702755E-02 -3.470486E-05 -2.110298E-02 -5.769891E-05 -1.950441E-02 -4.624026E-05 -1.773108E-02 -3.976096E-05 -2.121981E-02 -6.568857E-05 -1.052851E-02 -1.559210E-05 -1.304079E-02 -2.231298E-05 -1.944748E-02 -4.683893E-05 -1.445243E-02 -2.703435E-05 -1.597053E-02 -3.429994E-05 -1.650649E-02 -6.011419E-05 -8.568107E-03 -1.035370E-05 -5.963022E-03 -7.941116E-06 -1.005055E-02 -1.089546E-05 -9.025557E-03 -1.235125E-05 -1.058696E-02 -1.548458E-05 -1.428111E-02 -3.101021E-05 -6.332158E-03 -7.284553E-06 -1.107873E-02 -1.880555E-05 -9.074481E-03 -1.488548E-05 -8.633788E-03 -1.494006E-05 -9.852689E-03 -2.277679E-05 -1.279962E-02 -3.267960E-05 -1.096915E-02 -1.703897E-05 -6.543158E-03 -6.896083E-06 -7.823512E-03 -1.199583E-05 -6.285302E-03 -8.223945E-06 -7.196837E-03 -8.695066E-06 -6.939525E-03 -8.067024E-06 -4.593174E-03 -3.678022E-06 -4.766649E-03 -6.980855E-06 -4.492564E-03 -4.106885E-06 -5.836560E-03 -5.166762E-06 -4.091860E-03 -3.202729E-06 -2.851717E-03 -1.441790E-06 -1.131813E-02 -1.990562E-05 -8.044232E-03 -9.338147E-06 -9.601976E-03 -1.551372E-05 -1.271494E-02 -2.673243E-05 -6.142371E-03 -6.616946E-06 -7.543735E-03 -1.129556E-05 -1.054461E-02 -1.314345E-05 -1.244849E-02 -1.966250E-05 -9.734137E-03 -1.778830E-05 -1.360778E-02 -2.168963E-05 -8.980518E-03 -9.981098E-06 -5.673726E-03 -6.390047E-06 -1.495065E-02 -3.570344E-05 -1.139512E-02 -2.213315E-05 -1.578970E-02 -3.505969E-05 -1.629500E-02 -3.158196E-05 -1.481063E-02 -3.260955E-05 -1.632506E-02 -3.683693E-05 -1.058030E-02 -1.860245E-05 -1.014653E-02 -1.703372E-05 -1.053471E-02 -1.946614E-05 -1.087794E-02 -1.741794E-05 -1.749138E-02 -4.059625E-05 -1.441949E-02 -4.081297E-05 -2.238698E-02 -8.411387E-05 -1.355243E-02 -2.880517E-05 -2.176689E-02 -7.043906E-05 -1.938423E-02 -5.171647E-05 -1.365868E-02 -3.105929E-05 -1.615560E-02 -3.821091E-05 -1.688664E-02 -4.289252E-05 -1.314826E-02 -2.645963E-05 -1.505920E-02 -3.910868E-05 -1.696322E-02 -4.410507E-05 -1.531505E-02 -2.627391E-05 -1.302530E-02 -2.447578E-05 -2.215989E-02 -5.624695E-05 -1.558271E-02 -3.591163E-05 -1.660587E-02 -4.451639E-05 -2.152716E-02 -6.525487E-05 -1.897151E-02 -5.231568E-05 -1.728826E-02 -5.214345E-05 -1.902678E-02 -5.314163E-05 -2.333937E-02 -8.182246E-05 -9.443854E-03 -1.172248E-05 -1.198026E-02 -2.003714E-05 -2.138685E-02 -6.175227E-05 -1.274599E-02 -2.433959E-05 -1.947534E-02 -5.207291E-05 -1.815170E-02 -4.398794E-05 -3.169585E-02 -1.333543E-04 -1.905286E-02 -4.657423E-05 -1.494275E-02 -3.505332E-05 -1.763876E-02 -4.461835E-05 -1.182033E-02 -2.214931E-05 -1.968821E-02 -5.319218E-05 -1.722391E-02 -3.689380E-05 -1.164039E-02 -2.017520E-05 -1.987702E-02 -4.962563E-05 -1.593272E-02 -4.198443E-05 -1.295575E-02 -3.292363E-05 -1.574293E-02 -3.434465E-05 -2.730586E-02 -8.253402E-05 -2.116215E-02 -5.127586E-05 -1.343828E-02 -2.408890E-05 -1.857254E-02 -4.513774E-05 -1.500919E-02 -3.231350E-05 -1.678659E-02 -3.962936E-05 -1.488856E-02 -2.386764E-05 -1.230601E-02 -2.575268E-05 -2.037392E-02 -5.965465E-05 -1.096474E-02 -1.759636E-05 -2.187484E-02 -6.525702E-05 -1.374639E-02 -2.555749E-05 -1.511590E-02 -3.826384E-05 -1.563929E-02 -3.222315E-05 -1.684288E-02 -4.027516E-05 -1.773599E-02 -6.209617E-05 -1.720006E-02 -3.431594E-05 -1.841885E-02 -4.086225E-05 -1.218119E-02 -2.095533E-05 -1.065430E-02 -1.713440E-05 -1.058773E-02 -1.668419E-05 -1.135705E-02 -1.500764E-05 -1.158632E-02 -2.852635E-05 -8.247777E-03 -1.228385E-05 -1.907771E-02 -4.597570E-05 -1.777609E-02 -4.816332E-05 -1.285738E-02 -2.710713E-05 -1.336306E-02 -2.768885E-05 -7.498631E-03 -1.438567E-05 -1.168505E-02 -2.200300E-05 -8.575921E-03 -8.903420E-06 -6.935145E-03 -9.218014E-06 -9.998062E-03 -1.881829E-05 -8.939471E-03 -1.098615E-05 -7.860596E-03 -1.449285E-05 -1.082459E-02 -1.896980E-05 -5.782585E-03 -5.702033E-06 -1.004504E-02 -2.149248E-05 -7.503097E-03 -1.089878E-05 -6.843525E-03 -9.834532E-06 -1.381318E-03 -8.252352E-07 -5.676320E-03 -7.883845E-06 -5.874523E-03 -3.759183E-06 -4.793821E-03 -2.805686E-06 -6.125800E-03 -6.903423E-06 -8.300434E-03 -1.293197E-05 -8.058716E-03 -1.160479E-05 -6.964643E-03 -9.276538E-06 -3.462172E-03 -2.364550E-06 -4.968406E-03 -4.433251E-06 -6.306240E-03 -6.070974E-06 -6.018210E-03 -7.366216E-06 -8.837800E-03 -9.688936E-06 -5.096909E-03 -4.382163E-06 -3.815130E-03 -6.161058E-06 -4.515200E-03 -4.595497E-06 -6.864810E-03 -1.010895E-05 -6.423468E-03 -9.143165E-06 -9.538660E-03 -1.560977E-05 -1.261072E-02 -2.250707E-05 -1.026530E-02 -1.637414E-05 -9.557506E-03 -1.527890E-05 -8.827930E-03 -1.066139E-05 -5.478962E-03 -5.569868E-06 -9.080187E-03 -1.204024E-05 -1.528742E-02 -3.325338E-05 -1.337087E-02 -1.956015E-05 -1.675398E-02 -4.575869E-05 -1.281954E-02 -3.179463E-05 -8.332353E-03 -1.484699E-05 -1.617850E-02 -3.768574E-05 -1.581638E-02 -5.060008E-05 -1.558998E-02 -3.489775E-05 -1.170539E-02 -1.670388E-05 -9.403406E-03 -1.210849E-05 -6.538447E-03 -7.590433E-06 -1.533222E-02 -3.995585E-05 -9.660974E-03 -1.337453E-05 -1.612761E-02 -3.190924E-05 -1.123730E-02 -1.881522E-05 -6.517842E-03 -9.004602E-06 -1.039422E-02 -1.944508E-05 -1.196688E-02 -2.077099E-05 -1.825266E-02 -5.884867E-05 -1.114412E-02 -1.635734E-05 -6.855502E-03 -9.696697E-06 -7.937283E-03 -1.011203E-05 -1.305061E-02 -2.491232E-05 -2.084992E-02 -5.566232E-05 -9.019271E-03 -1.005494E-05 -1.029368E-02 -1.905328E-05 -1.763980E-02 -4.024339E-05 -9.329184E-03 -1.252705E-05 -1.325489E-02 -2.563636E-05 -1.556775E-02 -3.949834E-05 -2.061223E-02 -6.392049E-05 -1.758113E-02 -3.625999E-05 -1.157256E-02 -2.047838E-05 -8.563192E-03 -1.228712E-05 -1.031763E-02 -1.411955E-05 -1.512631E-02 -4.654173E-05 -1.486827E-02 -2.864290E-05 -2.251974E-02 -5.878585E-05 -1.538325E-02 -2.676876E-05 -1.352613E-02 -3.627305E-05 -1.449237E-02 -3.612781E-05 -1.192626E-02 -2.019597E-05 -1.304918E-02 -2.426503E-05 -1.605822E-02 -3.012824E-05 -1.727927E-02 -3.755550E-05 -9.669506E-03 -1.630871E-05 -1.276773E-02 -2.526258E-05 -1.428968E-02 -3.134862E-05 -1.703682E-02 -4.403612E-05 -1.839993E-02 -4.005997E-05 -1.709877E-02 -3.494229E-05 -1.020568E-02 -2.306756E-05 -1.556313E-02 -2.961997E-05 -1.367798E-02 -2.209767E-05 -1.479845E-02 -2.697536E-05 -1.064351E-02 -1.544937E-05 -1.457069E-02 -3.339049E-05 -1.022585E-02 -1.440893E-05 -1.072359E-02 -1.406891E-05 -2.091105E-02 -5.324749E-05 -1.381809E-02 -3.338254E-05 -1.600746E-02 -3.282400E-05 -1.918686E-02 -4.509327E-05 -1.087716E-02 -1.741352E-05 -1.712809E-02 -3.956314E-05 -1.312095E-02 -1.981242E-05 -1.874899E-02 -4.287445E-05 -1.113725E-02 -2.004136E-05 -7.103716E-03 -7.213595E-06 -1.369370E-02 -3.063256E-05 -9.195487E-03 -1.412638E-05 -1.141322E-02 -1.860950E-05 -1.114463E-02 -1.989362E-05 -1.766608E-02 -3.977019E-05 -1.831950E-02 -5.100972E-05 -9.842311E-03 -1.641174E-05 -1.050669E-02 -1.611304E-05 -9.275886E-03 -1.425314E-05 -1.489107E-02 -2.846318E-05 -1.024738E-02 -1.638704E-05 -1.238766E-02 -2.905937E-05 -8.220882E-03 -1.610701E-05 -7.911660E-03 -1.204791E-05 -6.724074E-03 -8.382502E-06 -7.246664E-03 -1.223989E-05 -9.981199E-03 -1.983647E-05 -7.195641E-03 -1.261848E-05 -5.805501E-03 -6.427362E-06 -7.853739E-03 -1.109259E-05 -5.029358E-03 -4.590158E-06 -7.362545E-03 -9.705721E-06 -6.742269E-03 -5.672589E-06 -8.306759E-03 -1.150294E-05 -2.269532E-03 -1.413152E-06 -5.728846E-03 -6.054291E-06 -6.497853E-03 -7.598936E-06 -5.211040E-03 -7.706367E-06 -1.091775E-02 -2.620541E-05 -7.186930E-03 -7.840316E-06 -5.773406E-03 -6.737773E-06 -8.315747E-03 -1.614189E-05 -1.045710E-02 -1.408567E-05 -1.373927E-02 -2.417114E-05 -4.474588E-03 -2.860895E-06 -7.106756E-03 -8.922176E-06 -1.703428E-02 -3.411039E-05 -7.032210E-03 -5.972986E-06 -7.519022E-03 -9.923714E-06 -1.019763E-02 -1.870985E-05 -1.003939E-02 -1.665677E-05 -5.257180E-03 -7.163497E-06 -6.709259E-03 -1.080672E-05 -6.660210E-03 -8.371462E-06 -1.339388E-02 -2.963406E-05 -2.041319E-02 -6.283530E-05 -1.277136E-02 -2.113278E-05 -1.095487E-02 -1.788661E-05 -1.210895E-02 -2.269317E-05 -9.526669E-03 -1.459758E-05 -1.595135E-02 -4.590455E-05 -1.583142E-02 -3.433698E-05 -1.814067E-02 -5.361094E-05 -2.020117E-02 -5.966829E-05 -1.078165E-02 -2.464395E-05 -1.503699E-02 -3.786272E-05 -1.636813E-02 -3.872799E-05 -2.272579E-02 -7.702949E-05 -1.895617E-02 -5.205980E-05 -1.364788E-02 -2.639491E-05 -1.991314E-02 -7.408716E-05 -1.011963E-02 -1.544567E-05 -1.853803E-02 -4.673643E-05 -1.601464E-02 -3.647742E-05 -2.688432E-02 -8.994718E-05 -1.910229E-02 -4.828596E-05 -1.310107E-02 -2.599395E-05 -2.493961E-02 -8.021464E-05 -2.136141E-02 -5.184829E-05 -2.544806E-02 -7.994724E-05 -1.143679E-02 -1.661591E-05 -1.709579E-02 -4.337367E-05 -2.083317E-02 -5.556329E-05 -1.866022E-02 -4.397347E-05 -3.145206E-02 -1.280431E-04 -2.210382E-02 -5.769121E-05 -1.823923E-02 -4.074602E-05 -1.528594E-02 -3.104999E-05 -1.711154E-02 -4.112452E-05 -1.507762E-02 -2.770618E-05 -2.206514E-02 -6.022082E-05 -2.319277E-02 -5.836530E-05 -1.896072E-02 -4.024144E-05 -1.655441E-02 -4.163720E-05 -1.804406E-02 -4.084019E-05 -2.452803E-02 -7.291599E-05 -2.802970E-02 -1.259325E-04 -2.453139E-02 -7.079239E-05 -2.489486E-02 -6.688553E-05 -2.178711E-02 -7.105053E-05 -1.906738E-02 -4.476745E-05 -2.527667E-02 -8.182112E-05 -2.331217E-02 -6.232971E-05 -2.781953E-02 -9.708263E-05 -1.997547E-02 -4.443113E-05 -2.088515E-02 -5.171598E-05 -2.303205E-02 -8.024769E-05 -1.915503E-02 -4.593806E-05 -2.571317E-02 -8.223527E-05 -1.506654E-02 -3.035107E-05 -2.999022E-02 -1.183624E-04 -2.875220E-02 -1.019916E-04 -1.859536E-02 -4.941826E-05 -2.237740E-02 -6.098459E-05 -1.818345E-02 -4.548133E-05 -2.387148E-02 -8.542723E-05 -1.893980E-02 -4.021031E-05 -2.098013E-02 -5.353962E-05 -2.652625E-02 -8.621445E-05 -1.979268E-02 -5.173051E-05 -2.005599E-02 -5.014567E-05 -1.869207E-02 -4.863434E-05 -2.062895E-02 -5.960259E-05 -2.035386E-02 -4.757091E-05 -1.380341E-02 -2.450580E-05 -1.716354E-02 -4.220694E-05 -1.514915E-02 -2.661478E-05 -9.617277E-03 -1.245420E-05 -1.625088E-02 -3.575586E-05 -1.556949E-02 -3.732096E-05 -1.713751E-02 -3.918991E-05 -1.288808E-02 -2.331234E-05 -1.411636E-02 -2.581158E-05 -8.295504E-03 -1.118839E-05 -1.490088E-02 -3.193897E-05 -1.120118E-02 -1.562213E-05 -1.159281E-02 -1.980721E-05 -1.203548E-02 -2.711369E-05 -1.339573E-02 -2.158602E-05 -1.280581E-02 -2.079765E-05 -1.083998E-02 -1.727408E-05 -1.315255E-02 -2.519274E-05 -1.207379E-02 -2.152665E-05 -1.232904E-02 -2.825538E-05 -1.209938E-02 -2.379986E-05 -7.347293E-03 -8.920021E-06 -1.420050E-02 -2.556068E-05 -1.406290E-02 -2.882913E-05 -1.226796E-02 -2.904134E-05 -1.529742E-02 -3.412784E-05 -9.361135E-03 -1.953641E-05 -7.653780E-03 -9.090398E-06 -1.172034E-02 -1.741493E-05 -6.481510E-03 -6.366134E-06 -1.483462E-02 -3.419849E-05 -7.287071E-03 -9.994231E-06 -7.014536E-03 -8.683589E-06 -3.914638E-03 -3.851978E-06 -1.039507E-02 -1.247058E-05 -1.449371E-02 -3.268737E-05 -6.107315E-03 -1.275657E-05 -5.912533E-03 -5.291900E-06 -1.241975E-02 -2.776459E-05 -1.652474E-02 -3.478228E-05 -9.924557E-03 -2.111611E-05 -1.112655E-02 -2.134337E-05 -1.490879E-02 -4.120682E-05 -1.214873E-02 -1.828276E-05 -1.878471E-02 -4.595384E-05 -1.068338E-02 -2.052816E-05 -9.957982E-03 -1.661273E-05 -8.679245E-03 -1.539340E-05 -7.944462E-03 -1.238828E-05 -9.333064E-03 -1.407498E-05 -2.180639E-02 -5.625519E-05 -2.409216E-02 -8.351837E-05 -2.095008E-02 -5.330117E-05 -2.458431E-02 -7.696318E-05 -1.741223E-02 -4.634669E-05 -2.052947E-02 -5.641630E-05 -2.507271E-02 -7.084493E-05 -2.192019E-02 -5.996923E-05 -1.687601E-02 -3.734411E-05 -2.188351E-02 -5.331644E-05 -2.625531E-02 -8.987505E-05 -1.947839E-02 -5.362737E-05 -2.561506E-02 -8.555702E-05 -3.072429E-02 -1.057779E-04 -2.548154E-02 -8.649311E-05 -2.215408E-02 -5.389914E-05 -2.857258E-02 -9.992187E-05 -2.271191E-02 -6.458178E-05 -3.417289E-02 -1.353676E-04 -2.406069E-02 -7.233156E-05 -2.858289E-02 -1.096000E-04 -3.086685E-02 -1.088635E-04 -1.806766E-02 -4.316705E-05 -2.440571E-02 -6.395626E-05 -3.255341E-02 -1.376111E-04 -4.078794E-02 -1.950454E-04 -2.169319E-02 -5.623674E-05 -2.222088E-02 -7.931181E-05 -3.507566E-02 -1.330312E-04 -3.153876E-02 -1.223922E-04 -3.739825E-02 -1.655348E-04 -3.186914E-02 -1.164407E-04 -3.186332E-02 -1.211760E-04 -3.046668E-02 -1.045865E-04 -2.468913E-02 -7.595312E-05 -2.725403E-02 -9.530282E-05 -3.669370E-02 -1.633028E-04 -4.142607E-02 -2.202378E-04 -2.274887E-02 -6.024427E-05 -2.852673E-02 -1.084379E-04 -3.552692E-02 -1.550998E-04 -1.953889E-02 -4.742931E-05 -4.288258E-02 -2.326284E-04 -3.527647E-02 -1.532875E-04 -3.831735E-02 -1.712470E-04 -3.740668E-02 -1.804477E-04 -3.067443E-02 -1.226235E-04 -2.859755E-02 -9.502065E-05 -3.656012E-02 -1.473474E-04 -4.428469E-02 -2.135422E-04 -3.876237E-02 -1.826793E-04 -3.168779E-02 -1.136526E-04 -4.132746E-02 -1.944335E-04 -3.080999E-02 -1.075137E-04 -3.809598E-02 -1.579372E-04 -3.950419E-02 -1.784657E-04 -5.023062E-02 -3.049706E-04 -4.789752E-02 -2.554387E-04 -3.458880E-02 -1.324150E-04 -4.090067E-02 -1.965130E-04 -3.045883E-02 -1.164732E-04 -3.897593E-02 -1.862204E-04 -1.900547E-02 -4.239429E-05 -2.523518E-02 -8.151515E-05 -3.480501E-02 -1.535823E-04 -2.911328E-02 -1.131135E-04 -3.135787E-02 -1.158315E-04 -2.364659E-02 -7.666160E-05 -3.489798E-02 -1.613478E-04 -3.305825E-02 -1.226465E-04 -3.424037E-02 -1.511504E-04 -3.144976E-02 -1.315971E-04 -2.386686E-02 -9.966283E-05 -2.343488E-02 -7.865295E-05 -1.809482E-02 -3.639503E-05 -1.592339E-02 -3.078924E-05 -3.395399E-02 -1.387775E-04 -2.173542E-02 -6.688037E-05 -1.139408E-02 -1.661367E-05 -1.191973E-02 -1.884978E-05 -2.149843E-02 -5.543388E-05 -2.139730E-02 -5.948238E-05 -1.878719E-02 -3.863865E-05 -2.861748E-02 -9.903233E-05 -1.663769E-02 -3.586183E-05 -2.392378E-02 -7.633777E-05 -1.826846E-02 -4.768962E-05 -1.258024E-02 -2.584217E-05 -1.836655E-02 -4.161069E-05 -1.896044E-02 -4.007711E-05 -1.782079E-02 -3.615894E-05 -1.682346E-02 -3.435373E-05 -1.864611E-02 -4.004514E-05 -2.027124E-02 -4.802356E-05 -1.572197E-02 -4.060890E-05 -1.809973E-02 -5.222844E-05 -8.922954E-03 -1.541312E-05 -1.042804E-02 -1.919810E-05 -1.663952E-02 -3.230801E-05 -1.416041E-02 -3.240599E-05 -1.364911E-02 -2.047968E-05 -1.466030E-02 -2.789488E-05 -7.525078E-03 -8.889694E-06 -6.730764E-03 -9.941085E-06 -1.007468E-02 -1.767697E-05 -1.050555E-02 -1.620042E-05 -8.346548E-03 -1.182646E-05 -9.053361E-03 -1.420984E-05 -1.665200E-02 -5.444887E-05 -1.527178E-02 -2.919176E-05 -1.380005E-02 -2.920152E-05 -9.043029E-03 -1.785555E-05 -1.950145E-02 -4.990311E-05 -1.401098E-02 -2.753310E-05 -1.823652E-02 -4.520948E-05 -1.710659E-02 -4.707810E-05 -1.381860E-02 -3.468506E-05 -1.372395E-02 -3.175759E-05 -1.525561E-02 -3.615913E-05 -1.061450E-02 -1.832455E-05 -2.040145E-02 -5.544400E-05 -2.550363E-02 -8.291428E-05 -1.927840E-02 -6.340108E-05 -1.775966E-02 -3.592996E-05 -1.876698E-02 -5.056466E-05 -1.520416E-02 -3.176693E-05 -2.911719E-02 -1.110393E-04 -2.789335E-02 -1.015992E-04 -2.154244E-02 -6.800841E-05 -2.176042E-02 -6.210896E-05 -2.465235E-02 -8.769146E-05 -2.163089E-02 -6.884278E-05 -4.263944E-02 -2.012458E-04 -3.780523E-02 -1.771907E-04 -3.718152E-02 -1.480234E-04 -3.477776E-02 -1.409494E-04 -3.400758E-02 -1.358091E-04 -2.463564E-02 -6.885284E-05 -3.580510E-02 -1.389221E-04 -2.581734E-02 -7.795599E-05 -4.453340E-02 -2.222774E-04 -3.924298E-02 -2.048002E-04 -2.186414E-02 -7.503195E-05 -2.414346E-02 -6.884988E-05 -4.920381E-02 -2.986041E-04 -4.271226E-02 -2.407998E-04 -3.511456E-02 -1.659456E-04 -3.959546E-02 -1.811704E-04 -4.332790E-02 -2.327770E-04 -3.005794E-02 -1.236765E-04 -4.201285E-02 -1.831068E-04 -3.539806E-02 -1.349359E-04 -4.860033E-02 -2.640914E-04 -3.738028E-02 -1.608258E-04 -3.344288E-02 -1.192143E-04 -3.329781E-02 -1.262633E-04 -5.050402E-02 -3.082255E-04 -6.167912E-02 -4.537041E-04 -4.061325E-02 -2.373203E-04 -4.113180E-02 -2.244264E-04 -4.273661E-02 -2.061457E-04 -3.909923E-02 -1.794019E-04 -4.467948E-02 -2.422984E-04 -3.644554E-02 -1.488516E-04 -6.208616E-02 -4.066650E-04 -5.622731E-02 -3.479864E-04 -3.604649E-02 -1.527817E-04 -4.489847E-02 -2.244948E-04 -4.852333E-02 -2.452380E-04 -5.916579E-02 -3.675786E-04 -5.027889E-02 -3.063063E-04 -5.223329E-02 -3.266355E-04 -5.303921E-02 -3.002831E-04 -4.084190E-02 -2.089059E-04 -4.269058E-02 -1.927344E-04 -4.181196E-02 -1.890866E-04 -4.239920E-02 -2.054052E-04 -4.178606E-02 -2.121443E-04 -3.962721E-02 -1.900681E-04 -3.998106E-02 -1.671101E-04 -4.097110E-02 -1.864628E-04 -5.252376E-02 -2.919653E-04 -4.986589E-02 -2.923184E-04 -4.281919E-02 -2.017141E-04 -5.707825E-02 -3.443945E-04 -4.193701E-02 -1.801946E-04 -3.890873E-02 -1.604416E-04 -2.771300E-02 -8.201460E-05 -4.516255E-02 -2.288159E-04 -3.504308E-02 -1.480297E-04 -3.354671E-02 -1.345202E-04 -4.155997E-02 -1.900709E-04 -2.311887E-02 -6.056166E-05 -4.403743E-02 -2.374715E-04 -1.996468E-02 -5.260666E-05 -3.196737E-02 -1.421833E-04 -4.035771E-02 -1.965928E-04 -3.317174E-02 -1.529423E-04 -2.357781E-02 -6.449390E-05 -2.467934E-02 -6.935734E-05 -4.424222E-02 -2.197069E-04 -3.398377E-02 -1.404692E-04 -2.969392E-02 -9.932175E-05 -2.586642E-02 -8.639774E-05 -2.018938E-02 -4.704545E-05 -2.460053E-02 -8.337921E-05 -2.140944E-02 -5.566819E-05 -1.750162E-02 -4.330128E-05 -1.823667E-02 -3.807392E-05 -2.182322E-02 -5.835666E-05 -1.996510E-02 -4.925786E-05 -2.054306E-02 -5.967285E-05 -2.448060E-02 -6.724552E-05 -2.420255E-02 -7.171101E-05 -2.224533E-02 -7.074407E-05 -2.688010E-02 -1.048025E-04 -1.252593E-02 -1.992438E-05 -1.627058E-02 -3.557197E-05 -1.458375E-02 -2.939085E-05 -6.673846E-03 -7.665690E-06 -1.782098E-02 -4.530371E-05 -1.873366E-02 -5.530746E-05 -1.014089E-02 -1.628821E-05 -9.132953E-03 -1.379610E-05 -1.363905E-02 -2.661815E-05 -1.338513E-02 -2.253429E-05 -8.423240E-03 -1.911938E-05 -1.484012E-02 -4.135636E-05 -1.418073E-02 -3.323365E-05 -1.543051E-02 -2.985655E-05 -1.632770E-02 -3.517623E-05 -2.008031E-02 -5.274018E-05 -1.602450E-02 -3.958879E-05 -1.750372E-02 -3.314152E-05 -1.219742E-02 -2.258004E-05 -1.433533E-02 -3.618336E-05 -9.075804E-03 -1.317139E-05 -7.380199E-03 -7.236358E-06 -1.782556E-02 -3.957064E-05 -1.184192E-02 -2.021154E-05 -2.859581E-02 -1.054928E-04 -2.697349E-02 -9.676496E-05 -2.792217E-02 -1.147611E-04 -1.382301E-02 -2.417383E-05 -2.411827E-02 -7.056685E-05 -1.982700E-02 -4.766108E-05 -2.818071E-02 -9.359800E-05 -2.219449E-02 -6.075282E-05 -2.314416E-02 -6.478789E-05 -2.443285E-02 -8.381567E-05 -2.019536E-02 -5.428133E-05 -1.353132E-02 -2.740754E-05 -4.406952E-02 -2.190081E-04 -3.446584E-02 -1.346151E-04 -3.753184E-02 -1.527576E-04 -3.033111E-02 -1.034049E-04 -2.855894E-02 -9.711291E-05 -2.771557E-02 -8.771393E-05 -3.898957E-02 -1.908877E-04 -4.305288E-02 -1.970134E-04 -3.486097E-02 -1.545961E-04 -3.499273E-02 -1.436152E-04 -3.110132E-02 -1.127757E-04 -3.008751E-02 -1.139676E-04 -6.319815E-02 -4.327893E-04 -5.504272E-02 -3.344552E-04 -4.591545E-02 -2.365710E-04 -3.617316E-02 -1.560924E-04 -5.218885E-02 -3.077972E-04 -4.686114E-02 -2.529342E-04 -5.728060E-02 -4.031273E-04 -3.978176E-02 -1.860198E-04 -5.004767E-02 -3.136544E-04 -4.523333E-02 -2.208929E-04 -3.194586E-02 -1.141458E-04 -3.721301E-02 -1.553134E-04 -7.477681E-02 -6.639195E-04 -6.780397E-02 -4.776195E-04 -6.358469E-02 -4.696106E-04 -6.032980E-02 -4.286567E-04 -5.153943E-02 -2.983568E-04 -5.818770E-02 -4.058262E-04 -6.750249E-02 -5.176461E-04 -5.373447E-02 -3.160363E-04 -6.782408E-02 -5.197564E-04 -5.101341E-02 -3.150794E-04 -3.969145E-02 -1.890305E-04 -4.675755E-02 -2.829176E-04 -4.899174E-02 -2.593746E-04 -7.529462E-02 -5.829369E-04 -5.523513E-02 -3.275402E-04 -3.691494E-02 -1.532620E-04 -6.863824E-02 -5.261979E-04 -5.665568E-02 -3.399426E-04 -5.021140E-02 -2.920406E-04 -5.159035E-02 -3.147743E-04 -8.420431E-02 -7.633948E-04 -6.502238E-02 -5.063282E-04 -4.930238E-02 -2.812855E-04 -4.815381E-02 -2.482742E-04 -4.967200E-02 -2.680540E-04 -5.523567E-02 -3.370328E-04 -4.300524E-02 -2.081672E-04 -3.836521E-02 -1.711214E-04 -5.253824E-02 -3.333353E-04 -4.027059E-02 -1.822925E-04 -3.645004E-02 -1.495178E-04 -3.990377E-02 -1.790132E-04 -4.399597E-02 -2.136921E-04 -4.313937E-02 -2.093007E-04 -3.431599E-02 -1.398795E-04 -4.051219E-02 -1.961233E-04 -4.595652E-02 -2.564444E-04 -3.332030E-02 -1.206481E-04 -4.197497E-02 -2.029057E-04 -3.566567E-02 -1.599693E-04 -3.563813E-02 -1.390992E-04 -3.428900E-02 -1.439048E-04 -3.548443E-02 -1.582734E-04 -3.147837E-02 -1.431168E-04 -3.473859E-02 -1.320531E-04 -3.340003E-02 -1.534631E-04 -2.995214E-02 -1.115961E-04 -3.783601E-02 -1.612451E-04 -2.593349E-02 -7.511302E-05 -2.220229E-02 -5.650585E-05 -2.396506E-02 -6.330344E-05 -2.415591E-02 -7.979178E-05 -3.230518E-02 -1.226469E-04 -3.148292E-02 -1.291525E-04 -2.555369E-02 -7.214626E-05 -2.008785E-02 -5.277321E-05 -2.623915E-02 -1.052699E-04 -1.687230E-02 -3.802212E-05 -1.828669E-02 -5.222647E-05 -2.568728E-02 -1.046345E-04 -1.666034E-02 -3.189735E-05 -1.441649E-02 -2.909234E-05 -1.961081E-02 -5.252583E-05 -1.446604E-02 -2.906063E-05 -2.499966E-02 -7.290861E-05 -2.036936E-02 -5.610925E-05 -9.247556E-03 -1.678837E-05 -1.093088E-02 -2.167681E-05 -1.260502E-02 -2.987668E-05 -9.613002E-03 -1.269981E-05 -1.504319E-02 -4.123453E-05 -1.804155E-02 -4.790967E-05 -1.950375E-02 -5.823817E-05 -1.292954E-02 -2.425508E-05 -9.979565E-03 -1.879915E-05 -1.627001E-02 -4.007960E-05 -1.727217E-02 -3.779588E-05 -1.821599E-02 -4.516560E-05 -1.246029E-02 -2.877178E-05 -7.419932E-03 -1.075442E-05 -1.027139E-02 -1.750906E-05 -6.011548E-03 -5.357981E-06 -1.284150E-02 -2.684216E-05 -7.873217E-03 -1.261811E-05 -3.056254E-02 -1.119101E-04 -2.367459E-02 -7.012832E-05 -3.125473E-02 -1.349511E-04 -2.032722E-02 -6.005633E-05 -1.966372E-02 -4.807430E-05 -1.888280E-02 -4.353141E-05 -3.148229E-02 -1.087028E-04 -2.569052E-02 -8.345601E-05 -1.988235E-02 -5.083043E-05 -3.033509E-02 -1.353984E-04 -2.455111E-02 -8.578087E-05 -2.292969E-02 -6.706042E-05 -3.506638E-02 -1.418820E-04 -2.811805E-02 -8.950254E-05 -3.758364E-02 -1.763474E-04 -4.852969E-02 -3.045767E-04 -3.345491E-02 -1.265446E-04 -3.311976E-02 -1.271997E-04 -4.406586E-02 -2.049053E-04 -3.977663E-02 -1.944792E-04 -3.568273E-02 -1.393831E-04 -4.714003E-02 -2.666571E-04 -3.938142E-02 -1.784684E-04 -3.504464E-02 -1.619498E-04 -6.038764E-02 -4.057914E-04 -5.523867E-02 -3.480079E-04 -5.012020E-02 -2.738532E-04 -5.300843E-02 -3.225930E-04 -4.819845E-02 -2.912996E-04 -4.192723E-02 -2.042929E-04 -5.437230E-02 -3.831173E-04 -4.855340E-02 -2.801897E-04 -5.632430E-02 -3.684549E-04 -3.908351E-02 -1.754220E-04 -3.723203E-02 -1.565670E-04 -3.662475E-02 -1.409549E-04 -7.828360E-02 -6.808841E-04 -6.139852E-02 -4.032303E-04 -6.455776E-02 -4.632098E-04 -4.996191E-02 -2.795507E-04 -5.586957E-02 -3.475409E-04 -4.296598E-02 -2.317524E-04 -6.386330E-02 -4.717762E-04 -5.291090E-02 -3.247736E-04 -5.483498E-02 -3.421555E-04 -4.502506E-02 -2.409819E-04 -5.510776E-02 -3.436300E-04 -4.165980E-02 -1.924264E-04 -5.979906E-02 -3.843900E-04 -5.815532E-02 -3.901796E-04 -6.144432E-02 -4.159903E-04 -5.918684E-02 -3.926095E-04 -7.241076E-02 -5.527725E-04 -5.729097E-02 -3.531500E-04 -5.051843E-02 -2.810907E-04 -5.618582E-02 -3.776148E-04 -5.589932E-02 -3.335647E-04 -6.161520E-02 -4.831295E-04 -5.389348E-02 -3.065669E-04 -4.348189E-02 -2.135964E-04 -4.695822E-02 -2.384098E-04 -6.006602E-02 -3.844395E-04 -4.864361E-02 -2.423012E-04 -4.186798E-02 -1.902022E-04 -4.797983E-02 -2.448734E-04 -4.768596E-02 -2.637688E-04 -4.383760E-02 -2.023880E-04 -3.729270E-02 -2.011170E-04 -4.671060E-02 -2.774443E-04 -4.261256E-02 -2.074667E-04 -3.057615E-02 -1.013174E-04 -3.642349E-02 -1.538488E-04 -2.640419E-02 -8.839937E-05 -5.298488E-02 -3.147305E-04 -2.462926E-02 -7.609382E-05 -3.274348E-02 -1.347060E-04 -4.085845E-02 -2.061636E-04 -3.613681E-02 -1.608827E-04 -3.188424E-02 -1.170448E-04 -3.090210E-02 -1.209556E-04 -4.916591E-02 -2.638816E-04 -3.463680E-02 -1.731202E-04 -2.473796E-02 -8.278777E-05 -2.876733E-02 -1.050578E-04 -2.818020E-02 -9.186488E-05 -2.922451E-02 -9.710630E-05 -2.867494E-02 -1.008386E-04 -2.048136E-02 -5.645393E-05 -2.709023E-02 -9.906565E-05 -2.060958E-02 -6.002022E-05 -2.400813E-02 -7.048793E-05 -2.041445E-02 -5.660380E-05 -3.022382E-02 -1.232007E-04 -2.428404E-02 -7.261848E-05 -1.317267E-02 -4.498520E-05 -1.725417E-02 -4.131436E-05 -1.439809E-02 -2.877223E-05 -1.849952E-02 -3.964099E-05 -1.298598E-02 -2.510194E-05 -1.158199E-02 -1.753824E-05 -2.399736E-02 -7.914398E-05 -1.618716E-02 -3.923219E-05 -1.582299E-02 -3.446241E-05 -1.281460E-02 -2.948723E-05 -1.687823E-02 -3.916635E-05 -1.992356E-02 -5.363759E-05 -9.964687E-03 -2.281351E-05 -9.741073E-03 -1.461704E-05 -1.016266E-02 -1.578045E-05 -1.165241E-02 -1.448412E-05 -1.645559E-02 -3.314741E-05 -1.019874E-02 -1.584348E-05 -1.400560E-02 -2.950132E-05 -1.339261E-02 -2.462337E-05 -9.864617E-03 -2.007031E-05 -1.033312E-02 -1.570664E-05 -1.150186E-02 -1.612123E-05 -8.165735E-03 -9.980334E-06 -1.039922E-02 -2.137334E-05 -7.778314E-03 -1.402972E-05 -2.352819E-02 -7.324745E-05 -1.832670E-02 -5.260061E-05 -1.958916E-02 -4.738463E-05 -2.752632E-02 -1.321234E-04 -1.290240E-02 -2.435598E-05 -1.180814E-02 -1.989960E-05 -1.968230E-02 -4.672576E-05 -2.074128E-02 -5.154692E-05 -1.506303E-02 -2.974396E-05 -2.158432E-02 -6.994225E-05 -2.106432E-02 -6.601892E-05 -1.297999E-02 -2.683746E-05 -4.398209E-02 -2.260240E-04 -3.493420E-02 -1.634600E-04 -3.877993E-02 -1.929775E-04 -2.663088E-02 -8.262555E-05 -2.385591E-02 -7.188146E-05 -2.756789E-02 -8.724472E-05 -4.223824E-02 -2.331366E-04 -3.372408E-02 -1.376633E-04 -2.877054E-02 -1.172152E-04 -2.505284E-02 -6.877934E-05 -2.710121E-02 -9.089126E-05 -2.491989E-02 -7.126133E-05 -4.605415E-02 -2.550818E-04 -3.674502E-02 -1.551214E-04 -3.682502E-02 -1.637234E-04 -4.294065E-02 -2.131753E-04 -3.770825E-02 -1.835164E-04 -3.445084E-02 -1.375944E-04 -3.954845E-02 -1.848016E-04 -4.320951E-02 -2.332661E-04 -2.976462E-02 -1.143727E-04 -3.263580E-02 -1.287108E-04 -4.185045E-02 -1.965114E-04 -3.879064E-02 -1.631517E-04 -6.117745E-02 -4.170051E-04 -5.208900E-02 -2.961117E-04 -5.034441E-02 -2.985461E-04 -4.763203E-02 -2.520770E-04 -4.424593E-02 -2.210065E-04 -4.633482E-02 -2.857246E-04 -6.172917E-02 -4.365884E-04 -4.667374E-02 -2.416468E-04 -4.615839E-02 -2.447158E-04 -4.202865E-02 -1.984881E-04 -3.687271E-02 -1.549029E-04 -3.781817E-02 -1.658791E-04 -5.350156E-02 -3.106556E-04 -5.738403E-02 -3.535711E-04 -5.581047E-02 -3.600168E-04 -5.548481E-02 -3.477589E-04 -5.976117E-02 -4.066921E-04 -3.679728E-02 -1.797632E-04 -4.181607E-02 -2.319380E-04 -4.475783E-02 -2.471295E-04 -5.073065E-02 -2.731166E-04 -4.282973E-02 -2.376864E-04 -3.923270E-02 -1.868782E-04 -3.175293E-02 -1.204289E-04 -3.821514E-02 -1.563696E-04 -4.698886E-02 -2.394623E-04 -4.501447E-02 -2.402396E-04 -3.789686E-02 -1.636683E-04 -4.356985E-02 -2.501184E-04 -3.738072E-02 -1.625968E-04 -3.207025E-02 -1.387594E-04 -3.204040E-02 -1.219128E-04 -4.516239E-02 -2.412503E-04 -4.133319E-02 -1.807484E-04 -2.760180E-02 -8.957336E-05 -4.274635E-02 -2.203768E-04 -3.183938E-02 -1.177784E-04 -3.431517E-02 -1.538918E-04 -3.335945E-02 -1.452163E-04 -3.036081E-02 -1.173248E-04 -3.231608E-02 -1.473817E-04 -3.026666E-02 -1.062646E-04 -2.381248E-02 -6.812346E-05 -2.438669E-02 -7.616674E-05 -2.657091E-02 -8.997086E-05 -2.155185E-02 -7.092421E-05 -2.241945E-02 -5.990905E-05 -3.070897E-02 -1.109960E-04 -2.580881E-02 -7.863309E-05 -2.134721E-02 -6.345767E-05 -3.007460E-02 -1.199346E-04 -2.158487E-02 -5.631137E-05 -2.267038E-02 -6.523479E-05 -2.199756E-02 -6.744627E-05 -1.920160E-02 -4.676740E-05 -1.927293E-02 -5.882526E-05 -1.309800E-02 -2.176798E-05 -1.864318E-02 -4.222760E-05 -2.427004E-02 -7.787837E-05 -2.143559E-02 -5.842615E-05 -1.187245E-02 -3.400806E-05 -1.386855E-02 -2.215090E-05 -1.089761E-02 -1.742663E-05 -1.054008E-02 -1.719743E-05 -1.573092E-02 -2.947697E-05 -1.260841E-02 -2.538616E-05 -9.335769E-03 -1.220699E-05 -9.218607E-03 -1.346226E-05 -1.232919E-02 -2.739036E-05 -1.540769E-02 -3.545632E-05 -1.047417E-02 -1.403218E-05 -8.091074E-03 -9.942405E-06 -9.757397E-03 -1.839030E-05 -1.147311E-02 -2.272680E-05 -6.625367E-03 -9.542469E-06 -1.132951E-02 -2.290402E-05 -1.276799E-02 -2.736073E-05 -1.641171E-02 -4.522620E-05 -1.038484E-02 -2.444781E-05 -1.059856E-02 -2.086366E-05 -1.070727E-02 -3.120073E-05 -9.434079E-03 -2.288235E-05 -1.260589E-02 -2.115523E-05 -8.609571E-03 -1.014235E-05 -1.906718E-02 -4.342750E-05 -1.697807E-02 -3.746587E-05 -1.655549E-02 -3.279717E-05 -2.335945E-02 -8.680066E-05 -1.947075E-02 -4.582833E-05 -2.334564E-02 -6.827484E-05 -1.970475E-02 -5.161446E-05 -2.176597E-02 -8.091171E-05 -1.794831E-02 -4.826888E-05 -1.453865E-02 -2.543285E-05 -2.285340E-02 -7.733631E-05 -1.495227E-02 -3.812970E-05 -2.993202E-02 -1.105328E-04 -2.591986E-02 -7.889731E-05 -2.891690E-02 -1.170195E-04 -2.591958E-02 -8.245187E-05 -2.472591E-02 -6.792489E-05 -1.984583E-02 -4.399055E-05 -2.723781E-02 -1.063286E-04 -2.214049E-02 -6.647832E-05 -1.976025E-02 -4.630788E-05 -2.362519E-02 -9.840049E-05 -2.147637E-02 -5.680267E-05 -1.716604E-02 -3.707514E-05 -3.853916E-02 -1.905886E-04 -3.220009E-02 -1.166545E-04 -3.072451E-02 -1.105417E-04 -3.416322E-02 -1.445852E-04 -3.081335E-02 -1.205464E-04 -2.381824E-02 -7.421006E-05 -2.919176E-02 -1.443329E-04 -3.165320E-02 -1.643449E-04 -2.399334E-02 -7.031311E-05 -2.931290E-02 -1.089751E-04 -2.541529E-02 -9.960904E-05 -2.496511E-02 -9.522684E-05 -4.191717E-02 -2.319644E-04 -4.194175E-02 -2.515421E-04 -4.029489E-02 -2.034800E-04 -2.949880E-02 -1.001309E-04 -3.311240E-02 -2.069653E-04 -3.311074E-02 -1.645850E-04 -2.609443E-02 -7.829184E-05 -2.523310E-02 -7.753633E-05 -3.376196E-02 -1.542562E-04 -3.370657E-02 -1.584460E-04 -2.316126E-02 -6.322560E-05 -2.849745E-02 -1.006036E-04 -4.156928E-02 -1.941410E-04 -3.356649E-02 -1.323048E-04 -3.504110E-02 -1.432793E-04 -4.188246E-02 -2.087133E-04 -2.686062E-02 -1.008920E-04 -3.264472E-02 -1.519956E-04 -3.182824E-02 -1.190821E-04 -3.230472E-02 -1.432567E-04 -3.014385E-02 -1.104329E-04 -3.127630E-02 -1.124605E-04 -3.215046E-02 -1.161615E-04 -3.028866E-02 -1.020886E-04 -3.771125E-02 -1.568073E-04 -3.370873E-02 -1.337798E-04 -4.025498E-02 -1.918052E-04 -2.635483E-02 -7.350768E-05 -2.361243E-02 -7.420144E-05 -3.747673E-02 -2.016310E-04 -2.747199E-02 -8.499093E-05 -3.168249E-02 -1.354519E-04 -2.123972E-02 -5.349966E-05 -2.029422E-02 -4.819609E-05 -2.757353E-02 -9.520625E-05 -3.241854E-02 -1.263115E-04 -2.339411E-02 -8.048390E-05 -2.881367E-02 -9.755501E-05 -2.959500E-02 -1.180648E-04 -2.255464E-02 -6.753101E-05 -4.047075E-02 -1.783640E-04 -3.116618E-02 -1.271595E-04 -2.360487E-02 -7.555159E-05 -2.020519E-02 -5.400702E-05 -2.646647E-02 -7.518930E-05 -2.547209E-02 -9.058727E-05 -1.278101E-02 -2.432873E-05 -2.394671E-02 -7.236070E-05 -1.399890E-02 -2.909745E-05 -1.693268E-02 -4.013852E-05 -1.661474E-02 -3.646989E-05 -1.683699E-02 -3.576439E-05 -1.878683E-02 -4.752490E-05 -1.779186E-02 -5.032257E-05 -1.615460E-02 -3.517429E-05 -1.467092E-02 -2.974604E-05 -1.693919E-02 -3.956534E-05 -1.570365E-02 -3.373372E-05 -1.503755E-02 -3.242993E-05 -1.350241E-02 -2.471502E-05 -1.132128E-02 -2.210554E-05 -1.394835E-02 -2.288474E-05 -7.707010E-03 -1.408651E-05 -1.105673E-02 -1.950348E-05 -1.597153E-02 -2.996363E-05 -1.072279E-02 -1.642956E-05 -9.931403E-03 -1.596209E-05 -3.110131E-03 -1.979116E-06 -1.465778E-02 -2.665954E-05 -8.711776E-03 -1.658595E-05 -3.336279E-03 -3.121041E-06 -1.220546E-02 -2.078425E-05 -1.225808E-02 -2.498648E-05 -5.941201E-03 -5.858248E-06 -8.017505E-03 -9.987361E-06 -1.032012E-02 -1.689346E-05 -1.122116E-02 -2.547015E-05 -7.303253E-03 -1.021165E-05 -1.018508E-02 -1.390217E-05 -6.537846E-03 -1.231905E-05 -3.757225E-03 -2.146236E-06 -6.253529E-03 -8.259456E-06 -8.429652E-03 -1.132331E-05 -6.846152E-03 -1.089548E-05 -1.540905E-02 -4.707146E-05 -1.380105E-02 -2.885252E-05 -1.506988E-02 -3.657193E-05 -1.379370E-02 -2.325176E-05 -9.540645E-03 -2.912938E-05 -1.053361E-02 -1.745746E-05 -8.796644E-03 -1.302715E-05 -9.798877E-03 -1.776907E-05 -1.287457E-02 -2.307421E-05 -1.194402E-02 -2.276268E-05 -7.875525E-03 -1.292927E-05 -5.533880E-03 -9.384723E-06 -1.864321E-02 -4.177596E-05 -1.252461E-02 -2.176958E-05 -1.644030E-02 -4.131255E-05 -1.697179E-02 -3.953043E-05 -9.140492E-03 -1.319242E-05 -9.958402E-03 -1.459665E-05 -1.425287E-02 -3.897232E-05 -1.522358E-02 -3.028879E-05 -1.361118E-02 -2.815573E-05 -1.173677E-02 -3.088583E-05 -1.617474E-02 -3.012921E-05 -1.598127E-02 -3.641752E-05 -1.724536E-02 -3.982285E-05 -2.253691E-02 -6.632574E-05 -2.268227E-02 -5.893945E-05 -2.582333E-02 -9.202078E-05 -1.982485E-02 -6.093449E-05 -1.544437E-02 -3.045457E-05 -1.968776E-02 -5.933245E-05 -2.092753E-02 -6.834686E-05 -1.664629E-02 -4.979724E-05 -1.855281E-02 -6.404621E-05 -2.195650E-02 -6.222690E-05 -2.186198E-02 -5.700014E-05 -2.078639E-02 -4.826480E-05 -2.147531E-02 -5.352146E-05 -2.309193E-02 -6.508444E-05 -2.306719E-02 -7.442212E-05 -2.181171E-02 -6.065432E-05 -2.787754E-02 -1.071646E-04 -2.038266E-02 -6.322425E-05 -2.066861E-02 -6.321760E-05 -2.341755E-02 -6.599464E-05 -1.940287E-02 -5.285084E-05 -2.311451E-02 -6.931733E-05 -2.685211E-02 -9.869681E-05 -2.577665E-02 -9.741583E-05 -2.127713E-02 -7.233352E-05 -3.534780E-02 -1.462501E-04 -2.985988E-02 -1.001501E-04 -2.157060E-02 -5.933210E-05 -2.112991E-02 -6.091345E-05 -1.791858E-02 -4.849939E-05 -2.317059E-02 -5.941629E-05 -1.585209E-02 -3.680922E-05 -1.761272E-02 -4.005327E-05 -2.673873E-02 -8.415236E-05 -2.195005E-02 -7.869690E-05 -2.169063E-02 -6.115181E-05 -1.902034E-02 -4.602942E-05 -2.149684E-02 -6.272837E-05 -2.152317E-02 -5.647475E-05 -1.267811E-02 -2.551472E-05 -1.902212E-02 -4.501454E-05 -1.468929E-02 -2.854665E-05 -2.098348E-02 -5.162857E-05 -1.448437E-02 -3.165154E-05 -1.385842E-02 -2.946322E-05 -2.214565E-02 -6.004180E-05 -1.824698E-02 -3.872549E-05 -1.212354E-02 -2.133339E-05 -2.018308E-02 -5.701150E-05 -2.166624E-02 -5.196544E-05 -2.142212E-02 -5.674884E-05 -1.267848E-02 -2.171626E-05 -1.758911E-02 -4.711902E-05 -1.111921E-02 -2.058872E-05 -1.517506E-02 -2.980149E-05 -1.147226E-02 -1.573079E-05 -1.249264E-02 -2.217903E-05 -1.604063E-02 -3.750625E-05 -1.275295E-02 -2.494568E-05 -1.612605E-02 -3.577658E-05 -1.249864E-02 -3.018969E-05 -1.188510E-02 -2.704321E-05 -1.571000E-02 -3.615816E-05 -1.235323E-02 -2.593348E-05 -1.676586E-02 -4.472755E-05 -1.093806E-02 -1.930162E-05 -1.176929E-02 -2.511180E-05 -1.397747E-02 -2.813515E-05 -9.701315E-03 -1.930872E-05 -1.399983E-02 -3.413054E-05 -1.986885E-02 -5.082098E-05 -8.243555E-03 -1.200852E-05 -1.024429E-02 -1.296572E-05 -1.258003E-02 -1.952799E-05 -1.610829E-02 -3.961341E-05 -1.010586E-02 -1.549208E-05 -1.252095E-02 -2.770018E-05 -8.230588E-03 -1.450505E-05 -8.380929E-03 -1.203824E-05 -8.828715E-03 -1.191588E-05 -6.588527E-03 -7.910780E-06 -6.380189E-03 -6.533479E-06 -5.052056E-03 -5.336338E-06 -3.648351E-03 -2.706990E-06 -2.149471E-03 -1.225876E-06 -9.270100E-03 -1.169691E-05 -1.117400E-02 -2.249063E-05 -5.230590E-03 -4.655893E-06 -7.224676E-03 -1.008003E-05 -3.887357E-03 -3.670860E-06 -3.183273E-03 -1.847498E-06 -3.708170E-03 -2.623818E-06 -5.854425E-03 -1.020941E-05 -5.406569E-03 -5.391988E-06 -9.036302E-03 -1.748353E-05 -8.903194E-03 -1.445005E-05 -9.987482E-03 -2.075751E-05 -8.426663E-03 -1.155563E-05 -8.912136E-03 -1.175066E-05 -4.122838E-03 -3.170046E-06 -4.845177E-03 -4.237971E-06 -6.822194E-03 -1.051328E-05 -4.425000E-03 -4.417976E-06 -7.424172E-03 -9.891741E-06 -4.992950E-03 -5.945799E-06 -7.149030E-03 -1.123994E-05 -4.625444E-03 -5.049047E-06 -1.123851E-02 -2.017630E-05 -1.074541E-02 -1.709195E-05 -1.430110E-02 -3.117294E-05 -9.806637E-03 -1.530391E-05 -1.043812E-02 -1.609521E-05 -1.012866E-02 -1.391247E-05 -1.428192E-02 -2.902409E-05 -1.605416E-02 -3.562493E-05 -9.063095E-03 -1.372032E-05 -9.587205E-03 -1.473939E-05 -9.634515E-03 -1.858518E-05 -1.164975E-02 -2.656325E-05 -1.361864E-02 -2.518422E-05 -1.167329E-02 -2.323748E-05 -1.622385E-02 -3.856234E-05 -1.214097E-02 -2.153842E-05 -1.381854E-02 -2.815505E-05 -1.415211E-02 -4.135908E-05 -1.568971E-02 -3.813496E-05 -1.198123E-02 -2.333564E-05 -8.499425E-03 -1.126897E-05 -1.312625E-02 -3.325212E-05 -1.172860E-02 -2.042689E-05 -1.005348E-02 -1.782865E-05 -1.548579E-02 -3.103766E-05 -1.744521E-02 -3.960003E-05 -1.654740E-02 -3.986988E-05 -1.620467E-02 -3.009003E-05 -1.948116E-02 -5.036150E-05 -1.418148E-02 -2.971887E-05 -1.337833E-02 -2.666872E-05 -1.314218E-02 -2.648418E-05 -1.436798E-02 -2.490823E-05 -9.444986E-03 -1.101269E-05 -1.962001E-02 -8.135189E-05 -1.158154E-02 -1.952295E-05 -1.471099E-02 -3.133120E-05 -1.541812E-02 -3.170497E-05 -1.674531E-02 -4.322938E-05 -1.669392E-02 -3.544709E-05 -1.333115E-02 -3.211381E-05 -1.738951E-02 -4.841020E-05 -1.007222E-02 -1.774930E-05 -1.295078E-02 -2.638113E-05 -1.271717E-02 -2.298976E-05 -1.404483E-02 -2.889248E-05 -1.576832E-02 -3.529377E-05 -1.252846E-02 -2.718789E-05 -2.519173E-02 -8.963887E-05 -1.493179E-02 -3.748831E-05 -1.259822E-02 -2.429153E-05 -1.224327E-02 -1.829117E-05 -1.391862E-02 -2.860704E-05 -8.357253E-03 -1.029121E-05 -1.570825E-02 -3.413707E-05 -1.359733E-02 -2.641606E-05 -1.091443E-02 -1.715332E-05 -8.155749E-03 -1.261821E-05 -1.313846E-02 -2.597075E-05 -8.293564E-03 -1.056976E-05 -1.638901E-02 -3.229628E-05 -1.331850E-02 -3.096114E-05 -1.103350E-02 -1.929035E-05 -1.727217E-02 -4.051979E-05 -9.518809E-03 -1.410510E-05 -1.300800E-02 -2.937228E-05 -1.046353E-02 -1.575334E-05 -1.036019E-02 -1.658144E-05 -8.892217E-03 -1.726775E-05 -9.649910E-03 -1.409080E-05 -1.146930E-02 -2.018867E-05 -8.918398E-03 -1.307570E-05 -1.525733E-02 -3.596673E-05 -1.004009E-02 -1.246514E-05 -1.066698E-02 -2.185894E-05 -7.770912E-03 -1.480934E-05 -7.264717E-03 -8.442828E-06 -6.706343E-03 -6.852573E-06 -5.559456E-03 -4.744752E-06 -5.773360E-03 -7.781275E-06 -1.331078E-02 -3.353599E-05 -8.788678E-03 -1.329146E-05 -4.884040E-03 -4.077409E-06 -8.675118E-03 -1.319086E-05 -4.761159E-03 -3.796641E-06 -5.277064E-03 -5.807731E-06 -1.108365E-02 -1.916299E-05 -5.331867E-03 -3.733672E-06 -7.054526E-03 -6.862094E-06 -5.863290E-03 -8.388015E-06 -7.544134E-03 -1.042553E-05 -5.750484E-03 -5.095339E-06 -5.249358E-03 -3.213161E-06 -7.899479E-03 -9.484436E-06 -4.160278E-03 -4.806702E-06 -7.679996E-03 -2.071836E-05 -6.241972E-03 -1.620756E-05 -5.913948E-03 -7.527048E-06 -4.733716E-03 -5.631878E-06 -2.903451E-03 -2.658722E-06 -3.127420E-03 -2.299870E-06 -2.273717E-03 -1.344135E-06 -6.534306E-03 -1.124316E-05 -7.835003E-03 -1.715904E-05 -4.882363E-03 -4.758963E-06 -3.720325E-03 -3.452423E-06 -1.428452E-03 -1.333526E-06 -3.504443E-03 -2.552735E-06 -8.268492E-03 -1.053438E-05 -9.457152E-03 -1.477101E-05 -4.409644E-03 -4.661365E-06 -5.391744E-03 -4.980226E-06 -7.357835E-03 -8.692158E-06 -4.819563E-03 -3.684180E-06 -7.257471E-03 -8.300854E-06 -8.234387E-03 -1.648552E-05 -7.005187E-03 -8.215133E-06 -8.218179E-03 -1.271584E-05 -4.248638E-03 -4.615897E-06 -6.471659E-03 -7.110986E-06 -8.889291E-03 -1.460347E-05 -8.616060E-03 -1.124291E-05 -8.973876E-03 -1.442105E-05 -6.214996E-03 -1.237961E-05 -6.199460E-03 -8.437599E-06 -2.474487E-03 -1.269623E-06 -1.303002E-02 -3.064014E-05 -1.148543E-02 -2.273454E-05 -1.266333E-02 -2.372659E-05 -1.058814E-02 -2.391393E-05 -5.834966E-03 -9.147127E-06 -5.517822E-03 -5.264691E-06 -1.270359E-02 -2.820747E-05 -1.820335E-02 -4.287032E-05 -1.202094E-02 -2.800408E-05 -7.736254E-03 -1.836141E-05 -6.145051E-03 -6.272679E-06 -7.726439E-03 -1.228446E-05 -1.411190E-02 -2.865658E-05 -6.550872E-03 -6.014982E-06 -2.088300E-02 -7.573466E-05 -1.388048E-02 -3.669556E-05 -1.132008E-02 -1.910843E-05 -1.611954E-02 -3.536212E-05 -1.481933E-02 -3.146401E-05 -1.247993E-02 -2.294126E-05 -1.394123E-02 -2.867543E-05 -1.072461E-02 -1.866919E-05 -8.610956E-03 -1.120688E-05 -8.083860E-03 -8.161992E-06 -1.162751E-02 -1.795366E-05 -9.128039E-03 -1.252646E-05 -9.364221E-03 -1.603445E-05 -8.294106E-03 -1.019170E-05 -5.833363E-03 -4.941650E-06 -9.811611E-03 -1.274458E-05 -1.603475E-02 -3.880395E-05 -1.271422E-02 -2.182851E-05 -1.519349E-02 -3.269445E-05 -9.595042E-03 -1.801667E-05 -7.059973E-03 -7.819618E-06 -5.876271E-03 -1.068936E-05 -1.340147E-02 -3.113903E-05 -4.145261E-03 -3.270808E-06 -1.596720E-02 -3.465819E-05 -1.433346E-02 -2.905578E-05 -8.468040E-03 -1.341062E-05 -1.395194E-02 -2.559614E-05 -1.200470E-02 -1.982352E-05 -1.665933E-02 -3.793148E-05 -1.726359E-02 -3.968046E-05 -6.540447E-03 -5.939253E-06 -8.142400E-03 -1.045929E-05 -6.566817E-03 -8.688594E-06 -1.015592E-02 -1.244647E-05 -1.077665E-02 -1.554617E-05 -1.360651E-02 -3.317478E-05 -1.060123E-02 -1.533418E-05 -3.815593E-03 -2.480255E-06 -9.569339E-03 -1.129499E-05 -9.012545E-03 -1.643164E-05 -1.246360E-02 -3.026280E-05 -8.297915E-03 -9.462041E-06 -5.099837E-03 -5.488747E-06 -8.276566E-03 -1.499072E-05 -3.692279E-03 -3.276555E-06 -8.083217E-03 -1.216780E-05 -9.547609E-03 -1.541880E-05 -1.043999E-02 -1.447586E-05 -9.984558E-03 -1.393147E-05 -6.036500E-03 -1.256268E-05 -5.023445E-03 -4.154969E-06 -7.024538E-03 -1.085504E-05 -7.537608E-03 -1.160621E-05 -5.017595E-03 -4.922120E-06 -5.050436E-03 -4.024516E-06 -3.123518E-03 -1.695608E-06 -3.831129E-03 -3.485286E-06 -5.964101E-03 -9.872984E-06 -3.809889E-03 -3.837033E-06 -4.120333E-03 -3.567476E-06 -3.925178E-03 -5.899336E-06 -3.890602E-03 -8.542757E-06 -6.033356E-03 -7.736141E-06 -4.271392E-03 -3.643602E-06 -2.282046E-03 -1.281394E-06 -6.262911E-03 -1.134696E-05 -4.313813E-03 -4.443331E-06 -1.308832E-03 -4.103970E-07 -2.590108E-03 -2.620429E-06 -5.831777E-03 -4.892875E-06 -5.376268E-03 -5.205758E-06 -9.496856E-03 -1.606537E-05 -7.245952E-03 -7.095242E-06 -7.623819E-03 -1.187689E-05 -5.536252E-03 -5.148443E-06 -1.245396E-02 -2.199505E-05 -7.641760E-03 -1.306388E-05 -1.005116E-02 -1.904677E-05 -1.159156E-02 -2.899326E-05 -1.114868E-02 -2.094752E-05 -1.010147E-02 -1.978005E-05 -8.874213E-03 -1.298622E-05 -1.283785E-02 -2.632677E-05 -5.598145E-03 -4.564302E-06 -4.874451E-03 -6.380741E-06 -4.166868E-03 -4.546806E-06 -5.450652E-03 -4.552973E-06 -9.123569E-03 -1.521157E-05 -1.341420E-02 -2.773663E-05 -9.949075E-03 -1.548877E-05 -1.128600E-02 -1.714535E-05 -9.944157E-03 -1.206624E-05 -9.339838E-03 -1.587210E-05 -1.407135E-02 -3.845557E-05 -1.079969E-02 -1.419090E-05 -1.806763E-02 -5.775082E-05 -1.538811E-02 -3.591506E-05 -9.283522E-03 -1.519392E-05 -8.256501E-03 -1.262631E-05 -1.236476E-02 -1.963613E-05 -2.020990E-02 -5.409171E-05 -1.152596E-02 -2.039197E-05 -1.050303E-02 -2.499041E-05 -1.326414E-02 -2.783213E-05 -7.696971E-03 -9.711977E-06 -1.473705E-02 -2.646008E-05 -1.062292E-02 -1.576562E-05 -1.707377E-02 -4.212601E-05 -8.778679E-03 -1.128995E-05 -9.710118E-03 -1.623481E-05 -7.636475E-03 -1.094355E-05 -1.387905E-02 -2.941626E-05 -1.776651E-02 -4.396460E-05 -1.818565E-02 -4.350858E-05 -1.761749E-02 -4.630235E-05 -2.043671E-02 -6.064648E-05 -1.635160E-02 -4.147100E-05 -1.364022E-02 -2.386011E-05 -1.724650E-02 -5.086651E-05 -1.457393E-02 -3.218203E-05 -1.625704E-02 -4.109869E-05 -1.536770E-02 -3.150971E-05 -1.415214E-02 -2.531338E-05 -1.764117E-02 -3.839917E-05 -1.856292E-02 -4.105079E-05 -1.122011E-02 -2.240362E-05 -1.237537E-02 -1.904481E-05 -1.725511E-02 -3.218693E-05 -1.246019E-02 -2.168729E-05 -2.268477E-02 -6.638152E-05 -1.772582E-02 -4.134691E-05 -1.846727E-02 -4.453692E-05 -2.211594E-02 -6.148331E-05 -1.337994E-02 -2.272968E-05 -1.800735E-02 -4.594283E-05 -1.767634E-02 -3.572802E-05 -2.109287E-02 -7.624418E-05 -2.116135E-02 -5.023945E-05 -1.511244E-02 -3.916543E-05 -2.555283E-02 -8.270634E-05 -2.320248E-02 -6.856995E-05 -1.490210E-02 -3.025554E-05 -1.650536E-02 -3.349063E-05 -2.005340E-02 -6.329046E-05 -1.876604E-02 -4.632276E-05 -2.017935E-02 -5.608622E-05 -1.623543E-02 -3.183867E-05 -1.059288E-02 -1.746867E-05 -1.923413E-02 -5.626395E-05 -1.874482E-02 -5.158196E-05 -1.436557E-02 -3.262805E-05 -1.736130E-02 -4.360560E-05 -2.044766E-02 -5.055246E-05 -1.508312E-02 -3.245600E-05 -1.328001E-02 -2.673879E-05 -1.466660E-02 -2.878429E-05 -1.289951E-02 -2.132152E-05 -1.410955E-02 -2.671457E-05 -1.814074E-02 -4.435357E-05 -2.012953E-02 -5.472686E-05 -1.186784E-02 -2.108638E-05 -1.158902E-02 -2.017687E-05 -9.605924E-03 -1.492077E-05 -1.409567E-02 -2.579784E-05 -1.311103E-02 -2.570267E-05 -1.707665E-02 -4.130920E-05 -1.248159E-02 -2.515719E-05 -2.097524E-02 -5.151201E-05 -1.444457E-02 -2.981175E-05 -1.072187E-02 -1.803695E-05 -9.014009E-03 -1.215827E-05 -9.559055E-03 -1.537581E-05 -1.354384E-02 -2.184405E-05 -4.828517E-03 -6.482158E-06 -6.253387E-03 -5.785292E-06 -1.379191E-02 -2.710641E-05 -1.011815E-02 -1.374848E-05 -1.342278E-02 -3.152030E-05 -8.883639E-03 -1.651249E-05 -1.847885E-02 -6.016422E-05 -8.586243E-03 -1.066056E-05 -6.968205E-03 -8.792141E-06 -1.218017E-02 -2.375039E-05 -4.288567E-03 -2.617468E-06 -6.568856E-03 -6.417620E-06 -9.364388E-03 -1.515485E-05 -7.810927E-03 -9.503941E-06 -1.316444E-02 -2.494672E-05 -8.772821E-03 -1.075467E-05 -9.114583E-03 -1.293064E-05 -5.120610E-03 -5.597666E-06 -1.156077E-02 -2.090644E-05 -1.044752E-02 -1.460984E-05 -4.306774E-03 -7.024156E-06 -6.743680E-03 -9.397053E-06 -1.132063E-02 -2.916783E-05 -9.875394E-03 -1.234227E-05 -8.066518E-03 -1.631648E-05 -1.197445E-02 -2.795662E-05 -1.196930E-02 -2.592654E-05 -1.424965E-02 -2.937215E-05 -9.362177E-03 -1.637802E-05 -1.115631E-02 -2.100489E-05 -6.612368E-03 -1.091592E-05 -1.030811E-02 -2.480048E-05 -1.024176E-02 -1.540918E-05 -8.799976E-03 -1.413045E-05 -1.817266E-02 -5.223457E-05 -1.320418E-02 -2.287606E-05 -1.190482E-02 -2.042598E-05 -1.296875E-02 -2.780267E-05 -1.250433E-02 -2.092242E-05 -1.114237E-02 -1.800945E-05 -1.312112E-02 -2.394975E-05 -1.206217E-02 -2.206129E-05 -1.913237E-02 -5.391475E-05 -2.015987E-02 -4.368668E-05 -1.126423E-02 -1.875823E-05 -1.360231E-02 -2.402648E-05 -1.853506E-02 -4.518491E-05 -1.582011E-02 -3.202477E-05 -1.750058E-02 -4.932715E-05 -1.849790E-02 -5.325631E-05 -2.129000E-02 -5.323882E-05 -1.294333E-02 -2.153410E-05 -2.386151E-02 -7.053393E-05 -2.237759E-02 -6.198345E-05 -1.402168E-02 -3.040550E-05 -2.166707E-02 -7.200843E-05 -1.815377E-02 -4.704586E-05 -2.159074E-02 -9.800484E-05 -2.096789E-02 -5.417603E-05 -2.036776E-02 -5.114163E-05 -1.950805E-02 -5.196224E-05 -1.203115E-02 -2.466652E-05 -2.375017E-02 -7.101139E-05 -2.078435E-02 -4.980028E-05 -1.967736E-02 -5.349609E-05 -1.492202E-02 -3.151061E-05 -2.448505E-02 -7.345642E-05 -2.875745E-02 -9.624049E-05 -1.308936E-02 -2.260928E-05 -1.883770E-02 -5.294121E-05 -2.132133E-02 -6.019067E-05 -2.681408E-02 -8.810170E-05 -1.857403E-02 -3.926673E-05 -1.774032E-02 -4.025585E-05 -2.588771E-02 -8.059759E-05 -2.050194E-02 -4.648784E-05 -2.612192E-02 -8.558295E-05 -1.686319E-02 -3.786866E-05 -2.745753E-02 -9.703052E-05 -2.602614E-02 -7.340705E-05 -2.099702E-02 -6.252305E-05 -2.411550E-02 -6.674417E-05 -2.570206E-02 -6.917677E-05 -2.753425E-02 -1.088979E-04 -2.289782E-02 -6.832742E-05 -1.728790E-02 -4.390010E-05 -2.345865E-02 -7.335296E-05 -1.670224E-02 -4.918814E-05 -2.958698E-02 -1.008389E-04 -2.262155E-02 -8.019776E-05 -2.171260E-02 -5.857256E-05 -2.739550E-02 -9.699654E-05 -1.898108E-02 -5.073772E-05 -2.158139E-02 -5.640212E-05 -2.653056E-02 -9.005949E-05 -2.557757E-02 -8.651930E-05 -1.719263E-02 -3.746877E-05 -1.270461E-02 -2.702019E-05 -2.371990E-02 -6.567867E-05 -2.133774E-02 -5.624387E-05 -2.412439E-02 -8.327847E-05 -2.144516E-02 -5.810134E-05 -2.096771E-02 -5.764847E-05 -2.010218E-02 -6.106688E-05 -2.662466E-02 -1.031716E-04 -2.128503E-02 -6.330504E-05 -2.077576E-02 -5.659759E-05 -1.910625E-02 -4.810183E-05 -1.994507E-02 -5.522830E-05 -1.318359E-02 -2.202071E-05 -1.847673E-02 -3.890771E-05 -1.525363E-02 -3.383373E-05 -2.323360E-02 -7.009641E-05 -2.160465E-02 -6.270896E-05 -2.815837E-02 -9.926554E-05 -2.825700E-02 -1.156243E-04 -1.661438E-02 -3.352935E-05 -1.707558E-02 -4.079662E-05 -1.663970E-02 -5.171770E-05 -1.537161E-02 -3.951696E-05 -1.515887E-02 -2.815234E-05 -1.262479E-02 -2.666049E-05 -2.270831E-02 -7.402779E-05 -1.637425E-02 -3.359896E-05 -1.433044E-02 -3.016015E-05 -1.086052E-02 -2.105095E-05 -1.827948E-02 -5.404440E-05 -1.512356E-02 -4.090325E-05 -1.341869E-02 -3.777277E-05 -1.144273E-02 -2.320403E-05 -1.032338E-02 -2.111004E-05 -1.324432E-02 -2.369582E-05 -1.323267E-02 -2.312589E-05 -7.378365E-03 -1.207116E-05 -1.198900E-02 -2.410816E-05 -1.143776E-02 -1.697429E-05 -5.960596E-03 -5.491388E-06 -8.671020E-03 -1.423578E-05 -1.046649E-02 -1.660152E-05 -1.015412E-02 -1.356611E-05 -4.437919E-03 -4.449282E-06 -8.070532E-03 -1.158768E-05 -1.339134E-02 -2.307637E-05 -1.588497E-02 -3.768975E-05 -9.869781E-03 -2.027492E-05 -1.346984E-02 -2.839713E-05 -1.481565E-02 -2.641963E-05 -1.622974E-02 -3.155688E-05 -1.228654E-02 -2.276535E-05 -9.854382E-03 -2.229720E-05 -8.655941E-03 -1.144096E-05 -8.579998E-03 -1.286624E-05 -1.701319E-02 -3.924030E-05 -9.817319E-03 -1.540490E-05 -2.169451E-02 -7.317248E-05 -2.105716E-02 -5.189702E-05 -1.963335E-02 -5.619116E-05 -2.183187E-02 -6.185293E-05 -1.721212E-02 -3.966296E-05 -1.657518E-02 -3.547912E-05 -1.888518E-02 -5.599282E-05 -1.856419E-02 -5.261571E-05 -2.022215E-02 -6.235701E-05 -1.750049E-02 -3.437263E-05 -2.144519E-02 -5.816976E-05 -1.487741E-02 -2.693460E-05 -1.556861E-02 -3.808581E-05 -2.287702E-02 -6.471426E-05 -1.502995E-02 -3.547384E-05 -2.333943E-02 -7.259310E-05 -1.682037E-02 -3.512266E-05 -1.559563E-02 -3.813310E-05 -2.534274E-02 -7.364335E-05 -2.480122E-02 -7.936460E-05 -1.877264E-02 -4.302495E-05 -2.255108E-02 -6.304951E-05 -1.327871E-02 -2.341276E-05 -1.978158E-02 -5.064958E-05 -2.719711E-02 -8.697999E-05 -3.450441E-02 -1.360084E-04 -2.418992E-02 -8.130715E-05 -2.755861E-02 -9.435699E-05 -2.906789E-02 -1.164895E-04 -2.492886E-02 -9.051357E-05 -2.149004E-02 -5.322652E-05 -1.882200E-02 -4.828092E-05 -3.559788E-02 -1.520518E-04 -2.750436E-02 -8.574229E-05 -2.225856E-02 -5.803244E-05 -2.338675E-02 -7.020780E-05 -3.715161E-02 -1.672352E-04 -2.832183E-02 -9.613959E-05 -3.620891E-02 -1.820751E-04 -1.842315E-02 -4.292893E-05 -3.073714E-02 -1.167359E-04 -2.239778E-02 -6.910113E-05 -3.816869E-02 -1.838537E-04 -3.039700E-02 -1.010395E-04 -2.746450E-02 -9.520787E-05 -2.678376E-02 -8.958685E-05 -1.959265E-02 -4.827447E-05 -2.161190E-02 -5.224194E-05 -2.866820E-02 -9.300929E-05 -3.051657E-02 -1.108463E-04 -2.779434E-02 -9.578374E-05 -2.381065E-02 -7.364073E-05 -3.580671E-02 -1.702522E-04 -3.245610E-02 -1.420184E-04 -3.074561E-02 -1.162297E-04 -2.368174E-02 -7.463994E-05 -3.053229E-02 -1.165041E-04 -2.791292E-02 -9.751321E-05 -1.851477E-02 -4.170606E-05 -2.647316E-02 -8.255669E-05 -2.688714E-02 -9.392494E-05 -3.140666E-02 -1.096021E-04 -2.467545E-02 -7.718465E-05 -1.941157E-02 -5.524811E-05 -3.374306E-02 -1.292663E-04 -2.025089E-02 -5.179623E-05 -2.535741E-02 -7.702579E-05 -2.469316E-02 -7.765177E-05 -2.952585E-02 -9.607704E-05 -2.637948E-02 -7.897857E-05 -2.244297E-02 -6.198303E-05 -2.299365E-02 -6.928750E-05 -2.384571E-02 -7.218845E-05 -3.265249E-02 -1.473318E-04 -2.949982E-02 -1.044208E-04 -2.330464E-02 -7.007243E-05 -1.937666E-02 -4.990461E-05 -1.836576E-02 -3.977508E-05 -2.200706E-02 -5.431158E-05 -1.760216E-02 -3.954597E-05 -2.161653E-02 -5.051231E-05 -2.685593E-02 -8.262522E-05 -2.031027E-02 -5.469024E-05 -1.729977E-02 -3.470083E-05 -2.245610E-02 -6.463192E-05 -2.480332E-02 -6.706820E-05 -1.636383E-02 -3.512895E-05 -1.629117E-02 -3.227987E-05 -1.777456E-02 -3.877314E-05 -1.523888E-02 -2.794713E-05 -1.933720E-02 -5.130630E-05 -2.073569E-02 -5.667785E-05 -2.159324E-02 -5.953356E-05 -2.252773E-02 -7.064923E-05 -1.497171E-02 -3.139235E-05 -1.702700E-02 -3.702921E-05 -1.197831E-02 -2.110040E-05 -1.326288E-02 -2.668205E-05 -9.877691E-03 -1.417188E-05 -9.222468E-03 -1.493126E-05 -1.916119E-02 -5.100381E-05 -1.618530E-02 -3.741295E-05 -9.744935E-03 -1.312151E-05 -4.205073E-03 -5.238984E-06 -1.606532E-02 -3.801359E-05 -1.115862E-02 -2.015015E-05 -1.312318E-02 -3.970688E-05 -1.092582E-02 -1.677629E-05 -8.988789E-03 -1.272128E-05 -1.116462E-02 -1.435361E-05 -1.177363E-02 -2.013606E-05 -1.392896E-02 -3.825189E-05 -7.595272E-03 -1.080161E-05 -1.243058E-02 -1.937258E-05 -8.823743E-03 -1.585993E-05 -1.072892E-02 -2.225554E-05 -9.610737E-03 -1.152464E-05 -7.143175E-03 -1.112162E-05 -9.471167E-03 -1.466213E-05 -1.060489E-02 -1.784667E-05 -2.767925E-02 -9.174943E-05 -1.613735E-02 -3.391468E-05 -1.980520E-02 -6.099070E-05 -2.710790E-02 -1.005842E-04 -1.498945E-02 -3.548209E-05 -2.090399E-02 -6.229284E-05 -1.867828E-02 -5.023418E-05 -2.101525E-02 -5.304849E-05 -1.495603E-02 -3.564927E-05 -2.206499E-02 -8.477764E-05 -1.774373E-02 -4.204463E-05 -1.321048E-02 -2.339091E-05 -3.032303E-02 -1.133561E-04 -2.906158E-02 -1.116010E-04 -1.416547E-02 -3.074243E-05 -2.396880E-02 -6.563656E-05 -2.277934E-02 -6.079700E-05 -1.978949E-02 -5.275993E-05 -2.518782E-02 -7.984951E-05 -2.706826E-02 -9.202956E-05 -2.708490E-02 -9.059865E-05 -1.986295E-02 -4.689709E-05 -2.616568E-02 -8.883803E-05 -2.130847E-02 -6.518411E-05 -2.806912E-02 -8.769554E-05 -3.084102E-02 -1.172123E-04 -2.897371E-02 -1.021030E-04 -2.903836E-02 -1.108727E-04 -2.605433E-02 -8.468280E-05 -2.332233E-02 -6.130579E-05 -3.234471E-02 -1.225845E-04 -3.300429E-02 -1.500123E-04 -2.311117E-02 -6.190932E-05 -2.436504E-02 -7.178823E-05 -3.008481E-02 -1.005979E-04 -1.928369E-02 -4.312116E-05 -3.011679E-02 -1.179304E-04 -4.008683E-02 -1.751489E-04 -3.496459E-02 -1.796935E-04 -3.097461E-02 -1.095044E-04 -2.638565E-02 -8.181552E-05 -2.620917E-02 -8.987429E-05 -3.998881E-02 -1.948994E-04 -3.258728E-02 -1.341640E-04 -2.561706E-02 -9.239575E-05 -2.588589E-02 -8.721515E-05 -2.944746E-02 -1.052164E-04 -2.989662E-02 -1.085775E-04 -4.206933E-02 -1.998885E-04 -4.066845E-02 -1.897463E-04 -3.508215E-02 -1.528988E-04 -3.120069E-02 -1.132167E-04 -3.286119E-02 -1.352262E-04 -2.909519E-02 -9.371026E-05 -3.840859E-02 -1.674324E-04 -2.454802E-02 -8.382699E-05 -3.347874E-02 -1.411597E-04 -3.060526E-02 -1.367041E-04 -3.069666E-02 -1.180094E-04 -2.561383E-02 -8.330685E-05 -2.628522E-02 -7.556832E-05 -3.582384E-02 -1.465406E-04 -2.376316E-02 -6.457049E-05 -2.495648E-02 -7.422669E-05 -3.093179E-02 -1.305765E-04 -2.264932E-02 -6.586890E-05 -2.047598E-02 -6.261296E-05 -1.933007E-02 -4.833006E-05 -3.257759E-02 -1.237865E-04 -2.571050E-02 -9.464525E-05 -2.463103E-02 -7.258362E-05 -2.557654E-02 -9.353236E-05 -2.284662E-02 -6.268018E-05 -2.491527E-02 -7.859483E-05 -1.681318E-02 -3.501371E-05 -1.365219E-02 -2.989006E-05 -2.210617E-02 -7.141867E-05 -1.271132E-02 -2.094510E-05 -1.683888E-02 -3.625752E-05 -2.058113E-02 -5.450372E-05 -1.739717E-02 -3.555630E-05 -1.829530E-02 -4.644023E-05 -1.776594E-02 -4.124796E-05 -1.418883E-02 -2.672278E-05 -1.760442E-02 -4.591128E-05 -1.891750E-02 -4.822430E-05 -2.178972E-02 -6.432900E-05 -1.443029E-02 -3.016588E-05 -2.256303E-02 -6.869229E-05 -2.251806E-02 -6.650662E-05 -1.323995E-02 -2.512378E-05 -1.335985E-02 -2.654692E-05 -1.740401E-02 -4.340090E-05 -1.330095E-02 -2.489342E-05 -1.207888E-02 -2.391548E-05 -1.667832E-02 -4.429778E-05 -1.489741E-02 -3.841273E-05 -1.143220E-02 -2.495364E-05 -1.240317E-02 -2.477660E-05 -1.342275E-02 -2.581056E-05 -1.621941E-02 -4.158232E-05 -1.159374E-02 -2.088416E-05 -9.404397E-03 -1.695010E-05 -1.056534E-02 -1.863945E-05 -1.162004E-02 -2.136658E-05 -1.095144E-02 -1.546737E-05 -1.144118E-02 -2.034439E-05 -1.322456E-02 -2.558634E-05 -1.172292E-02 -1.883806E-05 -8.086459E-03 -8.879405E-06 -9.613483E-03 -1.997653E-05 -9.179038E-03 -1.284128E-05 -1.897153E-02 -6.588307E-05 -1.524499E-02 -3.816344E-05 -1.007550E-02 -2.293895E-05 -1.297928E-02 -3.448976E-05 -6.475985E-03 -7.421175E-06 -7.302236E-03 -9.360854E-06 -1.268448E-02 -2.201962E-05 -1.331579E-02 -2.325496E-05 -1.816213E-02 -4.264316E-05 -1.951988E-02 -5.119100E-05 -1.565522E-02 -3.615086E-05 -2.309450E-02 -9.333193E-05 -1.557690E-02 -3.930051E-05 -9.451777E-03 -1.526280E-05 -2.041329E-02 -5.032056E-05 -2.673356E-02 -9.468703E-05 -1.094269E-02 -1.894088E-05 -1.679176E-02 -3.840079E-05 -1.732446E-02 -4.238174E-05 -1.027564E-02 -2.013019E-05 -1.861457E-02 -4.141552E-05 -2.507166E-02 -6.889370E-05 -2.041729E-02 -4.876339E-05 -2.283941E-02 -6.377266E-05 -1.892643E-02 -4.163099E-05 -2.187765E-02 -5.763946E-05 -2.028538E-02 -6.131503E-05 -2.103645E-02 -5.318838E-05 -1.715798E-02 -3.499249E-05 -1.485800E-02 -3.358359E-05 -1.984948E-02 -5.445579E-05 -1.703301E-02 -4.679668E-05 -3.309820E-02 -1.234499E-04 -2.275776E-02 -6.157529E-05 -3.261448E-02 -1.319771E-04 -2.554946E-02 -8.196680E-05 -2.004888E-02 -4.990133E-05 -1.939965E-02 -6.076153E-05 -2.548646E-02 -8.064466E-05 -2.855104E-02 -1.012305E-04 -2.762007E-02 -1.037910E-04 -1.839340E-02 -4.279463E-05 -1.686751E-02 -4.608015E-05 -2.084644E-02 -5.002926E-05 -4.132950E-02 -1.846233E-04 -3.460120E-02 -1.298466E-04 -3.552467E-02 -1.570092E-04 -2.933106E-02 -9.609808E-05 -2.684190E-02 -7.922498E-05 -2.487139E-02 -6.891792E-05 -3.728495E-02 -1.689194E-04 -2.818457E-02 -8.676068E-05 -3.441368E-02 -1.333471E-04 -2.818973E-02 -1.038355E-04 -2.356477E-02 -6.812284E-05 -2.343339E-02 -6.179023E-05 -4.344270E-02 -2.389724E-04 -4.294905E-02 -2.093287E-04 -3.836620E-02 -1.778263E-04 -2.841149E-02 -8.871119E-05 -4.014563E-02 -1.768024E-04 -2.920772E-02 -1.000217E-04 -2.615172E-02 -8.720279E-05 -2.000501E-02 -4.816703E-05 -4.057421E-02 -1.875221E-04 -2.445887E-02 -8.924764E-05 -2.817821E-02 -8.605351E-05 -2.110986E-02 -5.069715E-05 -2.927821E-02 -9.308711E-05 -3.362175E-02 -1.332596E-04 -3.475808E-02 -1.323338E-04 -3.289085E-02 -1.244729E-04 -3.022584E-02 -1.318809E-04 -3.196364E-02 -1.297968E-04 -1.687072E-02 -3.179809E-05 -1.801683E-02 -4.078604E-05 -2.960756E-02 -1.160952E-04 -3.466058E-02 -1.382880E-04 -2.412524E-02 -9.376449E-05 -3.370586E-02 -1.749860E-04 -1.744924E-02 -4.569761E-05 -2.327075E-02 -7.176336E-05 -2.067060E-02 -5.038568E-05 -2.065122E-02 -5.674893E-05 -1.185396E-02 -1.904589E-05 -1.187338E-02 -1.832962E-05 -1.361451E-02 -2.819447E-05 -1.785195E-02 -4.401066E-05 -2.526233E-02 -8.640741E-05 -1.793604E-02 -5.730915E-05 -1.571041E-02 -3.175367E-05 -1.678219E-02 -3.936420E-05 -1.486918E-02 -3.526965E-05 -2.794130E-02 -1.195339E-04 -1.996768E-02 -7.226779E-05 -1.162384E-02 -2.197081E-05 -2.096325E-02 -5.793563E-05 -1.837867E-02 -4.515139E-05 -1.703731E-02 -3.926907E-05 -1.268651E-02 -2.343106E-05 -1.879725E-02 -4.716744E-05 -1.709910E-02 -3.710250E-05 -1.228622E-02 -3.339394E-05 -1.352711E-02 -2.975058E-05 -1.155424E-02 -1.880536E-05 -1.121092E-02 -2.205103E-05 -1.476077E-02 -3.330714E-05 -1.255099E-02 -2.385469E-05 -1.347481E-02 -2.408221E-05 -1.470344E-02 -2.583766E-05 -9.187814E-03 -1.701394E-05 -1.028524E-02 -2.190585E-05 -1.204921E-02 -2.386486E-05 -1.214004E-02 -1.925520E-05 -1.294814E-02 -2.325545E-05 -1.470310E-02 -3.633457E-05 -7.703457E-03 -8.319661E-06 -9.053019E-03 -1.860099E-05 -3.939164E-03 -3.269741E-06 -9.533908E-03 -1.325293E-05 -1.227483E-02 -2.491268E-05 -1.259791E-02 -2.146362E-05 -4.323047E-03 -3.283543E-06 -9.255709E-03 -2.197638E-05 -4.603184E-03 -3.514783E-06 -4.229364E-03 -6.002727E-06 -1.275699E-02 -2.227133E-05 -1.051975E-02 -1.875691E-05 -1.939046E-02 -4.923847E-05 -1.621043E-02 -4.902401E-05 -1.162276E-02 -2.501804E-05 -1.178308E-02 -2.464996E-05 -1.264103E-02 -2.350170E-05 -1.829675E-02 -4.158987E-05 -1.935990E-02 -4.658558E-05 -2.050484E-02 -5.542682E-05 -1.261518E-02 -2.496199E-05 -2.338316E-02 -6.665179E-05 -1.422276E-02 -2.677276E-05 -1.418978E-02 -3.508840E-05 -3.161101E-02 -1.103014E-04 -2.806809E-02 -9.416094E-05 -1.970337E-02 -5.207680E-05 -2.017517E-02 -5.029958E-05 -2.476977E-02 -9.671590E-05 -1.993423E-02 -5.639950E-05 -2.220619E-02 -5.949033E-05 -2.663071E-02 -8.742719E-05 -1.716007E-02 -3.560277E-05 -1.620846E-02 -3.298124E-05 -2.027814E-02 -5.137992E-05 -2.241055E-02 -6.475298E-05 -3.149111E-02 -1.240574E-04 -3.301990E-02 -1.297806E-04 -2.289529E-02 -7.022820E-05 -2.770187E-02 -1.305531E-04 -2.647167E-02 -8.125885E-05 -2.470047E-02 -6.618469E-05 -1.972532E-02 -5.720249E-05 -2.301743E-02 -6.802664E-05 -1.851738E-02 -4.051694E-05 -1.781820E-02 -3.908008E-05 -2.011234E-02 -4.945371E-05 -1.788427E-02 -4.535953E-05 -3.355984E-02 -1.399308E-04 -3.141513E-02 -1.324421E-04 -3.123214E-02 -1.131961E-04 -2.990237E-02 -1.043368E-04 -2.483001E-02 -7.814014E-05 -2.780841E-02 -9.315514E-05 -2.944866E-02 -1.125594E-04 -3.115948E-02 -1.382235E-04 -3.135984E-02 -1.125014E-04 -2.632324E-02 -9.453811E-05 -3.001476E-02 -1.041868E-04 -2.694256E-02 -8.321200E-05 -2.693560E-02 -7.578608E-05 -3.360780E-02 -1.359544E-04 -3.373802E-02 -1.372586E-04 -2.236018E-02 -6.411192E-05 -2.962695E-02 -1.020105E-04 -2.783038E-02 -9.884369E-05 -2.407145E-02 -7.259162E-05 -2.611296E-02 -9.023141E-05 -3.127878E-02 -1.135229E-04 -2.950226E-02 -9.691197E-05 -2.305590E-02 -6.460450E-05 -2.321268E-02 -7.274626E-05 -2.804961E-02 -9.491270E-05 -2.841803E-02 -1.054470E-04 -2.423205E-02 -7.810874E-05 -2.714164E-02 -9.975157E-05 -2.873229E-02 -1.122814E-04 -2.098758E-02 -5.056677E-05 -2.557067E-02 -8.748635E-05 -2.267297E-02 -8.906984E-05 -2.139317E-02 -5.463244E-05 -2.294894E-02 -7.412557E-05 -1.571457E-02 -3.620884E-05 -2.240494E-02 -5.721050E-05 -2.805329E-02 -9.134972E-05 -3.310961E-02 -1.309241E-04 -1.731055E-02 -3.757453E-05 -1.519094E-02 -3.101001E-05 -3.089642E-02 -1.273235E-04 -2.655794E-02 -1.020322E-04 -1.930391E-02 -4.470231E-05 -1.322122E-02 -2.280479E-05 -2.267352E-02 -6.781380E-05 -2.377301E-02 -7.062640E-05 -1.061766E-02 -1.383149E-05 -1.989374E-02 -6.361786E-05 -2.625067E-02 -9.026084E-05 -2.498518E-02 -8.804371E-05 -2.106620E-02 -5.099756E-05 -1.201370E-02 -2.098230E-05 -2.562363E-02 -8.111943E-05 -1.462361E-02 -2.865648E-05 -2.187381E-02 -5.860668E-05 -1.613482E-02 -4.384305E-05 -1.621606E-02 -3.449398E-05 -1.444365E-02 -3.579161E-05 -1.323646E-02 -2.542031E-05 -1.061139E-02 -1.881978E-05 -8.801940E-03 -1.018150E-05 -1.139983E-02 -2.019736E-05 -1.681598E-02 -3.690065E-05 -1.399493E-02 -3.175563E-05 -1.420691E-02 -2.466458E-05 -1.368415E-02 -2.617814E-05 -4.389391E-03 -3.790342E-06 -8.841774E-03 -1.306452E-05 -6.705949E-03 -6.428293E-06 -3.807333E-03 -3.521598E-06 -8.526487E-03 -1.179686E-05 -6.365036E-03 -6.849920E-06 -9.633887E-03 -1.541102E-05 -1.123781E-02 -1.889506E-05 -6.073970E-03 -7.042592E-06 -5.473005E-03 -4.622656E-06 -9.289202E-03 -1.795737E-05 -1.030725E-02 -2.040465E-05 -6.753476E-03 -7.775016E-06 -5.874996E-03 -7.699447E-06 -4.803223E-03 -5.048987E-06 -9.387232E-03 -2.256112E-05 -6.779777E-03 -7.696560E-06 -7.302784E-03 -1.204717E-05 -1.858153E-02 -4.240154E-05 -1.133429E-02 -1.757188E-05 -1.090884E-02 -1.956959E-05 -1.761310E-02 -4.472462E-05 -1.208597E-02 -2.241660E-05 -8.447260E-03 -1.837826E-05 -2.154735E-02 -7.183466E-05 -1.059584E-02 -1.725144E-05 -1.078223E-02 -1.741743E-05 -1.142825E-02 -1.725056E-05 -8.052096E-03 -1.288141E-05 -8.852506E-03 -1.479325E-05 -1.503791E-02 -2.827810E-05 -1.427595E-02 -2.627358E-05 -1.151486E-02 -1.821048E-05 -1.479919E-02 -3.026089E-05 -1.396424E-02 -2.976716E-05 -1.102878E-02 -1.569768E-05 -1.486600E-02 -4.640833E-05 -2.329305E-02 -6.388242E-05 -1.077778E-02 -2.630229E-05 -1.187595E-02 -2.158652E-05 -1.706939E-02 -3.589833E-05 -9.894219E-03 -1.748099E-05 -2.294330E-02 -6.429613E-05 -2.112393E-02 -5.525797E-05 -1.888943E-02 -4.229674E-05 -1.872573E-02 -5.200290E-05 -2.190997E-02 -6.830515E-05 -1.857860E-02 -5.271689E-05 -1.824118E-02 -4.252719E-05 -1.695109E-02 -4.377846E-05 -1.942043E-02 -4.638640E-05 -2.430706E-02 -8.617790E-05 -1.728181E-02 -4.311630E-05 -1.163790E-02 -2.136880E-05 -2.488767E-02 -7.230908E-05 -2.919997E-02 -9.955761E-05 -2.584993E-02 -1.031623E-04 -2.268255E-02 -6.949158E-05 -3.146416E-02 -1.268057E-04 -2.236165E-02 -6.966628E-05 -2.724737E-02 -9.874601E-05 -2.224496E-02 -7.784128E-05 -2.189895E-02 -6.090239E-05 -1.839473E-02 -4.209614E-05 -2.542360E-02 -8.396121E-05 -2.052856E-02 -4.913619E-05 -3.120344E-02 -1.291172E-04 -2.944557E-02 -1.038017E-04 -3.259220E-02 -1.571837E-04 -2.454004E-02 -8.331616E-05 -2.553435E-02 -9.440752E-05 -2.541943E-02 -9.586937E-05 -2.061350E-02 -7.364042E-05 -2.329153E-02 -9.064116E-05 -2.078416E-02 -4.749189E-05 -2.761182E-02 -8.657370E-05 -2.266317E-02 -6.326775E-05 -2.686321E-02 -1.043542E-04 -2.182754E-02 -7.805811E-05 -2.766205E-02 -9.723951E-05 -1.892390E-02 -5.005671E-05 -2.382207E-02 -6.769044E-05 -2.015930E-02 -6.032256E-05 -1.427037E-02 -3.798052E-05 -1.767507E-02 -6.512871E-05 -2.123882E-02 -4.907487E-05 -2.157816E-02 -6.678135E-05 -1.919870E-02 -5.942855E-05 -2.192776E-02 -5.912113E-05 -1.744859E-02 -5.000179E-05 -1.577374E-02 -3.368332E-05 -2.305821E-02 -6.854360E-05 -2.058939E-02 -5.959718E-05 -1.350163E-02 -3.072943E-05 -1.774684E-02 -4.504160E-05 -1.929554E-02 -5.149838E-05 -1.225057E-02 -1.846451E-05 -1.522995E-02 -3.345735E-05 -1.488842E-02 -2.657892E-05 -1.308637E-02 -2.575083E-05 -1.550443E-02 -4.365385E-05 -1.262294E-02 -2.496948E-05 -2.022153E-02 -5.150955E-05 -2.016439E-02 -5.276144E-05 -1.850133E-02 -4.648369E-05 -9.903588E-03 -1.610212E-05 -1.242472E-02 -2.311415E-05 -1.448322E-02 -3.103193E-05 -1.821292E-02 -6.275309E-05 -1.275608E-02 -5.475363E-05 -1.800193E-02 -4.234061E-05 -8.782455E-03 -1.649077E-05 -1.220656E-02 -2.499398E-05 -1.247528E-02 -3.099809E-05 -4.915298E-03 -5.476965E-06 -9.391788E-03 -1.606380E-05 -6.771266E-03 -8.450336E-06 -5.095855E-03 -3.842657E-06 -1.019612E-02 -1.603701E-05 -1.266368E-02 -2.593740E-05 -1.437121E-03 -9.237680E-07 -7.738730E-03 -1.337549E-05 -1.101810E-02 -1.737730E-05 -3.189798E-03 -4.831494E-06 -8.313307E-03 -1.236384E-05 -4.760766E-03 -2.835247E-06 -8.211101E-03 -1.004626E-05 -4.023937E-03 -3.045420E-06 -3.795398E-03 -3.753905E-06 -6.439348E-03 -6.445882E-06 -8.789930E-03 -9.641461E-06 -1.003210E-02 -1.871561E-05 -7.188383E-03 -7.745644E-06 -8.884373E-03 -1.210321E-05 -4.201731E-03 -3.267512E-06 -6.156152E-03 -6.439386E-06 -6.368503E-03 -6.063000E-06 -5.865149E-03 -6.343581E-06 -8.242843E-03 -1.255409E-05 -6.079907E-03 -8.904171E-06 -1.068165E-02 -1.977482E-05 -9.934550E-03 -1.529904E-05 -9.391801E-03 -1.672164E-05 -9.638027E-03 -1.793124E-05 -1.056323E-02 -2.728241E-05 -7.672750E-03 -1.245311E-05 -5.340667E-03 -9.209395E-06 -1.355760E-02 -6.094725E-05 -8.047003E-03 -9.586050E-06 -1.285221E-02 -3.064011E-05 -1.569140E-02 -3.403460E-05 -1.271345E-02 -2.195068E-05 -1.226525E-02 -2.591890E-05 -1.571067E-02 -3.670153E-05 -1.000122E-02 -2.251836E-05 -1.263608E-02 -2.857491E-05 -1.467989E-02 -3.065952E-05 -1.992801E-02 -5.197568E-05 -1.634631E-02 -3.854791E-05 -9.765387E-03 -1.929348E-05 -1.567478E-02 -4.572326E-05 -1.122681E-02 -1.875141E-05 -1.438219E-02 -2.962331E-05 -2.198487E-02 -5.569638E-05 -1.350017E-02 -2.505385E-05 -1.864402E-02 -5.207299E-05 -1.588104E-02 -4.725574E-05 -1.091009E-02 -1.886410E-05 -2.047245E-02 -6.638244E-05 -1.595713E-02 -4.444025E-05 -1.240157E-02 -1.827292E-05 -8.920440E-03 -1.437145E-05 -1.325339E-02 -2.805692E-05 -1.008187E-02 -1.747750E-05 -1.944508E-02 -6.365499E-05 -2.320316E-02 -7.205046E-05 -2.067013E-02 -4.788913E-05 -1.843860E-02 -4.912723E-05 -2.314076E-02 -7.987697E-05 -2.082200E-02 -6.799905E-05 -1.477196E-02 -2.747397E-05 -1.645001E-02 -3.474675E-05 -2.251395E-02 -7.952533E-05 -1.283424E-02 -2.565340E-05 -1.302741E-02 -2.183293E-05 -1.627063E-02 -3.188570E-05 -1.694690E-02 -4.854666E-05 -1.768424E-02 -4.519650E-05 -1.688309E-02 -3.658427E-05 -2.081183E-02 -4.936469E-05 -1.521899E-02 -3.630188E-05 -1.538105E-02 -4.012152E-05 -1.852161E-02 -4.542222E-05 -2.027891E-02 -7.078559E-05 -1.530632E-02 -4.004295E-05 -1.251099E-02 -2.014674E-05 -1.766586E-02 -3.643771E-05 -1.011259E-02 -1.798254E-05 -1.785577E-02 -4.209205E-05 -1.591733E-02 -2.948407E-05 -1.973149E-02 -5.858390E-05 -2.318672E-02 -6.821666E-05 -1.606927E-02 -3.208169E-05 -1.561903E-02 -3.274947E-05 -8.671178E-03 -1.320312E-05 -1.321121E-02 -2.770105E-05 -1.276830E-02 -2.392358E-05 -8.675945E-03 -1.600673E-05 -1.631955E-02 -3.628609E-05 -1.268176E-02 -2.698295E-05 -1.305170E-02 -3.392622E-05 -1.151833E-02 -2.146481E-05 -1.382454E-02 -2.543511E-05 -1.268190E-02 -2.770093E-05 -1.670138E-02 -4.515019E-05 -1.411501E-02 -2.397072E-05 -1.054121E-02 -1.734424E-05 -1.038572E-02 -1.525222E-05 -1.239423E-02 -1.885637E-05 -8.231991E-03 -1.095003E-05 -1.346736E-02 -2.994113E-05 -1.282791E-02 -2.684630E-05 -1.377004E-02 -3.238869E-05 -1.142596E-02 -1.735764E-05 -1.062508E-02 -1.743282E-05 -1.257942E-02 -2.057274E-05 -1.169000E-02 -2.474569E-05 -6.423798E-03 -8.173196E-06 -7.740555E-03 -1.569990E-05 -8.666292E-03 -1.364526E-05 -1.430519E-02 -3.144468E-05 -1.034424E-02 -1.702524E-05 -1.041966E-02 -1.828082E-05 -7.823260E-03 -1.110455E-05 -7.252199E-03 -9.925677E-06 -2.994718E-03 -1.593375E-06 -1.048984E-02 -2.573976E-05 -5.641360E-03 -5.936595E-06 -5.229774E-03 -7.041393E-06 -9.930813E-03 -1.689201E-05 -4.386542E-03 -4.754619E-06 -5.133633E-03 -4.043150E-06 -3.269722E-03 -1.970563E-06 -4.951504E-03 -6.193676E-06 -4.410157E-03 -4.926957E-06 -8.875217E-03 -1.522029E-05 -6.496616E-03 -8.828653E-06 -5.733530E-03 -7.478095E-06 -4.584225E-03 -3.801824E-06 -5.014833E-03 -4.595598E-06 -4.918988E-03 -9.258105E-06 -5.483056E-03 -9.195257E-06 -5.228430E-03 -7.940306E-06 -5.117645E-03 -7.631754E-06 -5.072391E-03 -5.531082E-06 -3.632197E-03 -2.983079E-06 -4.693965E-03 -5.099544E-06 -2.051996E-03 -1.135888E-06 -7.304764E-03 -1.039220E-05 -3.647755E-03 -4.449912E-06 -3.476959E-03 -2.187942E-06 -9.489533E-03 -2.316279E-05 -5.751162E-03 -8.659685E-06 -4.963073E-03 -5.706592E-06 -6.138111E-03 -1.068804E-05 -9.307217E-03 -1.519475E-05 -4.545925E-03 -6.535861E-06 -8.294344E-03 -1.556852E-05 -7.173393E-03 -9.233319E-06 -1.078215E-02 -1.572789E-05 -9.705333E-03 -3.544244E-05 -7.945812E-03 -1.276101E-05 -1.168294E-02 -2.467022E-05 -6.645644E-03 -7.587545E-06 -5.760001E-03 -9.365634E-06 -8.601051E-03 -1.363162E-05 -8.005982E-03 -1.328267E-05 -1.261419E-02 -3.207736E-05 -5.901262E-03 -6.935112E-06 -6.430185E-03 -9.087951E-06 -6.884844E-03 -8.313889E-06 -4.278770E-03 -3.441959E-06 -1.137804E-02 -2.133967E-05 -1.214381E-02 -2.232652E-05 -1.740437E-02 -3.543180E-05 -1.246386E-02 -2.766736E-05 -1.214083E-02 -1.935442E-05 -1.166031E-02 -2.273794E-05 -1.042912E-02 -2.534376E-05 -1.253440E-02 -2.906078E-05 -3.580466E-03 -2.034018E-06 -9.607729E-03 -1.395640E-05 -9.100903E-03 -1.455039E-05 -5.382398E-03 -1.056575E-05 -1.720209E-02 -4.611390E-05 -1.189486E-02 -2.081478E-05 -2.098921E-02 -5.268336E-05 -1.295792E-02 -2.491469E-05 -1.359035E-02 -2.476233E-05 -1.320672E-02 -2.504384E-05 -1.004322E-02 -1.517085E-05 -6.328234E-03 -7.222517E-06 -7.696931E-03 -8.736384E-06 -9.062335E-03 -1.635044E-05 -1.220397E-02 -2.109811E-05 -9.542900E-03 -1.414586E-05 -2.001020E-02 -5.728709E-05 -1.200225E-02 -1.611148E-05 -1.851644E-02 -5.098601E-05 -1.159430E-02 -2.048997E-05 -1.198809E-02 -2.688531E-05 -1.067777E-02 -1.707832E-05 -1.686877E-02 -4.601130E-05 -1.514223E-02 -3.020548E-05 -9.412452E-03 -1.296937E-05 -8.734687E-03 -1.791696E-05 -7.182753E-03 -7.961564E-06 -7.131070E-03 -8.835775E-06 -1.176780E-02 -2.003672E-05 -1.238591E-02 -1.851917E-05 -1.482210E-02 -4.681620E-05 -8.008500E-03 -8.162099E-06 -1.099128E-02 -1.643104E-05 -1.234719E-02 -2.252478E-05 -9.121398E-03 -1.338217E-05 -9.649799E-03 -1.957300E-05 -1.239326E-02 -2.066867E-05 -7.925470E-03 -9.921111E-06 -6.952410E-03 -1.209167E-05 -1.305189E-02 -2.993481E-05 -1.011683E-02 -1.814412E-05 -9.138673E-03 -1.288657E-05 -9.613647E-03 -1.454996E-05 -9.587432E-03 -1.425997E-05 -4.100970E-03 -3.581979E-06 -6.384398E-03 -9.449653E-06 -5.332770E-03 -4.810910E-06 -8.205597E-03 -1.367429E-05 -4.458035E-03 -3.530187E-06 -3.214674E-03 -1.992488E-06 -6.119990E-03 -6.950277E-06 -4.194752E-03 -3.822292E-06 -7.270772E-03 -8.358483E-06 -7.963665E-03 -1.211727E-05 -1.139690E-02 -2.688370E-05 -1.072253E-02 -1.923075E-05 -9.310029E-03 -2.222401E-05 -6.635931E-03 -6.447355E-06 -6.067077E-03 -9.323989E-06 -6.686810E-03 -6.491688E-06 -7.266522E-03 -7.228635E-06 -2.677445E-03 -2.282809E-06 -7.272519E-03 -9.053976E-06 -5.368115E-03 -6.336538E-06 -3.059467E-03 -2.284551E-06 -3.148000E-03 -2.437724E-06 -3.588594E-03 -3.284908E-06 -4.456313E-03 -7.520958E-06 -2.798347E-03 -2.236317E-06 -6.840217E-03 -9.048482E-06 -1.575769E-03 -9.897286E-07 -2.611268E-03 -1.755955E-06 -1.750700E-03 -1.182162E-06 -2.239940E-03 -2.450046E-06 -1.507196E-03 -1.074090E-06 -6.865521E-03 -7.835832E-06 -2.312288E-03 -2.250952E-06 -4.625802E-03 -5.487129E-06 -2.141186E-03 -9.777142E-07 -1.364855E-03 -9.688473E-07 -3.118005E-03 -3.532909E-06 -2.850409E-03 -1.719105E-06 -3.414722E-03 -2.946427E-06 -5.867545E-03 -6.300551E-06 -3.511602E-03 -3.730751E-06 -2.231751E-03 -2.052805E-06 -2.099977E-03 -1.555011E-06 -2.936833E-03 -2.400849E-06 -5.147373E-03 -6.410685E-06 -9.334636E-03 -1.426974E-05 -5.355177E-03 -5.994759E-06 -5.939796E-03 -1.063177E-05 -5.190027E-03 -5.190207E-06 -5.258137E-03 -4.118191E-06 -6.041649E-03 -6.155598E-06 -5.622082E-03 -4.644624E-06 -1.149290E-02 -2.616444E-05 -7.309708E-03 -8.042562E-06 -3.694461E-03 -3.564990E-06 -6.879292E-03 -1.011779E-05 -9.522458E-03 -1.559720E-05 -5.391999E-03 -4.832231E-06 -5.698037E-03 -5.073533E-06 -1.893957E-03 -1.407429E-06 -7.904603E-03 -1.129256E-05 -5.420913E-03 -6.627464E-06 -6.982381E-03 -6.809893E-06 -6.325870E-03 -7.532835E-06 -4.682244E-03 -3.460830E-06 -6.920599E-03 -8.574244E-06 -3.733359E-03 -3.700527E-06 -4.030359E-03 -3.986131E-06 -5.047907E-03 -4.426148E-06 -9.528005E-03 -1.550618E-05 -7.877900E-03 -1.006685E-05 -9.780723E-03 -1.657015E-05 -4.812077E-03 -4.098229E-06 -7.016687E-03 -7.149177E-06 -4.037284E-03 -3.400182E-06 -3.277155E-03 -2.337977E-06 -6.137543E-03 -6.092367E-06 -6.278125E-03 -9.707219E-06 -2.576720E-03 -3.914988E-06 -4.835272E-03 -7.752895E-06 -6.736014E-03 -7.302508E-06 -6.970854E-03 -6.682760E-06 -6.313642E-03 -5.551521E-06 -7.635449E-03 -8.984939E-06 -8.683849E-03 -1.560378E-05 -7.530787E-03 -9.173765E-06 -1.569516E-02 -3.949851E-05 -1.097068E-02 -2.119987E-05 -7.309184E-03 -7.015811E-06 -8.665715E-03 -1.546974E-05 -7.723895E-03 -1.518562E-05 -4.905466E-03 -4.093288E-06 -1.077564E-02 -2.805109E-05 -8.569399E-03 -1.273736E-05 -1.038612E-02 -1.719585E-05 -7.354212E-03 -8.198097E-06 -9.350739E-03 -1.720908E-05 -4.787259E-03 -6.741535E-06 -7.220875E-03 -8.792305E-06 -5.379919E-03 -5.042148E-06 -8.788109E-03 -1.266781E-05 -7.402327E-03 -7.894813E-06 -4.207623E-03 -3.460121E-06 -7.902663E-03 -9.560483E-06 -5.174573E-03 -4.082169E-06 -1.104658E-02 -2.127916E-05 -5.782523E-03 -5.112492E-06 -3.632634E-03 -2.502751E-06 -5.337278E-03 -4.486802E-06 -4.249421E-03 -4.213447E-06 -7.491058E-03 -9.439118E-06 -5.243136E-03 -5.575342E-06 -1.237618E-02 -2.148757E-05 -8.041605E-03 -1.026055E-05 -6.349704E-03 -1.417430E-05 -6.087425E-03 -8.075635E-06 -4.602367E-03 -3.651645E-06 -4.154919E-03 -5.935728E-06 -1.040123E-02 -1.813267E-05 -8.425233E-03 -1.322959E-05 -5.094732E-03 -6.066657E-06 -3.282128E-03 -2.438795E-06 -4.478721E-03 -5.352957E-06 -4.621930E-03 -3.979448E-06 -3.591134E-03 -3.542812E-06 -3.931582E-03 -3.195193E-06 -7.517289E-03 -1.202563E-05 -4.445629E-03 -3.532948E-06 -5.122199E-03 -4.733178E-06 -6.079088E-03 -5.645343E-06 -5.005001E-03 -5.722868E-06 -4.017636E-03 -3.624033E-06 -3.326000E-03 -2.420695E-06 -3.011641E-03 -3.505638E-06 -2.136977E-03 -8.951049E-07 -1.175447E-03 -4.124064E-07 -7.823514E-03 -1.228293E-05 -4.920698E-03 -4.693144E-06 -3.285795E-03 -2.440402E-06 -4.028141E-03 -3.884837E-06 -2.781317E-03 -1.300197E-06 -3.926044E-03 -3.109193E-06 -4.628411E-03 -5.325271E-06 -4.051196E-03 -3.567334E-06 -3.272251E-03 -4.622968E-06 -3.143217E-03 -2.173404E-06 -2.374311E-03 -1.308003E-06 -1.326934E-03 -9.031223E-07 -3.522915E-03 -4.391282E-06 -5.770000E-04 -1.329958E-07 -2.830130E-03 -3.011060E-06 -2.210339E-03 -1.635883E-06 -3.721215E-03 -3.080210E-06 -6.120484E-03 -5.355595E-06 -3.678377E-03 -3.709180E-06 -2.413835E-03 -1.404139E-06 -5.860060E-03 -6.753555E-06 -6.142222E-03 -6.895111E-06 -4.689827E-03 -4.987858E-06 -3.810291E-03 -3.578451E-06 -4.720787E-03 -7.371870E-06 -1.759885E-03 -1.135197E-06 -4.523542E-03 -5.744713E-06 -4.512130E-03 -5.150402E-06 -8.505535E-03 -9.989819E-06 -8.615921E-03 -1.014660E-05 -6.886961E-03 -6.750505E-06 -6.626919E-03 -8.244527E-06 -9.376957E-03 -1.235456E-05 -9.638288E-03 -1.489772E-05 -1.001130E-02 -1.552242E-05 -1.028076E-02 -1.757757E-05 -3.716261E-03 -3.414503E-06 -1.351126E-02 -2.981345E-05 -7.730660E-03 -1.296080E-05 -8.324008E-03 -1.413367E-05 -9.824794E-03 -1.737391E-05 -8.406562E-03 -1.011462E-05 -6.244264E-03 -9.615840E-06 -5.753008E-03 -5.938129E-06 -1.161932E-02 -1.759635E-05 -7.019897E-03 -6.911798E-06 -1.124973E-02 -2.227076E-05 -9.974498E-03 -1.531239E-05 -1.750036E-02 -3.960636E-05 -1.123801E-02 -2.603078E-05 -6.620195E-03 -8.846067E-06 -8.621539E-03 -1.476285E-05 -1.144148E-02 -2.816625E-05 -9.236578E-03 -2.087006E-05 -1.022756E-02 -2.015506E-05 -8.313712E-03 -1.245193E-05 -8.472316E-03 -1.040768E-05 -1.100682E-02 -1.897584E-05 -7.072576E-03 -7.806879E-06 -8.257296E-03 -1.365708E-05 -8.677246E-03 -1.251818E-05 -1.847630E-03 -1.221029E-06 -3.514354E-03 -2.801550E-06 -4.635307E-03 -4.312440E-06 -1.719934E-02 -3.993958E-05 -1.168750E-02 -1.940685E-05 -1.392387E-02 -2.505551E-05 -9.162097E-03 -2.003276E-05 -1.068024E-02 -1.620043E-05 -6.143827E-03 -6.330015E-06 -9.757303E-03 -1.665448E-05 -1.205259E-02 -2.076304E-05 -1.099561E-02 -1.990285E-05 -8.729352E-03 -1.425139E-05 -5.036499E-03 -3.597216E-06 -4.573901E-03 -4.390016E-06 -1.098170E-02 -1.803805E-05 -1.450456E-02 -2.780429E-05 -6.373863E-03 -6.571288E-06 -9.888037E-03 -1.449978E-05 -1.253128E-02 -2.292463E-05 -1.075201E-02 -1.610392E-05 -8.884084E-03 -1.322461E-05 -5.357264E-03 -5.936993E-06 -1.493177E-02 -2.673706E-05 -5.699430E-03 -5.340117E-06 -8.188668E-03 -1.253943E-05 -4.838650E-03 -3.385865E-06 -1.000094E-02 -1.476818E-05 -1.063068E-02 -1.693667E-05 -9.830500E-03 -1.503630E-05 -1.025245E-02 -1.763545E-05 -1.028864E-02 -1.849793E-05 -5.900779E-03 -6.170864E-06 -1.177015E-02 -2.226737E-05 -7.509689E-03 -8.719533E-06 -1.206431E-02 -2.678780E-05 -9.200857E-03 -1.643527E-05 -5.468133E-03 -4.453812E-06 -7.516784E-03 -9.212924E-06 -1.111732E-02 -1.394083E-05 -1.179677E-02 -1.966452E-05 -4.112066E-03 -2.360474E-06 -4.867401E-03 -6.026552E-06 -8.104035E-03 -1.092048E-05 -1.016367E-02 -1.245298E-05 -8.572029E-03 -1.314727E-05 -5.230427E-03 -4.291571E-06 -1.462827E-02 -3.660743E-05 -1.133693E-02 -1.987800E-05 -8.632273E-03 -1.741700E-05 -9.505339E-03 -1.209742E-05 -3.350003E-03 -1.830051E-06 -1.189483E-02 -1.823139E-05 -6.269531E-03 -9.062971E-06 -5.745106E-03 -7.814173E-06 -5.494288E-03 -5.220575E-06 -8.224322E-03 -1.417410E-05 -7.485116E-03 -7.578271E-06 -4.217646E-03 -3.209044E-06 -9.597899E-03 -1.579356E-05 -9.222350E-03 -1.143785E-05 -5.917673E-03 -5.975846E-06 -4.191188E-03 -2.824383E-06 -5.746277E-03 -5.928494E-06 -5.146451E-03 -4.826427E-06 -3.536845E-03 -2.903999E-06 -2.348669E-03 -2.151234E-06 -7.673915E-03 -1.147821E-05 -4.006830E-03 -3.592361E-06 -4.896990E-03 -5.179793E-06 -5.024089E-03 -5.234216E-06 -6.039638E-03 -6.322254E-06 -8.201689E-03 -1.116771E-05 -6.614252E-03 -1.021009E-05 -4.191696E-03 -4.388316E-06 -1.128526E-02 -1.976083E-05 -1.067513E-02 -1.823942E-05 -3.764982E-03 -3.222515E-06 -3.948813E-03 -4.451513E-06 -1.000152E-02 -2.107330E-05 -6.164282E-03 -1.724834E-05 -1.006014E-02 -2.134032E-05 -1.286695E-02 -3.067989E-05 -8.978723E-03 -1.251581E-05 -5.346415E-03 -5.350269E-06 -3.635013E-03 -4.204044E-06 -6.583641E-03 -8.886395E-06 -6.112499E-03 -7.100313E-06 -9.075416E-03 -1.361298E-05 -9.360748E-03 -1.479673E-05 -1.287873E-02 -2.436676E-05 -1.196275E-02 -1.944035E-05 -9.130004E-03 -1.555860E-05 -9.992520E-03 -1.245497E-05 -1.115802E-02 -1.670908E-05 -1.081540E-02 -1.882462E-05 -1.372827E-02 -2.757409E-05 -8.020036E-03 -1.222038E-05 -6.290610E-03 -4.837074E-06 -1.576319E-02 -3.661568E-05 -1.430139E-02 -3.954353E-05 -1.550808E-02 -5.413485E-05 -9.529567E-03 -2.562847E-05 -1.252063E-02 -2.284038E-05 -8.998915E-03 -1.107600E-05 -1.128710E-02 -3.131513E-05 -8.894334E-03 -1.612799E-05 -9.936476E-03 -1.499512E-05 -1.085220E-02 -1.879083E-05 -7.842398E-03 -1.147755E-05 -9.478975E-03 -1.366773E-05 -8.870185E-03 -1.264668E-05 -1.265677E-02 -3.003173E-05 -7.082798E-03 -9.455651E-06 -6.207587E-03 -1.035866E-05 -9.389246E-03 -1.904336E-05 -6.809780E-03 -1.110927E-05 -1.415613E-02 -3.324858E-05 -1.411282E-02 -2.597041E-05 -1.427512E-02 -3.295595E-05 -1.943942E-02 -5.877560E-05 -8.220965E-03 -9.356934E-06 -9.250583E-03 -1.365956E-05 -1.656914E-02 -3.475091E-05 -1.843152E-02 -4.655130E-05 -1.153837E-02 -1.618003E-05 -1.196430E-02 -2.260049E-05 -1.575201E-02 -2.932265E-05 -1.575583E-02 -3.216253E-05 -1.342670E-02 -3.092689E-05 -1.018784E-02 -1.786160E-05 -1.303515E-02 -2.169915E-05 -1.219880E-02 -3.353411E-05 -7.032946E-03 -7.709601E-06 -1.229650E-02 -2.705058E-05 -1.615409E-02 -3.472477E-05 -1.821028E-02 -3.933712E-05 -1.470364E-02 -2.795706E-05 -1.050280E-02 -2.133231E-05 -1.154231E-02 -1.968046E-05 -7.645500E-03 -1.039514E-05 -1.741509E-02 -3.584004E-05 -8.821919E-03 -1.428153E-05 -1.857457E-02 -4.195598E-05 -1.552507E-02 -2.892265E-05 -7.183282E-03 -9.228195E-06 -1.217604E-02 -1.939061E-05 -1.541421E-02 -3.334972E-05 -2.052820E-02 -5.660936E-05 -9.353019E-03 -1.426621E-05 -1.251082E-02 -2.228447E-05 -1.368721E-02 -2.531714E-05 -1.226667E-02 -2.368414E-05 -1.371101E-02 -2.448795E-05 -1.201033E-02 -2.393841E-05 -1.280636E-02 -2.115640E-05 -1.264839E-02 -2.387771E-05 -9.055229E-03 -1.568024E-05 -9.856570E-03 -1.373965E-05 -1.373503E-02 -2.764304E-05 -1.700784E-02 -3.483410E-05 -1.212809E-02 -2.883883E-05 -1.598449E-02 -4.084533E-05 -1.457711E-02 -2.808561E-05 -1.586485E-02 -3.242222E-05 -1.605131E-02 -4.105521E-05 -1.119495E-02 -1.615746E-05 -1.324399E-02 -2.727755E-05 -9.867968E-03 -1.269902E-05 -1.261254E-02 -2.302293E-05 -1.153152E-02 -1.778319E-05 -9.627863E-03 -1.562429E-05 -9.050432E-03 -2.011089E-05 -1.012233E-02 -1.405672E-05 -8.911922E-03 -1.231699E-05 -1.264744E-02 -3.182267E-05 -1.122935E-02 -1.396398E-05 -1.004271E-02 -2.482202E-05 -7.894125E-03 -1.026568E-05 -8.738637E-03 -1.294773E-05 -1.219349E-02 -2.177467E-05 -9.967898E-03 -1.619041E-05 -7.763622E-03 -1.314523E-05 -7.889504E-03 -1.517342E-05 -7.877888E-03 -9.676691E-06 -7.292674E-03 -8.328724E-06 -9.035083E-03 -1.302638E-05 -9.363679E-03 -1.575034E-05 -9.640810E-03 -1.648917E-05 -6.094059E-03 -5.041308E-06 -4.386721E-03 -4.583987E-06 -8.186442E-03 -1.162059E-05 -6.547204E-03 -5.040030E-06 -4.382851E-03 -3.779716E-06 -4.722787E-03 -2.981327E-06 -1.235870E-02 -2.314605E-05 -1.222127E-02 -2.292500E-05 -7.743975E-03 -1.242313E-05 -5.687154E-03 -5.021930E-06 -7.628599E-03 -1.334325E-05 -8.144837E-03 -9.544871E-06 -8.964376E-03 -1.242765E-05 -9.619105E-03 -1.533853E-05 -1.084215E-02 -2.414197E-05 -6.098310E-03 -6.403053E-06 -3.971375E-03 -2.559046E-06 -4.956486E-03 -4.314077E-06 -1.650323E-02 -3.308582E-05 -1.785233E-02 -4.022948E-05 -1.226233E-02 -2.222264E-05 -1.324548E-02 -2.290739E-05 -1.170726E-02 -2.043035E-05 -1.128481E-02 -1.783746E-05 -1.446854E-02 -2.465804E-05 -1.308709E-02 -2.086517E-05 -1.532165E-02 -3.175587E-05 -1.176741E-02 -2.528693E-05 -6.104662E-03 -5.418027E-06 -5.028482E-03 -7.038340E-06 -1.452720E-02 -2.907362E-05 -2.155983E-02 -5.793543E-05 -8.953378E-03 -1.144318E-05 -1.193284E-02 -1.941045E-05 -1.898089E-02 -4.676936E-05 -8.078140E-03 -1.008669E-05 -1.345743E-02 -3.010294E-05 -1.166065E-02 -2.971259E-05 -2.140319E-02 -6.942386E-05 -1.156518E-02 -2.123401E-05 -1.063148E-02 -1.679318E-05 -1.035058E-02 -1.786819E-05 -1.141576E-02 -1.488341E-05 -2.132304E-02 -6.407400E-05 -1.417013E-02 -2.428688E-05 -1.578758E-02 -4.383560E-05 -1.510669E-02 -4.330783E-05 -1.061421E-02 -2.120867E-05 -9.836246E-03 -1.836620E-05 -1.170301E-02 -2.304010E-05 -2.297562E-02 -7.378766E-05 -2.077496E-02 -6.096800E-05 -8.479570E-03 -1.315595E-05 -1.334700E-02 -2.778150E-05 -1.518804E-02 -2.768676E-05 -1.665283E-02 -3.264844E-05 -1.337650E-02 -2.908404E-05 -1.642169E-02 -3.787016E-05 -1.532468E-02 -3.092775E-05 -1.264533E-02 -1.889367E-05 -1.570062E-02 -2.982615E-05 -1.201853E-02 -1.991814E-05 -1.956945E-02 -4.268136E-05 -1.749406E-02 -3.890385E-05 -9.761579E-03 -1.266596E-05 -1.131974E-02 -1.669105E-05 -1.583139E-02 -3.408051E-05 -1.813736E-02 -4.024179E-05 -1.749162E-02 -4.075339E-05 -1.806084E-02 -4.998400E-05 -1.798603E-02 -3.527089E-05 -1.363365E-02 -2.545698E-05 -1.735765E-02 -3.680633E-05 -1.313196E-02 -2.758452E-05 -1.257866E-02 -2.792705E-05 -1.371026E-02 -2.875442E-05 -1.449637E-02 -2.956474E-05 -1.184945E-02 -2.021992E-05 -1.160263E-02 -1.677863E-05 -1.486874E-02 -2.727812E-05 -1.334215E-02 -2.696922E-05 -8.375076E-03 -1.127780E-05 -1.398722E-02 -2.987500E-05 -1.431399E-02 -2.337988E-05 -1.685216E-02 -4.010946E-05 -1.220900E-02 -2.279807E-05 -1.359371E-02 -3.406479E-05 -1.497337E-02 -3.514338E-05 -1.077240E-02 -1.570437E-05 -1.286688E-02 -2.067034E-05 -1.804016E-02 -3.897670E-05 -1.720304E-02 -3.923736E-05 -1.248667E-02 -2.229239E-05 -9.872479E-03 -1.547272E-05 -1.404898E-02 -3.940008E-05 -1.102828E-02 -2.118933E-05 -9.527731E-03 -1.232685E-05 -1.183452E-02 -2.230399E-05 -1.235818E-02 -2.095622E-05 -9.045793E-03 -1.310065E-05 -7.573693E-03 -7.912407E-06 -7.098140E-03 -1.002223E-05 -1.087704E-02 -1.644644E-05 -1.403508E-02 -2.293868E-05 -1.102953E-02 -2.108622E-05 -1.278029E-02 -2.765609E-05 -1.000153E-02 -1.489998E-05 -1.023204E-02 -1.425642E-05 -1.077781E-02 -1.616312E-05 -1.504135E-02 -3.226364E-05 -8.290904E-03 -1.302393E-05 -1.081631E-02 -1.596914E-05 -1.061779E-02 -1.936956E-05 -9.609920E-03 -1.233187E-05 -7.536017E-03 -8.104937E-06 -1.064514E-02 -1.960743E-05 -4.303700E-03 -3.157059E-06 -4.544730E-03 -3.063284E-06 -9.403522E-03 -1.530342E-05 -6.146303E-03 -5.481247E-06 -5.504300E-03 -4.029062E-06 -2.514628E-03 -2.046696E-06 -1.150234E-02 -3.434888E-05 -6.476274E-03 -8.282595E-06 -5.180114E-03 -8.533421E-06 -6.593161E-03 -7.470575E-06 -1.087271E-02 -2.875725E-05 -1.114108E-02 -1.774790E-05 -9.707234E-03 -2.320447E-05 -7.474544E-03 -7.620487E-06 -1.189904E-02 -1.770896E-05 -8.306981E-03 -1.023805E-05 -1.044243E-02 -2.358835E-05 -7.956950E-03 -1.442236E-05 -6.383279E-03 -9.306381E-06 -6.540012E-03 -7.870617E-06 -7.547221E-03 -8.818582E-06 -8.118902E-03 -1.018402E-05 -1.219458E-02 -2.121863E-05 -9.183066E-03 -1.021558E-05 -8.537042E-03 -2.163043E-05 -9.801780E-03 -1.896248E-05 -7.436543E-03 -6.348631E-06 -8.783038E-03 -1.450508E-05 -1.198218E-02 -2.299991E-05 -1.176673E-02 -1.772108E-05 -7.610905E-03 -1.295193E-05 -1.236441E-02 -2.279242E-05 -1.374811E-02 -2.984764E-05 -8.276450E-03 -9.063020E-06 -2.838721E-02 -8.556398E-05 -1.876318E-02 -4.502643E-05 -1.545136E-02 -3.024495E-05 -1.307062E-02 -3.391324E-05 -1.321284E-02 -2.975134E-05 -1.195812E-02 -2.014099E-05 -2.398471E-02 -7.682355E-05 -1.699635E-02 -4.513757E-05 -1.109010E-02 -1.505508E-05 -1.463044E-02 -3.130849E-05 -1.445299E-02 -3.424691E-05 -1.847738E-02 -4.339745E-05 -2.269521E-02 -6.754400E-05 -1.622681E-02 -3.412820E-05 -1.867140E-02 -4.737811E-05 -1.704633E-02 -5.070683E-05 -2.137995E-02 -5.989756E-05 -1.262222E-02 -2.579396E-05 -1.649755E-02 -3.278397E-05 -1.021540E-02 -1.333464E-05 -1.399361E-02 -4.091195E-05 -1.481283E-02 -2.778259E-05 -1.110529E-02 -1.543650E-05 -1.370454E-02 -2.585161E-05 -2.187939E-02 -5.698664E-05 -2.156023E-02 -5.655243E-05 -1.819754E-02 -4.650955E-05 -1.667214E-02 -4.523740E-05 -1.212974E-02 -1.755527E-05 -1.664077E-02 -4.676917E-05 -1.598420E-02 -3.367421E-05 -2.197091E-02 -6.311844E-05 -1.554809E-02 -4.350026E-05 -1.662573E-02 -3.639737E-05 -1.377054E-02 -2.979629E-05 -1.718171E-02 -6.738915E-05 -2.224715E-02 -5.208199E-05 -2.028701E-02 -5.025768E-05 -2.346558E-02 -7.283542E-05 -2.047816E-02 -5.352208E-05 -2.103499E-02 -5.936660E-05 -1.795967E-02 -4.651152E-05 -2.451667E-02 -7.714718E-05 -2.018245E-02 -4.706972E-05 -1.870240E-02 -5.089247E-05 -1.414303E-02 -2.510243E-05 -1.249731E-02 -1.910688E-05 -1.461191E-02 -2.931018E-05 -1.772779E-02 -3.502831E-05 -2.405954E-02 -7.243269E-05 -1.698120E-02 -5.235943E-05 -1.363172E-02 -2.557442E-05 -2.085610E-02 -5.559729E-05 -1.434576E-02 -2.498955E-05 -2.151921E-02 -5.863979E-05 -1.804978E-02 -3.738678E-05 -1.626456E-02 -3.204521E-05 -1.416110E-02 -2.454304E-05 -1.349966E-02 -2.225683E-05 -1.376360E-02 -2.288533E-05 -1.304562E-02 -2.360964E-05 -1.204823E-02 -2.235548E-05 -1.581808E-02 -3.833344E-05 -1.458683E-02 -2.424983E-05 -1.532417E-02 -3.313140E-05 -1.674514E-02 -3.698941E-05 -8.820684E-03 -1.237269E-05 -1.325954E-02 -2.839297E-05 -1.346247E-02 -2.329594E-05 -1.218804E-02 -2.010088E-05 -7.816904E-03 -8.061895E-06 -1.115974E-02 -1.481199E-05 -1.126424E-02 -1.437812E-05 -1.155465E-02 -2.043504E-05 -1.330918E-02 -2.482809E-05 -1.359646E-02 -2.349457E-05 -6.879034E-03 -6.482253E-06 -1.025078E-02 -1.436298E-05 -1.124296E-02 -1.766927E-05 -9.157794E-03 -1.732026E-05 -1.080917E-02 -1.759748E-05 -1.224046E-02 -1.895136E-05 -1.132499E-02 -1.940702E-05 -1.055316E-02 -1.421109E-05 -6.950077E-03 -8.886009E-06 -1.146153E-02 -2.328053E-05 -6.534133E-03 -9.046637E-06 -5.113551E-03 -7.352574E-06 -1.096783E-02 -1.762871E-05 -8.670928E-03 -1.642712E-05 -6.666016E-03 -7.936419E-06 -4.024813E-03 -3.317441E-06 -6.604655E-03 -6.471414E-06 -7.218922E-03 -7.914816E-06 -7.543650E-03 -1.006296E-05 -8.390292E-03 -1.280688E-05 -6.833212E-03 -9.885211E-06 -8.859184E-03 -1.491876E-05 -4.271802E-03 -4.619779E-06 -8.415017E-03 -1.758541E-05 -7.880304E-03 -1.207340E-05 -6.190265E-03 -5.244062E-06 -1.255358E-02 -3.409848E-05 -4.588111E-03 -6.615112E-06 -7.290138E-03 -8.053715E-06 -2.708550E-03 -1.222054E-06 -7.971324E-03 -1.019545E-05 -2.186309E-03 -3.012755E-06 -1.730168E-02 -4.007549E-05 -9.437870E-03 -1.374155E-05 -8.710815E-03 -1.058748E-05 -6.876864E-03 -1.161077E-05 -1.183718E-02 -2.088043E-05 -1.317392E-02 -2.144719E-05 -1.202134E-02 -2.244800E-05 -1.219063E-02 -1.871706E-05 -9.457262E-03 -1.576600E-05 -8.456836E-03 -1.009365E-05 -6.722846E-03 -7.231603E-06 -9.056257E-03 -1.228372E-05 -1.680554E-02 -5.472386E-05 -1.583876E-02 -4.084512E-05 -1.451889E-02 -2.656784E-05 -1.154750E-02 -2.200804E-05 -8.960773E-03 -1.608168E-05 -1.021117E-02 -2.175200E-05 -1.537603E-02 -3.295291E-05 -1.346321E-02 -3.199823E-05 -1.020297E-02 -2.083570E-05 -1.574785E-02 -3.797866E-05 -1.224712E-02 -2.543224E-05 -1.213857E-02 -2.596422E-05 -1.978514E-02 -5.572712E-05 -1.721724E-02 -3.343383E-05 -1.917708E-02 -6.017423E-05 -1.746870E-02 -4.670195E-05 -1.601664E-02 -3.757776E-05 -1.391434E-02 -2.787908E-05 -2.112923E-02 -6.179734E-05 -1.494974E-02 -3.147270E-05 -2.027112E-02 -5.409774E-05 -1.762825E-02 -3.716705E-05 -1.490183E-02 -2.636325E-05 -1.144233E-02 -1.895260E-05 -2.252480E-02 -6.008716E-05 -2.061068E-02 -4.967689E-05 -1.978565E-02 -5.823807E-05 -1.627207E-02 -3.508510E-05 -2.308648E-02 -7.339685E-05 -9.920567E-03 -1.588060E-05 -1.582116E-02 -3.710173E-05 -1.359849E-02 -3.693990E-05 -2.449553E-02 -7.939873E-05 -1.712995E-02 -3.401990E-05 -1.578519E-02 -2.835653E-05 -1.996773E-02 -5.153308E-05 -1.784633E-02 -3.372557E-05 -2.328886E-02 -7.016669E-05 -1.908795E-02 -5.601183E-05 -2.149293E-02 -6.345938E-05 -2.432779E-02 -7.634443E-05 -2.394049E-02 -6.577991E-05 -1.506740E-02 -3.094281E-05 -1.388336E-02 -2.886613E-05 -1.614618E-02 -3.561899E-05 -1.595134E-02 -4.065708E-05 -1.340027E-02 -2.204671E-05 -1.472267E-02 -2.861240E-05 -1.790210E-02 -5.856300E-05 -2.646480E-02 -1.056654E-04 -1.880864E-02 -4.142515E-05 -1.426154E-02 -2.963840E-05 -1.165132E-02 -2.176252E-05 -1.428324E-02 -2.725319E-05 -1.588976E-02 -3.970327E-05 -1.833160E-02 -4.559784E-05 -1.772585E-02 -4.748240E-05 -1.848953E-02 -5.090661E-05 -1.272374E-02 -2.030829E-05 -1.412613E-02 -3.146328E-05 -1.649479E-02 -4.133012E-05 -1.209661E-02 -4.450673E-05 -1.369084E-02 -2.392580E-05 -1.531641E-02 -3.089017E-05 -1.580566E-02 -3.194323E-05 -1.132108E-02 -1.399526E-05 -8.190342E-03 -9.145143E-06 -7.902353E-03 -1.504796E-05 -1.258132E-02 -2.292738E-05 -6.958024E-03 -9.709387E-06 -1.037667E-02 -1.407859E-05 -1.201319E-02 -2.053522E-05 -9.379406E-03 -1.510952E-05 -1.279685E-02 -2.736611E-05 -1.191802E-02 -2.186093E-05 -6.155316E-03 -6.209415E-06 -8.817944E-03 -1.322568E-05 -7.497837E-03 -1.365620E-05 -9.976490E-03 -1.734874E-05 -7.558291E-03 -1.424385E-05 -8.801002E-03 -1.425950E-05 -9.075301E-03 -1.401503E-05 -5.681746E-03 -5.798447E-06 -4.827386E-03 -3.466370E-06 -5.884691E-03 -5.754861E-06 -1.211858E-02 -2.621006E-05 -5.629512E-03 -6.112612E-06 -5.768978E-03 -5.711093E-06 -1.075576E-02 -1.954724E-05 -5.977668E-03 -7.957209E-06 -6.775985E-03 -8.582096E-06 -3.503043E-03 -2.684132E-06 -8.113430E-03 -1.099167E-05 -8.263729E-03 -1.412028E-05 -3.781179E-03 -3.287824E-06 -8.368219E-03 -9.803361E-06 -1.068347E-02 -1.390398E-05 -1.118234E-02 -1.591023E-05 -1.016006E-02 -2.761365E-05 -6.634695E-03 -7.415821E-06 -1.042368E-02 -1.700083E-05 -1.024339E-02 -1.630692E-05 -5.465831E-03 -6.271754E-06 -1.117655E-02 -1.998616E-05 -8.708982E-03 -1.145629E-05 -3.321055E-03 -3.386533E-06 -8.951176E-03 -1.175568E-05 -7.413974E-03 -1.358203E-05 -1.289235E-02 -2.359140E-05 -9.817553E-03 -1.518261E-05 -9.879433E-03 -1.602972E-05 -1.177378E-02 -2.259438E-05 -5.796294E-03 -6.245744E-06 -1.138092E-02 -2.136416E-05 -8.927027E-03 -9.348267E-06 -9.673957E-03 -1.246216E-05 -1.280715E-02 -4.429778E-05 -8.808327E-03 -1.178528E-05 -7.125501E-03 -7.483806E-06 -4.620428E-03 -9.310180E-06 -1.680437E-02 -3.451199E-05 -2.026938E-02 -4.346902E-05 -1.635252E-02 -5.026111E-05 -1.278583E-02 -2.192134E-05 -1.301566E-02 -2.384432E-05 -9.286694E-03 -1.400657E-05 -1.107901E-02 -1.953576E-05 -1.150656E-02 -2.102378E-05 -1.772830E-02 -3.480088E-05 -1.063150E-02 -1.401509E-05 -1.374475E-02 -2.299888E-05 -6.867995E-03 -1.027748E-05 -1.580376E-02 -3.847030E-05 -1.668637E-02 -3.953893E-05 -1.442844E-02 -3.008408E-05 -1.827058E-02 -4.753438E-05 -1.440759E-02 -3.206648E-05 -1.592968E-02 -4.677348E-05 -1.718273E-02 -3.488836E-05 -1.688712E-02 -4.196255E-05 -2.047044E-02 -4.959256E-05 -1.306218E-02 -3.057713E-05 -8.848692E-03 -1.833823E-05 -1.117548E-02 -2.553563E-05 -2.169142E-02 -6.306137E-05 -2.218276E-02 -5.572871E-05 -1.802302E-02 -4.705313E-05 -1.782656E-02 -4.017437E-05 -1.925947E-02 -4.703183E-05 -1.641263E-02 -3.693267E-05 -1.516396E-02 -3.126646E-05 -1.512145E-02 -3.336386E-05 -1.579023E-02 -3.449473E-05 -1.368503E-02 -3.144328E-05 -1.108096E-02 -1.983330E-05 -1.447670E-02 -3.832266E-05 -1.831886E-02 -3.928136E-05 -1.893457E-02 -5.869250E-05 -1.764892E-02 -5.005397E-05 -1.637340E-02 -3.702753E-05 -9.686698E-03 -1.449037E-05 -1.006947E-02 -1.933484E-05 -1.884484E-02 -4.561680E-05 -1.468883E-02 -2.792875E-05 -1.670400E-02 -3.477624E-05 -1.632153E-02 -3.402425E-05 -9.187335E-03 -1.053828E-05 -9.985824E-03 -1.585776E-05 -1.303759E-02 -3.027649E-05 -1.872005E-02 -5.130980E-05 -1.633753E-02 -4.260466E-05 -1.020425E-02 -1.707335E-05 -1.320758E-02 -2.695180E-05 -1.208449E-02 -3.007055E-05 -1.286574E-02 -2.373357E-05 -1.095090E-02 -2.877553E-05 -1.692473E-02 -4.961965E-05 -1.190920E-02 -2.375507E-05 -5.682089E-03 -4.636856E-06 -1.035844E-02 -1.997872E-05 -9.666688E-03 -1.483243E-05 -1.613905E-02 -3.984840E-05 -1.572095E-02 -3.368762E-05 -1.108904E-02 -1.539438E-05 -1.486260E-02 -4.070529E-05 -1.042750E-02 -1.813263E-05 -1.042360E-02 -1.689881E-05 -8.718623E-03 -1.199955E-05 -1.039440E-02 -1.674301E-05 -5.162509E-03 -6.408708E-06 -9.563193E-03 -1.362142E-05 -6.648598E-03 -1.021485E-05 -1.122742E-02 -1.540873E-05 -7.837929E-03 -1.128828E-05 -1.114590E-02 -2.553030E-05 -1.141215E-02 -2.510840E-05 -1.152836E-02 -2.344713E-05 -7.971937E-03 -1.506387E-05 -1.248527E-02 -2.125446E-05 -6.066628E-03 -9.574143E-06 -1.087280E-02 -1.688717E-05 -9.550524E-03 -1.250483E-05 -5.306519E-03 -4.846453E-06 -7.512202E-03 -8.651766E-06 -7.508820E-03 -8.634705E-06 -5.185887E-03 -4.163304E-06 -1.379038E-02 -3.492367E-05 -9.235196E-03 -1.206055E-05 -1.392051E-02 -3.803496E-05 -7.049846E-03 -9.147756E-06 -5.323140E-03 -4.281730E-06 -8.229124E-03 -1.548991E-05 -7.235167E-03 -1.441034E-05 -2.366009E-03 -3.874657E-06 -5.945679E-03 -1.067197E-05 -5.871383E-03 -5.656813E-06 -9.732147E-03 -2.269675E-05 -6.582049E-03 -7.833573E-06 -3.066363E-03 -3.098185E-06 -5.796032E-03 -6.625438E-06 -8.122368E-03 -9.655803E-06 -1.121766E-02 -1.750086E-05 -1.036527E-02 -1.842391E-05 -5.944076E-03 -6.439480E-06 -2.283818E-03 -1.352210E-06 -1.446587E-03 -7.807258E-07 -4.944507E-03 -3.694344E-06 -3.281169E-03 -2.925608E-06 -9.286754E-03 -1.260048E-05 -1.272772E-02 -2.464058E-05 -1.270753E-02 -3.173555E-05 -1.419952E-02 -2.835999E-05 -9.671107E-03 -1.686465E-05 -9.583433E-03 -1.323773E-05 -1.186931E-02 -2.163029E-05 -1.267789E-02 -2.021594E-05 -8.275560E-03 -9.163723E-06 -1.062420E-02 -1.977462E-05 -1.198470E-02 -1.979838E-05 -1.324773E-02 -2.853129E-05 -1.727253E-02 -3.432691E-05 -1.381997E-02 -2.842333E-05 -1.578301E-02 -3.356518E-05 -1.555696E-02 -3.183947E-05 -8.166265E-03 -8.629223E-06 -1.747785E-02 -4.250397E-05 -9.541135E-03 -1.246077E-05 -1.393808E-02 -3.012112E-05 -1.209324E-02 -2.429593E-05 -1.079402E-02 -2.325836E-05 -1.374417E-02 -2.491779E-05 -9.500289E-03 -1.572888E-05 -1.222769E-02 -2.456217E-05 -1.097825E-02 -1.938425E-05 -1.410107E-02 -2.407486E-05 -2.024375E-02 -6.980050E-05 -1.220648E-02 -3.245536E-05 -1.137633E-02 -1.667373E-05 -1.038617E-02 -1.405080E-05 -1.243797E-02 -2.413125E-05 -9.998308E-03 -1.605906E-05 -8.805567E-03 -1.128015E-05 -1.388695E-02 -3.039013E-05 -1.242352E-02 -2.040627E-05 -2.645008E-02 -8.679965E-05 -2.076456E-02 -5.640973E-05 -1.805209E-02 -4.120924E-05 -1.246120E-02 -3.006639E-05 -1.810150E-02 -4.756486E-05 -1.472448E-02 -3.309142E-05 -2.571400E-02 -8.648041E-05 -1.341319E-02 -3.280431E-05 -1.535941E-02 -4.819536E-05 -2.373309E-02 -7.918529E-05 -5.757795E-03 -4.733061E-06 -1.174264E-02 -2.108284E-05 -1.884131E-02 -4.721518E-05 -1.750610E-02 -4.223243E-05 -1.716739E-02 -3.617002E-05 -1.252851E-02 -2.099071E-05 -1.388277E-02 -3.109337E-05 -1.350362E-02 -3.082057E-05 -1.238489E-02 -3.728424E-05 -9.966253E-03 -2.035860E-05 -2.285240E-02 -8.446864E-05 -1.327084E-02 -3.045931E-05 -1.193699E-02 -2.204142E-05 -6.923219E-03 -9.602029E-06 -1.838247E-02 -4.807008E-05 -1.863076E-02 -4.604209E-05 -1.334000E-02 -2.761396E-05 -1.141315E-02 -2.474696E-05 -2.286809E-02 -1.083380E-04 -1.645875E-02 -3.520343E-05 -1.229791E-02 -2.380600E-05 -1.284486E-02 -2.254139E-05 -1.854605E-02 -4.752272E-05 -1.049692E-02 -1.983824E-05 -7.207727E-03 -7.286730E-06 -1.686364E-02 -3.977916E-05 -1.314115E-02 -2.189974E-05 -1.520236E-02 -3.635654E-05 -1.096706E-02 -2.475645E-05 -7.932651E-03 -1.085523E-05 -1.515150E-02 -4.556316E-05 -1.171402E-02 -3.284784E-05 -1.087897E-02 -1.567310E-05 -8.199381E-03 -9.564718E-06 -9.456870E-03 -1.207744E-05 -8.827517E-03 -1.658191E-05 -5.512807E-03 -6.038391E-06 -8.573999E-03 -1.207656E-05 -1.047145E-02 -1.674083E-05 -9.666379E-03 -1.231732E-05 -1.046000E-02 -1.782331E-05 -6.009504E-03 -6.261797E-06 -1.111917E-02 -1.768100E-05 -1.105060E-02 -1.934982E-05 -5.280218E-03 -7.191057E-06 -7.637218E-03 -9.728555E-06 -1.009144E-02 -1.219856E-05 -4.974619E-03 -4.499916E-06 -6.589686E-03 -1.040697E-05 -7.787208E-03 -1.023212E-05 -6.068811E-03 -5.842725E-06 -3.416649E-03 -3.146550E-06 -9.213350E-03 -2.154615E-05 -6.752158E-03 -9.801770E-06 -4.758057E-03 -6.649209E-06 -6.129868E-03 -8.342508E-06 -2.783932E-03 -2.140712E-06 -6.308493E-03 -1.039901E-05 -2.249137E-03 -1.153739E-06 -2.514780E-03 -1.593412E-06 -6.018183E-03 -8.965827E-06 -3.234291E-03 -2.042484E-06 -7.860270E-03 -1.035245E-05 -3.414591E-03 -2.249770E-06 -7.941000E-03 -1.449758E-05 -3.591791E-03 -2.245391E-06 -7.807797E-03 -1.011270E-05 -7.726893E-03 -1.478217E-05 -2.506930E-03 -2.954554E-06 -5.955023E-03 -7.260418E-06 -5.294809E-03 -8.225926E-06 -2.802166E-03 -1.996795E-06 -2.404798E-03 -1.266950E-06 -4.125341E-03 -2.979146E-06 -7.417991E-03 -8.566910E-06 -8.158248E-03 -1.230927E-05 -7.976311E-03 -1.332178E-05 -8.873852E-03 -1.480843E-05 -9.373684E-03 -1.259336E-05 -8.214068E-03 -1.186084E-05 -6.962685E-03 -7.715598E-06 -8.834013E-03 -1.972166E-05 -5.435947E-03 -4.590835E-06 -5.487949E-03 -5.939754E-06 -6.678491E-03 -8.355182E-06 -4.058912E-03 -5.880001E-06 -1.360573E-02 -2.671641E-05 -1.143610E-02 -2.018223E-05 -7.702740E-03 -1.433952E-05 -5.873725E-03 -6.789166E-06 -1.088086E-02 -3.437425E-05 -7.089361E-03 -1.461407E-05 -8.765624E-03 -1.242854E-05 -9.453645E-03 -1.575322E-05 -1.001462E-02 -1.448625E-05 -1.282490E-02 -2.290074E-05 -8.545890E-03 -1.273760E-05 -7.387390E-03 -9.140356E-06 -1.399357E-02 -2.449459E-05 -1.337581E-02 -3.113825E-05 -1.423915E-02 -2.729711E-05 -6.580885E-03 -8.347839E-06 -7.779718E-03 -1.007558E-05 -7.480792E-03 -1.083253E-05 -1.275448E-02 -2.722719E-05 -1.292106E-02 -2.421066E-05 -9.755948E-03 -1.426055E-05 -9.117272E-03 -1.368142E-05 -7.455531E-03 -8.688003E-06 -1.042236E-02 -1.801425E-05 -1.296287E-02 -2.809397E-05 -1.390180E-02 -2.674920E-05 -1.265490E-02 -3.041327E-05 -1.269961E-02 -2.824134E-05 -1.133938E-02 -1.625519E-05 -9.821144E-03 -2.178670E-05 -1.530578E-02 -3.585772E-05 -1.299672E-02 -2.588612E-05 -1.544212E-02 -3.143850E-05 -8.347818E-03 -1.132876E-05 -1.393101E-02 -2.890996E-05 -6.639867E-03 -7.587375E-06 -1.839132E-02 -4.637735E-05 -1.188258E-02 -1.953879E-05 -1.588672E-02 -3.134987E-05 -1.425154E-02 -2.751603E-05 -4.920276E-03 -4.432356E-06 -1.374206E-02 -2.842285E-05 -1.673110E-02 -4.601232E-05 -1.254973E-02 -2.188833E-05 -6.444727E-03 -5.222041E-06 -1.023529E-02 -1.572480E-05 -1.087382E-02 -1.692895E-05 -9.038702E-03 -1.572012E-05 -1.398299E-02 -2.818260E-05 -8.766186E-03 -1.494609E-05 -1.321841E-02 -2.007819E-05 -1.562133E-02 -3.892744E-05 -8.289134E-03 -1.177987E-05 -8.947084E-03 -1.094585E-05 -1.594810E-02 -3.949297E-05 -1.285384E-02 -2.278617E-05 -5.689452E-03 -7.280228E-06 -9.766401E-03 -2.148390E-05 -8.496573E-03 -8.437729E-06 -7.991945E-03 -9.550933E-06 -9.608813E-03 -1.425597E-05 -1.052303E-02 -1.935336E-05 -8.548009E-03 -1.333735E-05 -7.337588E-03 -9.975447E-06 -1.423505E-02 -3.258201E-05 -1.136654E-02 -2.510870E-05 -7.860115E-03 -8.206414E-06 -8.309608E-03 -1.504702E-05 -1.110051E-02 -2.051470E-05 -6.172688E-03 -9.409184E-06 -9.740436E-03 -1.437599E-05 -8.997021E-03 -1.150131E-05 -1.279849E-02 -3.206319E-05 -1.028663E-02 -1.505898E-05 -1.122879E-02 -1.673337E-05 -8.223903E-03 -9.720008E-06 -8.464761E-03 -1.103940E-05 -6.670166E-03 -6.071848E-06 -4.620811E-03 -6.527856E-06 -3.824735E-03 -3.340845E-06 -5.634323E-03 -5.012909E-06 -3.166012E-03 -3.619323E-06 -9.167802E-03 -1.056621E-05 -3.221327E-03 -1.773076E-06 -5.412502E-03 -5.413007E-06 -6.702745E-03 -8.187361E-06 -4.863392E-03 -3.807791E-06 -4.405641E-03 -4.058186E-06 -6.131083E-03 -7.250341E-06 -4.913764E-03 -5.744987E-06 -4.588314E-03 -3.202328E-06 -6.804591E-03 -8.479426E-06 -7.252910E-03 -8.758909E-06 -4.312950E-03 -3.434388E-06 -1.807777E-03 -1.380521E-06 -4.671070E-03 -5.538033E-06 -7.067950E-03 -1.174764E-05 -2.930719E-03 -1.441738E-06 -1.279222E-03 -1.078804E-06 -3.507572E-03 -5.821750E-06 -9.678721E-03 -2.476852E-05 -2.874671E-03 -2.470595E-06 -2.182691E-03 -1.629987E-06 -3.621537E-03 -9.191521E-06 -1.740159E-03 -6.544183E-07 -3.203873E-03 -3.602845E-06 -2.890800E-03 -2.526106E-06 -3.068561E-03 -4.213711E-06 -6.078860E-03 -7.760574E-06 -7.287103E-03 -7.524310E-06 -7.509754E-03 -2.547783E-05 -2.646412E-03 -2.157075E-06 -6.255289E-03 -6.947406E-06 -4.941751E-03 -7.943248E-06 -9.224779E-03 -1.410566E-05 -4.906800E-03 -4.350073E-06 -7.923221E-03 -1.421559E-05 -2.900094E-03 -1.652857E-06 -3.445014E-03 -1.996755E-06 -2.978919E-03 -3.704572E-06 -8.310828E-03 -1.128557E-05 -8.914816E-03 -1.105293E-05 -6.453823E-03 -7.530365E-06 -8.529848E-03 -1.250596E-05 -1.241639E-02 -1.968019E-05 -3.654989E-03 -2.852818E-06 -6.194753E-03 -4.637962E-06 -7.168410E-03 -9.747482E-06 -7.074135E-03 -8.723001E-06 -3.088414E-03 -2.165114E-06 -4.736900E-03 -4.690360E-06 -5.496866E-03 -6.084993E-06 -9.992636E-03 -2.331975E-05 -5.785665E-03 -9.290287E-06 -9.268775E-03 -1.727651E-05 -1.110749E-02 -2.320101E-05 -6.035119E-03 -6.006884E-06 -6.097186E-03 -8.477525E-06 -9.286855E-03 -1.325325E-05 -5.725710E-03 -5.595748E-06 -5.225326E-03 -5.682741E-06 -8.374162E-03 -1.358989E-05 -8.070266E-03 -8.525794E-06 -5.663014E-03 -8.326352E-06 -1.077577E-02 -1.774824E-05 -6.823384E-03 -7.461723E-06 -1.309151E-02 -2.293933E-05 -9.734117E-03 -1.567869E-05 -1.064840E-02 -1.998801E-05 -6.598548E-03 -1.247960E-05 -8.533419E-03 -1.698271E-05 -1.187770E-02 -2.246194E-05 -3.905374E-03 -2.559130E-06 -2.608870E-03 -1.558560E-06 -6.052893E-03 -5.374399E-06 -5.291540E-03 -8.103686E-06 -7.976421E-03 -1.021030E-05 -9.757093E-03 -1.668583E-05 -7.385489E-03 -1.285403E-05 -7.929263E-03 -7.987788E-06 -9.704986E-03 -2.962975E-05 -7.525077E-03 -1.306302E-05 -6.991034E-03 -1.064873E-05 -5.005358E-03 -9.835012E-06 -8.092808E-03 -1.147394E-05 -4.474087E-03 -3.834905E-06 -6.834524E-03 -6.982199E-06 -4.812916E-03 -4.467796E-06 -5.990512E-03 -7.842268E-06 -4.574709E-03 -3.970763E-06 -4.788106E-03 -3.924811E-06 -8.916249E-03 -1.850608E-05 -5.259665E-03 -8.293438E-06 -9.696546E-03 -1.517672E-05 -4.590212E-03 -5.096431E-06 -7.314462E-03 -1.714769E-05 -3.860185E-03 -3.127895E-06 -1.784310E-03 -9.235975E-07 -5.547235E-03 -5.112055E-06 -5.865507E-03 -6.708947E-06 -4.328438E-03 -4.229047E-06 -5.092655E-03 -5.828910E-06 -6.709671E-03 -7.080990E-06 -4.327802E-03 -3.188523E-06 -4.937391E-03 -4.569445E-06 -8.293491E-03 -1.319561E-05 -3.930138E-03 -6.730814E-06 -4.416256E-03 -4.105889E-06 -3.467315E-03 -2.354469E-06 -5.332491E-03 -9.029639E-06 -2.694692E-03 -1.279641E-06 -5.342987E-03 -6.713119E-06 -7.519588E-03 -1.092346E-05 -5.285743E-03 -5.723628E-06 -6.665656E-03 -8.544653E-06 -3.846760E-03 -2.666108E-06 -6.284377E-03 -9.724369E-06 -6.196868E-03 -8.329996E-06 -5.286331E-03 -6.920429E-06 -7.052727E-03 -1.143953E-05 -5.029353E-03 -3.735294E-06 -2.407489E-03 -2.444788E-06 -4.133935E-04 -9.497986E-08 -6.027018E-03 -1.025712E-05 -3.598018E-03 -3.018229E-06 -4.613658E-03 -4.076030E-06 -3.342670E-03 -3.029962E-06 -3.733008E-03 -2.515848E-06 -5.141865E-03 -9.007182E-06 -7.728541E-03 -1.349554E-05 -1.579734E-03 -1.531714E-06 -3.519217E-03 -3.673203E-06 -5.032814E-03 -4.394432E-06 -1.399643E-03 -6.119406E-07 -3.930826E-03 -4.507517E-06 -4.767309E-03 -5.014044E-06 +3.142337E-02 +2.743459E-04 +9.594518E-02 +1.952932E-03 +9.019638E-02 +1.611295E-03 +1.348760E-01 +3.157312E-03 +7.436797E-02 +1.038777E-03 +4.555958E-02 +6.107386E-04 +5.199084E-02 +8.828006E-04 +5.105046E-02 +5.591936E-04 +1.095224E-01 +2.675022E-03 +2.084815E-02 +1.082750E-04 +5.579780E-02 +5.469202E-04 +9.495661E-02 +1.419966E-03 +1.280076E-01 +2.520103E-03 +1.241519E-01 +2.433480E-03 +1.349742E-01 +2.504188E-03 +1.141044E-01 +2.428038E-03 +1.130324E-01 +1.720356E-03 +1.137084E-01 +1.891251E-03 +9.882155E-02 +1.696404E-03 +6.040159E-02 +7.575405E-04 +8.644781E-02 +1.794389E-03 +9.727136E-02 +1.353541E-03 +1.340186E-01 +2.951310E-03 +2.318335E-01 +6.603252E-03 +1.476469E-01 +3.292917E-03 +1.666256E-01 +4.426400E-03 +1.293622E-01 +1.916729E-03 +1.918440E-01 +4.887813E-03 +1.680575E-01 +3.208887E-03 +4.923095E-02 +6.563588E-04 +7.910820E-02 +1.021972E-03 +1.020355E-01 +1.285191E-03 +1.510553E-01 +3.275953E-03 +1.255629E-01 +1.948581E-03 +1.692347E-01 +5.943449E-03 +1.672928E-01 +3.337911E-03 +1.558106E-01 +2.875549E-03 +1.060074E-01 +1.569679E-03 +6.877708E-02 +1.029829E-03 +8.362502E-02 +1.022521E-03 +9.945978E-02 +1.606528E-03 +1.674432E-01 +3.867189E-03 +1.216650E-01 +2.493133E-03 +2.238570E-01 +5.467591E-03 +2.663718E-01 +9.395499E-03 +2.244663E-01 +5.650733E-03 +1.682990E-01 +3.326460E-03 +1.290019E-01 +2.856345E-03 +1.239696E-01 +2.379611E-03 +1.458566E-01 +4.113559E-03 +8.070294E-02 +1.198068E-03 +1.357315E-01 +3.117868E-03 +1.619699E-01 +3.585731E-03 +1.958982E-01 +5.115746E-03 +1.776585E-01 +4.588826E-03 +2.147662E-01 +5.433421E-03 +1.627119E-01 +2.886284E-03 +1.796564E-01 +4.684076E-03 +1.086029E-01 +1.976496E-03 +8.785791E-02 +1.103156E-03 +7.879086E-02 +1.433937E-03 +8.614610E-02 +1.069819E-03 +1.500232E-01 +3.209360E-03 +1.756303E-01 +4.247818E-03 +1.790515E-01 +4.363179E-03 +1.654784E-01 +4.247475E-03 +1.886300E-01 +4.844638E-03 +1.374646E-01 +2.373831E-03 +1.262352E-01 +2.754572E-03 +2.298462E-02 +1.395953E-04 +5.638152E-02 +5.767254E-04 +1.053247E-01 +1.903155E-03 +9.609740E-02 +1.572744E-03 +7.877879E-02 +1.036092E-03 +1.903056E-01 +5.121011E-03 +1.730644E-01 +3.300158E-03 +1.346274E-01 +2.606991E-03 +9.714578E-02 +1.698684E-03 +1.273408E-01 +2.552547E-03 +5.037871E-02 +5.560040E-04 +1.261746E-01 +3.287745E-03 +9.958124E-02 +1.614296E-03 +7.079336E-02 +8.561171E-04 +8.863898E-02 +1.306731E-03 +1.199303E-01 +2.107276E-03 +2.313010E-01 +7.739556E-03 +1.577787E-01 +2.960256E-03 +8.639730E-02 +1.201841E-03 +5.659795E-02 +4.694852E-04 +5.104294E-02 +5.268938E-04 +6.384520E-02 +1.050476E-03 +3.339740E-02 +2.480850E-04 +8.437203E-02 +1.544760E-03 +4.625762E-02 +6.009114E-04 +1.343672E-01 +2.619580E-03 +1.174094E-01 +2.667947E-03 +8.357176E-02 +1.039130E-03 +4.731066E-02 +3.124630E-04 +4.749930E-02 +5.129237E-04 +3.878239E-02 +5.236943E-04 +7.558078E-02 +1.440107E-03 +6.555887E-02 +7.561836E-04 +1.303901E-01 +2.764679E-03 +1.387692E-01 +2.620702E-03 +1.410499E-01 +3.203643E-03 +1.309527E-01 +2.731943E-03 +9.589097E-02 +1.548067E-03 +5.609383E-02 +5.921134E-04 +1.096306E-01 +2.122353E-03 +6.381818E-02 +9.439513E-04 +9.835519E-02 +1.561650E-03 +1.200447E-01 +2.077537E-03 +2.289759E-01 +6.569922E-03 +2.044311E-01 +4.786937E-03 +1.795569E-01 +4.117727E-03 +1.740908E-01 +3.775648E-03 +2.114890E-01 +6.553709E-03 +1.350332E-01 +3.254232E-03 +1.354820E-01 +2.909227E-03 +1.050048E-01 +2.108780E-03 +8.281040E-02 +1.022772E-03 +1.833104E-01 +4.064796E-03 +2.402611E-01 +6.073468E-03 +3.742742E-01 +1.745484E-02 +2.898729E-01 +1.012881E-02 +2.171404E-01 +6.076897E-03 +2.979566E-01 +1.047393E-02 +2.109751E-01 +5.543123E-03 +1.422788E-01 +4.002215E-03 +9.650255E-02 +1.789194E-03 +1.408445E-01 +2.513931E-03 +2.413347E-01 +7.206284E-03 +2.604648E-01 +7.914689E-03 +3.102388E-01 +1.048609E-02 +2.561683E-01 +9.086015E-03 +2.716967E-01 +8.803461E-03 +2.977518E-01 +1.072036E-02 +3.421581E-01 +1.371034E-02 +1.976808E-01 +6.130857E-03 +1.456806E-01 +3.692821E-03 +1.100115E-01 +1.679926E-03 +2.387486E-01 +7.617983E-03 +3.141187E-01 +1.212145E-02 +2.966176E-01 +1.248345E-02 +3.537282E-01 +1.600143E-02 +3.340151E-01 +1.419108E-02 +2.809424E-01 +1.063357E-02 +2.844146E-01 +9.114045E-03 +2.163287E-01 +5.949023E-03 +2.049774E-01 +6.265197E-03 +9.480490E-02 +1.184376E-03 +1.939662E-01 +4.609676E-03 +3.432049E-01 +1.277974E-02 +3.647228E-01 +1.505221E-02 +4.009987E-01 +1.935283E-02 +3.138361E-01 +1.254893E-02 +3.438278E-01 +1.334226E-02 +2.812314E-01 +1.216852E-02 +2.603220E-01 +8.391117E-03 +1.709025E-01 +4.264016E-03 +1.228523E-01 +2.416939E-03 +2.193677E-01 +8.326726E-03 +2.247567E-01 +6.429339E-03 +3.095415E-01 +1.142281E-02 +3.219591E-01 +1.154933E-02 +2.649194E-01 +1.051513E-02 +2.305332E-01 +6.488165E-03 +2.399512E-01 +9.436021E-03 +2.213458E-01 +6.719185E-03 +1.570027E-01 +4.835079E-03 +1.619056E-01 +3.154405E-03 +1.837208E-01 +5.173191E-03 +3.043448E-01 +1.189455E-02 +2.712902E-01 +1.019092E-02 +2.235869E-01 +6.195184E-03 +2.265572E-01 +7.086879E-03 +2.151576E-01 +5.865290E-03 +1.688968E-01 +3.770170E-03 +1.499070E-01 +3.571856E-03 +8.289459E-02 +1.268000E-03 +5.858084E-02 +5.268907E-04 +1.735102E-01 +5.642665E-03 +1.105650E-01 +1.955407E-03 +1.548733E-01 +3.412279E-03 +2.344765E-01 +7.515146E-03 +2.374439E-01 +8.831961E-03 +1.659923E-01 +3.686020E-03 +1.449879E-01 +2.972972E-03 +9.581840E-02 +1.386427E-03 +9.139465E-02 +1.164619E-03 +5.379547E-02 +4.842685E-04 +1.110320E-01 +2.164188E-03 +1.159951E-01 +1.971890E-03 +8.974298E-02 +9.375211E-04 +1.130422E-01 +2.462443E-03 +1.443079E-01 +2.844402E-03 +1.492118E-01 +3.605953E-03 +8.581231E-02 +1.170765E-03 +6.919528E-02 +9.104379E-04 +6.099196E-02 +1.095513E-03 +6.749596E-02 +7.121686E-04 +1.323975E-01 +2.792090E-03 +1.222936E-01 +2.240408E-03 +1.253738E-01 +2.347752E-03 +9.735284E-02 +1.185189E-03 +1.264672E-01 +2.142006E-03 +1.287095E-01 +3.340920E-03 +9.705482E-02 +1.351531E-03 +1.342330E-01 +3.619967E-03 +1.155641E-01 +2.178751E-03 +1.590188E-01 +3.559315E-03 +1.952442E-01 +4.590395E-03 +2.383089E-01 +6.703841E-03 +2.139543E-01 +6.602658E-03 +2.675136E-01 +8.973198E-03 +1.944806E-01 +4.977204E-03 +1.990033E-01 +5.173772E-03 +1.906275E-01 +4.961645E-03 +1.599751E-01 +2.957031E-03 +1.307457E-01 +2.170448E-03 +1.198087E-01 +2.578187E-03 +1.726271E-01 +3.698889E-03 +2.713634E-01 +8.566663E-03 +5.122567E-01 +3.062512E-02 +3.831674E-01 +1.706626E-02 +3.633640E-01 +1.502241E-02 +3.451328E-01 +1.555073E-02 +2.472924E-01 +8.124732E-03 +1.762382E-01 +4.255455E-03 +1.467738E-01 +3.481509E-03 +1.785598E-01 +6.539443E-03 +1.830190E-01 +4.936379E-03 +4.659340E-01 +2.706966E-02 +5.023490E-01 +3.068085E-02 +6.853967E-01 +5.662300E-02 +5.682403E-01 +3.764689E-02 +6.281147E-01 +4.728417E-02 +4.542071E-01 +2.517473E-02 +3.144113E-01 +1.232063E-02 +1.468696E-01 +3.582954E-03 +1.682495E-01 +3.387004E-03 +2.702949E-01 +9.072068E-03 +3.573130E-01 +1.672769E-02 +5.167505E-01 +3.402812E-02 +7.998053E-01 +7.670496E-02 +5.201277E-01 +3.061828E-02 +3.850550E-01 +2.020363E-02 +4.560916E-01 +2.713184E-02 +2.072743E-01 +5.179000E-03 +2.166930E-01 +7.983860E-03 +1.091868E-01 +1.673174E-03 +1.811233E-01 +4.001677E-03 +3.770375E-01 +1.987838E-02 +5.296653E-01 +2.974185E-02 +6.974237E-01 +5.462807E-02 +6.467791E-01 +4.949991E-02 +4.891845E-01 +3.041285E-02 +4.240103E-01 +2.176819E-02 +2.841149E-01 +1.105366E-02 +1.929437E-01 +4.281538E-03 +1.862098E-01 +4.308366E-03 +2.076369E-01 +4.682464E-03 +4.176628E-01 +2.402640E-02 +4.457274E-01 +2.647548E-02 +4.766048E-01 +2.623379E-02 +6.278811E-01 +4.683999E-02 +4.823482E-01 +2.794296E-02 +4.641786E-01 +2.746647E-02 +3.023706E-01 +1.146381E-02 +1.123717E-01 +1.760314E-03 +2.354666E-01 +1.065017E-02 +1.636891E-01 +4.284691E-03 +3.284045E-01 +1.210523E-02 +3.167190E-01 +1.335793E-02 +4.092350E-01 +1.860896E-02 +4.539714E-01 +2.260730E-02 +3.725391E-01 +1.667519E-02 +2.795405E-01 +9.154147E-03 +2.199953E-01 +7.783541E-03 +1.469691E-01 +4.146173E-03 +1.326578E-01 +2.611109E-03 +1.785074E-01 +4.132173E-03 +1.589050E-01 +3.902915E-03 +3.079218E-01 +1.069274E-02 +2.451220E-01 +8.310971E-03 +2.928583E-01 +1.186840E-02 +2.064830E-01 +6.139283E-03 +1.801392E-01 +3.863618E-03 +2.009835E-01 +6.159157E-03 +7.378130E-02 +1.282188E-03 +9.714870E-02 +1.167567E-03 +9.636462E-02 +1.094431E-03 +1.542921E-01 +2.942637E-03 +1.601786E-01 +4.585595E-03 +1.459336E-01 +2.484655E-03 +9.912399E-02 +1.868517E-03 +1.685975E-01 +3.436440E-03 +2.015455E-01 +5.727404E-03 +1.119151E-01 +2.477462E-03 +9.150086E-02 +1.624380E-03 +4.742528E-02 +3.421264E-04 +1.823800E-01 +6.046172E-03 +1.581304E-01 +3.695801E-03 +1.537875E-01 +3.483744E-03 +1.816982E-01 +4.474357E-03 +3.000507E-01 +1.065688E-02 +2.500082E-01 +7.508730E-03 +1.601898E-01 +3.408525E-03 +1.114064E-01 +1.730639E-03 +6.865908E-02 +7.355866E-04 +9.123141E-02 +1.186111E-03 +1.471117E-01 +3.028305E-03 +2.643140E-01 +9.790031E-03 +1.648073E-01 +3.517309E-03 +3.044579E-01 +1.168982E-02 +2.742895E-01 +8.190026E-03 +3.695621E-01 +1.648852E-02 +2.657405E-01 +8.636878E-03 +2.280781E-01 +6.081628E-03 +9.988454E-02 +1.092936E-03 +1.046543E-01 +2.073804E-03 +2.777797E-01 +1.009800E-02 +3.660427E-01 +1.616450E-02 +4.337463E-01 +2.546284E-02 +5.444391E-01 +3.551092E-02 +5.792842E-01 +3.974284E-02 +4.833176E-01 +2.633603E-02 +4.210681E-01 +1.934743E-02 +2.502725E-01 +7.152209E-03 +1.687123E-01 +5.414669E-03 +1.627058E-01 +4.133768E-03 +2.466750E-01 +7.737265E-03 +4.604958E-01 +2.466857E-02 +7.297304E-01 +6.002099E-02 +7.696698E-01 +7.205977E-02 +8.144576E-01 +8.737915E-02 +6.712593E-01 +4.960413E-02 +5.784381E-01 +3.768770E-02 +3.018257E-01 +1.124658E-02 +1.848215E-01 +5.256814E-03 +2.038347E-01 +5.001616E-03 +3.509396E-01 +1.367373E-02 +4.548534E-01 +2.472124E-02 +8.408580E-01 +7.498379E-02 +1.124722E+00 +1.372134E-01 +1.212509E+00 +1.609699E-01 +8.686055E-01 +8.923119E-02 +7.260552E-01 +5.922762E-02 +3.646146E-01 +1.695667E-02 +1.757110E-01 +5.024516E-03 +1.686522E-01 +3.814685E-03 +3.023547E-01 +1.006813E-02 +4.941913E-01 +2.727393E-02 +8.741589E-01 +8.241692E-02 +1.172320E+00 +1.490257E-01 +1.292908E+00 +1.841406E-01 +8.909073E-01 +9.620969E-02 +5.209518E-01 +3.000472E-02 +3.965469E-01 +1.974149E-02 +1.711011E-01 +3.912611E-03 +2.142186E-01 +8.247066E-03 +1.696243E-01 +3.956462E-03 +4.329508E-01 +2.267303E-02 +8.198863E-01 +7.837270E-02 +6.590219E-01 +5.182644E-02 +8.592361E-01 +8.990276E-02 +7.462144E-01 +6.544856E-02 +4.258629E-01 +2.112979E-02 +3.282506E-01 +1.233694E-02 +1.821249E-01 +6.802302E-03 +1.278153E-01 +2.300850E-03 +2.284680E-01 +8.035892E-03 +3.703590E-01 +1.909858E-02 +5.158618E-01 +3.370797E-02 +6.443407E-01 +4.753054E-02 +4.526763E-01 +2.455356E-02 +4.869630E-01 +2.818017E-02 +3.109678E-01 +1.173563E-02 +2.453178E-01 +7.052370E-03 +1.075211E-01 +1.625602E-03 +1.378942E-01 +2.421025E-03 +1.933132E-01 +5.239277E-03 +2.414331E-01 +7.590068E-03 +3.174567E-01 +1.269551E-02 +3.329565E-01 +1.431369E-02 +2.940020E-01 +9.794156E-03 +3.154830E-01 +1.105998E-02 +1.936577E-01 +4.483865E-03 +1.897439E-01 +7.235399E-03 +8.021098E-02 +7.940912E-04 +1.193232E-01 +2.711280E-03 +1.497850E-01 +5.420438E-03 +1.798106E-01 +4.414091E-03 +1.785646E-01 +4.336702E-03 +2.470614E-01 +7.228380E-03 +2.216936E-01 +5.865658E-03 +1.741635E-01 +4.786790E-03 +1.747214E-01 +3.928453E-03 +1.102521E-01 +1.584592E-03 +5.728387E-02 +5.659010E-04 +1.152645E-01 +2.543824E-03 +1.840112E-01 +5.611376E-03 +1.808779E-01 +3.998170E-03 +2.131755E-01 +5.511261E-03 +2.007849E-01 +5.112077E-03 +3.237002E-01 +1.209173E-02 +1.935346E-01 +5.219674E-03 +1.711068E-01 +3.795257E-03 +1.074251E-01 +1.586218E-03 +6.720820E-02 +7.310529E-04 +9.257051E-02 +1.160366E-03 +1.514228E-01 +2.942798E-03 +2.811310E-01 +8.775540E-03 +2.594795E-01 +9.019644E-03 +3.003136E-01 +1.182153E-02 +4.026905E-01 +1.975388E-02 +3.985679E-01 +1.776400E-02 +3.845292E-01 +1.700936E-02 +2.100930E-01 +5.450110E-03 +1.547083E-01 +3.688477E-03 +1.485974E-01 +3.372341E-03 +2.297180E-01 +6.584276E-03 +3.595602E-01 +1.586479E-02 +5.554541E-01 +3.321204E-02 +5.883316E-01 +3.857351E-02 +6.573016E-01 +5.041895E-02 +5.627698E-01 +3.356380E-02 +3.735043E-01 +1.670088E-02 +3.414429E-01 +1.411003E-02 +1.873036E-01 +4.734353E-03 +1.417975E-01 +2.575062E-03 +3.667100E-01 +1.823639E-02 +6.423896E-01 +5.370929E-02 +7.643998E-01 +7.101610E-02 +1.205382E+00 +1.530951E-01 +1.222427E+00 +1.615304E-01 +1.056883E+00 +1.367649E-01 +4.172596E-01 +1.856012E-02 +2.619717E-01 +8.351589E-03 +2.212472E-01 +5.760540E-03 +1.661126E-01 +3.716273E-03 +4.669900E-01 +2.481995E-02 +6.482388E-01 +4.852353E-02 +1.177612E+00 +1.493796E-01 +4.114708E+00 +1.791984E+00 +4.267920E+00 +1.910806E+00 +1.305252E+00 +2.173314E-01 +7.310584E-01 +6.237152E-02 +3.486264E-01 +1.301568E-02 +2.353728E-01 +7.533032E-03 +2.045902E-01 +4.997184E-03 +3.852946E-01 +1.646521E-02 +7.067789E-01 +5.775428E-02 +1.160357E+00 +1.460044E-01 +4.632606E+00 +2.269726E+00 +4.571133E+00 +2.199170E+00 +1.255312E+00 +1.734311E-01 +6.504938E-01 +4.819256E-02 +3.901607E-01 +1.960621E-02 +1.562002E-01 +3.325900E-03 +2.268010E-01 +6.502538E-03 +3.992762E-01 +1.931929E-02 +6.043048E-01 +3.982372E-02 +8.282276E-01 +7.382650E-02 +1.344103E+00 +1.870469E-01 +1.382839E+00 +2.107838E-01 +9.896232E-01 +1.097631E-01 +6.864289E-01 +5.425243E-02 +2.853774E-01 +1.070129E-02 +2.461041E-01 +7.613043E-03 +1.582320E-01 +3.193514E-03 +2.300168E-01 +5.784482E-03 +3.991370E-01 +1.981940E-02 +5.676681E-01 +3.856145E-02 +7.434275E-01 +6.152443E-02 +8.380497E-01 +7.969257E-02 +6.480100E-01 +5.048920E-02 +3.911757E-01 +1.773775E-02 +2.643229E-01 +9.900690E-03 +2.187908E-01 +6.919967E-03 +1.281363E-01 +1.960588E-03 +2.139676E-01 +6.356521E-03 +2.176293E-01 +5.727003E-03 +3.884142E-01 +1.709017E-02 +4.870420E-01 +2.883252E-02 +4.513060E-01 +2.594396E-02 +4.082087E-01 +1.828447E-02 +2.453357E-01 +9.056291E-03 +1.830639E-01 +5.540521E-03 +1.290978E-01 +2.526036E-03 +6.956983E-02 +7.545215E-04 +1.496108E-01 +2.948765E-03 +2.351155E-01 +6.895402E-03 +2.477972E-01 +7.750073E-03 +3.720114E-01 +1.471500E-02 +2.574848E-01 +7.753799E-03 +1.890091E-01 +4.516094E-03 +1.459763E-01 +2.610376E-03 +1.564084E-01 +3.266574E-03 +9.405318E-02 +1.606034E-03 +1.034826E-01 +1.553063E-03 +1.405650E-01 +4.207768E-03 +1.889571E-01 +4.444562E-03 +1.743480E-01 +3.911447E-03 +1.416364E-01 +2.343860E-03 +2.307443E-01 +7.102755E-03 +1.617078E-01 +3.813457E-03 +2.205615E-01 +7.391402E-03 +1.408447E-01 +2.389426E-03 +9.537792E-02 +1.957273E-03 +1.595071E-01 +3.372622E-03 +3.062551E-01 +1.122418E-02 +2.387165E-01 +7.680438E-03 +3.528032E-01 +1.338298E-02 +4.441106E-01 +2.285936E-02 +4.110115E-01 +1.874949E-02 +4.317996E-01 +1.968661E-02 +2.839796E-01 +9.879629E-03 +2.732779E-01 +8.620164E-03 +8.157999E-02 +1.133034E-03 +1.899240E-01 +5.053348E-03 +3.227158E-01 +1.178834E-02 +4.709360E-01 +2.736173E-02 +5.067434E-01 +2.756649E-02 +8.055244E-01 +7.407530E-02 +5.370335E-01 +3.858979E-02 +6.205981E-01 +4.614253E-02 +4.705633E-01 +2.767424E-02 +2.636737E-01 +9.397976E-03 +1.130087E-01 +1.673004E-03 +1.453104E-01 +3.242010E-03 +3.886601E-01 +1.908900E-02 +4.993435E-01 +3.139490E-02 +8.513612E-01 +8.749837E-02 +1.516911E+00 +2.710712E-01 +1.406450E+00 +2.161620E-01 +9.587365E-01 +1.078758E-01 +5.299200E-01 +3.825470E-02 +3.672028E-01 +1.638863E-02 +2.169211E-01 +5.946348E-03 +1.719126E-01 +4.353756E-03 +4.539417E-01 +2.445131E-02 +7.058570E-01 +5.448241E-02 +1.213429E+00 +1.710532E-01 +3.713956E+00 +1.432033E+00 +4.227114E+00 +1.859722E+00 +1.246711E+00 +1.850981E-01 +6.478348E-01 +5.416126E-02 +3.563685E-01 +1.447225E-02 +1.280409E-01 +2.167446E-03 +2.218509E-01 +5.932778E-03 +3.947190E-01 +1.652818E-02 +6.507162E-01 +4.675889E-02 +1.242926E+00 +1.872176E-01 +4.302933E+00 +1.909275E+00 +4.304366E+00 +1.934972E+00 +1.169852E+00 +1.621969E-01 +5.990305E-01 +4.159076E-02 +3.509285E-01 +1.478774E-02 +2.153821E-01 +5.848786E-03 +1.402457E-01 +2.618558E-03 +3.307711E-01 +1.232965E-02 +5.849860E-01 +3.657295E-02 +9.034572E-01 +9.315387E-02 +1.520658E+00 +2.437423E-01 +1.135130E+00 +1.382627E-01 +9.014297E-01 +9.720847E-02 +6.579119E-01 +5.051533E-02 +2.848374E-01 +9.701790E-03 +1.904001E-01 +4.047242E-03 +1.851274E-01 +5.144918E-03 +2.519821E-01 +8.684849E-03 +3.532581E-01 +1.465522E-02 +4.544440E-01 +2.549015E-02 +6.963186E-01 +5.524192E-02 +6.097070E-01 +3.995479E-02 +6.074075E-01 +5.206769E-02 +4.374549E-01 +2.366240E-02 +2.574947E-01 +8.333501E-03 +1.278025E-01 +2.170886E-03 +1.071155E-01 +1.748974E-03 +2.015977E-01 +5.099277E-03 +2.726467E-01 +9.337718E-03 +3.349271E-01 +1.222785E-02 +4.388732E-01 +2.334318E-02 +3.408815E-01 +1.439810E-02 +3.712626E-01 +1.597510E-02 +2.480125E-01 +8.275523E-03 +1.520639E-01 +2.752778E-03 +9.365705E-02 +1.199392E-03 +1.085462E-01 +2.036623E-03 +1.408888E-01 +2.897433E-03 +1.878790E-01 +5.021441E-03 +2.297032E-01 +6.245973E-03 +1.858744E-01 +4.441917E-03 +2.423469E-01 +6.852465E-03 +2.283632E-01 +6.314480E-03 +1.928041E-01 +5.431526E-03 +1.198104E-01 +2.580046E-03 +8.619696E-02 +1.337493E-03 +7.780836E-02 +1.674226E-03 +9.692459E-02 +1.219361E-03 +1.943967E-01 +4.459891E-03 +2.494725E-01 +7.777487E-03 +2.097978E-01 +8.245740E-03 +1.661595E-01 +4.258378E-03 +1.854527E-01 +4.327935E-03 +1.668188E-01 +3.216331E-03 +1.301662E-01 +3.969782E-03 +1.007744E-01 +1.573169E-03 +8.648914E-02 +1.391423E-03 +1.534497E-01 +2.980148E-03 +2.082093E-01 +4.991376E-03 +3.380248E-01 +1.227721E-02 +3.907089E-01 +1.770627E-02 +2.531408E-01 +7.828810E-03 +4.168039E-01 +1.881861E-02 +2.593192E-01 +7.387676E-03 +1.993743E-01 +5.362856E-03 +1.368232E-01 +2.667957E-03 +1.495518E-01 +3.346868E-03 +2.630960E-01 +9.478703E-03 +3.929542E-01 +1.710164E-02 +4.865666E-01 +2.851594E-02 +5.029322E-01 +3.156083E-02 +6.553493E-01 +5.021005E-02 +5.667030E-01 +4.186377E-02 +4.105274E-01 +2.102523E-02 +2.247647E-01 +7.123896E-03 +1.695614E-01 +3.526426E-03 +1.545322E-01 +2.888223E-03 +3.063991E-01 +1.145076E-02 +4.512831E-01 +2.316067E-02 +6.346410E-01 +4.868689E-02 +6.441196E-01 +4.644860E-02 +9.190365E-01 +9.711802E-02 +7.458883E-01 +6.448193E-02 +5.178634E-01 +3.589903E-02 +3.059552E-01 +1.103037E-02 +1.919182E-01 +7.063068E-03 +2.127676E-01 +7.068298E-03 +2.804180E-01 +9.256761E-03 +6.148571E-01 +4.270398E-02 +7.914586E-01 +8.003283E-02 +1.553058E+00 +2.512378E-01 +1.233210E+00 +1.636276E-01 +8.484663E-01 +8.472718E-02 +4.846913E-01 +3.277993E-02 +2.970379E-01 +1.009480E-02 +1.648011E-01 +3.936025E-03 +2.568657E-01 +9.334526E-03 +3.308085E-01 +1.319117E-02 +4.514535E-01 +2.501083E-02 +7.404224E-01 +7.498948E-02 +1.441901E+00 +2.253633E-01 +1.361497E+00 +2.027947E-01 +9.218086E-01 +9.573599E-02 +5.121545E-01 +3.102991E-02 +2.714593E-01 +8.321432E-03 +1.610373E-01 +3.861192E-03 +1.260213E-01 +2.059778E-03 +2.639926E-01 +8.553712E-03 +3.903656E-01 +2.120434E-02 +6.713558E-01 +6.787067E-02 +8.249516E-01 +8.014323E-02 +9.661898E-01 +1.164265E-01 +6.453827E-01 +4.960136E-02 +4.223368E-01 +2.321407E-02 +3.176142E-01 +1.194832E-02 +2.024477E-01 +5.524067E-03 +1.462501E-01 +3.549186E-03 +2.271669E-01 +6.331342E-03 +3.160296E-01 +1.372436E-02 +4.432888E-01 +2.126301E-02 +7.270762E-01 +6.487099E-02 +6.978494E-01 +5.538934E-02 +4.501793E-01 +2.531848E-02 +4.611865E-01 +2.432741E-02 +2.455689E-01 +8.366273E-03 +9.950167E-02 +1.901085E-03 +1.014830E-01 +1.540688E-03 +2.039189E-01 +7.545412E-03 +1.818539E-01 +3.576974E-03 +3.044983E-01 +1.423699E-02 +2.729832E-01 +1.331202E-02 +3.106891E-01 +1.144803E-02 +3.971745E-01 +1.721238E-02 +2.448524E-01 +6.977697E-03 +2.084599E-01 +5.955188E-03 +6.078377E-02 +5.442247E-04 +6.352672E-02 +7.273361E-04 +1.338729E-01 +2.922319E-03 +1.615985E-01 +3.901096E-03 +1.883691E-01 +4.541820E-03 +1.994268E-01 +4.419502E-03 +2.550700E-01 +1.011995E-02 +2.656566E-01 +8.538973E-03 +1.326436E-01 +2.700926E-03 +1.828790E-01 +4.860390E-03 +1.055978E-01 +2.086153E-03 +2.486040E-02 +1.152553E-04 +6.977514E-02 +7.637517E-04 +1.426015E-01 +2.562593E-03 +2.239382E-01 +7.615366E-03 +2.159614E-01 +6.154601E-03 +1.386893E-01 +3.229314E-03 +1.469009E-01 +2.610026E-03 +1.359445E-01 +2.208925E-03 +7.949674E-02 +1.090923E-03 +9.409645E-02 +1.796197E-03 +9.915992E-02 +1.496092E-03 +1.773128E-01 +4.163631E-03 +1.666022E-01 +5.373828E-03 +2.624372E-01 +8.835121E-03 +3.345364E-01 +1.299223E-02 +2.295291E-01 +6.890997E-03 +3.168143E-01 +1.633856E-02 +1.606576E-01 +4.742954E-03 +2.198036E-01 +5.376103E-03 +1.444186E-01 +3.197937E-03 +1.523611E-01 +2.626194E-03 +2.057216E-01 +5.184325E-03 +2.484219E-01 +8.065603E-03 +3.170831E-01 +1.371214E-02 +4.112561E-01 +2.349214E-02 +4.574564E-01 +2.381874E-02 +3.633926E-01 +1.532926E-02 +4.139000E-01 +1.844845E-02 +3.224482E-01 +1.294508E-02 +2.591168E-01 +8.231726E-03 +2.238452E-01 +8.182427E-03 +3.179609E-01 +1.267020E-02 +3.742188E-01 +1.866260E-02 +3.918803E-01 +2.306037E-02 +5.631822E-01 +4.613548E-02 +5.724671E-01 +3.647197E-02 +5.376124E-01 +3.468394E-02 +4.185970E-01 +1.861497E-02 +2.486122E-01 +8.141595E-03 +1.588234E-01 +3.825511E-03 +1.596044E-01 +3.435511E-03 +2.204163E-01 +5.757785E-03 +4.455893E-01 +2.579049E-02 +6.569462E-01 +4.890438E-02 +6.135941E-01 +4.664131E-02 +6.793213E-01 +5.401213E-02 +6.548499E-01 +4.947625E-02 +4.849197E-01 +2.856176E-02 +2.762591E-01 +9.482575E-03 +1.599354E-01 +3.980976E-03 +1.632220E-01 +4.266101E-03 +2.203472E-01 +7.096957E-03 +4.060220E-01 +1.794153E-02 +4.157637E-01 +2.024853E-02 +6.946025E-01 +5.477741E-02 +6.505924E-01 +4.666856E-02 +5.068244E-01 +3.491193E-02 +3.470484E-01 +1.737934E-02 +2.293816E-01 +7.685918E-03 +2.389629E-01 +8.850896E-03 +1.505995E-01 +2.876582E-03 +2.907994E-01 +1.195800E-02 +3.543847E-01 +1.568913E-02 +4.095750E-01 +1.979096E-02 +4.799528E-01 +2.728872E-02 +5.142024E-01 +3.024987E-02 +4.680612E-01 +2.551940E-02 +4.058385E-01 +2.310793E-02 +2.880766E-01 +1.175767E-02 +1.167011E-01 +2.057180E-03 +1.385494E-01 +3.784085E-03 +2.491848E-01 +7.449392E-03 +3.333697E-01 +1.223435E-02 +3.161041E-01 +1.234645E-02 +4.104319E-01 +2.113108E-02 +4.583192E-01 +2.651122E-02 +3.790470E-01 +1.851680E-02 +2.516503E-01 +7.415388E-03 +1.782866E-01 +3.900659E-03 +1.104557E-01 +2.248074E-03 +1.167308E-01 +3.039772E-03 +2.075736E-01 +7.064068E-03 +2.180168E-01 +6.336070E-03 +2.903925E-01 +9.489097E-03 +2.744247E-01 +9.030846E-03 +3.403069E-01 +1.268580E-02 +3.019064E-01 +1.052699E-02 +2.436311E-01 +7.489666E-03 +1.319666E-01 +2.817088E-03 +7.556566E-02 +8.976997E-04 +3.554724E-02 +4.034308E-04 +5.711633E-02 +4.306501E-04 +1.133366E-01 +1.754982E-03 +1.590142E-01 +3.260631E-03 +1.569202E-01 +3.503970E-03 +1.640218E-01 +3.672006E-03 +1.402148E-01 +3.495565E-03 +1.950403E-01 +6.678626E-03 +7.542042E-02 +1.053718E-03 +8.890472E-02 +1.315673E-03 +5.118031E-02 +4.782731E-04 +5.313139E-02 +5.751260E-04 +9.883790E-02 +1.983226E-03 +1.303960E-01 +2.333665E-03 +2.038247E-01 +5.452430E-03 +8.165890E-02 +9.243538E-04 +1.461825E-01 +3.217211E-03 +9.194982E-02 +1.221828E-03 +1.074998E-01 +3.217694E-03 +7.113698E-02 +8.980335E-04 +6.159336E-02 +7.871872E-04 +1.581280E-01 +3.230054E-03 +1.149541E-01 +1.639607E-03 +1.442538E-01 +3.516238E-03 +1.614780E-01 +3.943314E-03 +2.221209E-01 +6.094039E-03 +1.765576E-01 +5.283407E-03 +1.870343E-01 +4.582302E-03 +1.502824E-01 +2.786908E-03 +1.049316E-01 +1.560309E-03 +1.483976E-01 +3.461823E-03 +1.381855E-01 +3.483987E-03 +1.636269E-01 +3.625941E-03 +2.129101E-01 +6.053342E-03 +2.865882E-01 +9.222808E-03 +3.948129E-01 +1.754777E-02 +1.863158E-01 +4.282436E-03 +2.302657E-01 +6.040845E-03 +1.622669E-01 +3.583977E-03 +1.260152E-01 +2.175978E-03 +1.208627E-01 +2.044210E-03 +2.640979E-01 +8.849372E-03 +2.498718E-01 +9.012857E-03 +3.228690E-01 +1.113733E-02 +4.366129E-01 +2.169977E-02 +3.613345E-01 +1.386290E-02 +3.326626E-01 +1.382728E-02 +2.546343E-01 +8.375242E-03 +1.750139E-01 +3.956566E-03 +1.149909E-01 +1.553531E-03 +9.171613E-02 +1.258097E-03 +1.688854E-01 +3.626841E-03 +3.074559E-01 +1.128795E-02 +4.014122E-01 +1.892526E-02 +2.960858E-01 +1.062685E-02 +3.156364E-01 +1.221711E-02 +2.303342E-01 +5.911752E-03 +2.465437E-01 +7.303148E-03 +2.499264E-01 +7.462884E-03 +1.679361E-01 +3.415565E-03 +8.403406E-02 +1.398023E-03 +2.084519E-01 +6.333576E-03 +2.870835E-01 +9.368435E-03 +3.331424E-01 +1.418197E-02 +3.028572E-01 +9.995543E-03 +3.615811E-01 +1.447718E-02 +3.003659E-01 +9.829990E-03 +2.216267E-01 +5.579967E-03 +1.265740E-01 +2.312172E-03 +1.539258E-01 +3.811869E-03 +5.116714E-02 +3.766772E-04 +2.069794E-01 +4.706478E-03 +2.824890E-01 +9.829374E-03 +4.342550E-01 +2.175150E-02 +3.338091E-01 +1.258397E-02 +2.975162E-01 +9.543763E-03 +2.958141E-01 +1.060228E-02 +2.072746E-01 +5.809548E-03 +1.572435E-01 +3.553858E-03 +8.780067E-02 +1.080238E-03 +6.277077E-02 +8.146319E-04 +2.027002E-01 +4.880471E-03 +2.249296E-01 +6.801086E-03 +2.562026E-01 +7.985736E-03 +2.610332E-01 +8.341277E-03 +2.487859E-01 +6.745574E-03 +2.452106E-01 +7.276116E-03 +1.292894E-01 +2.441647E-03 +1.384975E-01 +2.258716E-03 +1.262151E-01 +2.266348E-03 +8.499870E-02 +1.048605E-03 +1.061529E-01 +1.352122E-03 +1.903736E-01 +5.558784E-03 +1.487595E-01 +2.773453E-03 +1.839791E-01 +4.150617E-03 +1.465408E-01 +2.813252E-03 +1.828928E-01 +4.248902E-03 +2.248261E-01 +6.983599E-03 +1.693010E-01 +3.303866E-03 +6.453527E-02 +1.173497E-03 +1.147332E-01 +3.617311E-03 +7.981911E-02 +8.325283E-04 +8.959341E-02 +1.548148E-03 +1.554108E-01 +4.270743E-03 +1.060675E-01 +1.816154E-03 +1.871862E-01 +4.742433E-03 +8.649749E-02 +1.100158E-03 +1.195635E-01 +1.740482E-03 +1.099096E-01 +1.964225E-03 +6.441028E-02 +7.477974E-04 +6.164448E-02 +1.090465E-03 +4.631552E-02 +5.181770E-04 +7.007983E-02 +7.319313E-04 +5.381387E-02 +3.817146E-04 +9.120379E-02 +1.840216E-03 +9.523925E-02 +1.956679E-03 +6.828427E-02 +8.825134E-04 +3.090110E-02 +1.871704E-04 +3.528248E-02 +2.289672E-04 +2.405019E-02 +9.740436E-05 +7.703115E-02 +8.995936E-04 +1.026207E-01 +1.722791E-03 +1.220668E-01 +2.216590E-03 +8.640530E-02 +1.102412E-03 +1.518321E-01 +3.298050E-03 +1.321954E-01 +2.553334E-03 +1.593152E-01 +4.604144E-03 +8.524427E-02 +1.055424E-03 +4.996523E-02 +5.024077E-04 +7.358073E-02 +1.128410E-03 +1.189640E-01 +2.194057E-03 +1.207644E-01 +2.491839E-03 +1.083314E-01 +1.503478E-03 +2.128070E-01 +7.648402E-03 +1.315274E-01 +2.025984E-03 +1.514078E-01 +3.617861E-03 +1.141892E-01 +2.085004E-03 +1.013844E-01 +1.496233E-03 +1.248655E-01 +2.516158E-03 +6.288783E-02 +9.200482E-04 +8.317750E-02 +1.508722E-03 +1.324137E-01 +3.423783E-03 +1.514092E-01 +3.487353E-03 +1.888798E-01 +5.346454E-03 +1.360192E-01 +2.392896E-03 +1.868095E-01 +3.836399E-03 +1.715305E-01 +3.663437E-03 +1.304944E-01 +1.999316E-03 +1.436264E-01 +3.567607E-03 +8.539019E-02 +1.065672E-03 +7.909923E-02 +1.167334E-03 +1.799124E-01 +4.569449E-03 +1.589893E-01 +3.478790E-03 +1.741005E-01 +3.674254E-03 +2.126076E-01 +6.791986E-03 +1.862610E-01 +4.406388E-03 +2.386545E-01 +6.839411E-03 +1.744812E-01 +4.301498E-03 +6.344775E-02 +6.567949E-04 +6.849881E-02 +7.535621E-04 +8.197852E-02 +9.887532E-04 +1.446787E-01 +3.971664E-03 +2.032184E-01 +5.194567E-03 +1.662525E-01 +3.292552E-03 +2.664800E-01 +8.114532E-03 +2.447963E-01 +7.854969E-03 +1.957695E-01 +5.152593E-03 +1.708599E-01 +4.101306E-03 +1.103539E-01 +2.077575E-03 +7.844092E-02 +1.163579E-03 +1.268702E-01 +2.695645E-03 +9.533912E-02 +1.278173E-03 +1.446874E-01 +3.872867E-03 +1.322553E-01 +2.335662E-03 +1.726451E-01 +3.517931E-03 +1.876877E-01 +4.835176E-03 +1.573863E-01 +3.574829E-03 +2.339589E-01 +7.282388E-03 +1.501104E-01 +2.820093E-03 +5.397296E-02 +5.850746E-04 +7.619565E-02 +1.435724E-03 +9.012995E-02 +1.564717E-03 +1.628327E-01 +3.377881E-03 +1.563374E-01 +3.245008E-03 +2.276467E-01 +7.079821E-03 +2.135994E-01 +7.272300E-03 +1.402939E-01 +2.997945E-03 +2.226852E-01 +6.770128E-03 +8.944673E-02 +1.404954E-03 +5.580544E-02 +9.620095E-04 +5.967367E-02 +1.011919E-03 +3.214966E-02 +1.717861E-04 +1.433931E-01 +2.788824E-03 +1.494058E-01 +2.846313E-03 +1.213890E-01 +3.277981E-03 +1.367546E-01 +2.740789E-03 +1.233601E-01 +2.166273E-03 +6.717077E-02 +9.275956E-04 +7.800745E-02 +8.928402E-04 +4.302808E-02 +5.599709E-04 +8.657826E-02 +1.515787E-03 +5.180954E-02 +5.871992E-04 +4.455245E-02 +4.150367E-04 +7.224886E-02 +8.834373E-04 +7.163514E-02 +8.735272E-04 +1.058744E-01 +2.396856E-03 +8.813243E-02 +1.064695E-03 +8.319821E-02 +2.457105E-03 +6.193848E-02 +6.865448E-04 +6.069918E-02 +6.588335E-04 diff --git a/tests/regression_tests/white_plane/results_true.dat b/tests/regression_tests/white_plane/results_true.dat index dea369205..6f1d064eb 100644 --- a/tests/regression_tests/white_plane/results_true.dat +++ b/tests/regression_tests/white_plane/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.279902E+00 3.262078E-03 +2.279719E+00 5.380792E-03 diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index e13944e03..3c6d77a75 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -22,7 +22,7 @@ def test_get_atoms(res): t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) n_ref = np.array( - [6.67473282e+08, 3.72442707e+14, 3.61129692e+14, 4.01920099e+14]) + [6.67473282e+08, 3.88942731e+14, 3.73091215e+14, 3.26987387e+14]) np.testing.assert_allclose(t, t_ref) np.testing.assert_allclose(n, n_ref) @@ -48,8 +48,8 @@ def test_get_reaction_rate(res): t, r = res.get_reaction_rate("1", "Xe135", "(n,gamma)") t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] - n_ref = [6.67473282e+08, 3.72442707e+14, 3.61129692e+14, 4.01920099e+14] - xs_ref = [5.10301159e-05, 3.19379638e-05, 4.50543806e-05, 4.71004301e-05] + n_ref = [6.67473282e+08, 3.88942731e+14, 3.73091215e+14, 3.26987387e+14] + xs_ref = [2.53336104e-05, 4.21747011e-05, 3.48616127e-05, 3.61775563e-05] np.testing.assert_allclose(t, t_ref) np.testing.assert_allclose(r, np.array(n_ref) * xs_ref) @@ -61,8 +61,8 @@ def test_get_keff(res): t_min, k = res.get_keff(time_units='min') t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] - k_ref = [1.21409662, 1.16518654, 1.25357797, 1.22611968] - u_ref = [0.0278795195, 0.0233141097, 0.0167899218, 0.0246734716] + k_ref = [1.1596402556, 1.1914183335, 1.2292570871, 1.1797030302] + u_ref = [0.0270680649, 0.0219163444, 0.024268508 , 0.0221401194] np.testing.assert_allclose(t, t_ref) np.testing.assert_allclose(t_min * 60, t_ref) From ba074c5a5a2053ab8ac375c96eb17fec26fb303e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 10 Feb 2023 14:59:57 -0600 Subject: [PATCH 1569/2654] Fix several thermal scattering nuclide assignments --- openmc/data/njoy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/data/njoy.py b/openmc/data/njoy.py index d8ecaae18..9c2055cc4 100644 --- a/openmc/data/njoy.py +++ b/openmc/data/njoy.py @@ -51,7 +51,7 @@ _THERMAL_DATA = { 'c_Li_in_FLiBe': ThermalTuple('liflib', [3006, 3007], 1), 'c_Mg24': ThermalTuple('mg24', [12024], 1), 'c_N_in_UN': ThermalTuple('n-un', [7014, 7015], 1), - 'c_O_in_Al2O3': ThermalTuple('osap00', [92238], 1), + 'c_O_in_Al2O3': ThermalTuple('osap00', [8016, 8017, 8018], 1), 'c_O_in_BeO': ThermalTuple('obeo', [8016, 8017, 8018], 1), 'c_O_in_D2O': ThermalTuple('od2o', [8016, 8017, 8018], 1), 'c_O_in_H2O_solid': ThermalTuple('oice', [8016, 8017, 8018], 1), @@ -64,8 +64,8 @@ _THERMAL_DATA = { 'c_Si_in_SiC': ThermalTuple('sisic', [14028, 14029, 14030], 1), 'c_SiO2_alpha': ThermalTuple('sio2-a', [8016, 8017, 8018, 14028, 14029, 14030], 3), 'c_SiO2_beta': ThermalTuple('sio2-b', [8016, 8017, 8018, 14028, 14029, 14030], 3), - 'c_U_in_UN': ThermalTuple('u-un', [92238], 1), - 'c_U_in_UO2': ThermalTuple('uuo2', [8016, 8017, 8018], 1), + 'c_U_in_UN': ThermalTuple('u-un', [92233, 92234, 92235, 92236, 92238], 1), + 'c_U_in_UO2': ThermalTuple('uuo2', [92233, 92234, 92235, 92236, 92238], 1), 'c_Y_in_YH2': ThermalTuple('yyh2', [39089], 1), 'c_Zr_in_ZrH': ThermalTuple('zrzrh', [40000, 40090, 40091, 40092, 40094, 40096], 1), 'c_Zr_in_ZrH2': ThermalTuple('zrzrh2', [40000, 40090, 40091, 40092, 40094, 40096], 1), From fc619f8352589f795f4eaf0d73c37fca9f753af7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 12 Feb 2023 19:27:11 -0600 Subject: [PATCH 1570/2654] Fix documentation for MeshFilter and MeshSurfaceFilter --- openmc/filter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 4d40117fe..c52d3f135 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -762,7 +762,7 @@ class ParticleFilter(Filter): class MeshFilter(Filter): - """Bins tally event locations onto a regular, rectangular mesh. + """Bins tally event locations by mesh elements. Parameters ---------- @@ -959,7 +959,7 @@ class MeshFilter(Filter): class MeshSurfaceFilter(MeshFilter): - """Filter events by surface crossings on a regular, rectangular mesh. + """Filter events by surface crossings on a mesh. Parameters ---------- From 4783b34fe2aa6a744f38f474f44dcd58e0dddf27 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 13 Feb 2023 07:16:10 -0600 Subject: [PATCH 1571/2654] Fix several failing tests --- .../cpp_driver/results_true.dat | 22 +++++++++---------- .../particle_restart_eigval/results_true.dat | 8 +++---- .../particle_restart_eigval/test.py | 2 +- tests/regression_tests/periodic_6fold/test.py | 18 +++++++-------- tests/testing_harness.py | 7 ++++++ 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/tests/regression_tests/cpp_driver/results_true.dat b/tests/regression_tests/cpp_driver/results_true.dat index e44b45054..c2b0b8d6f 100644 --- a/tests/regression_tests/cpp_driver/results_true.dat +++ b/tests/regression_tests/cpp_driver/results_true.dat @@ -1,13 +1,13 @@ k-combined: -1.902610E+00 1.901530E-02 +1.933305E+00 1.300360E-02 tally 1: -9.580351E+01 -1.031580E+03 -2.745984E+01 -8.430494E+01 -9.422158E+01 -9.919885E+02 -2.174849E+02 -5.292948E+03 -2.174849E+02 -5.292948E+03 +9.552846E+01 +1.019358E+03 +2.887973E+01 +9.308509E+01 +9.732441E+01 +1.059022E+03 +2.217326E+02 +5.486892E+03 +2.217326E+02 +5.486892E+03 diff --git a/tests/regression_tests/particle_restart_eigval/results_true.dat b/tests/regression_tests/particle_restart_eigval/results_true.dat index 64101d770..bd81920ca 100644 --- a/tests/regression_tests/particle_restart_eigval/results_true.dat +++ b/tests/regression_tests/particle_restart_eigval/results_true.dat @@ -3,14 +3,14 @@ current batch: current generation: 1.000000E+00 particle id: -9.020000E+02 +2.540000E+02 run mode: eigenvalue particle weight: 1.000000E+00 particle energy: -3.691964E+06 +2.220048E+06 particle xyz: --5.047439E+01 2.730535E+01 -2.619863E+01 +-4.820850E+01 2.432936E+01 4.397668E+01 particle uvw: --6.278670E-01 1.419818E-01 -7.652609E-01 +-3.148565E-01 9.184190E-01 2.395245E-01 diff --git a/tests/regression_tests/particle_restart_eigval/test.py b/tests/regression_tests/particle_restart_eigval/test.py index e526e5003..f9d22edb8 100644 --- a/tests/regression_tests/particle_restart_eigval/test.py +++ b/tests/regression_tests/particle_restart_eigval/test.py @@ -2,5 +2,5 @@ from tests.testing_harness import ParticleRestartTestHarness def test_particle_restart_eigval(): - harness = ParticleRestartTestHarness('particle_11_902.h5') + harness = ParticleRestartTestHarness('particle_11_254.h5') harness.main() diff --git a/tests/regression_tests/periodic_6fold/test.py b/tests/regression_tests/periodic_6fold/test.py index 555ab24f9..69712eb5a 100644 --- a/tests/regression_tests/periodic_6fold/test.py +++ b/tests/regression_tests/periodic_6fold/test.py @@ -1,5 +1,6 @@ +from math import sin, cos, pi + import openmc -import numpy as np import pytest from tests.testing_harness import PyAPITestHarness @@ -24,17 +25,14 @@ def model(): # (it essentially defines a circle of half-cylinders), but it is # designed so that periodic and reflective BCs will give different # answers. - theta1 = (-1/6 + 1/2) * np.pi - theta2 = (1/6 - 1/2) * np.pi - plane1 = openmc.Plane(a=np.cos(theta1), b=np.sin(theta1), - boundary_type='periodic') - plane2 = openmc.Plane(a=np.cos(theta2), b=np.sin(theta2), - boundary_type='periodic') + theta1 = (-1/6 + 1/2) * pi + theta2 = (1/6 - 1/2) * pi + plane1 = openmc.Plane(a=cos(theta1), b=sin(theta1), boundary_type='periodic') + plane2 = openmc.Plane(a=cos(theta2), b=sin(theta2), boundary_type='periodic') - x_max = openmc.XPlane(x0=5., boundary_type='reflective') + x_max = openmc.XPlane(5., boundary_type='reflective') - z_cyl = openmc.ZCylinder(x0=3*np.cos(np.pi/6), y0=3*np.sin(np.pi/6), - r=2.0) + z_cyl = openmc.ZCylinder(x0=3*cos(pi/6), y0=3*sin(pi/6), r=2.0) outside_cyl = openmc.Cell(1, fill=water, region=( +plane1 & +plane2 & -x_max & +z_cyl)) diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 9a6db2a2e..0525dd476 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -276,6 +276,13 @@ class ParticleRestartTestHarness(TestHarness): return outstr + def _cleanup(self): + """Delete particle restart files.""" + super()._cleanup() + output = glob.glob('particle*.h5') + for f in output: + os.remove(f) + class PyAPITestHarness(TestHarness): def __init__(self, statepoint_name, model=None, inputs_true=None): From 893c4d06488f39216eb26fadd659c05322eccb2a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 13 Feb 2023 09:00:33 -0600 Subject: [PATCH 1572/2654] Try using 10**x instead of logspace in source test --- tests/regression_tests/source/test.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/regression_tests/source/test.py b/tests/regression_tests/source/test.py index e6a5bcf70..a1175c48f 100644 --- a/tests/regression_tests/source/test.py +++ b/tests/regression_tests/source/test.py @@ -39,15 +39,15 @@ class SourceTestHarness(PyAPITestHarness): spatial2 = openmc.stats.Box([-4., -4., -4.], [4., 4., 4.]) spatial3 = openmc.stats.Point([1.2, -2.3, 0.781]) spatial4 = openmc.stats.SphericalIndependent(r_dist, cos_theta_dist, - phi_dist, + phi_dist, origin=(1., 1., 0.)) - spatial5 = openmc.stats.CylindricalIndependent(r_dist, phi_dist, + spatial5 = openmc.stats.CylindricalIndependent(r_dist, phi_dist, z_dist, origin=(1., 1., 0.)) spatial6 = openmc.stats.SphericalIndependent(r_dist2, cos_theta_dist, - phi_dist, + phi_dist, origin=(1., 1., 0.)) - spatial7 = openmc.stats.CylindricalIndependent(r_dist1, phi_dist, + spatial7 = openmc.stats.CylindricalIndependent(r_dist1, phi_dist, z_dist, origin=(1., 1., 0.)) @@ -57,7 +57,10 @@ class SourceTestHarness(PyAPITestHarness): angle2 = openmc.stats.Monodirectional(reference_uvw=[0., 1., 0.]) angle3 = openmc.stats.Isotropic() - E = np.logspace(0, 7) + # Note that the definition for E is equivalent to logspace(0, 7) but we + # manually take powers because of last-digit differences that may cause + # test failures with different versions of numpy + E = np.array([10**x for x in np.linspace(0, 7)]) p = np.sin(np.linspace(0., pi)) p /= sum(np.diff(E)*p[:-1]) energy1 = openmc.stats.Maxwell(1.2895e6) From 75fe7f00a9668c7f86ce1ccb6943964fc2064055 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 13 Feb 2023 09:40:21 -0600 Subject: [PATCH 1573/2654] Apply code suggestions from @paulromano Co-authored-by: Paul Romano --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index b2114525f..734d04da4 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1941,7 +1941,7 @@ class UnstructuredMesh(MeshBase): def read_meshes(elem): - """Reads all mesh nodes under a a given XML node + """Generate dictionary of meshes from a given XML node Parameters ---------- From 3d548c882feac44867a1a4b888fad168ddce79fe Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 13 Feb 2023 09:52:17 -0600 Subject: [PATCH 1574/2654] Addressing latest comments from @paulromano --- openmc/mesh.py | 8 ++++---- openmc/settings.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 734d04da4..196d7f6c0 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1940,7 +1940,7 @@ class UnstructuredMesh(MeshBase): return cls(filename, library, mesh_id, '', length_multiplier) -def read_meshes(elem): +def _read_meshes(elem): """Generate dictionary of meshes from a given XML node Parameters @@ -1950,11 +1950,11 @@ def read_meshes(elem): Returns ------- - OrderedDict - An ordered dictionary with mesh IDs as keys and openmc.MeshBase + dict + A dictionary with mesh IDs as keys and openmc.MeshBase instanaces as values """ - out = OrderedDict() + out = dict() for mesh_elem in elem.findall('mesh'): mesh = MeshBase.from_xml_element(mesh_elem) out[mesh.id] = mesh diff --git a/openmc/settings.py b/openmc/settings.py index ff35a90cf..39329a69e 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -16,7 +16,7 @@ from openmc.stats.multivariate import MeshSpatial from . import RegularMesh, Source, VolumeCalculation, WeightWindows from ._xml import clean_indentation, get_text, reorder_attributes from openmc.checkvalue import PathLike -from .mesh import MeshBase, read_meshes +from .mesh import _read_meshes class RunMode(Enum): @@ -1762,5 +1762,5 @@ class Settings: """ tree = ET.parse(path) root = tree.getroot() - meshes = read_meshes(root) + meshes = _read_meshes(root) return cls.from_xml_element(root, meshes) From 68a0ec793614ec5ef30d6ec582bfba98524c133a Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Tue, 14 Feb 2023 15:05:37 +0100 Subject: [PATCH 1575/2654] fix return _materiaLs_by_id --- openmc/model/model.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 2f4489084..4fb8cd9e5 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -124,10 +124,11 @@ class Model: @lru_cache(maxsize=None) def _materials_by_id(self): """Dictionary mapping material ID --> material""" - if self.materials is None: - mats = self.geometry.get_all_materials().values() - else: + if self.materials: mats = self.materials + else: + mats = self.geometry.get_all_materials().values() + return {mat.id: mat for mat in mats} @property @@ -236,7 +237,8 @@ class Model: materials = openmc.Materials.from_xml(materials) geometry = openmc.Geometry.from_xml(geometry, materials) settings = openmc.Settings.from_xml(settings) - tallies = openmc.Tallies.from_xml(tallies) if Path(tallies).exists() else None + tallies = openmc.Tallies.from_xml( + tallies) if Path(tallies).exists() else None plots = openmc.Plots.from_xml(plots) if Path(plots).exists() else None return cls(geometry, materials, settings, tallies, plots) @@ -257,12 +259,16 @@ class Model: model = cls() meshes = {} - model.settings = openmc.Settings.from_xml_element(root.find('settings'), meshes) - model.materials = openmc.Materials.from_xml_element(root.find('materials')) - model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) + model.settings = openmc.Settings.from_xml_element( + root.find('settings'), meshes) + model.materials = openmc.Materials.from_xml_element( + root.find('materials')) + model.geometry = openmc.Geometry.from_xml_element( + root.find('geometry'), model.materials) if root.find('tallies'): - model.tallies = openmc.Tallies.from_xml_element(root.find('tallies'), meshes) + model.tallies = openmc.Tallies.from_xml_element( + root.find('tallies'), meshes) if root.find('plots'): model.plots = openmc.Plots.from_xml_element(root.find('plots')) @@ -530,11 +536,13 @@ class Model: if self.tallies: tallies_element = self.tallies.to_xml_element(mesh_memo) - xml.clean_indentation(tallies_element, level=1, trailing_indent=self.plots) + xml.clean_indentation( + tallies_element, level=1, trailing_indent=self.plots) ET.ElementTree(tallies_element).write(fh, encoding='unicode') if self.plots: plots_element = self.plots.to_xml_element() - xml.clean_indentation(plots_element, level=1, trailing_indent=False) + xml.clean_indentation( + plots_element, level=1, trailing_indent=False) ET.ElementTree(plots_element).write(fh, encoding='unicode') fh.write("\n") @@ -765,7 +773,8 @@ class Model: # Now we apply the volumes if apply_volumes: # Load the results and add them to the model - for i, vol_calc in enumerate(self.settings.volume_calculations): + for i, vol_calc in enumerate( + self.settings.volume_calculations): vol_calc.load_results(f"volume_{i + 1}.h5") # First add them to the Python side self.geometry.add_volume_information(vol_calc) @@ -933,7 +942,11 @@ class Model: self._change_py_lib_attribs(names_or_ids, vector, 'cell', 'translation') - def update_densities(self, names_or_ids, density, density_units='atom/b-cm'): + def update_densities( + self, + names_or_ids, + density, + density_units='atom/b-cm'): """Update the density of a given set of materials to a new value .. note:: If applying this change to a name that is not unique, then From 760ff7e34cfcb0d0c57fbd3ed90f8cf77d967be7 Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Tue, 14 Feb 2023 15:12:04 +0100 Subject: [PATCH 1576/2654] fix return _materiaLs_by_id --- openmc/model/model.py | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 4fb8cd9e5..6ce6ef33a 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -128,7 +128,6 @@ class Model: mats = self.materials else: mats = self.geometry.get_all_materials().values() - return {mat.id: mat for mat in mats} @property @@ -237,8 +236,7 @@ class Model: materials = openmc.Materials.from_xml(materials) geometry = openmc.Geometry.from_xml(geometry, materials) settings = openmc.Settings.from_xml(settings) - tallies = openmc.Tallies.from_xml( - tallies) if Path(tallies).exists() else None + tallies = openmc.Tallies.from_xml(tallies) if Path(tallies).exists() else None plots = openmc.Plots.from_xml(plots) if Path(plots).exists() else None return cls(geometry, materials, settings, tallies, plots) @@ -259,16 +257,12 @@ class Model: model = cls() meshes = {} - model.settings = openmc.Settings.from_xml_element( - root.find('settings'), meshes) - model.materials = openmc.Materials.from_xml_element( - root.find('materials')) - model.geometry = openmc.Geometry.from_xml_element( - root.find('geometry'), model.materials) + model.settings = openmc.Settings.from_xml_element(root.find('settings'), meshes) + model.materials = openmc.Materials.from_xml_element(root.find('materials')) + model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), model.materials) if root.find('tallies'): - model.tallies = openmc.Tallies.from_xml_element( - root.find('tallies'), meshes) + model.tallies = openmc.Tallies.from_xml_element(root.find('tallies'), meshes) if root.find('plots'): model.plots = openmc.Plots.from_xml_element(root.find('plots')) @@ -536,13 +530,11 @@ class Model: if self.tallies: tallies_element = self.tallies.to_xml_element(mesh_memo) - xml.clean_indentation( - tallies_element, level=1, trailing_indent=self.plots) + xml.clean_indentation(tallies_element, level=1, trailing_indent=self.plots) ET.ElementTree(tallies_element).write(fh, encoding='unicode') if self.plots: plots_element = self.plots.to_xml_element() - xml.clean_indentation( - plots_element, level=1, trailing_indent=False) + xml.clean_indentation(plots_element, level=1, trailing_indent=False) ET.ElementTree(plots_element).write(fh, encoding='unicode') fh.write("\n") @@ -773,8 +765,7 @@ class Model: # Now we apply the volumes if apply_volumes: # Load the results and add them to the model - for i, vol_calc in enumerate( - self.settings.volume_calculations): + for i, vol_calc in enumerate(self.settings.volume_calculations): vol_calc.load_results(f"volume_{i + 1}.h5") # First add them to the Python side self.geometry.add_volume_information(vol_calc) @@ -942,11 +933,7 @@ class Model: self._change_py_lib_attribs(names_or_ids, vector, 'cell', 'translation') - def update_densities( - self, - names_or_ids, - density, - density_units='atom/b-cm'): + def update_densities(self, names_or_ids, density, density_units='atom/b-cm'): """Update the density of a given set of materials to a new value .. note:: If applying this change to a name that is not unique, then From 070e5b93e1e8056465b2abf60a0152bf6efc5bf9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 14 Feb 2023 16:42:24 -0600 Subject: [PATCH 1577/2654] Try running CI on ubuntu-22.04 --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20bf47bbb..b1846c9a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,10 +22,10 @@ env: jobs: main: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: - python-version: ['3.10'] + python-version: ["3.10"] mpi: [n, y] omp: [n, y] dagmc: [n] @@ -45,27 +45,27 @@ jobs: omp: n mpi: n - dagmc: y - python-version: '3.10' + python-version: "3.10" mpi: y omp: y - ncrystal: y - python-version: '3.10' + python-version: "3.10" mpi: n omp: n - libmesh: y - python-version: '3.10' + python-version: "3.10" mpi: y omp: y - libmesh: y - python-version: '3.10' + python-version: "3.10" mpi: n omp: y - event: y - python-version: '3.10' + python-version: "3.10" omp: y mpi: n - vectfit: y - python-version: '3.10' + python-version: "3.10" omp: n mpi: y name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }}, From 0435e64fd0d271c0910ee9d19e5b0a84c337ac1d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 14 Feb 2023 23:09:54 -0600 Subject: [PATCH 1578/2654] Disable AVX512 in numpy runtime SIMD dispatch --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1846c9a0..0a47d5775 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,7 @@ jobs: EVENT: ${{ matrix.event }} VECTFIT: ${{ matrix.vectfit }} LIBMESH: ${{ matrix.libmesh }} + NPY_DISABLE_CPU_FEATURES: "AVX512F AVX512_SKX" steps: - uses: actions/checkout@v3 From 5f5c0ed7a7e4d23dc0ed87562770301bf5dc5e3e Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Wed, 15 Feb 2023 11:07:29 +0100 Subject: [PATCH 1579/2654] map_no_kargs --- openmc/deplete/pool.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/pool.py b/openmc/deplete/pool.py index 13acb8bf5..d1eab413f 100644 --- a/openmc/deplete/pool.py +++ b/openmc/deplete/pool.py @@ -15,7 +15,7 @@ USE_MULTIPROCESSING = True NUM_PROCESSES = None -def deplete(func, chain, x, rates, dt, matrix_func=None, **func_args): +def deplete(func, chain, x, rates, dt, matrix_func=None, *func_args): """Deplete materials using given reaction rates for a specified time Parameters @@ -60,7 +60,7 @@ def deplete(func, chain, x, rates, dt, matrix_func=None, **func_args): matrices = map(chain.form_matrix, rates, fission_yields) else: matrices = map(matrix_func, repeat(chain), rates, fission_yields, - **func_args) + *func_args) inputs = zip(matrices, x, repeat(dt)) From a2b828af52d5a93200693a3ed02411516916c7dd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 15 Feb 2023 07:09:38 -0600 Subject: [PATCH 1580/2654] Use 1 thread for OpenBLAS calls from numpy --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a47d5775..fd516b7f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,6 +83,7 @@ jobs: VECTFIT: ${{ matrix.vectfit }} LIBMESH: ${{ matrix.libmesh }} NPY_DISABLE_CPU_FEATURES: "AVX512F AVX512_SKX" + OPENBLAS_NUM_THREADS: 1 steps: - uses: actions/checkout@v3 From a25bbc250f2bdfefea6541b8dc8f2cc121a3266c Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Thu, 16 Feb 2023 14:50:23 +0100 Subject: [PATCH 1581/2654] renaming func_args into matrix_args, fixing docstring accordingly --- openmc/deplete/pool.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/pool.py b/openmc/deplete/pool.py index d1eab413f..aba60b558 100644 --- a/openmc/deplete/pool.py +++ b/openmc/deplete/pool.py @@ -15,7 +15,7 @@ USE_MULTIPROCESSING = True NUM_PROCESSES = None -def deplete(func, chain, x, rates, dt, matrix_func=None, *func_args): +def deplete(func, chain, x, rates, dt, matrix_func=None, *matrix_args): """Deplete materials using given reaction rates for a specified time Parameters @@ -37,8 +37,8 @@ def deplete(func, chain, x, rates, dt, matrix_func=None, *func_args): ``fission_yields = {parent: {product: yield_frac}}`` Expected to return the depletion matrix required by ``func`` - func_args : dict - Remaining keyword arguments passed to matrix_func when used + matrix_args : Any, optional + Additional arguments passed to matrix_func Returns ------- @@ -60,7 +60,7 @@ def deplete(func, chain, x, rates, dt, matrix_func=None, *func_args): matrices = map(chain.form_matrix, rates, fission_yields) else: matrices = map(matrix_func, repeat(chain), rates, fission_yields, - *func_args) + *matrix_args) inputs = zip(matrices, x, repeat(dt)) From 9e88e706fe92860ce973630a4a288b15a4a8b66c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 16 Feb 2023 16:20:44 +0000 Subject: [PATCH 1582/2654] testing get_all_universes is in DAGMCUniverse --- tests/unit_tests/test_universe.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py index 26b7779a7..a70bd4667 100644 --- a/tests/unit_tests/test_universe.py +++ b/tests/unit_tests/test_universe.py @@ -93,10 +93,12 @@ def test_get_all_universes(): u2 = openmc.Universe(cells=[c2]) c3 = openmc.Cell(fill=u1) c4 = openmc.Cell(fill=u2) - u3 = openmc.Universe(cells=[c3, c4]) + u3 = openmc.DAGMCUniverse(filename="") + c5 = openmc.Cell(fill=u3) + u4 = openmc.Universe(cells=[c3, c4, c5]) - univs = set(u3.get_all_universes().values()) - assert not (univs ^ {u1, u2}) + univs = set(u4.get_all_universes().values()) + assert not (univs ^ {u1, u2, u3}) def test_clone(): From 04d9e27866dad92dc1a6fbc7676e76750c96cb63 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 16 Feb 2023 16:24:24 +0000 Subject: [PATCH 1583/2654] moving get_all_universes method --- openmc/universe.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index c56cce7ca..2ed96f4bc 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -91,6 +91,23 @@ class UniverseBase(ABC, IDManagerMixin): else: raise ValueError('No volume information found for this universe.') + def get_all_universes(self): + """Return all universes that are contained within this one. + + Returns + ------- + universes : collections.OrderedDict + Dictionary whose keys are universe IDs and values are + :class:`Universe` instances + + """ + # Append all Universes within each Cell to the dictionary + universes = OrderedDict() + for cell in self.get_all_cells().values(): + universes.update(cell.get_all_universes()) + + return universes + @abstractmethod def create_xml_subelement(self, xml_element, memo=None): """Add the universe xml representation to an incoming xml element @@ -538,23 +555,6 @@ class Universe(UniverseBase): return materials - def get_all_universes(self): - """Return all universes that are contained within this one. - - Returns - ------- - universes : collections.OrderedDict - Dictionary whose keys are universe IDs and values are - :class:`Universe` instances - - """ - # Append all Universes within each Cell to the dictionary - universes = OrderedDict() - for cell in self.get_all_cells().values(): - universes.update(cell.get_all_universes()) - - return universes - def create_xml_subelement(self, xml_element, memo=None): # Iterate over all Cells for cell in self._cells.values(): From 1a2d1237da0b46f8cc0dddeaccee3c7f1036381d Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 16 Feb 2023 12:27:15 -0500 Subject: [PATCH 1584/2654] Update openmc/model/surface_composite.py Co-authored-by: Jonathan Shimwell --- openmc/model/surface_composite.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 044ecf61e..09c2f4fee 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -785,7 +785,6 @@ class Polygon(CompositeSurface): if np.sum(ypts*(np.roll(xpts, 1) - np.roll(xpts, -1))) < 0: points = points[::-1, :] - # Check if polygon is self-intersecting by comparing edges pairwise n = len(points) for i in range(n): From 1891ff7c2420e91701e41c9f9556e2938170649e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 16 Feb 2023 13:47:42 -0600 Subject: [PATCH 1585/2654] Updating batch number checks for simulation and sp load --- src/simulation.cpp | 2 +- src/state_point.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 2f07f8124..7740c81d8 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -236,7 +236,7 @@ int openmc_next_batch(int* status) // Check simulation ending criteria if (status) { - if (simulation::current_batch == settings::n_max_batches) { + if (simulation::current_batch >= settings::n_max_batches) { *status = STATUS_EXIT_MAX_BATCH; } else if (simulation::satisfy_triggers) { *status = STATUS_EXIT_ON_TRIGGER; diff --git a/src/state_point.cpp b/src/state_point.cpp index 4170421be..8ca0166c6 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -403,9 +403,10 @@ void load_state_point() // Read batch number to restart at read_dataset(file_id, "current_batch", simulation::restart_batch); - if (simulation::restart_batch > settings::n_batches) { - fatal_error("The number batches specified in settings.xml is fewer " - " than the number of batches in the given statepoint file."); + if (simulation::restart_batch >= settings::n_batches) { + fatal_error(fmt::format("The number of batches specified for simiulation ({}) is smaller" + " than the number of batches in the restart statepoint file ({})", + settings::n_batches, simulation::restart_batch)); } // Logical flag for source present in statepoint file From 0e10a7da47ddbea8fd43236db59f3d414124c33b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 16 Feb 2023 13:48:11 -0600 Subject: [PATCH 1586/2654] Allowing openmc.Pathlike for restart file argument --- openmc/executor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index accffd06a..e779fdde4 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -3,6 +3,7 @@ from numbers import Integral import subprocess import openmc +from openmc.checkvalue import PathLike from .plots import _get_plot_image @@ -73,8 +74,8 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, if event_based: args.append('-e') - if isinstance(restart_file, str): - args += ['-r', restart_file] + if isinstance(restart_file, PathLike.__args__): + args += ['-r', str(restart_file)] if tracks: args.append('-t') From ee2f0f2c53048bb7dafed8f270cad2668ea5da14 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 16 Feb 2023 13:48:28 -0600 Subject: [PATCH 1587/2654] Adding a test for restart runs --- tests/unit_tests/test_restart.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/unit_tests/test_restart.py diff --git a/tests/unit_tests/test_restart.py b/tests/unit_tests/test_restart.py new file mode 100644 index 000000000..f2d99e082 --- /dev/null +++ b/tests/unit_tests/test_restart.py @@ -0,0 +1,23 @@ +import openmc + +import pytest + +def test_restart(run_in_tmpdir): + + pincell = openmc.examples.pwr_pin_cell() + + # run the pincell + sp_file = pincell.run() + + # run a restart with the resulting statepoint + # and the settings unchanged + + with pytest.raises(RuntimeError, match='is smaller than the number of batches'): + pincell.run(restart_file=sp_file) + + # update the number of batches and run again + pincell.settings.batches = 15 + sp_file = pincell.run(restart_file=sp_file) + + sp = openmc.StatePoint(sp_file) + assert sp.n_batches == 15 \ No newline at end of file From 461fd54f11a74ce7713b8717661566905db76483 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 16 Feb 2023 13:53:57 -0600 Subject: [PATCH 1588/2654] Updating doc strings --- openmc/executor.py | 10 +++++----- openmc/geometry.py | 2 +- openmc/model/model.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index e779fdde4..758604c91 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -24,7 +24,7 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, Number of particles to simulate per generation. plot : bool, optional Run in plotting mode. Defaults to False. - restart_file : str, optional + restart_file : str or PathLike Path to restart file to use threads : int, optional Number of OpenMP threads. If OpenMC is compiled with OpenMP threading @@ -43,7 +43,7 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, mpi_args : list of str, optional MPI execute command and any additional MPI arguments to pass, e.g., ['mpiexec', '-n', '8']. - path_input : str or Pathlike + path_input : str or PathLike Path to a single XML file or a directory containing XML files for the OpenMC executable to read. @@ -231,7 +231,7 @@ def calculate_volumes(threads=None, output=True, cwd='.', cwd : str, optional Path to working directory to run in. Defaults to the current working directory. - path_input : str or Pathlike + path_input : str or PathLike Path to a single XML file or a directory containing XML files for the OpenMC executable to read. @@ -271,7 +271,7 @@ def run(particles=None, threads=None, geometry_debug=False, :envvar:`OMP_NUM_THREADS` environment variable). geometry_debug : bool, optional Turn on geometry debugging during simulation. Defaults to False. - restart_file : str, optional + restart_file : str or PathLike Path to restart file to use tracks : bool, optional Enables the writing of particles tracks. The number of particle tracks @@ -292,7 +292,7 @@ def run(particles=None, threads=None, geometry_debug=False, .. versionadded:: 0.12 - path_input : str or Pathlike + path_input : str or PathLike Path to a single XML file or a directory containing XML files for the OpenMC executable to read. diff --git a/openmc/geometry.py b/openmc/geometry.py index 511a3da40..d01826a4d 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -278,7 +278,7 @@ class Geometry: """ - # Using str and os.Pathlike here to avoid error when using just the imported PathLike + # Using str and os.PathLike here to avoid error when using just the imported PathLike # TypeError: Subscripted generics cannot be used with class and instance checks check_type('materials', materials, (str, os.PathLike, openmc.Materials)) diff --git a/openmc/model/model.py b/openmc/model/model.py index 6ce6ef33a..79708d62b 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -248,7 +248,7 @@ class Model: Parameters ---------- - path : str or Pathlike + path : str or PathLike Path to model.xml file """ tree = ET.parse(path) @@ -473,7 +473,7 @@ class Model: Parameters ---------- - path : str or Pathlike + path : str or PathLike Location of the XML file to write (default is 'model.xml'). Can be a directory or file path. remove_surfs : bool @@ -620,7 +620,7 @@ class Model: value set by the :envvar:`OMP_NUM_THREADS` environment variable). geometry_debug : bool, optional Turn on geometry debugging during simulation. Defaults to False. - restart_file : str, optional + restart_file : str or PathLike Path to restart file to use tracks : bool, optional Enables the writing of particles tracks. The number of particle From ce62bbd9c5822881b9bb35631f023967e2a75e83 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Feb 2023 14:06:59 -0600 Subject: [PATCH 1589/2654] Add missing override specifiers --- include/openmc/distribution.h | 18 ++-- include/openmc/distribution_energy.h | 12 +-- include/openmc/distribution_multi.h | 6 +- include/openmc/distribution_spatial.h | 12 +-- include/openmc/lattice.h | 50 +++++----- include/openmc/mesh.h | 2 - include/openmc/scattdata.h | 45 +++++---- include/openmc/surface.h | 137 +++++++++++++------------- 8 files changed, 142 insertions(+), 140 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 4fc0db2e0..815ffa21a 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -43,7 +43,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; // Properties const vector& x() const { return x_; } @@ -75,7 +75,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; double a() const { return a_; } double b() const { return b_; } @@ -99,7 +99,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; double a() const { return std::pow(offset_, ninv_); } double b() const { return std::pow(offset_ + span_, ninv_); } @@ -124,7 +124,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; double theta() const { return theta_; } @@ -144,7 +144,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; double a() const { return a_; } double b() const { return b_; } @@ -168,7 +168,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; double mean_value() const { return mean_value_; } double std_dev() const { return std_dev_; } @@ -191,7 +191,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; // x property vector& x() { return x_; } @@ -225,7 +225,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; const vector& x() const { return x_; } @@ -244,7 +244,7 @@ public: //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const; + double sample(uint64_t* seed) const override; private: // Storrage for probability + distribution diff --git a/include/openmc/distribution_energy.h b/include/openmc/distribution_energy.h index d8512aa45..9b08ed039 100644 --- a/include/openmc/distribution_energy.h +++ b/include/openmc/distribution_energy.h @@ -37,7 +37,7 @@ public: //! \param[in] E Incident particle energy in [eV] //! \param[inout] seed Pseudorandom number seed pointer //! \return Sampled energy in [eV] - double sample(double E, uint64_t* seed) const; + double sample(double E, uint64_t* seed) const override; private: int primary_flag_; //!< Indicator of whether the photon is a primary or @@ -58,7 +58,7 @@ public: //! \param[in] E Incident particle energy in [eV] //! \param[inout] seed Pseudorandom number seed pointer //! \return Sampled energy in [eV] - double sample(double E, uint64_t* seed) const; + double sample(double E, uint64_t* seed) const override; private: double threshold_; //!< Energy threshold in lab, (A + 1)/A * |Q| @@ -79,7 +79,7 @@ public: //! \param[in] E Incident particle energy in [eV] //! \param[inout] seed Pseudorandom number seed pointer //! \return Sampled energy in [eV] - double sample(double E, uint64_t* seed) const; + double sample(double E, uint64_t* seed) const override; private: //! Outgoing energy for a single incoming energy @@ -110,7 +110,7 @@ public: //! \param[in] E Incident particle energy in [eV] //! \param[inout] seed Pseudorandom number seed pointer //! \return Sampled energy in [eV] - double sample(double E, uint64_t* seed) const; + double sample(double E, uint64_t* seed) const override; private: Tabulated1D theta_; //!< Incoming energy dependent parameter @@ -130,7 +130,7 @@ public: //! \param[in] E Incident particle energy in [eV] //! \param[inout] seed Pseudorandom number seed pointer //! \return Sampled energy in [eV] - double sample(double E, uint64_t* seed) const; + double sample(double E, uint64_t* seed) const override; private: Tabulated1D theta_; //!< Incoming energy dependent parameter @@ -150,7 +150,7 @@ public: //! \param[in] E Incident particle energy in [eV] //! \param[inout] seed Pseudorandom number seed pointer //! \return Sampled energy in [eV] - double sample(double E, uint64_t* seed) const; + double sample(double E, uint64_t* seed) const override; private: Tabulated1D a_; //!< Energy-dependent 'a' parameter diff --git a/include/openmc/distribution_multi.h b/include/openmc/distribution_multi.h index 991294f79..e171d58ab 100644 --- a/include/openmc/distribution_multi.h +++ b/include/openmc/distribution_multi.h @@ -42,7 +42,7 @@ public: //! Sample a direction from the distribution //! \param seed Pseudorandom number seed pointer //! \return Direction sampled - Direction sample(uint64_t* seed) const; + Direction sample(uint64_t* seed) const override; // Observing pointers Distribution* mu() const { return mu_.get(); } @@ -66,7 +66,7 @@ public: //! Sample a direction from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled direction - Direction sample(uint64_t* seed) const; + Direction sample(uint64_t* seed) const override; }; //============================================================================== @@ -82,7 +82,7 @@ public: //! Sample a direction from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled direction - Direction sample(uint64_t* seed) const; + Direction sample(uint64_t* seed) const override; }; using UPtrAngle = unique_ptr; diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index dda23927e..a8cc7c58e 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -32,7 +32,7 @@ public: //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position - Position sample(uint64_t* seed) const; + Position sample(uint64_t* seed) const override; // Observer pointers Distribution* x() const { return x_.get(); } @@ -56,7 +56,7 @@ public: //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position - Position sample(uint64_t* seed) const; + Position sample(uint64_t* seed) const override; Distribution* r() const { return r_.get(); } Distribution* phi() const { return phi_.get(); } @@ -81,7 +81,7 @@ public: //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position - Position sample(uint64_t* seed) const; + Position sample(uint64_t* seed) const override; Distribution* r() const { return r_.get(); } Distribution* cos_theta() const { return cos_theta_.get(); } @@ -106,7 +106,7 @@ public: //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position - Position sample(uint64_t* seed) const; + Position sample(uint64_t* seed) const override; const Mesh* mesh() const { return model::meshes.at(mesh_idx_).get(); } @@ -132,7 +132,7 @@ public: //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position - Position sample(uint64_t* seed) const; + Position sample(uint64_t* seed) const override; // Properties bool only_fissionable() const { return only_fissionable_; } @@ -158,7 +158,7 @@ public: //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position - Position sample(uint64_t* seed) const; + Position sample(uint64_t* seed) const override; Position r() const { return r_; } diff --git a/include/openmc/lattice.h b/include/openmc/lattice.h index a2411467d..11dda4a6b 100644 --- a/include/openmc/lattice.h +++ b/include/openmc/lattice.h @@ -206,26 +206,28 @@ class RectLattice : public Lattice { public: explicit RectLattice(pugi::xml_node lat_node); - int32_t const& operator[](array const& i_xyz); + int32_t const& operator[](array const& i_xyz) override; - bool are_valid_indices(array const& i_xyz) const; + bool are_valid_indices(array const& i_xyz) const override; std::pair> distance( - Position r, Direction u, const array& i_xyz) const; + Position r, Direction u, const array& i_xyz) const override; - void get_indices(Position r, Direction u, array& result) const; + void get_indices( + Position r, Direction u, array& result) const override; - int get_flat_index(const array& i_xyz) const; + int get_flat_index(const array& i_xyz) const override; - Position get_local_position(Position r, const array& i_xyz) const; + Position get_local_position( + Position r, const array& i_xyz) const override; - int32_t& offset(int map, array const& i_xyz); + int32_t& offset(int map, array const& i_xyz) override; - int32_t offset(int map, int indx) const; + int32_t offset(int map, int indx) const override; - std::string index_to_string(int indx) const; + std::string index_to_string(int indx) const override; - void to_hdf5_inner(hid_t group_id) const; + void to_hdf5_inner(hid_t group_id) const override; private: array n_cells_; //!< Number of cells along each axis @@ -239,32 +241,34 @@ class HexLattice : public Lattice { public: explicit HexLattice(pugi::xml_node lat_node); - int32_t const& operator[](array const& i_xyz); + int32_t const& operator[](array const& i_xyz) override; - LatticeIter begin(); + LatticeIter begin() override; - ReverseLatticeIter rbegin(); + ReverseLatticeIter rbegin() override; - bool are_valid_indices(array const& i_xyz) const; + bool are_valid_indices(array const& i_xyz) const override; std::pair> distance( - Position r, Direction u, const array& i_xyz) const; + Position r, Direction u, const array& i_xyz) const override; - void get_indices(Position r, Direction u, array& result) const; + void get_indices( + Position r, Direction u, array& result) const override; - int get_flat_index(const array& i_xyz) const; + int get_flat_index(const array& i_xyz) const override; - Position get_local_position(Position r, const array& i_xyz) const; + Position get_local_position( + Position r, const array& i_xyz) const override; - bool is_valid_index(int indx) const; + bool is_valid_index(int indx) const override; - int32_t& offset(int map, array const& i_xyz); + int32_t& offset(int map, array const& i_xyz) override; - int32_t offset(int map, int indx) const; + int32_t offset(int map, int indx) const override; - std::string index_to_string(int indx) const; + std::string index_to_string(int indx) const override; - void to_hdf5_inner(hid_t group_id) const; + void to_hdf5_inner(hid_t group_id) const override; private: enum class Orientation { diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 7abc8a832..93d08f597 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -527,8 +527,6 @@ public: //! \return element connectivity as IDs of the vertices virtual std::vector connectivity(int id) const = 0; - virtual double volume(int bin) const = 0; - //! Get the library used for this unstructured mesh virtual std::string library() const = 0; diff --git a/include/openmc/scattdata.h b/include/openmc/scattdata.h index 9f911d7db..a75ef09d9 100644 --- a/include/openmc/scattdata.h +++ b/include/openmc/scattdata.h @@ -137,22 +137,23 @@ protected: public: void init(const xt::xtensor& in_gmin, const xt::xtensor& in_gmax, const double_2dvec& in_mult, - const double_3dvec& coeffs); + const double_3dvec& coeffs) override; - void combine( - const vector& those_scatts, const vector& scalars); + void combine(const vector& those_scatts, + const vector& scalars) override; //! \brief Find the maximal value of the angular distribution to use as a // bounding box with rejection sampling. void update_max_val(); - double calc_f(int gin, int gout, double mu); + double calc_f(int gin, int gout, double mu) override; - void sample(int gin, int& gout, double& mu, double& wgt, uint64_t* seed); + void sample( + int gin, int& gout, double& mu, double& wgt, uint64_t* seed) override; - size_t get_order() { return dist[0][0].size() - 1; }; + size_t get_order() override { return dist[0][0].size() - 1; }; - xt::xtensor get_matrix(size_t max_order); + xt::xtensor get_matrix(size_t max_order) override; }; //============================================================================== @@ -170,18 +171,19 @@ protected: public: void init(const xt::xtensor& in_gmin, const xt::xtensor& in_gmax, const double_2dvec& in_mult, - const double_3dvec& coeffs); + const double_3dvec& coeffs) override; - void combine( - const vector& those_scatts, const vector& scalars); + void combine(const vector& those_scatts, + const vector& scalars) override; - double calc_f(int gin, int gout, double mu); + double calc_f(int gin, int gout, double mu) override; - void sample(int gin, int& gout, double& mu, double& wgt, uint64_t* seed); + void sample( + int gin, int& gout, double& mu, double& wgt, uint64_t* seed) override; - size_t get_order() { return dist[0][0].size(); }; + size_t get_order() override { return dist[0][0].size(); }; - xt::xtensor get_matrix(size_t max_order); + xt::xtensor get_matrix(size_t max_order) override; }; //============================================================================== @@ -204,18 +206,19 @@ protected: public: void init(const xt::xtensor& in_gmin, const xt::xtensor& in_gmax, const double_2dvec& in_mult, - const double_3dvec& coeffs); + const double_3dvec& coeffs) override; - void combine( - const vector& those_scatts, const vector& scalars); + void combine(const vector& those_scatts, + const vector& scalars) override; - double calc_f(int gin, int gout, double mu); + double calc_f(int gin, int gout, double mu) override; - void sample(int gin, int& gout, double& mu, double& wgt, uint64_t* seed); + void sample( + int gin, int& gout, double& mu, double& wgt, uint64_t* seed) override; - size_t get_order() { return dist[0][0].size(); }; + size_t get_order() override { return dist[0][0].size(); }; - xt::xtensor get_matrix(size_t max_order); + xt::xtensor get_matrix(size_t max_order) override; }; //============================================================================== diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 84a2ed113..4c97a0514 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -146,9 +146,6 @@ class CSGSurface : public Surface { public: explicit CSGSurface(pugi::xml_node surf_node); CSGSurface(); - -protected: - virtual void to_hdf5_inner(hid_t group_id) const = 0; }; //============================================================================== @@ -160,11 +157,11 @@ protected: class SurfaceXPlane : public CSGSurface { public: explicit SurfaceXPlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; + BoundingBox bounding_box(bool pos_side) const override; double x0_; }; @@ -178,11 +175,11 @@ public: class SurfaceYPlane : public CSGSurface { public: explicit SurfaceYPlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; + BoundingBox bounding_box(bool pos_side) const override; double y0_; }; @@ -196,11 +193,11 @@ public: class SurfaceZPlane : public CSGSurface { public: explicit SurfaceZPlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; + BoundingBox bounding_box(bool pos_side) const override; double z0_; }; @@ -214,10 +211,10 @@ public: class SurfacePlane : public CSGSurface { public: explicit SurfacePlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; double A_, B_, C_, D_; }; @@ -232,11 +229,11 @@ public: class SurfaceXCylinder : public CSGSurface { public: explicit SurfaceXCylinder(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; + BoundingBox bounding_box(bool pos_side) const override; double y0_, z0_, radius_; }; @@ -251,11 +248,11 @@ public: class SurfaceYCylinder : public CSGSurface { public: explicit SurfaceYCylinder(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; + BoundingBox bounding_box(bool pos_side) const override; double x0_, z0_, radius_; }; @@ -270,11 +267,11 @@ public: class SurfaceZCylinder : public CSGSurface { public: explicit SurfaceZCylinder(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; + BoundingBox bounding_box(bool pos_side) const override; double x0_, y0_, radius_; }; @@ -289,11 +286,11 @@ public: class SurfaceSphere : public CSGSurface { public: explicit SurfaceSphere(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; + BoundingBox bounding_box(bool pos_side) const override; double x0_, y0_, z0_, radius_; }; @@ -308,10 +305,10 @@ public: class SurfaceXCone : public CSGSurface { public: explicit SurfaceXCone(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; double x0_, y0_, z0_, radius_sq_; }; @@ -326,10 +323,10 @@ public: class SurfaceYCone : public CSGSurface { public: explicit SurfaceYCone(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; double x0_, y0_, z0_, radius_sq_; }; @@ -344,10 +341,10 @@ public: class SurfaceZCone : public CSGSurface { public: explicit SurfaceZCone(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; double x0_, y0_, z0_, radius_sq_; }; @@ -362,10 +359,10 @@ public: class SurfaceQuadric : public CSGSurface { public: explicit SurfaceQuadric(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; // Ax^2 + By^2 + Cz^2 + Dxy + Eyz + Fxz + Gx + Hy + Jz + K = 0 double A_, B_, C_, D_, E_, F_, G_, H_, J_, K_; @@ -380,10 +377,10 @@ public: class SurfaceXTorus : public CSGSurface { public: explicit SurfaceXTorus(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; double x0_, y0_, z0_, A_, B_, C_; }; @@ -397,10 +394,10 @@ public: class SurfaceYTorus : public CSGSurface { public: explicit SurfaceYTorus(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; double x0_, y0_, z0_, A_, B_, C_; }; @@ -414,10 +411,10 @@ public: class SurfaceZTorus : public CSGSurface { public: explicit SurfaceZTorus(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + void to_hdf5_inner(hid_t group_id) const override; double x0_, y0_, z0_, A_, B_, C_; }; From 9803c2611196bb9d9e89ef46e24ab8c2d4b7e17d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 16 Feb 2023 16:18:41 -0600 Subject: [PATCH 1590/2654] bwd compatibility fix for reading filter elements --- openmc/filter.py | 2 ++ tests/unit_tests/test_restart.py | 23 ----------------------- 2 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 tests/unit_tests/test_restart.py diff --git a/openmc/filter.py b/openmc/filter.py index c52d3f135..1f2f9816c 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -258,6 +258,8 @@ class Filter(IDManagerMixin, metaclass=FilterMeta): """ filter_type = elem.get('type') + if filter_type is None: + filter_type = elem.find('type').text # If the filter type matches this class's short_name, then # there is no overridden from_xml_element method diff --git a/tests/unit_tests/test_restart.py b/tests/unit_tests/test_restart.py deleted file mode 100644 index f2d99e082..000000000 --- a/tests/unit_tests/test_restart.py +++ /dev/null @@ -1,23 +0,0 @@ -import openmc - -import pytest - -def test_restart(run_in_tmpdir): - - pincell = openmc.examples.pwr_pin_cell() - - # run the pincell - sp_file = pincell.run() - - # run a restart with the resulting statepoint - # and the settings unchanged - - with pytest.raises(RuntimeError, match='is smaller than the number of batches'): - pincell.run(restart_file=sp_file) - - # update the number of batches and run again - pincell.settings.batches = 15 - sp_file = pincell.run(restart_file=sp_file) - - sp = openmc.StatePoint(sp_file) - assert sp.n_batches == 15 \ No newline at end of file From 648313fab16719d526adb69444bf18303e94ec0d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 16 Feb 2023 16:28:05 -0600 Subject: [PATCH 1591/2654] Adding to regression test instead of making new unit test --- .../statepoint_restart/test.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/regression_tests/statepoint_restart/test.py b/tests/regression_tests/statepoint_restart/test.py index 4575607f7..9ab528e61 100644 --- a/tests/regression_tests/statepoint_restart/test.py +++ b/tests/regression_tests/statepoint_restart/test.py @@ -1,11 +1,14 @@ import glob import os +from pathlib import Path import openmc from tests.testing_harness import TestHarness from tests.regression_tests import config +from tests import cdtemp +import pytest class StatepointRestartTestHarness(TestHarness): def __init__(self, final_sp, restart_sp): @@ -59,3 +62,27 @@ def test_statepoint_restart(): harness = StatepointRestartTestHarness('statepoint.10.h5', 'statepoint.07.h5') harness.main() + + +def test_batch_check(request): + xmls = glob.glob('*.xml') + xmls = [request.fspath.dirpath() / Path(f) for f in xmls] + + with cdtemp(xmls): + model = openmc.Model.from_xml() + model.settings.particles = 100 + # run the model + sp_file = model.run() + + # run a restart with the resulting statepoint + # and the settings unchanged + with pytest.raises(RuntimeError, match='is smaller than the number of batches'): + model.run(restart_file=sp_file) + + # update the number of batches and run again + model.settings.batches = 15 + model.settings.statepoint = {} + sp_file = model.run(restart_file=sp_file) + + sp = openmc.StatePoint(sp_file) + assert sp.n_batches == 15 \ No newline at end of file From 65852f4fbc8e2cbe702af558733aff0bae83d1a3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 16 Feb 2023 17:52:23 -0600 Subject: [PATCH 1592/2654] Update batch comparison in statepoint load --- src/state_point.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 8ca0166c6..23538da59 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -403,10 +403,11 @@ void load_state_point() // Read batch number to restart at read_dataset(file_id, "current_batch", simulation::restart_batch); - if (simulation::restart_batch >= settings::n_batches) { - fatal_error(fmt::format("The number of batches specified for simiulation ({}) is smaller" - " than the number of batches in the restart statepoint file ({})", - settings::n_batches, simulation::restart_batch)); + if (simulation::restart_batch >= settings::n_max_batches) { + fatal_error(fmt::format( + "The number of batches specified for simiulation ({}) is smaller" + " than the number of batches in the restart statepoint file ({})", + settings::n_max_batches, simulation::restart_batch)); } // Logical flag for source present in statepoint file From 0aba858f95d4350c91228bdfe9962c4bc64582d8 Mon Sep 17 00:00:00 2001 From: josh Date: Fri, 17 Feb 2023 02:15:50 +0000 Subject: [PATCH 1593/2654] sort nuclides when adding by element --- openmc/element.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/element.py b/openmc/element.py index 49aeaf464..729266cc2 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -195,7 +195,7 @@ class Element(str): # If a cross_section library is not present, expand the element into # its natural nuclides else: - for nuclide in natural_nuclides: + for nuclide in sorted(list(natural_nuclides)): abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] # Modify mole fractions if enrichment provided From c634a1467445352974e391cdfe7e80d936d3c6a9 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 17 Feb 2023 10:56:42 -0500 Subject: [PATCH 1594/2654] added origin to docstrings --- openmc/mesh.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmc/mesh.py b/openmc/mesh.py index 10d07000e..06f024676 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1049,6 +1049,8 @@ class CylindricalMesh(StructuredMesh): The default value is [0, 2π], i.e. the full phi range. z_grid : numpy.ndarray 1-D array of mesh boundary points along the z-axis. + origin : tuple + The (x,y,z) origin of the mesh in cartesian coordinates indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), (2, 1, 1), ...] @@ -1376,6 +1378,8 @@ class SphericalMesh(StructuredMesh): phi_grid : numpy.ndarray 1-D array of mesh boundary points along the phi-axis in radians. The default value is [0, 2π], i.e. the full phi range. + origin : tuple + The (x,y,z) origin of the mesh in cartesian coordinates indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), (2, 1, 1), ...] From d5ce4af68a77d95605df461fa850a300c1804c2c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Feb 2023 07:45:47 -0600 Subject: [PATCH 1595/2654] Add RDMAV_FORK_SAFE=1 to avoid fork error with libfabric --- .github/workflows/ci.yml | 4 ++++ tools/ci/gha-script.sh | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd516b7f9..999dea312 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,6 +84,10 @@ jobs: LIBMESH: ${{ matrix.libmesh }} NPY_DISABLE_CPU_FEATURES: "AVX512F AVX512_SKX" OPENBLAS_NUM_THREADS: 1 + # libfabric complains about fork() as a result of using Python multiprocessing. + # We can work around it with RDMAV_FORK_SAFE=1 in libfabric < 1.13 and with + # FI_EFA_FORK_SAFE=1 in more recent versions. + RDMAV_FORK_SAFE: 1 steps: - uses: actions/checkout@v3 diff --git a/tools/ci/gha-script.sh b/tools/ci/gha-script.sh index 1f1c3a1eb..9de84f3e5 100755 --- a/tools/ci/gha-script.sh +++ b/tools/ci/gha-script.sh @@ -8,7 +8,7 @@ args=" " if [[ $MPI == 'y' ]]; then args="${args} --mpi " fi - + # Check for event-based if [[ $EVENT == 'y' ]]; then args="${args} --event " From eb0c8e497c7161d078854f82150b896c57b564dc Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Feb 2023 17:04:49 -0600 Subject: [PATCH 1596/2654] Move Filter::create implementation to filter.h --- include/openmc/tallies/filter.h | 19 +++++++++++++++++++ src/tallies/filter.cpp | 15 --------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/openmc/tallies/filter.h b/include/openmc/tallies/filter.h index 47b4c8a94..8a17ee7ea 100644 --- a/include/openmc/tallies/filter.h +++ b/include/openmc/tallies/filter.h @@ -157,5 +157,24 @@ extern vector> tally_filters; //! Make sure index corresponds to a valid filter int verify_filter(int32_t index); +//============================================================================== +// Filter implementation +//============================================================================== + +template +T* Filter::create(int32_t id) +{ + static_assert(std::is_base_of::value, + "Type specified is not derived from openmc::Filter"); + // Create filter and add to filters vector + auto filter = make_unique(); + auto ptr_out = filter.get(); + model::tally_filters.emplace_back(std::move(filter)); + // Assign ID + model::tally_filters.back()->set_id(id); + + return ptr_out; +} + } // namespace openmc #endif // OPENMC_TALLIES_FILTER_H diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index c00d4fd43..5e8204b2a 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -71,21 +71,6 @@ Filter::~Filter() model::filter_map.erase(id_); } -template -T* Filter::create(int32_t id) -{ - static_assert(std::is_base_of::value, - "Type specified is not derived from openmc::Filter"); - // Create filter and add to filters vector - auto filter = make_unique(); - auto ptr_out = filter.get(); - model::tally_filters.emplace_back(std::move(filter)); - // Assign ID - model::tally_filters.back()->set_id(id); - - return ptr_out; -} - Filter* Filter::create(pugi::xml_node node) { // Copy filter id From 14af9de1e2b56b2192bd295072ef54d2ff020e02 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Fri, 17 Feb 2023 19:16:15 -0600 Subject: [PATCH 1597/2654] Use more generalized error message. Refs #2394 --- src/dagmc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index f21d5d0a9..154200f3f 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -182,11 +182,11 @@ void DAGUniverse::init_geometry() model::cell_map[c->id_] = model::cells.size(); } else { warning(fmt::format("DAGMC Cell IDs: {}", dagmc_ids_for_dim(3))); - fatal_error(fmt::format("Cell ID {} exists in both DAGMC Universe {} " - "and the CSG geometry. Setting auto_geom_ids " + fatal_error(fmt::format("DAGMC Universe {} contains cell ID {}, which " + "already exists in the geometry. Setting auto_geom_ids " "to True when initiating the DAGMC Universe may " "resolve this issue", - c->id_, this->id_)); + this->id_, c->id_)); } // --- Materials --- From 5a6162754948b0fc2065c76869c04eb26989177d Mon Sep 17 00:00:00 2001 From: April Novak Date: Sat, 18 Feb 2023 17:18:53 -0800 Subject: [PATCH 1598/2654] Apply suggestions from code review Co-authored-by: Patrick Shriwise --- src/dagmc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 154200f3f..01ce8ef11 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -182,8 +182,8 @@ void DAGUniverse::init_geometry() model::cell_map[c->id_] = model::cells.size(); } else { warning(fmt::format("DAGMC Cell IDs: {}", dagmc_ids_for_dim(3))); - fatal_error(fmt::format("DAGMC Universe {} contains cell ID {}, which " - "already exists in the geometry. Setting auto_geom_ids " + fatal_error(fmt::format("DAGMC Universe {} contains a cell with ID {}, which " + "already exists elsewhere in the geometry. Setting auto_geom_ids " "to True when initiating the DAGMC Universe may " "resolve this issue", this->id_, c->id_)); From b8c7c7644422a7bd8b83cb096c3b50c4ef97ce00 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 21 Feb 2023 00:42:27 -0600 Subject: [PATCH 1599/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- src/state_point.cpp | 2 +- tests/regression_tests/statepoint_restart/test.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 23538da59..dfd3d381b 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -405,7 +405,7 @@ void load_state_point() if (simulation::restart_batch >= settings::n_max_batches) { fatal_error(fmt::format( - "The number of batches specified for simiulation ({}) is smaller" + "The number of batches specified for simulation ({}) is smaller" " than the number of batches in the restart statepoint file ({})", settings::n_max_batches, simulation::restart_batch)); } diff --git a/tests/regression_tests/statepoint_restart/test.py b/tests/regression_tests/statepoint_restart/test.py index 9ab528e61..35df4f07d 100644 --- a/tests/regression_tests/statepoint_restart/test.py +++ b/tests/regression_tests/statepoint_restart/test.py @@ -3,13 +3,12 @@ import os from pathlib import Path import openmc +import pytest from tests.testing_harness import TestHarness from tests.regression_tests import config from tests import cdtemp -import pytest - class StatepointRestartTestHarness(TestHarness): def __init__(self, final_sp, restart_sp): super().__init__(final_sp) @@ -65,8 +64,7 @@ def test_statepoint_restart(): def test_batch_check(request): - xmls = glob.glob('*.xml') - xmls = [request.fspath.dirpath() / Path(f) for f in xmls] + xmls = list(request.path.parent.glob('*.xml')) with cdtemp(xmls): model = openmc.Model.from_xml() From 1b68e61a3edd3290d587c2dcb9d752523599c452 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 21 Feb 2023 00:47:47 -0600 Subject: [PATCH 1600/2654] explicit instance check --- openmc/executor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/executor.py b/openmc/executor.py index 758604c91..aacc48b3f 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -1,9 +1,9 @@ from collections.abc import Iterable from numbers import Integral +import os import subprocess import openmc -from openmc.checkvalue import PathLike from .plots import _get_plot_image @@ -74,7 +74,7 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, if event_based: args.append('-e') - if isinstance(restart_file, PathLike.__args__): + if isinstance(restart_file, (str, os.PathLike)): args += ['-r', str(restart_file)] if tracks: From 0aa36836b3a73818fb9d29b4a8ac13150dd6df5b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 21 Feb 2023 00:48:23 -0600 Subject: [PATCH 1601/2654] Updating globs --- tests/regression_tests/statepoint_restart/test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/regression_tests/statepoint_restart/test.py b/tests/regression_tests/statepoint_restart/test.py index 35df4f07d..2f3a6ce88 100644 --- a/tests/regression_tests/statepoint_restart/test.py +++ b/tests/regression_tests/statepoint_restart/test.py @@ -1,4 +1,3 @@ -import glob import os from pathlib import Path @@ -44,7 +43,7 @@ class StatepointRestartTestHarness(TestHarness): def _run_openmc_restart(self): # Get the name of the statepoint file. - statepoint = glob.glob(os.path.join(os.getcwd(), self._restart_sp)) + statepoint = list(Path(os.getcwd()).glob(self._restart_sp)) assert len(statepoint) == 1 statepoint = statepoint[0] @@ -83,4 +82,4 @@ def test_batch_check(request): sp_file = model.run(restart_file=sp_file) sp = openmc.StatePoint(sp_file) - assert sp.n_batches == 15 \ No newline at end of file + assert sp.n_batches == 15 From 0419367815a3f552ccb1b994f7da2d8ecffc15d3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 21 Feb 2023 07:28:32 -0600 Subject: [PATCH 1602/2654] Update tests/regression_tests/statepoint_restart/test.py Co-authored-by: Paul Romano --- tests/regression_tests/statepoint_restart/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/statepoint_restart/test.py b/tests/regression_tests/statepoint_restart/test.py index 2f3a6ce88..8acd0e88b 100644 --- a/tests/regression_tests/statepoint_restart/test.py +++ b/tests/regression_tests/statepoint_restart/test.py @@ -43,7 +43,7 @@ class StatepointRestartTestHarness(TestHarness): def _run_openmc_restart(self): # Get the name of the statepoint file. - statepoint = list(Path(os.getcwd()).glob(self._restart_sp)) + statepoint = list(Path.cwd().glob(self._restart_sp)) assert len(statepoint) == 1 statepoint = statepoint[0] From 55179b5a46accdf8b8dfcd8ce1ed3c0f454a92f4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 21 Feb 2023 07:31:53 -0600 Subject: [PATCH 1603/2654] Removing os module from restart test --- tests/regression_tests/statepoint_restart/test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/regression_tests/statepoint_restart/test.py b/tests/regression_tests/statepoint_restart/test.py index 8acd0e88b..1e98bc480 100644 --- a/tests/regression_tests/statepoint_restart/test.py +++ b/tests/regression_tests/statepoint_restart/test.py @@ -1,4 +1,3 @@ -import os from pathlib import Path import openmc From f961fc90c2bc5c0565be5179a6a4c789cc553729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Tue, 21 Feb 2023 17:42:06 -0500 Subject: [PATCH 1604/2654] [skip ci] Modified the XML specs --- docs/source/io_formats/tallies.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/io_formats/tallies.rst b/docs/source/io_formats/tallies.rst index 8594bb11c..897941ad4 100644 --- a/docs/source/io_formats/tallies.rst +++ b/docs/source/io_formats/tallies.rst @@ -351,6 +351,9 @@ attributes/sub-elements: :theta_grid: The mesh divisions along the theta-axis. (For spherical mesh only.) + :origin: + The origin in cartesian coordinates. (For cylindrical and spherical meshes only.) + :library: The mesh library used to represent an unstructured mesh. This can be either "moab" or "libmesh". (For unstructured mesh only.) From 5556b0cedc0210ebc4913c6f6866cbf57ca4b4f4 Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 22 Feb 2023 18:24:50 +0000 Subject: [PATCH 1605/2654] order nuclides by increasing mass number --- openmc/data/data.py | 2 +- openmc/element.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 55bfb4f09..7d82a3c1f 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -489,7 +489,7 @@ def isotopes(element): # Get the nuclides present in nature result = [] - for kv in sorted(NATURAL_ABUNDANCE.items()): + for kv in NATURAL_ABUNDANCE.items(): if re.match(r'{}\d+'.format(element), kv[0]): result.append(kv) diff --git a/openmc/element.py b/openmc/element.py index 729266cc2..f1a5d31d3 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -4,7 +4,7 @@ from xml.etree import ElementTree as ET import openmc.checkvalue as cv import openmc -from openmc.data import NATURAL_ABUNDANCE, atomic_mass, \ +from openmc.data import NATURAL_ABUNDANCE, atomic_mass, zam, \ isotopes as natural_isotopes @@ -147,8 +147,8 @@ class Element(str): # and sort to avoid different ordering between Python 2 and 3. mutual_nuclides = natural_nuclides.intersection(library_nuclides) absent_nuclides = natural_nuclides.difference(mutual_nuclides) - mutual_nuclides = sorted(list(mutual_nuclides)) - absent_nuclides = sorted(list(absent_nuclides)) + mutual_nuclides = sorted(mutual_nuclides, key=zam) + absent_nuclides = sorted(absent_nuclides, key=zam) # If all naturally occurring isotopes are present in the library, # add them based on their abundance @@ -195,7 +195,7 @@ class Element(str): # If a cross_section library is not present, expand the element into # its natural nuclides else: - for nuclide in sorted(list(natural_nuclides)): + for nuclide in sorted(natural_nuclides, key=zam): abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] # Modify mole fractions if enrichment provided From 7becabcde4b2900ed134d1051a362411aca03dd2 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 23 Feb 2023 21:16:52 +0000 Subject: [PATCH 1606/2654] cm^3 instead of cm3 --- openmc/material.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index 28d38cb90..bdc25b280 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -144,7 +144,7 @@ class Material(IDManagerMixin): string += f' [{self._density_units}]\n' string += '{: <16}=\t{}'.format('\tVolume', self._volume) - string += ' [cm3]\n' + string += ' [cm^3]\n' string += '{: <16}\n'.format('\tS(a,b) Tables') From a270d4c01a9ed16d99b4fa98712469f7ba906959 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 23 Feb 2023 23:39:03 -0600 Subject: [PATCH 1607/2654] Using vertices property where possible. Correcting volume ordering in normalization --- openmc/mesh.py | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 904d4a2ad..5294b2dd6 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -266,7 +266,7 @@ class StructuredMesh(MeshBase): datasets_out.append(dataset) if volume_normalization: - dataset /= self.volumes.flatten() + dataset /= self.volumes.T.flatten() dataset_array = vtk.vtkDoubleArray() dataset_array.SetName(label) @@ -1012,7 +1012,7 @@ class RectilinearMesh(StructuredMesh): the VTK object """ # create points - pts_cartesian = np.array([[x, y, z] for z in self.z_grid for y in self.y_grid for x in self.x_grid]) + pts_cartesian = self.vertices.T.reshape(-1, 3) return super().write_data_to_vtk( points=pts_cartesian, @@ -1303,14 +1303,8 @@ class CylindricalMesh(StructuredMesh): the VTK object """ # create points - pts_cylindrical = np.array( - [ - [r, phi, z] - for z in self.z_grid - for phi in self.phi_grid - for r in self.r_grid - ] - ) + pts_cylindrical = self.vertices.T.reshape(-1, 3) + pts_cartesian = np.copy(pts_cylindrical) r, phi = pts_cylindrical[:, 0], pts_cylindrical[:, 1] pts_cartesian[:, 0] = r * np.cos(phi) @@ -1534,16 +1528,9 @@ class SphericalMesh(StructuredMesh): vtk.vtkStructuredGrid the VTK object """ - # create points - pts_spherical = np.array( - [ - [r, theta, phi] - for phi in self.phi_grid - for theta in self.theta_grid - for r in self.r_grid - ] - ) + pts_spherical = self.vertices.T.reshape(-1, 3) + pts_cartesian = np.copy(pts_spherical) r, theta, phi = pts_spherical[:, 0], pts_spherical[:, 1], pts_spherical[:, 2] pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) From 70b743e5edc2cd058fe0156a630b5ccedff7fcae Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 23 Feb 2023 23:59:46 -0600 Subject: [PATCH 1608/2654] Add test of volume normalization ordering --- tests/unit_tests/test_mesh_to_vtk.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index bc3633c8c..16bdcea05 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -34,7 +34,11 @@ def test_write_data_to_vtk(mesh, tmpdir): # BUILD filename = Path(tmpdir) / "out.vtk" - data = np.random.random(mesh.num_mesh_cells) + # use mesh element volumes as data to check volume-normalization ordering + # kji (i changing fastest) orering is expected for input data + # by using the volumes transposed as the data here, we can ensure the + # normalization is happening correctly + data = mesh.volumes.T # RUN mesh.write_data_to_vtk(filename=filename, datasets={"label1": data, "label2": data}) @@ -56,8 +60,13 @@ def test_write_data_to_vtk(mesh, tmpdir): assert array2.GetName() == "label2" # check size of datasets - assert nps.vtk_to_numpy(array1).size == data.size - assert nps.vtk_to_numpy(array2).size == data.size + data1 = nps.vtk_to_numpy(array1) + data2 = nps.vtk_to_numpy(array2) + assert data1.size == data.size + assert data2.size == data.size + + assert all(data1 == data2) + assert all(data1 == 1.0) @pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) From f0aa0ab3f248d26a3bb921e1ba6f84c3e9a6e4b9 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Fri, 24 Feb 2023 12:10:52 -0600 Subject: [PATCH 1609/2654] Add default constructor for VolumeCalculation. Refs #2398 --- include/openmc/volume_calc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/openmc/volume_calc.h b/include/openmc/volume_calc.h index 2efd955f0..ff75b2b8b 100644 --- a/include/openmc/volume_calc.h +++ b/include/openmc/volume_calc.h @@ -35,6 +35,8 @@ public: // Constructors VolumeCalculation(pugi::xml_node node); + VolumeCalculation() {} + // Methods //! \brief Stochastically determine the volume of a set of domains along with From 9858114ed71aed8e49c8f4395e5e2e37ab957e84 Mon Sep 17 00:00:00 2001 From: April Novak Date: Fri, 24 Feb 2023 11:53:40 -0800 Subject: [PATCH 1610/2654] Apply suggestions from code review Co-authored-by: Paul Romano --- include/openmc/volume_calc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/volume_calc.h b/include/openmc/volume_calc.h index ff75b2b8b..2773a39fa 100644 --- a/include/openmc/volume_calc.h +++ b/include/openmc/volume_calc.h @@ -35,7 +35,7 @@ public: // Constructors VolumeCalculation(pugi::xml_node node); - VolumeCalculation() {} + VolumeCalculation() = default; // Methods From 0d84c538181022f607ddceb898c132faac2568b8 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 24 Feb 2023 22:05:00 +0000 Subject: [PATCH 1611/2654] review improvment, refactor to single line Co-authored-by: Paul Romano --- openmc/material.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index bdc25b280..a1b3367a9 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -143,8 +143,7 @@ class Material(IDManagerMixin): string += '{: <16}=\t{}'.format('\tDensity', self._density) string += f' [{self._density_units}]\n' - string += '{: <16}=\t{}'.format('\tVolume', self._volume) - string += ' [cm^3]\n' + string += '{: <16}=\t{} [cm^3]\n'.format('\tVolume', self._volume) string += '{: <16}\n'.format('\tS(a,b) Tables') From 2f9f500542fef29ddf5ec1b408e9fd1e10c37f03 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 27 Feb 2023 16:10:27 -0500 Subject: [PATCH 1612/2654] removed check and always offset origin --- openmc/mesh.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 06f024676..2c74c7bfa 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1337,10 +1337,9 @@ class CylindricalMesh(StructuredMesh): pts_cartesian[:, 1] = r * np.sin(phi) # offset with origin - if any([coord != 0 for coord in self.origin]): - pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] - pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] - pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] + pts_cartesian[:, 0] += pts_cartesian[:, 0] + pts_cartesian[:, 1] += pts_cartesian[:, 1] + pts_cartesian[:, 2] += pts_cartesian[:, 2] return super().write_data_to_vtk( points=pts_cartesian, @@ -1598,10 +1597,9 @@ class SphericalMesh(StructuredMesh): pts_cartesian[:, 2] = r * np.cos(phi) # offset with origin - if any([coord != 0 for coord in self.origin]): - pts_cartesian[:, 0] = pts_cartesian[:, 0] + self.origin[0] - pts_cartesian[:, 1] = pts_cartesian[:, 1] + self.origin[1] - pts_cartesian[:, 2] = pts_cartesian[:, 2] + self.origin[2] + pts_cartesian[:, 0] += self.origin[0] + pts_cartesian[:, 1] += self.origin[1] + pts_cartesian[:, 2] += self.origin[2] return super().write_data_to_vtk( points=pts_cartesian, From c61e735a706b3bd251010ec8fa888cda30ebb596 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 27 Feb 2023 16:10:55 -0500 Subject: [PATCH 1613/2654] empty_like instead of copy --- openmc/mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 2c74c7bfa..9bed9200c 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1331,7 +1331,7 @@ class CylindricalMesh(StructuredMesh): for r in self.r_grid ] ) - pts_cartesian = np.copy(pts_cylindrical) + pts_cartesian = np.empty_like(pts_cylindrical) r, phi = pts_cylindrical[:, 0], pts_cylindrical[:, 1] pts_cartesian[:, 0] = r * np.cos(phi) pts_cartesian[:, 1] = r * np.sin(phi) @@ -1590,7 +1590,7 @@ class SphericalMesh(StructuredMesh): for r in self.r_grid ] ) - pts_cartesian = np.copy(pts_spherical) + pts_cartesian = np.empty_like(pts_spherical) r, theta, phi = pts_spherical[:, 0], pts_spherical[:, 1], pts_spherical[:, 2] pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) From 9ca6f1b65b469938b5bb067c1c6d9d11a21f3623 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 27 Feb 2023 16:13:31 -0500 Subject: [PATCH 1614/2654] fixed docstrings for origin --- openmc/mesh.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 9bed9200c..db57a3a9e 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1049,8 +1049,9 @@ class CylindricalMesh(StructuredMesh): The default value is [0, 2π], i.e. the full phi range. z_grid : numpy.ndarray 1-D array of mesh boundary points along the z-axis. - origin : tuple - The (x,y,z) origin of the mesh in cartesian coordinates + origin : numpy.ndarray + 1-D array of length 3 the (x,y,z) origin of the mesh in + cartesian coordinates indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), (2, 1, 1), ...] @@ -1377,8 +1378,9 @@ class SphericalMesh(StructuredMesh): phi_grid : numpy.ndarray 1-D array of mesh boundary points along the phi-axis in radians. The default value is [0, 2π], i.e. the full phi range. - origin : tuple - The (x,y,z) origin of the mesh in cartesian coordinates + origin : numpy.ndarray + 1-D array of length 3 the (x,y,z) origin of the mesh in + cartesian coordinates indices : Iterable of tuple An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), (2, 1, 1), ...] From 972e1c12ec4cc2001202409bf8227454f8c83abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:22:10 -0500 Subject: [PATCH 1615/2654] [skip ci] Minor refactoring Co-authored-by: Ethan Peterson --- openmc/mesh.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index db57a3a9e..a7c2eb172 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1594,14 +1594,9 @@ class SphericalMesh(StructuredMesh): ) pts_cartesian = np.empty_like(pts_spherical) r, theta, phi = pts_spherical[:, 0], pts_spherical[:, 1], pts_spherical[:, 2] - pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) - pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) - pts_cartesian[:, 2] = r * np.cos(phi) - - # offset with origin - pts_cartesian[:, 0] += self.origin[0] - pts_cartesian[:, 1] += self.origin[1] - pts_cartesian[:, 2] += self.origin[2] + pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) + self.origin[0] + pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) + self.origin[1] + pts_cartesian[:, 2] = r * np.cos(phi) + self.origin[2] return super().write_data_to_vtk( points=pts_cartesian, From 308be3f1eac95143eec2f3f40c36adb6dfa351c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Delaporte-Mathurin?= <40028739+RemDelaporteMathurin@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:23:45 -0500 Subject: [PATCH 1616/2654] Update openmc/mesh.py Co-authored-by: Ethan Peterson --- openmc/mesh.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index a7c2eb172..039f302e9 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1334,14 +1334,10 @@ class CylindricalMesh(StructuredMesh): ) pts_cartesian = np.empty_like(pts_cylindrical) r, phi = pts_cylindrical[:, 0], pts_cylindrical[:, 1] - pts_cartesian[:, 0] = r * np.cos(phi) - pts_cartesian[:, 1] = r * np.sin(phi) - - # offset with origin - pts_cartesian[:, 0] += pts_cartesian[:, 0] - pts_cartesian[:, 1] += pts_cartesian[:, 1] - pts_cartesian[:, 2] += pts_cartesian[:, 2] - + pts_cartesian[:, 0] = r * np.cos(phi) + self.origin[0] + pts_cartesian[:, 1] = r * np.sin(phi) + self.origin[1] + pts_cartesian[:, 2] += self.origin[2] + return super().write_data_to_vtk( points=pts_cartesian, filename=filename, From c71c13496356a0e65cc1ac284608a31845f0f934 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 27 Feb 2023 16:32:05 -0500 Subject: [PATCH 1617/2654] added grids in statepoint specs --- docs/source/io_formats/statepoint.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 9a08eed73..c0db5ea92 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -78,6 +78,12 @@ The current version of the statepoint file format is 17.0. of mesh. - **width** (*double[]*) -- Width of each mesh cell in each dimension. + - **Cylindrical & Spherical Mesh Only:** + - **r_grid** (*double[]*) -- The mesh divisions along the r-axis. + - **phi_grid** (*double[]*) -- The mesh divisions along the phi-axis. + - **origin** (*double[]*) -- The origin in cartesian coordinates. + - **Spherical Mesh Only:** + - **theta_grid** (*double[]*) -- The mesh divisions along the theta-axis. - **Unstructured Mesh Only:** - **filename** (*char[]*) -- Name of the mesh file. - **library** (*char[]*) -- Mesh library used to represent the From 728f48c2aef77fadcabef52fdaae33de0dd9323a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 1 Mar 2023 00:33:24 -0600 Subject: [PATCH 1618/2654] Adding another test that uses VTK to gather the data directly. Co-authored-by: Jonathan Shimwell --- tests/unit_tests/test_mesh_to_vtk.py | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 16bdcea05..a9dcd7243 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -91,3 +91,61 @@ def test_write_data_to_vtk_size_mismatch(mesh): ) with pytest.raises(ValueError, match=expected_error_msg): mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) + +def test_write_data_to_vtk_round_trip(run_in_tmpdir): + cmesh = openmc.CylindricalMesh() + cmesh.r_grid = (0.0, 1.0, 2.0) + cmesh.z_grid = (0.0, 2.0, 4.0, 5.0) + cmesh.phi_grid = (0.0, 3.0, 6.0) + + smesh = openmc.SphericalMesh() + smesh.r_grid = (0.0, 1.0, 2.0) + smesh.theta_grid = (0.0, 2.0, 4.0, 5.0) + smesh.phi_grid = (0.0, 3.0, 6.0) + + rmesh = openmc.RegularMesh() + rmesh.lower_left = (0.0, 0.0, 0.0) + rmesh.upper_right = (1.0, 3.0, 5.0) + rmesh.dimension = (2, 1, 6) + + for mesh in [smesh, cmesh, rmesh]: + + filename = "mesh.vtk" + data = np.array([1.0] * 12) # there are 12 voxels in each mesh + mesh.write_data_to_vtk( + filename=filename, + datasets={"normalized": data}, + volume_normalization=True + ) + + reader = vtk.vtkStructuredGridReader() + reader.SetFileName(filename) + reader.ReadAllFieldsOn() + reader.Update() + + cell_data = reader.GetOutput().GetCellData() + uniform_array = cell_data.GetArray("normalized") + num_tuples = uniform_array.GetNumberOfTuples() + vtk_values = [uniform_array.GetValue(i) for i in range(num_tuples)] + + # checks that the vtk cell values are equal to the data / mesh volumes + assert np.allclose(vtk_values, data / mesh.volumes.T.flatten()) + + mesh.write_data_to_vtk( + filename=filename, + datasets={"not_normalized": data}, + volume_normalization=False, + ) + + reader = vtk.vtkStructuredGridReader() + reader.SetFileName(filename) + reader.ReadAllFieldsOn() + reader.Update() + + cell_data = reader.GetOutput().GetCellData() + uniform_array = cell_data.GetArray("not_normalized") + num_tuples = uniform_array.GetNumberOfTuples() + vtk_values = [uniform_array.GetValue(i) for i in range(num_tuples)] + + # checks that the vtk cell values are equal to the data + assert np.array_equal(vtk_values, data) From f34b37bb4f6aa702107b63029b69ee5a0bed9fbd Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 2 Mar 2023 22:07:49 +0000 Subject: [PATCH 1619/2654] added test for element and nuclide plot --- tests/unit_tests/test_plotter.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_plotter.py b/tests/unit_tests/test_plotter.py index a3f1ff666..15526351a 100644 --- a/tests/unit_tests/test_plotter.py +++ b/tests/unit_tests/test_plotter.py @@ -1,5 +1,6 @@ -import openmc import numpy as np +import openmc +import pytest def test_calculate_cexs_elem_mat_sab(): @@ -25,3 +26,18 @@ def test_calculate_cexs_elem_mat_sab(): assert len(energy_grid) > 1 assert len(data) == 1 assert len(data[0]) == len(energy_grid) + + +@pytest.mark.parametrize("this, data_type", [("Li", "element"), ("Li6", "nuclide")]) +def test_calculate_cexs_with_element(this, data_type): + + # single type (reaction) + energy_grid, data = openmc.plotter.calculate_cexs( + this=this, data_type=data_type, types=[205] + ) + + assert isinstance(energy_grid, np.ndarray) + assert isinstance(data, np.ndarray) + assert len(energy_grid) > 1 + assert len(data) == 1 + assert len(data[0]) == len(energy_grid) From 33f9ab708384d9ee20afb1f9572a2d6941cc76df Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 2 Mar 2023 22:14:14 +0000 Subject: [PATCH 1620/2654] testing muliple reactions for elements+nuclides --- tests/unit_tests/test_plotter.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/unit_tests/test_plotter.py b/tests/unit_tests/test_plotter.py index 15526351a..be420c3e8 100644 --- a/tests/unit_tests/test_plotter.py +++ b/tests/unit_tests/test_plotter.py @@ -41,3 +41,17 @@ def test_calculate_cexs_with_element(this, data_type): assert len(energy_grid) > 1 assert len(data) == 1 assert len(data[0]) == len(energy_grid) + + # two types (reaction) + energy_grid, data = openmc.plotter.calculate_cexs( + this=this, data_type=data_type, types=[2, "elastic"] + ) + + assert isinstance(energy_grid, np.ndarray) + assert isinstance(data, np.ndarray) + assert len(energy_grid) > 1 + assert len(data) == 2 + assert len(data[0]) == len(energy_grid) + assert len(data[0]) == len(energy_grid) + # reactions are both the same MT number 2 is elastic + assert np.array_equal(data[0], data[1]) From 7f16f46beddff4d6090a154dc5270e35d31ce5a3 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 2 Mar 2023 23:52:00 +0000 Subject: [PATCH 1621/2654] material and plot_xs tests for plotter.py --- tests/unit_tests/test_plotter.py | 46 ++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/tests/unit_tests/test_plotter.py b/tests/unit_tests/test_plotter.py index be420c3e8..081fb520d 100644 --- a/tests/unit_tests/test_plotter.py +++ b/tests/unit_tests/test_plotter.py @@ -1,22 +1,27 @@ import numpy as np import openmc import pytest +from matplotlib.figure import Figure -def test_calculate_cexs_elem_mat_sab(): - """Checks that sab cross sections are included in the - _calculate_cexs_elem_mat method and have the correct shape""" - +@pytest.fixture(scope="module") +def test_mat(): mat_1 = openmc.Material() mat_1.add_element("H", 4.0, "ao") mat_1.add_element("O", 4.0, "ao") mat_1.add_element("C", 4.0, "ao") + return mat_1 - mat_1.add_s_alpha_beta("c_C6H6") - mat_1.set_density("g/cm3", 0.865) + +def test_calculate_cexs_elem_mat_sab(test_mat): + """Checks that sab cross sections are included in the + _calculate_cexs_elem_mat method and have the correct shape""" + + test_mat.add_s_alpha_beta("c_C6H6") + test_mat.set_density("g/cm3", 0.865) energy_grid, data = openmc.plotter._calculate_cexs_elem_mat( - mat_1, + test_mat, ["inelastic"], sab_name="c_C6H6", ) @@ -28,7 +33,7 @@ def test_calculate_cexs_elem_mat_sab(): assert len(data[0]) == len(energy_grid) -@pytest.mark.parametrize("this, data_type", [("Li", "element"), ("Li6", "nuclide")]) +@pytest.mark.parametrize("this,data_type", [("Li", "element"), ("Li6", "nuclide")]) def test_calculate_cexs_with_element(this, data_type): # single type (reaction) @@ -55,3 +60,28 @@ def test_calculate_cexs_with_element(this, data_type): assert len(data[0]) == len(energy_grid) # reactions are both the same MT number 2 is elastic assert np.array_equal(data[0], data[1]) + + +def test_calculate_cexs_with_materials(test_mat): + energy_grid, data = openmc.plotter.calculate_cexs( + this=test_mat, types=[205], data_type="material" + ) + + assert isinstance(energy_grid, np.ndarray) + assert isinstance(data, np.ndarray) + assert len(energy_grid) > 1 + assert len(data) == 1 + assert len(data[0]) == len(energy_grid) + + +@pytest.mark.parametrize(("this,data_type"), [("Be", "element"), ("Be9", "nuclide")]) +def test_plot_xs(this, data_type): + assert isinstance( + openmc.plotter.plot_xs(this, data_type=data_type, types=["total"]), Figure + ) + + +def test_plot_xs_mat(test_mat): + assert isinstance( + openmc.plotter.plot_xs(test_mat, data_type="material", types=["total"]), Figure + ) From c20f115cb936eb0b95cd72a87580a3570b93daa2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 3 Mar 2023 11:02:48 -0600 Subject: [PATCH 1622/2654] Change exception in decay source processing to warning --- openmc/data/decay.py | 4 ++-- openmc/stats/univariate.py | 26 ++++++++++++++------------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/openmc/data/decay.py b/openmc/data/decay.py index d00242438..57327c07f 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -558,9 +558,9 @@ class Decay(EqualityMixin): raise NotImplementedError("Multiple interpolation regions: {name}, {particle}") interpolation = INTERPOLATION_SCHEME[f.interpolation[0]] if interpolation not in ('histogram', 'linear-linear'): - raise NotImplementedError( + warn( f"Continuous spectra with {interpolation} interpolation " - f"({name}, {particle}) not supported") + f"({name}, {particle}) encountered.") intensity = spectra['continuous_normalization'].n rates = decay_constant * intensity * f.y diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 64627a4e1..240f13d14 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -834,10 +834,6 @@ class Tabular(Univariate): self._interpolation = interpolation def cdf(self): - if not self.interpolation in ('histogram', 'linear-linear'): - raise NotImplementedError('Can only generate CDFs for tabular ' - 'distributions using histogram or ' - 'linear-linear interpolation') c = np.zeros_like(self.x) x = self.x p = self.p @@ -846,15 +842,16 @@ class Tabular(Univariate): c[1:] = p[:-1] * np.diff(x) elif self.interpolation == 'linear-linear': c[1:] = 0.5 * (p[:-1] + p[1:]) * np.diff(x) + else: + raise NotImplementedError('Can only generate CDFs for tabular ' + 'distributions using histogram or ' + 'linear-linear interpolation') + return np.cumsum(c) def mean(self): """Compute the mean of the tabular distribution""" - if not self.interpolation in ('histogram', 'linear-linear'): - raise NotImplementedError('Can only compute mean for tabular ' - 'distributions using histogram ' - 'or linear-linear interpolation.') if self.interpolation == 'linear-linear': mean = 0.0 for i in range(1, len(self.x)): @@ -875,6 +872,10 @@ class Tabular(Univariate): x_r = self.x[1:] p_l = self.p[:-1] mean = (0.5 * (x_l + x_r) * (x_r - x_l) * p_l).sum() + else: + raise NotImplementedError('Can only compute mean for tabular ' + 'distributions using histogram ' + 'or linear-linear interpolation.') # Normalize for when integral of distribution is not 1 mean /= self.integral() @@ -886,10 +887,6 @@ class Tabular(Univariate): self.p /= self.cdf().max() def sample(self, n_samples=1, seed=None): - if not self.interpolation in ('histogram', 'linear-linear'): - raise NotImplementedError('Can only sample tabular distributions ' - 'using histogram or ' - 'linear-linear interpolation') np.random.seed(seed) xi = np.random.rand(n_samples) @@ -942,6 +939,11 @@ class Tabular(Univariate): m[non_zero] = x_i[non_zero] + (np.sqrt(quad) - p_i[non_zero]) / m[non_zero] samples_out = m + else: + raise NotImplementedError('Can only sample tabular distributions ' + 'using histogram or ' + 'linear-linear interpolation') + assert all(samples_out < self.x[-1]) return samples_out From c1232a83e0a259dc74188ce137f30bfff09b3177 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 3 Mar 2023 15:03:22 -0600 Subject: [PATCH 1623/2654] Add volume arguments on several methods in Material class --- openmc/material.py | 46 ++++++++++++++++++++++++------- tests/unit_tests/test_material.py | 16 +++++++++-- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index a1b3367a9..4004b77d9 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1029,7 +1029,8 @@ class Material(IDManagerMixin): return nuclides - def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False): + def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False, + volume: Optional[float] = None): """Returns the activity of the material or for each nuclide in the material in units of [Bq], [Bq/g] or [Bq/cm3]. @@ -1044,6 +1045,10 @@ class Material(IDManagerMixin): by_nuclide : bool Specifies if the activity should be returned for the material as a whole or per nuclide. Default is False. + volume : float, optional + Volume of the material if not assigned directly + + .. versionadded:: 0.13.3 Returns ------- @@ -1057,7 +1062,7 @@ class Material(IDManagerMixin): cv.check_type('by_nuclide', by_nuclide, bool) if units == 'Bq': - multiplier = self.volume + multiplier = volume if volume is not None else self.volume elif units == 'Bq/cm3': multiplier = 1 elif units == 'Bq/g': @@ -1070,7 +1075,8 @@ class Material(IDManagerMixin): return activity if by_nuclide else sum(activity.values()) - def get_decay_heat(self, units: str = 'W', by_nuclide: bool = False): + def get_decay_heat(self, units: str = 'W', by_nuclide: bool = False, + volume: Optional[float] = None): """Returns the decay heat of the material or for each nuclide in the material in units of [W], [W/g] or [W/cm3]. @@ -1085,6 +1091,10 @@ class Material(IDManagerMixin): by_nuclide : bool Specifies if the decay heat should be returned for the material as a whole or per nuclide. Default is False. + volume : float, optional + Volume of the material if not assigned directly + + .. versionadded:: 0.13.3 Returns ------- @@ -1098,7 +1108,7 @@ class Material(IDManagerMixin): cv.check_type('by_nuclide', by_nuclide, bool) if units == 'W': - multiplier = self.volume + multiplier = volume if volume is not None else self.volume elif units == 'W/cm3': multiplier = 1 elif units == 'W/g': @@ -1113,11 +1123,18 @@ class Material(IDManagerMixin): return decayheat if by_nuclide else sum(decayheat.values()) - def get_nuclide_atoms(self): + def get_nuclide_atoms(self, volume: Optional[float] = None): """Return number of atoms of each nuclide in the material .. versionadded:: 0.13.1 + Parameters + ---------- + volume : float, optional + Volume of the material if not assigned directly + + .. versionadded:: 0.13.3 + Returns ------- dict @@ -1125,11 +1142,13 @@ class Material(IDManagerMixin): atoms present in the material. """ - if self.volume is None: + if volume is None: + volume = self.volume + if volume is None: raise ValueError("Volume must be set in order to determine atoms.") atoms = {} for nuclide, atom_per_bcm in self.get_nuclide_atom_densities().items(): - atoms[nuclide] = 1.0e24 * atom_per_bcm * self.volume + atoms[nuclide] = 1.0e24 * atom_per_bcm * volume return atoms def get_mass_density(self, nuclide: Optional[str] = None): @@ -1154,7 +1173,7 @@ class Material(IDManagerMixin): mass_density += density_i return mass_density - def get_mass(self, nuclide: Optional[str] = None): + def get_mass(self, nuclide: Optional[str] = None, volume: Optional[float] = None): """Return mass of one or all nuclides. Note that this method requires that the :attr:`Material.volume` has @@ -1165,6 +1184,11 @@ class Material(IDManagerMixin): nuclides : str, optional Nuclide for which mass is desired. If not specified, the density for the entire material is given. + volume : float, optional + Volume of the material if not assigned directly + + .. versionadded:: 0.13.3 + Returns ------- @@ -1172,9 +1196,11 @@ class Material(IDManagerMixin): Mass of the nuclide/material in [g] """ - if self.volume is None: + if volume is None: + volume = self.volume + if volume is None: raise ValueError("Volume must be set in order to determine mass.") - return self.volume*self.get_mass_density(nuclide) + return volume*self.get_mass_density(nuclide) def clone(self, memo: Optional[dict] = None): """Create a copy of this material with a new unique ID. diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index e435c7493..3b93b6879 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -377,6 +377,9 @@ def test_get_nuclide_atoms(): atoms = mat.get_nuclide_atoms() assert atoms['Li6'] == pytest.approx(mat.density * mat.volume) + atoms = mat.get_nuclide_atoms(volume=10.0) + assert atoms['Li6'] == pytest.approx(mat.density * 10.0) + def test_mass(): m = openmc.Material() @@ -394,6 +397,9 @@ def test_mass(): assert m.get_mass() == pytest.approx(20.0) assert m.fissionable_mass == pytest.approx(10.0) + # Test with volume specified as argument + assert m.get_mass('Zr90', volume=1.0) == pytest.approx(1.0) + def test_materials(run_in_tmpdir): m1 = openmc.Material() @@ -544,11 +550,14 @@ def test_get_activity(): m4.volume = 10. assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq] + # Test with volume specified as argument + assert pytest.approx(m4.get_activity(units='Bq', volume=1.0)) == 355978108155965.94*3/2 + def test_get_decay_heat(): # Set chain file for testing openmc.config['chain_file'] = Path(__file__).parents[1] / 'chain_simple.xml' - + """Tests the decay heat of stable, metastable and active materials""" m1 = openmc.Material() m1.add_nuclide("U235", 0.2) @@ -589,7 +598,10 @@ def test_get_decay_heat(): # volume is required to calculate total decay heat m4.volume = 10. assert pytest.approx(m4.get_decay_heat(units='W')) == 40175.15720273193*3/2*10 # [W] - + + # Test with volume specified as argument + assert pytest.approx(m4.get_decay_heat(units='W', volume=1.0)) == 40175.15720273193*3/2 + def test_decay_photon_energy(): # Set chain file for testing From 59467633230660270fb74d0e6ceb0442b93e9680 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 4 Mar 2023 15:51:56 -0600 Subject: [PATCH 1624/2654] Moving origin data member down into Cylindrical/Spherical mesh using intermediate class --- include/openmc/mesh.h | 30 ++++++++++++++++++++++++++---- src/mesh.cpp | 14 ++++++++------ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 9554a5143..6ae076106 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -75,6 +75,12 @@ public: // Methods + //! Update a position to the local coordinates of the mesh + virtual void to_local_coords(Position& r) const {}; + + //! Return a position in the local coordinates of the mesh + virtual Position local_coords(const Position& r) const { return r; }; + //! Determine which bins were crossed by a particle // //! \param[in] r0 Previous position of the particle @@ -160,7 +166,7 @@ public: } }; - int get_bin(Position r) const override; + virtual int get_bin(Position r) const; int n_bins() const override; @@ -241,11 +247,27 @@ public: xt::xtensor lower_left_; //!< Lower-left coordinates of mesh xt::xtensor upper_right_; //!< Upper-right coordinates of mesh std::array shape_; //!< Number of mesh elements in each dimension - Position origin_ {0.0, 0.0, 0.0}; protected: }; +class PeriodicStructuredMesh : public StructuredMesh { + +public: + PeriodicStructuredMesh() = default; + PeriodicStructuredMesh(pugi::xml_node node) : StructuredMesh {node} {}; + + void to_local_coords(Position& r) const override { r -= origin_; }; + + Position local_coords(const Position& r) const override + { + return r - origin_; + }; + + // Data members + Position origin_ {0.0, 0.0, 0.0}; +}; + //============================================================================== //! Tessellation of n-dimensional Euclidean space by congruent squares or cubes //============================================================================== @@ -336,7 +358,7 @@ public: int set_grid(); }; -class CylindricalMesh : public StructuredMesh { +class CylindricalMesh : public PeriodicStructuredMesh { public: // Constructors CylindricalMesh() = default; @@ -390,7 +412,7 @@ private: } }; -class SphericalMesh : public StructuredMesh { +class SphericalMesh : public PeriodicStructuredMesh { public: // Constructors SphericalMesh() = default; diff --git a/src/mesh.cpp b/src/mesh.cpp index e0fa305ed..eca1d2a3f 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -446,8 +446,8 @@ void StructuredMesh::raytrace_mesh( // translate start and end positions, // this needs to come after the get_indices call because it does its own translation - r0 -= origin_; - r1 -= origin_; + to_local_coords(r0); + to_local_coords(r1); // Calculate initial distances to next surfaces in all three dimensions std::array distances; @@ -952,7 +952,8 @@ void RectilinearMesh::to_hdf5(hid_t group) const // CylindricalMesh implementation //============================================================================== -CylindricalMesh::CylindricalMesh(pugi::xml_node node) : StructuredMesh {node} +CylindricalMesh::CylindricalMesh(pugi::xml_node node) + : PeriodicStructuredMesh {node} { n_dimension_ = 3; @@ -976,7 +977,7 @@ std::string CylindricalMesh::get_mesh_type() const StructuredMesh::MeshIndex CylindricalMesh::get_indices( Position r, bool& in_mesh) const { - r -= origin_; + to_local_coords(r); Position mapped_r; mapped_r[0] = std::hypot(r.x, r.y); @@ -1189,7 +1190,8 @@ void CylindricalMesh::to_hdf5(hid_t group) const // SphericalMesh implementation //============================================================================== -SphericalMesh::SphericalMesh(pugi::xml_node node) : StructuredMesh {node} +SphericalMesh::SphericalMesh(pugi::xml_node node) + : PeriodicStructuredMesh {node} { n_dimension_ = 3; @@ -1213,7 +1215,7 @@ std::string SphericalMesh::get_mesh_type() const StructuredMesh::MeshIndex SphericalMesh::get_indices( Position r, bool& in_mesh) const { - r -= origin_; + to_local_coords(r); Position mapped_r; mapped_r[0] = r.norm(); From b02e558fae56486aed8d97ee1f00e8831be3f317 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 4 Mar 2023 23:57:55 -0600 Subject: [PATCH 1625/2654] Adding docstring. Updating method name --- include/openmc/mesh.h | 6 +++--- src/mesh.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 6ae076106..f19a22c09 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -76,7 +76,7 @@ public: // Methods //! Update a position to the local coordinates of the mesh - virtual void to_local_coords(Position& r) const {}; + virtual void local_coords(Position& r) const {}; //! Return a position in the local coordinates of the mesh virtual Position local_coords(const Position& r) const { return r; }; @@ -257,7 +257,7 @@ public: PeriodicStructuredMesh() = default; PeriodicStructuredMesh(pugi::xml_node node) : StructuredMesh {node} {}; - void to_local_coords(Position& r) const override { r -= origin_; }; + void local_coords(Position& r) const override { r -= origin_; }; Position local_coords(const Position& r) const override { @@ -265,7 +265,7 @@ public: }; // Data members - Position origin_ {0.0, 0.0, 0.0}; + Position origin_ {0.0, 0.0, 0.0}; //!< Origin of the mesh }; //============================================================================== diff --git a/src/mesh.cpp b/src/mesh.cpp index eca1d2a3f..9020a95aa 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -446,8 +446,8 @@ void StructuredMesh::raytrace_mesh( // translate start and end positions, // this needs to come after the get_indices call because it does its own translation - to_local_coords(r0); - to_local_coords(r1); + local_coords(r0); + local_coords(r1); // Calculate initial distances to next surfaces in all three dimensions std::array distances; @@ -977,7 +977,7 @@ std::string CylindricalMesh::get_mesh_type() const StructuredMesh::MeshIndex CylindricalMesh::get_indices( Position r, bool& in_mesh) const { - to_local_coords(r); + local_coords(r); Position mapped_r; mapped_r[0] = std::hypot(r.x, r.y); @@ -1215,7 +1215,7 @@ std::string SphericalMesh::get_mesh_type() const StructuredMesh::MeshIndex SphericalMesh::get_indices( Position r, bool& in_mesh) const { - to_local_coords(r); + local_coords(r); Position mapped_r; mapped_r[0] = r.norm(); From 1a9449debce3036b3ff3cf5e7b30662bae5b6b55 Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 6 Mar 2023 20:36:34 +0000 Subject: [PATCH 1626/2654] finding data_type arg automatically --- openmc/plotter.py | 131 +++++++++++++++---------------- tests/unit_tests/test_plotter.py | 28 +++---- 2 files changed, 76 insertions(+), 83 deletions(-) diff --git a/openmc/plotter.py b/openmc/plotter.py index e2d18d085..541b05f0b 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -53,16 +53,15 @@ _MIN_E = 1.e-5 _MAX_E = 20.e6 -def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, - axis=None, sab_name=None, ce_cross_sections=None, - mg_cross_sections=None, enrichment=None, plot_CE=True, orders=None, - divisor_orders=None, **kwargs): +def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, + sab_name=None, ce_cross_sections=None, mg_cross_sections=None, + enrichment=None, plot_CE=True, orders=None, divisor_orders=None): """Creates a figure of continuous-energy cross sections for this item. Parameters ---------- - this : str or openmc.Material - Object to source data from + this : {str, openmc.Nuclide, openmc.Element, openmc.Macroscopic, openmc.Material} + Object to source data from. Nuclides and Elements can be input as a str types : Iterable of values of PLOT_TYPES The type of cross sections to include in the plot. divisor_types : Iterable of values of PLOT_TYPES, optional @@ -74,9 +73,6 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, temperature of 294K will be plotted. Note that the nearest temperature in the library for each nuclide will be used as opposed to using any interpolation. - data_type : {'nuclide', 'element', 'material', 'macroscopic'}, optional - Type of object to plot. If not specified, a guess is made based on the - `this` argument. axis : matplotlib.axes, optional A previously generated axis to use for plotting. If not specified, a new axis and figure will be generated. @@ -101,9 +97,6 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, multi-group data. divisor_orders : Iterable of Integral, optional Same as orders, but for divisor_types - **kwargs - All keyword arguments are passed to - :func:`matplotlib.pyplot.figure`. Returns ------- @@ -117,27 +110,11 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, import matplotlib.pyplot as plt cv.check_type("plot_CE", plot_CE, bool) - - if data_type is None: - if isinstance(this, openmc.Nuclide): - data_type = 'nuclide' - elif isinstance(this, openmc.Element): - data_type = 'element' - elif isinstance(this, openmc.Material): - data_type = 'material' - elif isinstance(this, openmc.Macroscopic): - data_type = 'macroscopic' - elif isinstance(this, str): - if this[-1] in string.digits: - data_type = 'nuclide' - else: - data_type = 'element' - else: - raise TypeError("Invalid type for plotting") + cv.check_type("this", this, (str, openmc.Nuclide, openmc.Element, openmc.Material)) if plot_CE: # Calculate for the CE cross sections - E, data = calculate_cexs(this, data_type, types, temperature, sab_name, + E, data = calculate_cexs(this, types, temperature, sab_name, ce_cross_sections, enrichment) if divisor_types: cv.check_length('divisor types', divisor_types, len(types)) @@ -160,13 +137,13 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, data = data_new else: # Calculate for MG cross sections - E, data = calculate_mgxs(this, data_type, types, orders, temperature, + E, data = calculate_mgxs(this, types, orders, temperature, mg_cross_sections, ce_cross_sections, enrichment) if divisor_types: cv.check_length('divisor types', divisor_types, len(types)) - Ediv, data_div = calculate_mgxs(this, data_type, divisor_types, + Ediv, data_div = calculate_mgxs(this, divisor_types, divisor_orders, temperature, mg_cross_sections, ce_cross_sections, enrichment) @@ -201,23 +178,35 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, ax.set_xlim(_MIN_E, _MAX_E) else: ax.set_xlim(E[-1], E[0]) + + if isinstance(this, str): + # first entry in ELEMENT_SYMBOL is a neutron, the 1 removes this entry + if this in list(openmc.data.ELEMENT_SYMBOL.values())[1:]: + this = openmc.Element(this) + else: + this = openmc.Nuclide(this) + if divisor_types: - if data_type == 'nuclide': + if isinstance(this, openmc.Nuclide): ylabel = 'Nuclidic Microscopic Data' - elif data_type == 'element': + elif isinstance(this, openmc.Element): ylabel = 'Elemental Microscopic Data' - elif data_type == 'material' or data_type == 'macroscopic': + elif isinstance(this, openmc.Material) or isinstance(this, openmc.Macroscopic): ylabel = 'Macroscopic Data' + else: + raise TypeError("Invalid type for plotting") else: - if data_type == 'nuclide': + if isinstance(this, openmc.Nuclide): ylabel = 'Microscopic Cross Section [b]' - elif data_type == 'element': + elif isinstance(this, openmc.Element): ylabel = 'Elemental Cross Section [b]' - elif data_type == 'material' or data_type == 'macroscopic': + elif isinstance(this, openmc.Material) or isinstance(this, openmc.Macroscopic): ylabel = 'Macroscopic Cross Section [1/cm]' + else: + raise TypeError("Invalid type for plotting") ax.set_ylabel(ylabel) ax.legend(loc='best') - name = this.name if data_type == 'material' else this + name = this.name if isinstance(this, openmc.Material) else this if len(types) > 1: ax.set_title('Cross Sections for ' + name) else: @@ -226,16 +215,14 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, return fig -def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, +def calculate_cexs(this, types, temperature=294., sab_name=None, cross_sections=None, enrichment=None): """Calculates continuous-energy cross sections of a requested type. Parameters ---------- this : {str, openmc.Nuclide, openmc.Element, openmc.Material} - Object to source data from - data_type : {'nuclide', 'element', 'material'} - Type of object to plot + Object to source data from. Nuclides and Elements can be input as a str types : Iterable of values of PLOT_TYPES The type of cross sections to calculate temperature : float, optional @@ -262,39 +249,46 @@ def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, """ # Check types + cv.check_type('this', this, (str, openmc.Nuclide, openmc.Element, openmc.Material)) cv.check_type('temperature', temperature, Real) if sab_name: cv.check_type('sab_name', sab_name, str) if enrichment: cv.check_type('enrichment', enrichment, Real) - if data_type == 'nuclide': - if isinstance(this, str): - nuc = openmc.Nuclide(this) + # this is a nuclide or element if it is a string + if isinstance(this, str): + # first entry in ELEMENT_SYMBOL is a neutron, the 1 removes this entry + if this in list(openmc.data.ELEMENT_SYMBOL.values())[1:]: + this = openmc.Element(this) else: - nuc = this - energy_grid, xs = _calculate_cexs_nuclide(nuc, types, temperature, + this = openmc.Nuclide(this) + + if isinstance(this, openmc.Nuclide): + energy_grid, xs = _calculate_cexs_nuclide(this, types, temperature, sab_name, cross_sections) + # Convert xs (Iterable of Callable) to a grid of cross section values # calculated on the points in energy_grid for consistency with the # element and material functions. data = np.zeros((len(types), len(energy_grid))) for line in range(len(types)): data[line, :] = xs[line](energy_grid) - elif data_type == 'element': - if isinstance(this, str): - elem = openmc.Element(this) - else: - elem = this - energy_grid, data = _calculate_cexs_elem_mat(elem, types, temperature, + + elif isinstance(this, openmc.Element): + energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, cross_sections, sab_name, enrichment) - elif data_type == 'material': - cv.check_type('this', this, openmc.Material) + + elif isinstance(this, openmc.Material): energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, cross_sections) else: - raise TypeError("Invalid type") + msg = ( + f"{this} is an invalid type, acceptable types are str, " + "openmc.Nuclide, openmc.Element, openmc.Material." + ) + raise TypeError(msg) return energy_grid, data @@ -583,8 +577,7 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., name = nuclide[0] nuc = nuclide[1] sab_tab = sabs[name] - temp_E, temp_xs = calculate_cexs(nuc, 'nuclide', types, T, sab_tab, - cross_sections) + temp_E, temp_xs = calculate_cexs(nuc, types, T, sab_tab, cross_sections) E.append(temp_E) # Since the energy grids are different, store the cross sections as # a tabulated function so they can be calculated on any grid needed. @@ -611,7 +604,7 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., return energy_grid, data -def calculate_mgxs(this, data_type, types, orders=None, temperature=294., +def calculate_mgxs(this, types, orders=None, temperature=294., cross_sections=None, ce_cross_sections=None, enrichment=None): """Calculates multi-group cross sections of a requested type. @@ -622,10 +615,8 @@ def calculate_mgxs(this, data_type, types, orders=None, temperature=294., Parameters ---------- - this : str or openmc.Material - Object to source data from - data_type : {'nuclide', 'element', 'material', 'macroscopic'} - Type of object to plot + this : {str, openmc.Nuclide, openmc.Element, openmc.Macroscopic, openmc.Material} + Object to source data from. Nuclides and Elements can be input as a str types : Iterable of values of PLOT_TYPES_MGXS The type of cross sections to calculate orders : Iterable of Integral, optional @@ -665,10 +656,18 @@ def calculate_mgxs(this, data_type, types, orders=None, temperature=294., cv.check_type("cross_sections", cross_sections, str) library = openmc.MGXSLibrary.from_hdf5(cross_sections) - if data_type in ('nuclide', 'macroscopic'): + # this is a nuclide or element if it is a string + if isinstance(this, str): + # first entry in ELEMENT_SYMBOL is a neutron, the 1 removes this entry + if this in list(openmc.data.ELEMENT_SYMBOL.values())[1:]: + this = openmc.Element(this) + else: + this = openmc.Nuclide(this) + + if isinstance(this, openmc.Nuclide) or isinstance(this, openmc.Macroscopic): mgxs = _calculate_mgxs_nuc_macro(this, types, library, orders, temperature) - elif data_type in ('element', 'material'): + elif isinstance(this, openmc.Element) or isinstance(this, openmc.Material): mgxs = _calculate_mgxs_elem_mat(this, types, library, orders, temperature, ce_cross_sections, enrichment) diff --git a/tests/unit_tests/test_plotter.py b/tests/unit_tests/test_plotter.py index 081fb520d..f7c731f1d 100644 --- a/tests/unit_tests/test_plotter.py +++ b/tests/unit_tests/test_plotter.py @@ -4,7 +4,7 @@ import pytest from matplotlib.figure import Figure -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def test_mat(): mat_1 = openmc.Material() mat_1.add_element("H", 4.0, "ao") @@ -12,7 +12,6 @@ def test_mat(): mat_1.add_element("C", 4.0, "ao") return mat_1 - def test_calculate_cexs_elem_mat_sab(test_mat): """Checks that sab cross sections are included in the _calculate_cexs_elem_mat method and have the correct shape""" @@ -33,12 +32,11 @@ def test_calculate_cexs_elem_mat_sab(test_mat): assert len(data[0]) == len(energy_grid) -@pytest.mark.parametrize("this,data_type", [("Li", "element"), ("Li6", "nuclide")]) -def test_calculate_cexs_with_element(this, data_type): - +@pytest.mark.parametrize("this", ["Li", "Li6", openmc.Nuclide('Li6'), openmc.Element('Li')]) +def test_calculate_cexs_with_nuclide_and_element(this): # single type (reaction) energy_grid, data = openmc.plotter.calculate_cexs( - this=this, data_type=data_type, types=[205] + this=this, types=[205] ) assert isinstance(energy_grid, np.ndarray) @@ -47,9 +45,9 @@ def test_calculate_cexs_with_element(this, data_type): assert len(data) == 1 assert len(data[0]) == len(energy_grid) - # two types (reaction) + # two types (reactions) energy_grid, data = openmc.plotter.calculate_cexs( - this=this, data_type=data_type, types=[2, "elastic"] + this=this, types=[2, "elastic"] ) assert isinstance(energy_grid, np.ndarray) @@ -64,7 +62,7 @@ def test_calculate_cexs_with_element(this, data_type): def test_calculate_cexs_with_materials(test_mat): energy_grid, data = openmc.plotter.calculate_cexs( - this=test_mat, types=[205], data_type="material" + this=test_mat, types=[205] ) assert isinstance(energy_grid, np.ndarray) @@ -74,14 +72,10 @@ def test_calculate_cexs_with_materials(test_mat): assert len(data[0]) == len(energy_grid) -@pytest.mark.parametrize(("this,data_type"), [("Be", "element"), ("Be9", "nuclide")]) -def test_plot_xs(this, data_type): - assert isinstance( - openmc.plotter.plot_xs(this, data_type=data_type, types=["total"]), Figure - ) +@pytest.mark.parametrize("this", ["Be", "Be9", openmc.Nuclide('Be9'), openmc.Element('Be')]) +def test_plot_xs(this): + assert isinstance(openmc.plotter.plot_xs(this, types=['total']), Figure) def test_plot_xs_mat(test_mat): - assert isinstance( - openmc.plotter.plot_xs(test_mat, data_type="material", types=["total"]), Figure - ) + assert isinstance(openmc.plotter.plot_xs(test_mat, types=['total']), Figure) From ab4237c037a3f142e50168690c2c0dca5edefcf5 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 7 Mar 2023 14:36:07 -0500 Subject: [PATCH 1627/2654] use get_reshaped_data in tests --- tests/unit_tests/test_cylindrical_mesh.py | 2 +- tests/unit_tests/test_spherical_mesh.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index e67f21b15..9c8ce79f9 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -93,6 +93,6 @@ def test_offset_mesh(model, estimator, origin): # check that the lower half of the mesh contains a tally result # and that the upper half is zero - mean = tally.mean.reshape(mesh.dimension[::-1]).T + mean = tally.get_reshaped_data('mean', expand_dims=True) # assert np.count_nonzero(mean[:, :, :5]) == mean.size / 2 # assert np.count_nonzero(mean[:, :, 5:]) == 0 diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index d6ac435c2..489c4bd34 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -93,6 +93,6 @@ def test_offset_mesh(model, estimator, origin): # check that the lower half of the mesh contains a tally result # and that the upper half is zero - mean = tally.mean.reshape(mesh.dimension[::-1]).T + mean = tally.get_reshaped_data('mean', expand_dims=True) # assert np.count_nonzero(mean[:, :, :5]) == mean.size / 2 # assert np.count_nonzero(mean[:, :, 5:]) == 0 From da89de0034ff1c5d319424627f76672a4c3678d9 Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 7 Mar 2023 20:40:03 +0000 Subject: [PATCH 1628/2654] updated action versions to latest major release --- .github/workflows/dockerhub-publish-dagmc-libmesh.yml | 8 ++++---- .github/workflows/dockerhub-publish-dagmc.yml | 8 ++++---- .github/workflows/dockerhub-publish-dev.yml | 8 ++++---- .../workflows/dockerhub-publish-develop-dagmc-libmesh.yml | 8 ++++---- .github/workflows/dockerhub-publish-develop-dagmc.yml | 8 ++++---- .github/workflows/dockerhub-publish-develop-libmesh.yml | 8 ++++---- .github/workflows/dockerhub-publish-libmesh.yml | 8 ++++---- .../workflows/dockerhub-publish-release-dagmc-libmesh.yml | 8 ++++---- .github/workflows/dockerhub-publish-release-dagmc.yml | 8 ++++---- .github/workflows/dockerhub-publish-release-libmesh.yml | 8 ++++---- .github/workflows/dockerhub-publish-release.yml | 8 ++++---- .github/workflows/dockerhub-publish.yml | 8 ++++---- 12 files changed, 48 insertions(+), 48 deletions(-) diff --git a/.github/workflows/dockerhub-publish-dagmc-libmesh.yml b/.github/workflows/dockerhub-publish-dagmc-libmesh.yml index 3336c653e..3f0b5ab9b 100644 --- a/.github/workflows/dockerhub-publish-dagmc-libmesh.yml +++ b/.github/workflows/dockerhub-publish-dagmc-libmesh.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:latest-dagmc-libmesh diff --git a/.github/workflows/dockerhub-publish-dagmc.yml b/.github/workflows/dockerhub-publish-dagmc.yml index 663e1fd17..b6ba2f075 100644 --- a/.github/workflows/dockerhub-publish-dagmc.yml +++ b/.github/workflows/dockerhub-publish-dagmc.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:latest-dagmc diff --git a/.github/workflows/dockerhub-publish-dev.yml b/.github/workflows/dockerhub-publish-dev.yml index a08d13e5a..d2603ead4 100644 --- a/.github/workflows/dockerhub-publish-dev.yml +++ b/.github/workflows/dockerhub-publish-dev.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:develop diff --git a/.github/workflows/dockerhub-publish-develop-dagmc-libmesh.yml b/.github/workflows/dockerhub-publish-develop-dagmc-libmesh.yml index 0c90d8796..354f0a020 100644 --- a/.github/workflows/dockerhub-publish-develop-dagmc-libmesh.yml +++ b/.github/workflows/dockerhub-publish-develop-dagmc-libmesh.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:develop-dagmc-libmesh diff --git a/.github/workflows/dockerhub-publish-develop-dagmc.yml b/.github/workflows/dockerhub-publish-develop-dagmc.yml index b98b3dff6..36ec7a337 100644 --- a/.github/workflows/dockerhub-publish-develop-dagmc.yml +++ b/.github/workflows/dockerhub-publish-develop-dagmc.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:develop-dagmc diff --git a/.github/workflows/dockerhub-publish-develop-libmesh.yml b/.github/workflows/dockerhub-publish-develop-libmesh.yml index e42ba0b27..a89417316 100644 --- a/.github/workflows/dockerhub-publish-develop-libmesh.yml +++ b/.github/workflows/dockerhub-publish-develop-libmesh.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:develop-libmesh diff --git a/.github/workflows/dockerhub-publish-libmesh.yml b/.github/workflows/dockerhub-publish-libmesh.yml index a861c5c9c..e592ccb8e 100644 --- a/.github/workflows/dockerhub-publish-libmesh.yml +++ b/.github/workflows/dockerhub-publish-libmesh.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:latest-libmesh diff --git a/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml b/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml index 3dd830a26..c90302af4 100644 --- a/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml +++ b/.github/workflows/dockerhub-publish-release-dagmc-libmesh.yml @@ -13,20 +13,20 @@ jobs: run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:${{ env.RELEASE_VERSION }}-dagmc-libmesh diff --git a/.github/workflows/dockerhub-publish-release-dagmc.yml b/.github/workflows/dockerhub-publish-release-dagmc.yml index d7cfff019..ef66f6ead 100644 --- a/.github/workflows/dockerhub-publish-release-dagmc.yml +++ b/.github/workflows/dockerhub-publish-release-dagmc.yml @@ -13,20 +13,20 @@ jobs: run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:${{ env.RELEASE_VERSION }}-dagmc diff --git a/.github/workflows/dockerhub-publish-release-libmesh.yml b/.github/workflows/dockerhub-publish-release-libmesh.yml index d2fdbc469..72edfbc68 100644 --- a/.github/workflows/dockerhub-publish-release-libmesh.yml +++ b/.github/workflows/dockerhub-publish-release-libmesh.yml @@ -13,20 +13,20 @@ jobs: run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:${{ env.RELEASE_VERSION }}-libmesh diff --git a/.github/workflows/dockerhub-publish-release.yml b/.github/workflows/dockerhub-publish-release.yml index 4e3ad4177..22d21b4c9 100644 --- a/.github/workflows/dockerhub-publish-release.yml +++ b/.github/workflows/dockerhub-publish-release.yml @@ -13,20 +13,20 @@ jobs: run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:${{ env.RELEASE_VERSION }} diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml index 6bd0c4dc6..00a3ba316 100644 --- a/.github/workflows/dockerhub-publish.yml +++ b/.github/workflows/dockerhub-publish.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: push: true tags: openmc/openmc:latest From c487090b3f6c19b9de1adade6c6ccb261c1e1e08 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 6 Mar 2023 23:38:00 -0600 Subject: [PATCH 1629/2654] Correcting spherical to cartesian coordinate conversion --- openmc/mesh.py | 8 +- tests/unit_tests/test_mesh_to_vtk.py | 156 ++++++++++++++++++++++++--- 2 files changed, 147 insertions(+), 17 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 5294b2dd6..a0f86314d 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -446,7 +446,7 @@ class RegularMesh(StructuredMesh): if self._width is not None: self._width = None warnings.warn("Unsetting width attribute.") - + if self.lower_left is not None and any(np.isclose(self.lower_left, upper_right)): raise ValueError("Mesh cannot have zero thickness in any dimension") @@ -1533,9 +1533,9 @@ class SphericalMesh(StructuredMesh): pts_cartesian = np.copy(pts_spherical) r, theta, phi = pts_spherical[:, 0], pts_spherical[:, 1], pts_spherical[:, 2] - pts_cartesian[:, 0] = r * np.sin(phi) * np.cos(theta) - pts_cartesian[:, 1] = r * np.sin(phi) * np.sin(theta) - pts_cartesian[:, 2] = r * np.cos(phi) + pts_cartesian[:, 0] = r * np.sin(theta) * np.cos(phi) + pts_cartesian[:, 1] = r * np.sin(theta) * np.sin(phi) + pts_cartesian[:, 2] = r * np.cos(theta) return super().write_data_to_vtk( points=pts_cartesian, diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index a9dcd7243..06a5606e7 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -1,3 +1,5 @@ +from itertools import product + import numpy as np from pathlib import Path import pytest @@ -7,29 +9,77 @@ from vtk.util import numpy_support as nps import openmc +@pytest.fixture +def model(): + openmc.reset_auto_ids() + + surf1 = openmc.Sphere(r=10, boundary_type='vacuum') + surf2 = openmc.XPlane(x0=-0.001, boundary_type='vacuum') + + cell = openmc.Cell(region=-surf1 & -surf2) + + geometry = openmc.Geometry([cell]) + + settings = openmc.Settings() + settings.batches = 2 + settings.particles = 100 + settings.run_mode = 'fixed source' + + source = openmc.Source() + source.angle = openmc.stats.Isotropic() + source.energy = openmc.stats.Discrete([1.0e6], [1.0]) + source.space = openmc.stats.Point((-0.01, -0.01, -0.01)) + + settings.source = source + + model = openmc.Model(geometry=geometry, settings=settings) + + return model + regular_mesh = openmc.RegularMesh() -regular_mesh.lower_left = (0, 0, 0) -regular_mesh.upper_right = (1, 1, 1) +regular_mesh.lower_left = (-10, -10, -10) +regular_mesh.upper_right = (10, 10, 10) regular_mesh.dimension = [30, 20, 10] rectilinear_mesh = openmc.RectilinearMesh() -rectilinear_mesh.x_grid = np.linspace(1, 2, num=30) -rectilinear_mesh.y_grid = np.linspace(1, 2, num=30) -rectilinear_mesh.z_grid = np.linspace(1, 2, num=30) +rectilinear_mesh.x_grid = np.linspace(-10, 10, 6) +rectilinear_mesh.y_grid = np.logspace(0, 1, 7) +rectilinear_mesh.y_grid = \ + np.concatenate((-rectilinear_mesh.y_grid[::-1], rectilinear_mesh.y_grid)) +rectilinear_mesh.z_grid = np.linspace(-10, 10, 11) cylinder_mesh = openmc.CylindricalMesh() -cylinder_mesh.r_grid = np.linspace(1, 2, num=30) -cylinder_mesh.phi_grid = np.linspace(0, np.pi, num=50) -cylinder_mesh.z_grid = np.linspace(0, 1, num=30) +cylinder_mesh.r_grid = np.linspace(0, 10, 23) +cylinder_mesh.phi_grid = np.linspace(0, np.pi, 21) +cylinder_mesh.z_grid = np.linspace(0, 1, 15) spherical_mesh = openmc.SphericalMesh() -spherical_mesh.r_grid = np.linspace(1, 2, num=30) -spherical_mesh.phi_grid = np.linspace(0, np.pi, num=50) -spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, num=30) +spherical_mesh.r_grid = np.linspace(1, 10, 30) +spherical_mesh.phi_grid = np.linspace(0, np.pi, 25) +spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, 15) + +MESHES = [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh] + +x_plane = openmc.XPlane(x0=-0.001, boundary_type='vacuum') +y_plane = openmc.YPlane(y0=-0.001, boundary_type='vacuum') +z_plane = openmc.ZPlane(z0=-0.001, boundary_type='vacuum') + +SURFS = [x_plane, y_plane, z_plane] -@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) +def ids(mesh): + if isinstance(mesh, openmc.CylindricalMesh): + return 'cylindrical_mesh' + elif isinstance(mesh, openmc.RegularMesh): + return 'regular_mesh' + elif isinstance(mesh, openmc.RectilinearMesh): + return 'rectilinear_mesh' + elif isinstance(mesh, openmc.SphericalMesh): + return 'spherical_mesh' + + +@pytest.mark.parametrize("mesh", MESHES, ids=ids) def test_write_data_to_vtk(mesh, tmpdir): # BUILD filename = Path(tmpdir) / "out.vtk" @@ -69,7 +119,7 @@ def test_write_data_to_vtk(mesh, tmpdir): assert all(data1 == 1.0) -@pytest.mark.parametrize("mesh", [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh]) +@pytest.mark.parametrize("mesh", MESHES, ids=ids) def test_write_data_to_vtk_size_mismatch(mesh): """Checks that an error is raised when the size of the dataset doesn't match the mesh number of cells @@ -92,6 +142,7 @@ def test_write_data_to_vtk_size_mismatch(mesh): with pytest.raises(ValueError, match=expected_error_msg): mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) +<<<<<<< HEAD def test_write_data_to_vtk_round_trip(run_in_tmpdir): cmesh = openmc.CylindricalMesh() cmesh.r_grid = (0.0, 1.0, 2.0) @@ -149,3 +200,82 @@ def test_write_data_to_vtk_round_trip(run_in_tmpdir): # checks that the vtk cell values are equal to the data assert np.array_equal(vtk_values, data) +======= + +def mesh_surf_id(param): + + if isinstance(param, openmc.MeshBase): + return ids(param) + + if isinstance(param, openmc.XPlane): + return 'XPlane' + elif isinstance(param, openmc.YPlane): + return 'YPlane' + elif isinstance(param, openmc.ZPlane): + return 'ZPlane' + + +@pytest.mark.parametrize("mesh,surface", product(MESHES, SURFS), ids=mesh_surf_id) +def test_vtk_write_ordering(model, mesh, surface): + + tally = openmc.Tally() + tally.scores = ['flux'] + # use the mesh on the specified tally + mesh_filter = openmc.MeshFilter(mesh) + tally.filters = [mesh_filter] + + model.tallies = openmc.Tallies([tally]) + + # run the problem + sp_filename = model.run() + + with openmc.StatePoint(sp_filename) as sp: + mean = sp.tallies[tally.id].mean + + # write the data to a VTK file + vtk_filename = 'test.vtk' + mesh.write_data_to_vtk(vtk_filename, datasets={'mean': mean}) + + # read file + reader = vtk.vtkStructuredGridReader() + reader.SetFileName(str(vtk_filename)) + reader.Update() + + # check name of datasets + vtk_grid = reader.GetOutput() + array = vtk_grid.GetCellData().GetArray(0) + vtk_data = nps.vtk_to_numpy(array) + + # convenience function for determining if a mesh + # element has vertices in the geometry. This + # particular geometry allows us to assume that tally results + # in the element should be zero if none of its vertices lie in the geometry + def in_geom(cell): + point_ids = cell.GetPointIds() + + for i in range(point_ids.GetNumberOfIds()): + p = vtk_grid.GetPoint(point_ids.GetId(i)) + if model.geometry.find(p): + return True + + return False + + # reshape mean according to mesh dimensions + mean = mean.reshape(mesh.dimension[::-1]).T + centroid = [0.0, 0.0, 0.0] + + # check that tally and vtk array results are zero where expected + for ijk in mesh.indices: + ijk = tuple(n - 1 for n in ijk) + # get the cell from the stuctured mesh object + cell = vtk_grid.GetCell(*ijk) + if not in_geom(cell): + cell.GetCentroid(centroid) + err_msg = f'IJK: {ijk} should be zero but is not. Centroid: {centroid}' + assert mean[ijk] == 0.0, err_msg + + # need to get flat index with axes reversed due to ordering passed into the VTK file + flat_idx = np.ravel_multi_index(tuple(ijk[::-1]), mesh.dimension[::-1]) + assert vtk_data[flat_idx] == 0.0, err_msg + +>>>>>>> 641319115 (Correcting spherical to cartesian coordinate conversion) From ae57ad0e5be45619f260a3cd3d3df911467ec628 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 6 Mar 2023 23:39:15 -0600 Subject: [PATCH 1630/2654] Improving test coverage for mesh to vtk capability --- tests/unit_tests/test_mesh_to_vtk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 06a5606e7..22cdf1c1e 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -56,7 +56,7 @@ cylinder_mesh.z_grid = np.linspace(0, 1, 15) spherical_mesh = openmc.SphericalMesh() spherical_mesh.r_grid = np.linspace(1, 10, 30) -spherical_mesh.phi_grid = np.linspace(0, np.pi, 25) +spherical_mesh.phi_grid = np.linspace(0, 0.8*np.pi, 25) spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, 15) MESHES = [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh] From 285edc77b982e7abf9f89511ee2e82a59b686e53 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 8 Mar 2023 22:47:40 -0600 Subject: [PATCH 1631/2654] Corrections after rebase --- tests/unit_tests/test_mesh_to_vtk.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 22cdf1c1e..80da85d97 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -142,7 +142,6 @@ def test_write_data_to_vtk_size_mismatch(mesh): with pytest.raises(ValueError, match=expected_error_msg): mesh.write_data_to_vtk(filename="out.vtk", datasets={"label": data}) -<<<<<<< HEAD def test_write_data_to_vtk_round_trip(run_in_tmpdir): cmesh = openmc.CylindricalMesh() cmesh.r_grid = (0.0, 1.0, 2.0) @@ -200,7 +199,6 @@ def test_write_data_to_vtk_round_trip(run_in_tmpdir): # checks that the vtk cell values are equal to the data assert np.array_equal(vtk_values, data) -======= def mesh_surf_id(param): @@ -277,5 +275,3 @@ def test_vtk_write_ordering(model, mesh, surface): # need to get flat index with axes reversed due to ordering passed into the VTK file flat_idx = np.ravel_multi_index(tuple(ijk[::-1]), mesh.dimension[::-1]) assert vtk_data[flat_idx] == 0.0, err_msg - ->>>>>>> 641319115 (Correcting spherical to cartesian coordinate conversion) From a23a6c59283bedc3e5215857a8d14c92343903e5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Mar 2023 09:26:23 -0500 Subject: [PATCH 1632/2654] Improve error message when parallel HDF5 is found but MPI not enabled --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11ae71ac6..0dcaa6fb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,9 +156,9 @@ endif() find_package(HDF5 REQUIRED COMPONENTS C HL) if(HDF5_IS_PARALLEL) if(NOT OPENMC_USE_MPI) - message(FATAL_ERROR "Parallel HDF5 was detected, but the detected compiler,\ - ${CMAKE_CXX_COMPILER}, does not support MPI. An MPI-capable compiler must \ - be used with parallel HDF5.") + message(FATAL_ERROR "Parallel HDF5 was detected, but MPI was not enabled.\ + To use parallel HDF5, OpenMC needs to be built with MPI support by passing\ + -DOPENMC_USE_MPI=ON when calling cmake.") endif() message(STATUS "Using parallel HDF5") endif() From 3e6441a0d9cae4e83edd3205e421e13bb063d4b6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Mar 2023 09:45:29 -0500 Subject: [PATCH 1633/2654] Address @shimwell comments on #2412 --- openmc/material.py | 12 ++++++++---- openmc/model/model.py | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 4004b77d9..a2c6138d2 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1046,7 +1046,8 @@ class Material(IDManagerMixin): Specifies if the activity should be returned for the material as a whole or per nuclide. Default is False. volume : float, optional - Volume of the material if not assigned directly + Volume of the material. If not passed, defaults to using the + :attr:`Material.volume` attribute. .. versionadded:: 0.13.3 @@ -1092,7 +1093,8 @@ class Material(IDManagerMixin): Specifies if the decay heat should be returned for the material as a whole or per nuclide. Default is False. volume : float, optional - Volume of the material if not assigned directly + Volume of the material. If not passed, defaults to using the + :attr:`Material.volume` attribute. .. versionadded:: 0.13.3 @@ -1131,7 +1133,8 @@ class Material(IDManagerMixin): Parameters ---------- volume : float, optional - Volume of the material if not assigned directly + Volume of the material. If not passed, defaults to using the + :attr:`Material.volume` attribute. .. versionadded:: 0.13.3 @@ -1185,7 +1188,8 @@ class Material(IDManagerMixin): Nuclide for which mass is desired. If not specified, the density for the entire material is given. volume : float, optional - Volume of the material if not assigned directly + Volume of the material. If not passed, defaults to using the + :attr:`Material.volume` attribute. .. versionadded:: 0.13.3 diff --git a/openmc/model/model.py b/openmc/model/model.py index 79708d62b..45cbf8227 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -244,7 +244,7 @@ class Model: def from_model_xml(cls, path='model.xml'): """Create model from single XML file - .. vesionadded:: 0.13.3 + .. versionadded:: 0.13.3 Parameters ---------- From 2d20cd31f25c3949218dbb9a3a6350be5c961319 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Thu, 16 Mar 2023 14:37:05 -0500 Subject: [PATCH 1634/2654] initialize Discrete distribution with sequence of integers --- include/openmc/distribution.h | 1 + src/distribution.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 815ffa21a..86aa4a381 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -39,6 +39,7 @@ class Discrete : public Distribution { public: explicit Discrete(pugi::xml_node node); Discrete(const double* x, const double* p, int n); + Discrete(const double* p, int n); //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer diff --git a/src/distribution.cpp b/src/distribution.cpp index 4b4ebd69d..ce2a85705 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -41,6 +41,19 @@ Discrete::Discrete(const double* x, const double* p, int n) this->init_alias(x_vec, p_vec); } +Discrete::Discrete(const double* p, int n) +{ + std::vector p_vec(p, p + n); + std::vector x_vec(n); + + for (int i=0; iinit_alias(x_vec, p_vec); +} + void Discrete::init_alias(vector& x, vector& p) { x_ = x; From ee6975767d98f84133a0e4df3e443800a068fc32 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Thu, 16 Mar 2023 17:34:44 -0500 Subject: [PATCH 1635/2654] Use Discrete distribution for mesh sampling This version builds the independent variable by converting int to double and then converts back when sampling. --- include/openmc/distribution_spatial.h | 6 +----- src/distribution_spatial.cpp | 27 ++------------------------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index a8cc7c58e..63cbbb956 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -114,11 +114,7 @@ public: private: int32_t mesh_idx_ {C_NONE}; - double total_strength_ {0.0}; - // TODO: move to an independent class in the future that's similar - // to a discrete distribution without outcomes - std::vector mesh_CDF_; - std::vector mesh_strengths_; + UPtrDist elem_idx_; //!< Distribution of mesh element indices }; //============================================================================== diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index fb1fbf099..206f0b597 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -212,10 +212,6 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) int32_t n_bins = this->n_sources(); std::vector strengths(n_bins, 0.0); - mesh_CDF_.resize(n_bins + 1); - mesh_CDF_[0] = {0.0}; - total_strength_ = 0.0; - // Create cdfs for sampling for an element over a mesh // Volume scheme is weighted by the volume of each tet // File scheme is weighted by an array given in the xml file @@ -228,28 +224,9 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) "not match the number of entities in mesh {} ({}).", strengths.size(), mesh_id, n_bins)); } - mesh_strengths_ = std::move(strengths); + elem_idx_ = UPtrDist {new Discrete {strengths, n_bins}}; } - if (get_node_value_bool(node, "volume_normalized")) { - for (int i = 0; i < n_bins; i++) { - mesh_strengths_[i] *= mesh()->volume(i); - } - } - - total_strength_ = - std::accumulate(mesh_strengths_.begin(), mesh_strengths_.end(), 0.0); - - for (int i = 0; i < n_bins; i++) { - mesh_CDF_[i + 1] = mesh_CDF_[i] + mesh_strengths_[i] / total_strength_; - } - - if (fabs(mesh_CDF_.back() - 1.0) > FP_COINCIDENT) { - fatal_error( - fmt::format("Mesh sampling CDF is incorrectly formed. Final value is: {}", - mesh_CDF_.back())); - } - mesh_CDF_.back() = 1.0; } Position MeshSpatial::sample(uint64_t* seed) const @@ -257,7 +234,7 @@ Position MeshSpatial::sample(uint64_t* seed) const // Create random variable for sampling element from mesh double eta = prn(seed); // Sample over the CDF defined in initialization above - int32_t elem_idx = lower_bound_index(mesh_CDF_.begin(), mesh_CDF_.end(), eta); + int32_t elem_idx = elem_idx_->sample(eta); return mesh()->sample(seed, elem_idx); } From db92a64ec984b647fc71fcabb5c75288570d80a4 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Thu, 16 Mar 2023 17:51:41 -0500 Subject: [PATCH 1636/2654] rename variable for clarity; re-add volume normalization --- include/openmc/distribution_spatial.h | 2 +- src/distribution_spatial.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 63cbbb956..dc1d898fe 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -114,7 +114,7 @@ public: private: int32_t mesh_idx_ {C_NONE}; - UPtrDist elem_idx_; //!< Distribution of mesh element indices + UPtrDist elem_idx_dist_; //!< Distribution of mesh element indices }; //============================================================================== diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 206f0b597..544734d3b 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -224,8 +224,15 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) "not match the number of entities in mesh {} ({}).", strengths.size(), mesh_id, n_bins)); } - elem_idx_ = UPtrDist {new Discrete {strengths, n_bins}}; } + + if (get_node_value_bool(node, "volume_normalized")) { + for (int i = 0; i < n_bins; i++) { + strengths[i] *= mesh()->volume(i); + } + } + + elem_idx_dist_ = UPtrDist {new Discrete {strengths, n_bins}}; } @@ -234,7 +241,7 @@ Position MeshSpatial::sample(uint64_t* seed) const // Create random variable for sampling element from mesh double eta = prn(seed); // Sample over the CDF defined in initialization above - int32_t elem_idx = elem_idx_->sample(eta); + int32_t elem_idx = elem_idx_dist_->sample(eta); return mesh()->sample(seed, elem_idx); } From 09d068fa81abeebd44994422437f44caa34331d5 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Thu, 16 Mar 2023 21:16:59 -0500 Subject: [PATCH 1637/2654] syntax fixes --- src/distribution_spatial.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 544734d3b..7c5b2ed64 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -215,7 +215,6 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) // Create cdfs for sampling for an element over a mesh // Volume scheme is weighted by the volume of each tet // File scheme is weighted by an array given in the xml file - mesh_strengths_ = std::vector(n_bins, 1.0); if (check_for_node(node, "strengths")) { strengths = get_node_array(node, "strengths"); if (strengths.size() != n_bins) { @@ -232,16 +231,14 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) } } - elem_idx_dist_ = UPtrDist {new Discrete {strengths, n_bins}}; + elem_idx_dist_ = UPtrDist {new Discrete {strengths.data(), n_bins}}; } Position MeshSpatial::sample(uint64_t* seed) const { - // Create random variable for sampling element from mesh - double eta = prn(seed); // Sample over the CDF defined in initialization above - int32_t elem_idx = elem_idx_dist_->sample(eta); + int32_t elem_idx = elem_idx_dist_->sample(seed); return mesh()->sample(seed, elem_idx); } From c275933aae2e3fc035a4cdb9e9eee98755479851 Mon Sep 17 00:00:00 2001 From: Chris Keckler Date: Thu, 16 Mar 2023 21:24:53 -0700 Subject: [PATCH 1638/2654] Fix small typo in error message --- openmc/model/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 625094cce..ec35ab49f 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -636,7 +636,7 @@ class Model: if len(self.settings.volume_calculations) == 0: # Then there is no volume calculation specified - raise ValueError("The Settings.volume_calculation attribute must" + raise ValueError("The Settings.volume_calculations attribute must" " be specified before executing this method!") with _change_directory(Path(cwd)): From 29b57486871f39fc28a9e336ffc98e64afacc561 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Fri, 17 Mar 2023 08:27:09 -0500 Subject: [PATCH 1639/2654] reduce temporary memory use for potentially large data --- include/openmc/distribution.h | 2 +- src/distribution.cpp | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 86aa4a381..34744b3e3 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -61,7 +61,7 @@ private: void normalize(); //! Initialize alias tables for distribution - void init_alias(vector& x, vector& p); + void init_alias(); }; //============================================================================== diff --git a/src/distribution.cpp b/src/distribution.cpp index ce2a85705..e2e113826 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -26,38 +26,38 @@ Discrete::Discrete(pugi::xml_node node) { auto params = get_node_array(node, "parameters"); - std::size_t n = params.size(); - std::vector x_vec(params.begin(), params.begin() + n / 2); - std::vector p_vec(params.begin() + n / 2, params.end()); + std::size_t n = params.size()/2; - this->init_alias(x_vec, p_vec); + x_.assign(params.begin(), params.begin() + n); + prob_.assign(params.begin() + n, params.end()); + + this->init_alias(); } Discrete::Discrete(const double* x, const double* p, int n) { - std::vector x_vec(x, x + n); - std::vector p_vec(p, p + n); + + x_.assign(x, x + n); + prob_.assign(p, p + n); - this->init_alias(x_vec, p_vec); + this->init_alias(); } Discrete::Discrete(const double* p, int n) { - std::vector p_vec(p, p + n); - std::vector x_vec(n); + prob_.assign(p, p + n); + x_.resize(n); for (int i=0; iinit_alias(x_vec, p_vec); + this->init_alias(); } -void Discrete::init_alias(vector& x, vector& p) +void Discrete::init_alias() { - x_ = x; - prob_ = p; normalize(); // The initialization and sampling method is based on Vose From b20dda710b36798d078559fac4eee16c9cdfe6cd Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Fri, 17 Mar 2023 12:58:53 -0500 Subject: [PATCH 1640/2654] change initialization of strengths --- src/distribution_spatial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 7c5b2ed64..8060527a8 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -210,7 +210,7 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) } int32_t n_bins = this->n_sources(); - std::vector strengths(n_bins, 0.0); + std::vector strengths(n_bins, 1.0); // Create cdfs for sampling for an element over a mesh // Volume scheme is weighted by the volume of each tet From 487f02dd1dddfa09e51a3a2b78b70947aafec1be Mon Sep 17 00:00:00 2001 From: guyshtot Date: Tue, 21 Mar 2023 13:18:24 +0200 Subject: [PATCH 1641/2654] Add option to specify nuclides in the Library class --- openmc/mgxs/library.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index efe8dbe84..063134f7a 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -72,6 +72,11 @@ class Library: Number of equi-width polar angle bins for angle discretization num_azimuthal : Integral Number of equi-width azimuthal angle bins for angle discretization + nuclides : Iterable of str or 'sum' + The optional user-specified nuclides for which to compute cross + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides + are not specified by the user, all nuclides in the domain + are included. estimator : str or None The tally estimator used to compute multi-group cross sections. If None, the default for each MGXS type is used. @@ -107,6 +112,7 @@ class Library: self._energy_groups = None self._num_polar = 1 self._num_azimuthal = 1 + self._nuclides = None self._num_delayed_groups = 0 self._correction = 'P0' self._scatter_format = 'legendre' @@ -145,6 +151,7 @@ class Library: clone._energy_groups = copy.deepcopy(self.energy_groups, memo) clone._num_polar = self.num_polar clone._num_azimuthal = self.num_azimuthal + clone._nuclides = self._nuclides clone._num_delayed_groups = self.num_delayed_groups clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo) clone._all_mgxs = copy.deepcopy(self.all_mgxs) @@ -206,6 +213,14 @@ class Library: return self._domains @property + def nuclides(self): + if self.by_nuclide and self._nuclides: + return self._nuclides + elif self.by_nuclide: + raise ValueError("Nuclides weren't defined") + else: + return 'sum' + @property def energy_groups(self): return self._energy_groups @@ -275,6 +290,11 @@ class Library: cv.check_type('name', name, str) self._name = name + @nuclides.setter + def nuclides(self, nuclides): + cv.check_type('nuclides', nuclides, str) + self._nuclides = nuclides + @mgxs_types.setter def mgxs_types(self, mgxs_types): all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES + \ @@ -524,6 +544,18 @@ class Library: mgxs.legendre_order = self.legendre_order mgxs.histogram_bins = self.histogram_bins + if self.by_nuclide: + try: + domain_nuclides = domain.get_nuclides() + except AttributeError: + domain_nuclides = None + if self._nuclides: + if domain_nuclides: + mgxs.nuclides = [nuclide for nuclide in self.nuclides if nuclide in domain_nuclides] + [ + "total"] + else: + mgxs.nuclides = self._nuclides + self.all_mgxs[domain.id][mgxs_type] = mgxs def add_to_tallies_file(self, tallies_file, merge=True): From b3c7472c77b0f496a0a63e2a95af147e3f221030 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 21 Mar 2023 07:14:07 -0500 Subject: [PATCH 1642/2654] Add Python 3.11 to CI matrix --- .github/workflows/ci.yml | 17 ++++++++++------- setup.py | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 999dea312..4ec3e7d8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - python-version: ["3.10"] + python-version: ["3.11"] mpi: [n, y] omp: [n, y] dagmc: [n] @@ -44,28 +44,31 @@ jobs: - python-version: 3.9 omp: n mpi: n + - python-version: 3.10 + omp: n + mpi: n - dagmc: y - python-version: "3.10" + python-version: "3.11" mpi: y omp: y - ncrystal: y - python-version: "3.10" + python-version: "3.11" mpi: n omp: n - libmesh: y - python-version: "3.10" + python-version: "3.11" mpi: y omp: y - libmesh: y - python-version: "3.10" + python-version: "3.11" mpi: n omp: y - event: y - python-version: "3.10" + python-version: "3.11" omp: y mpi: n - vectfit: y - python-version: "3.10" + python-version: "3.11" omp: n mpi: y name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }}, diff --git a/setup.py b/setup.py index a9e863da2..29c129d7b 100755 --- a/setup.py +++ b/setup.py @@ -58,6 +58,7 @@ kwargs = { 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', ], # Dependencies From 354fd34c2c5dd1fa6d47dcff623089d87128e5ca Mon Sep 17 00:00:00 2001 From: guyshtot Date: Tue, 21 Mar 2023 14:59:01 +0200 Subject: [PATCH 1643/2654] Renamed previous use of _nuclides to _atomic_weight_ratios in the library class --- openmc/mgxs/library.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 063134f7a..0eb00c8f1 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -214,12 +214,8 @@ class Library: @property def nuclides(self): - if self.by_nuclide and self._nuclides: - return self._nuclides - elif self.by_nuclide: - raise ValueError("Nuclides weren't defined") - else: - return 'sum' + return self._nuclides + @property def energy_groups(self): return self._energy_groups @@ -292,7 +288,7 @@ class Library: @nuclides.setter def nuclides(self, nuclides): - cv.check_type('nuclides', nuclides, str) + cv.check_iterable_type('nuclides', nuclides, str) self._nuclides = nuclides @mgxs_types.setter @@ -549,12 +545,12 @@ class Library: domain_nuclides = domain.get_nuclides() except AttributeError: domain_nuclides = None - if self._nuclides: + if self.nuclides: if domain_nuclides: mgxs.nuclides = [nuclide for nuclide in self.nuclides if nuclide in domain_nuclides] + [ "total"] else: - mgxs.nuclides = self._nuclides + mgxs.nuclides = self.nuclides self.all_mgxs[domain.id][mgxs_type] = mgxs @@ -622,7 +618,7 @@ class Library: self._sp_filename = statepoint._f.filename self._geometry = statepoint.summary.geometry - self._nuclides = statepoint.summary.nuclides + self._atomic_weight_ratios = statepoint.summary.nuclides if statepoint.run_mode == 'eigenvalue': self._keff = statepoint.keff.n @@ -1037,7 +1033,7 @@ class Library: xsdata.num_azimuthal = self.num_azimuthal if nuclide != 'total': - xsdata.atomic_weight_ratio = self._nuclides[nuclide] + xsdata.atomic_weight_ratio = self._atomic_weight_ratios[nuclide] if subdomain is None: subdomain = 'all' From 3032ad7f3705468a40a0a4b2b7ef0ba3995dd2bb Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 21 Mar 2023 09:37:39 -0500 Subject: [PATCH 1644/2654] Stick with 3.10 as default, add single 3.11 job --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ec3e7d8b..82bd70a62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - python-version: ["3.11"] + python-version: ["3.10"] mpi: [n, y] omp: [n, y] dagmc: [n] @@ -44,31 +44,31 @@ jobs: - python-version: 3.9 omp: n mpi: n - - python-version: 3.10 + - python-version: "3.11" omp: n mpi: n - dagmc: y - python-version: "3.11" + python-version: "3.10" mpi: y omp: y - ncrystal: y - python-version: "3.11" + python-version: "3.10" mpi: n omp: n - libmesh: y - python-version: "3.11" + python-version: "3.10" mpi: y omp: y - libmesh: y - python-version: "3.11" + python-version: "3.10" mpi: n omp: y - event: y - python-version: "3.11" + python-version: "3.10" omp: y mpi: n - vectfit: y - python-version: "3.11" + python-version: "3.10" omp: n mpi: y name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }}, From cf8d9ef313d2a58fd52705d4c48e203143c98a20 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 21 Mar 2023 13:15:28 -0500 Subject: [PATCH 1645/2654] Handle zero photon cross sections in IncidentPhoton.from_ace properly --- openmc/data/photon.py | 9 ++++++--- src/photon.cpp | 10 +++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/openmc/data/photon.py b/openmc/data/photon.py index fc5da19eb..e83ff844d 100644 --- a/openmc/data/photon.py +++ b/openmc/data/photon.py @@ -514,13 +514,13 @@ class IncidentPhoton(EqualityMixin): # Read each reaction data = cls(Z) - for mt in (502, 504, 515, 522, 525): + for mt in (502, 504, 517, 522, 525): data.reactions[mt] = PhotonReaction.from_ace(ace, mt) # Get heating cross sections [eV-barn] from factors [eV per collision] # by multiplying with total xs data.reactions[525].xs.y *= sum([data.reactions[mt].xs.y for mt in - (502, 504, 515, 522)]) + (502, 504, 517, 522)]) # Compton profiles n_shell = ace.nxs[5] @@ -1000,7 +1000,7 @@ class PhotonReaction(EqualityMixin): elif mt == 504: # Incoherent scattering idx = ace.jxs[1] + n - elif mt == 515: + elif mt == 517: # Pair production idx = ace.jxs[1] + 4*n elif mt == 522: @@ -1021,6 +1021,9 @@ class PhotonReaction(EqualityMixin): else: nonzero = (xs != 0.0) xs[nonzero] = np.exp(xs[nonzero]) + + # Replace zero elements to small non-zero to enable log-log + xs[~nonzero] = np.exp(-500.0) rx.xs = Tabulated1D(energy, xs, [n], [5]) # Get form factors for incoherent/coherent scattering diff --git a/src/photon.cpp b/src/photon.cpp index c4beff019..08062a2e9 100644 --- a/src/photon.cpp +++ b/src/photon.cpp @@ -91,9 +91,13 @@ PhotonInteraction::PhotonInteraction(hid_t group) close_group(rgroup); // Read pair production - rgroup = open_group(group, "pair_production_electron"); - read_dataset(rgroup, "xs", pair_production_electron_); - close_group(rgroup); + if (object_exists(group, "pair_production_electron")) { + rgroup = open_group(group, "pair_production_electron"); + read_dataset(rgroup, "xs", pair_production_electron_); + close_group(rgroup); + } else { + pair_production_electron_ = xt::zeros_like(energy_); + } // Read pair production if (object_exists(group, "pair_production_nuclear")) { From bb5f727f85325cc2d4e94d00b1940c9d744dd568 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 21 Mar 2023 13:48:22 -0500 Subject: [PATCH 1646/2654] Update IO format docs for meshes --- docs/source/io_formats/statepoint.rst | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index c0db5ea92..09b1b1144 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -72,12 +72,17 @@ The current version of the statepoint file format is 17.0. :Datasets: - **type** (*char[]*) -- Type of mesh. - **dimension** (*int*) -- Number of mesh cells in each dimension. - - **lower_left** (*double[]*) -- Coordinates of lower-left corner of - mesh. - - **upper_right** (*double[]*) -- Coordinates of upper-right corner - of mesh. - - **width** (*double[]*) -- Width of each mesh cell in each - dimension. + - **Regular Mesh Only:** + - **lower_left** (*double[]*) -- Coordinates of lower-left corner of + mesh. + - **upper_right** (*double[]*) -- Coordinates of upper-right corner + of mesh. + - **width** (*double[]*) -- Width of each mesh cell in each + dimension. + - **Rectilinear Mesh Only:** + - **x_grid** (*double[]*) -- Mesh divisions along the x-axis. + - **y_grid** (*double[]*) -- Mesh divisions along the y-axis. + - **z_grid** (*double[]*) -- Mesh divisions along the z-axis. - **Cylindrical & Spherical Mesh Only:** - **r_grid** (*double[]*) -- The mesh divisions along the r-axis. - **phi_grid** (*double[]*) -- The mesh divisions along the phi-axis. From 38ca9b2f7cfdc71091d02b6bfe47ca19db33964d Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Tue, 21 Mar 2023 15:43:43 -0400 Subject: [PATCH 1647/2654] clang format fixes --- src/distribution.cpp | 7 +++---- src/distribution_spatial.cpp | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index e2e113826..0dac7af36 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -26,7 +26,7 @@ Discrete::Discrete(pugi::xml_node node) { auto params = get_node_array(node, "parameters"); - std::size_t n = params.size()/2; + std::size_t n = params.size() / 2; x_.assign(params.begin(), params.begin() + n); prob_.assign(params.begin() + n, params.end()); @@ -36,7 +36,7 @@ Discrete::Discrete(pugi::xml_node node) Discrete::Discrete(const double* x, const double* p, int n) { - + x_.assign(x, x + n); prob_.assign(p, p + n); @@ -48,8 +48,7 @@ Discrete::Discrete(const double* p, int n) prob_.assign(p, p + n); x_.resize(n); - for (int i=0; ivolume(i); } } elem_idx_dist_ = UPtrDist {new Discrete {strengths.data(), n_bins}}; - } Position MeshSpatial::sample(uint64_t* seed) const From 9b708e7ad47292a73455e26dda134ea0c6086625 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 21 Mar 2023 14:55:42 -0500 Subject: [PATCH 1648/2654] Apply suggestions from @paulromano Co-authored-by: Paul Romano --- tests/unit_tests/test_mesh_to_vtk.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/unit_tests/test_mesh_to_vtk.py b/tests/unit_tests/test_mesh_to_vtk.py index 80da85d97..4c0a43877 100644 --- a/tests/unit_tests/test_mesh_to_vtk.py +++ b/tests/unit_tests/test_mesh_to_vtk.py @@ -59,7 +59,7 @@ spherical_mesh.r_grid = np.linspace(1, 10, 30) spherical_mesh.phi_grid = np.linspace(0, 0.8*np.pi, 25) spherical_mesh.theta_grid = np.linspace(0, np.pi / 2, 15) -MESHES = [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh] +MESHES = [cylinder_mesh, regular_mesh, rectilinear_mesh, spherical_mesh] x_plane = openmc.XPlane(x0=-0.001, boundary_type='vacuum') y_plane = openmc.YPlane(y0=-0.001, boundary_type='vacuum') @@ -201,11 +201,9 @@ def test_write_data_to_vtk_round_trip(run_in_tmpdir): assert np.array_equal(vtk_values, data) def mesh_surf_id(param): - if isinstance(param, openmc.MeshBase): return ids(param) - - if isinstance(param, openmc.XPlane): + elif isinstance(param, openmc.XPlane): return 'XPlane' elif isinstance(param, openmc.YPlane): return 'YPlane' From 1d9446a065f6cc5be06c614624c6c157fba44a9e Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Tue, 21 Mar 2023 16:14:38 -0400 Subject: [PATCH 1649/2654] introduce method to sample discrete index and use in various places --- include/openmc/distribution.h | 34 ++++++++++--- include/openmc/distribution_spatial.h | 3 +- src/distribution.cpp | 72 +++++++++++++++------------ src/distribution_spatial.cpp | 2 +- 4 files changed, 71 insertions(+), 40 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 34744b3e3..2e210b7ab 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -32,27 +32,24 @@ using UPtrDist = unique_ptr; UPtrDist distribution_from_xml(pugi::xml_node node); //============================================================================== -//! A discrete distribution (probability mass function) +//! A discrete distribution index (probability mass function) //============================================================================== -class Discrete : public Distribution { +class DiscreteIndex { public: explicit Discrete(pugi::xml_node node); - Discrete(const double* x, const double* p, int n); Discrete(const double* p, int n); //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - double sample(uint64_t* seed) const override; + size_t sample(uint64_t* seed) const override; // Properties - const vector& x() const { return x_; } const vector& prob() const { return prob_; } const vector& alias() const { return alias_; } private: - vector x_; //!< Possible outcomes vector prob_; //!< Probability of accepting the uniformly sampled bin, //!< mapped to alias method table vector alias_; //!< Alias table @@ -64,6 +61,31 @@ private: void init_alias(); }; +//============================================================================== +//! A discrete distribution (probability mass function) +//============================================================================== + +class Discrete : public Distribution { +public: + explicit Discrete(pugi::xml_node node); + Discrete(const double* x, const double* p, int n); + + //! Sample a value from the distribution + //! \param seed Pseudorandom number seed pointer + //! \return Sampled value + double sample(uint64_t* seed) const override; + + // Properties + const vector& x() const { return x_; } + const vector& prob() const { return di_->prob(); } + const vector& alias() const { return di_->alias(); } + +private: + vector x_; //!< Possible outcomes + unique_ptr di_; //!< discrete probability distribution of + //!< outcome indices +}; + //============================================================================== //! Uniform distribution over the interval [a,b] //============================================================================== diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index dc1d898fe..9ca9c0684 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -114,7 +114,8 @@ public: private: int32_t mesh_idx_ {C_NONE}; - UPtrDist elem_idx_dist_; //!< Distribution of mesh element indices + unique_ptr elem_idx_dist_; //!< Distribution of + //!< mesh element indices }; //============================================================================== diff --git a/src/distribution.cpp b/src/distribution.cpp index 0dac7af36..2378cf117 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -19,43 +19,26 @@ namespace openmc { //============================================================================== -// Discrete implementation +// DiscreteIndex implementation //============================================================================== -Discrete::Discrete(pugi::xml_node node) +DiscreteIndex::DiscreteIndex(pugi::xml_node node) { auto params = get_node_array(node, "parameters"); - std::size_t n = params.size() / 2; - - x_.assign(params.begin(), params.begin() + n); - prob_.assign(params.begin() + n, params.end()); + prob_.assign(params.begin(), params.end()); this->init_alias(); } -Discrete::Discrete(const double* x, const double* p, int n) -{ - - x_.assign(x, x + n); - prob_.assign(p, p + n); - - this->init_alias(); -} - -Discrete::Discrete(const double* p, int n) +DiscreteIndex::DiscreteIndex(const double* p, int n) { prob_.assign(p, p + n); - x_.resize(n); - - for (int i = 0; i < n; i++) { - x_[i] = i; - } this->init_alias(); } -void Discrete::init_alias() +void DiscreteIndex::init_alias() { normalize(); @@ -66,12 +49,11 @@ void Discrete::init_alias() vector small; // Set and allocate memory - vector alias(x_.size(), 0); - alias_ = alias; + alias_.assign(prob_.size(), 0); // Fill large and small vectors based on 1/n - for (size_t i = 0; i < x_.size(); i++) { - prob_[i] *= x_.size(); + for (size_t i = 0; i < prob_.size(); i++) { + prob_[i] *= prob_.size(); if (prob_[i] > 1.0) { large.push_back(i); } else { @@ -98,23 +80,23 @@ void Discrete::init_alias() } } -double Discrete::sample(uint64_t* seed) const +size_t DiscreteIndex::sample(uint64_t* seed) const { // Alias sampling of discrete distribution - int n = x_.size(); + int n = prob_.size(); if (n > 1) { int u = prn(seed) * n; if (prn(seed) < prob_[u]) { - return x_[u]; + return u; } else { - return x_[alias_[u]]; + return alias_[u]; } } else { - return x_[0]; + return 0; } } -void Discrete::normalize() +void DiscreteIndex::normalize() { // Renormalize density function so that it sums to unity double norm = std::accumulate(prob_.begin(), prob_.end(), 0.0); @@ -123,6 +105,32 @@ void Discrete::normalize() } } +//============================================================================== +// Discrete implementation +//============================================================================== + +Discrete::Discrete(pugi::xml_node node) +{ + auto params = get_node_array(node, "parameters"); + + std::size_t n = params.size() / 2; + + x_.assign(params.begin(), params.begin() + n); + di_ = new DiscreteIndex(params.begin() + n, n) +} + +Discrete::Discrete(const double* x, const double* p, int n) +{ + + x_.assign(x, x + n); + di_ = new DiscreteIndex(params.begin() + n, n) +} + +double Discrete::sample(uint64_t* seed) const +{ + return x_[di_->sample(seed)]; +} + //============================================================================== // Uniform implementation //============================================================================== diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 272f9d941..c2d370b17 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -231,7 +231,7 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) } } - elem_idx_dist_ = UPtrDist {new Discrete {strengths.data(), n_bins}}; + elem_idx_dist_ = make_unique(strengths.data(), n_bins); } Position MeshSpatial::sample(uint64_t* seed) const From 60c3f2a9d56137ad1348768ad81126346b3555e9 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Tue, 21 Mar 2023 16:36:33 -0400 Subject: [PATCH 1650/2654] type consistency and storing size as local --- src/distribution.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index 2378cf117..2066e5a8c 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -48,12 +48,14 @@ void DiscreteIndex::init_alias() vector large; vector small; + size_t n = prob_.size(); + // Set and allocate memory - alias_.assign(prob_.size(), 0); + alias_.assign(n, 0); // Fill large and small vectors based on 1/n - for (size_t i = 0; i < prob_.size(); i++) { - prob_[i] *= prob_.size(); + for (size_t i = 0; i < n; i++) { + prob_[i] *= n; if (prob_[i] > 1.0) { large.push_back(i); } else { @@ -83,9 +85,9 @@ void DiscreteIndex::init_alias() size_t DiscreteIndex::sample(uint64_t* seed) const { // Alias sampling of discrete distribution - int n = prob_.size(); + size_t n = prob_.size(); if (n > 1) { - int u = prn(seed) * n; + size_t u = prn(seed) * n; if (prn(seed) < prob_[u]) { return u; } else { From 17e9918f5d33188f5882559b073fee72dce3e195 Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 21 Mar 2023 21:51:40 +0000 Subject: [PATCH 1651/2654] removed most deprecated types --- openmc/plotter.py | 127 +++++++++++++------------------ tests/unit_tests/test_plotter.py | 4 +- 2 files changed, 55 insertions(+), 76 deletions(-) diff --git a/openmc/plotter.py b/openmc/plotter.py index 541b05f0b..2bdcfe351 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -53,6 +53,9 @@ _MIN_E = 1.e-5 _MAX_E = 20.e6 +ELEMENT_NAMES = list(openmc.data.ELEMENT_SYMBOL.values())[1:] + + def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, sab_name=None, ce_cross_sections=None, mg_cross_sections=None, enrichment=None, plot_CE=True, orders=None, divisor_orders=None): @@ -60,7 +63,7 @@ def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, Parameters ---------- - this : {str, openmc.Nuclide, openmc.Element, openmc.Macroscopic, openmc.Material} + this : {str, openmc.Material} Object to source data from. Nuclides and Elements can be input as a str types : Iterable of values of PLOT_TYPES The type of cross sections to include in the plot. @@ -77,16 +80,14 @@ def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, A previously generated axis to use for plotting. If not specified, a new axis and figure will be generated. sab_name : str, optional - Name of S(a,b) library to apply to MT=2 data when applicable; only used - for items which are instances of openmc.Element or openmc.Nuclide + Name of S(a,b) library to apply to MT=2 data when applicable. ce_cross_sections : str, optional Location of cross_sections.xml file. Default is None. mg_cross_sections : str, optional Location of MGXS HDF5 Library file. Default is None. enrichment : float, optional Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None. This is only used for - items which are instances of openmc.Element + 4.95 weight percent enriched U. Default is None. plot_CE : bool, optional Denotes whether or not continuous-energy will be plotted. Defaults to plotting the continuous-energy data. @@ -110,7 +111,7 @@ def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, import matplotlib.pyplot as plt cv.check_type("plot_CE", plot_CE, bool) - cv.check_type("this", this, (str, openmc.Nuclide, openmc.Element, openmc.Material)) + cv.check_type("this", this, (str, openmc.Material)) if plot_CE: # Calculate for the CE cross sections @@ -179,28 +180,23 @@ def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, else: ax.set_xlim(E[-1], E[0]) - if isinstance(this, str): - # first entry in ELEMENT_SYMBOL is a neutron, the 1 removes this entry - if this in list(openmc.data.ELEMENT_SYMBOL.values())[1:]: - this = openmc.Element(this) - else: - this = openmc.Nuclide(this) - if divisor_types: - if isinstance(this, openmc.Nuclide): - ylabel = 'Nuclidic Microscopic Data' - elif isinstance(this, openmc.Element): - ylabel = 'Elemental Microscopic Data' - elif isinstance(this, openmc.Material) or isinstance(this, openmc.Macroscopic): + if isinstance(this, str): + if this in ELEMENT_NAMES: + ylabel = 'Elemental Microscopic Data' + else: + ylabel = 'Nuclide Microscopic Data' + elif isinstance(this, openmc.Material): ylabel = 'Macroscopic Data' else: raise TypeError("Invalid type for plotting") else: - if isinstance(this, openmc.Nuclide): - ylabel = 'Microscopic Cross Section [b]' - elif isinstance(this, openmc.Element): - ylabel = 'Elemental Cross Section [b]' - elif isinstance(this, openmc.Material) or isinstance(this, openmc.Macroscopic): + if isinstance(this, str): + if this in ELEMENT_NAMES: + ylabel = 'Elemental Cross Section [b]' + else: + ylabel = 'Microscopic Cross Section [b]' + elif isinstance(this, openmc.Material): ylabel = 'Macroscopic Cross Section [1/cm]' else: raise TypeError("Invalid type for plotting") @@ -221,8 +217,9 @@ def calculate_cexs(this, types, temperature=294., sab_name=None, Parameters ---------- - this : {str, openmc.Nuclide, openmc.Element, openmc.Material} - Object to source data from. Nuclides and Elements can be input as a str + this : {str, openmc.Material} + Object to source data from. Nuclides and Elements should be input as a + str types : Iterable of values of PLOT_TYPES The type of cross sections to calculate temperature : float, optional @@ -249,44 +246,37 @@ def calculate_cexs(this, types, temperature=294., sab_name=None, """ # Check types - cv.check_type('this', this, (str, openmc.Nuclide, openmc.Element, openmc.Material)) + cv.check_type('this', this, (str, openmc.Material)) cv.check_type('temperature', temperature, Real) if sab_name: cv.check_type('sab_name', sab_name, str) if enrichment: cv.check_type('enrichment', enrichment, Real) - # this is a nuclide or element if it is a string if isinstance(this, str): - # first entry in ELEMENT_SYMBOL is a neutron, the 1 removes this entry - if this in list(openmc.data.ELEMENT_SYMBOL.values())[1:]: - this = openmc.Element(this) + if this in ELEMENT_NAMES: + energy_grid, data = _calculate_cexs_elem_mat( + this, types, temperature, cross_sections, sab_name, enrichment + ) + else: - this = openmc.Nuclide(this) + energy_grid, xs = _calculate_cexs_nuclide( + this, types, temperature, sab_name, cross_sections + ) - if isinstance(this, openmc.Nuclide): - energy_grid, xs = _calculate_cexs_nuclide(this, types, temperature, - sab_name, cross_sections) - - # Convert xs (Iterable of Callable) to a grid of cross section values - # calculated on the points in energy_grid for consistency with the - # element and material functions. - data = np.zeros((len(types), len(energy_grid))) - for line in range(len(types)): - data[line, :] = xs[line](energy_grid) - - elif isinstance(this, openmc.Element): - energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, - cross_sections, sab_name, - enrichment) + # Convert xs (Iterable of Callable) to a grid of cross section values + # calculated on the points in energy_grid for consistency with the + # element and material functions. + data = np.zeros((len(types), len(energy_grid))) + for line in range(len(types)): + data[line, :] = xs[line](energy_grid) elif isinstance(this, openmc.Material): energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, cross_sections) else: msg = ( - f"{this} is an invalid type, acceptable types are str, " - "openmc.Nuclide, openmc.Element, openmc.Material." + f"{this} is an invalid type, acceptable types are str, openmc.Material." ) raise TypeError(msg) @@ -299,7 +289,7 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, Parameters ---------- - this : openmc.Nuclide + this : str Nuclide object to source data from types : Iterable of str or Integral The type of cross sections to calculate; values can either be those @@ -496,8 +486,8 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., Parameters ---------- - this : openmc.Material or openmc.Element - Object to source data from + this : openmc.Material or str + Object to source data from. Element can be input as str types : Iterable of values of PLOT_TYPES The type of cross sections to calculate temperature : float, optional @@ -538,18 +528,16 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., # Expand elements in to nuclides with atomic densities nuc_fractions = this.get_nuclide_atom_densities() # Create a dict of [nuclide name] = nuclide object to carry forward - # with a common nuclides format between openmc.Material and - # openmc.Element objects + # with a common nuclides format between openmc.Material and Elements nuclides = {nuclide: nuclide for nuclide in nuc_fractions} else: # Expand elements in to nuclides with atomic densities - nuclides = this.expand(1., 'ao', enrichment=enrichment, + nuclides = openmc.Element(this).expand(1., 'ao', enrichment=enrichment, cross_sections=cross_sections) # For ease of processing split out the nuclide and its fraction nuc_fractions = {nuclide[0]: nuclide[1] for nuclide in nuclides} # Create a dict of [nuclide name] = nuclide object to carry forward - # with a common nuclides format between openmc.Material and - # openmc.Element objects + # with a common nuclides format between openmc.Material and Elements nuclides = {nuclide[0]: nuclide[0] for nuclide in nuclides} # Identify the nuclides which have S(a,b) data @@ -615,7 +603,7 @@ def calculate_mgxs(this, types, orders=None, temperature=294., Parameters ---------- - this : {str, openmc.Nuclide, openmc.Element, openmc.Macroscopic, openmc.Material} + this : {str, openmc.Material} Object to source data from. Nuclides and Elements can be input as a str types : Iterable of values of PLOT_TYPES_MGXS The type of cross sections to calculate @@ -632,7 +620,6 @@ def calculate_mgxs(this, types, orders=None, temperature=294., Location of MGXS HDF5 Library file. Default is None. ce_cross_sections : str, optional Location of continuous-energy cross_sections.xml file. Default is None. - This is used only for expanding an openmc.Element object passed as this enrichment : float, optional Enrichment for U235 in weight percent. For example, input 4.95 for 4.95 weight percent enriched U. Default is None @@ -656,21 +643,13 @@ def calculate_mgxs(this, types, orders=None, temperature=294., cv.check_type("cross_sections", cross_sections, str) library = openmc.MGXSLibrary.from_hdf5(cross_sections) - # this is a nuclide or element if it is a string - if isinstance(this, str): - # first entry in ELEMENT_SYMBOL is a neutron, the 1 removes this entry - if this in list(openmc.data.ELEMENT_SYMBOL.values())[1:]: - this = openmc.Element(this) - else: - this = openmc.Nuclide(this) - - if isinstance(this, openmc.Nuclide) or isinstance(this, openmc.Macroscopic): - mgxs = _calculate_mgxs_nuc_macro(this, types, library, orders, - temperature) - elif isinstance(this, openmc.Element) or isinstance(this, openmc.Material): + if this in ELEMENT_NAMES or isinstance(this, openmc.Material): mgxs = _calculate_mgxs_elem_mat(this, types, library, orders, temperature, ce_cross_sections, enrichment) + elif isinstance(this, str): + mgxs = _calculate_mgxs_nuc_macro(this, types, library, orders, + temperature) else: raise TypeError("Invalid type") @@ -702,7 +681,7 @@ def _calculate_mgxs_nuc_macro(this, types, library, orders=None, Parameters ---------- - this : openmc.Nuclide or openmc.Macroscopic + this : str Object to source data from types : Iterable of str The type of cross sections to calculate; values can either be those @@ -840,8 +819,8 @@ def _calculate_mgxs_elem_mat(this, types, library, orders=None, Parameters ---------- - this : openmc.Element or openmc.Material - Object to source data from + this : str or openmc.Material + Object to source data from. Elements can be input as a str types : Iterable of str The type of cross sections to calculate; values can either be those in openmc.PLOT_TYPES_MGXS @@ -890,7 +869,7 @@ def _calculate_mgxs_elem_mat(this, types, library, orders=None, else: T = temperature # Expand elements in to nuclides with atomic densities - nuclides = this.expand(100., 'ao', enrichment=enrichment, + nuclides = openmc.Element(this).expand(100., 'ao', enrichment=enrichment, cross_sections=ce_cross_sections) # For ease of processing split out nuc and nuc_fractions diff --git a/tests/unit_tests/test_plotter.py b/tests/unit_tests/test_plotter.py index f7c731f1d..cabf9af6d 100644 --- a/tests/unit_tests/test_plotter.py +++ b/tests/unit_tests/test_plotter.py @@ -32,7 +32,7 @@ def test_calculate_cexs_elem_mat_sab(test_mat): assert len(data[0]) == len(energy_grid) -@pytest.mark.parametrize("this", ["Li", "Li6", openmc.Nuclide('Li6'), openmc.Element('Li')]) +@pytest.mark.parametrize("this", ["Li", "Li6"]) def test_calculate_cexs_with_nuclide_and_element(this): # single type (reaction) energy_grid, data = openmc.plotter.calculate_cexs( @@ -72,7 +72,7 @@ def test_calculate_cexs_with_materials(test_mat): assert len(data[0]) == len(energy_grid) -@pytest.mark.parametrize("this", ["Be", "Be9", openmc.Nuclide('Be9'), openmc.Element('Be')]) +@pytest.mark.parametrize("this", ["Be", "Be9"]) def test_plot_xs(this): assert isinstance(openmc.plotter.plot_xs(this, types=['total']), Figure) From 035e6dc45aee946976f30216be69371fd02aee21 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Wed, 22 Mar 2023 00:25:04 -0400 Subject: [PATCH 1652/2654] change to instance from pointer and cleanup lazy mistakes --- include/openmc/distribution.h | 14 ++++++++------ include/openmc/distribution_spatial.h | 4 ++-- src/distribution.cpp | 16 +++++++++++----- src/distribution_spatial.cpp | 2 +- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 2e210b7ab..b7d0e4721 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -37,13 +37,15 @@ UPtrDist distribution_from_xml(pugi::xml_node node); class DiscreteIndex { public: - explicit Discrete(pugi::xml_node node); - Discrete(const double* p, int n); + explicit DiscreteIndex(pugi::xml_node node); + DiscreteIndex(const double* p, int n); + + void assign(const double* p, int n); //! Sample a value from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled value - size_t sample(uint64_t* seed) const override; + size_t sample(uint64_t* seed) const; // Properties const vector& prob() const { return prob_; } @@ -81,9 +83,9 @@ public: const vector& alias() const { return di_->alias(); } private: - vector x_; //!< Possible outcomes - unique_ptr di_; //!< discrete probability distribution of - //!< outcome indices + vector x_; //!< Possible outcomes + DiscreteIndex di_; //!< discrete probability distribution of + //!< outcome indices }; //============================================================================== diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h index 9ca9c0684..9fba95060 100644 --- a/include/openmc/distribution_spatial.h +++ b/include/openmc/distribution_spatial.h @@ -114,8 +114,8 @@ public: private: int32_t mesh_idx_ {C_NONE}; - unique_ptr elem_idx_dist_; //!< Distribution of - //!< mesh element indices + DiscreteIndex elem_idx_dist_; //!< Distribution of + //!< mesh element indices }; //============================================================================== diff --git a/src/distribution.cpp b/src/distribution.cpp index 2066e5a8c..18fa41449 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -25,8 +25,9 @@ namespace openmc { DiscreteIndex::DiscreteIndex(pugi::xml_node node) { auto params = get_node_array(node, "parameters"); + std::size_t n = params.size() / 2; - prob_.assign(params.begin(), params.end()); + prob_.assign(params.begin() + n, params.end()); this->init_alias(); } @@ -38,6 +39,13 @@ DiscreteIndex::DiscreteIndex(const double* p, int n) this->init_alias(); } +void DiscreteIndex::assign(const double* p, int n) +{ + prob_.assign(p, p + n); + + this->init_alias(); +} + void DiscreteIndex::init_alias() { normalize(); @@ -111,21 +119,19 @@ void DiscreteIndex::normalize() // Discrete implementation //============================================================================== -Discrete::Discrete(pugi::xml_node node) +Discrete::Discrete(pugi::xml_node node) : di_(node) { auto params = get_node_array(node, "parameters"); std::size_t n = params.size() / 2; x_.assign(params.begin(), params.begin() + n); - di_ = new DiscreteIndex(params.begin() + n, n) } -Discrete::Discrete(const double* x, const double* p, int n) +Discrete::Discrete(const double* x, const double* p, int n) : di_(p, n) { x_.assign(x, x + n); - di_ = new DiscreteIndex(params.begin() + n, n) } double Discrete::sample(uint64_t* seed) const diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index c2d370b17..694617ac5 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -231,7 +231,7 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) } } - elem_idx_dist_ = make_unique(strengths.data(), n_bins); + elem_idx_dist_.assign(strengths.data(), n_bins); } Position MeshSpatial::sample(uint64_t* seed) const From df4cfad60c08e62463a748dac6413787692396c2 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Wed, 22 Mar 2023 00:29:28 -0400 Subject: [PATCH 1653/2654] more pointer to instance changes --- include/openmc/distribution.h | 4 ++-- src/distribution.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index b7d0e4721..12a6f6f5c 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -79,8 +79,8 @@ public: // Properties const vector& x() const { return x_; } - const vector& prob() const { return di_->prob(); } - const vector& alias() const { return di_->alias(); } + const vector& prob() const { return di_.prob(); } + const vector& alias() const { return di_.alias(); } private: vector x_; //!< Possible outcomes diff --git a/src/distribution.cpp b/src/distribution.cpp index 18fa41449..deea035de 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -136,7 +136,7 @@ Discrete::Discrete(const double* x, const double* p, int n) : di_(p, n) double Discrete::sample(uint64_t* seed) const { - return x_[di_->sample(seed)]; + return x_[di_.sample(seed)]; } //============================================================================== From c272ed4c4e11d8f3e35e877fb6246c65102c7ee8 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Wed, 22 Mar 2023 00:37:12 -0400 Subject: [PATCH 1654/2654] more pointer->instance repair --- src/distribution_spatial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp index 694617ac5..e1a4c20c2 100644 --- a/src/distribution_spatial.cpp +++ b/src/distribution_spatial.cpp @@ -237,7 +237,7 @@ MeshSpatial::MeshSpatial(pugi::xml_node node) Position MeshSpatial::sample(uint64_t* seed) const { // Sample over the CDF defined in initialization above - int32_t elem_idx = elem_idx_dist_->sample(seed); + int32_t elem_idx = elem_idx_dist_.sample(seed); return mesh()->sample(seed, elem_idx); } From fb4845494f19b6c0dfde82f1ecb90d5fa8a879a7 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Wed, 22 Mar 2023 00:37:21 -0400 Subject: [PATCH 1655/2654] add default empty consructor --- include/openmc/distribution.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h index 12a6f6f5c..03b046bbb 100644 --- a/include/openmc/distribution.h +++ b/include/openmc/distribution.h @@ -37,7 +37,8 @@ UPtrDist distribution_from_xml(pugi::xml_node node); class DiscreteIndex { public: - explicit DiscreteIndex(pugi::xml_node node); + DiscreteIndex() {}; + DiscreteIndex(pugi::xml_node node); DiscreteIndex(const double* p, int n); void assign(const double* p, int n); From 967cd43fa13f9360437e130a76086abb08abf106 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Wed, 22 Mar 2023 08:45:19 -0400 Subject: [PATCH 1656/2654] reuse assign --- src/distribution.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index deea035de..599f57ad4 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -27,16 +27,12 @@ DiscreteIndex::DiscreteIndex(pugi::xml_node node) auto params = get_node_array(node, "parameters"); std::size_t n = params.size() / 2; - prob_.assign(params.begin() + n, params.end()); - - this->init_alias(); + assign(params.begin(), n); } DiscreteIndex::DiscreteIndex(const double* p, int n) { - prob_.assign(p, p + n); - - this->init_alias(); + assign(p, n); } void DiscreteIndex::assign(const double* p, int n) From 83a124c49240725494a2f4795aa1e56954c46bf3 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Mar 2023 13:11:33 +0000 Subject: [PATCH 1657/2654] [skip ci] review improvments to docstring from @paulromano Co-authored-by: Paul Romano --- openmc/plotter.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/plotter.py b/openmc/plotter.py index 2bdcfe351..c66088cfd 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -63,8 +63,8 @@ def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, Parameters ---------- - this : {str, openmc.Material} - Object to source data from. Nuclides and Elements can be input as a str + this : str or openmc.Material + Object to source data from. Nuclides and elements can be input as a str types : Iterable of values of PLOT_TYPES The type of cross sections to include in the plot. divisor_types : Iterable of values of PLOT_TYPES, optional @@ -217,8 +217,8 @@ def calculate_cexs(this, types, temperature=294., sab_name=None, Parameters ---------- - this : {str, openmc.Material} - Object to source data from. Nuclides and Elements should be input as a + this : str or openmc.Material + Object to source data from. Nuclides and elements should be input as a str types : Iterable of values of PLOT_TYPES The type of cross sections to calculate @@ -603,8 +603,8 @@ def calculate_mgxs(this, types, orders=None, temperature=294., Parameters ---------- - this : {str, openmc.Material} - Object to source data from. Nuclides and Elements can be input as a str + this : str or openmc.Material + Object to source data from. Nuclides and elements can be input as a str types : Iterable of values of PLOT_TYPES_MGXS The type of cross sections to calculate orders : Iterable of Integral, optional From 6fc0c3e545627f67bece40950b3426b7001a0b56 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Wed, 22 Mar 2023 09:27:50 -0400 Subject: [PATCH 1658/2654] manually convert iterator to pointer --- src/distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index 599f57ad4..aa0e8e684 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -27,7 +27,7 @@ DiscreteIndex::DiscreteIndex(pugi::xml_node node) auto params = get_node_array(node, "parameters"); std::size_t n = params.size() / 2; - assign(params.begin(), n); + assign(&(*params.begin()), n); } DiscreteIndex::DiscreteIndex(const double* p, int n) From 993a8727980f52775025ab6f31144f1439013e10 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 22 Mar 2023 13:32:38 +0000 Subject: [PATCH 1659/2654] removed unused else and passing **kwargs --- openmc/plotter.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/openmc/plotter.py b/openmc/plotter.py index c66088cfd..a37b6f042 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -58,7 +58,8 @@ ELEMENT_NAMES = list(openmc.data.ELEMENT_SYMBOL.values())[1:] def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, sab_name=None, ce_cross_sections=None, mg_cross_sections=None, - enrichment=None, plot_CE=True, orders=None, divisor_orders=None): + enrichment=None, plot_CE=True, orders=None, divisor_orders=None, + **kwargs): """Creates a figure of continuous-energy cross sections for this item. Parameters @@ -98,6 +99,9 @@ def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, multi-group data. divisor_orders : Iterable of Integral, optional Same as orders, but for divisor_types + **kwargs : + All keyword arguments are passed to + :func:`matplotlib.pyplot.figure`. Returns ------- @@ -157,7 +161,7 @@ def plot_xs(this, types, divisor_types=None, temperature=294., axis=None, # Generate the plot if axis is None: - fig, ax = plt.subplots() + fig, ax = plt.subplots(**kwargs) else: fig = None ax = axis @@ -270,15 +274,9 @@ def calculate_cexs(this, types, temperature=294., sab_name=None, data = np.zeros((len(types), len(energy_grid))) for line in range(len(types)): data[line, :] = xs[line](energy_grid) - - elif isinstance(this, openmc.Material): + else: energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, cross_sections) - else: - msg = ( - f"{this} is an invalid type, acceptable types are str, openmc.Material." - ) - raise TypeError(msg) return energy_grid, data From 72a6f77b0c57cc1db62041409662a08f43112862 Mon Sep 17 00:00:00 2001 From: "Paul P.H. Wilson" Date: Wed, 22 Mar 2023 09:59:00 -0400 Subject: [PATCH 1660/2654] use correct part of parameters --- src/distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index aa0e8e684..32b47093c 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -27,7 +27,7 @@ DiscreteIndex::DiscreteIndex(pugi::xml_node node) auto params = get_node_array(node, "parameters"); std::size_t n = params.size() / 2; - assign(&(*params.begin()), n); + assign(&(*params.begin()) + n, n); } DiscreteIndex::DiscreteIndex(const double* p, int n) From 094eb958c1c110f77e7cc96c9d9136d88a5bdf7f Mon Sep 17 00:00:00 2001 From: zoeprieto <101403129+zoeprieto@users.noreply.github.com> Date: Wed, 22 Mar 2023 12:44:56 -0300 Subject: [PATCH 1661/2654] Add support for ncrystal materials --- openmc/plotter.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/openmc/plotter.py b/openmc/plotter.py index e2d18d085..9a939edc9 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -227,7 +227,7 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, - cross_sections=None, enrichment=None): + cross_sections=None, enrichment=None, ncrystal_cfg=None): """Calculates continuous-energy cross sections of a requested type. Parameters @@ -274,7 +274,8 @@ def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, else: nuc = this energy_grid, xs = _calculate_cexs_nuclide(nuc, types, temperature, - sab_name, cross_sections) + sab_name, cross_sections, + ncrystal_cfg) # Convert xs (Iterable of Callable) to a grid of cross section values # calculated on the points in energy_grid for consistency with the # element and material functions. @@ -300,7 +301,7 @@ def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, - cross_sections=None): + cross_sections=None, ncrystal_cfg=None): """Calculates continuous-energy cross sections of a requested type. Parameters @@ -438,6 +439,19 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, [sab_sum, nuc[mt].xs[nucT]], [sab_Emax]) funcs.append(pw_funcs) + elif ncrystal_cfg: + import NCrystal + nc_scatter = NCrystal.createScatter(ncrystal_cfg) + nc_func = nc_scatter.crossSectionNonOriented + nc_emax = 5 # eV # this should be obtained from NCRYSTAL_MAX_ENERGY + energy_grid = np.union1d(np.geomspace(min(energy_grid), + 1.1*nc_emax, + 1000),energy_grid) # NCrystal does not have + # an intrinsic energy grid + pw_funcs = openmc.data.Regions1D( + [nc_func, nuc[mt].xs[nucT]], + [nc_emax]) + funcs.append(pw_funcs) else: funcs.append(nuc[mt].xs[nucT]) elif mt in nuc: @@ -540,6 +554,7 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., # Load the library library = openmc.data.DataLibrary.from_xml(cross_sections) + ncrystal_cfg = None if isinstance(this, openmc.Material): # Expand elements in to nuclides with atomic densities nuc_fractions = this.get_nuclide_atom_densities() @@ -547,6 +562,8 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., # with a common nuclides format between openmc.Material and # openmc.Element objects nuclides = {nuclide: nuclide for nuclide in nuc_fractions} + # Add NCrystal cfg string if it exists + ncrystal_cfg = this.ncrystal_cfg else: # Expand elements in to nuclides with atomic densities nuclides = this.expand(1., 'ao', enrichment=enrichment, @@ -584,7 +601,7 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., nuc = nuclide[1] sab_tab = sabs[name] temp_E, temp_xs = calculate_cexs(nuc, 'nuclide', types, T, sab_tab, - cross_sections) + cross_sections, ncrystal_cfg=ncrystal_cfg) E.append(temp_E) # Since the energy grids are different, store the cross sections as # a tabulated function so they can be calculated on any grid needed. From 5160417e3e01097934eb0ef36610c35aa3fa6639 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 22 Mar 2023 12:45:33 -0500 Subject: [PATCH 1662/2654] load any nuclide requested that is not present in materials prior to constructing tally --- openmc/deplete/helpers.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index e51106544..90d1ddde4 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -15,7 +15,7 @@ from openmc.mpi import comm from openmc.checkvalue import check_type, check_greater_than from openmc.data import JOULE_PER_EV, REACTION_MT from openmc.lib import ( - Tally, MaterialFilter, EnergyFilter, EnergyFunctionFilter) + Tally, MaterialFilter, EnergyFilter, EnergyFunctionFilter, load_nuclide) import openmc.lib from .abc import ( ReactionRateHelper, NormalizationHelper, FissionYieldHelper) @@ -189,7 +189,7 @@ class DirectReactionRateHelper(ReactionRateHelper): def reset_tally_means(self): """Reset the cached mean rate tallies. .. note:: - + This step must be performed after each transport cycle """ self._rate_tally_means_cache = None @@ -306,6 +306,12 @@ class FluxCollapseHelper(ReactionRateHelper): self._rate_tally.filters = [MaterialFilter(materials)] self._rate_tally_means_cache = None if self._nuclides_direct is not None: + # check if any direct tally nuclides are requested that are not + # already loaded with the materials. Load separately if so. + mat_nuclides = [n for mat in materials for n in mat.nuclides] + extra_nuclides = set(self._nuclides_direct) - set(mat_nuclides) + for nuc in extra_nuclides: + load_nuclide(nuc) self._rate_tally.nuclides = self._nuclides_direct @property @@ -327,7 +333,7 @@ class FluxCollapseHelper(ReactionRateHelper): def reset_tally_means(self): """Reset the cached mean rate and flux tallies. .. note:: - + This step must be performed after each transport cycle """ self._flux_tally_means_cache = None From 9bb1ef4369871444f3342ee144a5854a34479a87 Mon Sep 17 00:00:00 2001 From: Paul Wilson Date: Wed, 22 Mar 2023 21:42:06 -0400 Subject: [PATCH 1663/2654] Update src/distribution.cpp Co-authored-by: Paul Romano --- src/distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distribution.cpp b/src/distribution.cpp index 32b47093c..10d404c10 100644 --- a/src/distribution.cpp +++ b/src/distribution.cpp @@ -27,7 +27,7 @@ DiscreteIndex::DiscreteIndex(pugi::xml_node node) auto params = get_node_array(node, "parameters"); std::size_t n = params.size() / 2; - assign(&(*params.begin()) + n, n); + assign(params.data() + n, n); } DiscreteIndex::DiscreteIndex(const double* p, int n) From 675ec5f9abc72d9e0c885139cc7a06539e33a459 Mon Sep 17 00:00:00 2001 From: guyshtot Date: Thu, 23 Mar 2023 13:07:21 +0200 Subject: [PATCH 1664/2654] Added test for the use of a Library with specified nuclides --- .../__init__.py | 0 .../inputs_true.dat | 1769 +++++++++++++++++ .../results_true.dat | 1 + .../mgxs_library_specific_nuclides/test.py | 71 + 4 files changed, 1841 insertions(+) create mode 100644 tests/regression_tests/mgxs_library_specific_nuclides/__init__.py create mode 100644 tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat create mode 100644 tests/regression_tests/mgxs_library_specific_nuclides/results_true.dat create mode 100644 tests/regression_tests/mgxs_library_specific_nuclides/test.py diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/__init__.py b/tests/regression_tests/mgxs_library_specific_nuclides/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat new file mode 100644 index 000000000..205eb059c --- /dev/null +++ b/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat @@ -0,0 +1,1769 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 1 + + + 3 + + + 0.0 20000000.0 + + + 2 + + + 3 + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U235 total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U235 total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + absorption + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + absorption + tracklength + + + 1 2 + U235 total + (n,2n) + tracklength + + + 1 2 + U235 total + (n,3n) + tracklength + + + 1 2 + U235 total + (n,4n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + absorption + tracklength + + + 1 2 + U235 total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + kappa-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + scatter + tracklength + + + 1 2 + total + flux + analog + + + 1 2 + U235 total + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + U235 total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + U235 total + nu-scatter + analog + + + 1 2 5 + U235 total + nu-scatter + analog + + + 1 2 5 + U235 total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U235 total + nu-fission + analog + + + 1 2 5 + U235 total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + scatter + tracklength + + + 1 2 5 30 + U235 total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + scatter + tracklength + + + 1 2 5 30 + U235 total + scatter + analog + + + 1 2 5 + U235 total + nu-scatter + analog + + + 1 54 + U235 total + nu-fission + analog + + + 1 5 + U235 total + nu-fission + analog + + + 1 54 + U235 total + prompt-nu-fission + analog + + + 1 5 + U235 total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + inverse-velocity + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + prompt-nu-fission + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + U235 total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U235 total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U235 total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,elastic) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,level) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,2n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,na) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,nc) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,gamma) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,a) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,Xa) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + heating + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + damage-energy + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,n1) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U235 total + (n,a0) + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + U235 total + (n,nc) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U235 total + (n,n1) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U235 total + (n,2n) + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + total + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 total + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 total + nu-scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + absorption + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + absorption + tracklength + + + 106 2 + Zr90 total + (n,2n) + tracklength + + + 106 2 + Zr90 total + (n,3n) + tracklength + + + 106 2 + Zr90 total + (n,4n) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + absorption + tracklength + + + 106 2 + Zr90 total + fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + nu-fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + kappa-fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + scatter + tracklength + + + 106 2 + total + flux + analog + + + 106 2 + Zr90 total + nu-scatter + analog + + + 106 2 + total + flux + analog + + + 106 2 5 30 + Zr90 total + scatter + analog + + + 106 2 + total + flux + analog + + + 106 2 5 30 + Zr90 total + nu-scatter + analog + + + 106 2 5 + Zr90 total + nu-scatter + analog + + + 106 2 5 + Zr90 total + scatter + analog + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 total + nu-fission + analog + + + 106 2 5 + Zr90 total + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + scatter + tracklength + + + 106 2 5 30 + Zr90 total + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + scatter + tracklength + + + 106 2 5 30 + Zr90 total + scatter + analog + + + 106 2 5 + Zr90 total + nu-scatter + analog + + + 106 54 + Zr90 total + nu-fission + analog + + + 106 5 + Zr90 total + nu-fission + analog + + + 106 54 + Zr90 total + prompt-nu-fission + analog + + + 106 5 + Zr90 total + prompt-nu-fission + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + inverse-velocity + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + prompt-nu-fission + tracklength + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 total + prompt-nu-fission + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 total + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 total + nu-scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,elastic) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,level) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,2n) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,na) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,nc) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,gamma) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,a) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,Xa) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + heating + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + damage-energy + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,n1) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 total + (n,a0) + tracklength + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 total + (n,nc) + analog + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 total + (n,n1) + analog + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 total + (n,2n) + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + total + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 total + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 total + nu-scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + absorption + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + absorption + tracklength + + + 211 2 + H1 total + (n,2n) + tracklength + + + 211 2 + H1 total + (n,3n) + tracklength + + + 211 2 + H1 total + (n,4n) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + absorption + tracklength + + + 211 2 + H1 total + fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + nu-fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + kappa-fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + scatter + tracklength + + + 211 2 + total + flux + analog + + + 211 2 + H1 total + nu-scatter + analog + + + 211 2 + total + flux + analog + + + 211 2 5 30 + H1 total + scatter + analog + + + 211 2 + total + flux + analog + + + 211 2 5 30 + H1 total + nu-scatter + analog + + + 211 2 5 + H1 total + nu-scatter + analog + + + 211 2 5 + H1 total + scatter + analog + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 total + nu-fission + analog + + + 211 2 5 + H1 total + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + scatter + tracklength + + + 211 2 5 30 + H1 total + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + scatter + tracklength + + + 211 2 5 30 + H1 total + scatter + analog + + + 211 2 5 + H1 total + nu-scatter + analog + + + 211 54 + H1 total + nu-fission + analog + + + 211 5 + H1 total + nu-fission + analog + + + 211 54 + H1 total + prompt-nu-fission + analog + + + 211 5 + H1 total + prompt-nu-fission + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + inverse-velocity + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + prompt-nu-fission + tracklength + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 total + prompt-nu-fission + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 total + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 total + nu-scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,elastic) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,level) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,2n) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,na) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,nc) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,gamma) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,a) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,Xa) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + heating + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + damage-energy + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,n1) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 total + (n,a0) + tracklength + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 total + (n,nc) + analog + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 total + (n,n1) + analog + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 total + (n,2n) + analog + + diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_specific_nuclides/results_true.dat new file mode 100644 index 000000000..05ee40902 --- /dev/null +++ b/tests/regression_tests/mgxs_library_specific_nuclides/results_true.dat @@ -0,0 +1 @@ +3e86542d1166b8a0bcc61742b88c9e931d63733477f3274b32b4da64d8f05413fa6330d5615f44f24735c2c2f77d3071f3dce38faba284c321ceab81c1064480 \ No newline at end of file diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/test.py b/tests/regression_tests/mgxs_library_specific_nuclides/test.py new file mode 100644 index 000000000..41ae0a689 --- /dev/null +++ b/tests/regression_tests/mgxs_library_specific_nuclides/test.py @@ -0,0 +1,71 @@ +import hashlib + +import openmc +import openmc.mgxs +from openmc.examples import pwr_pin_cell + +from tests.testing_harness import PyAPITestHarness + + +class MGXSTestHarness(PyAPITestHarness): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Initialize a two-group structure + energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) + + # Initialize MGXS Library for a few cross section types + self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) + self.mgxs_lib.by_nuclide = True + + # Test relevant MGXS types + relevant_MGXS_TYPES = [item for item in openmc.mgxs.MGXS_TYPES + if item != 'current'] + # Add in a subset of openmc.mgxs.ARBITRARY_VECTOR_TYPES and + # openmc.mgxs.ARBITRARY_MATRIX_TYPES so we can see the code works, + # but not use too much resources + relevant_MGXS_TYPES += [ + "(n,elastic)", "(n,level)", "(n,2n)", "(n,na)", "(n,nc)", + "(n,gamma)", "(n,a)", "(n,Xa)", "heating", "damage-energy", + "(n,n1)", "(n,a0)", "(n,nc) matrix", "(n,n1) matrix", + "(n,2n) matrix"] + self.mgxs_lib.mgxs_types = tuple(relevant_MGXS_TYPES) + self.mgxs_lib.energy_groups = energy_groups + self.mgxs_lib.legendre_order = 3 + self.mgxs_lib.domain_type = 'material' + self.mgxs_lib.nuclides=['U235','Zr90','H1'] + self.mgxs_lib.build_library() + + # Add tallies + self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + + def _get_results(self, hash_output=True): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + sp = openmc.StatePoint(self._sp_name) + + # Load the MGXS library from the statepoint + self.mgxs_lib.load_from_statepoint(sp) + + # Build a string from Pandas Dataframe for each MGXS + outstr = '' + for domain in self.mgxs_lib.domains: + for mgxs_type in self.mgxs_lib.mgxs_types: + mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) + df = mgxs.get_pandas_dataframe() + outstr += df.to_string() + '\n' + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + +def test_mgxs_library_specific_nuclides(): + model = pwr_pin_cell() + harness = MGXSTestHarness('statepoint.10.h5', model) + harness.main() From a704ec73f26a7e89de06c2e2303ee170f0adf5cf Mon Sep 17 00:00:00 2001 From: guyshtot Date: Thu, 23 Mar 2023 13:12:36 +0200 Subject: [PATCH 1665/2654] Applied CR suggestion --- openmc/mgxs/library.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 0eb00c8f1..1c3a5dbb4 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -547,8 +547,10 @@ class Library: domain_nuclides = None if self.nuclides: if domain_nuclides: - mgxs.nuclides = [nuclide for nuclide in self.nuclides if nuclide in domain_nuclides] + [ - "total"] + mgxs.nuclides = [ + nuclide for nuclide in self.nuclides + if nuclide in domain_nuclides + ] + ["total"] else: mgxs.nuclides = self.nuclides From 10787a2da6c4a154464c61df5e7e4823f686cb2b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 23 Mar 2023 13:37:26 -0500 Subject: [PATCH 1666/2654] Account for coincident position in find_r_crossing --- src/mesh.cpp | 10 +-- tests/unit_tests/test_filter_mesh.py | 97 ++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 02e5171bb..306e56070 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1075,7 +1075,8 @@ double CylindricalMesh::find_r_crossing( const double inv_denominator = 1.0 / denominator; const double p = (u.x * r.x + u.y * r.y) * inv_denominator; - double D = p * p + (r0 * r0 - r.x * r.x - r.y * r.y) * inv_denominator; + double c = r.x * r.x + r.y * r.y - r0 * r0; + double D = p * p - c * inv_denominator; if (D < 0.0) return INFTY; @@ -1083,7 +1084,7 @@ double CylindricalMesh::find_r_crossing( D = std::sqrt(D); // the solution -p - D is always smaller as -p + D : Check this one first - if (-p - D > l) + if (-p - D > l && std::abs(c) > FP_COINCIDENT) return -p - D; if (-p + D > l) return -p + D; @@ -1303,12 +1304,13 @@ double SphericalMesh::find_r_crossing( // |r+s*u| = |r| + 2*s*r*u + s^2 (|u|==1 !) const double r0 = grid_[0][shell]; const double p = r.dot(u); - double D = p * p - r.dot(r) + r0 * r0; + double c = r.dot(r) - r0 * r0; + double D = p * p - c; if (D >= 0.0) { D = std::sqrt(D); // the solution -p - D is always smaller as -p + D : Check this one first - if (-p - D > l) + if (-p - D > l && std::abs(c) > FP_COINCIDENT) return -p - D; if (-p + D > l) return -p + D; diff --git a/tests/unit_tests/test_filter_mesh.py b/tests/unit_tests/test_filter_mesh.py index 3bb836e46..5e5a84f7b 100644 --- a/tests/unit_tests/test_filter_mesh.py +++ b/tests/unit_tests/test_filter_mesh.py @@ -1,6 +1,7 @@ import math import numpy as np +import pytest from uncertainties import unumpy import openmc @@ -112,6 +113,102 @@ def test_cylindrical_mesh_estimators(run_in_tmpdir): std_dev = unumpy.std_devs(delta) assert np.all(diff < 3*std_dev) + +def test_cylindrical_mesh_coincident(run_in_tmpdir): + """Test for cylindrical mesh boundary being coincident with a cell boundary""" + + fuel = openmc.Material() + fuel.add_nuclide('U235', 1.) + fuel.set_density('g/cm3', 4.5) + + zcyl = openmc.ZCylinder(r=1.25) + box = openmc.rectangular_prism(4.0, 4.0, boundary_type='reflective') + cell1 = openmc.Cell(fill=fuel, region=-zcyl) + cell2 = openmc.Cell(fill=None, region=+zcyl & box) + model = openmc.Model() + model.geometry = openmc.Geometry([cell1, cell2]) + + model.settings.particles = 100 + model.settings.batches = 10 + model.settings.inactive = 0 + + cyl_mesh = openmc.CylindricalMesh() + cyl_mesh.r_grid = [0., 1.25] + cyl_mesh.phi_grid = [0., 2*math.pi] + cyl_mesh.z_grid = [-1e10, 1e10] + cyl_mesh_filter = openmc.MeshFilter(cyl_mesh) + cell_filter = openmc.CellFilter([cell1]) + + tally1 = openmc.Tally() + tally1.filters = [cyl_mesh_filter] + tally1.scores = ['flux'] + tally2 = openmc.Tally() + tally2.filters = [cell_filter] + tally2.scores = ['flux'] + model.tallies = openmc.Tallies([tally1, tally2]) + + # Run OpenMC + sp_filename = model.run() + + # Get flux for each of the two tallies + with openmc.StatePoint(sp_filename) as sp: + t1 = sp.tallies[tally1.id] + t2 = sp.tallies[tally2.id] + mean1 = t1.mean.ravel()[0] + mean2 = t2.mean.ravel()[0] + + # The two tallies should be exactly the same + assert mean1 == pytest.approx(mean2) + + +def test_spherical_mesh_coincident(run_in_tmpdir): + """Test for spherical mesh boundary being coincident with a cell boundary""" + + fuel = openmc.Material() + fuel.add_nuclide('U235', 1.) + fuel.set_density('g/cm3', 4.5) + + sph = openmc.Sphere(r=1.25) + rcc = openmc.model.RectangularParallelepiped( + -2.0, 2.0, -2.0, 2.0, -2.0, 2.0, boundary_type='reflective') + cell1 = openmc.Cell(fill=fuel, region=-sph) + cell2 = openmc.Cell(fill=None, region=+sph & -rcc) + model = openmc.Model() + model.geometry = openmc.Geometry([cell1, cell2]) + + model.settings.particles = 100 + model.settings.batches = 10 + model.settings.inactive = 0 + + sph_mesh = openmc.SphericalMesh() + sph_mesh.r_grid = [0., 1.25] + sph_mesh.phi_grid = [0., 2*math.pi] + sph_mesh.theta_grid = [0., math.pi] + sph_mesh_filter = openmc.MeshFilter(sph_mesh) + cell_filter = openmc.CellFilter([cell1]) + + tally1 = openmc.Tally() + tally1.filters = [sph_mesh_filter] + tally1.scores = ['flux'] + tally2 = openmc.Tally() + tally2.filters = [cell_filter] + tally2.scores = ['flux'] + model.tallies = openmc.Tallies([tally1, tally2]) + + # Run OpenMC + sp_filename = model.run() + + # Get flux for each of the two tallies + with openmc.StatePoint(sp_filename) as sp: + t1 = sp.tallies[tally1.id] + t2 = sp.tallies[tally2.id] + mean1 = t1.mean.ravel()[0] + mean2 = t2.mean.ravel()[0] + + # The two tallies should be exactly the same + assert mean1 == pytest.approx(mean2) + + def test_get_reshaped_data(run_in_tmpdir): """Test that expanding MeshFilter dimensions works as expected""" From e7eb746dc415d8c5822340052a22666302d35a15 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 23 Mar 2023 14:08:03 -0500 Subject: [PATCH 1667/2654] Always use quotes for python-version in ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82bd70a62..1a905b3cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,13 +35,13 @@ jobs: vectfit: [n] include: - - python-version: 3.7 + - python-version: "3.7" omp: n mpi: n - - python-version: 3.8 + - python-version: "3.8" omp: n mpi: n - - python-version: 3.9 + - python-version: "3.9" omp: n mpi: n - python-version: "3.11" From e93dd66430d7cae137cae8798b72645cd2d32726 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 23 Mar 2023 15:07:32 -0500 Subject: [PATCH 1668/2654] eliminate set/list redundancy Co-authored-by: Paul Romano --- openmc/deplete/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 90d1ddde4..ec0f65650 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -308,8 +308,8 @@ class FluxCollapseHelper(ReactionRateHelper): if self._nuclides_direct is not None: # check if any direct tally nuclides are requested that are not # already loaded with the materials. Load separately if so. - mat_nuclides = [n for mat in materials for n in mat.nuclides] - extra_nuclides = set(self._nuclides_direct) - set(mat_nuclides) + mat_nuclides = {n for mat in materials for n in mat.nuclides} + extra_nuclides = set(self._nuclides_direct) - mat_nuclides for nuc in extra_nuclides: load_nuclide(nuc) self._rate_tally.nuclides = self._nuclides_direct From 7f68462e3a4d6f10914e4812eba67d482e2cb7f1 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 23 Mar 2023 15:43:03 -0500 Subject: [PATCH 1669/2654] add nuclide that is not in model; (fails locally) --- tests/unit_tests/test_deplete_activation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 1842ad8ac..cef614f82 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -47,7 +47,7 @@ ENERGIES = np.logspace(log10(1e-5), log10(2e7), 100) ("direct", {}, 1e-5), ("flux", {'energies': ENERGIES}, 0.01), ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)']}, 1e-5), - ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)'], 'nuclides': ['W186']}, 1e-5), + ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)'], 'nuclides': ['W186', 'H3']}, 1e-5), ]) def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts, tolerance): # Determine (n.gamma) reaction rate using initial run From 2f5428f739808abc67674fc9fc126e197f3201a9 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Fri, 24 Mar 2023 12:13:00 -0400 Subject: [PATCH 1670/2654] Update openmc/model/surface_composite.py Co-authored-by: Patrick Shriwise --- openmc/model/surface_composite.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 09c2f4fee..354a62883 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -851,7 +851,6 @@ class Polygon(CompositeSurface): # All 4 cross products are zero # Determine number of unique points, x span and y span for # both line segments - #unique_pts = np.unique(np.vstack((p0, p1, p2, p3)), axis=0) xmin1, xmax1 = min(p0[0], p1[0]), max(p0[0], p1[0]) ymin1, ymax1 = min(p0[1], p1[1]), max(p0[1], p1[1]) xmin2, xmax2 = min(p2[0], p3[0]), max(p2[0], p3[0]) From 11e618fe81a2d7515a093d9549d083cc82bd73c2 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Tue, 28 Feb 2023 11:31:04 -0500 Subject: [PATCH 1671/2654] adding export_to_xml to run and updating tests --- openmc/model/model.py | 11 +- src/cell.cpp | 2 +- .../adj_cell_rotation/inputs_true.dat | 74 +- .../asymmetric_lattice/inputs_true.dat | 411 +- .../cpp_driver/inputs_true.dat | 84 +- .../create_fission_neutrons/inputs_true.dat | 71 +- .../create_fission_neutrons/test.py | 16 +- .../dagmc/external/inputs_true.dat | 77 +- .../dagmc/legacy/inputs_true.dat | 75 +- .../dagmc/refl/inputs_true.dat | 55 +- tests/regression_tests/dagmc/refl/test.py | 23 +- .../dagmc/universes/inputs_true.dat | 108 +- .../regression_tests/dagmc/universes/test.py | 23 +- .../dagmc/uwuw/inputs_true.dat | 55 +- tests/regression_tests/dagmc/uwuw/test.py | 22 +- .../diff_tally/inputs_true.dat | 723 ++- .../distribmat/inputs_true.dat | 117 +- .../distribmat/results_true.dat | 2 +- tests/regression_tests/distribmat/test.py | 17 +- .../eigenvalue_genperbatch/inputs_true.dat | 59 +- .../energy_cutoff/inputs_true.dat | 81 +- tests/regression_tests/energy_cutoff/test.py | 15 +- .../energy_laws/inputs_true.dat | 44 +- .../external_moab/inputs_true.dat | 143 +- tests/regression_tests/external_moab/test.py | 2 - .../filter_cellinstance/inputs_true.dat | 119 +- .../filter_energyfun/inputs_true.dat | 209 +- .../filter_mesh/inputs_true.dat | 301 +- .../filter_translations/inputs_true.dat | 165 +- .../fixed_source/inputs_true.dat | 59 +- .../iso_in_lab/inputs_true.dat | 488 +-- .../lattice_hex_coincident/inputs_true.dat | 160 +- .../lattice_hex_coincident/test.py | 13 +- .../lattice_hex_x/inputs_true.dat | 160 +- tests/regression_tests/lattice_hex_x/test.py | 15 +- .../lattice_multiple/inputs_true.dat | 96 +- .../lattice_rotated/inputs_true.dat | 114 +- .../regression_tests/mg_basic/inputs_true.dat | 126 +- .../mg_basic_delayed/inputs_true.dat | 124 +- .../mg_convert/inputs_true.dat | 56 +- tests/regression_tests/mg_convert/test.py | 12 +- .../mg_legendre/inputs_true.dat | 64 +- .../mg_max_order/inputs_true.dat | 66 +- .../mg_survival_biasing/inputs_true.dat | 66 +- .../mg_tallies/inputs_true.dat | 327 +- .../mgxs_library_ce_to_mg/inputs_true.dat | 499 ++- .../mgxs_library_ce_to_mg/test.py | 9 +- .../inputs_true.dat | 499 ++- .../mgxs_library_ce_to_mg_nuclides/test.py | 9 +- .../mgxs_library_condense/inputs_true.dat | 1061 +++-- .../mgxs_library_correction/inputs_true.dat | 685 ++- .../mgxs_library_distribcell/inputs_true.dat | 1047 +++-- .../mgxs_library_hdf5/inputs_true.dat | 1061 +++-- .../mgxs_library_histogram/inputs_true.dat | 535 ++- .../mgxs_library_mesh/inputs_true.dat | 1021 +++-- .../mgxs_library_no_nuclides/inputs_true.dat | 3901 ++++++++--------- .../mgxs_library_nuclides/inputs_true.dat | 3535 ++++++++------- .../multipole/inputs_true.dat | 103 +- .../regression_tests/ncrystal/inputs_true.dat | 87 +- .../regression_tests/periodic/inputs_true.dat | 72 +- .../periodic_6fold/inputs_true.dat | 66 +- .../periodic_hex/inputs_true.dat | 46 +- .../photon_production/inputs_true.dat | 133 +- .../photon_production_fission/inputs_true.dat | 95 +- .../photon_source/inputs_true.dat | 87 +- tests/regression_tests/photon_source/test.py | 15 +- .../resonance_scattering/inputs_true.dat | 66 +- .../resonance_scattering/test.py | 14 +- .../salphabeta/inputs_true.dat | 118 +- .../score_current/inputs_true.dat | 107 +- tests/regression_tests/source/inputs_true.dat | 298 +- tests/regression_tests/source/test.py | 14 +- .../source_dlopen/inputs_true.dat | 44 +- .../inputs_true.dat | 44 +- .../surface_source/inputs_true_read.dat | 65 +- .../surface_source/inputs_true_write.dat | 77 +- .../surface_source/surface_source_true.h5 | Bin 106144 -> 106144 bytes .../surface_tally/inputs_true.dat | 203 +- tests/regression_tests/surface_tally/test.py | 15 +- .../regression_tests/tallies/inputs_true.dat | 853 ++-- .../tally_aggregation/inputs_true.dat | 107 +- .../tally_arithmetic/inputs_true.dat | 109 +- .../tally_slice_merge/inputs_true.dat | 541 ++- tests/regression_tests/torus/inputs_true.dat | 66 +- .../torus/large_major/inputs_true.dat | 71 +- .../inputs_true.dat | 67 +- tests/regression_tests/triso/inputs_true.dat | 878 ++-- tests/regression_tests/triso/test.py | 14 +- .../unstructured_mesh/inputs_true.dat | 179 +- .../unstructured_mesh/inputs_true0.dat | 179 +- .../unstructured_mesh/inputs_true1.dat | 179 +- .../unstructured_mesh/inputs_true10.dat | 179 +- .../unstructured_mesh/inputs_true11.dat | 179 +- .../unstructured_mesh/inputs_true12.dat | 179 +- .../unstructured_mesh/inputs_true13.dat | 179 +- .../unstructured_mesh/inputs_true14.dat | 179 +- .../unstructured_mesh/inputs_true15.dat | 179 +- .../unstructured_mesh/inputs_true2.dat | 179 +- .../unstructured_mesh/inputs_true3.dat | 179 +- .../unstructured_mesh/inputs_true4.dat | 181 +- .../unstructured_mesh/inputs_true5.dat | 181 +- .../unstructured_mesh/inputs_true6.dat | 181 +- .../unstructured_mesh/inputs_true7.dat | 181 +- .../unstructured_mesh/inputs_true8.dat | 179 +- .../unstructured_mesh/inputs_true9.dat | 179 +- tests/regression_tests/void/inputs_true.dat | 261 +- .../volume_calc/inputs_true.dat | 148 +- .../volume_calc/inputs_true_mg.dat | 150 +- tests/regression_tests/volume_calc/test.py | 10 +- .../weightwindows/inputs_true.dat | 189 +- tests/testing_harness.py | 7 +- 111 files changed, 13560 insertions(+), 13643 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 3e0422eb1..78f02242f 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -596,7 +596,8 @@ class Model: def run(self, particles=None, threads=None, geometry_debug=False, restart_file=None, tracks=False, output=True, cwd='.', - openmc_exec='openmc', mpi_args=None, event_based=None): + openmc_exec='openmc', mpi_args=None, event_based=None, + export_model_xml=True): """Runs OpenMC. If the C API has been initialized, then the C API is used, otherwise, this method creates the XML files and runs OpenMC via a system call. In both cases this method returns the path to the last @@ -639,6 +640,9 @@ class Model: event_based : None or bool, optional Turns on event-based parallelism if True. If None, the value in the Settings will be used. + export_model_xml : bool, optional + Exports a single model.xml file rather than separate files. + Defaults to True. Returns ------- @@ -688,7 +692,10 @@ class Model: else: # Then run via the command line - self.export_to_xml() + if export_model_xml: + self.export_to_model_xml() + else: + self.export_to_xml() openmc.run(particles, threads, geometry_debug, restart_file, tracks, output, Path('.'), openmc_exec, mpi_args, event_based) diff --git a/src/cell.cpp b/src/cell.cpp index 9ba14c6cf..c96abf39b 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -291,7 +291,7 @@ CSGCell::CSGCell(pugi::xml_node cell_node) if (fill_present) { fill_ = std::stoi(get_node_value(cell_node, "fill")); if (fill_ == universe_) { - fatal_error(fmt::format("Cell {} is filled with the same universe that" + fatal_error(fmt::format("Cell {} is filled with the same universe that " "it is contained in.", id_)); } diff --git a/tests/regression_tests/adj_cell_rotation/inputs_true.dat b/tests/regression_tests/adj_cell_rotation/inputs_true.dat index 24b00199b..1c4516f42 100644 --- a/tests/regression_tests/adj_cell_rotation/inputs_true.dat +++ b/tests/regression_tests/adj_cell_rotation/inputs_true.dat @@ -1,38 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 10000 - 10 - 5 - - - -4.0 -4.0 -4.0 4.0 4.0 4.0 - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 10000 + 10 + 5 + + + -4.0 -4.0 -4.0 4.0 4.0 4.0 + + + + diff --git a/tests/regression_tests/asymmetric_lattice/inputs_true.dat b/tests/regression_tests/asymmetric_lattice/inputs_true.dat index bbdc79715..b247412e5 100644 --- a/tests/regression_tests/asymmetric_lattice/inputs_true.dat +++ b/tests/regression_tests/asymmetric_lattice/inputs_true.dat @@ -1,19 +1,168 @@ - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 @@ -31,197 +180,47 @@ 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 3 3 - -32.13 -32.13 - + + + 21.42 21.42 + 3 3 + -32.13 -32.13 + 8 7 7 8 8 8 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -32 -32 0 32 32 32 - - - - - - - 27 - - - 1 - nu-fission - - + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -32 -32 0 32 32 32 + + + + + + 27 + + + 1 + nu-fission + + + diff --git a/tests/regression_tests/cpp_driver/inputs_true.dat b/tests/regression_tests/cpp_driver/inputs_true.dat index faa3fa9b1..cdace34f0 100644 --- a/tests/regression_tests/cpp_driver/inputs_true.dat +++ b/tests/regression_tests/cpp_driver/inputs_true.dat @@ -1,45 +1,45 @@ - - - - - - - - 4.0 4.0 - 2 2 - -4.0 -4.0 - + + + + + + + + + + + + + + + + + + + + + + + + 4.0 4.0 + 2 2 + -4.0 -4.0 + 2 2 2 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 1 - + + + + + + + + + + eigenvalue + 100 + 10 + 1 + + diff --git a/tests/regression_tests/create_fission_neutrons/inputs_true.dat b/tests/regression_tests/create_fission_neutrons/inputs_true.dat index b0ca89647..f79ba379c 100644 --- a/tests/regression_tests/create_fission_neutrons/inputs_true.dat +++ b/tests/regression_tests/create_fission_neutrons/inputs_true.dat @@ -1,37 +1,36 @@ - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - -1 -1 -1 1 1 1 - - - - false - - - - - flux - - + + + + + + + + + + + + + + + + + + + fixed source + 100 + 10 + + + -1 -1 -1 1 1 1 + + + + false + + + + flux + + + diff --git a/tests/regression_tests/create_fission_neutrons/test.py b/tests/regression_tests/create_fission_neutrons/test.py index f1c1d072c..82bfaafa6 100755 --- a/tests/regression_tests/create_fission_neutrons/test.py +++ b/tests/regression_tests/create_fission_neutrons/test.py @@ -4,14 +4,14 @@ from tests.testing_harness import PyAPITestHarness class CreateFissionNeutronsTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Material is composed of H-1 and U-235 mat = openmc.Material(material_id=1, name='mat') mat.set_density('atom/b-cm', 0.069335) mat.add_nuclide('H1', 40.0) mat.add_nuclide('U235', 1.0) - materials_file = openmc.Materials([mat]) - materials_file.export_to_xml() + self._model.materials = openmc.Materials([mat]) # Cell is box with reflective boundary x1 = openmc.XPlane(surface_id=1, x0=-1) @@ -27,8 +27,7 @@ class CreateFissionNeutronsTestHarness(PyAPITestHarness): box.fill = mat root = openmc.Universe(universe_id=0, name='root universe') root.add_cell(box) - geometry = openmc.Geometry(root) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root) # Set the running parameters settings_file = openmc.Settings() @@ -41,14 +40,14 @@ class CreateFissionNeutronsTestHarness(PyAPITestHarness): watt_dist = openmc.stats.Watt() settings_file.source = openmc.source.Source(space=uniform_dist, energy=watt_dist) - settings_file.export_to_xml() + self._model.settings = settings_file # Create tallies tallies = openmc.Tallies() tally = openmc.Tally(1) tally.scores = ['flux'] tallies.append(tally) - tallies.export_to_xml() + self._model.tallies = tallies def _get_results(self): """Digest info in the statepoint and return as a string.""" @@ -66,5 +65,6 @@ class CreateFissionNeutronsTestHarness(PyAPITestHarness): def test_create_fission_neutrons(): - harness = CreateFissionNeutronsTestHarness('statepoint.10.h5') + harness = CreateFissionNeutronsTestHarness('statepoint.10.h5', + model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/dagmc/external/inputs_true.dat b/tests/regression_tests/dagmc/external/inputs_true.dat index dd75bbdbd..5547f333c 100644 --- a/tests/regression_tests/dagmc/external/inputs_true.dat +++ b/tests/regression_tests/dagmc/external/inputs_true.dat @@ -1,40 +1,39 @@ - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - 293 - - - - - 1 - - - 1 - total - - + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 0 + + + -4 -4 -4 4 4 4 + + + 293 + + + + 1 + + + 1 + total + + + diff --git a/tests/regression_tests/dagmc/legacy/inputs_true.dat b/tests/regression_tests/dagmc/legacy/inputs_true.dat index 2f5641046..89d458a2b 100644 --- a/tests/regression_tests/dagmc/legacy/inputs_true.dat +++ b/tests/regression_tests/dagmc/legacy/inputs_true.dat @@ -1,39 +1,38 @@ - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - - - - - 1 - - - 1 - total - - + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 0 + + + -4 -4 -4 4 4 4 + + + + + + 1 + + + 1 + total + + + diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat index 938916ece..894d50104 100644 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ b/tests/regression_tests/dagmc/refl/inputs_true.dat @@ -1,29 +1,28 @@ - - - - - - - - - eigenvalue - 100 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - - - - - 2 - - - 1 - total - - + + + + + + + + eigenvalue + 100 + 5 + 0 + + + -4 -4 -4 4 4 4 + + + + + + 2 + + + 1 + total + + + diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py index 5afc1a7a2..5b08f0c4a 100644 --- a/tests/regression_tests/dagmc/refl/test.py +++ b/tests/regression_tests/dagmc/refl/test.py @@ -10,34 +10,29 @@ pytestmark = pytest.mark.skipif( reason="DAGMC CAD geometry is not enabled.") class UWUWTest(PyAPITestHarness): - - def _build_inputs(self): - model = openmc.model.Model() + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 100 + self._model.settings.batches = 5 + self._model.settings.inactive = 0 + self._model.settings.particles = 100 source = openmc.Source(space=Box([-4, -4, -4], [ 4, 4, 4])) - model.settings.source = source - - model.settings.export_to_xml() + self._model.settings.source = source # geometry dag_univ = openmc.DAGMCUniverse("dagmc.h5m", auto_geom_ids=True) - model.geometry = openmc.Geometry(dag_univ) + self._model.geometry = openmc.Geometry(dag_univ) # tally tally = openmc.Tally() tally.scores = ['total'] tally.filters = [openmc.CellFilter(2)] - model.tallies = [tally] + self._model.tallies = [tally] - model.tallies.export_to_xml() - model.export_to_xml() def test_refl(): - harness = UWUWTest('statepoint.5.h5') + harness = UWUWTest('statepoint.5.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index ea6ad519b..b88e83df4 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,55 +1,55 @@ - - - - - 24.0 24.0 - 2 2 - -24.0 -24.0 - -9 9 -9 9 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 2 - -

false - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 24.0 24.0 + 2 2 + -24.0 -24.0 + +1 1 +1 1 + + + + + + + + + + eigenvalue + 100 + 10 + 2 + + false + + + diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 47897ad56..a318275cd 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -12,9 +12,8 @@ pytestmark = pytest.mark.skipif( class DAGMCUniverseTest(PyAPITestHarness): - - def _build_inputs(self): - model = openmc.model.Model() + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) ### MATERIALS ### fuel = openmc.Material(name='no-void fuel') @@ -40,7 +39,7 @@ class DAGMCUniverseTest(PyAPITestHarness): water.add_nuclide('B11', 3.2218e-05) water.add_s_alpha_beta('c_H_in_H2O') - model.materials = openmc.Materials([fuel, cladding, water]) + self._model.materials = openmc.Materials([fuel, cladding, water]) ### GEOMETRY ### # create the DAGMC universe @@ -51,7 +50,7 @@ class DAGMCUniverseTest(PyAPITestHarness): # uses the bound_dag_cell as the root argument to test the type checks in openmc.Geometry bound_pincell_geometry = openmc.Geometry(root=bound_pincell_universe) # assigns the bound_dag_geometry to the model to test the type checks in model.Geometry setter - model.Geometry = bound_pincell_geometry + self._model.geometry = bound_pincell_geometry # create a 2 x 2 lattice using the DAGMC pincell pitch = np.asarray((24.0, 24.0)) @@ -71,17 +70,15 @@ class DAGMCUniverseTest(PyAPITestHarness): bounding_region = +left & -right & +front & -back & +bottom & -top bounding_cell = openmc.Cell(fill=lattice, region=bounding_region) - model.geometry = openmc.Geometry([bounding_cell]) + self._model.geometry = openmc.Geometry([bounding_cell]) # settings - model.settings.particles = 100 - model.settings.batches = 10 - model.settings.inactive = 2 - model.settings.output = {'summary' : False} - - model.export_to_xml() + self._model.settings.particles = 100 + self._model.settings.batches = 10 + self._model.settings.inactive = 2 + self._model.settings.output = {'summary' : False} def test_univ(): - harness = DAGMCUniverseTest('statepoint.10.h5') + harness = DAGMCUniverseTest('statepoint.10.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/dagmc/uwuw/inputs_true.dat b/tests/regression_tests/dagmc/uwuw/inputs_true.dat index 7d533c5db..07384b625 100644 --- a/tests/regression_tests/dagmc/uwuw/inputs_true.dat +++ b/tests/regression_tests/dagmc/uwuw/inputs_true.dat @@ -1,29 +1,28 @@ - - - - - - - - - eigenvalue - 100 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - - - - - 1 - - - 1 - total - - + + + + + + + + eigenvalue + 100 + 5 + 0 + + + -4 -4 -4 4 4 4 + + + + + + 1 + + + 1 + total + + + diff --git a/tests/regression_tests/dagmc/uwuw/test.py b/tests/regression_tests/dagmc/uwuw/test.py index a8da2da60..19986e589 100644 --- a/tests/regression_tests/dagmc/uwuw/test.py +++ b/tests/regression_tests/dagmc/uwuw/test.py @@ -10,33 +10,29 @@ pytestmark = pytest.mark.skipif( reason="DAGMC CAD geometry is not enabled.") class UWUWTest(PyAPITestHarness): - - def _build_inputs(self): - model = openmc.model.Model() + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 100 + self._model.settings.batches = 5 + self._model.settings.inactive = 0 + self._model.settings.particles = 100 source = openmc.Source(space=Box([-4, -4, -4], [ 4, 4, 4])) - model.settings.source = source - - model.settings.export_to_xml() + self._model.settings.source = source # geometry dag_univ = openmc.DAGMCUniverse("dagmc.h5m") - model.geometry = openmc.Geometry(root=dag_univ) + self._model.geometry = openmc.Geometry(root=dag_univ) # tally tally = openmc.Tally() tally.scores = ['total'] tally.filters = [openmc.CellFilter(1)] - model.tallies = [tally] + self._model.tallies = [tally] - model.export_to_xml() def test_uwuw(): - harness = UWUWTest('statepoint.5.h5') + harness = UWUWTest('statepoint.5.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/diff_tally/inputs_true.dat b/tests/regression_tests/diff_tally/inputs_true.dat index 909475f96..99697a1e9 100644 --- a/tests/regression_tests/diff_tally/inputs_true.dat +++ b/tests/regression_tests/diff_tally/inputs_true.dat @@ -1,38 +1,187 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 @@ -50,12 +199,12 @@ 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 @@ -73,12 +222,12 @@ 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 @@ -100,12 +249,12 @@ 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 @@ -127,313 +276,163 @@ 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 3 - 0 - - - -160 -160 -183 160 160 183 - - - true - - - - - 1 3 - - - 0.0 0.625 20000000.0 - - - 1 - flux - 1 - - - 1 - flux - 2 - - - 1 - flux - 3 - - - 1 - flux - 4 - - - 1 - flux - 5 - - - 1 - total U235 - total absorption scatter fission nu-fission - 1 - - - 1 - total U235 - total absorption scatter fission nu-fission - 2 - - - 1 - total U235 - total absorption scatter fission nu-fission - 3 - - - 1 - total U235 - total absorption scatter fission nu-fission - 4 - - - 1 - total U235 - total absorption scatter fission nu-fission - 5 - - - 1 - absorption - analog - 1 - - - 1 - absorption - analog - 2 - - - 1 - absorption - analog - 3 - - - 1 - absorption - analog - 4 - - - 1 - absorption - analog - 5 - - - 1 2 - total U235 - nu-fission scatter - 1 - - - 1 2 - total U235 - nu-fission scatter - 2 - - - 1 2 - U235 - nu-fission scatter - 3 - - - 1 2 - U235 - nu-fission scatter - 4 - - - 1 2 - U235 - nu-fission scatter - 5 - - - - - - - + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 3 + 0 + + + -160 -160 -183 160 160 183 + + + true + + + + 1 3 + + + 0.0 0.625 20000000.0 + + + 1 + flux + 1 + + + 1 + flux + 2 + + + 1 + flux + 3 + + + 1 + flux + 4 + + + 1 + flux + 5 + + + 1 + total U235 + total absorption scatter fission nu-fission + 1 + + + 1 + total U235 + total absorption scatter fission nu-fission + 2 + + + 1 + total U235 + total absorption scatter fission nu-fission + 3 + + + 1 + total U235 + total absorption scatter fission nu-fission + 4 + + + 1 + total U235 + total absorption scatter fission nu-fission + 5 + + + 1 + absorption + analog + 1 + + + 1 + absorption + analog + 2 + + + 1 + absorption + analog + 3 + + + 1 + absorption + analog + 4 + + + 1 + absorption + analog + 5 + + + 1 2 + total U235 + nu-fission scatter + 1 + + + 1 2 + total U235 + nu-fission scatter + 2 + + + 1 2 + U235 + nu-fission scatter + 3 + + + 1 2 + U235 + nu-fission scatter + 4 + + + 1 2 + U235 + nu-fission scatter + 5 + + + + + + + + diff --git a/tests/regression_tests/distribmat/inputs_true.dat b/tests/regression_tests/distribmat/inputs_true.dat index a1c1e8311..f6c43c19a 100644 --- a/tests/regression_tests/distribmat/inputs_true.dat +++ b/tests/regression_tests/distribmat/inputs_true.dat @@ -1,62 +1,61 @@ - - - - - - - 2.0 2.0 - 1 - 2 2 - -2.0 -2.0 - + + + + + + + + + + + + + + + + + + + + + + + 2.0 2.0 + 1 + 2 2 + -2.0 -2.0 + 11 11 11 11 - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - -1 -1 -1 1 1 1 - - - - - - - 0 0 0 - 7 7 - 400 400 - - - 0 0 0 - 7 7 - 400 400 - - + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + -1 -1 -1 1 1 1 + + + + + + 0 0 0 + 7 7 + 400 400 + + + 0 0 0 + 7 7 + 400 400 + + + diff --git a/tests/regression_tests/distribmat/results_true.dat b/tests/regression_tests/distribmat/results_true.dat index 4613434ce..af7b27fe7 100644 --- a/tests/regression_tests/distribmat/results_true.dat +++ b/tests/regression_tests/distribmat/results_true.dat @@ -4,7 +4,7 @@ Cell ID = 11 Name = Fill = [2, None, 3, 2] - Region = -9 + Region = -1 Rotation = None Translation = None Volume = None diff --git a/tests/regression_tests/distribmat/test.py b/tests/regression_tests/distribmat/test.py index 33f64ba03..ab7897313 100644 --- a/tests/regression_tests/distribmat/test.py +++ b/tests/regression_tests/distribmat/test.py @@ -4,7 +4,8 @@ from tests.testing_harness import TestHarness, PyAPITestHarness class DistribmatTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) #################### # Materials #################### @@ -22,8 +23,8 @@ class DistribmatTestHarness(PyAPITestHarness): light_fuel.set_density('g/cc', 2.0) light_fuel.add_nuclide('U235', 1.0) - mats_file = openmc.Materials([moderator, dense_fuel, light_fuel]) - mats_file.export_to_xml() + self._model.materials = openmc.Materials([moderator, dense_fuel, + light_fuel]) #################### # Geometry @@ -54,8 +55,7 @@ class DistribmatTestHarness(PyAPITestHarness): c101.region = +x0 & -x1 & +y0 & -y1 root_univ = openmc.Universe(universe_id=0, cells=[c101]) - geometry = openmc.Geometry(root_univ) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root_univ) #################### # Settings @@ -67,7 +67,7 @@ class DistribmatTestHarness(PyAPITestHarness): sets_file.particles = 1000 sets_file.source = openmc.Source(space=openmc.stats.Box( [-1, -1, -1], [1, 1, 1])) - sets_file.export_to_xml() + self._model.settings = sets_file #################### # Plots @@ -89,8 +89,7 @@ class DistribmatTestHarness(PyAPITestHarness): plot2.width = (7, 7) plot2.pixels = (400, 400) - plots = openmc.Plots([plot1, plot2]) - plots.export_to_xml() + self._model.plots = openmc.Plots([plot1, plot2]) def _get_results(self): outstr = super()._get_results() @@ -100,5 +99,5 @@ class DistribmatTestHarness(PyAPITestHarness): def test_distribmat(): - harness = DistribmatTestHarness('statepoint.5.h5') + harness = DistribmatTestHarness('statepoint.5.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/eigenvalue_genperbatch/inputs_true.dat b/tests/regression_tests/eigenvalue_genperbatch/inputs_true.dat index 7348663e8..225b23ffa 100644 --- a/tests/regression_tests/eigenvalue_genperbatch/inputs_true.dat +++ b/tests/regression_tests/eigenvalue_genperbatch/inputs_true.dat @@ -1,31 +1,30 @@ - - - - - - - - - - - - - - eigenvalue - 1000 - 7 - 3 - 3 - - - -4.0 -4.0 -4.0 4.0 4.0 4.0 - - - - - - - flux - - + + + + + + + + + + + + + eigenvalue + 1000 + 7 + 3 + 3 + + + -4.0 -4.0 -4.0 4.0 4.0 4.0 + + + + + + flux + + + diff --git a/tests/regression_tests/energy_cutoff/inputs_true.dat b/tests/regression_tests/energy_cutoff/inputs_true.dat index bb02369dc..e874a0c7a 100644 --- a/tests/regression_tests/energy_cutoff/inputs_true.dat +++ b/tests/regression_tests/energy_cutoff/inputs_true.dat @@ -1,42 +1,41 @@ - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - -1 -1 -1 1 1 1 - - - - - 4.0 - - - - - - 0.0 4.0 - - - 1 - flux - - + + + + + + + + + + + + + + + + + + fixed source + 100 + 10 + + + -1 -1 -1 1 1 1 + + + + + 4.0 + + + + + 0.0 4.0 + + + 1 + flux + + + diff --git a/tests/regression_tests/energy_cutoff/test.py b/tests/regression_tests/energy_cutoff/test.py index d76edd9a0..e05d17f5f 100755 --- a/tests/regression_tests/energy_cutoff/test.py +++ b/tests/regression_tests/energy_cutoff/test.py @@ -4,7 +4,8 @@ from tests.testing_harness import PyAPITestHarness class EnergyCutoffTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Set energy cutoff energy_cutoff = 4.0 @@ -12,8 +13,7 @@ class EnergyCutoffTestHarness(PyAPITestHarness): mat = openmc.Material(material_id=1, name='mat') mat.set_density('atom/b-cm', 0.069335) mat.add_nuclide('H1', 40.0) - materials_file = openmc.Materials([mat]) - materials_file.export_to_xml() + self._model.materials = openmc.Materials([mat]) # Cell is box with reflective boundary x1 = openmc.XPlane(surface_id=1, x0=-1) @@ -29,8 +29,7 @@ class EnergyCutoffTestHarness(PyAPITestHarness): box.fill = mat root = openmc.Universe(universe_id=0, name='root universe') root.add_cell(box) - geometry = openmc.Geometry(root) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root) # Set the running parameters settings_file = openmc.Settings() @@ -43,7 +42,7 @@ class EnergyCutoffTestHarness(PyAPITestHarness): watt_dist = openmc.stats.Watt() settings_file.source = openmc.source.Source(space=uniform_dist, energy=watt_dist) - settings_file.export_to_xml() + self._model.settings = settings_file # Tally flux under energy cutoff tallies = openmc.Tallies() @@ -52,7 +51,7 @@ class EnergyCutoffTestHarness(PyAPITestHarness): energy_filter = openmc.filter.EnergyFilter((0.0, energy_cutoff)) tally.filters = [energy_filter] tallies.append(tally) - tallies.export_to_xml() + self._model.tallies = tallies def _get_results(self): """Digest info in the statepoint and return as a string.""" @@ -70,5 +69,5 @@ class EnergyCutoffTestHarness(PyAPITestHarness): def test_energy_cutoff(): - harness = EnergyCutoffTestHarness('statepoint.10.h5') + harness = EnergyCutoffTestHarness('statepoint.10.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/energy_laws/inputs_true.dat b/tests/regression_tests/energy_laws/inputs_true.dat index 2320b21d5..c89ccc97e 100644 --- a/tests/regression_tests/energy_laws/inputs_true.dat +++ b/tests/regression_tests/energy_laws/inputs_true.dat @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + diff --git a/tests/regression_tests/external_moab/inputs_true.dat b/tests/regression_tests/external_moab/inputs_true.dat index af259eee4..2bcbad0df 100644 --- a/tests/regression_tests/external_moab/inputs_true.dat +++ b/tests/regression_tests/external_moab/inputs_true.dat @@ -1,73 +1,72 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - 0.0 0.0 0.0 - - - - 15000000.0 1.0 - - - - - - - test_mesh_tets.h5m - - - 1 - - - 1 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 100 + 10 + + + 0.0 0.0 0.0 + + + + 15000000.0 1.0 + + + + + + test_mesh_tets.h5m + + + 1 + + + 1 + flux + tracklength + + + diff --git a/tests/regression_tests/external_moab/test.py b/tests/regression_tests/external_moab/test.py index b9d307239..12e0e5425 100644 --- a/tests/regression_tests/external_moab/test.py +++ b/tests/regression_tests/external_moab/test.py @@ -162,8 +162,6 @@ def test_external_mesh(cpp_driver): water_mat.set_density("atom/b-cm", 0.07416) materials.append(water_mat) - materials.export_to_xml() - # Geometry fuel_min_x = openmc.XPlane(-5.0, name="minimum x") fuel_max_x = openmc.XPlane(5.0, name="maximum x") diff --git a/tests/regression_tests/filter_cellinstance/inputs_true.dat b/tests/regression_tests/filter_cellinstance/inputs_true.dat index f9d3ca58d..d00aae75d 100644 --- a/tests/regression_tests/filter_cellinstance/inputs_true.dat +++ b/tests/regression_tests/filter_cellinstance/inputs_true.dat @@ -1,65 +1,64 @@ - - - - - - - - - 2 2 - 4 4 - -4 -4 - + + + + + + + + + + + + + + + + + + + + 2 2 + 4 4 + -4 -4 + 2 3 3 3 3 2 3 3 3 3 2 3 3 3 3 2 - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - 0.0 0.0 0.0 - - - - - - - 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 4 10 4 11 2 0 2 1 2 2 2 3 3 0 3 1 3 2 3 3 - - - 3 3 3 2 3 1 3 0 2 3 2 2 2 1 2 0 4 11 4 10 4 9 4 8 4 7 4 6 4 5 4 4 4 3 4 2 4 1 4 0 - - - 1 - total - - - 2 - total - - + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + 0.0 0.0 0.0 + + + + + + 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 4 10 4 11 2 0 2 1 2 2 2 3 3 0 3 1 3 2 3 3 + + + 3 3 3 2 3 1 3 0 2 3 2 2 2 1 2 0 4 11 4 10 4 9 4 8 4 7 4 6 4 5 4 4 4 3 4 2 4 1 4 0 + + + 1 + total + + + 2 + total + + + diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat index db7f91ed0..706c70e34 100644 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ b/tests/regression_tests/filter_energyfun/inputs_true.dat @@ -1,106 +1,105 @@ - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 - 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 - linear-linear - - - 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 - 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 - log-log - - - 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 - 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 - linear-log - - - 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 - 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 - log-linear - - - 0.0 5000000.0 10000000.0 15000000.0 - 0.2 0.7 0.7 0.2 - linear-linear - - - 0.0 5000000.0 10000000.0 15000000.0 - 0.2 0.7 0.7 0.2 - quadratic - - - 0.0 5000000.0 10000000.0 15000000.0 - 0.2 0.7 0.7 0.2 - cubic - - - 0.0 5000000.0 10000000.0 15000000.0 - 0.2 0.7 0.7 0.2 - histogram - - - Am241 - (n,gamma) - - - 1 - Am241 - (n,gamma) - - - 3 - Am241 - (n,gamma) - - - 4 - Am241 - (n,gamma) - - - 5 - Am241 - (n,gamma) - - - 6 - Am241 - (n,gamma) - - - 7 - Am241 - (n,gamma) - - - 8 - Am241 - (n,gamma) - - - 9 - Am241 - (n,gamma) - - + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + linear-linear + + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + log-log + + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + linear-log + + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + log-linear + + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + linear-linear + + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + quadratic + + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + cubic + + + 0.0 5000000.0 10000000.0 15000000.0 + 0.2 0.7 0.7 0.2 + histogram + + + Am241 + (n,gamma) + + + 1 + Am241 + (n,gamma) + + + 3 + Am241 + (n,gamma) + + + 4 + Am241 + (n,gamma) + + + 5 + Am241 + (n,gamma) + + + 6 + Am241 + (n,gamma) + + + 7 + Am241 + (n,gamma) + + + 8 + Am241 + (n,gamma) + + + 9 + Am241 + (n,gamma) + + + diff --git a/tests/regression_tests/filter_mesh/inputs_true.dat b/tests/regression_tests/filter_mesh/inputs_true.dat index 8b08a2a3c..d0b617903 100644 --- a/tests/regression_tests/filter_mesh/inputs_true.dat +++ b/tests/regression_tests/filter_mesh/inputs_true.dat @@ -1,152 +1,151 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 5 - -7.5 - 7.5 - - - 5 5 - -7.5 -7.5 - 7.5 7.5 - - - 5 5 5 - -7.5 -7.5 -7.5 - 7.5 7.5 7.5 - - - -7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5 - -7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5 - 1.0 1.223224374241637 1.4962778697388448 1.8302835609029084 2.2388474634702153 2.7386127875258306 3.3499379133114306 4.09772570775871 5.012437964687018 6.131336292779302 7.500000000000001 - - - 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 - 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 - -7.5 -6.5625 -5.625 -4.6875 -3.75 -2.8125 -1.875 -0.9375 0.0 0.9375 1.875 2.8125 3.75 4.6875 5.625 6.5625 7.5 - 0.0 0.0 0.0 - - - 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 - 0.0 0.39269908169872414 0.7853981633974483 1.1780972450961724 1.5707963267948966 1.9634954084936207 2.356194490192345 2.748893571891069 3.141592653589793 - 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 - 0.0 0.0 0.0 - - - 1 - - - 1 - - - 2 - - - 2 - - - 3 - - - 3 - - - 4 - - - 4 - - - 5 - - - 5 - - - 6 - - - 6 - - - 1 - total - - - 7 - current - - - 2 - total - - - 8 - current - - - 3 - total - - - 9 - current - - - 4 - total - - - 10 - current - - - 5 - total - - - 11 - current - - - 6 - total - - - 12 - current - - + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + + 5 + -7.5 + 7.5 + + + 5 5 + -7.5 -7.5 + 7.5 7.5 + + + 5 5 5 + -7.5 -7.5 -7.5 + 7.5 7.5 7.5 + + + -7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5 + -7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5 + 1.0 1.223224374241637 1.4962778697388448 1.8302835609029084 2.2388474634702153 2.7386127875258306 3.3499379133114306 4.09772570775871 5.012437964687018 6.131336292779302 7.500000000000001 + + + 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 + 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 + -7.5 -6.5625 -5.625 -4.6875 -3.75 -2.8125 -1.875 -0.9375 0.0 0.9375 1.875 2.8125 3.75 4.6875 5.625 6.5625 7.5 + 0.0 0.0 0.0 + + + 0.0 0.4411764705882353 0.8823529411764706 1.3235294117647058 1.7647058823529411 2.2058823529411766 2.6470588235294117 3.0882352941176467 3.5294117647058822 3.9705882352941178 4.411764705882353 4.852941176470588 5.294117647058823 5.735294117647059 6.1764705882352935 6.617647058823529 7.0588235294117645 7.5 + 0.0 0.39269908169872414 0.7853981633974483 1.1780972450961724 1.5707963267948966 1.9634954084936207 2.356194490192345 2.748893571891069 3.141592653589793 + 0.0 0.3490658503988659 0.6981317007977318 1.0471975511965976 1.3962634015954636 1.7453292519943295 2.0943951023931953 2.443460952792061 2.792526803190927 3.141592653589793 3.490658503988659 3.839724354387525 4.1887902047863905 4.537856055185257 4.886921905584122 5.235987755982989 5.585053606381854 5.93411945678072 6.283185307179586 + 0.0 0.0 0.0 + + + 1 + + + 1 + + + 2 + + + 2 + + + 3 + + + 3 + + + 4 + + + 4 + + + 5 + + + 5 + + + 6 + + + 6 + + + 1 + total + + + 7 + current + + + 2 + total + + + 8 + current + + + 3 + total + + + 9 + current + + + 4 + total + + + 10 + current + + + 5 + total + + + 11 + current + + + 6 + total + + + 12 + current + + + diff --git a/tests/regression_tests/filter_translations/inputs_true.dat b/tests/regression_tests/filter_translations/inputs_true.dat index d38bec39f..8ed705413 100644 --- a/tests/regression_tests/filter_translations/inputs_true.dat +++ b/tests/regression_tests/filter_translations/inputs_true.dat @@ -1,84 +1,83 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 3 4 5 - -9 -9 -9 - 9 9 9 - - - -9.0 0.0 9.0 - -9.0 -3.0 3.0 9.0 - -9.0 -4.5 0.0 4.5 9.0 - - - 3 4 5 - -19 -4 -9 - -1 14 9 - - - -19.0 -10.0 -1.0 - -4.0 2.0 8.0 14.0 - -9.0 -4.5 0.0 4.5 9.0 - - - 1 - - - 2 - - - 3 - - - 4 - - - 1 - total - - - 2 - total - - - 3 - total - - - 4 - total - - + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + + 3 4 5 + -9 -9 -9 + 9 9 9 + + + -9.0 0.0 9.0 + -9.0 -3.0 3.0 9.0 + -9.0 -4.5 0.0 4.5 9.0 + + + 3 4 5 + -19 -4 -9 + -1 14 9 + + + -19.0 -10.0 -1.0 + -4.0 2.0 8.0 14.0 + -9.0 -4.5 0.0 4.5 9.0 + + + 1 + + + 2 + + + 3 + + + 4 + + + 1 + total + + + 2 + total + + + 3 + total + + + 4 + total + + + diff --git a/tests/regression_tests/fixed_source/inputs_true.dat b/tests/regression_tests/fixed_source/inputs_true.dat index f1aebb3b2..57dcdb724 100644 --- a/tests/regression_tests/fixed_source/inputs_true.dat +++ b/tests/regression_tests/fixed_source/inputs_true.dat @@ -1,31 +1,30 @@ - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - 0.0 0.0 0.0 - - - 294 - - - - - flux - - + + + + + + + + + + + + + + fixed source + 100 + 10 + + + 0.0 0.0 0.0 + + + 294 + + + + flux + + + diff --git a/tests/regression_tests/iso_in_lab/inputs_true.dat b/tests/regression_tests/iso_in_lab/inputs_true.dat index 2a302ada6..6dd8578ff 100644 --- a/tests/regression_tests/iso_in_lab/inputs_true.dat +++ b/tests/regression_tests/iso_in_lab/inputs_true.dat @@ -1,38 +1,199 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + + + + + + + + U234 U235 U238 Xe135 O16 + + + + + + + + + Zr90 Zr91 Zr92 Zr94 Zr96 + + + + + + + + + H1 O16 B10 B11 + + + + + + + + + H1 O16 B10 B11 + + + + + + + + + + + + + + Fe54 Fe56 Fe57 Fe58 Ni58 Ni60 Mn55 Cr52 C0 Cu63 + + + + + + + + + + + + + + + + H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 + + + + + + + + + + + + + + + + H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 + + + + + + + + + + + + + + + + H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 + + + + + + + + + + + + + + + + H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 + + + + + + + + + + + + + + + + H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 + + + + + + + + + + + + + + H1 O16 B10 B11 Zr90 Zr91 Zr92 Zr94 Zr96 + + + + + + + + + + + + + + H1 O16 B10 B11 Zr90 Zr91 Zr92 Zr94 Zr96 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 @@ -50,12 +211,12 @@ 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 @@ -73,12 +234,12 @@ 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 @@ -100,12 +261,12 @@ 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 @@ -127,195 +288,34 @@ 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - U234 U235 U238 Xe135 O16 - - - - - - - - - Zr90 Zr91 Zr92 Zr94 Zr96 - - - - - - - - - H1 O16 B10 B11 - - - - - - - - - H1 O16 B10 B11 - - - - - - - - - - - - - - Fe54 Fe56 Fe57 Fe58 Ni58 Ni60 Mn55 Cr52 C0 Cu63 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - H1 O16 B10 B11 Zr90 Zr91 Zr92 Zr94 Zr96 - - - - - - - - - - - - - - H1 O16 B10 B11 Zr90 Zr91 Zr92 Zr94 Zr96 - - - - - eigenvalue - 100 - 10 - 5 - - - -160 -160 -183 160 160 183 - - - + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -160 -160 -183 160 160 183 + + + + diff --git a/tests/regression_tests/lattice_hex_coincident/inputs_true.dat b/tests/regression_tests/lattice_hex_coincident/inputs_true.dat index 0388a4f55..639235726 100644 --- a/tests/regression_tests/lattice_hex_coincident/inputs_true.dat +++ b/tests/regression_tests/lattice_hex_coincident/inputs_true.dat @@ -1,81 +1,81 @@ - - - - - - - - - - - 1.4 - 11 -
0.0 0.0
- - 10 -10 10 - 9 -10 10 - 10 -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 2 - - - -0.9899494936611666 -0.9899494936611666 0.0 0.9899494936611666 0.9899494936611666 10.0 - - - - false - - 22 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.4 + 3 +
0.0 0.0
+ + 2 +2 2 + 1 +2 2 + 2 +
+ + + + + + + + + + + + +
+ + eigenvalue + 1000 + 5 + 2 + + + -0.9899494936611666 -0.9899494936611666 0.0 0.9899494936611666 0.9899494936611666 10.0 + + + + false + + 22 + +
diff --git a/tests/regression_tests/lattice_hex_coincident/test.py b/tests/regression_tests/lattice_hex_coincident/test.py index 30bc470f2..fae7f939b 100644 --- a/tests/regression_tests/lattice_hex_coincident/test.py +++ b/tests/regression_tests/lattice_hex_coincident/test.py @@ -6,7 +6,8 @@ from tests.testing_harness import PyAPITestHarness class HexLatticeCoincidentTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) materials = openmc.Materials() fuel_mat = openmc.Material() @@ -40,7 +41,7 @@ class HexLatticeCoincidentTestHarness(PyAPITestHarness): zirc.add_nuclide('Zr96', 1.131E-03, 'ao') materials.append(zirc) - materials.export_to_xml() + self._model.materials = materials ### Geometry ### pin_rad = 0.7 # cm @@ -124,8 +125,7 @@ class HexLatticeCoincidentTestHarness(PyAPITestHarness): root_univ = openmc.Universe(name="root universe", cells=[pincell_only_cell,]) - geom = openmc.Geometry(root_univ) - geom.export_to_xml() + self._model.geometry = openmc.Geometry(root_univ) ### Settings ### @@ -144,8 +144,9 @@ class HexLatticeCoincidentTestHarness(PyAPITestHarness): settings.inactive = 2 settings.particles = 1000 settings.seed = 22 - settings.export_to_xml() + self._model.settings = settings def test_lattice_hex_coincident_surf(): - harness = HexLatticeCoincidentTestHarness('statepoint.5.h5') + harness = HexLatticeCoincidentTestHarness('statepoint.5.h5', + model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/lattice_hex_x/inputs_true.dat b/tests/regression_tests/lattice_hex_x/inputs_true.dat index b528a97b7..2cff10f75 100644 --- a/tests/regression_tests/lattice_hex_x/inputs_true.dat +++ b/tests/regression_tests/lattice_hex_x/inputs_true.dat @@ -1,23 +1,53 @@ - - - - - - - - - - - - - - - - 1.235 5.0 - 4 -
0.0 0.0 5.0
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.235 5.0 + 4 +
0.0 0.0 5.0
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 @@ -60,64 +90,34 @@ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - -13.62546635287517 -13.62546635287517 0.0 13.62546635287517 13.62546635287517 10.0 - - - 22 - +
+ + + + + + + + + + + + + + + + +
+ + eigenvalue + 1000 + 10 + 5 + + + -13.62546635287517 -13.62546635287517 0.0 13.62546635287517 13.62546635287517 10.0 + + + 22 + + diff --git a/tests/regression_tests/lattice_hex_x/test.py b/tests/regression_tests/lattice_hex_x/test.py index ecb27c9c2..e582c68ae 100644 --- a/tests/regression_tests/lattice_hex_x/test.py +++ b/tests/regression_tests/lattice_hex_x/test.py @@ -4,8 +4,8 @@ import numpy as np class HexLatticeOXTestHarness(PyAPITestHarness): - - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) materials = openmc.Materials() fuel_mat = openmc.Material(material_id=1, name="UO2") @@ -35,7 +35,7 @@ class HexLatticeOXTestHarness(PyAPITestHarness): zirc.add_element('Zr', 4.23e-2) materials.append(zirc) - materials.export_to_xml() + self._model.materials = materials # Geometry # @@ -165,7 +165,7 @@ class HexLatticeOXTestHarness(PyAPITestHarness): (4, 21), (5, 20), (4, 27), (5, 25), (4, 33)] for i, j in channels: universes[i][j] = abs_ch_univ - lattice = openmc.HexLattice(name="regular fuel assembly") + lattice = openmc.HexLattice(lattice_id=6, name="regular fuel assembly") lattice.orientation = "x" lattice.center = (0., 0., length/2.0) lattice.pitch = (assembly_pitch, length/2.0) @@ -180,8 +180,7 @@ class HexLatticeOXTestHarness(PyAPITestHarness): root_univ = openmc.Universe(universe_id=5, name="root universe", cells=[assembly_cell]) - geom = openmc.Geometry(root_univ) - geom.export_to_xml() + self._model.geometry = openmc.Geometry(root_univ) # Settings # @@ -198,9 +197,9 @@ class HexLatticeOXTestHarness(PyAPITestHarness): settings.inactive = 5 settings.particles = 1000 settings.seed = 22 - settings.export_to_xml() + self._model.settings = settings def test_lattice_hex_ox_surf(): - harness = HexLatticeOXTestHarness('statepoint.10.h5') + harness = HexLatticeOXTestHarness('statepoint.10.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/lattice_multiple/inputs_true.dat b/tests/regression_tests/lattice_multiple/inputs_true.dat index c92e841bc..0eed3c201 100644 --- a/tests/regression_tests/lattice_multiple/inputs_true.dat +++ b/tests/regression_tests/lattice_multiple/inputs_true.dat @@ -1,53 +1,53 @@ - - - - - - - - - 1.2 1.2 - 1 - 2 2 - -1.2 -1.2 - + + + + + + + + + + + + + + + + + + + + + + + 1.2 1.2 + 1 + 2 2 + -1.2 -1.2 + 2 1 1 1 - - - 2.4 2.4 - 2 2 - -2.4 -2.4 - + + + 2.4 2.4 + 2 2 + -2.4 -2.4 + 4 4 4 4 - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + diff --git a/tests/regression_tests/lattice_rotated/inputs_true.dat b/tests/regression_tests/lattice_rotated/inputs_true.dat index 8ee34b4f3..8e54bdf88 100644 --- a/tests/regression_tests/lattice_rotated/inputs_true.dat +++ b/tests/regression_tests/lattice_rotated/inputs_true.dat @@ -1,18 +1,35 @@ - - - - - - - - - - - 1.25 - 30 -
0.0 0.0
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.25 + 30 +
0.0 0.0
+ 2 1 1 1 2 1 @@ -22,50 +39,33 @@ 1 1 1 1 1 1 -
- - 1.25 1.25 - 30 - 4 4 - -2.5 -2.5 - +
+ + 1.25 1.25 + 30 + 4 4 + -2.5 -2.5 + 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - -
- - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - 0.0 0.0 0.0 - - - + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + 0.0 0.0 0.0 + + + + diff --git a/tests/regression_tests/mg_basic/inputs_true.dat b/tests/regression_tests/mg_basic/inputs_true.dat index 4f2fd3f0b..06406b5f2 100644 --- a/tests/regression_tests/mg_basic/inputs_true.dat +++ b/tests/regression_tests/mg_basic/inputs_true.dat @@ -1,64 +1,64 @@ - - - - - - - - - - - - - - - - - - 2g.h5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 154.90833333333333 1000.0 1000.0 - - - - false - - multi-group - - false - - + + + 2g.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + 0.0 -1000.0 -1000.0 154.90833333333333 1000.0 1000.0 + + + + false + + multi-group + + false + + + diff --git a/tests/regression_tests/mg_basic_delayed/inputs_true.dat b/tests/regression_tests/mg_basic_delayed/inputs_true.dat index 9fb7afe7e..05108d87d 100644 --- a/tests/regression_tests/mg_basic_delayed/inputs_true.dat +++ b/tests/regression_tests/mg_basic_delayed/inputs_true.dat @@ -1,63 +1,63 @@ - - - - - - - - - - - - - - - - - - 2g.h5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 154.90833333333333 1000.0 1000.0 - - - - false - - multi-group - - false - - + + + 2g.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + 0.0 -1000.0 -1000.0 154.90833333333333 1000.0 1000.0 + + + + false + + multi-group + + false + + + diff --git a/tests/regression_tests/mg_convert/inputs_true.dat b/tests/regression_tests/mg_convert/inputs_true.dat index 753c0d304..9276a7a7b 100644 --- a/tests/regression_tests/mg_convert/inputs_true.dat +++ b/tests/regression_tests/mg_convert/inputs_true.dat @@ -1,29 +1,29 @@ - - - - - - - - - - mgxs.h5 - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -5 -5 -5 5 5 5 - - - multi-group - + + + mgxs.h5 + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -5 -5 -5 5 5 5 + + + multi-group + + diff --git a/tests/regression_tests/mg_convert/test.py b/tests/regression_tests/mg_convert/test.py index c6ab485ea..d9c4a57bd 100755 --- a/tests/regression_tests/mg_convert/test.py +++ b/tests/regression_tests/mg_convert/test.py @@ -61,7 +61,8 @@ def build_mgxs_library(convert): class MGXSTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Instantiate some Macroscopic Data uo2_data = openmc.Macroscopic('UO2') @@ -73,7 +74,7 @@ class MGXSTestHarness(PyAPITestHarness): # Instantiate a Materials collection and export to XML materials_file = openmc.Materials([mat]) materials_file.cross_sections = "./mgxs.h5" - materials_file.export_to_xml() + self._model.materials = materials_file # Instantiate ZCylinder surfaces left = openmc.XPlane(surface_id=4, x0=-5., name='left') @@ -102,8 +103,7 @@ class MGXSTestHarness(PyAPITestHarness): root.add_cells([fuel]) # Instantiate a Geometry, register the root Universe, and export to XML - geometry = openmc.Geometry(root) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root) settings_file = openmc.Settings() settings_file.energy_mode = "multi-group" @@ -116,7 +116,7 @@ class MGXSTestHarness(PyAPITestHarness): uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:]) settings_file.source = openmc.source.Source(space=uniform_dist) - settings_file.export_to_xml() + self._model.settings = settings_file def _run_openmc(self): # Run multiple conversions to compare results @@ -194,5 +194,5 @@ class MGXSTestHarness(PyAPITestHarness): def test_mg_convert(): - harness = MGXSTestHarness('statepoint.10.h5') + harness = MGXSTestHarness('statepoint.10.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/mg_legendre/inputs_true.dat b/tests/regression_tests/mg_legendre/inputs_true.dat index ad3b434e6..d90dfb802 100644 --- a/tests/regression_tests/mg_legendre/inputs_true.dat +++ b/tests/regression_tests/mg_legendre/inputs_true.dat @@ -1,33 +1,33 @@ - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - - false - - + + + 2g.h5 + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 + + + + false + + multi-group + + false + + + diff --git a/tests/regression_tests/mg_max_order/inputs_true.dat b/tests/regression_tests/mg_max_order/inputs_true.dat index 2ac83852c..9bfcd54df 100644 --- a/tests/regression_tests/mg_max_order/inputs_true.dat +++ b/tests/regression_tests/mg_max_order/inputs_true.dat @@ -1,34 +1,34 @@ - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - 1 - - false - - + + + 2g.h5 + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 + + + + false + + multi-group + 1 + + false + + + diff --git a/tests/regression_tests/mg_survival_biasing/inputs_true.dat b/tests/regression_tests/mg_survival_biasing/inputs_true.dat index 5ece3ce9f..a3a2a726f 100644 --- a/tests/regression_tests/mg_survival_biasing/inputs_true.dat +++ b/tests/regression_tests/mg_survival_biasing/inputs_true.dat @@ -1,34 +1,34 @@ - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - true - - false - - + + + 2g.h5 + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 + + + + false + + multi-group + true + + false + + + diff --git a/tests/regression_tests/mg_tallies/inputs_true.dat b/tests/regression_tests/mg_tallies/inputs_true.dat index 562958722..bdd41c7f8 100644 --- a/tests/regression_tests/mg_tallies/inputs_true.dat +++ b/tests/regression_tests/mg_tallies/inputs_true.dat @@ -1,165 +1,164 @@ - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - - false - - - - - - 10 1 1 - 0.0 0.0 0.0 - 929.45 1000 1000 - - - 1 - - - 1 - - - 0.0 20000000.0 - - - 0.0 20000000.0 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 5 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - analog - - - 5 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - tracklength - - - 6 1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux scatter nu-scatter - analog - - - 6 1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - collision - - - 6 1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - tracklength - - - 6 1 2 - scatter nu-scatter nu-fission - - - 6 3 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux scatter nu-scatter - analog - - - 6 3 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - collision - - - 6 3 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - tracklength - - - 6 3 4 - scatter nu-scatter nu-fission - - - 5 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - analog - - - 5 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - tracklength - - - 6 1 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate scatter nu-scatter - analog - - - 6 1 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - collision - - - 6 1 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - tracklength - - - 6 1 2 - mat_1 - scatter nu-scatter nu-fission - - - 6 3 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate scatter nu-scatter - analog - - - 6 3 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - collision - - - 6 3 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - tracklength - - - 6 3 4 - mat_1 - scatter nu-scatter nu-fission - - + + + 2g.h5 + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 + + + + false + + multi-group + + false + + + + + 10 1 1 + 0.0 0.0 0.0 + 929.45 1000 1000 + + + 1 + + + 1 + + + 0.0 20000000.0 + + + 0.0 20000000.0 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 5 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux + analog + + + 5 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux + tracklength + + + 6 1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux scatter nu-scatter + analog + + + 6 1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux + collision + + + 6 1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux + tracklength + + + 6 1 2 + scatter nu-scatter nu-fission + + + 6 3 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux scatter nu-scatter + analog + + + 6 3 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux + collision + + + 6 3 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux + tracklength + + + 6 3 4 + scatter nu-scatter nu-fission + + + 5 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate + analog + + + 5 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate + tracklength + + + 6 1 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate scatter nu-scatter + analog + + + 6 1 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate + collision + + + 6 1 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate + tracklength + + + 6 1 2 + mat_1 + scatter nu-scatter nu-fission + + + 6 3 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate scatter nu-scatter + analog + + + 6 3 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate + collision + + + 6 3 + mat_1 + total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate + tracklength + + + 6 3 4 + mat_1 + scatter nu-scatter nu-fission + + + diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat b/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat index bc5c4b2d4..533160577 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat @@ -1,251 +1,250 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 3 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - analog - - - 1 2 7 - total - nu-fission - analog - - - 1 2 - total - flux - analog - - - 1 2 7 11 - total - nu-scatter - analog - - - 1 2 7 - total - nu-scatter - analog - - - 1 2 7 - total - scatter - analog - - - 15 2 - total - flux - tracklength - - - 15 2 - total - total - tracklength - - - 15 2 - total - flux - tracklength - - - 15 2 - total - absorption - tracklength - - - 15 2 - total - flux - analog - - - 15 2 7 - total - nu-fission - analog - - - 15 2 - total - flux - analog - - - 15 2 7 11 - total - nu-scatter - analog - - - 15 2 7 - total - nu-scatter - analog - - - 15 2 7 - total - scatter - analog - - - 29 2 - total - flux - tracklength - - - 29 2 - total - total - tracklength - - - 29 2 - total - flux - tracklength - - - 29 2 - total - absorption - tracklength - - - 29 2 - total - flux - analog - - - 29 2 7 - total - nu-fission - analog - - - 29 2 - total - flux - analog - - - 29 2 7 11 - total - nu-scatter - analog - - - 29 2 7 - total - nu-scatter - analog - - - 29 2 7 - total - scatter - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 3 + + + 2 + + + 3 + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + flux + analog + + + 1 2 7 + total + nu-fission + analog + + + 1 2 + total + flux + analog + + + 1 2 7 11 + total + nu-scatter + analog + + + 1 2 7 + total + nu-scatter + analog + + + 1 2 7 + total + scatter + analog + + + 15 2 + total + flux + tracklength + + + 15 2 + total + total + tracklength + + + 15 2 + total + flux + tracklength + + + 15 2 + total + absorption + tracklength + + + 15 2 + total + flux + analog + + + 15 2 7 + total + nu-fission + analog + + + 15 2 + total + flux + analog + + + 15 2 7 11 + total + nu-scatter + analog + + + 15 2 7 + total + nu-scatter + analog + + + 15 2 7 + total + scatter + analog + + + 29 2 + total + flux + tracklength + + + 29 2 + total + total + tracklength + + + 29 2 + total + flux + tracklength + + + 29 2 + total + absorption + tracklength + + + 29 2 + total + flux + analog + + + 29 2 7 + total + nu-fission + analog + + + 29 2 + total + flux + analog + + + 29 2 7 11 + total + nu-scatter + analog + + + 29 2 7 + total + nu-scatter + analog + + + 29 2 7 + total + scatter + analog + + + diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/test.py b/tests/regression_tests/mgxs_library_ce_to_mg/test.py index 72f052e68..4dff67323 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg/test.py +++ b/tests/regression_tests/mgxs_library_ce_to_mg/test.py @@ -48,15 +48,12 @@ class MGXSTestHarness(PyAPITestHarness): # Modify materials and settings so we can run in MG mode self._model.materials.cross_sections = './mgxs.h5' self._model.settings.energy_mode = 'multi-group' + # Dont need tallies so clear them from the model + self._model.tallies = openmc.Tallies() # Write modified input files - self._model.settings.export_to_xml() - self._model.geometry.export_to_xml() - self._model.materials.export_to_xml() + self._model.export_to_model_xml() self._model.mgxs_file.export_to_hdf5() - # Dont need tallies.xml, so remove the file - if os.path.exists('tallies.xml'): - os.remove('tallies.xml') # Enforce closing statepoint and summary files so HDF5 # does not throw an error during the next OpenMC execution diff --git a/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/inputs_true.dat index 576f27966..fe154a018 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/inputs_true.dat @@ -1,251 +1,250 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 3 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - absorption - tracklength - - - 1 2 - total - flux - analog - - - 1 2 7 - U234 U235 U238 O16 - nu-fission - analog - - - 1 2 - total - flux - analog - - - 1 2 7 11 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 7 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 7 - U234 U235 U238 O16 - scatter - analog - - - 15 2 - total - flux - tracklength - - - 15 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 15 2 - total - flux - tracklength - - - 15 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 15 2 - total - flux - analog - - - 15 2 7 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 15 2 - total - flux - analog - - - 15 2 7 11 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 15 2 7 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 15 2 7 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 29 2 - total - flux - tracklength - - - 29 2 - H1 O16 B10 B11 - total - tracklength - - - 29 2 - total - flux - tracklength - - - 29 2 - H1 O16 B10 B11 - absorption - tracklength - - - 29 2 - total - flux - analog - - - 29 2 7 - H1 O16 B10 B11 - nu-fission - analog - - - 29 2 - total - flux - analog - - - 29 2 7 11 - H1 O16 B10 B11 - nu-scatter - analog - - - 29 2 7 - H1 O16 B10 B11 - nu-scatter - analog - - - 29 2 7 - H1 O16 B10 B11 - scatter - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 3 + + + 2 + + + 3 + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + absorption + tracklength + + + 1 2 + total + flux + analog + + + 1 2 7 + U234 U235 U238 O16 + nu-fission + analog + + + 1 2 + total + flux + analog + + + 1 2 7 11 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 2 7 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 2 7 + U234 U235 U238 O16 + scatter + analog + + + 15 2 + total + flux + tracklength + + + 15 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 15 2 + total + flux + tracklength + + + 15 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + absorption + tracklength + + + 15 2 + total + flux + analog + + + 15 2 7 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog + + + 15 2 + total + flux + analog + + + 15 2 7 11 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 15 2 7 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 15 2 7 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 29 2 + total + flux + tracklength + + + 29 2 + H1 O16 B10 B11 + total + tracklength + + + 29 2 + total + flux + tracklength + + + 29 2 + H1 O16 B10 B11 + absorption + tracklength + + + 29 2 + total + flux + analog + + + 29 2 7 + H1 O16 B10 B11 + nu-fission + analog + + + 29 2 + total + flux + analog + + + 29 2 7 11 + H1 O16 B10 B11 + nu-scatter + analog + + + 29 2 7 + H1 O16 B10 B11 + nu-scatter + analog + + + 29 2 7 + H1 O16 B10 B11 + scatter + analog + + + diff --git a/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py b/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py index b624140d4..ee0cdf0d9 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py @@ -48,15 +48,12 @@ class MGXSTestHarness(PyAPITestHarness): # Modify materials and settings so we can run in MG mode self._model.materials.cross_sections = './mgxs.h5' self._model.settings.energy_mode = 'multi-group' + # Dont need tallies so clear them from the model + self._model.tallies = openmc.Tallies() # Write modified input files - self._model.settings.export_to_xml() - self._model.geometry.export_to_xml() - self._model.materials.export_to_xml() + self._model.export_to_model_xml() self._model.mgxs_file.export_to_hdf5() - # Dont need tallies.xml, so remove the file - if os.path.exists('tallies.xml'): - os.remove('tallies.xml') # Enforce closing statepoint and summary files so HDF5 # does not throw an error during the next OpenMC execution diff --git a/tests/regression_tests/mgxs_library_condense/inputs_true.dat b/tests/regression_tests/mgxs_library_condense/inputs_true.dat index cac18ffcd..c8f140f80 100644 --- a/tests/regression_tests/mgxs_library_condense/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_condense/inputs_true.dat @@ -1,532 +1,531 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 2 2 - -100.0 -100.0 - 100.0 100.0 - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 1 - - - 1 2 3 4 5 6 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - (n,2n) - tracklength - - - 1 2 - total - (n,3n) - tracklength - - - 1 2 - total - (n,4n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 54 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 54 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 68 2 - total - current - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 79 2 - total - delayed-nu-fission - tracklength - - - 1 79 54 - total - delayed-nu-fission - analog - - - 1 79 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 79 2 - total - delayed-nu-fission - tracklength - - - 1 79 - total - delayed-nu-fission - tracklength - - - 1 79 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 79 2 5 - total - delayed-nu-fission - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 2 2 + -100.0 -100.0 + 100.0 100.0 + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 1 + + + 3 + + + 0.0 20000000.0 + + + 1 + + + 1 2 3 4 5 6 + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + (n,2n) + tracklength + + + 1 2 + total + (n,3n) + tracklength + + + 1 2 + total + (n,4n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + kappa-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 + total + flux + analog + + + 1 2 + total + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + nu-scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + nu-fission + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 54 + total + nu-fission + analog + + + 1 5 + total + nu-fission + analog + + + 1 54 + total + prompt-nu-fission + analog + + + 1 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + inverse-velocity + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + prompt-nu-fission + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + total + prompt-nu-fission + analog + + + 68 2 + total + current + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 54 + total + delayed-nu-fission + analog + + + 1 79 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 + total + delayed-nu-fission + tracklength + + + 1 79 + total + decay-rate + tracklength + + + 1 2 + total + flux + analog + + + 1 79 2 5 + total + delayed-nu-fission + analog + + + diff --git a/tests/regression_tests/mgxs_library_correction/inputs_true.dat b/tests/regression_tests/mgxs_library_correction/inputs_true.dat index 8c1cd4d16..a1cc111de 100644 --- a/tests/regression_tests/mgxs_library_correction/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_correction/inputs_true.dat @@ -1,344 +1,343 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 0 - - - 2 - - - 3 - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 12 - total - scatter - analog - - - 1 3 4 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 12 - total - scatter - analog - - - 1 2 3 - total - nu-scatter - analog - - - 1 3 4 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 19 2 - total - flux - analog - - - 19 2 3 4 - total - scatter - analog - - - 19 2 - total - flux - analog - - - 19 2 3 4 - total - nu-scatter - analog - - - 19 2 - total - flux - tracklength - - - 19 2 - total - scatter - tracklength - - - 19 2 3 12 - total - scatter - analog - - - 19 3 4 - total - scatter - analog - - - 19 2 - total - flux - analog - - - 19 2 - total - flux - tracklength - - - 19 2 - total - scatter - tracklength - - - 19 2 3 12 - total - scatter - analog - - - 19 2 3 - total - nu-scatter - analog - - - 19 3 4 - total - nu-scatter - analog - - - 19 2 - total - flux - analog - - - 37 2 - total - flux - analog - - - 37 2 3 4 - total - scatter - analog - - - 37 2 - total - flux - analog - - - 37 2 3 4 - total - nu-scatter - analog - - - 37 2 - total - flux - tracklength - - - 37 2 - total - scatter - tracklength - - - 37 2 3 12 - total - scatter - analog - - - 37 3 4 - total - scatter - analog - - - 37 2 - total - flux - analog - - - 37 2 - total - flux - tracklength - - - 37 2 - total - scatter - tracklength - - - 37 2 3 12 - total - scatter - analog - - - 37 2 3 - total - nu-scatter - analog - - - 37 3 4 - total - nu-scatter - analog - - - 37 2 - total - flux - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 1 + + + 0 + + + 2 + + + 3 + + + 1 2 + total + flux + analog + + + 1 2 3 4 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 3 4 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 12 + total + scatter + analog + + + 1 3 4 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 12 + total + scatter + analog + + + 1 2 3 + total + nu-scatter + analog + + + 1 3 4 + total + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 19 2 + total + flux + analog + + + 19 2 3 4 + total + scatter + analog + + + 19 2 + total + flux + analog + + + 19 2 3 4 + total + nu-scatter + analog + + + 19 2 + total + flux + tracklength + + + 19 2 + total + scatter + tracklength + + + 19 2 3 12 + total + scatter + analog + + + 19 3 4 + total + scatter + analog + + + 19 2 + total + flux + analog + + + 19 2 + total + flux + tracklength + + + 19 2 + total + scatter + tracklength + + + 19 2 3 12 + total + scatter + analog + + + 19 2 3 + total + nu-scatter + analog + + + 19 3 4 + total + nu-scatter + analog + + + 19 2 + total + flux + analog + + + 37 2 + total + flux + analog + + + 37 2 3 4 + total + scatter + analog + + + 37 2 + total + flux + analog + + + 37 2 3 4 + total + nu-scatter + analog + + + 37 2 + total + flux + tracklength + + + 37 2 + total + scatter + tracklength + + + 37 2 3 12 + total + scatter + analog + + + 37 3 4 + total + scatter + analog + + + 37 2 + total + flux + analog + + + 37 2 + total + flux + tracklength + + + 37 2 + total + scatter + tracklength + + + 37 2 3 12 + total + scatter + analog + + + 37 2 3 + total + nu-scatter + analog + + + 37 3 4 + total + nu-scatter + analog + + + 37 2 + total + flux + analog + + + diff --git a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat index bd6abbb7c..895389fb9 100644 --- a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat @@ -1,17 +1,43 @@ - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 @@ -29,514 +55,487 @@ 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -10.71 -10.71 -1 10.71 10.71 1 - - - - - - - 1 - - - 0.0 20000000.0 - - - 0.0 20000000.0 - - - 1 - - - 3 - - - 1 2 3 4 5 6 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - (n,2n) - tracklength - - - 1 2 - total - (n,3n) - tracklength - - - 1 2 - total - (n,4n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 2 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 75 2 - total - delayed-nu-fission - tracklength - - - 1 75 2 - total - delayed-nu-fission - analog - - - 1 75 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 75 2 - total - delayed-nu-fission - tracklength - - - 1 75 - total - delayed-nu-fission - tracklength - - - 1 75 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 75 2 5 - total - delayed-nu-fission - analog - - + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -10.71 -10.71 -1 10.71 10.71 1 + + + + + + 1 + + + 0.0 20000000.0 + + + 0.0 20000000.0 + + + 1 + + + 3 + + + 1 2 3 4 5 6 + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + (n,2n) + tracklength + + + 1 2 + total + (n,3n) + tracklength + + + 1 2 + total + (n,4n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + kappa-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 + total + flux + analog + + + 1 2 + total + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + nu-scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + nu-fission + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 2 + total + nu-fission + analog + + + 1 5 + total + nu-fission + analog + + + 1 2 + total + prompt-nu-fission + analog + + + 1 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + inverse-velocity + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + prompt-nu-fission + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 75 2 + total + delayed-nu-fission + tracklength + + + 1 75 2 + total + delayed-nu-fission + analog + + + 1 75 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 75 2 + total + delayed-nu-fission + tracklength + + + 1 75 + total + delayed-nu-fission + tracklength + + + 1 75 + total + decay-rate + tracklength + + + 1 2 + total + flux + analog + + + 1 75 2 5 + total + delayed-nu-fission + analog + + + diff --git a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat index cac18ffcd..c8f140f80 100644 --- a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat @@ -1,532 +1,531 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 2 2 - -100.0 -100.0 - 100.0 100.0 - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 1 - - - 1 2 3 4 5 6 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - (n,2n) - tracklength - - - 1 2 - total - (n,3n) - tracklength - - - 1 2 - total - (n,4n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 54 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 54 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 68 2 - total - current - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 79 2 - total - delayed-nu-fission - tracklength - - - 1 79 54 - total - delayed-nu-fission - analog - - - 1 79 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 79 2 - total - delayed-nu-fission - tracklength - - - 1 79 - total - delayed-nu-fission - tracklength - - - 1 79 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 79 2 5 - total - delayed-nu-fission - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 2 2 + -100.0 -100.0 + 100.0 100.0 + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 1 + + + 3 + + + 0.0 20000000.0 + + + 1 + + + 1 2 3 4 5 6 + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + (n,2n) + tracklength + + + 1 2 + total + (n,3n) + tracklength + + + 1 2 + total + (n,4n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + kappa-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 + total + flux + analog + + + 1 2 + total + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + nu-scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + nu-fission + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 54 + total + nu-fission + analog + + + 1 5 + total + nu-fission + analog + + + 1 54 + total + prompt-nu-fission + analog + + + 1 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + inverse-velocity + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + prompt-nu-fission + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + total + prompt-nu-fission + analog + + + 68 2 + total + current + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 54 + total + delayed-nu-fission + analog + + + 1 79 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 + total + delayed-nu-fission + tracklength + + + 1 79 + total + decay-rate + tracklength + + + 1 2 + total + flux + analog + + + 1 79 2 5 + total + delayed-nu-fission + analog + + + diff --git a/tests/regression_tests/mgxs_library_histogram/inputs_true.dat b/tests/regression_tests/mgxs_library_histogram/inputs_true.dat index d1bd197a7..0ea55bb04 100644 --- a/tests/regression_tests/mgxs_library_histogram/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_histogram/inputs_true.dat @@ -1,269 +1,268 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - -1.0 -0.8181818181818181 -0.6363636363636364 -0.4545454545454546 -0.2727272727272727 -0.09090909090909083 0.09090909090909083 0.2727272727272727 0.4545454545454546 0.6363636363636365 0.8181818181818183 1.0 - - - 2 - - - 3 - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 4 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 4 - total - scatter - analog - - - 1 2 3 - total - nu-scatter - analog - - - 17 2 - total - flux - analog - - - 17 2 3 4 - total - scatter - analog - - - 17 2 - total - flux - analog - - - 17 2 3 4 - total - nu-scatter - analog - - - 17 2 - total - flux - tracklength - - - 17 2 - total - scatter - tracklength - - - 17 2 3 4 - total - scatter - analog - - - 17 2 - total - flux - tracklength - - - 17 2 - total - scatter - tracklength - - - 17 2 3 4 - total - scatter - analog - - - 17 2 3 - total - nu-scatter - analog - - - 33 2 - total - flux - analog - - - 33 2 3 4 - total - scatter - analog - - - 33 2 - total - flux - analog - - - 33 2 3 4 - total - nu-scatter - analog - - - 33 2 - total - flux - tracklength - - - 33 2 - total - scatter - tracklength - - - 33 2 3 4 - total - scatter - analog - - - 33 2 - total - flux - tracklength - - - 33 2 - total - scatter - tracklength - - - 33 2 3 4 - total - scatter - analog - - - 33 2 3 - total - nu-scatter - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + -1.0 -0.8181818181818181 -0.6363636363636364 -0.4545454545454546 -0.2727272727272727 -0.09090909090909083 0.09090909090909083 0.2727272727272727 0.4545454545454546 0.6363636363636365 0.8181818181818183 1.0 + + + 2 + + + 3 + + + 1 2 + total + flux + analog + + + 1 2 3 4 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 3 4 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 4 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 4 + total + scatter + analog + + + 1 2 3 + total + nu-scatter + analog + + + 17 2 + total + flux + analog + + + 17 2 3 4 + total + scatter + analog + + + 17 2 + total + flux + analog + + + 17 2 3 4 + total + nu-scatter + analog + + + 17 2 + total + flux + tracklength + + + 17 2 + total + scatter + tracklength + + + 17 2 3 4 + total + scatter + analog + + + 17 2 + total + flux + tracklength + + + 17 2 + total + scatter + tracklength + + + 17 2 3 4 + total + scatter + analog + + + 17 2 3 + total + nu-scatter + analog + + + 33 2 + total + flux + analog + + + 33 2 3 4 + total + scatter + analog + + + 33 2 + total + flux + analog + + + 33 2 3 4 + total + nu-scatter + analog + + + 33 2 + total + flux + tracklength + + + 33 2 + total + scatter + tracklength + + + 33 2 3 4 + total + scatter + analog + + + 33 2 + total + flux + tracklength + + + 33 2 + total + scatter + tracklength + + + 33 2 3 4 + total + scatter + analog + + + 33 2 3 + total + nu-scatter + analog + + + diff --git a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat index ac2ff0c81..b18e9773b 100644 --- a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat @@ -1,512 +1,511 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 2 2 - -100.0 -100.0 - 100.0 100.0 - - - 1 - - - 0.0 20000000.0 - - - 0.0 20000000.0 - - - 1 - - - 3 - - - 1 - - - 1 2 3 4 5 6 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - (n,2n) - tracklength - - - 1 2 - total - (n,3n) - tracklength - - - 1 2 - total - (n,4n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 2 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 68 2 - total - current - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 79 2 - total - delayed-nu-fission - tracklength - - - 1 79 2 - total - delayed-nu-fission - analog - - - 1 79 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 79 2 - total - delayed-nu-fission - tracklength - - - 1 79 - total - delayed-nu-fission - tracklength - - - 1 79 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 79 2 5 - total - delayed-nu-fission - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + + 2 2 + -100.0 -100.0 + 100.0 100.0 + + + 1 + + + 0.0 20000000.0 + + + 0.0 20000000.0 + + + 1 + + + 3 + + + 1 + + + 1 2 3 4 5 6 + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + (n,2n) + tracklength + + + 1 2 + total + (n,3n) + tracklength + + + 1 2 + total + (n,4n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + kappa-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 + total + flux + analog + + + 1 2 + total + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + nu-scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + nu-fission + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 2 + total + nu-fission + analog + + + 1 5 + total + nu-fission + analog + + + 1 2 + total + prompt-nu-fission + analog + + + 1 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + inverse-velocity + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + prompt-nu-fission + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + total + prompt-nu-fission + analog + + + 68 2 + total + current + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 2 + total + delayed-nu-fission + analog + + + 1 79 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 79 2 + total + delayed-nu-fission + tracklength + + + 1 79 + total + delayed-nu-fission + tracklength + + + 1 79 + total + decay-rate + tracklength + + + 1 2 + total + flux + analog + + + 1 79 2 5 + total + delayed-nu-fission + analog + + + diff --git a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat index 59cbddec4..54d095ac6 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat @@ -1,1952 +1,1951 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 1 2 3 4 5 6 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - (n,2n) - tracklength - - - 1 2 - total - (n,3n) - tracklength - - - 1 2 - total - (n,4n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 30 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 54 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 54 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,elastic) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,level) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,2n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,na) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,nc) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,gamma) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,a) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,Xa) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - heating - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - damage-energy - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,n1) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - (n,a0) - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - (n,nc) - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - (n,n1) - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - (n,2n) - analog - - - 1 2 - total - flux - tracklength - - - 1 108 2 - total - delayed-nu-fission - tracklength - - - 1 108 54 - total - delayed-nu-fission - analog - - - 1 108 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 108 2 - total - delayed-nu-fission - tracklength - - - 1 108 - total - delayed-nu-fission - tracklength - - - 1 108 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 108 2 5 - total - delayed-nu-fission - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - total - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - total - tracklength - - - 122 2 - total - flux - analog - - - 122 5 6 - total - scatter - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - total - tracklength - - - 122 2 - total - flux - analog - - - 122 5 6 - total - nu-scatter - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - absorption - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - absorption - tracklength - - - 122 2 - total - (n,2n) - tracklength - - - 122 2 - total - (n,3n) - tracklength - - - 122 2 - total - (n,4n) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - absorption - tracklength - - - 122 2 - total - fission - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - fission - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - nu-fission - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - kappa-fission - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - scatter - tracklength - - - 122 2 - total - flux - analog - - - 122 2 - total - nu-scatter - analog - - - 122 2 - total - flux - analog - - - 122 2 5 30 - total - scatter - analog - - - 122 2 - total - flux - analog - - - 122 2 5 30 - total - nu-scatter - analog - - - 122 2 5 - total - nu-scatter - analog - - - 122 2 5 - total - scatter - analog - - - 122 2 - total - flux - analog - - - 122 2 5 - total - nu-fission - analog - - - 122 2 5 - total - scatter - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - scatter - tracklength - - - 122 2 5 30 - total - scatter - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - scatter - tracklength - - - 122 2 5 30 - total - scatter - analog - - - 122 2 5 - total - nu-scatter - analog - - - 122 54 - total - nu-fission - analog - - - 122 5 - total - nu-fission - analog - - - 122 54 - total - prompt-nu-fission - analog - - - 122 5 - total - prompt-nu-fission - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - inverse-velocity - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - prompt-nu-fission - tracklength - - - 122 2 - total - flux - analog - - - 122 2 5 - total - prompt-nu-fission - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - total - tracklength - - - 122 2 - total - flux - analog - - - 122 5 6 - total - scatter - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - total - tracklength - - - 122 2 - total - flux - analog - - - 122 5 6 - total - nu-scatter - analog - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,elastic) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,level) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,2n) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,na) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,nc) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,gamma) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,a) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,Xa) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - heating - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - damage-energy - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,n1) - tracklength - - - 122 2 - total - flux - tracklength - - - 122 2 - total - (n,a0) - tracklength - - - 122 2 - total - flux - analog - - - 122 2 5 - total - (n,nc) - analog - - - 122 2 - total - flux - analog - - - 122 2 5 - total - (n,n1) - analog - - - 122 2 - total - flux - analog - - - 122 2 5 - total - (n,2n) - analog - - - 122 2 - total - flux - tracklength - - - 122 108 2 - total - delayed-nu-fission - tracklength - - - 122 108 54 - total - delayed-nu-fission - analog - - - 122 108 5 - total - delayed-nu-fission - analog - - - 122 2 - total - nu-fission - tracklength - - - 122 108 2 - total - delayed-nu-fission - tracklength - - - 122 108 - total - delayed-nu-fission - tracklength - - - 122 108 - total - decay-rate - tracklength - - - 122 2 - total - flux - analog - - - 122 108 2 5 - total - delayed-nu-fission - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - total - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - total - tracklength - - - 243 2 - total - flux - analog - - - 243 5 6 - total - scatter - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - total - tracklength - - - 243 2 - total - flux - analog - - - 243 5 6 - total - nu-scatter - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - absorption - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - absorption - tracklength - - - 243 2 - total - (n,2n) - tracklength - - - 243 2 - total - (n,3n) - tracklength - - - 243 2 - total - (n,4n) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - absorption - tracklength - - - 243 2 - total - fission - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - fission - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - nu-fission - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - kappa-fission - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - scatter - tracklength - - - 243 2 - total - flux - analog - - - 243 2 - total - nu-scatter - analog - - - 243 2 - total - flux - analog - - - 243 2 5 30 - total - scatter - analog - - - 243 2 - total - flux - analog - - - 243 2 5 30 - total - nu-scatter - analog - - - 243 2 5 - total - nu-scatter - analog - - - 243 2 5 - total - scatter - analog - - - 243 2 - total - flux - analog - - - 243 2 5 - total - nu-fission - analog - - - 243 2 5 - total - scatter - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - scatter - tracklength - - - 243 2 5 30 - total - scatter - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - scatter - tracklength - - - 243 2 5 30 - total - scatter - analog - - - 243 2 5 - total - nu-scatter - analog - - - 243 54 - total - nu-fission - analog - - - 243 5 - total - nu-fission - analog - - - 243 54 - total - prompt-nu-fission - analog - - - 243 5 - total - prompt-nu-fission - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - inverse-velocity - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - prompt-nu-fission - tracklength - - - 243 2 - total - flux - analog - - - 243 2 5 - total - prompt-nu-fission - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - total - tracklength - - - 243 2 - total - flux - analog - - - 243 5 6 - total - scatter - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - total - tracklength - - - 243 2 - total - flux - analog - - - 243 5 6 - total - nu-scatter - analog - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,elastic) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,level) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,2n) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,na) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,nc) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,gamma) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,a) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,Xa) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - heating - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - damage-energy - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,n1) - tracklength - - - 243 2 - total - flux - tracklength - - - 243 2 - total - (n,a0) - tracklength - - - 243 2 - total - flux - analog - - - 243 2 5 - total - (n,nc) - analog - - - 243 2 - total - flux - analog - - - 243 2 5 - total - (n,n1) - analog - - - 243 2 - total - flux - analog - - - 243 2 5 - total - (n,2n) - analog - - - 243 2 - total - flux - tracklength - - - 243 108 2 - total - delayed-nu-fission - tracklength - - - 243 108 54 - total - delayed-nu-fission - analog - - - 243 108 5 - total - delayed-nu-fission - analog - - - 243 2 - total - nu-fission - tracklength - - - 243 108 2 - total - delayed-nu-fission - tracklength - - - 243 108 - total - delayed-nu-fission - tracklength - - - 243 108 - total - decay-rate - tracklength - - - 243 2 - total - flux - analog - - - 243 108 2 5 - total - delayed-nu-fission - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 1 + + + 3 + + + 0.0 20000000.0 + + + 1 2 3 4 5 6 + + + 2 + + + 3 + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + (n,2n) + tracklength + + + 1 2 + total + (n,3n) + tracklength + + + 1 2 + total + (n,4n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + absorption + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + kappa-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 + total + flux + analog + + + 1 2 + total + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + total + nu-scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + nu-fission + analog + + + 1 2 5 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 5 30 + total + scatter + analog + + + 1 2 5 + total + nu-scatter + analog + + + 1 54 + total + nu-fission + analog + + + 1 5 + total + nu-fission + analog + + + 1 54 + total + prompt-nu-fission + analog + + + 1 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + inverse-velocity + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + prompt-nu-fission + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + total + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,elastic) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,level) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,2n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,na) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,nc) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,gamma) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,a) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,Xa) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + heating + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + damage-energy + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,n1) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + total + (n,a0) + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + total + (n,nc) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + (n,n1) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + (n,2n) + analog + + + 1 2 + total + flux + tracklength + + + 1 108 2 + total + delayed-nu-fission + tracklength + + + 1 108 54 + total + delayed-nu-fission + analog + + + 1 108 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 108 2 + total + delayed-nu-fission + tracklength + + + 1 108 + total + delayed-nu-fission + tracklength + + + 1 108 + total + decay-rate + tracklength + + + 1 2 + total + flux + analog + + + 1 108 2 5 + total + delayed-nu-fission + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + total + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + total + tracklength + + + 122 2 + total + flux + analog + + + 122 5 6 + total + scatter + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + total + tracklength + + + 122 2 + total + flux + analog + + + 122 5 6 + total + nu-scatter + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + absorption + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + absorption + tracklength + + + 122 2 + total + (n,2n) + tracklength + + + 122 2 + total + (n,3n) + tracklength + + + 122 2 + total + (n,4n) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + absorption + tracklength + + + 122 2 + total + fission + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + fission + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + nu-fission + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + kappa-fission + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + scatter + tracklength + + + 122 2 + total + flux + analog + + + 122 2 + total + nu-scatter + analog + + + 122 2 + total + flux + analog + + + 122 2 5 30 + total + scatter + analog + + + 122 2 + total + flux + analog + + + 122 2 5 30 + total + nu-scatter + analog + + + 122 2 5 + total + nu-scatter + analog + + + 122 2 5 + total + scatter + analog + + + 122 2 + total + flux + analog + + + 122 2 5 + total + nu-fission + analog + + + 122 2 5 + total + scatter + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + scatter + tracklength + + + 122 2 5 30 + total + scatter + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + scatter + tracklength + + + 122 2 5 30 + total + scatter + analog + + + 122 2 5 + total + nu-scatter + analog + + + 122 54 + total + nu-fission + analog + + + 122 5 + total + nu-fission + analog + + + 122 54 + total + prompt-nu-fission + analog + + + 122 5 + total + prompt-nu-fission + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + inverse-velocity + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + prompt-nu-fission + tracklength + + + 122 2 + total + flux + analog + + + 122 2 5 + total + prompt-nu-fission + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + total + tracklength + + + 122 2 + total + flux + analog + + + 122 5 6 + total + scatter + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + total + tracklength + + + 122 2 + total + flux + analog + + + 122 5 6 + total + nu-scatter + analog + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,elastic) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,level) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,2n) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,na) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,nc) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,gamma) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,a) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,Xa) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + heating + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + damage-energy + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,n1) + tracklength + + + 122 2 + total + flux + tracklength + + + 122 2 + total + (n,a0) + tracklength + + + 122 2 + total + flux + analog + + + 122 2 5 + total + (n,nc) + analog + + + 122 2 + total + flux + analog + + + 122 2 5 + total + (n,n1) + analog + + + 122 2 + total + flux + analog + + + 122 2 5 + total + (n,2n) + analog + + + 122 2 + total + flux + tracklength + + + 122 108 2 + total + delayed-nu-fission + tracklength + + + 122 108 54 + total + delayed-nu-fission + analog + + + 122 108 5 + total + delayed-nu-fission + analog + + + 122 2 + total + nu-fission + tracklength + + + 122 108 2 + total + delayed-nu-fission + tracklength + + + 122 108 + total + delayed-nu-fission + tracklength + + + 122 108 + total + decay-rate + tracklength + + + 122 2 + total + flux + analog + + + 122 108 2 5 + total + delayed-nu-fission + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + nu-scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + absorption + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + absorption + tracklength + + + 243 2 + total + (n,2n) + tracklength + + + 243 2 + total + (n,3n) + tracklength + + + 243 2 + total + (n,4n) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + absorption + tracklength + + + 243 2 + total + fission + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + fission + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + nu-fission + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + kappa-fission + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + scatter + tracklength + + + 243 2 + total + flux + analog + + + 243 2 + total + nu-scatter + analog + + + 243 2 + total + flux + analog + + + 243 2 5 30 + total + scatter + analog + + + 243 2 + total + flux + analog + + + 243 2 5 30 + total + nu-scatter + analog + + + 243 2 5 + total + nu-scatter + analog + + + 243 2 5 + total + scatter + analog + + + 243 2 + total + flux + analog + + + 243 2 5 + total + nu-fission + analog + + + 243 2 5 + total + scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + scatter + tracklength + + + 243 2 5 30 + total + scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + scatter + tracklength + + + 243 2 5 30 + total + scatter + analog + + + 243 2 5 + total + nu-scatter + analog + + + 243 54 + total + nu-fission + analog + + + 243 5 + total + nu-fission + analog + + + 243 54 + total + prompt-nu-fission + analog + + + 243 5 + total + prompt-nu-fission + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + inverse-velocity + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + prompt-nu-fission + tracklength + + + 243 2 + total + flux + analog + + + 243 2 5 + total + prompt-nu-fission + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + total + tracklength + + + 243 2 + total + flux + analog + + + 243 5 6 + total + nu-scatter + analog + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,elastic) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,level) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,2n) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,na) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,nc) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,gamma) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,a) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,Xa) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + heating + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + damage-energy + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,n1) + tracklength + + + 243 2 + total + flux + tracklength + + + 243 2 + total + (n,a0) + tracklength + + + 243 2 + total + flux + analog + + + 243 2 5 + total + (n,nc) + analog + + + 243 2 + total + flux + analog + + + 243 2 5 + total + (n,n1) + analog + + + 243 2 + total + flux + analog + + + 243 2 5 + total + (n,2n) + analog + + + 243 2 + total + flux + tracklength + + + 243 108 2 + total + delayed-nu-fission + tracklength + + + 243 108 54 + total + delayed-nu-fission + analog + + + 243 108 5 + total + delayed-nu-fission + analog + + + 243 2 + total + nu-fission + tracklength + + + 243 108 2 + total + delayed-nu-fission + tracklength + + + 243 108 + total + delayed-nu-fission + tracklength + + + 243 108 + total + decay-rate + tracklength + + + 243 2 + total + flux + analog + + + 243 108 2 5 + total + delayed-nu-fission + analog + + + diff --git a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat index e45fe389e..5e9720ced 100644 --- a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat @@ -1,1769 +1,1768 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - absorption - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,2n) - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,3n) - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,4n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - absorption - tracklength - - - 1 2 - U234 U235 U238 O16 - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 5 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 5 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - U234 U235 U238 O16 - nu-fission - analog - - - 1 2 5 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 5 30 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 5 30 - U234 U235 U238 O16 - scatter - analog - - - 1 2 5 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 54 - U234 U235 U238 O16 - nu-fission - analog - - - 1 5 - U234 U235 U238 O16 - nu-fission - analog - - - 1 54 - U234 U235 U238 O16 - prompt-nu-fission - analog - - - 1 5 - U234 U235 U238 O16 - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - U234 U235 U238 O16 - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,elastic) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,level) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,2n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,na) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,nc) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,gamma) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,a) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,Xa) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - heating - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - damage-energy - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,n1) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - (n,a0) - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - U234 U235 U238 O16 - (n,nc) - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - U234 U235 U238 O16 - (n,n1) - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - U234 U235 U238 O16 - (n,2n) - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 106 2 - total - flux - analog - - - 106 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 106 2 - total - flux - analog - - - 106 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,2n) - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,3n) - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,4n) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - kappa-fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 106 2 - total - flux - analog - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 106 2 - total - flux - analog - - - 106 2 5 30 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 106 2 - total - flux - analog - - - 106 2 5 30 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 106 2 5 30 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 106 2 5 30 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 106 54 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 106 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 106 54 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 106 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - inverse-velocity - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - tracklength - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 106 2 - total - flux - analog - - - 106 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 106 2 - total - flux - analog - - - 106 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,elastic) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,level) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,2n) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,na) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,nc) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,gamma) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,a) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,Xa) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - heating - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - damage-energy - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,n1) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,a0) - tracklength - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,nc) - analog - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,n1) - analog - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - (n,2n) - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - total - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 - H1 O16 B10 B11 - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 - H1 O16 B10 B11 - nu-scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - absorption - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - absorption - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,2n) - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,3n) - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,4n) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - absorption - tracklength - - - 211 2 - H1 O16 B10 B11 - fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - nu-fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - kappa-fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - scatter - tracklength - - - 211 2 - total - flux - analog - - - 211 2 - H1 O16 B10 B11 - nu-scatter - analog - - - 211 2 - total - flux - analog - - - 211 2 5 30 - H1 O16 B10 B11 - scatter - analog - - - 211 2 - total - flux - analog - - - 211 2 5 30 - H1 O16 B10 B11 - nu-scatter - analog - - - 211 2 5 - H1 O16 B10 B11 - nu-scatter - analog - - - 211 2 5 - H1 O16 B10 B11 - scatter - analog - - - 211 2 - total - flux - analog - - - 211 2 5 - H1 O16 B10 B11 - nu-fission - analog - - - 211 2 5 - H1 O16 B10 B11 - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - scatter - tracklength - - - 211 2 5 30 - H1 O16 B10 B11 - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - scatter - tracklength - - - 211 2 5 30 - H1 O16 B10 B11 - scatter - analog - - - 211 2 5 - H1 O16 B10 B11 - nu-scatter - analog - - - 211 54 - H1 O16 B10 B11 - nu-fission - analog - - - 211 5 - H1 O16 B10 B11 - nu-fission - analog - - - 211 54 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 211 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - inverse-velocity - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - prompt-nu-fission - tracklength - - - 211 2 - total - flux - analog - - - 211 2 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 - H1 O16 B10 B11 - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 - H1 O16 B10 B11 - nu-scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,elastic) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,level) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,2n) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,na) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,nc) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,gamma) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,a) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,Xa) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - heating - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - damage-energy - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,n1) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 O16 B10 B11 - (n,a0) - tracklength - - - 211 2 - total - flux - analog - - - 211 2 5 - H1 O16 B10 B11 - (n,nc) - analog - - - 211 2 - total - flux - analog - - - 211 2 5 - H1 O16 B10 B11 - (n,n1) - analog - - - 211 2 - total - flux - analog - - - 211 2 5 - H1 O16 B10 B11 - (n,2n) - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 1 + + + 3 + + + 0.0 20000000.0 + + + 2 + + + 3 + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + total + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + absorption + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + absorption + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,2n) + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,3n) + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,4n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + absorption + tracklength + + + 1 2 + U234 U235 U238 O16 + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + nu-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + kappa-fission + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + scatter + tracklength + + + 1 2 + total + flux + analog + + + 1 2 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 30 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 2 5 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 2 5 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + nu-fission + analog + + + 1 2 5 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + scatter + tracklength + + + 1 2 5 30 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + scatter + tracklength + + + 1 2 5 30 + U234 U235 U238 O16 + scatter + analog + + + 1 2 5 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 54 + U234 U235 U238 O16 + nu-fission + analog + + + 1 5 + U234 U235 U238 O16 + nu-fission + analog + + + 1 54 + U234 U235 U238 O16 + prompt-nu-fission + analog + + + 1 5 + U234 U235 U238 O16 + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + inverse-velocity + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + prompt-nu-fission + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + prompt-nu-fission + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U234 U235 U238 O16 + scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + total + tracklength + + + 1 2 + total + flux + analog + + + 1 5 6 + U234 U235 U238 O16 + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,elastic) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,level) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,2n) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,na) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,nc) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,gamma) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,a) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,Xa) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + heating + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + damage-energy + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,n1) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,a0) + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + (n,nc) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + (n,n1) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + (n,2n) + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + absorption + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + absorption + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,2n) + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,3n) + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,4n) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + absorption + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + kappa-fission + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + tracklength + + + 106 2 + total + flux + analog + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 106 2 + total + flux + analog + + + 106 2 5 30 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 + total + flux + analog + + + 106 2 5 30 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + tracklength + + + 106 2 5 30 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + tracklength + + + 106 2 5 30 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 106 54 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog + + + 106 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog + + + 106 54 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog + + + 106 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + inverse-velocity + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + tracklength + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 106 2 + total + flux + analog + + + 106 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,elastic) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,level) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,2n) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,na) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,nc) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,gamma) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,a) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,Xa) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + heating + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + damage-energy + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,n1) + tracklength + + + 106 2 + total + flux + tracklength + + + 106 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,a0) + tracklength + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,nc) + analog + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,n1) + analog + + + 106 2 + total + flux + analog + + + 106 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,2n) + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + absorption + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + absorption + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,2n) + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,3n) + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,4n) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + absorption + tracklength + + + 211 2 + H1 O16 B10 B11 + fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + nu-fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + kappa-fission + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + scatter + tracklength + + + 211 2 + total + flux + analog + + + 211 2 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 + total + flux + analog + + + 211 2 5 30 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + analog + + + 211 2 5 30 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 5 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 5 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 O16 B10 B11 + nu-fission + analog + + + 211 2 5 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + scatter + tracklength + + + 211 2 5 30 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + scatter + tracklength + + + 211 2 5 30 + H1 O16 B10 B11 + scatter + analog + + + 211 2 5 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 54 + H1 O16 B10 B11 + nu-fission + analog + + + 211 5 + H1 O16 B10 B11 + nu-fission + analog + + + 211 54 + H1 O16 B10 B11 + prompt-nu-fission + analog + + + 211 5 + H1 O16 B10 B11 + prompt-nu-fission + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + inverse-velocity + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + prompt-nu-fission + tracklength + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 O16 B10 B11 + prompt-nu-fission + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + total + tracklength + + + 211 2 + total + flux + analog + + + 211 5 6 + H1 O16 B10 B11 + nu-scatter + analog + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,elastic) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,level) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,2n) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,na) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,nc) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,gamma) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,a) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,Xa) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + heating + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + damage-energy + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,n1) + tracklength + + + 211 2 + total + flux + tracklength + + + 211 2 + H1 O16 B10 B11 + (n,a0) + tracklength + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 O16 B10 B11 + (n,nc) + analog + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 O16 B10 B11 + (n,n1) + analog + + + 211 2 + total + flux + analog + + + 211 2 5 + H1 O16 B10 B11 + (n,2n) + analog + + + diff --git a/tests/regression_tests/multipole/inputs_true.dat b/tests/regression_tests/multipole/inputs_true.dat index 3bbcc2024..3a602b28b 100644 --- a/tests/regression_tests/multipole/inputs_true.dat +++ b/tests/regression_tests/multipole/inputs_true.dat @@ -1,55 +1,54 @@ - - - - - - - 2.0 2.0 - 1 - 2 2 - -2.0 -2.0 - + + + + + + + + + + + + + + + + + + + + 2.0 2.0 + 1 + 2 2 + -2.0 -2.0 + 11 11 11 11 - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - -1 -1 -1 1 1 1 - - - true - 1000 - - - - - U235 O16 total - total fission (n,gamma) elastic (n,p) - - + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + -1 -1 -1 1 1 1 + + + true + 1000 + + + + U235 O16 total + total fission (n,gamma) elastic (n,p) + + + diff --git a/tests/regression_tests/ncrystal/inputs_true.dat b/tests/regression_tests/ncrystal/inputs_true.dat index 7a3f20eb3..a609edcae 100644 --- a/tests/regression_tests/ncrystal/inputs_true.dat +++ b/tests/regression_tests/ncrystal/inputs_true.dat @@ -1,45 +1,44 @@ - - - - - - - - - - - - - - - - fixed source - 100000 - 10 - - - 0 0 -20 - - - - 0.012 1.0 - - - - - - - 1 - - - 0.0 0.017453292519943295 0.03490658503988659 0.05235987755982989 0.06981317007977318 0.08726646259971647 0.10471975511965978 0.12217304763960307 0.13962634015954636 0.15707963267948966 0.17453292519943295 0.19198621771937624 0.20943951023931956 0.22689280275926285 0.24434609527920614 0.2617993877991494 0.2792526803190927 0.29670597283903605 0.3141592653589793 0.33161255787892263 0.3490658503988659 0.3665191429188092 0.3839724354387525 0.4014257279586958 0.4188790204786391 0.4363323129985824 0.4537856055185257 0.47123889803846897 0.4886921905584123 0.5061454830783556 0.5235987755982988 0.5410520681182421 0.5585053606381855 0.5759586531581288 0.5934119456780721 0.6108652381980153 0.6283185307179586 0.6457718232379019 0.6632251157578453 0.6806784082777885 0.6981317007977318 0.7155849933176751 0.7330382858376184 0.7504915783575618 0.767944870877505 0.7853981633974483 0.8028514559173916 0.8203047484373349 0.8377580409572782 0.8552113334772214 0.8726646259971648 0.8901179185171081 0.9075712110370514 0.9250245035569946 0.9424777960769379 0.9599310885968813 0.9773843811168246 0.9948376736367679 1.0122909661567112 1.0297442586766545 1.0471975511965976 1.064650843716541 1.0821041362364843 1.0995574287564276 1.117010721276371 1.1344640137963142 1.1519173063162575 1.1693705988362009 1.1868238913561442 1.2042771838760873 1.2217304763960306 1.239183768915974 1.2566370614359172 1.2740903539558606 1.2915436464758039 1.3089969389957472 1.3264502315156905 1.3439035240356338 1.361356816555577 1.3788101090755203 1.3962634015954636 1.413716694115407 1.4311699866353502 1.4486232791552935 1.4660765716752369 1.4835298641951802 1.5009831567151235 1.5184364492350666 1.53588974175501 1.5533430342749532 1.5707963267948966 1.5882496193148399 1.6057029118347832 1.6231562043547265 1.6406094968746698 1.6580627893946132 1.6755160819145565 1.6929693744344996 1.710422666954443 1.7278759594743862 1.7453292519943295 1.7627825445142729 1.7802358370342162 1.7976891295541595 1.8151424220741028 1.8325957145940461 1.8500490071139892 1.8675022996339325 1.8849555921538759 1.9024088846738192 1.9198621771937625 1.9373154697137058 1.9547687622336491 1.9722220547535925 1.9896753472735358 2.007128639793479 2.0245819323134224 2.0420352248333655 2.059488517353309 2.076941809873252 2.0943951023931953 2.111848394913139 2.129301687433082 2.1467549799530254 2.1642082724729685 2.181661564992912 2.199114857512855 2.2165681500327987 2.234021442552742 2.251474735072685 2.2689280275926285 2.2863813201125716 2.303834612632515 2.321287905152458 2.3387411976724017 2.356194490192345 2.3736477827122884 2.3911010752322315 2.4085543677521746 2.426007660272118 2.443460952792061 2.4609142453120048 2.478367537831948 2.4958208303518914 2.5132741228718345 2.530727415391778 2.548180707911721 2.5656340004316642 2.5830872929516078 2.600540585471551 2.6179938779914944 2.6354471705114375 2.652900463031381 2.670353755551324 2.6878070480712677 2.705260340591211 2.722713633111154 2.7401669256310974 2.7576202181510405 2.775073510670984 2.792526803190927 2.8099800957108707 2.827433388230814 2.8448866807507573 2.8623399732707004 2.8797932657906435 2.897246558310587 2.91469985083053 2.9321531433504737 2.949606435870417 2.9670597283903604 2.9845130209103035 3.001966313430247 3.01941960595019 3.036872898470133 3.0543261909900767 3.07177948351002 3.0892327760299634 3.1066860685499065 3.12413936106985 3.141592653589793 - - - 1 - - - 1 2 3 - current - - + + + + + + + + + + + + + + + fixed source + 100000 + 10 + + + 0 0 -20 + + + + 0.012 1.0 + + + + + + 1 + + + 0.0 0.017453292519943295 0.03490658503988659 0.05235987755982989 0.06981317007977318 0.08726646259971647 0.10471975511965978 0.12217304763960307 0.13962634015954636 0.15707963267948966 0.17453292519943295 0.19198621771937624 0.20943951023931956 0.22689280275926285 0.24434609527920614 0.2617993877991494 0.2792526803190927 0.29670597283903605 0.3141592653589793 0.33161255787892263 0.3490658503988659 0.3665191429188092 0.3839724354387525 0.4014257279586958 0.4188790204786391 0.4363323129985824 0.4537856055185257 0.47123889803846897 0.4886921905584123 0.5061454830783556 0.5235987755982988 0.5410520681182421 0.5585053606381855 0.5759586531581288 0.5934119456780721 0.6108652381980153 0.6283185307179586 0.6457718232379019 0.6632251157578453 0.6806784082777885 0.6981317007977318 0.7155849933176751 0.7330382858376184 0.7504915783575618 0.767944870877505 0.7853981633974483 0.8028514559173916 0.8203047484373349 0.8377580409572782 0.8552113334772214 0.8726646259971648 0.8901179185171081 0.9075712110370514 0.9250245035569946 0.9424777960769379 0.9599310885968813 0.9773843811168246 0.9948376736367679 1.0122909661567112 1.0297442586766545 1.0471975511965976 1.064650843716541 1.0821041362364843 1.0995574287564276 1.117010721276371 1.1344640137963142 1.1519173063162575 1.1693705988362009 1.1868238913561442 1.2042771838760873 1.2217304763960306 1.239183768915974 1.2566370614359172 1.2740903539558606 1.2915436464758039 1.3089969389957472 1.3264502315156905 1.3439035240356338 1.361356816555577 1.3788101090755203 1.3962634015954636 1.413716694115407 1.4311699866353502 1.4486232791552935 1.4660765716752369 1.4835298641951802 1.5009831567151235 1.5184364492350666 1.53588974175501 1.5533430342749532 1.5707963267948966 1.5882496193148399 1.6057029118347832 1.6231562043547265 1.6406094968746698 1.6580627893946132 1.6755160819145565 1.6929693744344996 1.710422666954443 1.7278759594743862 1.7453292519943295 1.7627825445142729 1.7802358370342162 1.7976891295541595 1.8151424220741028 1.8325957145940461 1.8500490071139892 1.8675022996339325 1.8849555921538759 1.9024088846738192 1.9198621771937625 1.9373154697137058 1.9547687622336491 1.9722220547535925 1.9896753472735358 2.007128639793479 2.0245819323134224 2.0420352248333655 2.059488517353309 2.076941809873252 2.0943951023931953 2.111848394913139 2.129301687433082 2.1467549799530254 2.1642082724729685 2.181661564992912 2.199114857512855 2.2165681500327987 2.234021442552742 2.251474735072685 2.2689280275926285 2.2863813201125716 2.303834612632515 2.321287905152458 2.3387411976724017 2.356194490192345 2.3736477827122884 2.3911010752322315 2.4085543677521746 2.426007660272118 2.443460952792061 2.4609142453120048 2.478367537831948 2.4958208303518914 2.5132741228718345 2.530727415391778 2.548180707911721 2.5656340004316642 2.5830872929516078 2.600540585471551 2.6179938779914944 2.6354471705114375 2.652900463031381 2.670353755551324 2.6878070480712677 2.705260340591211 2.722713633111154 2.7401669256310974 2.7576202181510405 2.775073510670984 2.792526803190927 2.8099800957108707 2.827433388230814 2.8448866807507573 2.8623399732707004 2.8797932657906435 2.897246558310587 2.91469985083053 2.9321531433504737 2.949606435870417 2.9670597283903604 2.9845130209103035 3.001966313430247 3.01941960595019 3.036872898470133 3.0543261909900767 3.07177948351002 3.0892327760299634 3.1066860685499065 3.12413936106985 3.141592653589793 + + + 1 + + + 1 2 3 + current + + + diff --git a/tests/regression_tests/periodic/inputs_true.dat b/tests/regression_tests/periodic/inputs_true.dat index c1f6d1563..9934e2de0 100644 --- a/tests/regression_tests/periodic/inputs_true.dat +++ b/tests/regression_tests/periodic/inputs_true.dat @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 4 - 0 - - - 0 0 0 5 5 0 - - - + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 4 + 0 + + + 0 0 0 5 5 0 + + + + diff --git a/tests/regression_tests/periodic_6fold/inputs_true.dat b/tests/regression_tests/periodic_6fold/inputs_true.dat index 35bbcc047..9c2899417 100644 --- a/tests/regression_tests/periodic_6fold/inputs_true.dat +++ b/tests/regression_tests/periodic_6fold/inputs_true.dat @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 4 - 0 - - - 0 0 0 5 5 0 - - - + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 4 + 0 + + + 0 0 0 5 5 0 + + + + diff --git a/tests/regression_tests/periodic_hex/inputs_true.dat b/tests/regression_tests/periodic_hex/inputs_true.dat index 00e539d4b..f4869fa58 100644 --- a/tests/regression_tests/periodic_hex/inputs_true.dat +++ b/tests/regression_tests/periodic_hex/inputs_true.dat @@ -1,24 +1,24 @@ - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + diff --git a/tests/regression_tests/photon_production/inputs_true.dat b/tests/regression_tests/photon_production/inputs_true.dat index 09f1fd290..0b2b43468 100644 --- a/tests/regression_tests/photon_production/inputs_true.dat +++ b/tests/regression_tests/photon_production/inputs_true.dat @@ -1,68 +1,67 @@ - - - - - - - - - - - - - - - - - - - fixed source - 10000 - 1 - - - 0 0 0 - - - - 14000000.0 1.0 - - - ttb - true - - 1000.0 - - - - - - 1 - - - neutron photon electron positron - - - 1 2 - current - - - 2 - Al27 total - total (n,gamma) - tracklength - - - 2 - Al27 total - total heating (n,gamma) - collision - - - 2 - Al27 total - total heating (n,gamma) - analog - - + + + + + + + + + + + + + + + + + + fixed source + 10000 + 1 + + + 0 0 0 + + + + 14000000.0 1.0 + + + ttb + true + + 1000.0 + + + + + 1 + + + neutron photon electron positron + + + 1 2 + current + + + 2 + Al27 total + total (n,gamma) + tracklength + + + 2 + Al27 total + total heating (n,gamma) + collision + + + 2 + Al27 total + total heating (n,gamma) + analog + + + diff --git a/tests/regression_tests/photon_production_fission/inputs_true.dat b/tests/regression_tests/photon_production_fission/inputs_true.dat index c317f6273..ea6e9d9ee 100644 --- a/tests/regression_tests/photon_production_fission/inputs_true.dat +++ b/tests/regression_tests/photon_production_fission/inputs_true.dat @@ -1,49 +1,48 @@ - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 2 - - - 0 0 0 - - - true - - - - - neutron photon - - - 1 - U235 total - fission heating-local - tracklength - - - 1 - U235 total - fission heating heating-local - collision - - - 1 - U235 total - fission heating heating-local - analog - - + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 2 + + + 0 0 0 + + + true + + + + neutron photon + + + 1 + U235 total + fission heating-local + tracklength + + + 1 + U235 total + fission heating heating-local + collision + + + 1 + U235 total + fission heating heating-local + analog + + + diff --git a/tests/regression_tests/photon_source/inputs_true.dat b/tests/regression_tests/photon_source/inputs_true.dat index f7c9c24b4..4c61b47fc 100644 --- a/tests/regression_tests/photon_source/inputs_true.dat +++ b/tests/regression_tests/photon_source/inputs_true.dat @@ -1,45 +1,44 @@ - - - - - - - - - - - - - - - - - fixed source - 10000 - 1 - - - 0 0 0 - - - - 10000000.0 1.0 - - - ttb - true - - 1000.0 - - - - - - photon - - - 1 - flux (n,gamma) - - + + + + + + + + + + + + + + + + fixed source + 10000 + 1 + + + 0 0 0 + + + + 10000000.0 1.0 + + + ttb + true + + 1000.0 + + + + + photon + + + 1 + flux (n,gamma) + + + diff --git a/tests/regression_tests/photon_source/test.py b/tests/regression_tests/photon_source/test.py index a2bfb9038..d4b4a69fd 100644 --- a/tests/regression_tests/photon_source/test.py +++ b/tests/regression_tests/photon_source/test.py @@ -7,20 +7,19 @@ from tests.testing_harness import PyAPITestHarness class SourceTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) mat = openmc.Material() mat.set_density('g/cm3', 0.998207) mat.add_element('H', 0.111894) mat.add_element('O', 0.888106) - materials = openmc.Materials([mat]) - materials.export_to_xml() + self._model.materials = openmc.Materials([mat]) sphere = openmc.Sphere(r=1.0e9, boundary_type='reflective') inside_sphere = openmc.Cell() inside_sphere.region = -sphere inside_sphere.fill = mat - geometry = openmc.Geometry([inside_sphere]) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry([inside_sphere]) source = openmc.Source() source.space = openmc.stats.Point((0, 0, 0)) @@ -36,16 +35,16 @@ class SourceTestHarness(PyAPITestHarness): settings.cutoff = {'energy_photon' : 1000.0} settings.run_mode = 'fixed source' settings.source = source - settings.export_to_xml() + self._model.settings = settings particle_filter = openmc.ParticleFilter('photon') tally = openmc.Tally() tally.filters = [particle_filter] tally.scores = ['flux', '(n,gamma)'] tallies = openmc.Tallies([tally]) - tallies.export_to_xml() + self._model.tallies = tallies def test_photon_source(): - harness = SourceTestHarness('statepoint.1.h5') + harness = SourceTestHarness('statepoint.1.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/resonance_scattering/inputs_true.dat b/tests/regression_tests/resonance_scattering/inputs_true.dat index 57a5e1a4b..7165fa72b 100644 --- a/tests/regression_tests/resonance_scattering/inputs_true.dat +++ b/tests/regression_tests/resonance_scattering/inputs_true.dat @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - -4 -4 -4 4 4 4 - - - - true - rvs - 1.0 - 210.0 - U238 U235 Pu239 - - + + + + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + -4 -4 -4 4 4 4 + + + + true + rvs + 1.0 + 210.0 + U238 U235 Pu239 + + + diff --git a/tests/regression_tests/resonance_scattering/test.py b/tests/regression_tests/resonance_scattering/test.py index e77dd9258..d9f76fac5 100644 --- a/tests/regression_tests/resonance_scattering/test.py +++ b/tests/regression_tests/resonance_scattering/test.py @@ -4,7 +4,8 @@ from tests.testing_harness import PyAPITestHarness class ResonanceScatteringTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Materials mat = openmc.Material(material_id=1) mat.set_density('g/cc', 1.0) @@ -13,15 +14,13 @@ class ResonanceScatteringTestHarness(PyAPITestHarness): mat.add_nuclide('Pu239', 0.02) mat.add_nuclide('H1', 20.0) - mats_file = openmc.Materials([mat]) - mats_file.export_to_xml() + self._model.materials = openmc.Materials([mat]) # Geometry dumb_surface = openmc.XPlane(100, boundary_type='reflective') c1 = openmc.Cell(cell_id=1, fill=mat, region=-dumb_surface) root_univ = openmc.Universe(universe_id=0, cells=[c1]) - geometry = openmc.Geometry(root_univ) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root_univ) # Resonance elastic scattering settings res_scat_settings = { @@ -39,9 +38,10 @@ class ResonanceScatteringTestHarness(PyAPITestHarness): settings.source = openmc.source.Source( space=openmc.stats.Box([-4, -4, -4], [4, 4, 4])) settings.resonance_scattering = res_scat_settings - settings.export_to_xml() + self._model.settings = settings def test_resonance_scattering(): - harness = ResonanceScatteringTestHarness('statepoint.10.h5') + harness = ResonanceScatteringTestHarness('statepoint.10.h5', + model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/salphabeta/inputs_true.dat b/tests/regression_tests/salphabeta/inputs_true.dat index 29d8065cf..31a81b2c8 100644 --- a/tests/regression_tests/salphabeta/inputs_true.dat +++ b/tests/regression_tests/salphabeta/inputs_true.dat @@ -1,60 +1,60 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 400 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 400 + 5 + 0 + + + -4 -4 -4 4 4 4 + + + + diff --git a/tests/regression_tests/score_current/inputs_true.dat b/tests/regression_tests/score_current/inputs_true.dat index 2b81f508f..f9c9ba494 100644 --- a/tests/regression_tests/score_current/inputs_true.dat +++ b/tests/regression_tests/score_current/inputs_true.dat @@ -1,55 +1,54 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 3 3 3 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - 1 - - - 0.0 0.253 20000000.0 - - - 1 - current - - - 1 2 - current - - + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + + 3 3 3 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + 1 + + + 0.0 0.253 20000000.0 + + + 1 + current + + + 1 2 + current + + + diff --git a/tests/regression_tests/source/inputs_true.dat b/tests/regression_tests/source/inputs_true.dat index c9c9c4277..adf60c814 100644 --- a/tests/regression_tests/source/inputs_true.dat +++ b/tests/regression_tests/source/inputs_true.dat @@ -1,150 +1,150 @@ - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - - - -4.0 -1.0 3.0 0.2 0.3 0.5 - - - -2.0 0.0 2.0 0.2 0.3 0.2 - - - - - -1.0 0.0 1.0 0.5 0.25 0.25 - - - - - - - - -4.0 -4.0 -4.0 4.0 4.0 4.0 - - - - - - - 1.2 -2.3 0.781 - - - - 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 - - - - - - - 0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3 - - - - - - 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 - - - - - - - - -2.0 0.0 2.0 0.2 0.3 0.2 - - - - - 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 - - - - - - - - -2.0 0.0 2.0 0.2 0.3 0.2 - - - - - - - - - - - - - 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 - - - - - - - - - 0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3 - - - - - - - - - - - - - - 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 - - - - + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + + + -4.0 -1.0 3.0 0.2 0.3 0.5 + + + -2.0 0.0 2.0 0.2 0.3 0.2 + + + + + -1.0 0.0 1.0 0.5 0.25 0.25 + + + + + + + + -4.0 -4.0 -4.0 4.0 4.0 4.0 + + + + + + + 1.2 -2.3 0.781 + + + + 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 + + + + + + + 0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3 + + + + + + 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 + + + + + + + + -2.0 0.0 2.0 0.2 0.3 0.2 + + + + + 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 + + + + + + + + -2.0 0.0 2.0 0.2 0.3 0.2 + + + + + + + + + + + + + 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 + + + + + + + + + 0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3 + + + + + + + + + + + + + + 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 + + + + + diff --git a/tests/regression_tests/source/test.py b/tests/regression_tests/source/test.py index a1175c48f..af9e67baa 100644 --- a/tests/regression_tests/source/test.py +++ b/tests/regression_tests/source/test.py @@ -7,12 +7,12 @@ from tests.testing_harness import PyAPITestHarness class SourceTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) mat1 = openmc.Material(material_id=1, temperature=294) mat1.set_density('g/cm3', 4.5) mat1.add_nuclide(openmc.Nuclide('U235'), 1.0) - materials = openmc.Materials([mat1]) - materials.export_to_xml() + self._model.materials = openmc.Materials([mat1]) sphere = openmc.Sphere(surface_id=1, r=10.0, boundary_type='vacuum') inside_sphere = openmc.Cell(cell_id=1) @@ -21,9 +21,7 @@ class SourceTestHarness(PyAPITestHarness): root = openmc.Universe(universe_id=0) root.add_cell(inside_sphere) - geometry = openmc.Geometry() - geometry.root_universe = root - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root) # Create an array of different sources x_dist = openmc.stats.Uniform(-3., 3.) @@ -84,9 +82,9 @@ class SourceTestHarness(PyAPITestHarness): settings.inactive = 5 settings.particles = 1000 settings.source = [source1, source2, source3, source4, source5, source6, source7, source8] - settings.export_to_xml() + self._model.settings = settings def test_source(): - harness = SourceTestHarness('statepoint.10.h5') + harness = SourceTestHarness('statepoint.10.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/source_dlopen/inputs_true.dat b/tests/regression_tests/source_dlopen/inputs_true.dat index 23878ac20..1a447ae3d 100644 --- a/tests/regression_tests/source_dlopen/inputs_true.dat +++ b/tests/regression_tests/source_dlopen/inputs_true.dat @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - 0 - - + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + 0 + + + diff --git a/tests/regression_tests/source_parameterized_dlopen/inputs_true.dat b/tests/regression_tests/source_parameterized_dlopen/inputs_true.dat index f4a0eba73..208030e2e 100644 --- a/tests/regression_tests/source_parameterized_dlopen/inputs_true.dat +++ b/tests/regression_tests/source_parameterized_dlopen/inputs_true.dat @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - 0 - - + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + 0 + + + diff --git a/tests/regression_tests/surface_source/inputs_true_read.dat b/tests/regression_tests/surface_source/inputs_true_read.dat index 3a122c737..fb843a6d1 100644 --- a/tests/regression_tests/surface_source/inputs_true_read.dat +++ b/tests/regression_tests/surface_source/inputs_true_read.dat @@ -1,34 +1,33 @@ - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - surface_source_true.h5 - - 1 - - - - - 3 - - - 1 - flux - - + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + surface_source_true.h5 + + 1 + + + + 3 + + + 1 + flux + + + diff --git a/tests/regression_tests/surface_source/inputs_true_write.dat b/tests/regression_tests/surface_source/inputs_true_write.dat index 48dde9900..dbdf22395 100644 --- a/tests/regression_tests/surface_source/inputs_true_write.dat +++ b/tests/regression_tests/surface_source/inputs_true_write.dat @@ -1,40 +1,39 @@ - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - 0 0 0 - - - - 1 - 1000 - - 1 - - - - - 3 - - - 1 - flux - - + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + 0 0 0 + + + + 1 + 1000 + + 1 + + + + 3 + + + 1 + flux + + + diff --git a/tests/regression_tests/surface_source/surface_source_true.h5 b/tests/regression_tests/surface_source/surface_source_true.h5 index c1b6402118e353f0e55f01ab33d0f034b3d777bc..9090c9fac498c9bf36710154a028cd48ad748e8b 100644 GIT binary patch delta 11109 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 0 - - - -0.62992 -0.62992 -1 0.62992 0.62992 1 - - - - - - - 13 - - - 14 - - - 0.0 4000000.0 20000000.0 - - - 0.0 0.7853981633974483 3.141592653589793 - - - 0.0 0.7853981633974483 3.141592653589793 - - - 1 - - - 14 - - - 13 - - - 2 - - - 3 - - - 5 6 1 2 3 - current - - - 5 4 1 2 3 - current - - - 7 8 1 2 3 - current - - - 7 4 1 2 3 - current - - - 4 1 2 3 - current - - - 10 1 2 3 - current - - - 11 1 - current - - - 11 1 - current - - + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 0 + + + -0.62992 -0.62992 -1 0.62992 0.62992 1 + + + + + + 1 + + + 2 + + + 0.0 4000000.0 20000000.0 + + + 0.0 0.7853981633974483 3.141592653589793 + + + 0.0 0.7853981633974483 3.141592653589793 + + + 1 + + + 2 + + + 1 + + + 2 + + + 3 + + + 5 6 1 2 3 + current + + + 5 4 1 2 3 + current + + + 7 8 1 2 3 + current + + + 7 4 1 2 3 + current + + + 4 1 2 3 + current + + + 10 1 2 3 + current + + + 11 1 + current + + + 11 1 + current + + + diff --git a/tests/regression_tests/surface_tally/test.py b/tests/regression_tests/surface_tally/test.py index d21f361e6..001fe6448 100644 --- a/tests/regression_tests/surface_tally/test.py +++ b/tests/regression_tests/surface_tally/test.py @@ -6,7 +6,8 @@ from tests.testing_harness import PyAPITestHarness class SurfaceTallyTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Instantiate some Materials and register the appropriate Nuclides uo2 = openmc.Material(name='UO2 fuel at 2.4% wt enrichment') uo2.set_density('g/cc', 10.0) @@ -21,8 +22,7 @@ class SurfaceTallyTestHarness(PyAPITestHarness): borated_water.add_nuclide('O16', 1.0) # Instantiate a Materials collection and export to XML - materials_file = openmc.Materials([uo2, borated_water]) - materials_file.export_to_xml() + self._model.materials = openmc.Materials([uo2, borated_water]) # Instantiate ZCylinder surfaces fuel_or = openmc.ZCylinder(surface_id=1, x0=0, y0=0, r=1, @@ -61,8 +61,7 @@ class SurfaceTallyTestHarness(PyAPITestHarness): root_univ.add_cell(root_cell) # Instantiate a Geometry, register the root Universe - geometry = openmc.Geometry(root_univ) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root_univ) # Instantiate a Settings object, set all runtime parameters settings_file = openmc.Settings() @@ -76,7 +75,7 @@ class SurfaceTallyTestHarness(PyAPITestHarness): uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:],\ only_fissionable=True) settings_file.source = openmc.source.Source(space=uniform_dist) - settings_file.export_to_xml() + self._model.settings = settings_file # Tallies file tallies_file = openmc.Tallies() @@ -156,7 +155,7 @@ class SurfaceTallyTestHarness(PyAPITestHarness): surf_tally3.scores = ['current'] tallies_file.append(surf_tally3) - tallies_file.export_to_xml() + self._model.tallies = tallies_file def _get_results(self): """Digest info in the statepoint and return as a string.""" @@ -174,5 +173,5 @@ class SurfaceTallyTestHarness(PyAPITestHarness): def test_surface_tally(): - harness = SurfaceTallyTestHarness('statepoint.10.h5') + harness = SurfaceTallyTestHarness('statepoint.10.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/tallies/inputs_true.dat b/tests/regression_tests/tallies/inputs_true.dat index 61daba0d4..e6725024a 100644 --- a/tests/regression_tests/tallies/inputs_true.dat +++ b/tests/regression_tests/tallies/inputs_true.dat @@ -1,38 +1,187 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 @@ -50,12 +199,12 @@ 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 @@ -73,12 +222,12 @@ 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 @@ -100,12 +249,12 @@ 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 @@ -127,378 +276,228 @@ 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 400 - 5 - 0 - - - -160 -160 -183 160 160 183 - - - - - - - 2 2 - -182.07 -182.07 - 182.07 182.07 - - - -3.14159 -1.885 -0.6283 0.6283 1.885 3.14159 - - - 1 - - - 10 21 22 23 - - - 1 2 3 4 5 6 - - - 0.0 0.253 1000.0 1000000.0 20000000.0 - - - 0.0 0.253 1000.0 1000000.0 20000000.0 - - - 1 2 3 4 - - - -1.0 -0.5 0.0 0.5 1.0 - - - 0.0 0.6283 1.2566 1.885 2.5132 3.14159 - - - 4 - - - 4 - - - 1 2 3 4 6 8 - - - 1 2 5 3 6 - - - 10 21 22 23 60 - - - 21 22 23 27 28 29 60 - - - 1 - flux - tracklength - - - 1 - flux - analog - - - 1 2 - flux - tracklength - - - 3 - total - - - 4 - U235 O16 total - delayed-nu-fission decay-rate - - - 5 - total - - - 6 - scatter - - - 5 6 - scatter nu-fission - - - 7 - total - - - 8 - scatter nu-scatter - - - 8 2 - scatter nu-scatter - - - 9 - flux - tracklength - - - 9 - flux - analog - - - 9 2 - flux - tracklength - - - 10 - scatter nu-scatter - analog - - - 11 - scatter nu-scatter flux total - analog - - - 11 - flux total - collision - - - 11 - flux total - tracklength - - - 12 - total - - - 15 - scatter - - - 13 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - tracklength - - - 13 - U235 O16 total - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - tracklength - - - 13 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - analog - - - 13 - U235 O16 total - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - analog - - - 13 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - collision - - - 13 - U235 O16 total - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - collision - - - 14 - flux - tracklength - - - 14 - flux - analog - - - 14 - flux - collision - - - H1-production H2-production H3-production He3-production He4-production heating damage-energy - - + + + + + + + + + + + + + + + + + + + + + eigenvalue + 400 + 5 + 0 + + + -160 -160 -183 160 160 183 + + + + + + 2 2 + -182.07 -182.07 + 182.07 182.07 + + + -3.14159 -1.885 -0.6283 0.6283 1.885 3.14159 + + + 1 + + + 10 21 22 23 + + + 1 2 3 4 5 6 + + + 0.0 0.253 1000.0 1000000.0 20000000.0 + + + 0.0 0.253 1000.0 1000000.0 20000000.0 + + + 1 2 3 4 + + + -1.0 -0.5 0.0 0.5 1.0 + + + 0.0 0.6283 1.2566 1.885 2.5132 3.14159 + + + 4 + + + 4 + + + 1 2 3 4 6 8 + + + 1 2 5 3 6 + + + 10 21 22 23 60 + + + 21 22 23 27 28 29 60 + + + 1 + flux + tracklength + + + 1 + flux + analog + + + 1 2 + flux + tracklength + + + 3 + total + + + 4 + U235 O16 total + delayed-nu-fission decay-rate + + + 5 + total + + + 6 + scatter + + + 5 6 + scatter nu-fission + + + 7 + total + + + 8 + scatter nu-scatter + + + 8 2 + scatter nu-scatter + + + 9 + flux + tracklength + + + 9 + flux + analog + + + 9 2 + flux + tracklength + + + 10 + scatter nu-scatter + analog + + + 11 + scatter nu-scatter flux total + analog + + + 11 + flux total + collision + + + 11 + flux total + tracklength + + + 12 + total + + + 15 + scatter + + + 13 + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate + tracklength + + + 13 + U235 O16 total + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate + tracklength + + + 13 + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate + analog + + + 13 + U235 O16 total + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate + analog + + + 13 + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate + collision + + + 13 + U235 O16 total + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate + collision + + + 14 + flux + tracklength + + + 14 + flux + analog + + + 14 + flux + collision + + + H1-production H2-production H3-production He3-production He4-production heating damage-energy + + + diff --git a/tests/regression_tests/tally_aggregation/inputs_true.dat b/tests/regression_tests/tally_aggregation/inputs_true.dat index 80356f711..bb2dcddc5 100644 --- a/tests/regression_tests/tally_aggregation/inputs_true.dat +++ b/tests/regression_tests/tally_aggregation/inputs_true.dat @@ -1,57 +1,56 @@ - - - - - - 1.2 1.2 - 1 - 2 2 - -1.2 -1.2 - + + + + + + + + + + + + + + + + + + + + + + 1.2 1.2 + 1 + 2 2 + -1.2 -1.2 + 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - - - 0.0 0.253 1000.0 1000000.0 20000000.0 - - - 1 - - - 1 2 - U234 U235 U238 - nu-fission total - - + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + + + 0.0 0.253 1000.0 1000000.0 20000000.0 + + + 1 + + + 1 2 + U234 U235 U238 + nu-fission total + + + diff --git a/tests/regression_tests/tally_arithmetic/inputs_true.dat b/tests/regression_tests/tally_arithmetic/inputs_true.dat index fbbf94fa9..41760f3cf 100644 --- a/tests/regression_tests/tally_arithmetic/inputs_true.dat +++ b/tests/regression_tests/tally_arithmetic/inputs_true.dat @@ -1,56 +1,55 @@ - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 2 2 - -10.0 -10.0 - 10.0 10.0 - - - 1 2 - - - 0.0 10.0 20000000.0 - - - 1 - - - 2 1 - U234 U235 - nu-fission total - - - 1 3 - U238 U235 - total fission - - + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + + 2 2 + -10.0 -10.0 + 10.0 10.0 + + + 1 2 + + + 0.0 10.0 20000000.0 + + + 1 + + + 2 1 + U234 U235 + nu-fission total + + + 1 3 + U238 U235 + total fission + + + diff --git a/tests/regression_tests/tally_slice_merge/inputs_true.dat b/tests/regression_tests/tally_slice_merge/inputs_true.dat index 6f421b1d9..5b5731efb 100644 --- a/tests/regression_tests/tally_slice_merge/inputs_true.dat +++ b/tests/regression_tests/tally_slice_merge/inputs_true.dat @@ -1,38 +1,187 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 @@ -50,12 +199,12 @@ 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - + + + 1.26 1.26 + 17 17 + -10.71 -10.71 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 @@ -73,12 +222,12 @@ 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 @@ -100,12 +249,12 @@ 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - + + + 21.42 21.42 + 21 21 + -224.91 -224.91 + 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 @@ -127,222 +276,72 @@ 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -160 -160 -183 160 160 183 - - - - - - - - 2 2 - -50.0 -50.0 - 50.0 50.0 - - - 21 27 - - - 0.0 0.625 20000000.0 - - - 21 - - - 1 - - - 16 8 - U235 U238 - fission nu-fission - tracklength - - - 6 8 - U235 U238 - fission nu-fission - tracklength - - - 7 8 - U235 U238 - fission nu-fission - tracklength - - + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -160 -160 -183 160 160 183 + + + + + + + 2 2 + -50.0 -50.0 + 50.0 50.0 + + + 21 27 + + + 0.0 0.625 20000000.0 + + + 21 + + + 1 + + + 16 8 + U235 U238 + fission nu-fission + tracklength + + + 6 8 + U235 U238 + fission nu-fission + tracklength + + + 7 8 + U235 U238 + fission nu-fission + tracklength + + + diff --git a/tests/regression_tests/torus/inputs_true.dat b/tests/regression_tests/torus/inputs_true.dat index 0ccbda400..c4aa2072a 100644 --- a/tests/regression_tests/torus/inputs_true.dat +++ b/tests/regression_tests/torus/inputs_true.dat @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + diff --git a/tests/regression_tests/torus/large_major/inputs_true.dat b/tests/regression_tests/torus/large_major/inputs_true.dat index ae3f72d0f..8e3c9a9e3 100644 --- a/tests/regression_tests/torus/large_major/inputs_true.dat +++ b/tests/regression_tests/torus/large_major/inputs_true.dat @@ -1,37 +1,36 @@ - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - -1000.0 0 0 - - - - - - - flux - - + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + -1000.0 0 0 + + + + + + flux + + + diff --git a/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat b/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat index 2c422697b..d30f24fc0 100644 --- a/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat +++ b/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat @@ -1,35 +1,34 @@ - - - - - - - - - - - - - - eigenvalue - 400 - 15 - 10 - - 0.003 - std_dev - - - true - 1000 - 1 - - 1 - - - - - flux - - + + + + + + + + + + + + + eigenvalue + 400 + 15 + 10 + + 0.003 + std_dev + + + true + 1000 + 1 + + 1 + + + + flux + + + diff --git a/tests/regression_tests/triso/inputs_true.dat b/tests/regression_tests/triso/inputs_true.dat index 2ea049465..c43483884 100644 --- a/tests/regression_tests/triso/inputs_true.dat +++ b/tests/regression_tests/triso/inputs_true.dat @@ -1,442 +1,442 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0.3333333333333333 0.3333333333333333 0.3333333333333333 - 38 - 3 3 3 - -0.5 -0.5 -0.5 - -17 18 19 -14 15 16 -11 12 13 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.3333333333333333 0.3333333333333333 0.3333333333333333 + 30 + 3 3 3 + -0.5 -0.5 -0.5 + +9 10 11 +6 7 8 +3 4 5 -26 27 28 -23 24 25 -20 21 22 +18 19 20 +15 16 17 +12 13 14 -35 36 37 -32 33 34 -29 30 31 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 4 - 0 - - - 0.0 0.0 0.0 - - - +27 28 29 +24 25 26 +21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 4 + 0 + + + 0.0 0.0 0.0 + + + + diff --git a/tests/regression_tests/triso/test.py b/tests/regression_tests/triso/test.py index c44715691..248724cc2 100644 --- a/tests/regression_tests/triso/test.py +++ b/tests/regression_tests/triso/test.py @@ -9,7 +9,8 @@ from tests.testing_harness import PyAPITestHarness class TRISOTestHarness(PyAPITestHarness): - def _build_inputs(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Define TRISO matrials fuel = openmc.Material() fuel.set_density('g/cm3', 10.5) @@ -78,20 +79,19 @@ class TRISOTestHarness(PyAPITestHarness): box.fill = lattice root = openmc.Universe(0, cells=[box]) - geom = openmc.Geometry(root) - geom.export_to_xml() + self._model.geometry = openmc.Geometry(root) settings = openmc.Settings() settings.batches = 4 settings.inactive = 0 settings.particles = 100 settings.source = openmc.Source(space=openmc.stats.Point()) - settings.export_to_xml() + self._model.settings = settings - mats = openmc.Materials([fuel, porous_carbon, ipyc, sic, opyc, graphite]) - mats.export_to_xml() + self._model.materials = openmc.Materials([fuel, porous_carbon, ipyc, + sic, opyc, graphite]) def test_triso(): - harness = TRISOTestHarness('statepoint.4.h5') + harness = TRISOTestHarness('statepoint.4.h5', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/unstructured_mesh/inputs_true.dat b/tests/regression_tests/unstructured_mesh/inputs_true.dat index e556782ad..dba721d7e 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_hexes.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_hexes.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true0.dat b/tests/regression_tests/unstructured_mesh/inputs_true0.dat index 2e2594cde..7c3b5a53a 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true0.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true0.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true1.dat b/tests/regression_tests/unstructured_mesh/inputs_true1.dat index 84a3b186b..2a0ca5168 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true1.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true1.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true10.dat b/tests/regression_tests/unstructured_mesh/inputs_true10.dat index e9272a333..1290a9835 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true10.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true10.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true11.dat b/tests/regression_tests/unstructured_mesh/inputs_true11.dat index 0b89d280c..5edb5cf0f 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true11.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true11.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true12.dat b/tests/regression_tests/unstructured_mesh/inputs_true12.dat index b3673a254..d8def3b5b 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true12.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true12.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.e - - - 1 - - - 2 - - - 1 - flux - tracklength - - - 2 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.e + + + 1 + + + 2 + + + 1 + flux + tracklength + + + 2 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true13.dat b/tests/regression_tests/unstructured_mesh/inputs_true13.dat index c466396b6..3afb0ce50 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true13.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true13.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.e - - - 1 - - - 2 - - - 1 - flux - tracklength - - - 2 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.e + + + 1 + + + 2 + + + 1 + flux + tracklength + + + 2 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true14.dat b/tests/regression_tests/unstructured_mesh/inputs_true14.dat index 8c6a5120a..b7de468ea 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true14.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true14.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.e - - - 1 - - - 2 - - - 1 - flux - tracklength - - - 2 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.e + + + 1 + + + 2 + + + 1 + flux + tracklength + + + 2 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true15.dat b/tests/regression_tests/unstructured_mesh/inputs_true15.dat index 1b9abbd83..bdb1dd037 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true15.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true15.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.e - - - 1 - - - 2 - - - 1 - flux - tracklength - - - 2 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.e + + + 1 + + + 2 + + + 1 + flux + tracklength + + + 2 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true2.dat b/tests/regression_tests/unstructured_mesh/inputs_true2.dat index 7136d485a..b2a998786 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true2.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true2.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true3.dat b/tests/regression_tests/unstructured_mesh/inputs_true3.dat index 23900a060..4a66dc2a6 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true3.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true3.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true4.dat b/tests/regression_tests/unstructured_mesh/inputs_true4.dat index 995a1828f..7006c0f41 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true4.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true4.dat @@ -1,92 +1,91 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.exo - - - 9 - - - 10 - - - 9 - flux - tracklength - - - 10 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 100 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.exo + + + 9 + + + 10 + + + 9 + flux + tracklength + + + 10 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true5.dat b/tests/regression_tests/unstructured_mesh/inputs_true5.dat index 60229e5e5..6c20900fa 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true5.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true5.dat @@ -1,92 +1,91 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.exo - - - 11 - - - 12 - - - 11 - flux - tracklength - - - 12 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 100 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.exo + + + 11 + + + 12 + + + 11 + flux + tracklength + + + 12 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true6.dat b/tests/regression_tests/unstructured_mesh/inputs_true6.dat index 7a9257cb7..e0be90360 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true6.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true6.dat @@ -1,92 +1,91 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.exo - - - 13 - - - 14 - - - 13 - flux - tracklength - - - 14 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 100 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.exo + + + 13 + + + 14 + + + 13 + flux + tracklength + + + 14 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true7.dat b/tests/regression_tests/unstructured_mesh/inputs_true7.dat index 52802febf..3a4cc1b83 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true7.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true7.dat @@ -1,92 +1,91 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.exo - - - 15 - - - 16 - - - 15 - flux - tracklength - - - 16 - flux - tracklength - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 100 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.exo + + + 15 + + + 16 + + + 15 + flux + tracklength + + + 16 + flux + tracklength + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true8.dat b/tests/regression_tests/unstructured_mesh/inputs_true8.dat index a0cbbcae7..bd19a95ae 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true8.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true8.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets_w_holes.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets_w_holes.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/unstructured_mesh/inputs_true9.dat b/tests/regression_tests/unstructured_mesh/inputs_true9.dat index 930bd8579..2e595a96c 100644 --- a/tests/regression_tests/unstructured_mesh/inputs_true9.dat +++ b/tests/regression_tests/unstructured_mesh/inputs_true9.dat @@ -1,91 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 10 - - - - - 1.0 1.0 - - - 0.0 1.0 - - - - 15000000.0 1.0 - - - - - - - 10 10 10 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - test_mesh_tets.e - - - 1 - - - 2 - - - 1 - flux - collision - - - 2 - flux - collision - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 10 + + + + + 1.0 1.0 + + + 0.0 1.0 + + + + 15000000.0 1.0 + + + + + + 10 10 10 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + test_mesh_tets.e + + + 1 + + + 2 + + + 1 + flux + collision + + + 2 + flux + collision + + + diff --git a/tests/regression_tests/void/inputs_true.dat b/tests/regression_tests/void/inputs_true.dat index 644952097..443c168bd 100644 --- a/tests/regression_tests/void/inputs_true.dat +++ b/tests/regression_tests/void/inputs_true.dat @@ -1,132 +1,131 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 3 - - - 0.0 0.0 0.0 - - - - - - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 - - - 1 - total - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 1000 + 3 + + + 0.0 0.0 0.0 + + + + + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 + + + 1 + total + + + diff --git a/tests/regression_tests/volume_calc/inputs_true.dat b/tests/regression_tests/volume_calc/inputs_true.dat index aaf6d8b00..879e05b8f 100644 --- a/tests/regression_tests/volume_calc/inputs_true.dat +++ b/tests/regression_tests/volume_calc/inputs_true.dat @@ -1,75 +1,75 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - volume - - cell - 1 2 3 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - material - 1 2 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - universe - 0 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - cell - 1 2 3 - 100 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - - material - 1 2 - 100 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - - cell - 1 2 3 - 100 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + volume + + cell + 1 2 3 + 100000 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + material + 1 2 + 100000 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + universe + 0 + 100000 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + cell + 1 2 3 + 100 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + + material + 1 2 + 100 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + + cell + 1 2 3 + 100 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + + diff --git a/tests/regression_tests/volume_calc/inputs_true_mg.dat b/tests/regression_tests/volume_calc/inputs_true_mg.dat index 21c2a9834..f114bd8c2 100644 --- a/tests/regression_tests/volume_calc/inputs_true_mg.dat +++ b/tests/regression_tests/volume_calc/inputs_true_mg.dat @@ -1,76 +1,76 @@ - - - - - - - - - - - - - mg_lib.h5 - - - - - - - - - - - - - - - volume - multi-group - - cell - 1 2 3 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - material - 1 2 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - universe - 0 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - cell - 1 2 3 - 100 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - - material - 1 2 - 100 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - - cell - 1 2 3 - 100 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - + + + mg_lib.h5 + + + + + + + + + + + + + + + + + + + + + + + + volume + multi-group + + cell + 1 2 3 + 100000 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + material + 1 2 + 100000 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + universe + 0 + 100000 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + cell + 1 2 3 + 100 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + + material + 1 2 + 100 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + + cell + 1 2 3 + 100 + -1.0 -1.0 -6.0 + 1.0 1.0 6.0 + + + + diff --git a/tests/regression_tests/volume_calc/test.py b/tests/regression_tests/volume_calc/test.py index e04eac7ff..c94d16c79 100644 --- a/tests/regression_tests/volume_calc/test.py +++ b/tests/regression_tests/volume_calc/test.py @@ -21,7 +21,6 @@ class VolumeTest(PyAPITestHarness): if not is_ce: self.inputs_true = 'inputs_true_mg.dat' - def _build_inputs(self): # Define materials water = openmc.Material(1) water.add_nuclide('H1', 2.0) @@ -39,7 +38,7 @@ class VolumeTest(PyAPITestHarness): materials = openmc.Materials((water, fuel)) if not self.is_ce: materials.cross_sections = 'mg_lib.h5' - materials.export_to_xml() + self._model.materials = materials cyl = openmc.ZCylinder(surface_id=1, r=1.0, boundary_type='vacuum') top_sphere = openmc.Sphere(surface_id=2, z0=5., r=1., boundary_type='vacuum') @@ -53,8 +52,7 @@ class VolumeTest(PyAPITestHarness): bottom_hemisphere = openmc.Cell(3, fill=water, region=-bottom_sphere & -top_plane) root = openmc.Universe(0, cells=(inside_cyl, top_hemisphere, bottom_hemisphere)) - geometry = openmc.Geometry(root) - geometry.export_to_xml() + self._model.geometry = openmc.Geometry(root) # Set up stochastic volume calculation ll, ur = root.bounding_box @@ -79,7 +77,7 @@ class VolumeTest(PyAPITestHarness): if not self.is_ce: settings.energy_mode = 'multi-group' settings.volume_calculations = vol_calcs - settings.export_to_xml() + self._model.settings = settings # Create the MGXS file if necessary if not self.is_ce: @@ -170,5 +168,5 @@ class VolumeTest(PyAPITestHarness): @pytest.mark.parametrize('is_ce', [True, False]) def test_volume_calc(is_ce): - harness = VolumeTest(is_ce, '') + harness = VolumeTest(is_ce, '', model=openmc.Model()) harness.main() diff --git a/tests/regression_tests/weightwindows/inputs_true.dat b/tests/regression_tests/weightwindows/inputs_true.dat index eb42baddf..16f03a4a0 100644 --- a/tests/regression_tests/weightwindows/inputs_true.dat +++ b/tests/regression_tests/weightwindows/inputs_true.dat @@ -1,96 +1,95 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 200 - 2 - - - 0.001 0.001 0.001 - - - 14000000.0 1.0 - - - true - - 2 - neutron - 0.0 0.5 20000000.0 - -1.0 0.007673145137236567 6.542700644645627e-07 0.0017541380096893788 0.0007245451610090619 7.476545089278482e-06 2.253382683081525e-06 2.1040609012865134e-05 0.08285899874014539 -1.0 1.0262431550731535e-13 3.3164825349503764e-16 0.0064803314120165335 3.5981031766416143e-06 -1.0 1.6205064883026195e-11 1.7770136411255912e-05 0.0001670700632870335 4.323138781337963e-05 -1.0 -1.0 6.922231352729155e-05 0.06550426960512012 -1.0 2.5639656866250453e-06 1.4508262073256659e-13 -1.0 -1.0 0.0009127050763987511 3.8523247550378815e-12 -1.0 0.0008175033526488423 -1.0 0.015148978428271613 2.5157355790201773e-07 2.1612150425221703e-06 1.3181562352445092e-10 2.9282097947816224e-05 2.762955748645507e-05 2.936268747135548e-14 1.6859219614058024e-19 3.937160538176268e-07 2.6011787393916806e-06 0.001570829313580841 -1.0 1.7041669224797384e-09 1.6421491993751715e-11 0.4899999304038166 6.948292975998466e-07 -1.0 -1.0 0.08657573566388353 0.006639379668946672 1.681305446488884e-11 2.2487617828938326e-05 4.109066205029878e-05 0.08288806458368345 -1.0 0.007385384405891666 -1.0 -1.0 1.008394964750947e-06 6.655926357459275e-08 0.0016279794552427574 1.4825219199133353e-12 -1.0 1.93847081892941e-05 1.284759166582202e-05 5.1161740516205715e-05 2.5447281241730366e-07 3.853097455417877e-06 -1.0 8.887234042637684e-05 0.01621821782442112 -1.0 1.8747824667478637e-14 5.97653814110781e-06 -1.0 -1.0 1.2296747260635405e-06 -1.0 -1.0 7.754700849337902e-06 7.091263906557291e-05 3.2799045883372075e-06 0.00020573181450240786 5.6949597066784976e-05 1.271128669411295e-07 0.0010019432401508087 -1.0 -1.0 6.848642863465585e-07 5.783974359937857e-06 2.380955631371226e-06 4.756872959630257e-05 2.1360401784344975e-18 0.00046029617115127556 1.0092905083158804e-11 0.08095280568305474 3.89841667138598e-08 4.354946981329799e-05 -1.0 0.5 0.0015447823995470042 -1.0 -1.0 0.001959411999677113 0.48573842213878143 -1.0 7.962899789920809e-06 5.619835883512353e-14 0.0835648710074336 2.7207433165796702e-11 0.00027464244062887683 4.076762579823379e-17 2.124999182004655e-05 8.037131813528501e-07 8.846493399850663e-06 1.080711295768551e-05 -1.0 -1.0 0.0010737081832502356 2.679340942769232e-06 2.1648918040467363e-05 0.0002668579837809081 1.3455341306162382e-05 2.5629068330446215e-05 1.3228013765525015e-05 -1.0 -1.0 7.002861620919232e-08 1.5172912057312398e-14 -1.0 7.989579285134734e-06 2.639268952045579e-10 -1.0 0.013330619853379314 0.00021534568699157805 2.4469456008493614e-09 8.211982683649991e-09 1.951356547084204e-15 0.00016419031150495913 5.985108617124989e-06 1.28584557092134e-05 1.5476769237571295e-14 5.5379154134462336e-08 0.0016637126543321873 2.499931357628383e-07 8.020767115181574e-07 2.7697233171399416e-13 -1.0 0.007197662162700777 -1.0 0.0833931797381589 2.8226276944532696e-05 3.353295403842037e-05 5.504813693036933e-12 0.007136750029575816 0.08636569925236791 -1.0 -1.0 6.315154082213375e-07 0.4877856021170283 -1.0 3.7051518220083886e-06 -1.0 0.0017950613169359904 7.84289689494925e-06 9.041149893307806e-07 -1.0 8.48176145671274e-10 9.03108551826469e-05 3.634644995026692e-05 2.0295213621716706e-09 1.0305672698745657e-11 1.5550455959178486e-06 0.01664109232689093 8.533030345699353e-17 0.0009252532821720597 -1.0 7.695031155172816e-14 0.0007151459162818186 -1.0 -1.0 5.182269672663266e-10 3.0160758454323657e-07 -1.0 0.06539005235506369 3.452537179033895e-05 -1.0 -1.0 3.855884234344845e-06 0.00017699858357744463 2.594951085377588e-06 1.1333627604823673e-09 -1.0 2.4306375693722205e-06 0.0063790654507599135 2.2060992580622125e-11 -1.0 -1.0 0.0848872967381878 3.932389299316285e-06 1.2911827198500372e-08 1.957092814065688e-05 0.0007213722022489493 0.0018327593437608 1.6699254277734109e-06 0.007188410694198128 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 - -10.0 0.07673145137236567 6.5427006446456266e-06 0.017541380096893787 0.0072454516100906195 7.476545089278483e-05 2.253382683081525e-05 0.00021040609012865135 0.828589987401454 -10.0 1.0262431550731535e-12 3.3164825349503764e-15 0.06480331412016534 3.5981031766416144e-05 -10.0 1.6205064883026195e-10 0.0001777013641125591 0.001670700632870335 0.0004323138781337963 -10.0 -10.0 0.0006922231352729155 0.6550426960512012 -10.0 2.5639656866250452e-05 1.4508262073256658e-12 -10.0 -10.0 0.009127050763987512 3.852324755037882e-11 -10.0 0.008175033526488424 -10.0 0.15148978428271614 2.515735579020177e-06 2.1612150425221703e-05 1.3181562352445092e-09 0.00029282097947816227 0.0002762955748645507 2.9362687471355483e-13 1.6859219614058023e-18 3.937160538176268e-06 2.6011787393916804e-05 0.015708293135808408 -10.0 1.7041669224797384e-08 1.6421491993751715e-10 4.899999304038166 6.948292975998466e-06 -10.0 -10.0 0.8657573566388354 0.06639379668946672 1.681305446488884e-10 0.00022487617828938325 0.0004109066205029878 0.8288806458368345 -10.0 0.07385384405891665 -10.0 -10.0 1.0083949647509469e-05 6.655926357459275e-07 0.016279794552427576 1.4825219199133352e-11 -10.0 0.000193847081892941 0.0001284759166582202 0.0005116174051620571 2.5447281241730365e-06 3.853097455417877e-05 -10.0 0.0008887234042637684 0.16218217824421122 -10.0 1.8747824667478637e-13 5.97653814110781e-05 -10.0 -10.0 1.2296747260635405e-05 -10.0 -10.0 7.754700849337902e-05 0.0007091263906557291 3.2799045883372076e-05 0.0020573181450240785 0.0005694959706678497 1.271128669411295e-06 0.010019432401508087 -10.0 -10.0 6.848642863465585e-06 5.7839743599378564e-05 2.380955631371226e-05 0.0004756872959630257 2.1360401784344976e-17 0.004602961711512756 1.0092905083158804e-10 0.8095280568305474 3.89841667138598e-07 0.00043549469813297995 -10.0 5.0 0.015447823995470043 -10.0 -10.0 0.01959411999677113 4.8573842213878144 -10.0 7.96289978992081e-05 5.619835883512353e-13 0.8356487100743359 2.7207433165796704e-10 0.002746424406288768 4.076762579823379e-16 0.00021249991820046548 8.037131813528501e-06 8.846493399850663e-05 0.0001080711295768551 -10.0 -10.0 0.010737081832502356 2.679340942769232e-05 0.00021648918040467362 0.0026685798378090807 0.00013455341306162382 0.00025629068330446217 0.00013228013765525016 -10.0 -10.0 7.002861620919232e-07 1.51729120573124e-13 -10.0 7.989579285134734e-05 2.639268952045579e-09 -10.0 0.13330619853379314 0.0021534568699157807 2.4469456008493615e-08 8.211982683649991e-08 1.951356547084204e-14 0.0016419031150495913 5.985108617124989e-05 0.000128584557092134 1.5476769237571296e-13 5.537915413446234e-07 0.016637126543321872 2.499931357628383e-06 8.020767115181574e-06 2.7697233171399415e-12 -10.0 0.07197662162700777 -10.0 0.8339317973815891 0.000282262769445327 0.00033532954038420373 5.504813693036933e-11 0.07136750029575815 0.8636569925236791 -10.0 -10.0 6.3151540822133754e-06 4.877856021170283 -10.0 3.7051518220083885e-05 -10.0 0.017950613169359905 7.84289689494925e-05 9.041149893307805e-06 -10.0 8.48176145671274e-09 0.000903108551826469 0.0003634644995026692 2.0295213621716707e-08 1.0305672698745658e-10 1.5550455959178486e-05 0.1664109232689093 8.533030345699353e-16 0.009252532821720597 -10.0 7.695031155172816e-13 0.007151459162818186 -10.0 -10.0 5.182269672663266e-09 3.0160758454323656e-06 -10.0 0.6539005235506369 0.0003452537179033895 -10.0 -10.0 3.855884234344845e-05 0.0017699858357744464 2.594951085377588e-05 1.1333627604823672e-08 -10.0 2.4306375693722206e-05 0.06379065450759913 2.2060992580622125e-10 -10.0 -10.0 0.848872967381878 3.9323892993162844e-05 1.2911827198500372e-07 0.0001957092814065688 0.0072137220224894934 0.018327593437608 1.669925427773411e-05 0.07188410694198127 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 - 3 - 1.5 - 10 - 1e-38 - - - 5 6 7 - -240 -240 -240 - 240 240 240 - - - 2 - neutron - 0.0 0.5 20000000.0 - -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 0.06827568359008944 0.00017329528628152923 0.018541112907970003 0.011113024641218336 8.76041935303527e-05 8.168081568291806e-05 0.00046693784586018913 0.4952432605379829 2.2512327083641865e-10 4.6258592060517866e-07 2.7044817176109556e-05 0.054902816619122045 0.00014126153603265097 8.304845400451923e-08 2.2950716170641463e-05 0.0001335621430311088 0.003432919201293737 0.0005197081842709918 5.726152701849347e-16 -1.0 0.0013332554437480327 0.4346984808472855 7.691527781829036e-17 0.00011042047857307253 3.0571050855707084e-06 -1.0 4.986698316296507e-06 0.011128424196387618 1.3106335518133802e-05 5.447493368067179e-10 0.011440381012864086 4.670673837764874e-08 0.12364069326350118 0.00012558879474108074 3.136829920007009e-05 2.34750482787598e-05 0.001537590300149361 0.0017693279949094218 6.717625881826167e-05 4.587143797469485e-08 2.6211239246796104e-05 0.00030002326388383244 0.01729816946709781 4.5757238372058234e-11 6.92296299242814e-05 3.792209399652396e-06 -1.0 9.256616392487858e-05 8.541606727879512e-07 -1.0 0.49317081643076643 0.05500108683629957 1.298062961617927e-05 0.0006870228272606287 0.0008231482263927564 0.5 3.419181071650816e-06 0.06433819434431046 6.574706543646946e-16 4.0404626147344e-13 0.0003782322077390033 0.00012637534695610975 0.017602971074583987 1.0044390728858277e-05 -1.0 0.0008787411098754915 0.00023686818807101741 0.0009304497896205121 6.949587369646497e-05 0.00012918433677593975 2.0707648529746894e-06 0.0023295401596005313 0.11819165666519223 -1.0 2.1606550732170693e-05 0.00022057970761624768 -1.0 1.0325207105027347e-08 0.0002029396545382813 2.1234980618763222e-13 -1.0 0.00024175998138228048 0.001178616843705956 0.0001399807456616496 0.0038811025614225057 0.0011076796092102186 0.00010814452764860558 0.010955637485319249 -1.0 9.382800796426366e-17 5.098747893974248e-05 0.00027052054298385255 0.00021305826462238593 0.000808100901275472 4.233410073487772e-06 0.0051513292132259495 8.616027294555462e-07 0.4873897581604287 2.9093345975075226e-05 0.000469589568463265 -1.0 -1.0 0.017802624844035688 1.3116807133030035e-15 2.617878055106949e-16 0.01884234453311008 -1.0 2.027381220364608e-16 0.0004299195570308035 1.4628847959717225e-05 0.4899952354672477 2.774067049392004e-07 0.004441328419270369 4.279460329782799e-09 0.0012297303081805393 0.0002792896409558745 0.0006934466049804711 8.370896020975689e-05 3.8270536025799805e-15 -1.0 0.01208261392046878 0.0001497958445994315 0.0015016500045374082 0.005384625561469684 0.00025519632243117644 0.0011028020390507682 0.0002362355168421952 -1.0 -1.0 8.862760180332873e-05 1.3806577785135177e-06 -1.0 0.0001319677450153934 2.6866894852481906e-05 -1.0 0.11510120013926417 0.002672923773363389 1.2257360246712472e-05 8.544159282151438e-05 2.777791741571174e-05 0.0014957033281168012 0.0003257646134837451 0.0008919466185572302 1.2907171695294846e-13 4.6842350882367666e-05 0.01721806295736377 0.00025106741008066317 0.00022234471595443313 2.101790478097517e-09 5.752120832330886e-11 0.06428782790571179 3.2478301680021854e-08 0.4903495510314233 0.001146714816952061 0.0004777967757842694 1.0882011018684852e-06 0.05708498338352203 0.4981497862127628 -1.0 3.2790914744011534e-06 0.00010077009726691265 -1.0 2.210707325798542e-07 4.3166052799897375e-05 -1.0 0.01825795827020865 0.0003182108781955478 3.8561696337086434e-05 1.0995322456277382e-06 9.53380658669839e-06 0.001550036616828061 0.0012648333883989995 5.272021975060514e-06 1.9257248009114363e-05 0.00016757997590048827 0.11891251244906934 5.515522196186723e-06 0.01102706140784316 9.904481358675478e-13 3.520674728719278e-05 0.011294708566804167 7.239087311622819e-08 -1.0 3.5740607788414942e-06 0.00035983547999740665 1.0588257623722672e-07 0.42372713683725016 0.0011273340972061078 8.582011716859219e-15 1.1514579117272292e-10 0.00043130977711323417 0.0027847329307350423 0.00017287873387910357 6.401055165502384e-06 1.722191123879782e-08 0.00020848309220162036 0.05639071613735579 1.8064550990294753e-05 1.289814511028015e-06 1.078687446476881e-14 0.4897735047310072 0.0002981891705231209 0.00016079768514218546 9.332371598523186e-05 0.011724714376848187 0.019040707071165303 0.00014242053195529864 0.06684484191345574 -1.0 - -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 0.6827568359008944 0.0017329528628152924 0.18541112907970003 0.11113024641218336 0.0008760419353035269 0.0008168081568291806 0.004669378458601891 4.952432605379829 2.2512327083641864e-09 4.625859206051786e-06 0.00027044817176109554 0.5490281661912204 0.0014126153603265096 8.304845400451923e-07 0.00022950716170641464 0.001335621430311088 0.03432919201293737 0.0051970818427099184 5.726152701849347e-15 -10.0 0.013332554437480326 4.346984808472855 7.6915277818290365e-16 0.0011042047857307254 3.0571050855707086e-05 -10.0 4.986698316296507e-05 0.11128424196387618 0.000131063355181338 5.447493368067179e-09 0.11440381012864086 4.670673837764874e-07 1.2364069326350118 0.0012558879474108074 0.0003136829920007009 0.000234750482787598 0.01537590300149361 0.01769327994909422 0.0006717625881826168 4.587143797469485e-07 0.000262112392467961 0.0030002326388383245 0.1729816946709781 4.5757238372058235e-10 0.0006922962992428139 3.792209399652396e-05 -10.0 0.0009256616392487858 8.541606727879512e-06 -10.0 4.931708164307665 0.5500108683629957 0.00012980629616179268 0.006870228272606287 0.008231482263927564 5.0 3.419181071650816e-05 0.6433819434431045 6.574706543646946e-15 4.0404626147344005e-12 0.003782322077390033 0.0012637534695610975 0.17602971074583987 0.00010044390728858278 -10.0 0.008787411098754914 0.002368681880710174 0.00930449789620512 0.0006949587369646498 0.0012918433677593976 2.0707648529746893e-05 0.023295401596005315 1.1819165666519222 -10.0 0.00021606550732170693 0.0022057970761624767 -10.0 1.0325207105027347e-07 0.0020293965453828133 2.123498061876322e-12 -10.0 0.0024175998138228046 0.01178616843705956 0.0013998074566164962 0.03881102561422506 0.011076796092102187 0.0010814452764860557 0.10955637485319249 -10.0 9.382800796426367e-16 0.0005098747893974248 0.0027052054298385255 0.0021305826462238594 0.00808100901275472 4.233410073487772e-05 0.0515132921322595 8.61602729455546e-06 4.873897581604287 0.0002909334597507523 0.0046958956846326495 -10.0 -10.0 0.1780262484403569 1.3116807133030034e-14 2.6178780551069492e-15 0.1884234453311008 -10.0 2.027381220364608e-15 0.004299195570308035 0.00014628847959717226 4.899952354672477 2.774067049392004e-06 0.04441328419270369 4.279460329782799e-08 0.012297303081805393 0.002792896409558745 0.006934466049804711 0.0008370896020975689 3.8270536025799805e-14 -10.0 0.1208261392046878 0.001497958445994315 0.015016500045374082 0.05384625561469684 0.0025519632243117644 0.011028020390507681 0.002362355168421952 -10.0 -10.0 0.0008862760180332873 1.3806577785135176e-05 -10.0 0.001319677450153934 0.00026866894852481903 -10.0 1.1510120013926417 0.026729237733633893 0.00012257360246712473 0.0008544159282151438 0.0002777791741571174 0.014957033281168012 0.0032576461348374514 0.008919466185572301 1.2907171695294846e-12 0.00046842350882367664 0.17218062957363772 0.0025106741008066318 0.0022234471595443312 2.101790478097517e-08 5.752120832330886e-10 0.6428782790571179 3.2478301680021856e-07 4.903495510314233 0.01146714816952061 0.004777967757842694 1.0882011018684853e-05 0.5708498338352204 4.981497862127628 -10.0 3.279091474401153e-05 0.0010077009726691265 -10.0 2.210707325798542e-06 0.00043166052799897375 -10.0 0.1825795827020865 0.0031821087819554777 0.00038561696337086434 1.0995322456277382e-05 9.53380658669839e-05 0.01550036616828061 0.012648333883989995 5.272021975060514e-05 0.00019257248009114364 0.0016757997590048828 1.1891251244906933 5.515522196186723e-05 0.1102706140784316 9.904481358675478e-12 0.0003520674728719278 0.11294708566804167 7.239087311622819e-07 -10.0 3.574060778841494e-05 0.0035983547999740664 1.0588257623722672e-06 4.237271368372502 0.011273340972061077 8.582011716859219e-14 1.151457911727229e-09 0.004313097771132342 0.027847329307350423 0.0017287873387910357 6.401055165502385e-05 1.722191123879782e-07 0.0020848309220162036 0.5639071613735579 0.00018064550990294753 1.289814511028015e-05 1.078687446476881e-13 4.897735047310072 0.002981891705231209 0.0016079768514218546 0.0009332371598523186 0.11724714376848187 0.19040707071165303 0.0014242053195529865 0.6684484191345574 -10.0 - 3 - 1.5 - 10 - 1e-38 - - 200 - - - - - 5 10 15 - -240 -240 -240 - 240 240 240 - - - 1 - - - 0.0 0.5 20000000.0 - - - neutron photon - - - 1 2 3 - flux - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed source + 200 + 2 + + + 0.001 0.001 0.001 + + + 14000000.0 1.0 + + + true + + 2 + neutron + 0.0 0.5 20000000.0 + -1.0 0.007673145137236567 6.542700644645627e-07 0.0017541380096893788 0.0007245451610090619 7.476545089278482e-06 2.253382683081525e-06 2.1040609012865134e-05 0.08285899874014539 -1.0 1.0262431550731535e-13 3.3164825349503764e-16 0.0064803314120165335 3.5981031766416143e-06 -1.0 1.6205064883026195e-11 1.7770136411255912e-05 0.0001670700632870335 4.323138781337963e-05 -1.0 -1.0 6.922231352729155e-05 0.06550426960512012 -1.0 2.5639656866250453e-06 1.4508262073256659e-13 -1.0 -1.0 0.0009127050763987511 3.8523247550378815e-12 -1.0 0.0008175033526488423 -1.0 0.015148978428271613 2.5157355790201773e-07 2.1612150425221703e-06 1.3181562352445092e-10 2.9282097947816224e-05 2.762955748645507e-05 2.936268747135548e-14 1.6859219614058024e-19 3.937160538176268e-07 2.6011787393916806e-06 0.001570829313580841 -1.0 1.7041669224797384e-09 1.6421491993751715e-11 0.4899999304038166 6.948292975998466e-07 -1.0 -1.0 0.08657573566388353 0.006639379668946672 1.681305446488884e-11 2.2487617828938326e-05 4.109066205029878e-05 0.08288806458368345 -1.0 0.007385384405891666 -1.0 -1.0 1.008394964750947e-06 6.655926357459275e-08 0.0016279794552427574 1.4825219199133353e-12 -1.0 1.93847081892941e-05 1.284759166582202e-05 5.1161740516205715e-05 2.5447281241730366e-07 3.853097455417877e-06 -1.0 8.887234042637684e-05 0.01621821782442112 -1.0 1.8747824667478637e-14 5.97653814110781e-06 -1.0 -1.0 1.2296747260635405e-06 -1.0 -1.0 7.754700849337902e-06 7.091263906557291e-05 3.2799045883372075e-06 0.00020573181450240786 5.6949597066784976e-05 1.271128669411295e-07 0.0010019432401508087 -1.0 -1.0 6.848642863465585e-07 5.783974359937857e-06 2.380955631371226e-06 4.756872959630257e-05 2.1360401784344975e-18 0.00046029617115127556 1.0092905083158804e-11 0.08095280568305474 3.89841667138598e-08 4.354946981329799e-05 -1.0 0.5 0.0015447823995470042 -1.0 -1.0 0.001959411999677113 0.48573842213878143 -1.0 7.962899789920809e-06 5.619835883512353e-14 0.0835648710074336 2.7207433165796702e-11 0.00027464244062887683 4.076762579823379e-17 2.124999182004655e-05 8.037131813528501e-07 8.846493399850663e-06 1.080711295768551e-05 -1.0 -1.0 0.0010737081832502356 2.679340942769232e-06 2.1648918040467363e-05 0.0002668579837809081 1.3455341306162382e-05 2.5629068330446215e-05 1.3228013765525015e-05 -1.0 -1.0 7.002861620919232e-08 1.5172912057312398e-14 -1.0 7.989579285134734e-06 2.639268952045579e-10 -1.0 0.013330619853379314 0.00021534568699157805 2.4469456008493614e-09 8.211982683649991e-09 1.951356547084204e-15 0.00016419031150495913 5.985108617124989e-06 1.28584557092134e-05 1.5476769237571295e-14 5.5379154134462336e-08 0.0016637126543321873 2.499931357628383e-07 8.020767115181574e-07 2.7697233171399416e-13 -1.0 0.007197662162700777 -1.0 0.0833931797381589 2.8226276944532696e-05 3.353295403842037e-05 5.504813693036933e-12 0.007136750029575816 0.08636569925236791 -1.0 -1.0 6.315154082213375e-07 0.4877856021170283 -1.0 3.7051518220083886e-06 -1.0 0.0017950613169359904 7.84289689494925e-06 9.041149893307806e-07 -1.0 8.48176145671274e-10 9.03108551826469e-05 3.634644995026692e-05 2.0295213621716706e-09 1.0305672698745657e-11 1.5550455959178486e-06 0.01664109232689093 8.533030345699353e-17 0.0009252532821720597 -1.0 7.695031155172816e-14 0.0007151459162818186 -1.0 -1.0 5.182269672663266e-10 3.0160758454323657e-07 -1.0 0.06539005235506369 3.452537179033895e-05 -1.0 -1.0 3.855884234344845e-06 0.00017699858357744463 2.594951085377588e-06 1.1333627604823673e-09 -1.0 2.4306375693722205e-06 0.0063790654507599135 2.2060992580622125e-11 -1.0 -1.0 0.0848872967381878 3.932389299316285e-06 1.2911827198500372e-08 1.957092814065688e-05 0.0007213722022489493 0.0018327593437608 1.6699254277734109e-06 0.007188410694198128 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 + -10.0 0.07673145137236567 6.5427006446456266e-06 0.017541380096893787 0.0072454516100906195 7.476545089278483e-05 2.253382683081525e-05 0.00021040609012865135 0.828589987401454 -10.0 1.0262431550731535e-12 3.3164825349503764e-15 0.06480331412016534 3.5981031766416144e-05 -10.0 1.6205064883026195e-10 0.0001777013641125591 0.001670700632870335 0.0004323138781337963 -10.0 -10.0 0.0006922231352729155 0.6550426960512012 -10.0 2.5639656866250452e-05 1.4508262073256658e-12 -10.0 -10.0 0.009127050763987512 3.852324755037882e-11 -10.0 0.008175033526488424 -10.0 0.15148978428271614 2.515735579020177e-06 2.1612150425221703e-05 1.3181562352445092e-09 0.00029282097947816227 0.0002762955748645507 2.9362687471355483e-13 1.6859219614058023e-18 3.937160538176268e-06 2.6011787393916804e-05 0.015708293135808408 -10.0 1.7041669224797384e-08 1.6421491993751715e-10 4.899999304038166 6.948292975998466e-06 -10.0 -10.0 0.8657573566388354 0.06639379668946672 1.681305446488884e-10 0.00022487617828938325 0.0004109066205029878 0.8288806458368345 -10.0 0.07385384405891665 -10.0 -10.0 1.0083949647509469e-05 6.655926357459275e-07 0.016279794552427576 1.4825219199133352e-11 -10.0 0.000193847081892941 0.0001284759166582202 0.0005116174051620571 2.5447281241730365e-06 3.853097455417877e-05 -10.0 0.0008887234042637684 0.16218217824421122 -10.0 1.8747824667478637e-13 5.97653814110781e-05 -10.0 -10.0 1.2296747260635405e-05 -10.0 -10.0 7.754700849337902e-05 0.0007091263906557291 3.2799045883372076e-05 0.0020573181450240785 0.0005694959706678497 1.271128669411295e-06 0.010019432401508087 -10.0 -10.0 6.848642863465585e-06 5.7839743599378564e-05 2.380955631371226e-05 0.0004756872959630257 2.1360401784344976e-17 0.004602961711512756 1.0092905083158804e-10 0.8095280568305474 3.89841667138598e-07 0.00043549469813297995 -10.0 5.0 0.015447823995470043 -10.0 -10.0 0.01959411999677113 4.8573842213878144 -10.0 7.96289978992081e-05 5.619835883512353e-13 0.8356487100743359 2.7207433165796704e-10 0.002746424406288768 4.076762579823379e-16 0.00021249991820046548 8.037131813528501e-06 8.846493399850663e-05 0.0001080711295768551 -10.0 -10.0 0.010737081832502356 2.679340942769232e-05 0.00021648918040467362 0.0026685798378090807 0.00013455341306162382 0.00025629068330446217 0.00013228013765525016 -10.0 -10.0 7.002861620919232e-07 1.51729120573124e-13 -10.0 7.989579285134734e-05 2.639268952045579e-09 -10.0 0.13330619853379314 0.0021534568699157807 2.4469456008493615e-08 8.211982683649991e-08 1.951356547084204e-14 0.0016419031150495913 5.985108617124989e-05 0.000128584557092134 1.5476769237571296e-13 5.537915413446234e-07 0.016637126543321872 2.499931357628383e-06 8.020767115181574e-06 2.7697233171399415e-12 -10.0 0.07197662162700777 -10.0 0.8339317973815891 0.000282262769445327 0.00033532954038420373 5.504813693036933e-11 0.07136750029575815 0.8636569925236791 -10.0 -10.0 6.3151540822133754e-06 4.877856021170283 -10.0 3.7051518220083885e-05 -10.0 0.017950613169359905 7.84289689494925e-05 9.041149893307805e-06 -10.0 8.48176145671274e-09 0.000903108551826469 0.0003634644995026692 2.0295213621716707e-08 1.0305672698745658e-10 1.5550455959178486e-05 0.1664109232689093 8.533030345699353e-16 0.009252532821720597 -10.0 7.695031155172816e-13 0.007151459162818186 -10.0 -10.0 5.182269672663266e-09 3.0160758454323656e-06 -10.0 0.6539005235506369 0.0003452537179033895 -10.0 -10.0 3.855884234344845e-05 0.0017699858357744464 2.594951085377588e-05 1.1333627604823672e-08 -10.0 2.4306375693722206e-05 0.06379065450759913 2.2060992580622125e-10 -10.0 -10.0 0.848872967381878 3.9323892993162844e-05 1.2911827198500372e-07 0.0001957092814065688 0.0072137220224894934 0.018327593437608 1.669925427773411e-05 0.07188410694198127 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 + 3 + 1.5 + 10 + 1e-38 + + + 5 6 7 + -240 -240 -240 + 240 240 240 + + + 2 + neutron + 0.0 0.5 20000000.0 + -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 0.06827568359008944 0.00017329528628152923 0.018541112907970003 0.011113024641218336 8.76041935303527e-05 8.168081568291806e-05 0.00046693784586018913 0.4952432605379829 2.2512327083641865e-10 4.6258592060517866e-07 2.7044817176109556e-05 0.054902816619122045 0.00014126153603265097 8.304845400451923e-08 2.2950716170641463e-05 0.0001335621430311088 0.003432919201293737 0.0005197081842709918 5.726152701849347e-16 -1.0 0.0013332554437480327 0.4346984808472855 7.691527781829036e-17 0.00011042047857307253 3.0571050855707084e-06 -1.0 4.986698316296507e-06 0.011128424196387618 1.3106335518133802e-05 5.447493368067179e-10 0.011440381012864086 4.670673837764874e-08 0.12364069326350118 0.00012558879474108074 3.136829920007009e-05 2.34750482787598e-05 0.001537590300149361 0.0017693279949094218 6.717625881826167e-05 4.587143797469485e-08 2.6211239246796104e-05 0.00030002326388383244 0.01729816946709781 4.5757238372058234e-11 6.92296299242814e-05 3.792209399652396e-06 -1.0 9.256616392487858e-05 8.541606727879512e-07 -1.0 0.49317081643076643 0.05500108683629957 1.298062961617927e-05 0.0006870228272606287 0.0008231482263927564 0.5 3.419181071650816e-06 0.06433819434431046 6.574706543646946e-16 4.0404626147344e-13 0.0003782322077390033 0.00012637534695610975 0.017602971074583987 1.0044390728858277e-05 -1.0 0.0008787411098754915 0.00023686818807101741 0.0009304497896205121 6.949587369646497e-05 0.00012918433677593975 2.0707648529746894e-06 0.0023295401596005313 0.11819165666519223 -1.0 2.1606550732170693e-05 0.00022057970761624768 -1.0 1.0325207105027347e-08 0.0002029396545382813 2.1234980618763222e-13 -1.0 0.00024175998138228048 0.001178616843705956 0.0001399807456616496 0.0038811025614225057 0.0011076796092102186 0.00010814452764860558 0.010955637485319249 -1.0 9.382800796426366e-17 5.098747893974248e-05 0.00027052054298385255 0.00021305826462238593 0.000808100901275472 4.233410073487772e-06 0.0051513292132259495 8.616027294555462e-07 0.4873897581604287 2.9093345975075226e-05 0.000469589568463265 -1.0 -1.0 0.017802624844035688 1.3116807133030035e-15 2.617878055106949e-16 0.01884234453311008 -1.0 2.027381220364608e-16 0.0004299195570308035 1.4628847959717225e-05 0.4899952354672477 2.774067049392004e-07 0.004441328419270369 4.279460329782799e-09 0.0012297303081805393 0.0002792896409558745 0.0006934466049804711 8.370896020975689e-05 3.8270536025799805e-15 -1.0 0.01208261392046878 0.0001497958445994315 0.0015016500045374082 0.005384625561469684 0.00025519632243117644 0.0011028020390507682 0.0002362355168421952 -1.0 -1.0 8.862760180332873e-05 1.3806577785135177e-06 -1.0 0.0001319677450153934 2.6866894852481906e-05 -1.0 0.11510120013926417 0.002672923773363389 1.2257360246712472e-05 8.544159282151438e-05 2.777791741571174e-05 0.0014957033281168012 0.0003257646134837451 0.0008919466185572302 1.2907171695294846e-13 4.6842350882367666e-05 0.01721806295736377 0.00025106741008066317 0.00022234471595443313 2.101790478097517e-09 5.752120832330886e-11 0.06428782790571179 3.2478301680021854e-08 0.4903495510314233 0.001146714816952061 0.0004777967757842694 1.0882011018684852e-06 0.05708498338352203 0.4981497862127628 -1.0 3.2790914744011534e-06 0.00010077009726691265 -1.0 2.210707325798542e-07 4.3166052799897375e-05 -1.0 0.01825795827020865 0.0003182108781955478 3.8561696337086434e-05 1.0995322456277382e-06 9.53380658669839e-06 0.001550036616828061 0.0012648333883989995 5.272021975060514e-06 1.9257248009114363e-05 0.00016757997590048827 0.11891251244906934 5.515522196186723e-06 0.01102706140784316 9.904481358675478e-13 3.520674728719278e-05 0.011294708566804167 7.239087311622819e-08 -1.0 3.5740607788414942e-06 0.00035983547999740665 1.0588257623722672e-07 0.42372713683725016 0.0011273340972061078 8.582011716859219e-15 1.1514579117272292e-10 0.00043130977711323417 0.0027847329307350423 0.00017287873387910357 6.401055165502384e-06 1.722191123879782e-08 0.00020848309220162036 0.05639071613735579 1.8064550990294753e-05 1.289814511028015e-06 1.078687446476881e-14 0.4897735047310072 0.0002981891705231209 0.00016079768514218546 9.332371598523186e-05 0.011724714376848187 0.019040707071165303 0.00014242053195529864 0.06684484191345574 -1.0 + -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 -10.0 0.6827568359008944 0.0017329528628152924 0.18541112907970003 0.11113024641218336 0.0008760419353035269 0.0008168081568291806 0.004669378458601891 4.952432605379829 2.2512327083641864e-09 4.625859206051786e-06 0.00027044817176109554 0.5490281661912204 0.0014126153603265096 8.304845400451923e-07 0.00022950716170641464 0.001335621430311088 0.03432919201293737 0.0051970818427099184 5.726152701849347e-15 -10.0 0.013332554437480326 4.346984808472855 7.6915277818290365e-16 0.0011042047857307254 3.0571050855707086e-05 -10.0 4.986698316296507e-05 0.11128424196387618 0.000131063355181338 5.447493368067179e-09 0.11440381012864086 4.670673837764874e-07 1.2364069326350118 0.0012558879474108074 0.0003136829920007009 0.000234750482787598 0.01537590300149361 0.01769327994909422 0.0006717625881826168 4.587143797469485e-07 0.000262112392467961 0.0030002326388383245 0.1729816946709781 4.5757238372058235e-10 0.0006922962992428139 3.792209399652396e-05 -10.0 0.0009256616392487858 8.541606727879512e-06 -10.0 4.931708164307665 0.5500108683629957 0.00012980629616179268 0.006870228272606287 0.008231482263927564 5.0 3.419181071650816e-05 0.6433819434431045 6.574706543646946e-15 4.0404626147344005e-12 0.003782322077390033 0.0012637534695610975 0.17602971074583987 0.00010044390728858278 -10.0 0.008787411098754914 0.002368681880710174 0.00930449789620512 0.0006949587369646498 0.0012918433677593976 2.0707648529746893e-05 0.023295401596005315 1.1819165666519222 -10.0 0.00021606550732170693 0.0022057970761624767 -10.0 1.0325207105027347e-07 0.0020293965453828133 2.123498061876322e-12 -10.0 0.0024175998138228046 0.01178616843705956 0.0013998074566164962 0.03881102561422506 0.011076796092102187 0.0010814452764860557 0.10955637485319249 -10.0 9.382800796426367e-16 0.0005098747893974248 0.0027052054298385255 0.0021305826462238594 0.00808100901275472 4.233410073487772e-05 0.0515132921322595 8.61602729455546e-06 4.873897581604287 0.0002909334597507523 0.0046958956846326495 -10.0 -10.0 0.1780262484403569 1.3116807133030034e-14 2.6178780551069492e-15 0.1884234453311008 -10.0 2.027381220364608e-15 0.004299195570308035 0.00014628847959717226 4.899952354672477 2.774067049392004e-06 0.04441328419270369 4.279460329782799e-08 0.012297303081805393 0.002792896409558745 0.006934466049804711 0.0008370896020975689 3.8270536025799805e-14 -10.0 0.1208261392046878 0.001497958445994315 0.015016500045374082 0.05384625561469684 0.0025519632243117644 0.011028020390507681 0.002362355168421952 -10.0 -10.0 0.0008862760180332873 1.3806577785135176e-05 -10.0 0.001319677450153934 0.00026866894852481903 -10.0 1.1510120013926417 0.026729237733633893 0.00012257360246712473 0.0008544159282151438 0.0002777791741571174 0.014957033281168012 0.0032576461348374514 0.008919466185572301 1.2907171695294846e-12 0.00046842350882367664 0.17218062957363772 0.0025106741008066318 0.0022234471595443312 2.101790478097517e-08 5.752120832330886e-10 0.6428782790571179 3.2478301680021856e-07 4.903495510314233 0.01146714816952061 0.004777967757842694 1.0882011018684853e-05 0.5708498338352204 4.981497862127628 -10.0 3.279091474401153e-05 0.0010077009726691265 -10.0 2.210707325798542e-06 0.00043166052799897375 -10.0 0.1825795827020865 0.0031821087819554777 0.00038561696337086434 1.0995322456277382e-05 9.53380658669839e-05 0.01550036616828061 0.012648333883989995 5.272021975060514e-05 0.00019257248009114364 0.0016757997590048828 1.1891251244906933 5.515522196186723e-05 0.1102706140784316 9.904481358675478e-12 0.0003520674728719278 0.11294708566804167 7.239087311622819e-07 -10.0 3.574060778841494e-05 0.0035983547999740664 1.0588257623722672e-06 4.237271368372502 0.011273340972061077 8.582011716859219e-14 1.151457911727229e-09 0.004313097771132342 0.027847329307350423 0.0017287873387910357 6.401055165502385e-05 1.722191123879782e-07 0.0020848309220162036 0.5639071613735579 0.00018064550990294753 1.289814511028015e-05 1.078687446476881e-13 4.897735047310072 0.002981891705231209 0.0016079768514218546 0.0009332371598523186 0.11724714376848187 0.19040707071165303 0.0014242053195529865 0.6684484191345574 -10.0 + 3 + 1.5 + 10 + 1e-38 + + 200 + + + + 5 10 15 + -240 -240 -240 + 240 240 240 + + + 1 + + + 0.0 0.5 20000000.0 + + + neutron photon + + + 1 2 3 + flux + + + diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 0525dd476..157f6e640 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -336,12 +336,11 @@ class PyAPITestHarness(TestHarness): def _build_inputs(self): """Write input XML files.""" - self._model.export_to_xml() + self._model.export_to_model_xml() def _get_inputs(self): """Return a hash digest of the input XML files.""" - xmls = ['geometry.xml', 'materials.xml', 'settings.xml', - 'tallies.xml', 'plots.xml'] + xmls = ['model.xml', 'plots.xml'] return ''.join([open(fname).read() for fname in xmls if os.path.exists(fname)]) @@ -371,7 +370,7 @@ class PyAPITestHarness(TestHarness): """Delete XMLs, statepoints, tally, and test files.""" super()._cleanup() output = ['materials.xml', 'geometry.xml', 'settings.xml', - 'tallies.xml', 'plots.xml', 'inputs_test.dat'] + 'tallies.xml', 'plots.xml', 'inputs_test.dat', 'model.xml'] for f in output: if os.path.exists(f): os.remove(f) From 00657ccf871ba6a4ea4d1d0cdd1ed087ba838120 Mon Sep 17 00:00:00 2001 From: guyshtot Date: Sat, 25 Mar 2023 13:50:06 +0300 Subject: [PATCH 1672/2654] Update openmc/mgxs/library.py apply CR suggestion Co-authored-by: Paul Romano --- openmc/mgxs/library.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 1c3a5dbb4..8ab052b0d 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -548,9 +548,9 @@ class Library: if self.nuclides: if domain_nuclides: mgxs.nuclides = [ - nuclide for nuclide in self.nuclides - if nuclide in domain_nuclides - ] + ["total"] + nuclide for nuclide in self.nuclides + if nuclide in domain_nuclides + ] + ["total"] else: mgxs.nuclides = self.nuclides From ff9d2283c428a0fe435c5fc2867426f818d18d21 Mon Sep 17 00:00:00 2001 From: guyshtot Date: Sat, 25 Mar 2023 13:52:23 +0300 Subject: [PATCH 1673/2654] Update tests/regression_tests/mgxs_library_specific_nuclides/test.py Remove double spaces at MGXS types in a test Co-authored-by: Paul Romano --- .../regression_tests/mgxs_library_specific_nuclides/test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/test.py b/tests/regression_tests/mgxs_library_specific_nuclides/test.py index 41ae0a689..e749ca137 100644 --- a/tests/regression_tests/mgxs_library_specific_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_specific_nuclides/test.py @@ -25,9 +25,9 @@ class MGXSTestHarness(PyAPITestHarness): # openmc.mgxs.ARBITRARY_MATRIX_TYPES so we can see the code works, # but not use too much resources relevant_MGXS_TYPES += [ - "(n,elastic)", "(n,level)", "(n,2n)", "(n,na)", "(n,nc)", - "(n,gamma)", "(n,a)", "(n,Xa)", "heating", "damage-energy", - "(n,n1)", "(n,a0)", "(n,nc) matrix", "(n,n1) matrix", + "(n,elastic)", "(n,level)", "(n,2n)", "(n,na)", "(n,nc)", + "(n,gamma)", "(n,a)", "(n,Xa)", "heating", "damage-energy", + "(n,n1)", "(n,a0)", "(n,nc) matrix", "(n,n1) matrix", "(n,2n) matrix"] self.mgxs_lib.mgxs_types = tuple(relevant_MGXS_TYPES) self.mgxs_lib.energy_groups = energy_groups From 4e7cae8b9858db63fc8e2806c997dc90311e3958 Mon Sep 17 00:00:00 2001 From: guyshtot Date: Sat, 25 Mar 2023 13:52:37 +0300 Subject: [PATCH 1674/2654] Update tests/regression_tests/mgxs_library_specific_nuclides/test.py Co-authored-by: Paul Romano --- tests/regression_tests/mgxs_library_specific_nuclides/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/test.py b/tests/regression_tests/mgxs_library_specific_nuclides/test.py index e749ca137..9af2ce17c 100644 --- a/tests/regression_tests/mgxs_library_specific_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_specific_nuclides/test.py @@ -33,7 +33,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.energy_groups = energy_groups self.mgxs_lib.legendre_order = 3 self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.nuclides=['U235','Zr90','H1'] + self.mgxs_lib.nuclides = ['U235', 'Zr90', 'H1'] self.mgxs_lib.build_library() # Add tallies From 3d1811a64a9f168d003ce6791a5b7da6c0bfd906 Mon Sep 17 00:00:00 2001 From: guyshtot Date: Sat, 25 Mar 2023 13:57:08 +0300 Subject: [PATCH 1675/2654] Changed merge=False to merge=True in mgxs_library_specific_nucides test to speed up the test. --- .../inputs_true.dat | 1691 +---------------- .../mgxs_library_specific_nuclides/test.py | 2 +- 2 files changed, 71 insertions(+), 1622 deletions(-) diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat index 205eb059c..061aa1b95 100644 --- a/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat @@ -50,12 +50,15 @@ - - 1 + + 1 2 3 0.0 0.625 20000000.0 + + 1 + 0.0 0.625 20000000.0 @@ -71,1699 +74,145 @@ 2 - + 3 - - 1 2 + + 383 2 total flux tracklength - + 1 2 U235 total - total + total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) tracklength - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - total - tracklength - - - 1 2 + + 383 2 total flux analog - + 1 5 6 U235 total - scatter + scatter nu-scatter analog - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U235 total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - absorption - tracklength - - - 1 2 - U235 total - (n,2n) - tracklength - - - 1 2 - U235 total - (n,3n) - tracklength - - - 1 2 - U235 total - (n,4n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - absorption - tracklength - - - 1 2 - U235 total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - U235 total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - U235 total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 30 - U235 total - nu-scatter - analog - - - 1 2 5 - U235 total - nu-scatter - analog - - - 1 2 5 - U235 total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - U235 total - nu-fission - analog - - - 1 2 5 - U235 total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - scatter - tracklength - - - 1 2 5 30 - U235 total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - scatter - tracklength - - - 1 2 5 30 - U235 total - scatter - analog - - - 1 2 5 - U235 total - nu-scatter - analog - - - 1 54 - U235 total - nu-fission - analog - - - 1 5 - U235 total - nu-fission - analog - - - 1 54 - U235 total - prompt-nu-fission - analog - - - 1 5 - U235 total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - 1 2 U235 total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - U235 total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U235 total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U235 total nu-scatter analog - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,elastic) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,level) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,2n) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,na) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,nc) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,gamma) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,a) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,Xa) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - heating - tracklength - - - 1 2 - total - flux - tracklength - - 1 2 + 1 2 5 30 U235 total - damage-energy - tracklength + scatter nu-scatter + analog - - 1 2 - total - flux - tracklength - - - 1 2 + + 1 2 5 U235 total - (n,n1) - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U235 total - (n,a0) - tracklength - - - 1 2 - total - flux + nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) analog - 1 2 5 + 1 54 U235 total - (n,nc) + nu-fission prompt-nu-fission analog - 1 2 - total - flux - analog - - - 1 2 5 + 1 5 U235 total - (n,n1) + nu-fission prompt-nu-fission analog - - 1 2 - total - flux - analog - - - 1 2 5 - U235 total - (n,2n) - analog - - - 106 2 - total - flux - tracklength - - + 106 2 Zr90 total - total + total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) tracklength - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - total - tracklength - - - 106 2 - total - flux - analog - - + 106 5 6 Zr90 total - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - total - tracklength - - - 106 2 - total - flux - analog - - - 106 5 6 - Zr90 total - nu-scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - absorption - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - absorption - tracklength - - - 106 2 - Zr90 total - (n,2n) - tracklength - - - 106 2 - Zr90 total - (n,3n) - tracklength - - - 106 2 - Zr90 total - (n,4n) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - absorption - tracklength - - - 106 2 - Zr90 total - fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - nu-fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - kappa-fission - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - scatter - tracklength - - - 106 2 - total - flux - analog - - - 106 2 - Zr90 total - nu-scatter - analog - - - 106 2 - total - flux - analog - - - 106 2 5 30 - Zr90 total - scatter - analog - - - 106 2 - total - flux - analog - - - 106 2 5 30 - Zr90 total - nu-scatter - analog - - - 106 2 5 - Zr90 total - nu-scatter - analog - - - 106 2 5 - Zr90 total - scatter - analog - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 total - nu-fission - analog - - - 106 2 5 - Zr90 total - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - scatter - tracklength - - - 106 2 5 30 - Zr90 total - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - scatter - tracklength - - - 106 2 5 30 - Zr90 total - scatter - analog - - - 106 2 5 - Zr90 total - nu-scatter - analog - - - 106 54 - Zr90 total - nu-fission - analog - - - 106 5 - Zr90 total - nu-fission - analog - - - 106 54 - Zr90 total - prompt-nu-fission - analog - - - 106 5 - Zr90 total - prompt-nu-fission - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - inverse-velocity - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - prompt-nu-fission - tracklength - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 total - prompt-nu-fission - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - total - tracklength - - - 106 2 - total - flux - analog - - - 106 5 6 - Zr90 total - scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - total - tracklength - - - 106 2 - total - flux - analog - - - 106 5 6 - Zr90 total - nu-scatter - analog - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,elastic) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,level) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,2n) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,na) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,nc) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,gamma) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,a) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,Xa) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - heating - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - damage-energy - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,n1) - tracklength - - - 106 2 - total - flux - tracklength - - - 106 2 - Zr90 total - (n,a0) - tracklength - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 total - (n,nc) - analog - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 total - (n,n1) - analog - - - 106 2 - total - flux - analog - - - 106 2 5 - Zr90 total - (n,2n) - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - total - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 - H1 total - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 - H1 total - nu-scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - absorption - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - absorption - tracklength - - - 211 2 - H1 total - (n,2n) - tracklength - - - 211 2 - H1 total - (n,3n) - tracklength - - - 211 2 - H1 total - (n,4n) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - absorption - tracklength - - - 211 2 - H1 total - fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - nu-fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - kappa-fission - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - scatter - tracklength - - - 211 2 - total - flux - analog - - - 211 2 - H1 total - nu-scatter - analog - - - 211 2 - total - flux - analog - - - 211 2 5 30 - H1 total - scatter - analog - - - 211 2 - total - flux - analog - - - 211 2 5 30 - H1 total - nu-scatter - analog - - - 211 2 5 - H1 total - nu-scatter - analog - - - 211 2 5 - H1 total - scatter - analog - - - 211 2 - total - flux - analog - - - 211 2 5 - H1 total - nu-fission - analog - - - 211 2 5 - H1 total - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - scatter - tracklength - - - 211 2 5 30 - H1 total - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - scatter - tracklength - - - 211 2 5 30 - H1 total - scatter - analog - - - 211 2 5 - H1 total - nu-scatter + scatter nu-scatter analog - 211 54 - H1 total - nu-fission + 106 2 + Zr90 total + nu-scatter analog - - 211 5 - H1 total - nu-fission + + 106 2 5 30 + Zr90 total + scatter nu-scatter analog - - 211 54 - H1 total - prompt-nu-fission + + 106 2 5 + Zr90 total + nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) analog - - 211 5 - H1 total - prompt-nu-fission + + 106 54 + Zr90 total + nu-fission prompt-nu-fission analog - - 211 2 - total - flux + + 106 5 + Zr90 total + nu-fission prompt-nu-fission + analog + + + 251 2 + H1 total + total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) tracklength - - 211 2 + + 251 5 6 H1 total - inverse-velocity - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - prompt-nu-fission - tracklength - - - 211 2 - total - flux + scatter nu-scatter analog - - 211 2 5 - H1 total - prompt-nu-fission - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 - H1 total - scatter - analog - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - total - tracklength - - - 211 2 - total - flux - analog - - - 211 5 6 + + 251 2 H1 total nu-scatter analog - - 211 2 - total - flux - tracklength - - - 211 2 + + 251 2 5 30 H1 total - (n,elastic) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,level) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,2n) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,na) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,nc) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,gamma) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,a) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,Xa) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - heating - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - damage-energy - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,n1) - tracklength - - - 211 2 - total - flux - tracklength - - - 211 2 - H1 total - (n,a0) - tracklength - - - 211 2 - total - flux + scatter nu-scatter analog - - 211 2 5 + + 251 2 5 H1 total - (n,nc) + nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) analog - - 211 2 - total - flux - analog - - - 211 2 5 + + 251 54 H1 total - (n,n1) + nu-fission prompt-nu-fission analog - - 211 2 - total - flux - analog - - - 211 2 5 + + 251 5 H1 total - (n,2n) + nu-fission prompt-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/test.py b/tests/regression_tests/mgxs_library_specific_nuclides/test.py index 9af2ce17c..61910e539 100644 --- a/tests/regression_tests/mgxs_library_specific_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_specific_nuclides/test.py @@ -37,7 +37,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=True) def _get_results(self, hash_output=True): """Digest info in the statepoint and return as a string.""" From 04806858cafa75b287a6fe32778286a41efb8e95 Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 23 Mar 2023 14:59:37 -0400 Subject: [PATCH 1676/2654] update old tests to use new model.xml --- openmc/plots.py | 6 +- tests/regression_tests/cmfd_feed/geometry.xml | 43 -- .../regression_tests/cmfd_feed/materials.xml | 12 - tests/regression_tests/cmfd_feed/model.xml | 51 ++ tests/regression_tests/cmfd_feed/settings.xml | 26 - tests/regression_tests/cmfd_feed/tallies.xml | 21 - .../cmfd_feed_expanding_window/geometry.xml | 43 -- .../cmfd_feed_expanding_window/materials.xml | 12 - .../cmfd_feed_expanding_window/model.xml | 51 ++ .../cmfd_feed_expanding_window/settings.xml | 26 - .../cmfd_feed_expanding_window/tallies.xml | 21 - .../cmfd_feed_rectlin/geometry.xml | 43 -- .../cmfd_feed_rectlin/materials.xml | 12 - .../cmfd_feed_rectlin/model.xml | 51 ++ .../cmfd_feed_rectlin/settings.xml | 26 - .../cmfd_feed_rectlin/tallies.xml | 21 - .../cmfd_feed_ref_d/geometry.xml | 43 -- .../cmfd_feed_ref_d/materials.xml | 12 - .../cmfd_feed_ref_d/model.xml | 51 ++ .../cmfd_feed_ref_d/settings.xml | 26 - .../cmfd_feed_ref_d/tallies.xml | 21 - .../cmfd_feed_rolling_window/geometry.xml | 43 -- .../cmfd_feed_rolling_window/materials.xml | 12 - .../cmfd_feed_rolling_window/model.xml | 51 ++ .../cmfd_feed_rolling_window/settings.xml | 26 - .../cmfd_feed_rolling_window/tallies.xml | 21 - .../regression_tests/cmfd_nofeed/geometry.xml | 43 -- .../cmfd_nofeed/materials.xml | 12 - tests/regression_tests/cmfd_nofeed/model.xml | 51 ++ .../regression_tests/cmfd_nofeed/settings.xml | 26 - .../regression_tests/cmfd_nofeed/tallies.xml | 21 - .../cmfd_restart/geometry.xml | 43 -- .../cmfd_restart/materials.xml | 12 - tests/regression_tests/cmfd_restart/model.xml | 54 ++ .../cmfd_restart/settings.xml | 28 - .../regression_tests/cmfd_restart/tallies.xml | 21 - .../filter_distribcell/case-4/geometry.xml | 23 - .../filter_distribcell/case-4/materials.xml | 19 - .../filter_distribcell/case-4/model.xml | 61 ++ .../filter_distribcell/case-4/settings.xml | 12 - .../filter_distribcell/case-4/tallies.xml | 14 - .../infinite_cell/geometry.xml | 17 - .../infinite_cell/materials.xml | 14 - .../regression_tests/infinite_cell/model.xml | 39 ++ .../infinite_cell/settings.xml | 15 - .../mg_temperature/build_2g.py | 593 +++++++++--------- tests/regression_tests/plot/geometry.xml | 13 - tests/regression_tests/plot/materials.xml | 19 - tests/regression_tests/plot/model.xml | 76 +++ tests/regression_tests/plot/plots.xml | 33 - tests/regression_tests/plot/settings.xml | 13 - tests/regression_tests/plot/tallies.xml | 20 - .../plot_overlaps/geometry.xml | 14 - .../plot_overlaps/materials.xml | 19 - .../regression_tests/plot_overlaps/model.xml | 65 ++ .../regression_tests/plot_overlaps/plots.xml | 35 -- .../plot_overlaps/settings.xml | 13 - .../regression_tests/plot_voxel/geometry.xml | 13 - .../regression_tests/plot_voxel/materials.xml | 19 - tests/regression_tests/plot_voxel/model.xml | 42 ++ tests/regression_tests/plot_voxel/plots.xml | 10 - .../regression_tests/plot_voxel/settings.xml | 13 - .../track_output/geometry.xml | 305 --------- .../track_output/materials.xml | 95 --- tests/regression_tests/track_output/model.xml | 299 +++++++++ .../track_output/settings.xml | 23 - 66 files changed, 1241 insertions(+), 1787 deletions(-) delete mode 100644 tests/regression_tests/cmfd_feed/geometry.xml delete mode 100644 tests/regression_tests/cmfd_feed/materials.xml create mode 100644 tests/regression_tests/cmfd_feed/model.xml delete mode 100644 tests/regression_tests/cmfd_feed/settings.xml delete mode 100644 tests/regression_tests/cmfd_feed/tallies.xml delete mode 100644 tests/regression_tests/cmfd_feed_expanding_window/geometry.xml delete mode 100644 tests/regression_tests/cmfd_feed_expanding_window/materials.xml create mode 100644 tests/regression_tests/cmfd_feed_expanding_window/model.xml delete mode 100644 tests/regression_tests/cmfd_feed_expanding_window/settings.xml delete mode 100644 tests/regression_tests/cmfd_feed_expanding_window/tallies.xml delete mode 100644 tests/regression_tests/cmfd_feed_rectlin/geometry.xml delete mode 100644 tests/regression_tests/cmfd_feed_rectlin/materials.xml create mode 100644 tests/regression_tests/cmfd_feed_rectlin/model.xml delete mode 100644 tests/regression_tests/cmfd_feed_rectlin/settings.xml delete mode 100644 tests/regression_tests/cmfd_feed_rectlin/tallies.xml delete mode 100644 tests/regression_tests/cmfd_feed_ref_d/geometry.xml delete mode 100644 tests/regression_tests/cmfd_feed_ref_d/materials.xml create mode 100644 tests/regression_tests/cmfd_feed_ref_d/model.xml delete mode 100644 tests/regression_tests/cmfd_feed_ref_d/settings.xml delete mode 100644 tests/regression_tests/cmfd_feed_ref_d/tallies.xml delete mode 100644 tests/regression_tests/cmfd_feed_rolling_window/geometry.xml delete mode 100644 tests/regression_tests/cmfd_feed_rolling_window/materials.xml create mode 100644 tests/regression_tests/cmfd_feed_rolling_window/model.xml delete mode 100644 tests/regression_tests/cmfd_feed_rolling_window/settings.xml delete mode 100644 tests/regression_tests/cmfd_feed_rolling_window/tallies.xml delete mode 100644 tests/regression_tests/cmfd_nofeed/geometry.xml delete mode 100644 tests/regression_tests/cmfd_nofeed/materials.xml create mode 100644 tests/regression_tests/cmfd_nofeed/model.xml delete mode 100644 tests/regression_tests/cmfd_nofeed/settings.xml delete mode 100644 tests/regression_tests/cmfd_nofeed/tallies.xml delete mode 100644 tests/regression_tests/cmfd_restart/geometry.xml delete mode 100644 tests/regression_tests/cmfd_restart/materials.xml create mode 100644 tests/regression_tests/cmfd_restart/model.xml delete mode 100644 tests/regression_tests/cmfd_restart/settings.xml delete mode 100644 tests/regression_tests/cmfd_restart/tallies.xml delete mode 100644 tests/regression_tests/filter_distribcell/case-4/geometry.xml delete mode 100644 tests/regression_tests/filter_distribcell/case-4/materials.xml create mode 100644 tests/regression_tests/filter_distribcell/case-4/model.xml delete mode 100644 tests/regression_tests/filter_distribcell/case-4/settings.xml delete mode 100644 tests/regression_tests/filter_distribcell/case-4/tallies.xml delete mode 100644 tests/regression_tests/infinite_cell/geometry.xml delete mode 100644 tests/regression_tests/infinite_cell/materials.xml create mode 100644 tests/regression_tests/infinite_cell/model.xml delete mode 100644 tests/regression_tests/infinite_cell/settings.xml delete mode 100644 tests/regression_tests/plot/geometry.xml delete mode 100644 tests/regression_tests/plot/materials.xml create mode 100644 tests/regression_tests/plot/model.xml delete mode 100644 tests/regression_tests/plot/plots.xml delete mode 100644 tests/regression_tests/plot/settings.xml delete mode 100644 tests/regression_tests/plot/tallies.xml delete mode 100644 tests/regression_tests/plot_overlaps/geometry.xml delete mode 100644 tests/regression_tests/plot_overlaps/materials.xml create mode 100644 tests/regression_tests/plot_overlaps/model.xml delete mode 100644 tests/regression_tests/plot_overlaps/plots.xml delete mode 100644 tests/regression_tests/plot_overlaps/settings.xml delete mode 100644 tests/regression_tests/plot_voxel/geometry.xml delete mode 100644 tests/regression_tests/plot_voxel/materials.xml create mode 100644 tests/regression_tests/plot_voxel/model.xml delete mode 100644 tests/regression_tests/plot_voxel/plots.xml delete mode 100644 tests/regression_tests/plot_voxel/settings.xml delete mode 100644 tests/regression_tests/track_output/geometry.xml delete mode 100644 tests/regression_tests/track_output/materials.xml create mode 100644 tests/regression_tests/track_output/model.xml delete mode 100644 tests/regression_tests/track_output/settings.xml diff --git a/openmc/plots.py b/openmc/plots.py index 0a0451625..4b7d58e3b 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -683,11 +683,11 @@ class Plot(IDManagerMixin): if self._meshlines is not None: subelement = ET.SubElement(element, "meshlines") subelement.set("meshtype", self._meshlines['type']) - if self._meshlines['id'] is not None: + if 'id' in self._meshlines: subelement.set("id", str(self._meshlines['id'])) - if self._meshlines['linewidth'] is not None: + if 'linewidth' in self._meshlines: subelement.set("linewidth", str(self._meshlines['linewidth'])) - if self._meshlines['color'] is not None: + if 'color' in self._meshlines: subelement.set("color", ' '.join(map( str, self._meshlines['color']))) diff --git a/tests/regression_tests/cmfd_feed/geometry.xml b/tests/regression_tests/cmfd_feed/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed/materials.xml b/tests/regression_tests/cmfd_feed/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed/model.xml b/tests/regression_tests/cmfd_feed/model.xml new file mode 100644 index 000000000..b3fe853b2 --- /dev/null +++ b/tests/regression_tests/cmfd_feed/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 10 + + + -10.0 -1.0 -1.0 10.0 1.0 1.0 + + + 10 + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + 1 + + + 1 + flux + + + diff --git a/tests/regression_tests/cmfd_feed/settings.xml b/tests/regression_tests/cmfd_feed/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed/tallies.xml b/tests/regression_tests/cmfd_feed/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/geometry.xml b/tests/regression_tests/cmfd_feed_expanding_window/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/materials.xml b/tests/regression_tests/cmfd_feed_expanding_window/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/model.xml b/tests/regression_tests/cmfd_feed_expanding_window/model.xml new file mode 100644 index 000000000..b3fe853b2 --- /dev/null +++ b/tests/regression_tests/cmfd_feed_expanding_window/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 10 + + + -10.0 -1.0 -1.0 10.0 1.0 1.0 + + + 10 + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + 1 + + + 1 + flux + + + diff --git a/tests/regression_tests/cmfd_feed_expanding_window/settings.xml b/tests/regression_tests/cmfd_feed_expanding_window/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/tallies.xml b/tests/regression_tests/cmfd_feed_expanding_window/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_rectlin/geometry.xml b/tests/regression_tests/cmfd_feed_rectlin/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed_rectlin/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed_rectlin/materials.xml b/tests/regression_tests/cmfd_feed_rectlin/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed_rectlin/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_rectlin/model.xml b/tests/regression_tests/cmfd_feed_rectlin/model.xml new file mode 100644 index 000000000..b3fe853b2 --- /dev/null +++ b/tests/regression_tests/cmfd_feed_rectlin/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 10 + + + -10.0 -1.0 -1.0 10.0 1.0 1.0 + + + 10 + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + 1 + + + 1 + flux + + + diff --git a/tests/regression_tests/cmfd_feed_rectlin/settings.xml b/tests/regression_tests/cmfd_feed_rectlin/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed_rectlin/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_rectlin/tallies.xml b/tests/regression_tests/cmfd_feed_rectlin/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed_rectlin/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/geometry.xml b/tests/regression_tests/cmfd_feed_ref_d/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/materials.xml b/tests/regression_tests/cmfd_feed_ref_d/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/model.xml b/tests/regression_tests/cmfd_feed_ref_d/model.xml new file mode 100644 index 000000000..b3fe853b2 --- /dev/null +++ b/tests/regression_tests/cmfd_feed_ref_d/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 10 + + + -10.0 -1.0 -1.0 10.0 1.0 1.0 + + + 10 + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + 1 + + + 1 + flux + + + diff --git a/tests/regression_tests/cmfd_feed_ref_d/settings.xml b/tests/regression_tests/cmfd_feed_ref_d/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/tallies.xml b/tests/regression_tests/cmfd_feed_ref_d/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/geometry.xml b/tests/regression_tests/cmfd_feed_rolling_window/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/materials.xml b/tests/regression_tests/cmfd_feed_rolling_window/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/model.xml b/tests/regression_tests/cmfd_feed_rolling_window/model.xml new file mode 100644 index 000000000..b3fe853b2 --- /dev/null +++ b/tests/regression_tests/cmfd_feed_rolling_window/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 10 + + + -10.0 -1.0 -1.0 10.0 1.0 1.0 + + + 10 + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + 1 + + + 1 + flux + + + diff --git a/tests/regression_tests/cmfd_feed_rolling_window/settings.xml b/tests/regression_tests/cmfd_feed_rolling_window/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/tallies.xml b/tests/regression_tests/cmfd_feed_rolling_window/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_nofeed/geometry.xml b/tests/regression_tests/cmfd_nofeed/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_nofeed/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_nofeed/materials.xml b/tests/regression_tests/cmfd_nofeed/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_nofeed/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_nofeed/model.xml b/tests/regression_tests/cmfd_nofeed/model.xml new file mode 100644 index 000000000..b3fe853b2 --- /dev/null +++ b/tests/regression_tests/cmfd_nofeed/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 10 + + + -10.0 -1.0 -1.0 10.0 1.0 1.0 + + + 10 + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + 1 + + + 1 + flux + + + diff --git a/tests/regression_tests/cmfd_nofeed/settings.xml b/tests/regression_tests/cmfd_nofeed/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_nofeed/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_nofeed/tallies.xml b/tests/regression_tests/cmfd_nofeed/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_nofeed/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_restart/geometry.xml b/tests/regression_tests/cmfd_restart/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_restart/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_restart/materials.xml b/tests/regression_tests/cmfd_restart/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_restart/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_restart/model.xml b/tests/regression_tests/cmfd_restart/model.xml new file mode 100644 index 000000000..487e9b66d --- /dev/null +++ b/tests/regression_tests/cmfd_restart/model.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 10 + + + -10.0 -1.0 -1.0 10.0 1.0 1.0 + + + + 15 20 + + 10 + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + + + 10 1 1 + -10.0 -1.0 -1.0 + 10.0 1.0 1.0 + + + 1 + + + 1 + flux + + + diff --git a/tests/regression_tests/cmfd_restart/settings.xml b/tests/regression_tests/cmfd_restart/settings.xml deleted file mode 100644 index ba5495911..000000000 --- a/tests/regression_tests/cmfd_restart/settings.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - - - diff --git a/tests/regression_tests/cmfd_restart/tallies.xml b/tests/regression_tests/cmfd_restart/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_restart/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/filter_distribcell/case-4/geometry.xml b/tests/regression_tests/filter_distribcell/case-4/geometry.xml deleted file mode 100644 index c835218bc..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/geometry.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - 1.0 - 3 -
0.0 0.0
- - 1 -1 1 - 1 -1 1 - 1 -
- - - - - -
diff --git a/tests/regression_tests/filter_distribcell/case-4/materials.xml b/tests/regression_tests/filter_distribcell/case-4/materials.xml deleted file mode 100644 index 2eb744fe6..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-4/model.xml b/tests/regression_tests/filter_distribcell/case-4/model.xml new file mode 100644 index 000000000..869421919 --- /dev/null +++ b/tests/regression_tests/filter_distribcell/case-4/model.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 3 +
0.0 0.0
+ + 1 +1 1 + 1 +1 1 + 1 +
+ + + + + +
+ + eigenvalue + 1000 + 1 + 0 + + + -1.0 -1.0 -1.0 1.0 1.0 1.0 + + + + + + 101 + + + 1 + total + + +
diff --git a/tests/regression_tests/filter_distribcell/case-4/settings.xml b/tests/regression_tests/filter_distribcell/case-4/settings.xml deleted file mode 100644 index f3f0779bc..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - eigenvalue - 1000 - 1 - 0 - - - -1 -1 -1 1 1 1 - - - diff --git a/tests/regression_tests/filter_distribcell/case-4/tallies.xml b/tests/regression_tests/filter_distribcell/case-4/tallies.xml deleted file mode 100644 index b923c030b..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - distribcell - 101 - - - - 1 - total - - - diff --git a/tests/regression_tests/infinite_cell/geometry.xml b/tests/regression_tests/infinite_cell/geometry.xml deleted file mode 100644 index 90bd2233b..000000000 --- a/tests/regression_tests/infinite_cell/geometry.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - 11 12 - 12 11 - - - - - - - diff --git a/tests/regression_tests/infinite_cell/materials.xml b/tests/regression_tests/infinite_cell/materials.xml deleted file mode 100644 index 6acd8df74..000000000 --- a/tests/regression_tests/infinite_cell/materials.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/infinite_cell/model.xml b/tests/regression_tests/infinite_cell/model.xml new file mode 100644 index 000000000..0f741a86d --- /dev/null +++ b/tests/regression_tests/infinite_cell/model.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + 2.0 2.0 + 12 + 2 2 + -2.0 -2.0 + +11 12 +12 11 + + + + + eigenvalue + 1000 + 10 + 5 + + + -4.0 -4.0 -4.0 4.0 4.0 4.0 + + + + diff --git a/tests/regression_tests/infinite_cell/settings.xml b/tests/regression_tests/infinite_cell/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/infinite_cell/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/mg_temperature/build_2g.py b/tests/regression_tests/mg_temperature/build_2g.py index 1256ca0f7..42f948be1 100644 --- a/tests/regression_tests/mg_temperature/build_2g.py +++ b/tests/regression_tests/mg_temperature/build_2g.py @@ -1,297 +1,296 @@ -import openmc -import numpy as np - -names = ['H', 'O', 'Zr', 'U235', 'U238'] - - -def build_openmc_xs_lib(name, groups, temperatures, xsdict, micro=True): - """Build an Openm XSdata based on dictionary values""" - xsdata = openmc.XSdata(name, groups, temperatures=temperatures) - xsdata.order = 0 - for tt in temperatures: - xsdata.set_absorption(xsdict[tt]['absorption'][name], temperature=tt) - xsdata.set_scatter_matrix(xsdict[tt]['scatter'][name], temperature=tt) - xsdata.set_total(xsdict[tt]['total'][name], temperature=tt) - if (name in xsdict[tt]['nu-fission'].keys()): - xsdata.set_nu_fission(xsdict[tt]['nu-fission'][name], - temperature=tt) - xsdata.set_chi(np.array([1., 0.]), temperature=tt) - return xsdata - - -def create_micro_xs_dict(): - """Returns micro xs library""" - xs_micro = {} - reactions = ['absorption', 'total', 'scatter', 'nu-fission'] - # chi is unnecessary when energy bound is in thermal region - # Temperature 300K - # absorption - xs_micro[300] = {r: {} for r in reactions} - xs_micro[300]['absorption']['H'] = np.array([1.0285E-4, 0.0057]) - xs_micro[300]['absorption']['O'] = np.array([7.1654E-5, 3.0283E-6]) - xs_micro[300]['absorption']['Zr'] = np.array([4.5918E-5, 3.6303E-5]) - xs_micro[300]['absorption']['U235'] = np.array([0.0035, 0.1040]) - xs_micro[300]['absorption']['U238'] = np.array([0.0056, 0.0094]) - # nu-scatter matrix - xs_micro[300]['scatter']['H'] = np.array([[[0.0910, 0.01469], - [0.0, 0.3316]]]) - xs_micro[300]['scatter']['O'] = np.array([[[0.0814, 3.3235E-4], - [0.0, 0.0960]]]) - xs_micro[300]['scatter']['Zr'] = np.array([[[0.0311, 2.6373E-5], - [0.0, 0.0315]]]) - xs_micro[300]['scatter']['U235'] = np.array([[[0.0311, 2.6373E-5], - [0.0, 0.0315]]]) - xs_micro[300]['scatter']['U238'] = np.array([[[0.0551, 2.2341E-5], - [0.0, 0.0526]]]) - # nu-fission - xs_micro[300]['nu-fission']['U235'] = np.array([0.0059, 0.2160]) - xs_micro[300]['nu-fission']['U238'] = np.array([0.0019, 1.4627E-7]) - # total - xs_micro[300]['total']['H'] = xs_micro[300]['absorption']['H'] + \ - np.sum(xs_micro[300]['scatter']['H'][0], 1) - xs_micro[300]['total']['O'] = xs_micro[300]['absorption']['O'] + \ - np.sum(xs_micro[300]['scatter']['O'][0], 1) - - xs_micro[300]['total']['Zr'] = xs_micro[300]['absorption']['Zr'] + \ - np.sum(xs_micro[300]['scatter']['Zr'][0], 1) - - xs_micro[300]['total']['U235'] = xs_micro[300]['absorption']['U235'] + \ - np.sum(xs_micro[300]['scatter']['U235'][0], 1) - - xs_micro[300]['total']['U238'] = xs_micro[300]['absorption']['U238'] + \ - np.sum(xs_micro[300]['scatter']['U238'][0], 1) - - # Temperature 600K - xs_micro[600] = {r: {} for r in reactions} - # absorption - xs_micro[600]['absorption']['H'] = np.array([1.0356E-4, 0.0046]) - xs_micro[600]['absorption']['O'] = np.array([7.2678E-5, 2.4963E-6]) - xs_micro[600]['absorption']['Zr'] = np.array([4.7256E-5, 2.9757E-5]) - xs_micro[600]['absorption']['U235'] = np.array([0.0035, 0.0853]) - xs_micro[600]['absorption']['U238'] = np.array([0.0058, 0.0079]) - # nu-scatter matrix - xs_micro[600]['scatter']['H'] = np.array([[[0.0910, 0.0138], - [0.0, 0.3316]]]) - xs_micro[600]['scatter']['O'] = np.array([[[0.0814, 3.5367E-4], - [0.0, 0.0959]]]) - xs_micro[600]['scatter']['Zr'] = np.array([[[0.0311, 3.2293E-5], - [0.0, 0.0314]]]) - xs_micro[600]['scatter']['U235'] = np.array([[[0.0022, 1.9763E-6], - [9.1634E-8, 0.0039]]]) - xs_micro[600]['scatter']['U238'] = np.array([[[0.0556, 2.8803E-5], - [0.0, 0.0536]]]) - # nu-fission - xs_micro[600]['nu-fission']['U235'] = np.array([0.0059, 0.1767]) - xs_micro[600]['nu-fission']['U238'] = np.array([0.0019, 1.2405E-7]) - # total - xs_micro[600]['total']['H'] = xs_micro[600]['absorption']['H'] + \ - np.sum(xs_micro[600]['scatter']['H'][0], 1) - xs_micro[600]['total']['O'] = xs_micro[600]['absorption']['O'] + \ - np.sum(xs_micro[600]['scatter']['O'][0], 1) - - xs_micro[600]['total']['Zr'] = xs_micro[600]['absorption']['Zr'] + \ - np.sum(xs_micro[600]['scatter']['Zr'][0], 1) - - xs_micro[600]['total']['U235'] = xs_micro[600]['absorption']['U235'] + \ - np.sum(xs_micro[600]['scatter']['U235'][0], 1) - - xs_micro[600]['total']['U238'] = xs_micro[600]['absorption']['U238'] + \ - np.sum(xs_micro[600]['scatter']['U238'][0], 1) - - # Temperature 900K - xs_micro[900] = {r: {} for r in reactions} - # absorption - xs_micro[900]['absorption']['H'] = np.array([1.0529E-4, 0.0040]) - xs_micro[900]['absorption']['O'] = np.array([7.3055E-5, 2.1850E-6]) - xs_micro[900]['absorption']['Zr'] = np.array([4.7141E-5, 2.5941E-5]) - xs_micro[900]['absorption']['U235'] = np.array([0.0035, 0.0749]) - xs_micro[900]['absorption']['U238'] = np.array([0.0060, 0.0071]) - # total - xs_micro[900]['total']['H'] = np.array([0.2982, 0.7332]) - xs_micro[900]['total']['O'] = np.array([0.0885, 0.1004]) - xs_micro[900]['total']['Zr'] = np.array([0.0370, 0.0317]) - xs_micro[900]['total']['U235'] = np.array([0.0061, 0.0789]) - xs_micro[900]['total']['U238'] = np.array([0.0707, 0.0613]) - # nu-scatter matrix - xs_micro[900]['scatter']['H'] = np.array([[[0.0913, 0.0147], - [0.0, 0.4020]]]) - xs_micro[900]['scatter']['O'] = np.array([[[0.0812, 4.0413E-4], - [0.0, 0.0965]]]) - xs_micro[900]['scatter']['Zr'] = np.array([[[0.0311, 3.6735E-5], - [0.0, 0.0314]]]) - xs_micro[900]['scatter']['U235'] = np.array([[[0.0022, 2.9034E-6], - [1.3117E-8, 0.0039]]]) - xs_micro[900]['scatter']['U238'] = np.array([[[0.0560, 3.7619E-5], - [0.0, 0.0538]]]) - # nu-fission - xs_micro[900]['nu-fission']['U235'] = np.array([0.0059, 0.1545]) - xs_micro[900]['nu-fission']['U238'] = np.array([0.0019, 1.1017E-7]) - # total - xs_micro[900]['total']['H'] = xs_micro[900]['absorption']['H'] + \ - np.sum(xs_micro[900]['scatter']['H'][0], 1) - xs_micro[900]['total']['O'] = xs_micro[900]['absorption']['O'] + \ - np.sum(xs_micro[900]['scatter']['O'][0], 1) - - xs_micro[900]['total']['Zr'] = xs_micro[900]['absorption']['Zr'] + \ - np.sum(xs_micro[900]['scatter']['Zr'][0], 1) - - xs_micro[900]['total']['U235'] = xs_micro[900]['absorption']['U235'] + \ - np.sum(xs_micro[900]['scatter']['U235'][0], 1) - - xs_micro[900]['total']['U238'] = xs_micro[900]['absorption']['U238'] + \ - np.sum(xs_micro[900]['scatter']['U238'][0], 1) - - # roll axis for scatter matrix - for t in xs_micro: - for n in xs_micro[t]['scatter']: - xs_micro[t]['scatter'][n] = np.rollaxis(xs_micro[t]['scatter'][n], - 0, 3) - return xs_micro - - -def create_macro_dict(xs_micro): - """Create a dictionary with two group cross-section""" - xs_macro = {} - for t, d1 in xs_micro.items(): - xs_macro[t] = {} - for r, d2 in d1.items(): - temp = [] - xs_macro[t][r] = {} - for n, v in d2.items(): - temp.append(d2[n]) - # The name 'macro' is needed to store data at the same level - # of a xs_macro dictionary as for xs_micro and use it in - # function build_openmc_xs_lib - xs_macro[t][r]['macro'] = sum(temp) - return xs_macro - - -def create_openmc_2mg_libs(names): - """Built a micro/macro two group openmc MGXS libraries""" - # Initialized library params - group_edges = [0.0, 0.625, 20.0e6] - groups = openmc.mgxs.EnergyGroups(group_edges=group_edges) - mg_cross_sections_file_micro = openmc.MGXSLibrary(groups) - mg_cross_sections_file_macro = openmc.MGXSLibrary(groups) - # Building a micro mg library - micro_cs = create_micro_xs_dict() - for name in names: - mg_cross_sections_file_micro.add_xsdata(build_openmc_xs_lib(name, - groups, - [t for t in - micro_cs], - micro_cs)) - # Building a macro mg library - macro_xs = create_macro_dict(micro_cs) - mg_cross_sections_file_macro.add_xsdata(build_openmc_xs_lib('macro', - groups, - [t for t in - macro_xs], - macro_xs)) - # Exporting library to hdf5 files - mg_cross_sections_file_micro.export_to_hdf5('micro_2g.h5') - mg_cross_sections_file_macro.export_to_hdf5('macro_2g.h5') - # Returning the macro_xs dict is needed for analytical solution - return macro_xs - - -def analytical_solution_2g_therm(xsmin, xsmax=None, wgt=1.0): - """ Calculate eigenvalue based on analytical solution for eq Lf = (1/k)Qf - in two group for infinity dilution media in assumption of group - boundary in thermal spectra < 1.e+3 Ev - Parameters: - ---------- - xsmin : dict - macro cross-sections dictionary with minimum range temperature - xsmax : dict - macro cross-sections dictionary with maximum range temperature - by default: None not used for standalone temperature - wgt : float - weight for interpolation by default 1.0 - Returns: - ------- - keff : np.float64 - analytical eigenvalue of critical eq matrix - """ - if xsmax is None: - sa = xsmin['absorption']['macro'] - ss12 = xsmin['scatter']['macro'][0][1][0] - nsf = xsmin['nu-fission']['macro'] - else: - sa = xsmin['absorption']['macro'] * wgt + \ - xsmax['absorption']['macro'] * (1 - wgt) - ss12 = xsmin['scatter']['macro'][0][1][0] * wgt + \ - xsmax['scatter']['macro'][0][1][0] * (1 - wgt) - nsf = xsmin['nu-fission']['macro'] * wgt + \ - xsmax['nu-fission']['macro'] * (1 - wgt) - L = np.array([sa[0] + ss12, 0.0, -ss12, sa[1]]).reshape(2, 2) - Q = np.array([nsf[0], nsf[1], 0.0, 0.0]).reshape(2, 2) - arr = np.linalg.inv(L).dot(Q) - return np.amax(np.linalg.eigvals(arr)) - - -def build_inf_model(xsnames, xslibname, temperature, tempmethod='nearest'): - """ Building an infinite medium for openmc multi-group testing - Parameters: - ---------- - xsnames : list of str() - list with xs names - xslibname: - name of hdf5 file with cross-section library - temperature : float - value of a current temperature in K - tempmethod : {'nearest', 'interpolation'} - by default 'nearest' - """ - inf_medium = openmc.Material(name='test material', material_id=1) - inf_medium.set_density("sum") - for xs in xsnames: - inf_medium.add_nuclide(xs, 1) - INF = 11.1 - # Instantiate a Materials collection and export to XML - materials_file = openmc.Materials([inf_medium]) - materials_file.cross_sections = xslibname - materials_file.export_to_xml() - - # Instantiate boundary Planes - min_x = openmc.XPlane(boundary_type='reflective', x0=-INF) - max_x = openmc.XPlane(boundary_type='reflective', x0=INF) - min_y = openmc.YPlane(boundary_type='reflective', y0=-INF) - max_y = openmc.YPlane(boundary_type='reflective', y0=INF) - - # Instantiate a Cell - cell = openmc.Cell(cell_id=1, name='cell') - cell.temperature = temperature - # Register bounding Surfaces with the Cell - cell.region = +min_x & -max_x & +min_y & -max_y - - # Fill the Cell with the Material - cell.fill = inf_medium - - # Create root universe - root_universe = openmc.Universe(name='root universe', cells=[cell]) - - # Create Geometry and set root Universe - openmc_geometry = openmc.Geometry(root_universe) - - # Export to "geometry.xml" - openmc_geometry.export_to_xml() - - # OpenMC simulation parameters - batches = 200 - inactive = 5 - particles = 5000 - - # Instantiate a Settings object - settings_file = openmc.Settings() - settings_file.batches = batches - settings_file.inactive = inactive - settings_file.particles = particles - settings_file.energy_mode = 'multi-group' - settings_file.output = {'summary': False} - # Create an initial uniform spatial source distribution over fissionable zones - bounds = [-INF, -INF, -INF, INF, INF, INF] - uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) - settings_file.temperature = {'method': tempmethod} - settings_file.source = openmc.Source(space=uniform_dist) - settings_file.export_to_xml() +import openmc +import numpy as np + +names = ['H', 'O', 'Zr', 'U235', 'U238'] + + +def build_openmc_xs_lib(name, groups, temperatures, xsdict, micro=True): + """Build an Openm XSdata based on dictionary values""" + xsdata = openmc.XSdata(name, groups, temperatures=temperatures) + xsdata.order = 0 + for tt in temperatures: + xsdata.set_absorption(xsdict[tt]['absorption'][name], temperature=tt) + xsdata.set_scatter_matrix(xsdict[tt]['scatter'][name], temperature=tt) + xsdata.set_total(xsdict[tt]['total'][name], temperature=tt) + if (name in xsdict[tt]['nu-fission'].keys()): + xsdata.set_nu_fission(xsdict[tt]['nu-fission'][name], + temperature=tt) + xsdata.set_chi(np.array([1., 0.]), temperature=tt) + return xsdata + + +def create_micro_xs_dict(): + """Returns micro xs library""" + xs_micro = {} + reactions = ['absorption', 'total', 'scatter', 'nu-fission'] + # chi is unnecessary when energy bound is in thermal region + # Temperature 300K + # absorption + xs_micro[300] = {r: {} for r in reactions} + xs_micro[300]['absorption']['H'] = np.array([1.0285E-4, 0.0057]) + xs_micro[300]['absorption']['O'] = np.array([7.1654E-5, 3.0283E-6]) + xs_micro[300]['absorption']['Zr'] = np.array([4.5918E-5, 3.6303E-5]) + xs_micro[300]['absorption']['U235'] = np.array([0.0035, 0.1040]) + xs_micro[300]['absorption']['U238'] = np.array([0.0056, 0.0094]) + # nu-scatter matrix + xs_micro[300]['scatter']['H'] = np.array([[[0.0910, 0.01469], + [0.0, 0.3316]]]) + xs_micro[300]['scatter']['O'] = np.array([[[0.0814, 3.3235E-4], + [0.0, 0.0960]]]) + xs_micro[300]['scatter']['Zr'] = np.array([[[0.0311, 2.6373E-5], + [0.0, 0.0315]]]) + xs_micro[300]['scatter']['U235'] = np.array([[[0.0311, 2.6373E-5], + [0.0, 0.0315]]]) + xs_micro[300]['scatter']['U238'] = np.array([[[0.0551, 2.2341E-5], + [0.0, 0.0526]]]) + # nu-fission + xs_micro[300]['nu-fission']['U235'] = np.array([0.0059, 0.2160]) + xs_micro[300]['nu-fission']['U238'] = np.array([0.0019, 1.4627E-7]) + # total + xs_micro[300]['total']['H'] = xs_micro[300]['absorption']['H'] + \ + np.sum(xs_micro[300]['scatter']['H'][0], 1) + xs_micro[300]['total']['O'] = xs_micro[300]['absorption']['O'] + \ + np.sum(xs_micro[300]['scatter']['O'][0], 1) + + xs_micro[300]['total']['Zr'] = xs_micro[300]['absorption']['Zr'] + \ + np.sum(xs_micro[300]['scatter']['Zr'][0], 1) + + xs_micro[300]['total']['U235'] = xs_micro[300]['absorption']['U235'] + \ + np.sum(xs_micro[300]['scatter']['U235'][0], 1) + + xs_micro[300]['total']['U238'] = xs_micro[300]['absorption']['U238'] + \ + np.sum(xs_micro[300]['scatter']['U238'][0], 1) + + # Temperature 600K + xs_micro[600] = {r: {} for r in reactions} + # absorption + xs_micro[600]['absorption']['H'] = np.array([1.0356E-4, 0.0046]) + xs_micro[600]['absorption']['O'] = np.array([7.2678E-5, 2.4963E-6]) + xs_micro[600]['absorption']['Zr'] = np.array([4.7256E-5, 2.9757E-5]) + xs_micro[600]['absorption']['U235'] = np.array([0.0035, 0.0853]) + xs_micro[600]['absorption']['U238'] = np.array([0.0058, 0.0079]) + # nu-scatter matrix + xs_micro[600]['scatter']['H'] = np.array([[[0.0910, 0.0138], + [0.0, 0.3316]]]) + xs_micro[600]['scatter']['O'] = np.array([[[0.0814, 3.5367E-4], + [0.0, 0.0959]]]) + xs_micro[600]['scatter']['Zr'] = np.array([[[0.0311, 3.2293E-5], + [0.0, 0.0314]]]) + xs_micro[600]['scatter']['U235'] = np.array([[[0.0022, 1.9763E-6], + [9.1634E-8, 0.0039]]]) + xs_micro[600]['scatter']['U238'] = np.array([[[0.0556, 2.8803E-5], + [0.0, 0.0536]]]) + # nu-fission + xs_micro[600]['nu-fission']['U235'] = np.array([0.0059, 0.1767]) + xs_micro[600]['nu-fission']['U238'] = np.array([0.0019, 1.2405E-7]) + # total + xs_micro[600]['total']['H'] = xs_micro[600]['absorption']['H'] + \ + np.sum(xs_micro[600]['scatter']['H'][0], 1) + xs_micro[600]['total']['O'] = xs_micro[600]['absorption']['O'] + \ + np.sum(xs_micro[600]['scatter']['O'][0], 1) + + xs_micro[600]['total']['Zr'] = xs_micro[600]['absorption']['Zr'] + \ + np.sum(xs_micro[600]['scatter']['Zr'][0], 1) + + xs_micro[600]['total']['U235'] = xs_micro[600]['absorption']['U235'] + \ + np.sum(xs_micro[600]['scatter']['U235'][0], 1) + + xs_micro[600]['total']['U238'] = xs_micro[600]['absorption']['U238'] + \ + np.sum(xs_micro[600]['scatter']['U238'][0], 1) + + # Temperature 900K + xs_micro[900] = {r: {} for r in reactions} + # absorption + xs_micro[900]['absorption']['H'] = np.array([1.0529E-4, 0.0040]) + xs_micro[900]['absorption']['O'] = np.array([7.3055E-5, 2.1850E-6]) + xs_micro[900]['absorption']['Zr'] = np.array([4.7141E-5, 2.5941E-5]) + xs_micro[900]['absorption']['U235'] = np.array([0.0035, 0.0749]) + xs_micro[900]['absorption']['U238'] = np.array([0.0060, 0.0071]) + # total + xs_micro[900]['total']['H'] = np.array([0.2982, 0.7332]) + xs_micro[900]['total']['O'] = np.array([0.0885, 0.1004]) + xs_micro[900]['total']['Zr'] = np.array([0.0370, 0.0317]) + xs_micro[900]['total']['U235'] = np.array([0.0061, 0.0789]) + xs_micro[900]['total']['U238'] = np.array([0.0707, 0.0613]) + # nu-scatter matrix + xs_micro[900]['scatter']['H'] = np.array([[[0.0913, 0.0147], + [0.0, 0.4020]]]) + xs_micro[900]['scatter']['O'] = np.array([[[0.0812, 4.0413E-4], + [0.0, 0.0965]]]) + xs_micro[900]['scatter']['Zr'] = np.array([[[0.0311, 3.6735E-5], + [0.0, 0.0314]]]) + xs_micro[900]['scatter']['U235'] = np.array([[[0.0022, 2.9034E-6], + [1.3117E-8, 0.0039]]]) + xs_micro[900]['scatter']['U238'] = np.array([[[0.0560, 3.7619E-5], + [0.0, 0.0538]]]) + # nu-fission + xs_micro[900]['nu-fission']['U235'] = np.array([0.0059, 0.1545]) + xs_micro[900]['nu-fission']['U238'] = np.array([0.0019, 1.1017E-7]) + # total + xs_micro[900]['total']['H'] = xs_micro[900]['absorption']['H'] + \ + np.sum(xs_micro[900]['scatter']['H'][0], 1) + xs_micro[900]['total']['O'] = xs_micro[900]['absorption']['O'] + \ + np.sum(xs_micro[900]['scatter']['O'][0], 1) + + xs_micro[900]['total']['Zr'] = xs_micro[900]['absorption']['Zr'] + \ + np.sum(xs_micro[900]['scatter']['Zr'][0], 1) + + xs_micro[900]['total']['U235'] = xs_micro[900]['absorption']['U235'] + \ + np.sum(xs_micro[900]['scatter']['U235'][0], 1) + + xs_micro[900]['total']['U238'] = xs_micro[900]['absorption']['U238'] + \ + np.sum(xs_micro[900]['scatter']['U238'][0], 1) + + # roll axis for scatter matrix + for t in xs_micro: + for n in xs_micro[t]['scatter']: + xs_micro[t]['scatter'][n] = np.rollaxis(xs_micro[t]['scatter'][n], + 0, 3) + return xs_micro + + +def create_macro_dict(xs_micro): + """Create a dictionary with two group cross-section""" + xs_macro = {} + for t, d1 in xs_micro.items(): + xs_macro[t] = {} + for r, d2 in d1.items(): + temp = [] + xs_macro[t][r] = {} + for n, v in d2.items(): + temp.append(d2[n]) + # The name 'macro' is needed to store data at the same level + # of a xs_macro dictionary as for xs_micro and use it in + # function build_openmc_xs_lib + xs_macro[t][r]['macro'] = sum(temp) + return xs_macro + + +def create_openmc_2mg_libs(names): + """Built a micro/macro two group openmc MGXS libraries""" + # Initialized library params + group_edges = [0.0, 0.625, 20.0e6] + groups = openmc.mgxs.EnergyGroups(group_edges=group_edges) + mg_cross_sections_file_micro = openmc.MGXSLibrary(groups) + mg_cross_sections_file_macro = openmc.MGXSLibrary(groups) + # Building a micro mg library + micro_cs = create_micro_xs_dict() + for name in names: + mg_cross_sections_file_micro.add_xsdata(build_openmc_xs_lib(name, + groups, + [t for t in + micro_cs], + micro_cs)) + # Building a macro mg library + macro_xs = create_macro_dict(micro_cs) + mg_cross_sections_file_macro.add_xsdata(build_openmc_xs_lib('macro', + groups, + [t for t in + macro_xs], + macro_xs)) + # Exporting library to hdf5 files + mg_cross_sections_file_micro.export_to_hdf5('micro_2g.h5') + mg_cross_sections_file_macro.export_to_hdf5('macro_2g.h5') + # Returning the macro_xs dict is needed for analytical solution + return macro_xs + + +def analytical_solution_2g_therm(xsmin, xsmax=None, wgt=1.0): + """ Calculate eigenvalue based on analytical solution for eq Lf = (1/k)Qf + in two group for infinity dilution media in assumption of group + boundary in thermal spectra < 1.e+3 Ev + Parameters: + ---------- + xsmin : dict + macro cross-sections dictionary with minimum range temperature + xsmax : dict + macro cross-sections dictionary with maximum range temperature + by default: None not used for standalone temperature + wgt : float + weight for interpolation by default 1.0 + Returns: + ------- + keff : np.float64 + analytical eigenvalue of critical eq matrix + """ + if xsmax is None: + sa = xsmin['absorption']['macro'] + ss12 = xsmin['scatter']['macro'][0][1][0] + nsf = xsmin['nu-fission']['macro'] + else: + sa = xsmin['absorption']['macro'] * wgt + \ + xsmax['absorption']['macro'] * (1 - wgt) + ss12 = xsmin['scatter']['macro'][0][1][0] * wgt + \ + xsmax['scatter']['macro'][0][1][0] * (1 - wgt) + nsf = xsmin['nu-fission']['macro'] * wgt + \ + xsmax['nu-fission']['macro'] * (1 - wgt) + L = np.array([sa[0] + ss12, 0.0, -ss12, sa[1]]).reshape(2, 2) + Q = np.array([nsf[0], nsf[1], 0.0, 0.0]).reshape(2, 2) + arr = np.linalg.inv(L).dot(Q) + return np.amax(np.linalg.eigvals(arr)) + + +def build_inf_model(xsnames, xslibname, temperature, tempmethod='nearest'): + """ Building an infinite medium for openmc multi-group testing + Parameters: + ---------- + xsnames : list of str() + list with xs names + xslibname: + name of hdf5 file with cross-section library + temperature : float + value of a current temperature in K + tempmethod : {'nearest', 'interpolation'} + by default 'nearest' + """ + model = openmc.Model() + inf_medium = openmc.Material(name='test material', material_id=1) + inf_medium.set_density("sum") + for xs in xsnames: + inf_medium.add_nuclide(xs, 1) + INF = 11.1 + # Instantiate a Materials collection and export to XML + materials_file = openmc.Materials([inf_medium]) + materials_file.cross_sections = xslibname + model.materials = materials_file + + # Instantiate boundary Planes + min_x = openmc.XPlane(boundary_type='reflective', x0=-INF) + max_x = openmc.XPlane(boundary_type='reflective', x0=INF) + min_y = openmc.YPlane(boundary_type='reflective', y0=-INF) + max_y = openmc.YPlane(boundary_type='reflective', y0=INF) + + # Instantiate a Cell + cell = openmc.Cell(cell_id=1, name='cell') + cell.temperature = temperature + # Register bounding Surfaces with the Cell + cell.region = +min_x & -max_x & +min_y & -max_y + + # Fill the Cell with the Material + cell.fill = inf_medium + + # Create root universe + root_universe = openmc.Universe(name='root universe', cells=[cell]) + + # Create Geometry and set root Universe + model.geometry = openmc.Geometry(root_universe) + + # OpenMC simulation parameters + batches = 200 + inactive = 5 + particles = 5000 + + # Instantiate a Settings object + settings_file = openmc.Settings() + settings_file.batches = batches + settings_file.inactive = inactive + settings_file.particles = particles + settings_file.energy_mode = 'multi-group' + settings_file.output = {'summary': False} + # Create an initial uniform spatial source distribution over fissionable zones + bounds = [-INF, -INF, -INF, INF, INF, INF] + uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) + settings_file.temperature = {'method': tempmethod} + settings_file.source = openmc.Source(space=uniform_dist) + model.settings = settings_file + model.export_to_model_xml() diff --git a/tests/regression_tests/plot/geometry.xml b/tests/regression_tests/plot/geometry.xml deleted file mode 100644 index 83619d9f7..000000000 --- a/tests/regression_tests/plot/geometry.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot/materials.xml b/tests/regression_tests/plot/materials.xml deleted file mode 100644 index 90b354267..000000000 --- a/tests/regression_tests/plot/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot/model.xml b/tests/regression_tests/plot/model.xml new file mode 100644 index 000000000..a63ff95da --- /dev/null +++ b/tests/regression_tests/plot/model.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + plot + 1 + + 5 4 3 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + + + -10.0 10.0 + -10.0 10.0 + -10.0 0.0 5.0 7.5 8.75 10.0 + + + 2 + + + 1 + total + + + + + 0.0 0.0 0.0 + 25.0 25.0 + 200 200 + + + + + 0.0 0.0 0.0 + 25.0 25.0 + 200 200 + + + + + 0.0 0.0 0.0 + 25.0 25.0 + 200 200 + 0 0 0 + + + 0.0 0.0 0.0 + 20.0 20.0 10.0 + 100 100 10 + + + diff --git a/tests/regression_tests/plot/plots.xml b/tests/regression_tests/plot/plots.xml deleted file mode 100644 index ce63da144..000000000 --- a/tests/regression_tests/plot/plots.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 0. 0. 0. - 25 25 - 200 200 - - - - - - 0. 0. 0. - 25 25 - 200 200 - - - - - - 0. 0. 0. - 25 25 - 200 200 - 0 0 0 - - - - 100 100 10 - 0. 0. 0. - 20 20 10 - - - diff --git a/tests/regression_tests/plot/settings.xml b/tests/regression_tests/plot/settings.xml deleted file mode 100644 index adf256d2d..000000000 --- a/tests/regression_tests/plot/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - plot - - - 5 4 3 - -10 -10 -10 - 10 10 10 - - 1 - - diff --git a/tests/regression_tests/plot/tallies.xml b/tests/regression_tests/plot/tallies.xml deleted file mode 100644 index b7e678ca0..000000000 --- a/tests/regression_tests/plot/tallies.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - -10 10 - -10 10 - -10 0 5 7.5 8.75 10 - - - - mesh - 2 - - - - 1 - total - - - diff --git a/tests/regression_tests/plot_overlaps/geometry.xml b/tests/regression_tests/plot_overlaps/geometry.xml deleted file mode 100644 index 7a9f1fb41..000000000 --- a/tests/regression_tests/plot_overlaps/geometry.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_overlaps/materials.xml b/tests/regression_tests/plot_overlaps/materials.xml deleted file mode 100644 index 90b354267..000000000 --- a/tests/regression_tests/plot_overlaps/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_overlaps/model.xml b/tests/regression_tests/plot_overlaps/model.xml new file mode 100644 index 000000000..e3b65d45d --- /dev/null +++ b/tests/regression_tests/plot_overlaps/model.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + plot + 1 + + 5 4 3 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + + + 0.0 0.0 0.0 + 25.0 25.0 + 200 200 + + true + + + + 0.0 0.0 0.0 + 25.0 25.0 + 200 200 + + true + 255 211 0 + + + 0.0 0.0 0.0 + 25.0 25.0 + 200 200 + 0 0 0 + + + 0.0 0.0 0.0 + 20.0 20.0 10.0 + 100 100 10 + + + diff --git a/tests/regression_tests/plot_overlaps/plots.xml b/tests/regression_tests/plot_overlaps/plots.xml deleted file mode 100644 index 28064f58f..000000000 --- a/tests/regression_tests/plot_overlaps/plots.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - 0. 0. 0. - 25 25 - 200 200 - - - true - - - - 0. 0. 0. - 25 25 - 200 200 - - true - 255 211 0 - - - - 0. 0. 0. - 25 25 - 200 200 - 0 0 0 - - - - 100 100 10 - 0. 0. 0. - 20 20 10 - - - diff --git a/tests/regression_tests/plot_overlaps/settings.xml b/tests/regression_tests/plot_overlaps/settings.xml deleted file mode 100644 index adf256d2d..000000000 --- a/tests/regression_tests/plot_overlaps/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - plot - - - 5 4 3 - -10 -10 -10 - 10 10 10 - - 1 - - diff --git a/tests/regression_tests/plot_voxel/geometry.xml b/tests/regression_tests/plot_voxel/geometry.xml deleted file mode 100644 index 83619d9f7..000000000 --- a/tests/regression_tests/plot_voxel/geometry.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_voxel/materials.xml b/tests/regression_tests/plot_voxel/materials.xml deleted file mode 100644 index 90b354267..000000000 --- a/tests/regression_tests/plot_voxel/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_voxel/model.xml b/tests/regression_tests/plot_voxel/model.xml new file mode 100644 index 000000000..7b0e854c5 --- /dev/null +++ b/tests/regression_tests/plot_voxel/model.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + plot + 1 + + 5 4 3 + -10.0 -10.0 -10.0 + 10.0 10.0 10.0 + + + + + 0.0 0.0 0.0 + 20.0 20.0 10.0 + 50 50 10 + + + diff --git a/tests/regression_tests/plot_voxel/plots.xml b/tests/regression_tests/plot_voxel/plots.xml deleted file mode 100644 index 833329b42..000000000 --- a/tests/regression_tests/plot_voxel/plots.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - 50 50 10 - 0. 0. 0. - 20 20 10 - - - diff --git a/tests/regression_tests/plot_voxel/settings.xml b/tests/regression_tests/plot_voxel/settings.xml deleted file mode 100644 index adf256d2d..000000000 --- a/tests/regression_tests/plot_voxel/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - plot - - - 5 4 3 - -10 -10 -10 - 10 10 10 - - 1 - - diff --git a/tests/regression_tests/track_output/geometry.xml b/tests/regression_tests/track_output/geometry.xml deleted file mode 100644 index 5b16fe26c..000000000 --- a/tests/regression_tests/track_output/geometry.xml +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 1 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - - - - - - - - - - -85.8774 -85.8774 - 24.5364 24.5364 - - 999 999 130 140 150 999 999 - 999 220 230 240 250 260 999 - 130 320 777 222 333 360 150 - 410 240 444 111 666 240 470 - 510 520 888 555 998 560 570 - 999 620 630 240 650 660 999 - 999 999 510 740 570 999 999 - - - - - - - - diff --git a/tests/regression_tests/track_output/materials.xml b/tests/regression_tests/track_output/materials.xml deleted file mode 100644 index 5dc9a6475..000000000 --- a/tests/regression_tests/track_output/materials.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/track_output/model.xml b/tests/regression_tests/track_output/model.xml new file mode 100644 index 000000000..36ccb2b46 --- /dev/null +++ b/tests/regression_tests/track_output/model.xml @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 +2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 +2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 +2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 +2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 +2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 3 2 2 2 2 2 2 2 1 2 2 2 +2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + 1.63576 1.63576 + 15 15 + -12.2682 -12.2682 + +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + 24.5364 24.5364 + 7 7 + -85.8774 -85.8774 + +999 999 130 140 150 999 999 +999 220 230 240 250 260 999 +130 320 777 222 333 360 150 +410 240 444 111 666 240 470 +510 520 888 555 998 560 570 +999 620 630 240 650 660 999 +999 999 510 740 570 999 999 + + + + + + + + + + + + eigenvalue + 100 + 2 + 0 + + + -1.0 -1.0 -1.0 1.0 1.0 1.0 + + + 1 1 1 1 1 30 2 1 60 + + diff --git a/tests/regression_tests/track_output/settings.xml b/tests/regression_tests/track_output/settings.xml deleted file mode 100644 index dcfa118c8..000000000 --- a/tests/regression_tests/track_output/settings.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - eigenvalue - 2 - 0 - 100 - - - - - -1 -1 -1 1 1 1 - - - - - 1 1 1 - 1 1 30 - 2 1 60 - - - From 2d6938553a6a987d0b766ed5f42e4fe16669480e Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Sat, 25 Mar 2023 09:13:58 -0500 Subject: [PATCH 1677/2654] Update tests/unit_tests/test_deplete_activation.py Co-authored-by: Paul Romano --- tests/unit_tests/test_deplete_activation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index cef614f82..4c3d1de09 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -47,7 +47,7 @@ ENERGIES = np.logspace(log10(1e-5), log10(2e7), 100) ("direct", {}, 1e-5), ("flux", {'energies': ENERGIES}, 0.01), ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)']}, 1e-5), - ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)'], 'nuclides': ['W186', 'H3']}, 1e-5), + ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)'], 'nuclides': ['W186', 'H3']}, 1e-2), ]) def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts, tolerance): # Determine (n.gamma) reaction rate using initial run From 2aef18c02ac82c7c90d59466b199a58883018bd1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 25 Mar 2023 11:55:53 -0500 Subject: [PATCH 1678/2654] Loosen tolerance on coincidence check for cyl/sph meshes and parametrize tests --- src/mesh.cpp | 7 ++++--- tests/unit_tests/test_filter_mesh.py | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 306e56070..3ee489a68 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -500,7 +500,8 @@ void StructuredMesh::raytrace_mesh( } // translate start and end positions, - // this needs to come after the get_indices call because it does its own translation + // this needs to come after the get_indices call because it does its own + // translation local_coords(r0); local_coords(r1); @@ -1084,7 +1085,7 @@ double CylindricalMesh::find_r_crossing( D = std::sqrt(D); // the solution -p - D is always smaller as -p + D : Check this one first - if (-p - D > l && std::abs(c) > FP_COINCIDENT) + if (-p - D > l && std::abs(c) > 1e-10) return -p - D; if (-p + D > l) return -p + D; @@ -1310,7 +1311,7 @@ double SphericalMesh::find_r_crossing( if (D >= 0.0) { D = std::sqrt(D); // the solution -p - D is always smaller as -p + D : Check this one first - if (-p - D > l && std::abs(c) > FP_COINCIDENT) + if (-p - D > l && std::abs(c) > 1e-10) return -p - D; if (-p + D > l) return -p + D; diff --git a/tests/unit_tests/test_filter_mesh.py b/tests/unit_tests/test_filter_mesh.py index 5e5a84f7b..e3fae15be 100644 --- a/tests/unit_tests/test_filter_mesh.py +++ b/tests/unit_tests/test_filter_mesh.py @@ -114,15 +114,16 @@ def test_cylindrical_mesh_estimators(run_in_tmpdir): assert np.all(diff < 3*std_dev) -def test_cylindrical_mesh_coincident(run_in_tmpdir): +@pytest.mark.parametrize("scale", [1.0, 1e2, 1e4, 1e5]) +def test_cylindrical_mesh_coincident(scale, run_in_tmpdir): """Test for cylindrical mesh boundary being coincident with a cell boundary""" fuel = openmc.Material() fuel.add_nuclide('U235', 1.) fuel.set_density('g/cm3', 4.5) - zcyl = openmc.ZCylinder(r=1.25) - box = openmc.rectangular_prism(4.0, 4.0, boundary_type='reflective') + zcyl = openmc.ZCylinder(r=1.25*scale) + box = openmc.rectangular_prism(4*scale, 4*scale, boundary_type='reflective') cell1 = openmc.Cell(fill=fuel, region=-zcyl) cell2 = openmc.Cell(fill=None, region=+zcyl & box) model = openmc.Model() @@ -133,7 +134,7 @@ def test_cylindrical_mesh_coincident(run_in_tmpdir): model.settings.inactive = 0 cyl_mesh = openmc.CylindricalMesh() - cyl_mesh.r_grid = [0., 1.25] + cyl_mesh.r_grid = [0., 1.25*scale] cyl_mesh.phi_grid = [0., 2*math.pi] cyl_mesh.z_grid = [-1e10, 1e10] cyl_mesh_filter = openmc.MeshFilter(cyl_mesh) @@ -161,16 +162,18 @@ def test_cylindrical_mesh_coincident(run_in_tmpdir): assert mean1 == pytest.approx(mean2) -def test_spherical_mesh_coincident(run_in_tmpdir): +@pytest.mark.parametrize("scale", [1.0, 1e2, 1e4, 1e5]) +def test_spherical_mesh_coincident(scale, run_in_tmpdir): """Test for spherical mesh boundary being coincident with a cell boundary""" fuel = openmc.Material() fuel.add_nuclide('U235', 1.) fuel.set_density('g/cm3', 4.5) - sph = openmc.Sphere(r=1.25) + sph = openmc.Sphere(r=1.25*scale) rcc = openmc.model.RectangularParallelepiped( - -2.0, 2.0, -2.0, 2.0, -2.0, 2.0, boundary_type='reflective') + -2*scale, 2*scale, -2*scale, 2*scale, -2*scale, 2*scale, + boundary_type='reflective') cell1 = openmc.Cell(fill=fuel, region=-sph) cell2 = openmc.Cell(fill=None, region=+sph & -rcc) model = openmc.Model() @@ -181,7 +184,7 @@ def test_spherical_mesh_coincident(run_in_tmpdir): model.settings.inactive = 0 sph_mesh = openmc.SphericalMesh() - sph_mesh.r_grid = [0., 1.25] + sph_mesh.r_grid = [0., 1.25*scale] sph_mesh.phi_grid = [0., 2*math.pi] sph_mesh.theta_grid = [0., math.pi] sph_mesh_filter = openmc.MeshFilter(sph_mesh) From 5b7fb427d3cb4c5ba9fa2a5555004c10e2e53db1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 25 Mar 2023 15:36:11 -0500 Subject: [PATCH 1679/2654] Apply @pshriwise suggestion adding 0.1 to scale Co-authored-by: Patrick Shriwise --- tests/unit_tests/test_filter_mesh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_filter_mesh.py b/tests/unit_tests/test_filter_mesh.py index e3fae15be..c93bfa037 100644 --- a/tests/unit_tests/test_filter_mesh.py +++ b/tests/unit_tests/test_filter_mesh.py @@ -114,7 +114,7 @@ def test_cylindrical_mesh_estimators(run_in_tmpdir): assert np.all(diff < 3*std_dev) -@pytest.mark.parametrize("scale", [1.0, 1e2, 1e4, 1e5]) +@pytest.mark.parametrize("scale", [0.1, 1.0, 1e2, 1e4, 1e5]) def test_cylindrical_mesh_coincident(scale, run_in_tmpdir): """Test for cylindrical mesh boundary being coincident with a cell boundary""" @@ -162,7 +162,7 @@ def test_cylindrical_mesh_coincident(scale, run_in_tmpdir): assert mean1 == pytest.approx(mean2) -@pytest.mark.parametrize("scale", [1.0, 1e2, 1e4, 1e5]) +@pytest.mark.parametrize("scale", [0.1, 1.0, 1e2, 1e4, 1e5]) def test_spherical_mesh_coincident(scale, run_in_tmpdir): """Test for spherical mesh boundary being coincident with a cell boundary""" From b7250db6e130c37fe5e5dc54da9b57f7a1cbad38 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 26 Mar 2023 16:03:55 -0500 Subject: [PATCH 1680/2654] Update reference inputs for mgxs_library_specific_nuclides test --- .../inputs_true.dat | 433 +++++++++--------- 1 file changed, 216 insertions(+), 217 deletions(-) diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat index 061aa1b95..938b1c19d 100644 --- a/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_specific_nuclides/inputs_true.dat @@ -1,218 +1,217 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 2 3 - - - 0.0 0.625 20000000.0 - - - 1 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 2 - - - 3 - - - 383 2 - total - flux - tracklength - - - 1 2 - U235 total - total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) - tracklength - - - 383 2 - total - flux - analog - - - 1 5 6 - U235 total - scatter nu-scatter - analog - - - 1 2 - U235 total - nu-scatter - analog - - - 1 2 5 30 - U235 total - scatter nu-scatter - analog - - - 1 2 5 - U235 total - nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) - analog - - - 1 54 - U235 total - nu-fission prompt-nu-fission - analog - - - 1 5 - U235 total - nu-fission prompt-nu-fission - analog - - - 106 2 - Zr90 total - total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) - tracklength - - - 106 5 6 - Zr90 total - scatter nu-scatter - analog - - - 106 2 - Zr90 total - nu-scatter - analog - - - 106 2 5 30 - Zr90 total - scatter nu-scatter - analog - - - 106 2 5 - Zr90 total - nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) - analog - - - 106 54 - Zr90 total - nu-fission prompt-nu-fission - analog - - - 106 5 - Zr90 total - nu-fission prompt-nu-fission - analog - - - 251 2 - H1 total - total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) - tracklength - - - 251 5 6 - H1 total - scatter nu-scatter - analog - - - 251 2 - H1 total - nu-scatter - analog - - - 251 2 5 30 - H1 total - scatter nu-scatter - analog - - - 251 2 5 - H1 total - nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) - analog - - - 251 54 - H1 total - nu-fission prompt-nu-fission - analog - - - 251 5 - H1 total - nu-fission prompt-nu-fission - analog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + 1 2 3 + + + 0.0 0.625 20000000.0 + + + 1 + + + 0.0 0.625 20000000.0 + + + 1 + + + 3 + + + 0.0 20000000.0 + + + 2 + + + 3 + + + 383 2 + total + flux + tracklength + + + 1 2 + U235 total + total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) + tracklength + + + 383 2 + total + flux + analog + + + 1 5 6 + U235 total + scatter nu-scatter + analog + + + 1 2 + U235 total + nu-scatter + analog + + + 1 2 5 30 + U235 total + scatter nu-scatter + analog + + + 1 2 5 + U235 total + nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) + analog + + + 1 54 + U235 total + nu-fission prompt-nu-fission + analog + + + 1 5 + U235 total + nu-fission prompt-nu-fission + analog + + + 106 2 + Zr90 total + total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) + tracklength + + + 106 5 6 + Zr90 total + scatter nu-scatter + analog + + + 106 2 + Zr90 total + nu-scatter + analog + + + 106 2 5 30 + Zr90 total + scatter nu-scatter + analog + + + 106 2 5 + Zr90 total + nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) + analog + + + 106 54 + Zr90 total + nu-fission prompt-nu-fission + analog + + + 106 5 + Zr90 total + nu-fission prompt-nu-fission + analog + + + 251 2 + H1 total + total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0) + tracklength + + + 251 5 6 + H1 total + scatter nu-scatter + analog + + + 251 2 + H1 total + nu-scatter + analog + + + 251 2 5 30 + H1 total + scatter nu-scatter + analog + + + 251 2 5 + H1 total + nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n) + analog + + + 251 54 + H1 total + nu-fission prompt-nu-fission + analog + + + 251 5 + H1 total + nu-fission prompt-nu-fission + analog + + + From 6910e3657257ca1dcd6a00370614655afe6b3201 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 26 Mar 2023 23:22:25 -0500 Subject: [PATCH 1681/2654] Adjustment to coincidence checking and case for r_grid[0] == 0 --- src/mesh.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 3ee489a68..5eb400a4b 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1066,6 +1066,9 @@ double CylindricalMesh::find_r_crossing( // s^2 * (u^2 + v^2) + 2*s*(u*x+v*y) + x^2+y^2-r0^2 = 0 const double r0 = grid_[0][shell]; + if (r0 == 0.0) + return INFTY; + const double denominator = u.x * u.x + u.y * u.y; // Direction of flight is in z-direction. Will never intersect r. @@ -1085,6 +1088,9 @@ double CylindricalMesh::find_r_crossing( D = std::sqrt(D); // the solution -p - D is always smaller as -p + D : Check this one first + if (std::abs(c) <= 1e-10) + return INFTY; + if (-p - D > l && std::abs(c) > 1e-10) return -p - D; if (-p + D > l) @@ -1304,14 +1310,19 @@ double SphericalMesh::find_r_crossing( // solve |r+s*u| = r0 // |r+s*u| = |r| + 2*s*r*u + s^2 (|u|==1 !) const double r0 = grid_[0][shell]; + if (r0 == 0.0) + return INFTY; const double p = r.dot(u); double c = r.dot(r) - r0 * r0; double D = p * p - c; + if (std::abs(c) <= 1e-10) + return INFTY; + if (D >= 0.0) { D = std::sqrt(D); // the solution -p - D is always smaller as -p + D : Check this one first - if (-p - D > l && std::abs(c) > 1e-10) + if (-p - D > l) return -p - D; if (-p + D > l) return -p + D; From 160360a2a6d2cf1f9bdbbdefa921c2bbca8f394e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 27 Mar 2023 15:09:15 -0500 Subject: [PATCH 1682/2654] Remove old condition for cylindrical mesh --- src/mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 5eb400a4b..3d94d21a0 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1091,7 +1091,7 @@ double CylindricalMesh::find_r_crossing( if (std::abs(c) <= 1e-10) return INFTY; - if (-p - D > l && std::abs(c) > 1e-10) + if (-p - D > l) return -p - D; if (-p + D > l) return -p + D; From 13a9e8fae4567f2a19156f087f6e4f038f032b20 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 27 Mar 2023 15:17:15 -0500 Subject: [PATCH 1683/2654] Adding tests with void geometry for cylindrical and spherical mesh --- tests/unit_tests/test_cylindrical_mesh.py | 89 +++++++++++++++++++ tests/unit_tests/test_spherical_mesh.py | 100 ++++++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index 83ba09cc5..c8346bb4a 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -103,3 +103,92 @@ def test_offset_mesh(model, estimator, origin): mean[i, j, k] == 0.0 else: mean[i, j, k] != 0.0 + +@pytest.fixture() +def void_coincident_geom_model(): + """A model with many geometric boundaries coincident with mesh boundaries + across many scales + """ + openmc.reset_auto_ids() + model = openmc.model.Model() + + model.materials = openmc.Materials() + radii = [0.1,1, 5, 50, 100, 150, 250] + spheres = [openmc.Sphere(r=ri) for ri in radii] + spheres[-1].boundary_type = 'vacuum' + + regions = openmc.model.subdivide(spheres)[:-1] + cells = [openmc.Cell(region=r, fill=None) for r in regions] + geom = openmc.Geometry(cells) + + model.geometry = geom + + settings = openmc.Settings(run_mode='fixed source') + settings.batches = 2 + settings.particles = 1000 + model.settings = settings + + mesh = openmc.CylindricalMesh() + mesh.r_grid = np.linspace(0, 250, 501) + mesh.z_grid = [-250, 250] + mesh.phi_grid = np.linspace(0, 2*np.pi, 2) + mesh_filter = openmc.MeshFilter(mesh) + + tally = openmc.Tally() + tally.scores = ['flux'] + tally.filters = [mesh_filter] + + model.tallies = openmc.Tallies([tally]) + + return model + + +# convenience function for checking tally results +# in the following tests +def _check_void_cylindrical_tally(statepoint_filename): + with openmc.StatePoint(statepoint_filename) as sp: + flux_tally = sp.tallies[1] + mesh = flux_tally.find_filter(openmc.MeshFilter).mesh + neutron_flux = flux_tally.get_reshaped_data().squeeze() / mesh.volumes.flatten() + flux_diff = np.diff(neutron_flux) + # ensure flux values are monotonically decreasing due to + # geometric attenuation + assert (flux_diff < 0.0).all() + + +def test_void_geom_pnt_src(run_in_tmpdir, void_coincident_geom_model): + src = openmc.Source() + src.space = openmc.stats.Point() + src.angle = openmc.stats.PolarAzimuthal(mu=openmc.stats.Discrete([0.0], [1.0])) + src.energy = openmc.stats.Discrete([14.06e6], [1]) + void_coincident_geom_model.settings.source = src + + sp_filename = void_coincident_geom_model.run() + _check_void_cylindrical_tally(sp_filename) + + +def test_void_geom_boundary_src(run_in_tmpdir, void_coincident_geom_model): + bbox = void_coincident_geom_model.geometry.bounding_box + + outer_r = bbox[1][0] - 0.0001 + + radial_vals = np.linspace(0.0, 2.0*np.pi, 100) + + sources = [] + + energy = openmc.stats.Discrete([14.06e6], [1]) + for val in radial_vals: + src = openmc.Source() + src.energy = energy + + pnt = np.array([np.cos(val), np.sin(val), 0.0]) + u = -pnt + src.space = openmc.stats.Point(outer_r*pnt) + src.angle = openmc.stats.Monodirectional(u) + + sources.append(src) + + void_coincident_geom_model.settings.source = sources + sp_filename = void_coincident_geom_model.run() + + _check_void_cylindrical_tally(sp_filename) \ No newline at end of file diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index 73153f5cc..860156671 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -107,3 +107,103 @@ def test_offset_mesh(model, estimator, origin): mean[i, j, k] == 0.0 else: mean[i, j, k] != 0.0 + +# Some void geometry tests to check our radial intersection methods on +# spherical and cylindrical meshes + +@pytest.fixture() +def void_coincident_geom_model(): + """A model with many geometric boundaries coincident with mesh boundaries + across many scales + """ + openmc.reset_auto_ids() + + model = openmc.Model() + + model.materials = openmc.Materials() + radii = [0.1, 1, 5, 50, 100, 150, 250] + spheres = [openmc.Sphere(r=ri) for ri in radii] + spheres[-1].boundary_type = 'vacuum' + + regions = openmc.model.subdivide(spheres)[:-1] + cells = [openmc.Cell(region=r, fill=None) for r in regions] + geom = openmc.Geometry(cells) + + model.geometry = geom + + settings = openmc.Settings(run_mode='fixed source') + settings.batches = 2 + settings.particles = 5000 + model.settings = settings + + mesh = openmc.SphericalMesh() + mesh.r_grid = np.linspace(0, 250, 501) + mesh_filter = openmc.MeshFilter(mesh) + + tally = openmc.Tally() + tally.scores = ['flux'] + tally.filters = [mesh_filter] + + model.tallies = openmc.Tallies([tally]) + + return model + + +# convenience function for checking tally results +# in the following tests +def _check_void_spherical_tally(statepoint_filename): + with openmc.StatePoint(statepoint_filename) as sp: + flux_tally = sp.tallies[1] + mesh = flux_tally.find_filter(openmc.MeshFilter).mesh + neutron_flux = flux_tally.get_reshaped_data().squeeze() / mesh.volumes.flatten() + flux_diff = np.diff(neutron_flux) + # ensure flux values are monotonically decreasing due to + # geometric attenuation + assert (flux_diff < 0.0).all() + + +def test_void_geom_pnt_src(run_in_tmpdir, void_coincident_geom_model): + # add isotropic point source + src = openmc.Source() + src.space = openmc.stats.Point() + src.energy = openmc.stats.Discrete([14.06e6], [1]) + void_coincident_geom_model.settings.source = src + + sp_filename = void_coincident_geom_model.run() + + _check_void_spherical_tally(sp_filename) + + +def test_void_geom_boundary_src(run_in_tmpdir, void_coincident_geom_model): + # update source to a number of points on the outside of the sphere + # with directions pointing toward the origin + + # sources + phi_vals = np.linspace(0, np.pi, 20) + theta_vals = np.linspace(0, 2.0*np.pi, 20) + + bbox = void_coincident_geom_model.geometry.bounding_box + # can't source particles directly on the geometry boundary + outer_r = bbox[1][0] - 0.00001 + + sources = [] + + energy = openmc.stats.Discrete([14.06e6], [1]) + + for phi, theta in zip(phi_vals, theta_vals): + + src = openmc.Source() + src.energy = energy + + pnt = np.array([np.sin(phi)*np.cos(theta), np.sin(phi)*np.sin(theta), np.cos(phi)]) + u = -pnt + src.space = openmc.stats.Point(outer_r*pnt) + src.angle = openmc.stats.Monodirectional(u) + + sources.append(src) + + void_coincident_geom_model.settings.source = sources + + sp_filename = void_coincident_geom_model.run() + + _check_void_spherical_tally(sp_filename) From ab403b2fc8cf0aed15065c7caeafdfa79f4c07af Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 27 Mar 2023 16:15:38 -0500 Subject: [PATCH 1684/2654] Improvements to tests --- tests/unit_tests/test_cylindrical_mesh.py | 22 ++++++++++++-------- tests/unit_tests/test_spherical_mesh.py | 25 ++++++++++++----------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index c8346bb4a..27c4d5a1f 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -149,12 +149,12 @@ def _check_void_cylindrical_tally(statepoint_filename): with openmc.StatePoint(statepoint_filename) as sp: flux_tally = sp.tallies[1] mesh = flux_tally.find_filter(openmc.MeshFilter).mesh - neutron_flux = flux_tally.get_reshaped_data().squeeze() / mesh.volumes.flatten() - flux_diff = np.diff(neutron_flux) - # ensure flux values are monotonically decreasing due to - # geometric attenuation - assert (flux_diff < 0.0).all() - + neutron_flux = flux_tally.get_reshaped_data().squeeze() + # we expect the tally results to be the same as the mesh grid width + # for these cases + print(neutron_flux) + d_r = mesh.r_grid[1] - mesh.r_grid[0] + assert neutron_flux == pytest.approx(d_r) def test_void_geom_pnt_src(run_in_tmpdir, void_coincident_geom_model): src = openmc.Source() @@ -168,11 +168,15 @@ def test_void_geom_pnt_src(run_in_tmpdir, void_coincident_geom_model): def test_void_geom_boundary_src(run_in_tmpdir, void_coincident_geom_model): + # update source to a number of points on the outside of the cylinder + # with directions pointing toward the origin bbox = void_coincident_geom_model.geometry.bounding_box - outer_r = bbox[1][0] - 0.0001 + # can't source particle directly on the geometry boundary + outer_r = bbox[1][0] - 1e-08 - radial_vals = np.linspace(0.0, 2.0*np.pi, 100) + n_sources = 100 + radial_vals = np.linspace(0.0, 2.0*np.pi, n_sources) sources = [] @@ -185,7 +189,7 @@ def test_void_geom_boundary_src(run_in_tmpdir, void_coincident_geom_model): u = -pnt src.space = openmc.stats.Point(outer_r*pnt) src.angle = openmc.stats.Monodirectional(u) - + src.strength = 0.5/n_sources sources.append(src) void_coincident_geom_model.settings.source = sources diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index 860156671..0f02e9699 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -155,11 +155,11 @@ def _check_void_spherical_tally(statepoint_filename): with openmc.StatePoint(statepoint_filename) as sp: flux_tally = sp.tallies[1] mesh = flux_tally.find_filter(openmc.MeshFilter).mesh - neutron_flux = flux_tally.get_reshaped_data().squeeze() / mesh.volumes.flatten() - flux_diff = np.diff(neutron_flux) - # ensure flux values are monotonically decreasing due to - # geometric attenuation - assert (flux_diff < 0.0).all() + neutron_flux = flux_tally.get_reshaped_data().squeeze() + # the flux values for each bin should equal the width + # width of the mesh bins + d_r = mesh.r_grid[1] - mesh.r_grid[0] + assert neutron_flux == pytest.approx(d_r) def test_void_geom_pnt_src(run_in_tmpdir, void_coincident_geom_model): @@ -169,22 +169,21 @@ def test_void_geom_pnt_src(run_in_tmpdir, void_coincident_geom_model): src.energy = openmc.stats.Discrete([14.06e6], [1]) void_coincident_geom_model.settings.source = src + # run model and check tally results sp_filename = void_coincident_geom_model.run() - _check_void_spherical_tally(sp_filename) def test_void_geom_boundary_src(run_in_tmpdir, void_coincident_geom_model): # update source to a number of points on the outside of the sphere # with directions pointing toward the origin - - # sources - phi_vals = np.linspace(0, np.pi, 20) - theta_vals = np.linspace(0, 2.0*np.pi, 20) + n_sources = 20 + phi_vals = np.linspace(0, np.pi, n_sources) + theta_vals = np.linspace(0, 2.0*np.pi, n_sources) bbox = void_coincident_geom_model.geometry.bounding_box # can't source particles directly on the geometry boundary - outer_r = bbox[1][0] - 0.00001 + outer_r = bbox[1][0] - 1e-08 sources = [] @@ -199,11 +198,13 @@ def test_void_geom_boundary_src(run_in_tmpdir, void_coincident_geom_model): u = -pnt src.space = openmc.stats.Point(outer_r*pnt) src.angle = openmc.stats.Monodirectional(u) + # set source strengths so that we can still expect + # a tally value of 0.5 + src.strength = 0.5/n_sources sources.append(src) void_coincident_geom_model.settings.source = sources sp_filename = void_coincident_geom_model.run() - _check_void_spherical_tally(sp_filename) From 63fa42843b04966d75bb4eb0c3a91e12e531d2b9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 27 Mar 2023 16:50:18 -0500 Subject: [PATCH 1685/2654] Removing unused print statements --- tests/unit_tests/test_cylindrical_mesh.py | 2 -- tests/unit_tests/test_spherical_mesh.py | 1 - 2 files changed, 3 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index 27c4d5a1f..cbdb1d315 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -98,7 +98,6 @@ def test_offset_mesh(model, estimator, origin): centroids = mesh.centroids for ijk in mesh.indices: i, j, k = np.array(ijk) - 1 - print(centroids[:, i, j, k]) if model.geometry.find(centroids[:, i, j, k]): mean[i, j, k] == 0.0 else: @@ -152,7 +151,6 @@ def _check_void_cylindrical_tally(statepoint_filename): neutron_flux = flux_tally.get_reshaped_data().squeeze() # we expect the tally results to be the same as the mesh grid width # for these cases - print(neutron_flux) d_r = mesh.r_grid[1] - mesh.r_grid[0] assert neutron_flux == pytest.approx(d_r) diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index 0f02e9699..ba3167d6f 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -102,7 +102,6 @@ def test_offset_mesh(model, estimator, origin): centroids = mesh.centroids for ijk in mesh.indices: i, j, k = np.array(ijk) - 1 - print(centroids[:, i, j, k]) if model.geometry.find(centroids[:, i, j, k]): mean[i, j, k] == 0.0 else: From 26c031a041e110b1ac944044c5d011e4b874b20d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 27 Mar 2023 16:54:42 -0500 Subject: [PATCH 1686/2654] Run tests in tmpdir to keep repo clean --- tests/unit_tests/test_cylindrical_mesh.py | 2 +- tests/unit_tests/test_spherical_mesh.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index cbdb1d315..2be0f4962 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -75,7 +75,7 @@ def label(p): return f'estimator:{p}' @pytest.mark.parametrize('estimator,origin', test_cases, ids=label) -def test_offset_mesh(model, estimator, origin): +def test_offset_mesh(run_in_tmpdir, model, estimator, origin): """Tests that the mesh has been moved based on tally results """ mesh = model.tallies[0].filters[0].mesh diff --git a/tests/unit_tests/test_spherical_mesh.py b/tests/unit_tests/test_spherical_mesh.py index ba3167d6f..ac2781378 100644 --- a/tests/unit_tests/test_spherical_mesh.py +++ b/tests/unit_tests/test_spherical_mesh.py @@ -79,7 +79,7 @@ def label(p): return f'estimator:{p}' @pytest.mark.parametrize('estimator,origin', test_cases, ids=label) -def test_offset_mesh(model, estimator, origin): +def test_offset_mesh(run_in_tmpdir, model, estimator, origin): """Tests that the mesh has been moved based on tally results """ mesh = model.tallies[0].filters[0].mesh From e41ae3604ea6a7448219be7ae764337ac0043edc Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Mon, 27 Mar 2023 18:36:49 -0500 Subject: [PATCH 1687/2654] Clone material. Refs #2442 --- include/openmc/material.h | 3 +++ src/material.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/openmc/material.h b/include/openmc/material.h index 8db9bb628..36a6acf93 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -90,6 +90,9 @@ public: void set_densities( const vector& name, const vector& density); + //! Clone the material by deep-copying all members + void clone(); + //---------------------------------------------------------------------------- // Accessors diff --git a/src/material.cpp b/src/material.cpp index 74a8d7e35..ec82a7eea 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -353,6 +353,37 @@ Material::~Material() model::material_map.erase(id_); } +void Material::clone() +{ + std::unique_ptr mat = std::make_unique(); + mat->index_ = model::materials.size(); + mat->set_id(C_NONE); + + // set all other parameters to whatever the calling Material has + mat->name_ = name_; + mat->nuclide_ = nuclide_; + mat->element_ = element_; + mat->ncrystal_mat_ = ncrystal_mat_; + mat->atom_density_ = atom_density_; + mat->density_ = density_; + mat->density_gpcc_ = density_gpcc_; + mat->volume_ = volume_; + mat->fissionable_ = fissionable_; + mat->depletable_ = depletable_; + mat->p0_ = p0_; + mat->mat_nuclide_index_ = mat_nuclide_index_; + mat->thermal_tables_ = thermal_tables_; + mat->temperature_ = temperature_; + + if (ttb_) + { + std::unique_ptr ptr2{new Bremsstrahlung{*ttb_}}; + mat->ttb_ = std::move(ptr2); + } + + model::materials.push_back(std::move(mat)); +} + void Material::finalize() { // Set fissionable if any nuclide is fissionable From a44c1f89de907292863b47ecdc62b10cb6685d40 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Mon, 27 Mar 2023 19:21:30 -0500 Subject: [PATCH 1688/2654] Address review comments. Refs #2442 --- src/material.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/material.cpp b/src/material.cpp index ec82a7eea..165a5c2e7 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -353,7 +353,7 @@ Material::~Material() model::material_map.erase(id_); } -void Material::clone() +Material & Material::clone() { std::unique_ptr mat = std::make_unique(); mat->index_ = model::materials.size(); @@ -376,12 +376,10 @@ void Material::clone() mat->temperature_ = temperature_; if (ttb_) - { - std::unique_ptr ptr2{new Bremsstrahlung{*ttb_}}; - mat->ttb_ = std::move(ptr2); - } + mat->ttb_ = std::make_unique(*ttb_); model::materials.push_back(std::move(mat)); + return *mat; } void Material::finalize() From fa222a4b314dac399d471fd2016e839a9c98549a Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Mon, 27 Mar 2023 19:23:04 -0500 Subject: [PATCH 1689/2654] Address review comments. --- include/openmc/material.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/material.h b/include/openmc/material.h index 36a6acf93..36d7c34c6 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -91,7 +91,7 @@ public: const vector& name, const vector& density); //! Clone the material by deep-copying all members - void clone(); + Material & clone(); //---------------------------------------------------------------------------- // Accessors From e5863eec1b80a24ffb471eb8287125c1e18d00db Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 28 Mar 2023 07:35:22 -0500 Subject: [PATCH 1690/2654] Correcting variable name --- tests/unit_tests/test_cylindrical_mesh.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index 2be0f4962..caf933360 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -113,10 +113,10 @@ def void_coincident_geom_model(): model.materials = openmc.Materials() radii = [0.1,1, 5, 50, 100, 150, 250] - spheres = [openmc.Sphere(r=ri) for ri in radii] - spheres[-1].boundary_type = 'vacuum' + cylinders = [openmc.Sphere(r=ri) for ri in radii] + cylinders[-1].boundary_type = 'vacuum' - regions = openmc.model.subdivide(spheres)[:-1] + regions = openmc.model.subdivide(cylinders)[:-1] cells = [openmc.Cell(region=r, fill=None) for r in regions] geom = openmc.Geometry(cells) From 86e9a4bd4b1c619e3f39b761a3a81658665ded19 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 28 Mar 2023 08:47:42 -0500 Subject: [PATCH 1691/2654] Adding constants for coincidence checking --- include/openmc/constants.h | 4 ++++ src/mesh.cpp | 4 ++-- src/surface.cpp | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/openmc/constants.h b/include/openmc/constants.h index 2a867c0ca..b0031fae3 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -51,6 +51,10 @@ constexpr double FP_PRECISION {1e-14}; constexpr double FP_REL_PRECISION {1e-5}; constexpr double FP_COINCIDENT {1e-12}; +// Coincidence tolerances +constexpr double TORUS_TOL {1e-10}; +constexpr double RADIAL_MESH_TOL {1e-10}; + // Maximum number of random samples per history constexpr int MAX_SAMPLE {100000}; diff --git a/src/mesh.cpp b/src/mesh.cpp index 3d94d21a0..e72a5cf7d 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1088,7 +1088,7 @@ double CylindricalMesh::find_r_crossing( D = std::sqrt(D); // the solution -p - D is always smaller as -p + D : Check this one first - if (std::abs(c) <= 1e-10) + if (std::abs(c) <= RADIAL_MESH_TOL) return INFTY; if (-p - D > l) @@ -1316,7 +1316,7 @@ double SphericalMesh::find_r_crossing( double c = r.dot(r) - r0 * r0; double D = p * p - c; - if (std::abs(c) <= 1e-10) + if (std::abs(c) <= RADIAL_MESH_TOL) return INFTY; if (D >= 0.0) { diff --git a/src/surface.cpp b/src/surface.cpp index c0b3f0a59..2403d0c6a 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -1044,7 +1044,7 @@ double torus_distance(double x1, double x2, double x3, double u1, double u2, // zero but possibly small and positive. A tolerance is set to discard that // zero. double distance = INFTY; - double cutoff = coincident ? 1e-10 : 0.0; + double cutoff = coincident ? TORUS_TOL : 0.0; for (int i = 0; i < 4; ++i) { if (roots[i].imag() == 0) { double root = roots[i].real(); From 6cb4401230e9189169a4754180ec3d6a2b3e20b1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 28 Mar 2023 10:11:14 -0500 Subject: [PATCH 1692/2654] Correcting surface type in cylinder tests --- tests/unit_tests/test_cylindrical_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_cylindrical_mesh.py b/tests/unit_tests/test_cylindrical_mesh.py index caf933360..4382b49ba 100644 --- a/tests/unit_tests/test_cylindrical_mesh.py +++ b/tests/unit_tests/test_cylindrical_mesh.py @@ -113,7 +113,7 @@ def void_coincident_geom_model(): model.materials = openmc.Materials() radii = [0.1,1, 5, 50, 100, 150, 250] - cylinders = [openmc.Sphere(r=ri) for ri in radii] + cylinders = [openmc.ZCylinder(r=ri) for ri in radii] cylinders[-1].boundary_type = 'vacuum' regions = openmc.model.subdivide(cylinders)[:-1] From 7bbf5466e6aec1c7610e69e8c7a6f144e8951f1d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 26 Mar 2023 11:15:36 -0500 Subject: [PATCH 1693/2654] Add missing versionadded directives --- openmc/deplete/results.py | 2 ++ openmc/filter.py | 2 ++ openmc/geometry.py | 2 ++ openmc/model/model.py | 2 ++ openmc/model/surface_composite.py | 4 +++- openmc/tallies.py | 2 ++ 6 files changed, 13 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 3602d6918..c9dc19816 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -398,6 +398,8 @@ class Results(list): path : PathLike Path to materials XML file to read. Defaults to 'materials.xml'. + .. versionadded:: 0.13.3 + Returns ------- mat_file : Materials diff --git a/openmc/filter.py b/openmc/filter.py index 3240c9e25..cc7bdd931 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1349,6 +1349,8 @@ class EnergyFilter(RealFilter): (e.g., a source spectrum) based on tally results that were obtained from using an :class:`~openmc.EnergyFilter`. + .. versionadded:: 0.13.3 + Parameters ---------- values : iterable of float diff --git a/openmc/geometry.py b/openmc/geometry.py index d01826a4d..ad86cc56b 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -537,6 +537,8 @@ class Geometry: def get_surfaces_by_name(self, name, case_sensitive=False, matching=False): """Return a list of surfaces with matching names. + .. versionadded:: 0.13.3 + Parameters ---------- name : str diff --git a/openmc/model/model.py b/openmc/model/model.py index 78f02242f..4202cf60b 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -644,6 +644,8 @@ class Model: Exports a single model.xml file rather than separate files. Defaults to True. + .. versionadded:: 0.13.3 + Returns ------- Path diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 354a62883..25826723c 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -632,6 +632,8 @@ class ZConeOneSided(CompositeSurface): class Polygon(CompositeSurface): """Create a polygon composite surface from a path of closed points. + .. versionadded:: 0.13.3 + Parameters ---------- points : np.ndarray @@ -927,7 +929,7 @@ class Polygon(CompositeSurface): if group is None: sidx = next(iter(neighbor_map)) return self._group_simplices(neighbor_map, group=[sidx]) - # Otherwise use the last simplex in the group + # Otherwise use the last simplex in the group else: sidx = group[-1] # Remove current simplex from dictionary since it is in a group diff --git a/openmc/tallies.py b/openmc/tallies.py index 688369de0..1a27e1bd4 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1436,6 +1436,8 @@ class Tally(IDManagerMixin): dimensions. This will result in more than one dimension per filter for the returned data array. + .. versionadded:: 0.13.3 + Returns ------- numpy.ndarray From 75dcf5b9a77f27eeb6e971e9b606360b0dc1bbf9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 26 Mar 2023 11:16:23 -0500 Subject: [PATCH 1694/2654] Add release notes for 0.13.3 --- docs/source/releasenotes/0.13.2.rst | 2 +- docs/source/releasenotes/0.13.3.rst | 134 ++++++++++++++++++++++++++++ docs/source/releasenotes/index.rst | 1 + 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 docs/source/releasenotes/0.13.3.rst diff --git a/docs/source/releasenotes/0.13.2.rst b/docs/source/releasenotes/0.13.2.rst index e9175358b..b0c9b0691 100644 --- a/docs/source/releasenotes/0.13.2.rst +++ b/docs/source/releasenotes/0.13.2.rst @@ -14,7 +14,7 @@ Notably, a capability has been added to compute the photon spectra from decay of unstable nuclides. Alongside that, a new :data:`openmc.config` configuration variable has been introduced that allows easier configuration of data sources. Additionally, users can now perform cell or material rejection when sampling -external source distributions. Finally, +external source distributions. ------------------------------------ Compatibility Notes and Deprecations diff --git a/docs/source/releasenotes/0.13.3.rst b/docs/source/releasenotes/0.13.3.rst new file mode 100644 index 000000000..c2debbcb3 --- /dev/null +++ b/docs/source/releasenotes/0.13.3.rst @@ -0,0 +1,134 @@ +==================== +What's New in 0.13.3 +==================== + +.. currentmodule:: openmc + +------- +Summary +------- + +This release of OpenMC includes many bug fixes, performance improvements, and +several notable new features. Some of the highlights include support for MCPL +source files, NCrystal thermal scattering materials, and a new +:class:`openmc.stats.MeshSpatial` class that allows a source distribution to be +specified over a mesh. Additionally, OpenMC now allows you to export your model +as a single XML file rather than separate XML files for geometry, materials, +settings, and tallies. + +------------------------------------ +Compatibility Notes and Deprecations +------------------------------------ + +- Atomic mass data used in :func:`openmc.data.atomic_mass` has been updated to + AME 2020, which results in slightly different masses. + +------------ +New Features +------------ + +- Support was added for `MCPL `_ files to be + used as external sources. Additionally, source points and surfaces sources can + be written as MCPL files instead of HDF5 files. (`#2116 + `_) +- Support was added for `NCrystal `_ + thermal scattering materials. (`#2222 + `_) +- The :class:`~openmc.CylindricalMesh` and :class:`~openmc.SphericalMesh` + classes now have an ``origin`` attribute that changes the center of the mesh. + (`#2256 `_) +- A new :class:`openmc.model.Polygon` class allows defining generalized 2D + polygons. (`#2266 `_) +- A new :func:`openmc.data.decay_energy` function and + :meth:`openmc.Material.get_decay_heat` method enable determination of decay + heat from a single nuclide or material. (`#2287 + `_) +- Full models can now be written as a single XML file rather than separate + geometry, materials, settings, and tallies XML files. (`#2291 + `_) +- Discrete distributions are now sampled using alias sampling, which is O(1) in + time. (`#2329 `_) +- The new :class:`openmc.stats.MeshSpatial` allows a spatial source distribution + to be specified with source strengths for each mesh element. (`#2334 + `_) +- The new :meth:`openmc.Geometry.get_surfaces_by_name` method returns a list of + matching surfaces in a geometry. (`#2347 + `_) +- A new :attr:`openmc.Settings.create_delayed_neutrons` attribute controls + whether delayed neutrons are created during a simulation. (`#2348 + `_) +- The :meth:`openmc.deplete.Results.export_to_materials` method now takes a + ``path`` argument. (`#2364 `_) +- A new :meth:`openmc.EnergyFilter.get_tabular` method allows one to create a + tabular distribution based on tally results using an energy filter. (`#2371 + `_) +- Several methods in the :class:`openmc.Material` class that require a volume to + be set (e.g., :meth:`~openmc.Material.get_mass`) now accept a ``volume`` + argument. (`#2412 `_) + +--------- +Bug Fixes +--------- + +- Fix for finding redundant surfaces (`#2263 `_) +- Adds tolerance for temperatures slightly out of bounds (`#2265 `_) +- Fix getter/setter for weight window bounds (`#2275 `_) +- Make sure Chain.reduce preserves decay source (`#2283 `_) +- Fix array shape for weight window bounds (`#2284 `_) +- Fix for non-zero CDF start points in TSL data (`#2290 `_) +- Fix a case where inelastic scattering yield is zero (`#2295 `_) +- Prevent Compton profile out-of-bounds memory access (`#2297 `_) +- Produce light particles from decay (`#2301 `_) +- Fix zero runtime attributes in depletion statepoints (`#2302 `_) +- Fix bug in openmc.Universe.get_nuclide_densities (`#2310 `_) +- Only show print output from depletion on rank 0 (`#2311 `_) +- Fix photon transport with no atomic relaxation data (`#2312 `_) +- Fix for precedence in region expressions (`#2318 `_) +- Allow source particles with energy below cutoff (`#2319 `_) +- Fix IncidentNeutron.from_njoy for high temperatures (`#2320 `_) +- Add capability to unset cell temperatures (`#2323 `_) +- Fix in plot_xs when S(a,b) tables are present (`#2335 `_) +- Various fixes for tally triggers (`#2344 `_) +- Raise error when mesh is flat (`#2363 `_) +- Don't call normalize inside Tabular.mean (`#2375 `_) +- Avoid out-of-bounds access in inelastic scatter sampling (`#2378 `_) +- Use correct direction for anisotropic fission (`#2381 `_) +- Fix several thermal scattering nuclide assignments (`#2382 `_) +- Fix _materials_by_id attribute in Model (`#2385 `_) +- Updates to batch checks for simulation restarts (`#2390 `_) +- write_data_to_vtk volume normalization correction (`#2397 `_) +- Enable generation of JEFF 3.3 depletion chain (`#2410 `_) +- Fix spherical to Cartesian coordinate conversion (`#2417 `_) +- Handle zero photon cross sections in IncidentPhoton.from_ace (`#2433 `_) +- Fix hybrid depletion when nuclides are not present (`#2436 `_) +- Fix bug in cylindrical and spherical meshes (`#2439 `_) +- Improvements to mesh radial boundary coincidence (`#2443 `_) + +------------ +Contributors +------------ + +- `Hunter Belanger `_ +- `Rémi Delaporte-Mathurin `_ +- `Christopher Fichtlscherer `_ +- `Valerio Giusti `_ +- `Chris Keckler `_ +- `Kalin Kiesling `_ +- `Thomas Kittelmann `_ +- `Erik Knudsen `_ +- `Colin Larmier `_ +- `Amanda Lund `_ +- `Jose Ignacio Marquez Damien `_ +- `Josh May `_ +- `Patrick Myers `_ +- `Baptiste Mouginot `_ +- `April Novak `_ +- `Matthew Nyberg `_ +- `Ethan Peterson `_ +- `Gavin Ridley `_ +- `Paul Romano `_ +- `Patrick Shriwise `_ +- `Jonathan Shimwell `_ +- `Paul Wilson `_ +- `Olek Yardas `_ +- `Jiankai Yu `_ diff --git a/docs/source/releasenotes/index.rst b/docs/source/releasenotes/index.rst index 910737a41..30b6d51de 100644 --- a/docs/source/releasenotes/index.rst +++ b/docs/source/releasenotes/index.rst @@ -7,6 +7,7 @@ Release Notes .. toctree:: :maxdepth: 1 + 0.13.3 0.13.2 0.13.1 0.13.0 From 2f50599d4f347d5a247f0ca8c3f5419d2b8b6301 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 26 Mar 2023 16:15:23 -0500 Subject: [PATCH 1695/2654] Update install instructions --- docs/source/usersguide/install.rst | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 899e16506..af6a93f9d 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -277,7 +277,7 @@ Prerequisites Lists) files instead of .h5 files for sources (external source distribution, k-eigenvalue source distribution, and surface sources). To turn this option on in the CMake configuration step, add the following - option: + option:: cmake -DOPENMC_USE_MCPL=on .. @@ -288,7 +288,7 @@ Prerequisites on-the-fly approach. To use it `install `_ and `initialize `_ - NCrystal and turn on the option in the CMake configuration step: + NCrystal and turn on the option in the CMake configuration step:: cmake -DOPENMC_USE_NCRYSTAL=on .. @@ -299,7 +299,7 @@ Prerequisites be used, but the implementation is currently restricted to collision estimators. In addition to turning this option on, the path to the libMesh installation should be specified as part of the ``CMAKE_PREFIX_PATH`` - variable.:: + variable:: cmake -DOPENMC_USE_LIBMESH=on -DOPENMC_USE_MPI=on -DCMAKE_PREFIX_PATH=/path/to/libmesh/installation .. @@ -371,6 +371,10 @@ CMakeLists.txt Options The following options are available in the CMakeLists.txt file: +OPENMC_ENABLE_COVERAGE + Compile and link code instrumented for coverage analysis. This is typically + used in conjunction with gcov_. (Default: off) + OPENMC_ENABLE_PROFILE Enables profiling using the GNU profiler, gprof. (Default: off) @@ -385,22 +389,23 @@ OPENMC_USE_DAGMC should also be defined as `DAGMC_ROOT` in the CMake configuration command. (Default: off) +OPENMC_USE_MCPL + Turns on support for reading MCPL_ source files and writing MCPL source points + and surface sources. (Default: off) + OPENMC_USE_NCRYSTAL - Turns on support for NCrystal materials. NCrystal must be - `installed `_ and - `initialized `_. + Turns on support for NCrystal materials. NCrystal must be `installed + `_ and `initialized + `_. (Default: off) OPENMC_USE_LIBMESH Enables the use of unstructured mesh tallies with libMesh_. (Default: off) -OPENMC_ENABLE_COVERAGE - Compile and link code instrumented for coverage analysis. This is typically - used in conjunction with gcov_. (Default: off) - OPENMC_USE_MPI - Turns on compiling with MPI (default: off). For further information on MPI options, - please see the `FindMPI.cmake documentation `_. + Turns on compiling with MPI (Default: off). For further information on MPI + options, please see the `FindMPI.cmake documentation + `_. To set any of these options (e.g., turning on profiling), the following form should be used: From 8a5fb8a8b067e5a333176e51f19a7b581863b339 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 26 Mar 2023 16:15:43 -0500 Subject: [PATCH 1696/2654] Update version number to 0.13.3 --- include/openmc/version.h.in | 2 +- openmc/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index e1c2b0541..a518e0d63 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -10,7 +10,7 @@ namespace openmc { constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {true}; +constexpr bool VERSION_DEV {false}; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/openmc/__init__.py b/openmc/__init__.py index cbf4d9ae2..f94cd038f 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -38,4 +38,4 @@ from .config import * from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.13.3-dev' +__version__ = '0.13.3' From e7a688a867f84bc764117b1b492d172978a7fa33 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 28 Mar 2023 10:27:46 -0500 Subject: [PATCH 1697/2654] Update Spack installation instructions --- docs/source/usersguide/install.rst | 31 +++++++++++++----------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index af6a93f9d..ed02c5d9f 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -105,9 +105,9 @@ other information use: .. note:: - It should be noted that by default OpenMC builds with ``-O2 -g`` flags which - are equivalent to a CMake build type of `RelwithDebInfo`. In addition, MPI - is OFF while OpenMP is ON. + It should be noted that by default OpenMC is built with + `-DCMAKE_BUILD_TYPE=RelwithDebInfo`. In addition, MPI is OFF while OpenMP is + ON. It is recommended to install OpenMC with the Python API. Information about this Spack recipe can be found with the following command: @@ -133,17 +133,18 @@ following command: configured defaults unless otherwise specfied in the specification on the command line. In the above example, assuming the default options weren't changed in Spack's package configuration, py-openmc will link against a - non-optimized non-MPI openmc. Even if an optimized openmc was built - separately, it will rebuild openmc with optimization OFF. Thus, if you are - trying to link against dependencies that were configured different than - defaults, ``^openmc[variants]`` will have to be present in the command. + non-MPI non-release build of openmc. Even if a release build of openmc was + built separately, it will rebuild openmc with the default build type. Thus, + if you are trying to link against dependencies that were configured + different than defaults, ``^openmc[variants]`` will have to be present in + the command. -For a more performant build of OpenMC with optimization turned ON and MPI -provided by OpenMPI, the following command can be used: +For a release build of OpenMC with MPI support on (provided by OpenMPI), the +following command can be used: .. code-block:: sh - spack install py-openmc+mpi ^openmc+optimize ^openmpi + spack install py-openmc +mpi ^openmpi ^openmc build_type=Release .. note:: @@ -163,7 +164,7 @@ This can be observed using Spack's ``spec`` tool: .. code-block:: - spack spec py-openmc+mpi ^openmc+optimize + spack spec py-openmc +mpi ^openmc build_type=Release Once installed, environment/lmod modules can be generated or Spack's ``load`` feature can be used to access the installed packages. @@ -526,13 +527,7 @@ distribution/repository, run: pip will first check that all :ref:`required third-party packages ` have been installed, and if they are not present, they will be installed by downloading the appropriate packages from the Python -Package Index (`PyPI `_). However, do note that since pip -runs the ``setup.py`` script which requires NumPy, you will have to first -install NumPy: - -.. code-block:: sh - - pip install numpy +Package Index (`PyPI `_). Installing in "Development" Mode -------------------------------- From b84a021c58623e8198cf315c6993e64e3b051613 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Tue, 28 Mar 2023 13:50:02 -0500 Subject: [PATCH 1698/2654] Improve documentation. Refs #2442 --- include/openmc/material.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/openmc/material.h b/include/openmc/material.h index 36d7c34c6..deaee2469 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -90,7 +90,10 @@ public: void set_densities( const vector& name, const vector& density); - //! Clone the material by deep-copying all members + //! Clone the material by deep-copying all members, except for the ID, + // which will get auto-assigned to the next available ID. After creating + // the new material, it is added to openmc::model::materials. + //! \return reference to the cloned material Material & clone(); //---------------------------------------------------------------------------- From ca061bc7e5ecad80ca074070438ebeab9b791b0b Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Tue, 28 Mar 2023 19:20:49 -0500 Subject: [PATCH 1699/2654] Return non-null. --- src/material.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/material.cpp b/src/material.cpp index 165a5c2e7..092055aa1 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -379,7 +379,7 @@ Material & Material::clone() mat->ttb_ = std::make_unique(*ttb_); model::materials.push_back(std::move(mat)); - return *mat; + return *model::materials.back(); } void Material::finalize() From e2373c833b719a05c1c7e4b3cec261e750af1cbe Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 29 Mar 2023 06:51:01 -0500 Subject: [PATCH 1700/2654] Show MCPL and NCrystal in openmc --version --- src/output.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/output.cpp b/src/output.cpp index ae0907d02..04e15b82d 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -360,6 +360,8 @@ void print_build_info() std::string png(n); std::string profiling(n); std::string coverage(n); + std::string mcpl(n); + std::string ncrystal(n); #ifdef PHDF5 phdf5 = y; @@ -373,6 +375,12 @@ void print_build_info() #ifdef LIBMESH libmesh = y; #endif +#ifdef OPENMC_MCPL + mcpl = y; +#endif +#ifdef NCRYSTAL + ncrystal = y; +#endif #ifdef USE_LIBPNG png = y; #endif @@ -396,6 +404,8 @@ void print_build_info() fmt::print("PNG support: {}\n", png); fmt::print("DAGMC support: {}\n", dagmc); fmt::print("libMesh support: {}\n", libmesh); + fmt::print("MCPL support: {}\n", mcpl); + fmt::print("NCrystal support: {}\n", ncrystal); fmt::print("Coverage testing: {}\n", coverage); fmt::print("Profiling flags: {}\n", profiling); } From c3fdf4edd2ee6dc7d9ea2a9e5c48c3d0efb670f4 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Wed, 29 Mar 2023 14:40:37 -0500 Subject: [PATCH 1701/2654] Group openmc::model lines together. Refs #2442 --- src/material.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/material.cpp b/src/material.cpp index 092055aa1..82dd0d4d9 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -356,8 +356,6 @@ Material::~Material() Material & Material::clone() { std::unique_ptr mat = std::make_unique(); - mat->index_ = model::materials.size(); - mat->set_id(C_NONE); // set all other parameters to whatever the calling Material has mat->name_ = name_; @@ -378,6 +376,8 @@ Material & Material::clone() if (ttb_) mat->ttb_ = std::make_unique(*ttb_); + mat->index_ = model::materials.size(); + mat->set_id(C_NONE); model::materials.push_back(std::move(mat)); return *model::materials.back(); } From 5fcb7208dfe9316407a9598e7aff5c498f218cd6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 29 Mar 2023 14:41:03 -0500 Subject: [PATCH 1702/2654] Change version number to 0.13.4-dev --- CMakeLists.txt | 2 +- docs/source/conf.py | 2 +- include/openmc/version.h.in | 2 +- openmc/__init__.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dcaa6fb3..866050a98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(openmc C CXX) # Set version numbers set(OPENMC_VERSION_MAJOR 0) set(OPENMC_VERSION_MINOR 13) -set(OPENMC_VERSION_RELEASE 3) +set(OPENMC_VERSION_RELEASE 4) set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) diff --git a/docs/source/conf.py b/docs/source/conf.py index 988e626cf..8dbbfc6d4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -71,7 +71,7 @@ copyright = '2011-2023, Massachusetts Institute of Technology, UChicago Argonne # The short X.Y version. version = "0.13" # The full version, including alpha/beta/rc tags. -release = "0.13.3" +release = "0.13.4" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index a518e0d63..e1c2b0541 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -10,7 +10,7 @@ namespace openmc { constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {false}; +constexpr bool VERSION_DEV {true}; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/openmc/__init__.py b/openmc/__init__.py index f94cd038f..ac9e02e16 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -38,4 +38,4 @@ from .config import * from openmc.model import rectangular_prism, hexagonal_prism, Model -__version__ = '0.13.3' +__version__ = '0.13.4-dev' From 9ebacff23a1d0d1a38878c40ebe8ab819c7b1b4c Mon Sep 17 00:00:00 2001 From: zoeprieto <101403129+zoeprieto@users.noreply.github.com> Date: Wed, 29 Mar 2023 16:56:12 -0300 Subject: [PATCH 1703/2654] Update docstrings Added description of ncrystal_cfg --- openmc/plotter.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmc/plotter.py b/openmc/plotter.py index 13cd69b40..0362a8d17 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -240,6 +240,8 @@ def calculate_cexs(this, types, temperature=294., sab_name=None, Enrichment for U235 in weight percent. For example, input 4.95 for 4.95 weight percent enriched U. Default is None (natural composition). + ncrystal_cfg : str, optional + Configuration string for NCrystal material. Returns ------- @@ -304,6 +306,8 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, Name of S(a,b) library to apply to MT=2 data when applicable. cross_sections : str, optional Location of cross_sections.xml file. Default is None. + ncrystal_cfg : str, optional + Configuration string for NCrystal material. Returns ------- From 2172907bcfa8ac7463b67c000ac3056b1ca92ec6 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Fri, 31 Mar 2023 13:46:42 -0400 Subject: [PATCH 1704/2654] refactor particle source import/export --- include/openmc/file_utils.h | 26 +++++ include/openmc/mcpl_interface.h | 18 +++- include/openmc/message_passing.h | 16 +++ include/openmc/shared_array.h | 6 ++ include/openmc/state_point.h | 27 ++++- src/mcpl_interface.cpp | 55 ++++------ src/message_passing.cpp | 23 ++++ src/output.cpp | 10 ++ src/simulation.cpp | 34 ++++-- src/source.cpp | 2 +- src/state_point.cpp | 128 ++++++++++------------- tests/cpp_unit_tests/CMakeLists.txt | 1 + tests/cpp_unit_tests/test_file_utils.cpp | 28 +++++ 13 files changed, 248 insertions(+), 126 deletions(-) create mode 100644 tests/cpp_unit_tests/test_file_utils.cpp diff --git a/include/openmc/file_utils.h b/include/openmc/file_utils.h index 9612896be..5604e3230 100644 --- a/include/openmc/file_utils.h +++ b/include/openmc/file_utils.h @@ -1,6 +1,8 @@ #ifndef OPENMC_FILE_UTILS_H #define OPENMC_FILE_UTILS_H +#include // any_of +#include // for isalpha #include // for ifstream #include #include @@ -33,6 +35,30 @@ inline bool file_exists(const std::string& filename) return s.good(); } +// Gets the file extension of whatever string is passed in. This is defined as +// a sequence of strictly alphanumeric characters which follow the last period, +// i.e. at least one alphabet character is present, and zero or more numbers. +// If such a sequence of characters is not found, an empty string is returned. +inline std::string get_file_extension(const std::string& filename) +{ + // check that at least one letter is present + const std::string::size_type last_period_pos = filename.find_last_of('.'); + + // no file extension + if (last_period_pos == std::string::npos) + return ""; + + const std::string ending = filename.substr(last_period_pos + 1); + + // check that at least one character is present. + const bool has_alpha = std::any_of(ending.begin(), ending.end(), + [](char x) { return static_cast(std::isalpha(x)); }); + if (has_alpha) + return ending; + else + return ""; +} + } // namespace openmc #endif // OPENMC_FILE_UTILS_H diff --git a/include/openmc/mcpl_interface.h b/include/openmc/mcpl_interface.h index 64f15c13a..ec2c7ac35 100644 --- a/include/openmc/mcpl_interface.h +++ b/include/openmc/mcpl_interface.h @@ -4,6 +4,8 @@ #include "openmc/particle_data.h" #include "openmc/vector.h" +#include + #include namespace openmc { @@ -26,11 +28,17 @@ vector mcpl_source_sites(std::string path); //! Write an MCPL source file // -//! \param[in] filename Path to MCPL file -//! \param[in] surf_source_bank Whether to use the surface source bank -void write_mcpl_source_point( - const char* filename, bool surf_source_bank = false); - +//! \param[in] filename Path to MCPL file +//! \param[in] source_bank Vector of SourceSites to write to file for this +//! MPI rank +//! \param[in] bank_indx Pointer to vector of site index ranges over all +//! MPI ranks, allowed to leave this argument alone +//! or pass a nullptr if not running in MPI mode. +//! The option of passing a nullptr has been left +//! for developers to experiment with serial code +//! before writing the fully MPI-parallel version. +void write_mcpl_source_point(const char* filename, + gsl::span source_bank, vector const& bank_index); } // namespace openmc #endif // OPENMC_MCPL_INTERFACE_H diff --git a/include/openmc/message_passing.h b/include/openmc/message_passing.h index b02d2938f..abd6f68b0 100644 --- a/include/openmc/message_passing.h +++ b/include/openmc/message_passing.h @@ -1,10 +1,14 @@ #ifndef OPENMC_MESSAGE_PASSING_H #define OPENMC_MESSAGE_PASSING_H +#include + #ifdef OPENMC_MPI #include #endif +#include "openmc/vector.h" + namespace openmc { namespace mpi { @@ -17,6 +21,18 @@ extern MPI_Datatype source_site; extern MPI_Comm intracomm; #endif +// Calculates global indices of the bank particles +// across all ranks using a parallel scan. This is used to write +// the surface source file in parallel runs. It will probably +// be used in the future for other types of bank like particles +// in flight used to kick off transient simulations. +// +// More abstractly, this just takes a number from each MPI rank, +// and returns a vector which is the exclusive parallel scan across +// all of those numbers, having a length of the number of MPI ranks +// plus one. +vector calculate_parallel_index_vector(const int64_t size); + } // namespace mpi } // namespace openmc diff --git a/include/openmc/shared_array.h b/include/openmc/shared_array.h index 6fee29b82..676481296 100644 --- a/include/openmc/shared_array.h +++ b/include/openmc/shared_array.h @@ -115,6 +115,12 @@ public: T* data() { return data_.get(); } const T* data() const { return data_.get(); } + //! Classic iterators + T* begin() { return data_.get(); } + const T* cbegin() const { return data_.get(); } + T* end() { return data_.get() + size_; } + const T* cend() const { return data_.get() + size_; } + private: //========================================================================== // Data members diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 5ada2bf88..ca4b293eb 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -3,18 +3,39 @@ #include +#include + #include "hdf5.h" #include "openmc/capi.h" #include "openmc/particle.h" +#include "openmc/shared_array.h" #include "openmc/vector.h" namespace openmc { void load_state_point(); -vector calculate_surf_source_size(); -void write_source_point(const char* filename, bool surf_source_bank = false); -void write_source_bank(hid_t group_id, bool surf_source_bank); + +// By passing in a filename, source bank, and list of source indices +// on each MPI rank, this writes an HDF5 file which contains that +// information which can later be read in by read_source_bank +// (defined below). If you're writing code to write out a new kind +// of particle bank, this function is the one you want to use! +// +// For example, this is used to write both the surface source sites +// or fission source sites for eigenvalue continuation runs. +// +// This function ends up calling write_source_bank, and is responsible +// for opening the file to be written to and controlling whether the +// write is done in parallel (if compiled with parallel HDF5). +void write_source_point(const char* filename, gsl::span source_bank, + vector const& bank_index); + +// This appends a source bank specification to an HDF5 file +// that's already open. It is used internally by write_source_point. +void write_source_bank(hid_t group_id, gsl::span source_bank, + vector const& bank_index); + void read_source_bank( hid_t group_id, vector& sites, bool distribute); void write_tally_results_nr(hid_t file_id); diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp index a38891478..b64531eed 100644 --- a/src/mcpl_interface.cpp +++ b/src/mcpl_interface.cpp @@ -2,6 +2,7 @@ #include "openmc/bank.h" #include "openmc/error.h" +#include "openmc/file_utils.h" #include "openmc/message_passing.h" #include "openmc/settings.h" #include "openmc/simulation.h" @@ -110,37 +111,18 @@ vector mcpl_source_sites(std::string path) //============================================================================== #ifdef OPENMC_MCPL -void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) +void write_mcpl_source_bank(mcpl_outfile_t file_id, + gsl::span source_bank, vector const& bank_index) { int64_t dims_size = settings::n_particles; int64_t count_size = simulation::work_per_rank; - // Set vectors for source bank and starting bank index of each process - vector* bank_index = &simulation::work_index; - vector* source_bank = &simulation::source_bank; - vector surf_source_index_vector; - vector surf_source_bank_vector; - - if (surf_source_bank) { - surf_source_index_vector = calculate_surf_source_size(); - dims_size = surf_source_index_vector[mpi::n_procs]; - count_size = simulation::surf_source_bank.size(); - - bank_index = &surf_source_index_vector; - - // Copy data in a SharedArray into a vector. - surf_source_bank_vector.resize(count_size); - surf_source_bank_vector.assign(simulation::surf_source_bank.data(), - simulation::surf_source_bank.data() + count_size); - source_bank = &surf_source_bank_vector; - } - if (mpi::master) { // Particles are writeen to disk from the master node only // Save source bank sites since the array is overwritten below #ifdef OPENMC_MPI - vector temp_source {source_bank->begin(), source_bank->end()}; + vector temp_source {source_bank.begin(), source_bank.end()}; #endif // loop over the other nodes and receive data - then write those. @@ -151,11 +133,11 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) #ifdef OPENMC_MPI if (i > 0) - MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + MPI_Recv(source_bank.data(), count[0], mpi::source_site, i, i, mpi::intracomm, MPI_STATUS_IGNORE); #endif // now write the source_bank data again. - for (const auto& site : *source_bank) { + for (const auto& site : source_bank) { // particle is now at the iterator // write it to the mcpl-file mcpl_particle_t p; @@ -194,11 +176,11 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) } #ifdef OPENMC_MPI // Restore state of source bank - std::copy(temp_source.begin(), temp_source.end(), source_bank->begin()); + std::copy(temp_source.begin(), temp_source.end(), source_bank.begin()); #endif } else { #ifdef OPENMC_MPI - MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + MPI_Send(source_bank.data(), count_size, mpi::source_site, 0, mpi::rank, mpi::intracomm); #endif } @@ -207,17 +189,16 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, bool surf_source_bank) //============================================================================== -void write_mcpl_source_point(const char* filename, bool surf_source_bank) +void write_mcpl_source_point(const char* filename, + gsl::span source_bank, vector const& bank_index) { - std::string filename_; - if (filename) { - filename_ = filename; - } else { - // Determine width for zero padding - int w = std::to_string(settings::n_max_batches).size(); - - filename_ = fmt::format("{0}source.{1:0{2}}.mcpl", settings::path_output, - simulation::current_batch, w); + std::string filename_(filename); + const auto extension = get_file_extension(filename_); + if (extension == "") { + filename_.append(".mcpl"); + } else if (extension != "mcpl") { + fatal_error("write_mcpl_source_point was passed an incorrect file " + "extension. Must either pass nothing or .mcpl"); } #ifdef OPENMC_MCPL @@ -236,7 +217,7 @@ void write_mcpl_source_point(const char* filename, bool surf_source_bank) mcpl_hdr_set_srcname(file_id, line.c_str()); } - write_mcpl_source_bank(file_id, surf_source_bank); + write_mcpl_source_bank(file_id, source_bank, bank_index); if (mpi::master) { mcpl_close_outfile(file_id); diff --git a/src/message_passing.cpp b/src/message_passing.cpp index f87782083..fa9036c71 100644 --- a/src/message_passing.cpp +++ b/src/message_passing.cpp @@ -17,6 +17,29 @@ extern "C" bool openmc_master() return mpi::master; } +vector calculate_parallel_index_vector(const int64_t size) +{ + vector result; + result.reserve(n_procs + 1); + +#ifdef OPENMC_MPI + result.resize(n_procs); + vector bank_size(n_procs); + + // Populate the result with cumulative sum of the number of + // surface source banks per process + MPI_Scan(&size, bank_size.data(), 1, MPI_INT64_T, MPI_SUM, intracomm); + MPI_Allgather( + bank_size.data(), 1, MPI_INT64_T, result.data(), 1, MPI_INT64_T, intracomm); + result.insert(result.begin(), 0); +#else + result.push_back(0); + result.push_back(size); +#endif + + return result; +} + } // namespace mpi } // namespace openmc diff --git a/src/output.cpp b/src/output.cpp index ae0907d02..53f5b647f 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -360,6 +360,8 @@ void print_build_info() std::string png(n); std::string profiling(n); std::string coverage(n); + std::string mcpl(n); + std::string ncrystal(n); #ifdef PHDF5 phdf5 = y; @@ -382,6 +384,12 @@ void print_build_info() #ifdef COVERAGEBUILD coverage = y; #endif +#ifdef NCRYSTAL + ncrystal = y; +#endif +#ifdef OPENMC_MCPL + mcpl = y; +#endif // Wraps macro variables in quotes #define STRINGIFY(x) STRINGIFY2(x) @@ -396,6 +404,8 @@ void print_build_info() fmt::print("PNG support: {}\n", png); fmt::print("DAGMC support: {}\n", dagmc); fmt::print("libMesh support: {}\n", libmesh); + fmt::print("NCrystal support: {}\n", profiling); + fmt::print("MCPL support: {}\n", profiling); fmt::print("Coverage testing: {}\n", coverage); fmt::print("Profiling flags: {}\n", profiling); } diff --git a/src/simulation.cpp b/src/simulation.cpp index 7740c81d8..d46787c28 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -392,21 +392,32 @@ void finalize_batch() // Write out a separate source point if it's been specified for this batch if (contains(settings::sourcepoint_batch, simulation::current_batch) && settings::source_write && settings::source_separate) { + + // Determine width for zero padding + int w = std::to_string(settings::n_max_batches).size(); + std::string source_point_filename = fmt::format("{0}source.{1:0{2}}", + settings::path_output, simulation::current_batch, w); + gsl::span bankspan(simulation::source_bank); if (settings::source_mcpl_write) { - write_mcpl_source_point(nullptr); + write_mcpl_source_point( + source_point_filename.c_str(), bankspan, simulation::work_index); } else { - write_source_point(nullptr); + write_source_point( + source_point_filename.c_str(), bankspan, simulation::work_index); } } // Write a continously-overwritten source point if requested. if (settings::source_latest) { + + // note: correct file extension appended automatically + auto filename = settings::path_output + "source"; + gsl::span bankspan(simulation::source_bank); if (settings::source_mcpl_write) { - auto filename = settings::path_output + "source.mcpl"; - write_mcpl_source_point(filename.c_str()); + write_mcpl_source_point( + filename.c_str(), bankspan, simulation::work_index); } else { - auto filename = settings::path_output + "source.h5"; - write_source_point(filename.c_str()); + write_source_point(filename.c_str(), bankspan, simulation::work_index); } } } @@ -414,12 +425,15 @@ void finalize_batch() // Write out surface source if requested. if (settings::surf_source_write && simulation::current_batch == settings::n_batches) { + auto filename = settings::path_output + "surface_source"; + auto surf_work_index = + mpi::calculate_parallel_index_vector(simulation::surf_source_bank.size()); + gsl::span surfbankspan(simulation::surf_source_bank.begin(), + simulation::surf_source_bank.size()); if (settings::surf_mcpl_write) { - auto filename = settings::path_output + "surface_source.mcpl"; - write_mcpl_source_point(filename.c_str(), true); + write_mcpl_source_point(filename.c_str(), surfbankspan, surf_work_index); } else { - auto filename = settings::path_output + "surface_source.h5"; - write_source_point(filename.c_str(), true); + write_source_point(filename.c_str(), surfbankspan, surf_work_index); } } } diff --git a/src/source.cpp b/src/source.cpp index 5862a41e2..163c85676 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -403,7 +403,7 @@ void initialize_source() write_message("Writing out initial source...", 5); std::string filename = settings::path_output + "initial_source.h5"; hid_t file_id = file_open(filename, 'w', true); - write_source_bank(file_id, false); + write_source_bank(file_id, simulation::source_bank, simulation::work_index); file_close(file_id); } } diff --git a/src/state_point.cpp b/src/state_point.cpp index dfd3d381b..10bcd9365 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -13,6 +13,7 @@ #include "openmc/constants.h" #include "openmc/eigenvalue.h" #include "openmc/error.h" +#include "openmc/file_utils.h" #include "openmc/hdf5_interface.h" #include "openmc/mesh.h" #include "openmc/message_passing.h" @@ -34,7 +35,8 @@ extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) { simulation::time_statepoint.start(); - // Set the filename + // If a nullptr is passed in, we assume that the user + // wants a default name for this, of the form like output/statepoint.20.h5 std::string filename_; if (filename) { filename_ = filename; @@ -47,6 +49,15 @@ extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) simulation::current_batch, w); } + // If a file name was specified, ensure it has .h5 file extension + const auto extension = get_file_extension(filename_); + if (extension == "") { + filename_.append(".h5"); + } else if (extension != "h5") { + fatal_error("openmc_statepoint_write was passed an incorrect file " + "extension. Must either have no file extension or .h5"); + } + // Determine whether or not to write the source bank bool write_source_ = write_source ? *write_source : true; @@ -316,7 +327,7 @@ extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) if (write_source_) { if (mpi::master || parallel) file_id = file_open(filename_, 'a', true); - write_source_bank(file_id, false); + write_source_bank(file_id, simulation::source_bank, simulation::work_index); if (mpi::master || parallel) file_close(file_id); } @@ -541,31 +552,8 @@ hid_t h5banktype() return banktype; } -vector calculate_surf_source_size() -{ - vector surf_source_index; - surf_source_index.reserve(mpi::n_procs + 1); - -#ifdef OPENMC_MPI - surf_source_index.resize(mpi::n_procs); - vector bank_size(mpi::n_procs); - - // Populate the surf_source_index with cumulative sum of the number of - // surface source banks per process - int64_t size = simulation::surf_source_bank.size(); - MPI_Scan(&size, bank_size.data(), 1, MPI_INT64_T, MPI_SUM, mpi::intracomm); - MPI_Allgather(bank_size.data(), 1, MPI_INT64_T, surf_source_index.data(), 1, - MPI_INT64_T, mpi::intracomm); - surf_source_index.insert(surf_source_index.begin(), 0); -#else - surf_source_index.push_back(0); - surf_source_index.push_back(simulation::surf_source_bank.size()); -#endif - - return surf_source_index; -} - -void write_source_point(const char* filename, bool surf_source_bank) +void write_source_point(const char* filename, gsl::span source_bank, + vector const& bank_index) { // When using parallel HDF5, the file is written to collectively by all // processes. With MPI-only, the file is opened and written by the master @@ -577,58 +565,59 @@ void write_source_point(const char* filename, bool surf_source_bank) bool parallel = false; #endif - std::string filename_; - if (filename) { - filename_ = filename; - } else { - // Determine width for zero padding - int w = std::to_string(settings::n_max_batches).size(); + if (!filename) + fatal_error("write_source_point filename needs a nonempty name."); - filename_ = fmt::format("{0}source.{1:0{2}}.h5", settings::path_output, - simulation::current_batch, w); + std::string filename_(filename); + const auto extension = get_file_extension(filename_); + if (extension == "") { + filename_.append(".h5"); + } else if (extension != "h5") { + fatal_error("openmc_source_point was passed an incorrect file " + "extension. Must either have no file extension or .h5"); } hid_t file_id; if (mpi::master || parallel) { - file_id = file_open(filename_, 'w', true); + file_id = file_open(filename_.c_str(), 'w', true); write_attribute(file_id, "filetype", "source"); } // Get pointer to source bank and write to file - write_source_bank(file_id, surf_source_bank); + write_source_bank(file_id, source_bank, bank_index); if (mpi::master || parallel) file_close(file_id); } -void write_source_bank(hid_t group_id, bool surf_source_bank) +void write_source_bank(hid_t group_id, gsl::span source_bank, + vector const& bank_index) { hid_t banktype = h5banktype(); // Set total and individual process dataspace sizes for source bank - int64_t dims_size = settings::n_particles; - int64_t count_size = simulation::work_per_rank; + // TODO: are these correct? + // the old code was + // + // int64_t dims_size = settings::n_particles; + // int64_t count_size = simulation::work_per_rank; + // + // but that doesn't make sense! The count on a rank is not + // necessarily equal to work_per_rank. For the case of the + // fission source bank, that's true, but for surface source + // creation, there may be a different number of particles + // on each rank. + // + // Hence, I have changed count_size to be the number + // on this rank rather than work_per_rank. Similarly, + // dims_size used to be n_particles, but for surface sources, + // we are not guaranteed to create n_particles at the surface. + // As a result, I've changed this to be the total size of + // the bank across all ranks, which maintains the correct + // behavior for fission bank outputs. - // Set vectors for source bank and starting bank index of each process - vector* bank_index = &simulation::work_index; - vector* source_bank = &simulation::source_bank; - vector surf_source_index_vector; - vector surf_source_bank_vector; - - // Reset dataspace sizes and vectors for surface source bank - if (surf_source_bank) { - surf_source_index_vector = calculate_surf_source_size(); - dims_size = surf_source_index_vector[mpi::n_procs]; - count_size = simulation::surf_source_bank.size(); - - bank_index = &surf_source_index_vector; - - // Copy data in a SharedArray into a vector. - surf_source_bank_vector.resize(count_size); - surf_source_bank_vector.assign(simulation::surf_source_bank.data(), - simulation::surf_source_bank.data() + count_size); - source_bank = &surf_source_bank_vector; - } + int64_t dims_size = bank_index.back(); + int64_t count_size = bank_index[mpi::rank + 1] - bank_index[mpi::rank]; #ifdef PHDF5 // Set size of total dataspace for all procs and rank @@ -642,7 +631,7 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) hid_t memspace = H5Screate_simple(1, count, nullptr); // Select hyperslab for this dataspace - hsize_t start[] {static_cast((*bank_index)[mpi::rank])}; + hsize_t start[] {static_cast(bank_index[mpi::rank])}; H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); // Set up the property list for parallel writing @@ -650,7 +639,7 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); // Write data to file in parallel - H5Dwrite(dset, banktype, memspace, dspace, plist, source_bank->data()); + H5Dwrite(dset, banktype, memspace, dspace, plist, source_bank.data()); // Free resources H5Sclose(dspace); @@ -669,31 +658,30 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) // Save source bank sites since the array is overwritten below #ifdef OPENMC_MPI - vector temp_source {source_bank->begin(), source_bank->end()}; + vector temp_source {source_bank.begin(), source_bank.end()}; #endif for (int i = 0; i < mpi::n_procs; ++i) { // Create memory space - hsize_t count[] { - static_cast((*bank_index)[i + 1] - (*bank_index)[i])}; + hsize_t count[] {static_cast(bank_index[i + 1] - bank_index[i])}; hid_t memspace = H5Screate_simple(1, count, nullptr); #ifdef OPENMC_MPI // Receive source sites from other processes if (i > 0) - MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i, + MPI_Recv(source_bank.data(), count[0], mpi::source_site, i, i, mpi::intracomm, MPI_STATUS_IGNORE); #endif // Select hyperslab for this dataspace dspace = H5Dget_space(dset); - hsize_t start[] {static_cast((*bank_index)[i])}; + hsize_t start[] {static_cast(bank_index[i])}; H5Sselect_hyperslab( dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); // Write data to hyperslab H5Dwrite( - dset, banktype, memspace, dspace, H5P_DEFAULT, (*source_bank).data()); + dset, banktype, memspace, dspace, H5P_DEFAULT, source_bank.data()); H5Sclose(memspace); H5Sclose(dspace); @@ -704,11 +692,11 @@ void write_source_bank(hid_t group_id, bool surf_source_bank) #ifdef OPENMC_MPI // Restore state of source bank - std::copy(temp_source.begin(), temp_source.end(), source_bank->begin()); + std::copy(temp_source.begin(), temp_source.end(), source_bank.begin()); #endif } else { #ifdef OPENMC_MPI - MPI_Send(source_bank->data(), count_size, mpi::source_site, 0, mpi::rank, + MPI_Send(source_bank.data(), count_size, mpi::source_site, 0, mpi::rank, mpi::intracomm); #endif } diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index 3d48545b4..e017b8700 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -1,5 +1,6 @@ set(TEST_NAMES test_distribution + test_file_utils # Add additional unit test files here ) diff --git a/tests/cpp_unit_tests/test_file_utils.cpp b/tests/cpp_unit_tests/test_file_utils.cpp new file mode 100644 index 000000000..23222f639 --- /dev/null +++ b/tests/cpp_unit_tests/test_file_utils.cpp @@ -0,0 +1,28 @@ +#include "openmc/file_utils.h" +#include + +using namespace openmc; + +TEST_CASE("Test get_file_extension") +{ + REQUIRE(get_file_extension("rememberthealamo.png") == "png"); + REQUIRE(get_file_extension("statepoint.20.h5") == "h5"); + REQUIRE(get_file_extension("wEiRDNaa_ame.h4") == "h4"); + REQUIRE(get_file_extension("has_directory/asdf.20.h5") == "h5"); + REQUIRE(get_file_extension("wasssssup_lol") == ""); + REQUIRE(get_file_extension("has_directory/secret_file") == ""); +} + +TEST_CASE("Test dir_exists") +{ + // not sure how to test this when running on windows? + REQUIRE(dir_exists("/")); + + // if this exists on your system... you deserve for this test to fail + REQUIRE(!dir_exists("/asdfa/asdfasdf/asdgasodgosuihasjkgh/")); +} + +TEST_CASE("Test file_exists") +{ + // TODO make a file test it exists, delete it +} From 30ed6020092768b2dd208e5343c399c2eac13d64 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Fri, 31 Mar 2023 23:59:04 -0400 Subject: [PATCH 1705/2654] update documentation --- include/openmc/mcpl_interface.h | 8 +++----- include/openmc/state_point.h | 5 +++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/openmc/mcpl_interface.h b/include/openmc/mcpl_interface.h index ec2c7ac35..1f0c94d6d 100644 --- a/include/openmc/mcpl_interface.h +++ b/include/openmc/mcpl_interface.h @@ -32,11 +32,9 @@ vector mcpl_source_sites(std::string path); //! \param[in] source_bank Vector of SourceSites to write to file for this //! MPI rank //! \param[in] bank_indx Pointer to vector of site index ranges over all -//! MPI ranks, allowed to leave this argument alone -//! or pass a nullptr if not running in MPI mode. -//! The option of passing a nullptr has been left -//! for developers to experiment with serial code -//! before writing the fully MPI-parallel version. +//! MPI ranks. This can be computed by calling +//! calculate_parallel_index_vector on +//! source_bank.size(). void write_mcpl_source_point(const char* filename, gsl::span source_bank, vector const& bank_index); } // namespace openmc diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index ca4b293eb..db1ac2edb 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -28,6 +28,11 @@ void load_state_point(); // This function ends up calling write_source_bank, and is responsible // for opening the file to be written to and controlling whether the // write is done in parallel (if compiled with parallel HDF5). +// +// bank_index is an exclusive parallel scan of the source_bank.size() +// values on each rank, used to create global indexing. This vector +// can be created by calling calculate_parallel_index_vector on +// source_bank.size() if such a vector is not already available. void write_source_point(const char* filename, gsl::span source_bank, vector const& bank_index); From 5a8e1cc988b7d6e7204aa45675ca31316e94988e Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sat, 1 Apr 2023 00:22:50 -0400 Subject: [PATCH 1706/2654] fix typo --- src/mcpl_interface.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp index b64531eed..64d6046e3 100644 --- a/src/mcpl_interface.cpp +++ b/src/mcpl_interface.cpp @@ -128,8 +128,7 @@ void write_mcpl_source_bank(mcpl_outfile_t file_id, // loop over the other nodes and receive data - then write those. for (int i = 0; i < mpi::n_procs; ++i) { // number of particles for node node i - size_t count[] { - static_cast((*bank_index)[i + 1] - (*bank_index)[i])}; + size_t count[] {static_cast(bank_index[i + 1] - bank_index[i])}; #ifdef OPENMC_MPI if (i > 0) From 95e3f94630f017decf7d5ebc9cd4bcdfd6fb5875 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 4 Apr 2023 22:49:11 +0200 Subject: [PATCH 1707/2654] Implement CruciformPrism composite surface --- docs/source/pythonapi/model.rst | 3 +- openmc/model/surface_composite.py | 74 +++++++++++++++++++++- tests/unit_tests/test_surface_composite.py | 62 ++++++++++++++++++ 3 files changed, 137 insertions(+), 2 deletions(-) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index cdabee396..c9c6e117a 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -24,14 +24,15 @@ Composite Surfaces :nosignatures: :template: myclass.rst + openmc.model.CruciformPrism openmc.model.CylinderSector openmc.model.IsogonalOctagon + openmc.model.Polygon openmc.model.RectangularParallelepiped openmc.model.RightCircularCylinder openmc.model.XConeOneSided openmc.model.YConeOneSided openmc.model.ZConeOneSided - openmc.model.Polygon TRISO Fuel Modeling ------------------- diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 25826723c..6acfdde4a 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -630,7 +630,7 @@ class ZConeOneSided(CompositeSurface): class Polygon(CompositeSurface): - """Create a polygon composite surface from a path of closed points. + """Polygon formed from a path of closed points. .. versionadded:: 0.13.3 @@ -1079,3 +1079,75 @@ class Polygon(CompositeSurface): disp_vec = distance / costheta * unit_nvec return type(self)(self.points + disp_vec, basis=self.basis) + + +class CruciformPrism(CompositeSurface): + """Generalized cruciform prism + + This surface represents a prism parallel to an axis formed by planes at + multiple distances from the center. Equivalent to the 'gcross' derived + surface in Serpent. + + .. versionadded:: 0.13.4 + + Parameters + ---------- + distances : iterable of float + A monotonically increasing (or decreasing) iterable of distances in [cm] + that form the planes of the generalized cruciform. + center : iterable of float + The center of the prism in the two non-parallel axes (e.g., (x, y) when + axis is 'z') in [cm] + axis : {'x', 'y', 'z'} + Axis to which the prism is parallel + **kwargs + Keyword arguments passed to underlying plane classes + + """ + + def __init__(self, distances, center=(0., 0.), axis='z', **kwargs): + x0, y0 = center + self.distances = distances + + if axis == 'x': + cls_horizontal = openmc.YPlane + cls_vertical = openmc.ZPlane + elif axis == 'y': + cls_horizontal = openmc.XPlane + cls_vertical = openmc.ZPlane + elif axis == 'z': + cls_horizontal = openmc.XPlane + cls_vertical = openmc.YPlane + else: + raise ValueError("axis must be 'x', 'y', or 'z'") + + # Create each planar surface + surfnames = [] + for i, d in enumerate(distances): + setattr(self, f'hmin{i}', cls_horizontal(x0 - d, **kwargs)) + setattr(self, f'hmax{i}', cls_horizontal(x0 + d, **kwargs)) + setattr(self, f'vmin{i}', cls_vertical(y0 - d, **kwargs)) + setattr(self, f'vmax{i}', cls_vertical(y0 + d, **kwargs)) + surfnames.extend([f'hmin{i}', f'hmax{i}', f'vmin{i}', f'vmax{i}']) + + # Set _surfnames to satisfy CompositeSurface protocol + self._surfnames = tuple(surfnames) + + @property + def _surface_names(self): + return self._surfnames + + def __neg__(self): + n = len(self.distances) + regions = [] + for i in range(n): + regions.append( + +getattr(self, f'hmin{i}') & + -getattr(self, f'hmax{i}') & + +getattr(self, f'vmin{n-1-i}') & + -getattr(self, f'vmax{n-1-i}') + ) + return openmc.Union(regions) + + def __pos__(self): + return ~(-self) diff --git a/tests/unit_tests/test_surface_composite.py b/tests/unit_tests/test_surface_composite.py index 3f94893ed..066dd3307 100644 --- a/tests/unit_tests/test_surface_composite.py +++ b/tests/unit_tests/test_surface_composite.py @@ -315,6 +315,7 @@ def test_isogonal_octagon(axis, plane_tb, plane_lr, axis_idx): # Make sure repr works repr(s) + def test_polygon(): # define a 5 pointed star centered on 1, 1 star = np.array([[1. , 2. ], @@ -393,3 +394,64 @@ def test_polygon(): [6.88, 3.02]]) with pytest.raises(ValueError): openmc.model.Polygon(rz_points) + + +@pytest.mark.parametrize("axis", ["x", "y", "z"]) +def test_cruciform_prism(axis): + center = x0, y0 = (3., 4.) + distances = [2., 3., 5.] + s = openmc.model.CruciformPrism(distances, center, axis=axis) + + if axis == 'x': + i1, i2 = 1, 2 + elif axis == 'y': + i1, i2 = 0, 2 + elif axis == 'z': + i1, i2 = 0, 1 + plane_cls = (openmc.XPlane, openmc.YPlane, openmc.ZPlane) + + # Check type of surfaces + for i in range(3): + assert isinstance(getattr(s, f'hmin{i}'), plane_cls[i1]) + assert isinstance(getattr(s, f'hmax{i}'), plane_cls[i1]) + assert isinstance(getattr(s, f'vmin{i}'), plane_cls[i2]) + assert isinstance(getattr(s, f'vmax{i}'), plane_cls[i2]) + + # Make sure boundary condition propagates + s.boundary_type = 'reflective' + for i in range(3): + assert getattr(s, f'hmin{i}').boundary_type == 'reflective' + assert getattr(s, f'hmax{i}').boundary_type == 'reflective' + assert getattr(s, f'vmin{i}').boundary_type == 'reflective' + assert getattr(s, f'vmax{i}').boundary_type == 'reflective' + + # Check bounding box + ll, ur = (+s).bounding_box + assert np.all(np.isinf(ll)) + assert np.all(np.isinf(ur)) + ll, ur = (-s).bounding_box + assert ur[i1] == pytest.approx(x0 + distances[-1]) + assert ur[i2] == pytest.approx(y0 + distances[-1]) + assert ll[i1] == pytest.approx(x0 - distances[-1]) + assert ll[i2] == pytest.approx(y0 - distances[-1]) + + # __contains__ on associated half-spaces + point_pos, point_neg = np.zeros(3), np.zeros(3) + point_pos[i1] = x0 + 3.1 + point_pos[i2] = y0 + 2.05 + point_neg[i1] = x0 + 3.5 + point_neg[i2] = y0 + 1.99 + assert point_pos in +s + assert point_pos not in -s + assert point_neg in -s + assert point_neg not in +s + + # translate method + t = uniform(-5.0, 5.0) + s_t = s.translate((t, t, t)) + ll_t, ur_t = (-s_t).bounding_box + assert ur_t == pytest.approx(ur + t) + assert ll_t == pytest.approx(ll + t) + + # Make sure repr works + repr(s) From e3e659ca834411bd56bb288223f64e7f978575b1 Mon Sep 17 00:00:00 2001 From: stchaker Date: Tue, 4 Apr 2023 16:58:28 -0400 Subject: [PATCH 1708/2654] avoid python C API segfault on intel mac --- include/openmc/settings.h | 7 ++++++- src/initialize.cpp | 1 + src/settings.cpp | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 806288efe..9cd2f7c2d 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -68,7 +68,12 @@ extern std::string path_input; //!< directory where main .xml files resides extern std::string path_output; //!< directory where output files are written extern std::string path_particle_restart; //!< path to a particle restart file extern std::string path_sourcepoint; //!< path to a source file -extern "C" std::string path_statepoint; //!< path to a statepoint file +extern std::string path_statepoint; //!< path to a statepoint file + +// This is required because the c_str() may not be the first thing in +// std::string. Sometimes it is, but it seems libc++ may not be like that +// on some computers, like the intel Mac. +extern "C" char const* path_statepoint_c; //!< C pointer to statepoint file name extern "C" int32_t n_inactive; //!< number of inactive batches extern "C" int32_t max_lost_particles; //!< maximum number of lost particles diff --git a/src/initialize.cpp b/src/initialize.cpp index 6383af64e..da35d4ff6 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -193,6 +193,7 @@ int parse_command_line(int argc, char* argv[]) // Set path and flag for type of run if (filetype == "statepoint") { settings::path_statepoint = argv[i]; + settings::path_statepoint_c = settings::path_statepoint.c_str(); settings::restart_run = true; } else if (filetype == "particle restart") { settings::path_particle_restart = argv[i]; diff --git a/src/settings.cpp b/src/settings.cpp index 2f8fbd1d0..cf678d404 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -82,6 +82,8 @@ std::string path_output; std::string path_particle_restart; std::string path_sourcepoint; std::string path_statepoint; +std::string empty_string = ""; +char const* path_statepoint_c {empty_string.c_str()}; int32_t n_inactive {0}; int32_t max_lost_particles {10}; From e2dedf546118684019fe70f191541d260c0e4b8f Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Mon, 13 Dec 2021 14:37:08 -0500 Subject: [PATCH 1709/2654] move common with projection plot to base class --- include/openmc/plot.h | 54 ++++++++++++++++++++------------- src/plot.cpp | 69 ++++++++++++++++++------------------------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index a415b1747..1c2d9e48d 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -102,7 +102,7 @@ enum class PlotColorBy { cells = 0, mats = 1 }; //=============================================================================== // Plot class //=============================================================================== -class PlotBase { +class SlicePlotBase { public: template T get_map() const; @@ -113,12 +113,13 @@ public: Position width_; //!< Plot width in geometry PlotBasis basis_; //!< Plot basis (XY/XZ/YZ) array pixels_; //!< Plot size in pixels - bool color_overlaps_; //!< Show overlapping cells? - int level_; //!< Plot universe level + bool slice_color_overlaps_; //!< Show overlapping cells? + int slice_level_ {-1}; //!< Plot universe level +private: }; template -T PlotBase::get_map() const +T SlicePlotBase::get_map() const { size_t width = pixels_[0]; @@ -164,7 +165,7 @@ T PlotBase::get_map() const p.r() = xyz; p.u() = dir; p.coord(0).universe = model::root_universe; - int level = level_; + int level = slice_level_; int j {}; #pragma omp for @@ -182,7 +183,7 @@ T PlotBase::get_map() const if (found_cell) { data.set_value(y, x, p, j); } - if (color_overlaps_ && check_cell_overlap(p, false)) { + if (slice_color_overlaps_ && check_cell_overlap(p, false)) { data.set_overlap(y, x); } } // inner for @@ -192,7 +193,31 @@ T PlotBase::get_map() const return data; } -class Plot : public PlotBase { +// Common data and methods between ProjectionPlot and Plot types +class PlotBase { +protected: + void set_id(pugi::xml_node plot_node); + void set_bg_color(pugi::xml_node plot_node); + void set_universe(pugi::xml_node plot_node); + void set_default_colors(pugi::xml_node plot_node); + void set_user_colors(pugi::xml_node plot_node); + void set_overlap_color(pugi::xml_node plot_node); + void set_mask(pugi::xml_node plot_node); + +public: + PlotBase(pugi::xml_node plot_node); + int id_; // Plot ID + int level_; // Universe level to plot + bool color_overlaps_; //!< Show overlapping cells? + PlotColorBy color_by_; // Plot coloring (cell/material) + RGBColor not_found_ {WHITE}; // Plot background color + RGBColor overlap_color_ {RED}; // Plot overlap color + vector colors_; // Plot colors + std::string path_plot_; // Plot output filename +}; + +// Represents either a voxel or pixel plot +class Plot : public SlicePlotBase, public PlotBase { public: // Constructor @@ -200,32 +225,19 @@ public: // Methods private: - void set_id(pugi::xml_node plot_node); - void set_type(pugi::xml_node plot_node); void set_output_path(pugi::xml_node plot_node); - void set_bg_color(pugi::xml_node plot_node); + void set_type(pugi::xml_node plot_node); void set_basis(pugi::xml_node plot_node); void set_origin(pugi::xml_node plot_node); void set_width(pugi::xml_node plot_node); - void set_universe(pugi::xml_node plot_node); - void set_default_colors(pugi::xml_node plot_node); - void set_user_colors(pugi::xml_node plot_node); void set_meshlines(pugi::xml_node plot_node); - void set_mask(pugi::xml_node plot_node); - void set_overlap_color(pugi::xml_node plot_node); // Members public: - int id_; //!< Plot ID PlotType type_; //!< Plot type (Slice/Voxel) - PlotColorBy color_by_; //!< Plot coloring (cell/material) int meshlines_width_; //!< Width of lines added to the plot int index_meshlines_mesh_ {-1}; //!< Index of the mesh to draw on the plot RGBColor meshlines_color_; //!< Color of meshlines on the plot - RGBColor not_found_ {WHITE}; //!< Plot background color - RGBColor overlap_color_ {RED}; //!< Plot overlap color - vector colors_; //!< Plot colors - std::string path_plot_; //!< Plot output filename }; //=============================================================================== diff --git a/src/plot.cpp b/src/plot.cpp index fac13a1f4..d3486d553 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -213,7 +213,7 @@ void create_image(Plot const& pl) #endif } -void Plot::set_id(pugi::xml_node plot_node) +void PlotBase::set_id(pugi::xml_node plot_node) { // Copy data into plots if (check_for_node(plot_node, "id")) { @@ -298,16 +298,11 @@ void Plot::set_output_path(pugi::xml_node plot_node) } } -void Plot::set_bg_color(pugi::xml_node plot_node) +void PlotBase::set_bg_color(pugi::xml_node plot_node) { // Copy plot background color if (check_for_node(plot_node, "background")) { vector bg_rgb = get_node_array(plot_node, "background"); - if (PlotType::voxel == type_) { - if (mpi::master) { - warning(fmt::format("Background color ignored in voxel plot {}", id_)); - } - } if (bg_rgb.size() == 3) { not_found_ = bg_rgb; } else { @@ -371,7 +366,7 @@ void Plot::set_width(pugi::xml_node plot_node) } } -void Plot::set_universe(pugi::xml_node plot_node) +void PlotBase::set_universe(pugi::xml_node plot_node) { // Copy plot universe level if (check_for_node(plot_node, "level")) { @@ -384,7 +379,7 @@ void Plot::set_universe(pugi::xml_node plot_node) } } -void Plot::set_default_colors(pugi::xml_node plot_node) +void PlotBase::set_default_colors(pugi::xml_node plot_node) { // Copy plot color type and initialize all colors randomly std::string pl_color_by = "cell"; @@ -411,15 +406,8 @@ void Plot::set_default_colors(pugi::xml_node plot_node) } } -void Plot::set_user_colors(pugi::xml_node plot_node) +void PlotBase::set_user_colors(pugi::xml_node plot_node) { - if (!plot_node.select_nodes("color").empty() && PlotType::voxel == type_) { - if (mpi::master) { - warning( - fmt::format("Color specifications ignored in voxel plot {}", id_)); - } - } - for (auto cn : plot_node.children("color")) { // Make sure 3 values are specified for RGB vector user_rgb = get_node_array(cn, "rgb"); @@ -562,18 +550,12 @@ void Plot::set_meshlines(pugi::xml_node plot_node) } } -void Plot::set_mask(pugi::xml_node plot_node) +void PlotBase::set_mask(pugi::xml_node plot_node) { // Deal with masks pugi::xpath_node_set mask_nodes = plot_node.select_nodes("mask"); if (!mask_nodes.empty()) { - if (PlotType::voxel == type_) { - if (mpi::master) { - warning(fmt::format("Mask ignored in voxel plot {}", id_)); - } - } - if (mask_nodes.size() == 1) { // Get pointer to mask pugi::xml_node mask_node = mask_nodes[0].node(); @@ -625,7 +607,7 @@ void Plot::set_mask(pugi::xml_node plot_node) } } -void Plot::set_overlap_color(pugi::xml_node plot_node) +void PlotBase::set_overlap_color(pugi::xml_node plot_node) { color_overlaps_ = false; if (check_for_node(plot_node, "show_overlaps")) { @@ -654,23 +636,29 @@ void Plot::set_overlap_color(pugi::xml_node plot_node) } } -Plot::Plot(pugi::xml_node plot_node) - : index_meshlines_mesh_ {-1}, overlap_color_ {RED} +PlotBase::PlotBase(pugi::xml_node plot_node) { set_id(plot_node); - set_type(plot_node); - set_output_path(plot_node); set_bg_color(plot_node); - set_basis(plot_node); - set_origin(plot_node); - set_width(plot_node); set_universe(plot_node); set_default_colors(plot_node); set_user_colors(plot_node); - set_meshlines(plot_node); set_mask(plot_node); set_overlap_color(plot_node); -} // End Plot constructor +} + +Plot::Plot(pugi::xml_node plot_node) + : PlotBase(plot_node), index_meshlines_mesh_ {-1} +{ + set_type(plot_node); + set_output_path(plot_node); + set_basis(plot_node); + set_origin(plot_node); + set_width(plot_node); + set_meshlines(plot_node); + slice_level_ = level_; // Copy level employed in SlicePlotBase::get_map + slice_color_overlaps_ = color_overlaps_; +} //============================================================================== // OUTPUT_PPM writes out a previously generated image to a PPM file @@ -914,13 +902,12 @@ void create_voxel(Plot const& pl) hid_t dspace, dset, memspace; voxel_init(file_id, &(dims[0]), &dspace, &dset, &memspace); - PlotBase pltbase; + SlicePlotBase pltbase; pltbase.width_ = pl.width_; pltbase.origin_ = pl.origin_; pltbase.basis_ = PlotBasis::xy; pltbase.pixels_ = pl.pixels_; - pltbase.level_ = -1; // all universes for voxel files - pltbase.color_overlaps_ = pl.color_overlaps_; + pltbase.slice_color_overlaps_ = pl.color_overlaps_; ProgressBar pb; for (int z = 0; z < pl.pixels_[2]; z++) { @@ -989,13 +976,13 @@ RGBColor random_color(void) extern "C" int openmc_id_map(const void* plot, int32_t* data_out) { - auto plt = reinterpret_cast(plot); + auto plt = reinterpret_cast(plot); if (!plt) { set_errmsg("Invalid slice pointer passed to openmc_id_map"); return OPENMC_E_INVALID_ARGUMENT; } - if (plt->color_overlaps_ && model::overlap_check_count.size() == 0) { + if (plt->slice_color_overlaps_ && model::overlap_check_count.size() == 0) { model::overlap_check_count.resize(model::cells.size()); } @@ -1010,13 +997,13 @@ extern "C" int openmc_id_map(const void* plot, int32_t* data_out) extern "C" int openmc_property_map(const void* plot, double* data_out) { - auto plt = reinterpret_cast(plot); + auto plt = reinterpret_cast(plot); if (!plt) { set_errmsg("Invalid slice pointer passed to openmc_id_map"); return OPENMC_E_INVALID_ARGUMENT; } - if (plt->color_overlaps_ && model::overlap_check_count.size() == 0) { + if (plt->slice_color_overlaps_ && model::overlap_check_count.size() == 0) { model::overlap_check_count.resize(model::cells.size()); } From 5105a8423db4247870cea160e2c073dc59a6c30c Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Mon, 13 Dec 2021 16:05:41 -0500 Subject: [PATCH 1710/2654] further refactor of plots, start ProjectionPlot --- include/openmc/plot.h | 145 ++++++++++------ src/output.cpp | 55 +----- src/plot.cpp | 383 ++++++++++++++++++++++++------------------ 3 files changed, 319 insertions(+), 264 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index 1c2d9e48d..edd118bc3 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -23,12 +23,13 @@ namespace openmc { // Global variables //=============================================================================== -class Plot; +class PlottableInterface; namespace model { extern std::unordered_map plot_map; //!< map of plot ids to index -extern vector plots; //!< Plot instance container +extern std::vector> + plots; //!< Plot instance container extern uint64_t plotter_seed; // Stream index used by the plotter @@ -67,6 +68,49 @@ struct RGBColor { const RGBColor WHITE {255, 255, 255}; const RGBColor RED {255, 0, 0}; +/* + * PlottableInterface classes just have to have a unique ID in the plots.xml + * file, and guarantee being able to create output in some way. + */ +class PlottableInterface { +private: + void set_id(pugi::xml_node plot_node); + int id_; // unique plot ID + + void set_bg_color(pugi::xml_node plot_node); + void set_universe(pugi::xml_node plot_node); + void set_default_colors(pugi::xml_node plot_node); + void set_user_colors(pugi::xml_node plot_node); + void set_overlap_color(pugi::xml_node plot_node); + void set_mask(pugi::xml_node plot_node); + +protected: + // Plot output filename, derived classes have logic to set it + std::string path_plot_; + +public: + enum class PlotColorBy { cells = 0, mats = 1 }; + + // Creates the output image named path_plot_ + virtual void create_output() const = 0; + + // Print useful info to the terminal + virtual void print_info() const = 0; + + const std::string& path_plot() const { return path_plot_; } + const int id() const { return id_; } + const int level() const { return level_; } + + // Public color-related data + PlottableInterface(pugi::xml_node plot_node); + int level_; // Universe level to plot + bool color_overlaps_; // Show overlapping cells? + PlotColorBy color_by_; // Plot coloring (cell/material) + RGBColor not_found_ {WHITE}; // Plot background color + RGBColor overlap_color_ {RED}; // Plot overlap color + vector colors_; // Plot colors +}; + typedef xt::xtensor ImageData; struct IdData { @@ -93,20 +137,17 @@ struct PropertyData { xt::xtensor data_; //!< 2D array of temperature & density data }; -enum class PlotType { slice = 1, voxel = 2 }; - -enum class PlotBasis { xy = 1, xz = 2, yz = 3 }; - -enum class PlotColorBy { cells = 0, mats = 1 }; - //=============================================================================== // Plot class //=============================================================================== + class SlicePlotBase { public: template T get_map() const; + enum class PlotBasis { xy = 1, xz = 2, yz = 3 }; + // Members public: Position origin_; //!< Plot origin in geometry @@ -193,72 +234,78 @@ T SlicePlotBase::get_map() const return data; } -// Common data and methods between ProjectionPlot and Plot types -class PlotBase { +// Provides methods and data for controlling plot colors +class PlotColorMixin { protected: - void set_id(pugi::xml_node plot_node); - void set_bg_color(pugi::xml_node plot_node); - void set_universe(pugi::xml_node plot_node); - void set_default_colors(pugi::xml_node plot_node); - void set_user_colors(pugi::xml_node plot_node); - void set_overlap_color(pugi::xml_node plot_node); - void set_mask(pugi::xml_node plot_node); public: - PlotBase(pugi::xml_node plot_node); - int id_; // Plot ID - int level_; // Universe level to plot - bool color_overlaps_; //!< Show overlapping cells? - PlotColorBy color_by_; // Plot coloring (cell/material) - RGBColor not_found_ {WHITE}; // Plot background color - RGBColor overlap_color_ {RED}; // Plot overlap color - vector colors_; // Plot colors - std::string path_plot_; // Plot output filename }; // Represents either a voxel or pixel plot -class Plot : public SlicePlotBase, public PlotBase { +class Plot : public PlottableInterface, public SlicePlotBase { public: - // Constructor - Plot(pugi::xml_node plot); + enum class PlotType { slice = 1, voxel = 2 }; + + Plot(pugi::xml_node plot, PlotType type); - // Methods private: void set_output_path(pugi::xml_node plot_node); - void set_type(pugi::xml_node plot_node); void set_basis(pugi::xml_node plot_node); void set_origin(pugi::xml_node plot_node); void set_width(pugi::xml_node plot_node); void set_meshlines(pugi::xml_node plot_node); - // Members public: + // Add mesh lines to ImageData + void draw_mesh_lines(ImageData& data) const; + void create_image() const; + void create_voxel() const; + + virtual void create_output() const; + virtual void print_info() const; + PlotType type_; //!< Plot type (Slice/Voxel) int meshlines_width_; //!< Width of lines added to the plot int index_meshlines_mesh_ {-1}; //!< Index of the mesh to draw on the plot RGBColor meshlines_color_; //!< Color of meshlines on the plot }; +class ProjectionPlot : public PlottableInterface { +public: + ProjectionPlot(pugi::xml_node plot); + + virtual void create_output() const; + virtual void print_info() const; + +private: + void set_look_at(pugi::xml_node plot); + void set_camera_position(pugi::xml_node plot); + void set_field_of_view(pugi::xml_node plot); + + std::array pixels_; // pixel dimension of resulting image + double horizontal_field_of_view_; // horiz. f.o.v. in degrees + double vertical_field_of_view_; // vert. f.o.v. in degrees + Position camera_position_; // where camera is + Position look_at_; // point camera is centered looking at +}; + //=============================================================================== // Non-member functions //=============================================================================== -//! Add mesh lines to image data of a plot object -//! \param[in] plot object -//! \param[out] image data associated with the plot object -void draw_mesh_lines(Plot const& pl, ImageData& data); - -//! Write a PPM image using a plot object's image data -//! \param[in] plot object -//! \param[out] image data associated with the plot object -void output_ppm(Plot const& pl, const ImageData& data); +/* Write a PPM image + * filename - name of output file + * data - image data to write + */ +void output_ppm(const std::string& filename, const ImageData& data); #ifdef USE_LIBPNG -//! Write a PNG image using a plot object's image data -//! \param[in] plot object -//! \param[out] image data associated with the plot object -void output_png(Plot const& pl, const ImageData& data); +/* Write a PNG image + * filename - name of output file + * data - image data to write + */ +void output_png(const std::string& filename, const ImageData& data); #endif //! Initialize a voxel file @@ -298,14 +345,6 @@ void read_plots_xml(pugi::xml_node root); //! Clear memory void free_memory_plot(); -//! Create an image for a plot object -//! \param[in] plot object -void create_image(Plot const& pl); - -//! Create an hdf5 voxel file for a plot object -//! \param[in] plot object -void create_voxel(Plot const& pl); - //! Create a randomly generated RGB color //! \return RGBColor with random value RGBColor random_color(); diff --git a/src/output.cpp b/src/output.cpp index 04e15b82d..666ae15b3 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -221,56 +221,11 @@ void print_plot() if (settings::verbosity < 5) return; - for (auto pl : model::plots) { - // Plot id - fmt::print("Plot ID: {}\n", pl.id_); - // Plot filename - fmt::print("Plot file: {}\n", pl.path_plot_); - // Plot level - fmt::print("Universe depth: {}\n", pl.level_); - - // Plot type - if (PlotType::slice == pl.type_) { - fmt::print("Plot Type: Slice\n"); - } else if (PlotType::voxel == pl.type_) { - fmt::print("Plot Type: Voxel\n"); - } - - // Plot parameters - fmt::print( - "Origin: {} {} {}\n", pl.origin_[0], pl.origin_[1], pl.origin_[2]); - - if (PlotType::slice == pl.type_) { - fmt::print("Width: {:4} {:4}\n", pl.width_[0], pl.width_[1]); - } else if (PlotType::voxel == pl.type_) { - fmt::print( - "Width: {:4} {:4} {:4}\n", pl.width_[0], pl.width_[1], pl.width_[2]); - } - - if (PlotColorBy::cells == pl.color_by_) { - fmt::print("Coloring: Cells\n"); - } else if (PlotColorBy::mats == pl.color_by_) { - fmt::print("Coloring: Materials\n"); - } - - if (PlotType::slice == pl.type_) { - switch (pl.basis_) { - case PlotBasis::xy: - fmt::print("Basis: XY\n"); - break; - case PlotBasis::xz: - fmt::print("Basis: XZ\n"); - break; - case PlotBasis::yz: - fmt::print("Basis: YZ\n"); - break; - } - fmt::print("Pixels: {} {}\n", pl.pixels_[0], pl.pixels_[1]); - } else if (PlotType::voxel == pl.type_) { - fmt::print( - "Voxels: {} {} {}\n", pl.pixels_[0], pl.pixels_[1], pl.pixels_[2]); - } - + for (const auto& pl : model::plots) { + fmt::print("Plot ID: {}\n", pl->id()); + fmt::print("Plot file: {}\n", pl->path_plot()); + fmt::print("Universe depth: {}\n", pl->level()); + pl->print_info(); // prints type-specific plot info fmt::print("\n"); } } diff --git a/src/plot.cpp b/src/plot.cpp index d3486d553..fdba1370d 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -97,7 +97,7 @@ void PropertyData::set_overlap(size_t y, size_t x) namespace model { std::unordered_map plot_map; -vector plots; +std::vector> plots; uint64_t plotter_seed = 1; } // namespace model @@ -110,20 +110,66 @@ extern "C" int openmc_plot_geometry() { for (auto& pl : model::plots) { - write_message(5, "Processing plot {}: {}...", pl.id_, pl.path_plot_); - - if (PlotType::slice == pl.type_) { - // create 2D image - create_image(pl); - } else if (PlotType::voxel == pl.type_) { - // create voxel file for 3D viewing - create_voxel(pl); - } + write_message(5, "Processing plot {}: {}...", pl->id(), pl->path_plot()); + pl->create_output(); } return 0; } +void Plot::create_output() const +{ + if (PlotType::slice == type_) { + // create 2D image + create_image(); + } else if (PlotType::voxel == type_) { + // create voxel file for 3D viewing + create_voxel(); + } +} + +void Plot::print_info() const +{ + // Plot type + if (PlotType::slice == type_) { + fmt::print("Plot Type: Slice\n"); + } else if (PlotType::voxel == type_) { + fmt::print("Plot Type: Voxel\n"); + } + + // Plot parameters + fmt::print("Origin: {} {} {}\n", origin_[0], origin_[1], origin_[2]); + + if (PlotType::slice == type_) { + fmt::print("Width: {:4} {:4}\n", width_[0], width_[1]); + } else if (PlotType::voxel == type_) { + fmt::print("Width: {:4} {:4} {:4}\n", width_[0], width_[1], width_[2]); + } + + if (PlotColorBy::cells == color_by_) { + fmt::print("Coloring: Cells\n"); + } else if (PlotColorBy::mats == color_by_) { + fmt::print("Coloring: Materials\n"); + } + + if (PlotType::slice == type_) { + switch (basis_) { + case PlotBasis::xy: + fmt::print("Basis: XY\n"); + break; + case PlotBasis::xz: + fmt::print("Basis: XZ\n"); + break; + case PlotBasis::yz: + fmt::print("Basis: YZ\n"); + break; + } + fmt::print("Pixels: {} {}\n", pixels_[0], pixels_[1]); + } else if (PlotType::voxel == type_) { + fmt::print("Voxels: {} {} {}\n", pixels_[0], pixels_[1], pixels_[2]); + } +} + void read_plots_xml() { // Check if plots.xml exists; this is only necessary when the plot runmode is @@ -148,8 +194,26 @@ void read_plots_xml() void read_plots_xml(pugi::xml_node root) { for (auto node : root.children("plot")) { - model::plots.emplace_back(node); - model::plot_map[model::plots.back().id_] = model::plots.size() - 1; + std::string id_string = get_node_value(node, "id", true); + int id = std::stoi(id_string); + if (check_for_node(node, "type")) { + std::string type_str = get_node_value(node, "type", true); + if (type_str == "slice") + model::plots.emplace_back( + std::make_unique(node, Plot::PlotType::slice)); + else if (type_str == "voxel") + model::plots.emplace_back( + std::make_unique(node, Plot::PlotType::voxel)); + else if (type_str == "projection") + model::plots.emplace_back(std::make_unique(node)); + else + fatal_error( + fmt::format("Unsupported plot type '{}' in plot {}", type_str, id)); + + model::plot_map[model::plots.back()->id()] = model::plots.size() - 1; + } else { + fatal_error(fmt::format("Must specify plot type in plot {}", id)); + } } } @@ -159,61 +223,58 @@ void free_memory_plot() model::plot_map.clear(); } -//============================================================================== -// CREATE_IMAGE creates an image based on user input from a plots.xml +// creates an image based on user input from a plots.xml // specification in the PNG/PPM format -//============================================================================== - -void create_image(Plot const& pl) +void Plot::create_image() const { - size_t width = pl.pixels_[0]; - size_t height = pl.pixels_[1]; + size_t width = pixels_[0]; + size_t height = pixels_[1]; - ImageData data({width, height}, pl.not_found_); + ImageData data({width, height}, not_found_); // generate ids for the plot - auto ids = pl.get_map(); + auto ids = get_map(); // assign colors for (size_t y = 0; y < height; y++) { for (size_t x = 0; x < width; x++) { - int idx = pl.color_by_ == PlotColorBy::cells ? 0 : 2; + int idx = color_by_ == PlotColorBy::cells ? 0 : 2; auto id = ids.data_(y, x, idx); // no setting needed if not found if (id == NOT_FOUND) { continue; } if (id == OVERLAP) { - data(x, y) = pl.overlap_color_; + data(x, y) = overlap_color_; continue; } - if (PlotColorBy::cells == pl.color_by_) { - data(x, y) = pl.colors_[model::cell_map[id]]; - } else if (PlotColorBy::mats == pl.color_by_) { + if (PlotColorBy::cells == color_by_) { + data(x, y) = colors_[model::cell_map[id]]; + } else if (PlotColorBy::mats == color_by_) { if (id == MATERIAL_VOID) { data(x, y) = WHITE; continue; } - data(x, y) = pl.colors_[model::material_map[id]]; + data(x, y) = colors_[model::material_map[id]]; } // color_by if-else } // x for loop } // y for loop // draw mesh lines if present - if (pl.index_meshlines_mesh_ >= 0) { - draw_mesh_lines(pl, data); + if (index_meshlines_mesh_ >= 0) { + draw_mesh_lines(data); } // create image file #ifdef USE_LIBPNG - output_png(pl, data); + output_png(path_plot(), data); #else - output_ppm(pl, data); + output_ppm(path_plot(), data); #endif } -void PlotBase::set_id(pugi::xml_node plot_node) +void PlottableInterface::set_id(pugi::xml_node plot_node) { // Copy data into plots if (check_for_node(plot_node, "id")) { @@ -229,27 +290,6 @@ void PlotBase::set_id(pugi::xml_node plot_node) } } -void Plot::set_type(pugi::xml_node plot_node) -{ - // Copy plot type - // Default is slice - type_ = PlotType::slice; - // check type specified on plot node - if (check_for_node(plot_node, "type")) { - std::string type_str = get_node_value(plot_node, "type", true); - // set type using node value - if (type_str == "slice") { - type_ = PlotType::slice; - } else if (type_str == "voxel") { - type_ = PlotType::voxel; - } else { - // if we're here, something is wrong - fatal_error( - fmt::format("Unsupported plot type '{}' in plot {}", type_str, id_)); - } - } -} - void Plot::set_output_path(pugi::xml_node plot_node) { // Set output file path @@ -258,7 +298,7 @@ void Plot::set_output_path(pugi::xml_node plot_node) if (check_for_node(plot_node, "filename")) { filename = get_node_value(plot_node, "filename"); } else { - filename = fmt::format("plot_{}", id_); + filename = fmt::format("plot_{}", id()); } // add appropriate file extension to name switch (type_) { @@ -284,7 +324,7 @@ void Plot::set_output_path(pugi::xml_node plot_node) pixels_[1] = pxls[1]; } else { fatal_error( - fmt::format(" must be length 2 in slice plot {}", id_)); + fmt::format(" must be length 2 in slice plot {}", id())); } } else if (PlotType::voxel == type_) { if (pxls.size() == 3) { @@ -293,12 +333,12 @@ void Plot::set_output_path(pugi::xml_node plot_node) pixels_[2] = pxls[2]; } else { fatal_error( - fmt::format(" must be length 3 in voxel plot {}", id_)); + fmt::format(" must be length 3 in voxel plot {}", id())); } } } -void PlotBase::set_bg_color(pugi::xml_node plot_node) +void PlottableInterface::set_bg_color(pugi::xml_node plot_node) { // Copy plot background color if (check_for_node(plot_node, "background")) { @@ -306,7 +346,7 @@ void PlotBase::set_bg_color(pugi::xml_node plot_node) if (bg_rgb.size() == 3) { not_found_ = bg_rgb; } else { - fatal_error(fmt::format("Bad background RGB in plot {}", id_)); + fatal_error(fmt::format("Bad background RGB in plot {}", id())); } } } @@ -327,7 +367,7 @@ void Plot::set_basis(pugi::xml_node plot_node) basis_ = PlotBasis::yz; } else { fatal_error( - fmt::format("Unsupported plot basis '{}' in plot {}", pl_basis, id_)); + fmt::format("Unsupported plot basis '{}' in plot {}", pl_basis, id())); } } } @@ -339,7 +379,7 @@ void Plot::set_origin(pugi::xml_node plot_node) if (pl_origin.size() == 3) { origin_ = pl_origin; } else { - fatal_error(fmt::format("Origin must be length 3 in plot {}", id_)); + fatal_error(fmt::format("Origin must be length 3 in plot {}", id())); } } @@ -353,7 +393,7 @@ void Plot::set_width(pugi::xml_node plot_node) width_.y = pl_width[1]; } else { fatal_error( - fmt::format(" must be length 2 in slice plot {}", id_)); + fmt::format(" must be length 2 in slice plot {}", id())); } } else if (PlotType::voxel == type_) { if (pl_width.size() == 3) { @@ -361,25 +401,25 @@ void Plot::set_width(pugi::xml_node plot_node) width_ = pl_width; } else { fatal_error( - fmt::format(" must be length 3 in voxel plot {}", id_)); + fmt::format(" must be length 3 in voxel plot {}", id())); } } } -void PlotBase::set_universe(pugi::xml_node plot_node) +void PlottableInterface::set_universe(pugi::xml_node plot_node) { // Copy plot universe level if (check_for_node(plot_node, "level")) { level_ = std::stoi(get_node_value(plot_node, "level")); if (level_ < 0) { - fatal_error(fmt::format("Bad universe level in plot {}", id_)); + fatal_error(fmt::format("Bad universe level in plot {}", id())); } } else { level_ = PLOT_LEVEL_LOWEST; } } -void PlotBase::set_default_colors(pugi::xml_node plot_node) +void PlottableInterface::set_default_colors(pugi::xml_node plot_node) { // Copy plot color type and initialize all colors randomly std::string pl_color_by = "cell"; @@ -394,7 +434,7 @@ void PlotBase::set_default_colors(pugi::xml_node plot_node) colors_.resize(model::materials.size()); } else { fatal_error(fmt::format( - "Unsupported plot color type '{}' in plot {}", pl_color_by, id_)); + "Unsupported plot color type '{}' in plot {}", pl_color_by, id())); } for (auto& c : colors_) { @@ -406,21 +446,21 @@ void PlotBase::set_default_colors(pugi::xml_node plot_node) } } -void PlotBase::set_user_colors(pugi::xml_node plot_node) +void PlottableInterface::set_user_colors(pugi::xml_node plot_node) { for (auto cn : plot_node.children("color")) { // Make sure 3 values are specified for RGB vector user_rgb = get_node_array(cn, "rgb"); if (user_rgb.size() != 3) { - fatal_error(fmt::format("Bad RGB in plot {}", id_)); + fatal_error(fmt::format("Bad RGB in plot {}", id())); } // Ensure that there is an id for this color specification int col_id; if (check_for_node(cn, "id")) { col_id = std::stoi(get_node_value(cn, "id")); } else { - fatal_error( - fmt::format("Must specify id for color specification in plot {}", id_)); + fatal_error(fmt::format( + "Must specify id for color specification in plot {}", id())); } // Add RGB if (PlotColorBy::cells == color_by_) { @@ -429,7 +469,7 @@ void PlotBase::set_user_colors(pugi::xml_node plot_node) colors_[col_id] = user_rgb; } else { warning(fmt::format( - "Could not find cell {} specified in plot {}", col_id, id_)); + "Could not find cell {} specified in plot {}", col_id, id())); } } else if (PlotColorBy::mats == color_by_) { if (model::material_map.find(col_id) != model::material_map.end()) { @@ -437,7 +477,7 @@ void PlotBase::set_user_colors(pugi::xml_node plot_node) colors_[col_id] = user_rgb; } else { warning(fmt::format( - "Could not find material {} specified in plot {}", col_id, id_)); + "Could not find material {} specified in plot {}", col_id, id())); } } } // color node loop @@ -450,7 +490,7 @@ void Plot::set_meshlines(pugi::xml_node plot_node) if (!mesh_line_nodes.empty()) { if (PlotType::voxel == type_) { - warning(fmt::format("Meshlines ignored in voxel plot {}", id_)); + warning(fmt::format("Meshlines ignored in voxel plot {}", id())); } if (mesh_line_nodes.size() == 1) { @@ -464,7 +504,7 @@ void Plot::set_meshlines(pugi::xml_node plot_node) } else { fatal_error(fmt::format( "Must specify a meshtype for meshlines specification in plot {}", - id_)); + id())); } // Ensure that there is a linewidth for this meshlines specification @@ -475,7 +515,7 @@ void Plot::set_meshlines(pugi::xml_node plot_node) } else { fatal_error(fmt::format( "Must specify a linewidth for meshlines specification in plot {}", - id_)); + id())); } // Check for color @@ -484,7 +524,7 @@ void Plot::set_meshlines(pugi::xml_node plot_node) vector ml_rgb = get_node_array(meshlines_node, "color"); if (ml_rgb.size() != 3) { fatal_error( - fmt::format("Bad RGB for meshlines color in plot {}", id_)); + fmt::format("Bad RGB for meshlines color in plot {}", id())); } meshlines_color_ = ml_rgb; } @@ -492,7 +532,8 @@ void Plot::set_meshlines(pugi::xml_node plot_node) // Set mesh based on type if ("ufs" == meshtype) { if (!simulation::ufs_mesh) { - fatal_error(fmt::format("No UFS mesh for meshlines on plot {}", id_)); + fatal_error( + fmt::format("No UFS mesh for meshlines on plot {}", id())); } else { for (int i = 0; i < model::meshes.size(); ++i) { if (const auto* m = @@ -508,7 +549,7 @@ void Plot::set_meshlines(pugi::xml_node plot_node) } else if ("entropy" == meshtype) { if (!simulation::entropy_mesh) { fatal_error( - fmt::format("No entropy mesh for meshlines on plot {}", id_)); + fmt::format("No entropy mesh for meshlines on plot {}", id())); } else { for (int i = 0; i < model::meshes.size(); ++i) { if (const auto* m = @@ -530,7 +571,7 @@ void Plot::set_meshlines(pugi::xml_node plot_node) std::stringstream err_msg; fatal_error(fmt::format("Must specify a mesh id for meshlines tally " "mesh specification in plot {}", - id_)); + id())); } // find the tally index int idx; @@ -538,19 +579,19 @@ void Plot::set_meshlines(pugi::xml_node plot_node) if (err != 0) { fatal_error(fmt::format("Could not find mesh {} specified in " "meshlines for plot {}", - tally_mesh_id, id_)); + tally_mesh_id, id())); } index_meshlines_mesh_ = idx; } else { - fatal_error(fmt::format("Invalid type for meshlines on plot {}", id_)); + fatal_error(fmt::format("Invalid type for meshlines on plot {}", id())); } } else { - fatal_error(fmt::format("Mutliple meshlines specified in plot {}", id_)); + fatal_error(fmt::format("Mutliple meshlines specified in plot {}", id())); } } } -void PlotBase::set_mask(pugi::xml_node plot_node) +void PlottableInterface::set_mask(pugi::xml_node plot_node) { // Deal with masks pugi::xpath_node_set mask_nodes = plot_node.select_nodes("mask"); @@ -564,7 +605,7 @@ void PlotBase::set_mask(pugi::xml_node plot_node) vector iarray = get_node_array(mask_node, "components"); if (iarray.size() == 0) { fatal_error( - fmt::format("Missing in mask of plot {}", id_)); + fmt::format("Missing in mask of plot {}", id())); } // First we need to change the user-specified identifiers to indices @@ -576,7 +617,7 @@ void PlotBase::set_mask(pugi::xml_node plot_node) } else { fatal_error(fmt::format("Could not find cell {} specified in the " "mask in plot {}", - col_id, id_)); + col_id, id())); } } else if (PlotColorBy::mats == color_by_) { if (model::material_map.find(col_id) != model::material_map.end()) { @@ -584,7 +625,7 @@ void PlotBase::set_mask(pugi::xml_node plot_node) } else { fatal_error(fmt::format("Could not find material {} specified in " "the mask in plot {}", - col_id, id_)); + col_id, id())); } } } @@ -602,12 +643,12 @@ void PlotBase::set_mask(pugi::xml_node plot_node) } } else { - fatal_error(fmt::format("Mutliple masks specified in plot {}", id_)); + fatal_error(fmt::format("Mutliple masks specified in plot {}", id())); } } } -void PlotBase::set_overlap_color(pugi::xml_node plot_node) +void PlottableInterface::set_overlap_color(pugi::xml_node plot_node) { color_overlaps_ = false; if (check_for_node(plot_node, "show_overlaps")) { @@ -617,13 +658,13 @@ void PlotBase::set_overlap_color(pugi::xml_node plot_node) if (!color_overlaps_) { warning(fmt::format( "Overlap color specified in plot {} but overlaps won't be shown.", - id_)); + id())); } vector olap_clr = get_node_array(plot_node, "overlap_color"); if (olap_clr.size() == 3) { overlap_color_ = olap_clr; } else { - fatal_error(fmt::format("Bad overlap RGB in plot {}", id_)); + fatal_error(fmt::format("Bad overlap RGB in plot {}", id())); } } } @@ -636,7 +677,7 @@ void PlotBase::set_overlap_color(pugi::xml_node plot_node) } } -PlotBase::PlotBase(pugi::xml_node plot_node) +PlottableInterface::PlottableInterface(pugi::xml_node plot_node) { set_id(plot_node); set_bg_color(plot_node); @@ -647,10 +688,9 @@ PlotBase::PlotBase(pugi::xml_node plot_node) set_overlap_color(plot_node); } -Plot::Plot(pugi::xml_node plot_node) - : PlotBase(plot_node), index_meshlines_mesh_ {-1} +Plot::Plot(pugi::xml_node plot_node, PlotType type) + : PlottableInterface(plot_node), index_meshlines_mesh_ {-1}, type_(type) { - set_type(plot_node); set_output_path(plot_node); set_basis(plot_node); set_origin(plot_node); @@ -664,10 +704,10 @@ Plot::Plot(pugi::xml_node plot_node) // OUTPUT_PPM writes out a previously generated image to a PPM file //============================================================================== -void output_ppm(Plot const& pl, const ImageData& data) +void output_ppm(const std::string& filename, const ImageData& data) { // Open PPM file for writing - std::string fname = pl.path_plot_; + std::string fname = filename; fname = strtrim(fname); std::ofstream of; @@ -675,14 +715,14 @@ void output_ppm(Plot const& pl, const ImageData& data) // Write header of << "P6\n"; - of << pl.pixels_[0] << " " << pl.pixels_[1] << "\n"; + of << data.shape()[0] << " " << data.shape()[1] << "\n"; of << "255\n"; of.close(); of.open(fname, std::ios::binary | std::ios::app); // Write color for each pixel - for (int y = 0; y < pl.pixels_[1]; y++) { - for (int x = 0; x < pl.pixels_[0]; x++) { + for (int y = 0; y < data.shape()[1]; y++) { + for (int x = 0; x < data.shape()[0]; x++) { RGBColor rgb = data(x, y); of << rgb.red << rgb.green << rgb.blue; } @@ -695,10 +735,10 @@ void output_ppm(Plot const& pl, const ImageData& data) //============================================================================== #ifdef USE_LIBPNG -void output_png(Plot const& pl, const ImageData& data) +void output_png(const std::string& filename, const ImageData& data) { // Open PNG file for writing - std::string fname = pl.path_plot_; + std::string fname = filename; fname = strtrim(fname); auto fp = std::fopen(fname.c_str(), "wb"); @@ -714,8 +754,8 @@ void output_png(Plot const& pl, const ImageData& data) png_init_io(png_ptr, fp); // Write header (8 bit colour depth) - int width = pl.pixels_[0]; - int height = pl.pixels_[1]; + int width = data.shape()[0]; + int height = data.shape()[1]; png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); @@ -748,13 +788,13 @@ void output_png(Plot const& pl, const ImageData& data) // DRAW_MESH_LINES draws mesh line boundaries on an image //============================================================================== -void draw_mesh_lines(Plot const& pl, ImageData& data) +void Plot::draw_mesh_lines(ImageData& data) const { RGBColor rgb; - rgb = pl.meshlines_color_; + rgb = meshlines_color_; int ax1, ax2; - switch (pl.basis_) { + switch (basis_) { case PlotBasis::xy: ax1 = 0; ax2 = 1; @@ -771,45 +811,45 @@ void draw_mesh_lines(Plot const& pl, ImageData& data) UNREACHABLE(); } - Position ll_plot {pl.origin_}; - Position ur_plot {pl.origin_}; + Position ll_plot {origin_}; + Position ur_plot {origin_}; - ll_plot[ax1] -= pl.width_[0] / 2.; - ll_plot[ax2] -= pl.width_[1] / 2.; - ur_plot[ax1] += pl.width_[0] / 2.; - ur_plot[ax2] += pl.width_[1] / 2.; + ll_plot[ax1] -= width_[0] / 2.; + ll_plot[ax2] -= width_[1] / 2.; + ur_plot[ax1] += width_[0] / 2.; + ur_plot[ax2] += width_[1] / 2.; Position width = ur_plot - ll_plot; // Find the (axis-aligned) lines of the mesh that intersect this plot. auto axis_lines = - model::meshes[pl.index_meshlines_mesh_]->plot(ll_plot, ur_plot); + model::meshes[index_meshlines_mesh_]->plot(ll_plot, ur_plot); // Find the bounds along the second axis (accounting for low-D meshes). int ax2_min, ax2_max; if (axis_lines.second.size() > 0) { double frac = (axis_lines.second.back() - ll_plot[ax2]) / width[ax2]; - ax2_min = (1.0 - frac) * pl.pixels_[1]; + ax2_min = (1.0 - frac) * pixels_[1]; if (ax2_min < 0) ax2_min = 0; frac = (axis_lines.second.front() - ll_plot[ax2]) / width[ax2]; - ax2_max = (1.0 - frac) * pl.pixels_[1]; - if (ax2_max > pl.pixels_[1]) - ax2_max = pl.pixels_[1]; + ax2_max = (1.0 - frac) * pixels_[1]; + if (ax2_max > pixels_[1]) + ax2_max = pixels_[1]; } else { ax2_min = 0; - ax2_max = pl.pixels_[1]; + ax2_max = pixels_[1]; } // Iterate across the first axis and draw lines. for (auto ax1_val : axis_lines.first) { double frac = (ax1_val - ll_plot[ax1]) / width[ax1]; - int ax1_ind = frac * pl.pixels_[0]; + int ax1_ind = frac * pixels_[0]; for (int ax2_ind = ax2_min; ax2_ind < ax2_max; ++ax2_ind) { - for (int plus = 0; plus <= pl.meshlines_width_; plus++) { - if (ax1_ind + plus >= 0 && ax1_ind + plus < pl.pixels_[0]) + for (int plus = 0; plus <= meshlines_width_; plus++) { + if (ax1_ind + plus >= 0 && ax1_ind + plus < pixels_[0]) data(ax1_ind + plus, ax2_ind) = rgb; - if (ax1_ind - plus >= 0 && ax1_ind - plus < pl.pixels_[0]) + if (ax1_ind - plus >= 0 && ax1_ind - plus < pixels_[0]) data(ax1_ind - plus, ax2_ind) = rgb; } } @@ -819,60 +859,57 @@ void draw_mesh_lines(Plot const& pl, ImageData& data) int ax1_min, ax1_max; if (axis_lines.first.size() > 0) { double frac = (axis_lines.first.front() - ll_plot[ax1]) / width[ax1]; - ax1_min = frac * pl.pixels_[0]; + ax1_min = frac * pixels_[0]; if (ax1_min < 0) ax1_min = 0; frac = (axis_lines.first.back() - ll_plot[ax1]) / width[ax1]; - ax1_max = frac * pl.pixels_[0]; - if (ax1_max > pl.pixels_[0]) - ax1_max = pl.pixels_[0]; + ax1_max = frac * pixels_[0]; + if (ax1_max > pixels_[0]) + ax1_max = pixels_[0]; } else { ax1_min = 0; - ax1_max = pl.pixels_[0]; + ax1_max = pixels_[0]; } // Iterate across the second axis and draw lines. for (auto ax2_val : axis_lines.second) { double frac = (ax2_val - ll_plot[ax2]) / width[ax2]; - int ax2_ind = (1.0 - frac) * pl.pixels_[1]; + int ax2_ind = (1.0 - frac) * pixels_[1]; for (int ax1_ind = ax1_min; ax1_ind < ax1_max; ++ax1_ind) { - for (int plus = 0; plus <= pl.meshlines_width_; plus++) { - if (ax2_ind + plus >= 0 && ax2_ind + plus < pl.pixels_[1]) + for (int plus = 0; plus <= meshlines_width_; plus++) { + if (ax2_ind + plus >= 0 && ax2_ind + plus < pixels_[1]) data(ax1_ind, ax2_ind + plus) = rgb; - if (ax2_ind - plus >= 0 && ax2_ind - plus < pl.pixels_[1]) + if (ax2_ind - plus >= 0 && ax2_ind - plus < pixels_[1]) data(ax1_ind, ax2_ind - plus) = rgb; } } } } -//============================================================================== -// CREATE_VOXEL outputs a binary file that can be input into silomesh for 3D -// geometry visualization. It works the same way as create_image by dragging a -// particle across the geometry for the specified number of voxels. The first 3 -// int's in the binary are the number of x, y, and z voxels. The next 3 -// double's are the widths of the voxels in the x, y, and z directions. The -// next 3 double's are the x, y, and z coordinates of the lower left -// point. Finally the binary is filled with entries of four int's each. Each -// 'row' in the binary contains four int's: 3 for x,y,z position and 1 for -// cell or material id. For 1 million voxels this produces a file of -// approximately 15MB. -// ============================================================================= - -void create_voxel(Plot const& pl) +/* outputs a binary file that can be input into silomesh for 3D geometry + * visualization. It works the same way as create_image by dragging a particle + * across the geometry for the specified number of voxels. The first 3 int's in + * the binary are the number of x, y, and z voxels. The next 3 double's are + * the widths of the voxels in the x, y, and z directions. The next 3 double's + * are the x, y, and z coordinates of the lower left point. Finally the binary + * is filled with entries of four int's each. Each 'row' in the binary contains + * four int's: 3 for x,y,z position and 1 for cell or material id. For 1 + * million voxels this produces a file of approximately 15MB. + */ +void Plot::create_voxel() const { // compute voxel widths in each direction array vox; - vox[0] = pl.width_[0] / (double)pl.pixels_[0]; - vox[1] = pl.width_[1] / (double)pl.pixels_[1]; - vox[2] = pl.width_[2] / (double)pl.pixels_[2]; + vox[0] = width_[0] / static_cast(pixels_[0]); + vox[1] = width_[1] / static_cast(pixels_[1]); + vox[2] = width_[2] / static_cast(pixels_[2]); // initial particle position - Position ll = pl.origin_ - pl.width_ / 2.; + Position ll = origin_ - width_ / 2.; // Open binary plot file for writing std::ofstream of; - std::string fname = std::string(pl.path_plot_); + std::string fname = std::string(path_plot_); fname = strtrim(fname); hid_t file_id = file_open(fname, 'w'); @@ -888,7 +925,7 @@ void create_voxel(Plot const& pl) // Write current date and time write_attribute(file_id, "date_and_time", time_stamp().c_str()); array pixels; - std::copy(pl.pixels_.begin(), pl.pixels_.end(), pixels.begin()); + std::copy(pixels_.begin(), pixels_.end(), pixels.begin()); write_attribute(file_id, "num_voxels", pixels); write_attribute(file_id, "voxel_width", vox); write_attribute(file_id, "lower_left", ll); @@ -896,23 +933,24 @@ void create_voxel(Plot const& pl) // Create dataset for voxel data -- note that the dimensions are reversed // since we want the order in the file to be z, y, x hsize_t dims[3]; - dims[0] = pl.pixels_[2]; - dims[1] = pl.pixels_[1]; - dims[2] = pl.pixels_[0]; + dims[0] = pixels_[2]; + dims[1] = pixels_[1]; + dims[2] = pixels_[0]; hid_t dspace, dset, memspace; voxel_init(file_id, &(dims[0]), &dspace, &dset, &memspace); SlicePlotBase pltbase; - pltbase.width_ = pl.width_; - pltbase.origin_ = pl.origin_; + pltbase.width_ = width_; + pltbase.origin_ = origin_; pltbase.basis_ = PlotBasis::xy; - pltbase.pixels_ = pl.pixels_; - pltbase.slice_color_overlaps_ = pl.color_overlaps_; + pltbase.pixels_ = pixels_; + pltbase.slice_color_overlaps_ = color_overlaps_; ProgressBar pb; - for (int z = 0; z < pl.pixels_[2]; z++) { + for (int z = 0; z < pixels_[2]; z++) { // update progress bar - pb.set_value(100. * (double)z / (double)(pl.pixels_[2] - 1)); + pb.set_value( + 100. * static_cast(z) / static_cast((pixels_[2] - 1))); // update z coordinate pltbase.origin_.z = ll.z + z * vox[2]; @@ -921,7 +959,7 @@ void create_voxel(Plot const& pl) IdData ids = pltbase.get_map(); // select only cell/material ID data and flip the y-axis - int idx = pl.color_by_ == PlotColorBy::cells ? 0 : 2; + int idx = color_by_ == PlotColorBy::cells ? 0 : 2; xt::xtensor data_slice = xt::view(ids.data_, xt::all(), xt::all(), idx); xt::xtensor data_flipped = xt::flip(data_slice, 0); @@ -973,6 +1011,29 @@ RGBColor random_color(void) int(prn(&model::plotter_seed) * 255), int(prn(&model::plotter_seed) * 255)}; } +ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) +{ + set_look_at(node); + set_camera_position(node); + set_field_of_view(node); +} + +void ProjectionPlot::create_output() const +{ + // TODO +} + +void ProjectionPlot::print_info() const +{ + // TODO +} + +void ProjectionPlot::set_camera_position(pugi::xml_node node) {} + +void ProjectionPlot::set_look_at(pugi::xml_node node) {} + +void ProjectionPlot::set_field_of_view(pugi::xml_node node) {} + extern "C" int openmc_id_map(const void* plot, int32_t* data_out) { From d5aafc91cb65003399ec8f9dd7db048ea02979a0 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Tue, 14 Dec 2021 15:37:40 -0500 Subject: [PATCH 1711/2654] projection plots nominally working --- include/openmc/plot.h | 27 +- src/plot.cpp | 246 +++++++++++++++++- .../plot_projections/__init__.py | 0 .../plot_projections/geometry.xml | 15 ++ .../plot_projections/materials.xml | 19 ++ .../plot_projections/plots.xml | 30 +++ .../plot_projections/results_true.dat | 1 + .../plot_projections/settings.xml | 13 + .../plot_projections/tallies.xml | 20 ++ .../regression_tests/plot_projections/test.py | 60 +++++ 10 files changed, 421 insertions(+), 10 deletions(-) create mode 100644 tests/regression_tests/plot_projections/__init__.py create mode 100644 tests/regression_tests/plot_projections/geometry.xml create mode 100644 tests/regression_tests/plot_projections/materials.xml create mode 100644 tests/regression_tests/plot_projections/plots.xml create mode 100644 tests/regression_tests/plot_projections/results_true.dat create mode 100644 tests/regression_tests/plot_projections/settings.xml create mode 100644 tests/regression_tests/plot_projections/tallies.xml create mode 100644 tests/regression_tests/plot_projections/test.py diff --git a/include/openmc/plot.h b/include/openmc/plot.h index edd118bc3..af65fb7c3 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -67,6 +67,7 @@ struct RGBColor { // some default colors const RGBColor WHITE {255, 255, 255}; const RGBColor RED {255, 0, 0}; +const RGBColor BLACK {0, 0, 0}; /* * PlottableInterface classes just have to have a unique ID in the plots.xml @@ -272,6 +273,10 @@ public: }; class ProjectionPlot : public PlottableInterface { + + // TODO add optional choice between perspective or orthographic + // TODO add optionl to turn off wireframe + public: ProjectionPlot(pugi::xml_node plot); @@ -279,15 +284,27 @@ public: virtual void print_info() const; private: - void set_look_at(pugi::xml_node plot); - void set_camera_position(pugi::xml_node plot); - void set_field_of_view(pugi::xml_node plot); + void set_look_at(pugi::xml_node node); + void set_camera_position(pugi::xml_node node); + void set_field_of_view(pugi::xml_node node); + void set_pixels(pugi::xml_node node); + void set_opacities(pugi::xml_node node); std::array pixels_; // pixel dimension of resulting image - double horizontal_field_of_view_; // horiz. f.o.v. in degrees - double vertical_field_of_view_; // vert. f.o.v. in degrees + double horizontal_field_of_view_ {70.0}; // horiz. f.o.v. in degrees Position camera_position_; // where camera is Position look_at_; // point camera is centered looking at + Direction up_ {0.0, 0.0, 1.0}; // which way is up + bool wireframe_; // draw wireframe around ID boundaries (material or cell + // based on color_by) + RGBColor wireframe_color_ {BLACK}; // wireframe color + std::vector + xs_; // macro cross section values for cell volume rendering + + // If starting the particle from outside the geometry, we have to + // find a distance to the boundary in a non-standard surface intersection + // check. It's an exhaustive search over surfaces in the top-level universe. + static bool advance_to_boundary_from_void(Particle& p); }; //=============================================================================== diff --git a/src/plot.cpp b/src/plot.cpp index fdba1370d..bb643af53 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1016,23 +1016,259 @@ ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) set_look_at(node); set_camera_position(node); set_field_of_view(node); + set_pixels(node); + set_opacities(node); + + // TODO naming stuff... + std::string name = "projection" + std::to_string(id()) + ".png"; + path_plot_ = name; +} + +// Advances to the next boundary from outside the geometry +bool ProjectionPlot::advance_to_boundary_from_void(Particle& p) +{ + constexpr double scoot = 1e-5; + double min_dist = {INFINITY}; + auto coord = p.coord(0); + Universe* uni = model::universes[model::root_universe].get(); + for (auto c_i : uni->cells_) { + auto dist = model::cells.at(c_i)->distance(coord.r, coord.u, 0, &p); + if (dist.first < min_dist) + min_dist = dist.first; + } + if (min_dist > 1e300) + return false; + else { // advance the particle + for (int j = 0; j < p.n_coord(); ++j) + p.coord(j).r += (min_dist + scoot) * p.coord(j).u; + return true; + } } void ProjectionPlot::create_output() const { - // TODO + // Get centerline vector for camera-to-model. We create vectors around this + // that form a pixel array, and then trace rays along that. + Direction looking_direction = look_at_ - camera_position_; + looking_direction /= looking_direction.norm(); + + // Now we convert to the polar coordinate system with the polar angle + // measuring the angle from the vector up_. Phi is the rotation about up_. For + // now, up_ is hard-coded to be +z. + constexpr double DEGREE_TO_RADIAN = M_PI / 180.0; + double phi0 = std::atan2(looking_direction.y, looking_direction.x); + double mu0 = std::acos(looking_direction.z); + double horiz_fov_radians = horizontal_field_of_view_ * DEGREE_TO_RADIAN; + double p0 = static_cast(pixels_[0]); + double p1 = static_cast(pixels_[1]); + double vert_fov_radians = horiz_fov_radians * p1 / p0; + double dphi = horiz_fov_radians / p0; + double dmu = vert_fov_radians / p1; + + size_t width = pixels_[0]; + size_t height = pixels_[1]; + ImageData data({width, height}, not_found_); + + // Loop over horizontal lines (vert field of view) + SourceSite s; // Where particle starts from (camera) + s.E = 1; + s.wgt = 1; + s.delayed_group = 0; + s.particle = ParticleType::photon; // just has to be something reasonable + s.parent_id = 1; + s.progeny_id = 2; + s.r = camera_position_; + + Particle p; + s.u.x = 1.0; + s.u.y = 0.0; + s.u.z = 0.0; + p.from_source(&s); + + // Do preliminary loop to advance to get within the geometry + struct TrackSegment { + int id; // material or cell ID (which is being colored) + double length; // length of this track intersection + TrackSegment(int id_a, double length_a) : id(id_a), length(length_a) {} + }; + std::vector segments; + std::vector old_segments; + + for (int vert = 0; vert < pixels_[1]; ++vert) { + for (int horiz = 0; horiz < pixels_[0]; ++horiz) { + double this_phi = phi0 - horiz_fov_radians / 2.0 + dphi * horiz; + double this_mu = mu0 - vert_fov_radians / 2.0 + dmu * vert; + s.u.x = std::cos(this_phi) * std::sin(this_mu); + s.u.y = std::sin(this_phi) * std::sin(this_mu); + s.u.z = std::cos(this_mu); + p.from_source(&s); // put particle at camera + bool hitsomething = false; + bool intersection_found = true; + int loop_counter = 0; + const int max_intersections = 1000000; + + old_segments = segments; + segments.clear(); + while (intersection_found) { + bool inside_cell = exhaustive_find_cell(p); + if (inside_cell) { + hitsomething = true; + intersection_found = true; + auto dist = distance_to_boundary(p); + segments.emplace_back(color_by_ == PlotColorBy::mats + ? p.material() + : p.coord(p.n_coord() - 1).cell, + dist.distance); + + // Advance particle + for (int lev = 0; lev < p.n_coord(); ++lev) { + p.coord(lev).r += dist.distance * p.coord(lev).u; + } + p.surface() = dist.surface_index; + p.n_coord_last() = p.n_coord(); + p.n_coord() = dist.coord_level; + if (dist.lattice_translation[0] != 0 || + dist.lattice_translation[1] != 0 || + dist.lattice_translation[2] != 0) { + cross_lattice(p, dist); + } + + } else { + intersection_found = advance_to_boundary_from_void(p); + } + loop_counter++; + if (loop_counter > max_intersections) + fatal_error("Infinite loop in projection plot"); + } + + // Now color the pixel based on what we have intersected... + // Loops backwards over intersections. + Position current_color(not_found_.red, not_found_.green, not_found_.blue); + for (unsigned i = segments.size(); i-- > 0;) { + int colormap_idx = segments[i].id; + RGBColor seg_color = colors_[colormap_idx]; + Position seg_color_vec(seg_color.red, seg_color.green, seg_color.blue); + double mixing = std::exp(-xs_[colormap_idx] * segments[i].length); + current_color = current_color * mixing + (1.0 - mixing) * seg_color_vec; + RGBColor result; + result.red = static_cast(current_color.x); + result.green = static_cast(current_color.y); + result.blue = static_cast(current_color.z); + data(horiz, vert) = result; + } + + // Check to draw wireframe + bool draw_wireframe = false; + if (segments.size() == old_segments.size()) { + for (int i = 0; i < segments.size(); ++i) { + if (segments[i].id != old_segments[i].id) { + draw_wireframe = true; + break; + } + } + } else { + draw_wireframe = true; + } + if (draw_wireframe) { + data(horiz, vert) = wireframe_color_; + } + } + } +#ifdef USE_LIBPNG + output_png(path_plot(), data); +#else + output_ppm(path_plot(), data); +#endif } void ProjectionPlot::print_info() const { - // TODO + fmt::print("Plot Type: Projection\n"); + fmt::print("Camera position: {} {} {}\n", camera_position_.x, + camera_position_.y, camera_position_.z); + fmt::print("Look at: {} {} {}\n", look_at_.x, look_at_.y, look_at_.z); + fmt::print( + "Horizontal field of view: {} degrees\n", horizontal_field_of_view_); + fmt::print("Pixels: {} {}\n", pixels_[0], pixels_[1]); } -void ProjectionPlot::set_camera_position(pugi::xml_node node) {} +void ProjectionPlot::set_opacities(pugi::xml_node node) +{ -void ProjectionPlot::set_look_at(pugi::xml_node node) {} + xs_.resize(colors_.size(), 1e6); // set to large value for opaque by default -void ProjectionPlot::set_field_of_view(pugi::xml_node node) {} + for (auto cn : node.children("color")) { + // Make sure 3 values are specified for RGB + double user_xs = std::stod(get_node_value(cn, "xs")); + int col_id = std::stoi(get_node_value(cn, "id")); + + // Add RGB + if (PlotColorBy::cells == color_by_) { + if (model::cell_map.find(col_id) != model::cell_map.end()) { + col_id = model::cell_map[col_id]; + xs_[col_id] = user_xs; + } else { + warning(fmt::format( + "Could not find cell {} specified in plot {}", col_id, id())); + } + } else if (PlotColorBy::mats == color_by_) { + if (model::material_map.find(col_id) != model::material_map.end()) { + col_id = model::material_map[col_id]; + xs_[col_id] = user_xs; + } else { + warning(fmt::format( + "Could not find material {} specified in plot {}", col_id, id())); + } + } + } +} + +void ProjectionPlot::set_pixels(pugi::xml_node node) +{ + vector pxls = get_node_array(node, "pixels"); + if (pxls.size() != 2) + fatal_error( + fmt::format(" must be length 2 in projection plot {}", id())); + pixels_[0] = pxls[0]; + pixels_[1] = pxls[1]; +} + +void ProjectionPlot::set_camera_position(pugi::xml_node node) +{ + vector camera_pos = get_node_array(node, "camera_position"); + if (camera_pos.size() != 3) { + fatal_error( + fmt::format("look_at element must have three floating point values")); + } + camera_position_.x = camera_pos[0]; + camera_position_.y = camera_pos[1]; + camera_position_.z = camera_pos[2]; +} + +void ProjectionPlot::set_look_at(pugi::xml_node node) +{ + vector look_at = get_node_array(node, "look_at"); + if (look_at.size() != 3) { + fatal_error("look_at element must have three floating point values"); + } + look_at_.x = look_at[0]; + look_at_.y = look_at[1]; + look_at_.z = look_at[2]; +} + +void ProjectionPlot::set_field_of_view(pugi::xml_node node) +{ + // Defaults to 70 degree horizontal field of view (see .h file) + if (check_for_node(node, "field_of_view")) { + double fov = std::stod(get_node_value(node, "field_of_view", true)); + if (fov < 180.0 && fov > 0.0) { + horizontal_field_of_view_ = fov; + } else { + fatal_error(fmt::format( + "Field of view for plot {} out-of-range. Must be in (0, 180).", id())); + } + } +} extern "C" int openmc_id_map(const void* plot, int32_t* data_out) { diff --git a/tests/regression_tests/plot_projections/__init__.py b/tests/regression_tests/plot_projections/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/plot_projections/geometry.xml b/tests/regression_tests/plot_projections/geometry.xml new file mode 100644 index 000000000..982187644 --- /dev/null +++ b/tests/regression_tests/plot_projections/geometry.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tests/regression_tests/plot_projections/materials.xml b/tests/regression_tests/plot_projections/materials.xml new file mode 100644 index 000000000..35f0de312 --- /dev/null +++ b/tests/regression_tests/plot_projections/materials.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/regression_tests/plot_projections/plots.xml b/tests/regression_tests/plot_projections/plots.xml new file mode 100644 index 000000000..2d22c8865 --- /dev/null +++ b/tests/regression_tests/plot_projections/plots.xml @@ -0,0 +1,30 @@ + + + + + 0. 0. 0. + 20. 20. 20. + 200 200 + + + + 70 + + + + 0. 0. 0. + 20. 20. 20. + 25 25 + 200 200 + + 90 + + + + 0. 0. 0. + 20. 20. 20. + 200 200 + 240 240 240 + + + diff --git a/tests/regression_tests/plot_projections/results_true.dat b/tests/regression_tests/plot_projections/results_true.dat new file mode 100644 index 000000000..45e097f62 --- /dev/null +++ b/tests/regression_tests/plot_projections/results_true.dat @@ -0,0 +1 @@ +8231bc2d60bee9df464fbf3c5b2ea611dcd0f10232f6a9b04f58fc5226716acb31580578f74d194f8ab2df1848ea1556621bf997e1d1562d5eb8471def2a5f24 \ No newline at end of file diff --git a/tests/regression_tests/plot_projections/settings.xml b/tests/regression_tests/plot_projections/settings.xml new file mode 100644 index 000000000..adf256d2d --- /dev/null +++ b/tests/regression_tests/plot_projections/settings.xml @@ -0,0 +1,13 @@ + + + + plot + + + 5 4 3 + -10 -10 -10 + 10 10 10 + + 1 + + diff --git a/tests/regression_tests/plot_projections/tallies.xml b/tests/regression_tests/plot_projections/tallies.xml new file mode 100644 index 000000000..b7e678ca0 --- /dev/null +++ b/tests/regression_tests/plot_projections/tallies.xml @@ -0,0 +1,20 @@ + + + + + -10 10 + -10 10 + -10 0 5 7.5 8.75 10 + + + + mesh + 2 + + + + 1 + total + + + diff --git a/tests/regression_tests/plot_projections/test.py b/tests/regression_tests/plot_projections/test.py new file mode 100644 index 000000000..2e1f4cd8d --- /dev/null +++ b/tests/regression_tests/plot_projections/test.py @@ -0,0 +1,60 @@ +import glob +import hashlib +import os + +import h5py +import openmc + +from tests.testing_harness import TestHarness +from tests.regression_tests import config + + +class PlotTestHarness(TestHarness): + """Specialized TestHarness for running OpenMC plotting tests.""" + def __init__(self, plot_names): + super().__init__(None) + self._plot_names = plot_names + + def _run_openmc(self): + openmc.plot_geometry(openmc_exec=config['exe']) + + def _test_output_created(self): + """Make sure *.png has been created.""" + for fname in self._plot_names: + assert os.path.exists(fname), 'Plot output file does not exist.' + + def _cleanup(self): + super()._cleanup() + for fname in self._plot_names: + if os.path.exists(fname): + os.remove(fname) + + def _get_results(self): + """Return a string hash of the plot files.""" + outstr = bytes() + + for fname in self._plot_names: + if fname.endswith('.png'): + # Add PNG output to results + with open(fname, 'rb') as fh: + outstr += fh.read() + elif fname.endswith('.h5'): + # Add voxel data to results + with h5py.File(fname, 'r') as fh: + outstr += fh.attrs['filetype'] + outstr += fh.attrs['num_voxels'].tobytes() + outstr += fh.attrs['lower_left'].tobytes() + outstr += fh.attrs['voxel_width'].tobytes() + outstr += fh['data'][()].tobytes() + + # Hash the information and return. + sha512 = hashlib.sha512() + sha512.update(outstr) + outstr = sha512.hexdigest() + + return outstr + + +def test_plot(): + harness = PlotTestHarness(('projection1.png', 'projection2.png', 'projection3.png')) + harness.main() From bad79975b04f30f6025310cbe8982d54b3d7c458 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 16 Dec 2021 14:10:19 -0500 Subject: [PATCH 1712/2654] make wireframes not spotty --- src/plot.cpp | 59 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/src/plot.cpp b/src/plot.cpp index bb643af53..2d5d039cb 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1085,16 +1085,28 @@ void ProjectionPlot::create_output() const s.u.z = 0.0; p.from_source(&s); - // Do preliminary loop to advance to get within the geometry struct TrackSegment { int id; // material or cell ID (which is being colored) double length; // length of this track intersection TrackSegment(int id_a, double length_a) : id(id_a), length(length_a) {} }; - std::vector segments; - std::vector old_segments; + + /* Holds all of the track segments for the current rendered line of pixels. + * old_segments holds a copy of this_line_segments from the previous line. + * By holding both we can check if the cell/material intersection stack + * differs from the left or upper neighbor. This allows a robustly drawn + * wireframe. If only checking the left pixel (which requires substantially + * less memory), the wireframe tends to be spotty and be disconnected for + * surface edges oriented horizontally in the rendering. + * + * Note that a vector of vectors is required rather than a 2-tensor, + * since the stack size varies within each column. + */ + std::vector> this_line_segments(pixels_[0]); + std::vector> old_segments(pixels_[0]); for (int vert = 0; vert < pixels_[1]; ++vert) { + old_segments = this_line_segments; for (int horiz = 0; horiz < pixels_[0]; ++horiz) { double this_phi = phi0 - horiz_fov_radians / 2.0 + dphi * horiz; double this_mu = mu0 - vert_fov_radians / 2.0 + dmu * vert; @@ -1107,17 +1119,16 @@ void ProjectionPlot::create_output() const int loop_counter = 0; const int max_intersections = 1000000; - old_segments = segments; - segments.clear(); + this_line_segments[horiz].clear(); while (intersection_found) { bool inside_cell = exhaustive_find_cell(p); if (inside_cell) { hitsomething = true; intersection_found = true; auto dist = distance_to_boundary(p); - segments.emplace_back(color_by_ == PlotColorBy::mats - ? p.material() - : p.coord(p.n_coord() - 1).cell, + this_line_segments[horiz].emplace_back( + color_by_ == PlotColorBy::mats ? p.material() + : p.coord(p.n_coord() - 1).cell, dist.distance); // Advance particle @@ -1144,6 +1155,7 @@ void ProjectionPlot::create_output() const // Now color the pixel based on what we have intersected... // Loops backwards over intersections. Position current_color(not_found_.red, not_found_.green, not_found_.blue); + const auto& segments = this_line_segments[horiz]; for (unsigned i = segments.size(); i-- > 0;) { int colormap_idx = segments[i].id; RGBColor seg_color = colors_[colormap_idx]; @@ -1157,17 +1169,30 @@ void ProjectionPlot::create_output() const data(horiz, vert) = result; } - // Check to draw wireframe - bool draw_wireframe = false; - if (segments.size() == old_segments.size()) { - for (int i = 0; i < segments.size(); ++i) { - if (segments[i].id != old_segments[i].id) { - draw_wireframe = true; - break; + auto trackstack_equivalent = + [](const std::vector& track1, + const std::vector& track2) -> bool { + if (track1.size() != track2.size()) + return false; + for (int i = 0; i < track1.size(); ++i) { + if (track1[i].id != track2[i].id) { + return false; } } - } else { - draw_wireframe = true; + return true; + }; + + // Check to draw wireframe + bool draw_wireframe = false; + if (horiz > 0) { + draw_wireframe = + draw_wireframe || !trackstack_equivalent(this_line_segments[horiz], + this_line_segments[horiz - 1]); + } + if (vert > 0) { + draw_wireframe = + draw_wireframe || !trackstack_equivalent( + this_line_segments[horiz], old_segments[horiz]); } if (draw_wireframe) { data(horiz, vert) = wireframe_color_; From 071b6fa7967c75e91ae861097b01f6a9adc97a16 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 16 Dec 2021 14:41:03 -0500 Subject: [PATCH 1713/2654] pick up on cell edges, not just boundaries --- include/openmc/plot.h | 34 +++++++++++++++++++++--- src/plot.cpp | 62 ++++++++++++++++++++++++++----------------- 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index af65fb7c3..d9bea700d 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -290,6 +290,24 @@ private: void set_pixels(pugi::xml_node node); void set_opacities(pugi::xml_node node); + /* Used for drawing wireframe and colors. We record the list of + * surface/cell/material intersections and the corresponding lengths as a ray + * traverses the geometry, then color by iterating in reverse. + */ + struct TrackSegment { + int id; // material or cell ID (which is being colored) + double length; // length of this track intersection + + /* Recording this allows us to draw edges on the wireframe. For instance + * if two surfaces bound a single cell, it allows drawing that sharp edge + * where the surfaces intersect. + */ + int surface; // last surface ID intersected in this segment + TrackSegment(int id_a, double length_a, int surface_a) + : id(id_a), length(length_a), surface(surface_a) + {} + }; + std::array pixels_; // pixel dimension of resulting image double horizontal_field_of_view_ {70.0}; // horiz. f.o.v. in degrees Position camera_position_; // where camera is @@ -301,10 +319,18 @@ private: std::vector xs_; // macro cross section values for cell volume rendering - // If starting the particle from outside the geometry, we have to - // find a distance to the boundary in a non-standard surface intersection - // check. It's an exhaustive search over surfaces in the top-level universe. - static bool advance_to_boundary_from_void(Particle& p); + /* If starting the particle from outside the geometry, we have to + * find a distance to the boundary in a non-standard surface intersection + * check. It's an exhaustive search over surfaces in the top-level universe. + */ + static int advance_to_boundary_from_void(Particle& p); + + /* Checks if a vector of two TrackSegments is equivalent. We define this + * to mean not having matching intersection lengths, but rather having + * a matching sequence of surface/cell/material intersections. + */ + static bool trackstack_equivalent(const std::vector& track1, + const std::vector& track2); }; //=============================================================================== diff --git a/src/plot.cpp b/src/plot.cpp index 2d5d039cb..372c5a25b 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1025,26 +1025,46 @@ ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) } // Advances to the next boundary from outside the geometry -bool ProjectionPlot::advance_to_boundary_from_void(Particle& p) +// Returns -1 if no intersection found, and the surface index +// if an intersection was found. +int ProjectionPlot::advance_to_boundary_from_void(Particle& p) { constexpr double scoot = 1e-5; double min_dist = {INFINITY}; auto coord = p.coord(0); Universe* uni = model::universes[model::root_universe].get(); + int intersected_surface = -1; for (auto c_i : uni->cells_) { auto dist = model::cells.at(c_i)->distance(coord.r, coord.u, 0, &p); - if (dist.first < min_dist) + if (dist.first < min_dist) { min_dist = dist.first; + intersected_surface = dist.second; + } } if (min_dist > 1e300) - return false; + return -1; else { // advance the particle for (int j = 0; j < p.n_coord(); ++j) p.coord(j).r += (min_dist + scoot) * p.coord(j).u; - return true; + return intersected_surface; } } +bool ProjectionPlot::trackstack_equivalent( + const std::vector& track1, + const std::vector& track2) +{ + if (track1.size() != track2.size()) + return false; + for (int i = 0; i < track1.size(); ++i) { + if (track1[i].id != track2[i].id || + track1[i].surface != track2[i].surface) { + return false; + } + } + return true; +} + void ProjectionPlot::create_output() const { // Get centerline vector for camera-to-model. We create vectors around this @@ -1085,12 +1105,6 @@ void ProjectionPlot::create_output() const s.u.z = 0.0; p.from_source(&s); - struct TrackSegment { - int id; // material or cell ID (which is being colored) - double length; // length of this track intersection - TrackSegment(int id_a, double length_a) : id(id_a), length(length_a) {} - }; - /* Holds all of the track segments for the current rendered line of pixels. * old_segments holds a copy of this_line_segments from the previous line. * By holding both we can check if the cell/material intersection stack @@ -1120,16 +1134,26 @@ void ProjectionPlot::create_output() const const int max_intersections = 1000000; this_line_segments[horiz].clear(); + int first_surface = -1; // surface first passed when entering the model + bool first_inside_model = true; // false after entering the model while (intersection_found) { bool inside_cell = exhaustive_find_cell(p); if (inside_cell) { + + // This allows drawing wireframes with surface intersection + // edges on the model boundary for the same cell. + if (first_inside_model) { + this_line_segments[horiz].emplace_back(0, 0.0, first_surface); + first_inside_model = false; + } + hitsomething = true; intersection_found = true; auto dist = distance_to_boundary(p); this_line_segments[horiz].emplace_back( color_by_ == PlotColorBy::mats ? p.material() : p.coord(p.n_coord() - 1).cell, - dist.distance); + dist.distance, dist.surface_index); // Advance particle for (int lev = 0; lev < p.n_coord(); ++lev) { @@ -1145,7 +1169,8 @@ void ProjectionPlot::create_output() const } } else { - intersection_found = advance_to_boundary_from_void(p); + first_surface = advance_to_boundary_from_void(p); + intersection_found = first_surface != -1; // -1 if no surface found } loop_counter++; if (loop_counter > max_intersections) @@ -1169,19 +1194,6 @@ void ProjectionPlot::create_output() const data(horiz, vert) = result; } - auto trackstack_equivalent = - [](const std::vector& track1, - const std::vector& track2) -> bool { - if (track1.size() != track2.size()) - return false; - for (int i = 0; i < track1.size(); ++i) { - if (track1[i].id != track2[i].id) { - return false; - } - } - return true; - }; - // Check to draw wireframe bool draw_wireframe = false; if (horiz > 0) { From d51fd873ab3d4b6fdac00111f6b573ae713bfa4d Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 16 Dec 2021 15:10:16 -0500 Subject: [PATCH 1714/2654] read user-provided plot names, also more sophisticated file extension checking --- include/openmc/plot.h | 1 + src/plot.cpp | 44 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index d9bea700d..d35259dba 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -284,6 +284,7 @@ public: virtual void print_info() const; private: + void set_output_path(pugi::xml_node plot_node); void set_look_at(pugi::xml_node node); void set_camera_position(pugi::xml_node node); void set_field_of_view(pugi::xml_node node); diff --git a/src/plot.cpp b/src/plot.cpp index 372c5a25b..a63a16e0e 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -290,6 +290,17 @@ void PlottableInterface::set_id(pugi::xml_node plot_node) } } +// Checks if png or ppm is already present +bool file_extension_present( + const std::string& filename, const std::string& extension) +{ + std::string file_extension_if_present = + filename.substr(filename.find_last_of(".") + 1); + if (file_extension_if_present == extension) + return true; + return false; +} + void Plot::set_output_path(pugi::xml_node plot_node) { // Set output file path @@ -304,13 +315,16 @@ void Plot::set_output_path(pugi::xml_node plot_node) switch (type_) { case PlotType::slice: #ifdef USE_LIBPNG - filename.append(".png"); + if (!file_extension_present(filename, "png")) + filename.append(".png"); #else - filename.append(".ppm"); + if (!file_extension_present(filename, "ppm")) + filename.append(".ppm"); #endif break; case PlotType::voxel: - filename.append(".h5"); + if (!file_extension_present(filename, "h5")) + filename.append(".h5"); break; } @@ -1013,15 +1027,33 @@ RGBColor random_color(void) ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) { + set_output_path(node); set_look_at(node); set_camera_position(node); set_field_of_view(node); set_pixels(node); set_opacities(node); +} - // TODO naming stuff... - std::string name = "projection" + std::to_string(id()) + ".png"; - path_plot_ = name; +void ProjectionPlot::set_output_path(pugi::xml_node node) +{ + // Set output file path + std::string filename; + + if (check_for_node(node, "filename")) { + filename = get_node_value(node, "filename"); + } else { + filename = fmt::format("plot_{}", id()); + } + +#ifdef USE_LIBPNG + if (!file_extension_present(filename, "png")) + filename.append(".png"); +#else + if (!file_extension_present(filename, "ppm")) + filename.append(".ppm"); +#endif + path_plot_ = filename; } // Advances to the next boundary from outside the geometry From 76cc722090f4cd856131cb48affc69eebed88cbd Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 16 Dec 2021 17:24:32 -0500 Subject: [PATCH 1715/2654] add option to do orthographic projection --- include/openmc/plot.h | 13 +++++++-- include/openmc/position.h | 5 ++++ src/plot.cpp | 59 +++++++++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index d35259dba..c4476af41 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -274,9 +274,6 @@ public: class ProjectionPlot : public PlottableInterface { - // TODO add optional choice between perspective or orthographic - // TODO add optionl to turn off wireframe - public: ProjectionPlot(pugi::xml_node plot); @@ -290,6 +287,7 @@ private: void set_field_of_view(pugi::xml_node node); void set_pixels(pugi::xml_node node); void set_opacities(pugi::xml_node node); + void set_orthographic_width(pugi::xml_node node); /* Used for drawing wireframe and colors. We record the list of * surface/cell/material intersections and the corresponding lengths as a ray @@ -316,6 +314,12 @@ private: Direction up_ {0.0, 0.0, 1.0}; // which way is up bool wireframe_; // draw wireframe around ID boundaries (material or cell // based on color_by) + + /* The horizontal thickness, if using an orthographic projection. + * If set to zero, we assume using a perspective projection. + */ + double orthographic_width_ {0.0}; + RGBColor wireframe_color_ {BLACK}; // wireframe color std::vector xs_; // macro cross section values for cell volume rendering @@ -332,6 +336,9 @@ private: */ static bool trackstack_equivalent(const std::vector& track1, const std::vector& track2); + + // Closed form 3x3 matrix inversion + static std::vector invert_matrix(const std::vector& input); }; //=============================================================================== diff --git a/include/openmc/position.h b/include/openmc/position.h index 4fde420cc..0200cda3b 100644 --- a/include/openmc/position.h +++ b/include/openmc/position.h @@ -83,6 +83,11 @@ struct Position { return x * other.x + y * other.y + z * other.z; } inline double norm() const { return std::sqrt(x * x + y * y + z * z); } + inline Position cross(Position other) const + { + return {y * other.z - z * other.y, z * other.x - x * other.z, + x * other.y - y * other.x}; + } //! Reflect a direction across a normal vector //! \param[in] other Vector to reflect across diff --git a/src/plot.cpp b/src/plot.cpp index a63a16e0e..67e36c448 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1033,6 +1033,12 @@ ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) set_field_of_view(node); set_pixels(node); set_opacities(node); + set_orthographic_width(node); + + if (check_for_node(node, "orthographic_width") && + check_for_node(node, "field_of_view")) + fatal_error("orthographic_width and field_of_view are mutually exclusive " + "parameters."); } void ProjectionPlot::set_output_path(pugi::xml_node node) @@ -1101,15 +1107,26 @@ void ProjectionPlot::create_output() const { // Get centerline vector for camera-to-model. We create vectors around this // that form a pixel array, and then trace rays along that. + auto up = up_ / up_.norm(); Direction looking_direction = look_at_ - camera_position_; looking_direction /= looking_direction.norm(); + if (std::abs(std::abs(looking_direction.dot(up)) - 1.0) < 1e-9) + fatal_error("Up vector cannot align with vector between camera position " + "and look_at!"); + Direction cam_yaxis = looking_direction.cross(up); + cam_yaxis /= cam_yaxis.norm(); + Direction cam_zaxis = cam_yaxis.cross(looking_direction); + cam_zaxis /= cam_zaxis.norm(); + + // Transformation matrix for directions + std::vector camera_to_model = {looking_direction.x, cam_yaxis.x, + cam_zaxis.x, looking_direction.y, cam_yaxis.y, cam_zaxis.y, + looking_direction.z, cam_yaxis.z, cam_zaxis.z}; // Now we convert to the polar coordinate system with the polar angle // measuring the angle from the vector up_. Phi is the rotation about up_. For // now, up_ is hard-coded to be +z. constexpr double DEGREE_TO_RADIAN = M_PI / 180.0; - double phi0 = std::atan2(looking_direction.y, looking_direction.x); - double mu0 = std::acos(looking_direction.z); double horiz_fov_radians = horizontal_field_of_view_ * DEGREE_TO_RADIAN; double p0 = static_cast(pixels_[0]); double p1 = static_cast(pixels_[1]); @@ -1154,11 +1171,25 @@ void ProjectionPlot::create_output() const for (int vert = 0; vert < pixels_[1]; ++vert) { old_segments = this_line_segments; for (int horiz = 0; horiz < pixels_[0]; ++horiz) { - double this_phi = phi0 - horiz_fov_radians / 2.0 + dphi * horiz; - double this_mu = mu0 - vert_fov_radians / 2.0 + dmu * vert; - s.u.x = std::cos(this_phi) * std::sin(this_mu); - s.u.y = std::sin(this_phi) * std::sin(this_mu); - s.u.z = std::cos(this_mu); + + // Generate the starting position/direction of the ray + if (orthographic_width_ == 0.0) { // perspective projection + double this_phi = -horiz_fov_radians / 2.0 + dphi * horiz; + double this_mu = -vert_fov_radians / 2.0 + dmu * vert + M_PI / 2.0; + Direction camera_local_vec; + camera_local_vec.x = std::cos(this_phi) * std::sin(this_mu); + camera_local_vec.y = std::sin(this_phi) * std::sin(this_mu); + camera_local_vec.z = std::cos(this_mu); + s.u = camera_local_vec.rotate(camera_to_model); + } else { // orthographic projection + s.u = looking_direction; + + double x_pix_coord = (static_cast(horiz) - p0 / 2.0) / p0; + double y_pix_coord = (static_cast(vert) - p1 / 2.0) / p0; + s.r = camera_position_ + cam_yaxis * x_pix_coord * orthographic_width_ + + cam_zaxis * y_pix_coord * orthographic_width_; + } + p.from_source(&s); // put particle at camera bool hitsomething = false; bool intersection_found = true; @@ -1238,7 +1269,7 @@ void ProjectionPlot::create_output() const draw_wireframe || !trackstack_equivalent( this_line_segments[horiz], old_segments[horiz]); } - if (draw_wireframe) { + if (draw_wireframe && wireframe_) { data(horiz, vert) = wireframe_color_; } } @@ -1263,7 +1294,6 @@ void ProjectionPlot::print_info() const void ProjectionPlot::set_opacities(pugi::xml_node node) { - xs_.resize(colors_.size(), 1e6); // set to large value for opaque by default for (auto cn : node.children("color")) { @@ -1292,6 +1322,17 @@ void ProjectionPlot::set_opacities(pugi::xml_node node) } } +void ProjectionPlot::set_orthographic_width(pugi::xml_node node) +{ + if (check_for_node(node, "orthographic_width")) { + double orthographic_width = + std::stod(get_node_value(node, "orthographic_width", true)); + if (orthographic_width < 0.0) + fatal_error("Requires positive orthographic_width"); + orthographic_width_ = orthographic_width; + } +} + void ProjectionPlot::set_pixels(pugi::xml_node node) { vector pxls = get_node_array(node, "pixels"); From a030aaa59dd736d4a7304f622f223fcc81deff2d Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 16 Dec 2021 18:02:14 -0500 Subject: [PATCH 1716/2654] fix projection plot tests --- include/openmc/plot.h | 4 ++-- .../plot_projections/geometry.xml | 2 +- .../plot_projections/plots.xml | 24 ++++++++++++++++++- .../plot_projections/results_true.dat | 2 +- .../regression_tests/plot_projections/test.py | 2 +- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index c4476af41..7e85996de 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -312,8 +312,8 @@ private: Position camera_position_; // where camera is Position look_at_; // point camera is centered looking at Direction up_ {0.0, 0.0, 1.0}; // which way is up - bool wireframe_; // draw wireframe around ID boundaries (material or cell - // based on color_by) + bool wireframe_ {true}; // draw wireframe around ID boundaries (material or + // cell based on color_by) /* The horizontal thickness, if using an orthographic projection. * If set to zero, we assume using a perspective projection. diff --git a/tests/regression_tests/plot_projections/geometry.xml b/tests/regression_tests/plot_projections/geometry.xml index 982187644..a648dfe92 100644 --- a/tests/regression_tests/plot_projections/geometry.xml +++ b/tests/regression_tests/plot_projections/geometry.xml @@ -4,7 +4,7 @@ - + diff --git a/tests/regression_tests/plot_projections/plots.xml b/tests/regression_tests/plot_projections/plots.xml index 2d22c8865..b25f177b0 100644 --- a/tests/regression_tests/plot_projections/plots.xml +++ b/tests/regression_tests/plot_projections/plots.xml @@ -13,11 +13,12 @@ 0. 0. 0. - 20. 20. 20. + 10. 10. 0. 25 25 200 200 90 + example1 @@ -25,6 +26,27 @@ 20. 20. 20. 200 200 240 240 240 + example2.png + + + + 0. 0. 0. + 0. 10.0 20. + 200 200 + 110 240 240 + example3.png + + + + 0. 0. 0. + 10. 10. 10. + 25 25 + 200 200 + 25.0 + orthographic_example1 + + + diff --git a/tests/regression_tests/plot_projections/results_true.dat b/tests/regression_tests/plot_projections/results_true.dat index 45e097f62..004b752eb 100644 --- a/tests/regression_tests/plot_projections/results_true.dat +++ b/tests/regression_tests/plot_projections/results_true.dat @@ -1 +1 @@ -8231bc2d60bee9df464fbf3c5b2ea611dcd0f10232f6a9b04f58fc5226716acb31580578f74d194f8ab2df1848ea1556621bf997e1d1562d5eb8471def2a5f24 \ No newline at end of file +5fdff140078cd45efe7a507feeb06c00fa735820157a9a5a066905468b1052640c3b81065f968f6280c05eef7e9e4305a631e0e0aa2e467c9bd9d4f1a097ab09 \ No newline at end of file diff --git a/tests/regression_tests/plot_projections/test.py b/tests/regression_tests/plot_projections/test.py index 2e1f4cd8d..972e0e0d7 100644 --- a/tests/regression_tests/plot_projections/test.py +++ b/tests/regression_tests/plot_projections/test.py @@ -56,5 +56,5 @@ class PlotTestHarness(TestHarness): def test_plot(): - harness = PlotTestHarness(('projection1.png', 'projection2.png', 'projection3.png')) + harness = PlotTestHarness(('plot_1.png', 'example1.png', 'example3.png', 'orthographic_example1.png')) harness.main() From a832fc8b9408056830dd5f17d51b08003a21ac1d Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Fri, 17 Dec 2021 17:11:49 -0500 Subject: [PATCH 1717/2654] adjustable wireframe thickness --- include/openmc/plot.h | 6 ++++-- src/plot.cpp | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index 7e85996de..a58480c6b 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -288,6 +288,7 @@ private: void set_pixels(pugi::xml_node node); void set_opacities(pugi::xml_node node); void set_orthographic_width(pugi::xml_node node); + void set_wireframe_thickness(pugi::xml_node node); /* Used for drawing wireframe and colors. We record the list of * surface/cell/material intersections and the corresponding lengths as a ray @@ -312,14 +313,15 @@ private: Position camera_position_; // where camera is Position look_at_; // point camera is centered looking at Direction up_ {0.0, 0.0, 1.0}; // which way is up - bool wireframe_ {true}; // draw wireframe around ID boundaries (material or - // cell based on color_by) /* The horizontal thickness, if using an orthographic projection. * If set to zero, we assume using a perspective projection. */ double orthographic_width_ {0.0}; + // Thickness of the wireframe lines. Can set to zero for no wireframe. + int wireframe_thickness_ {1}; + RGBColor wireframe_color_ {BLACK}; // wireframe color std::vector xs_; // macro cross section values for cell volume rendering diff --git a/src/plot.cpp b/src/plot.cpp index 67e36c448..8e2816005 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1034,6 +1034,7 @@ ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) set_pixels(node); set_opacities(node); set_orthographic_width(node); + set_wireframe_thickness(node); if (check_for_node(node, "orthographic_width") && check_for_node(node, "field_of_view")) @@ -1138,6 +1139,11 @@ void ProjectionPlot::create_output() const size_t height = pixels_[1]; ImageData data({width, height}, not_found_); + // This array marks where the initial wireframe was drawn. + // We convolve it with a filter that gets adjusted with the + // wireframe thickness in order to thicken the lines. + xt::xtensor wireframe_initial({width, height}, 0); + // Loop over horizontal lines (vert field of view) SourceSite s; // Where particle starts from (camera) s.E = 1; @@ -1269,11 +1275,31 @@ void ProjectionPlot::create_output() const draw_wireframe || !trackstack_equivalent( this_line_segments[horiz], old_segments[horiz]); } - if (draw_wireframe && wireframe_) { - data(horiz, vert) = wireframe_color_; + if (draw_wireframe) { + wireframe_initial(horiz, vert) = 1; } } } + + // Now thicken the wireframe lines and apply them to our image + for (int vert = 0; vert < pixels_[1]; ++vert) { + for (int horiz = 0; horiz < pixels_[0]; ++horiz) { + if (wireframe_initial(horiz, vert)) { + if (wireframe_thickness_ == 1) + data(horiz, vert) = wireframe_color_; + for (int i = -wireframe_thickness_ / 2; i < wireframe_thickness_ / 2; + ++i) + for (int j = -wireframe_thickness_ / 2; j < wireframe_thickness_ / 2; + ++j) + if (i * i + j * j < wireframe_thickness_ * wireframe_thickness_) { + if (horiz + i >= 0 && horiz + i < pixels_[0] && vert + j >= 0 && + vert + j < pixels_[1]) + data(horiz + i, vert + j) = wireframe_color_; + } + } + } + } + #ifdef USE_LIBPNG output_png(path_plot(), data); #else @@ -1333,6 +1359,17 @@ void ProjectionPlot::set_orthographic_width(pugi::xml_node node) } } +void ProjectionPlot::set_wireframe_thickness(pugi::xml_node node) +{ + if (check_for_node(node, "wireframe_thickness")) { + int wireframe_thickness = + std::stoi(get_node_value(node, "wireframe_thickness", true)); + if (wireframe_thickness < 0) + fatal_error("Requires non-negative wireframe thickness"); + wireframe_thickness_ = wireframe_thickness; + } +} + void ProjectionPlot::set_pixels(pugi::xml_node node) { vector pxls = get_node_array(node, "pixels"); From c9e296d2a98c93bb6fdf169be8e25e52ed60e586 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Fri, 17 Dec 2021 17:12:55 -0500 Subject: [PATCH 1718/2654] update tests --- tests/regression_tests/plot_projections/plots.xml | 2 ++ tests/regression_tests/plot_projections/results_true.dat | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/plot_projections/plots.xml b/tests/regression_tests/plot_projections/plots.xml index b25f177b0..11fa27211 100644 --- a/tests/regression_tests/plot_projections/plots.xml +++ b/tests/regression_tests/plot_projections/plots.xml @@ -18,6 +18,7 @@ 200 200 90 + 4 example1 @@ -43,6 +44,7 @@ 25 25 200 200 25.0 + 2 orthographic_example1 diff --git a/tests/regression_tests/plot_projections/results_true.dat b/tests/regression_tests/plot_projections/results_true.dat index 004b752eb..638981dc7 100644 --- a/tests/regression_tests/plot_projections/results_true.dat +++ b/tests/regression_tests/plot_projections/results_true.dat @@ -1 +1 @@ -5fdff140078cd45efe7a507feeb06c00fa735820157a9a5a066905468b1052640c3b81065f968f6280c05eef7e9e4305a631e0e0aa2e467c9bd9d4f1a097ab09 \ No newline at end of file +96690b9e545d24b4e922aa30bffdd09863315e4a10301a5402c1b9f196a5ad67a1c8ac00231a1eeadb5d9c4f87cccd13bd86105765b002572acc4a33a32b070f \ No newline at end of file From 030c3af9e43cba25587510558f538738dde1757b Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 19 Dec 2021 01:10:51 -0500 Subject: [PATCH 1719/2654] parallelization of projection plots almost works except edge case --- include/openmc/plot.h | 7 -- src/plot.cpp | 279 +++++++++++++++++++++++++----------------- 2 files changed, 170 insertions(+), 116 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index a58480c6b..b076c0870 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -235,13 +235,6 @@ T SlicePlotBase::get_map() const return data; } -// Provides methods and data for controlling plot colors -class PlotColorMixin { -protected: - -public: -}; - // Represents either a voxel or pixel plot class Plot : public PlottableInterface, public SlicePlotBase { diff --git a/src/plot.cpp b/src/plot.cpp index 8e2816005..c2911f872 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1144,22 +1144,6 @@ void ProjectionPlot::create_output() const // wireframe thickness in order to thicken the lines. xt::xtensor wireframe_initial({width, height}, 0); - // Loop over horizontal lines (vert field of view) - SourceSite s; // Where particle starts from (camera) - s.E = 1; - s.wgt = 1; - s.delayed_group = 0; - s.particle = ParticleType::photon; // just has to be something reasonable - s.parent_id = 1; - s.progeny_id = 2; - s.r = camera_position_; - - Particle p; - s.u.x = 1.0; - s.u.y = 0.0; - s.u.z = 0.0; - p.from_source(&s); - /* Holds all of the track segments for the current rendered line of pixels. * old_segments holds a copy of this_line_segments from the previous line. * By holding both we can check if the cell/material intersection stack @@ -1171,115 +1155,192 @@ void ProjectionPlot::create_output() const * Note that a vector of vectors is required rather than a 2-tensor, * since the stack size varies within each column. */ - std::vector> this_line_segments(pixels_[0]); +#ifdef _OPENMP + const int n_threads = omp_get_max_threads(); +#else + const int n_threads = 1; +#endif + std::vector>> this_line_segments( + omp_get_max_threads()); + for (int t = 0; t < omp_get_max_threads(); ++t) { + this_line_segments[t].resize(pixels_[0]); + } + + // The last thread writes to this, and the first thread reads from it. std::vector> old_segments(pixels_[0]); - for (int vert = 0; vert < pixels_[1]; ++vert) { - old_segments = this_line_segments; - for (int horiz = 0; horiz < pixels_[0]; ++horiz) { +#pragma omp parallel + { - // Generate the starting position/direction of the ray - if (orthographic_width_ == 0.0) { // perspective projection - double this_phi = -horiz_fov_radians / 2.0 + dphi * horiz; - double this_mu = -vert_fov_radians / 2.0 + dmu * vert + M_PI / 2.0; - Direction camera_local_vec; - camera_local_vec.x = std::cos(this_phi) * std::sin(this_mu); - camera_local_vec.y = std::sin(this_phi) * std::sin(this_mu); - camera_local_vec.z = std::cos(this_mu); - s.u = camera_local_vec.rotate(camera_to_model); - } else { // orthographic projection - s.u = looking_direction; +#ifdef _OPENMP + const int n_threads = omp_get_max_threads(); + const int tid = omp_get_thread_num(); +#else + int n_threads = 1; + int tid = 0; +#endif - double x_pix_coord = (static_cast(horiz) - p0 / 2.0) / p0; - double y_pix_coord = (static_cast(vert) - p1 / 2.0) / p0; - s.r = camera_position_ + cam_yaxis * x_pix_coord * orthographic_width_ + - cam_zaxis * y_pix_coord * orthographic_width_; - } + SourceSite s; // Where particle starts from (camera) + s.E = 1; + s.wgt = 1; + s.delayed_group = 0; + s.particle = ParticleType::photon; // just has to be something reasonable + s.parent_id = 1; + s.progeny_id = 2; + s.r = camera_position_; - p.from_source(&s); // put particle at camera - bool hitsomething = false; - bool intersection_found = true; - int loop_counter = 0; - const int max_intersections = 1000000; + Particle p; + s.u.x = 1.0; + s.u.y = 0.0; + s.u.z = 0.0; + p.from_source(&s); - this_line_segments[horiz].clear(); - int first_surface = -1; // surface first passed when entering the model - bool first_inside_model = true; // false after entering the model - while (intersection_found) { - bool inside_cell = exhaustive_find_cell(p); - if (inside_cell) { + int vert = omp_get_thread_num(); + for (int iter = 0; iter <= pixels_[1] / n_threads; iter++) { + if (vert < pixels_[1]) { - // This allows drawing wireframes with surface intersection - // edges on the model boundary for the same cell. - if (first_inside_model) { - this_line_segments[horiz].emplace_back(0, 0.0, first_surface); - first_inside_model = false; + // Save bottom line of current work chunk to compare against later + if (tid == n_threads - 1) + old_segments = this_line_segments[n_threads - 1]; + + for (int horiz = 0; horiz < pixels_[0]; ++horiz) { + + // Generate the starting position/direction of the ray + if (orthographic_width_ == 0.0) { // perspective projection + double this_phi = -horiz_fov_radians / 2.0 + dphi * horiz; + double this_mu = -vert_fov_radians / 2.0 + dmu * vert + M_PI / 2.0; + Direction camera_local_vec; + camera_local_vec.x = std::cos(this_phi) * std::sin(this_mu); + camera_local_vec.y = std::sin(this_phi) * std::sin(this_mu); + camera_local_vec.z = std::cos(this_mu); + s.u = camera_local_vec.rotate(camera_to_model); + } else { // orthographic projection + s.u = looking_direction; + + double x_pix_coord = (static_cast(horiz) - p0 / 2.0) / p0; + double y_pix_coord = (static_cast(vert) - p1 / 2.0) / p0; + s.r = camera_position_ + + cam_yaxis * x_pix_coord * orthographic_width_ + + cam_zaxis * y_pix_coord * orthographic_width_; } - hitsomething = true; - intersection_found = true; - auto dist = distance_to_boundary(p); - this_line_segments[horiz].emplace_back( - color_by_ == PlotColorBy::mats ? p.material() - : p.coord(p.n_coord() - 1).cell, - dist.distance, dist.surface_index); + p.from_source(&s); // put particle at camera + bool hitsomething = false; + bool intersection_found = true; + int loop_counter = 0; + const int max_intersections = 1000000; - // Advance particle - for (int lev = 0; lev < p.n_coord(); ++lev) { - p.coord(lev).r += dist.distance * p.coord(lev).u; - } - p.surface() = dist.surface_index; - p.n_coord_last() = p.n_coord(); - p.n_coord() = dist.coord_level; - if (dist.lattice_translation[0] != 0 || - dist.lattice_translation[1] != 0 || - dist.lattice_translation[2] != 0) { - cross_lattice(p, dist); + this_line_segments[tid][horiz].clear(); + + int first_surface = + -1; // surface first passed when entering the model + bool first_inside_model = true; // false after entering the model + while (intersection_found) { + bool inside_cell = exhaustive_find_cell(p); + if (inside_cell) { + + // This allows drawing wireframes with surface intersection + // edges on the model boundary for the same cell. + if (first_inside_model) { + this_line_segments[tid][horiz].emplace_back( + 0, 0.0, first_surface); + first_inside_model = false; + } + + hitsomething = true; + intersection_found = true; + auto dist = distance_to_boundary(p); + this_line_segments[tid][horiz].emplace_back( + color_by_ == PlotColorBy::mats ? p.material() + : p.coord(p.n_coord() - 1).cell, + dist.distance, dist.surface_index); + + // Advance particle + for (int lev = 0; lev < p.n_coord(); ++lev) { + p.coord(lev).r += dist.distance * p.coord(lev).u; + } + p.surface() = dist.surface_index; + p.n_coord_last() = p.n_coord(); + p.n_coord() = dist.coord_level; + if (dist.lattice_translation[0] != 0 || + dist.lattice_translation[1] != 0 || + dist.lattice_translation[2] != 0) { + cross_lattice(p, dist); + } + + } else { + first_surface = advance_to_boundary_from_void(p); + intersection_found = + first_surface != -1; // -1 if no surface found + } + loop_counter++; + if (loop_counter > max_intersections) + fatal_error("Infinite loop in projection plot"); } - } else { - first_surface = advance_to_boundary_from_void(p); - intersection_found = first_surface != -1; // -1 if no surface found + // Now color the pixel based on what we have intersected... + // Loops backwards over intersections. + Position current_color( + not_found_.red, not_found_.green, not_found_.blue); + const auto& segments = this_line_segments[tid][horiz]; + for (unsigned i = segments.size(); i-- > 0;) { + int colormap_idx = segments[i].id; + RGBColor seg_color = colors_[colormap_idx]; + Position seg_color_vec( + seg_color.red, seg_color.green, seg_color.blue); + double mixing = std::exp(-xs_[colormap_idx] * segments[i].length); + current_color = + current_color * mixing + (1.0 - mixing) * seg_color_vec; + RGBColor result; + result.red = static_cast(current_color.x); + result.green = static_cast(current_color.y); + result.blue = static_cast(current_color.z); + data(horiz, vert) = result; + } + + // Check to draw wireframe in horizontal direction. No inter-thread + // comm. + if (horiz > 0) { + if (!trackstack_equivalent(this_line_segments[tid][horiz], + this_line_segments[tid][horiz - 1])) { + wireframe_initial(horiz, vert) = 1; + } + } + } + } // end "if" vert in correct range + + // We require a barrier before comparing vertical neighbors' intersection + // stacks. i.e. all threads must be done with their line. +#pragma omp barrier + + // Now that the horizontal line has finished rendering, we can fill in + // wireframe entries that require comparison among all the threads. Hence + // the omp barrier being used. It has to be OUTSIDE any if blocks! + if (vert < pixels_[1]) { + // Loop over horizontal pixels, checking intersection stack of upper + // neighbor + + const std::vector>* top_cmp = nullptr; + if (tid == 0) + top_cmp = &old_segments; + else + top_cmp = &this_line_segments[tid - 1]; + + for (int horiz = 0; horiz < pixels_[0]; ++horiz) { + if (!trackstack_equivalent( + this_line_segments[tid][horiz], (*top_cmp)[horiz])) { + wireframe_initial(horiz, vert) = 1; + } } - loop_counter++; - if (loop_counter > max_intersections) - fatal_error("Infinite loop in projection plot"); } - // Now color the pixel based on what we have intersected... - // Loops backwards over intersections. - Position current_color(not_found_.red, not_found_.green, not_found_.blue); - const auto& segments = this_line_segments[horiz]; - for (unsigned i = segments.size(); i-- > 0;) { - int colormap_idx = segments[i].id; - RGBColor seg_color = colors_[colormap_idx]; - Position seg_color_vec(seg_color.red, seg_color.green, seg_color.blue); - double mixing = std::exp(-xs_[colormap_idx] * segments[i].length); - current_color = current_color * mixing + (1.0 - mixing) * seg_color_vec; - RGBColor result; - result.red = static_cast(current_color.x); - result.green = static_cast(current_color.y); - result.blue = static_cast(current_color.z); - data(horiz, vert) = result; - } - - // Check to draw wireframe - bool draw_wireframe = false; - if (horiz > 0) { - draw_wireframe = - draw_wireframe || !trackstack_equivalent(this_line_segments[horiz], - this_line_segments[horiz - 1]); - } - if (vert > 0) { - draw_wireframe = - draw_wireframe || !trackstack_equivalent( - this_line_segments[horiz], old_segments[horiz]); - } - if (draw_wireframe) { - wireframe_initial(horiz, vert) = 1; - } + // We need another barrier to ensure threads don't proceed to modify their + // intersection stacks on that horizontal line while others are + // potentially still working on the above. +#pragma omp barrier + vert += n_threads; } - } + } // end omp parallel // Now thicken the wireframe lines and apply them to our image for (int vert = 0; vert < pixels_[1]; ++vert) { From a0401906cd5c94d6668c902ec8a8447528f478cc Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 19 Dec 2021 01:21:01 -0500 Subject: [PATCH 1720/2654] parallel projection plotting now matches single thread results --- src/plot.cpp | 12 ++++++++---- .../plot_projections/results_true.dat | 2 +- tests/regression_tests/plot_projections/test.py | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/plot.cpp b/src/plot.cpp index c2911f872..f7d1224f2 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1197,11 +1197,15 @@ void ProjectionPlot::create_output() const int vert = omp_get_thread_num(); for (int iter = 0; iter <= pixels_[1] / n_threads; iter++) { - if (vert < pixels_[1]) { - // Save bottom line of current work chunk to compare against later - if (tid == n_threads - 1) - old_segments = this_line_segments[n_threads - 1]; + // Save bottom line of current work chunk to compare against later + // I used to have this inside the below if block, but it causes a + // spurious line to be drawn at the bottom of the image. Not sure + // why, but moving it here fixes things. + if (tid == n_threads - 1) + old_segments = this_line_segments[n_threads - 1]; + + if (vert < pixels_[1]) { for (int horiz = 0; horiz < pixels_[0]; ++horiz) { diff --git a/tests/regression_tests/plot_projections/results_true.dat b/tests/regression_tests/plot_projections/results_true.dat index 638981dc7..7f41f6a40 100644 --- a/tests/regression_tests/plot_projections/results_true.dat +++ b/tests/regression_tests/plot_projections/results_true.dat @@ -1 +1 @@ -96690b9e545d24b4e922aa30bffdd09863315e4a10301a5402c1b9f196a5ad67a1c8ac00231a1eeadb5d9c4f87cccd13bd86105765b002572acc4a33a32b070f \ No newline at end of file +186d646c4959755bf809d35c9f33a931fbd5195145131ae6764955bf276d44acf24970dfff76001106b93a7ce239d67d569440136b13073082c8ee23419d721e \ No newline at end of file diff --git a/tests/regression_tests/plot_projections/test.py b/tests/regression_tests/plot_projections/test.py index 972e0e0d7..c390a06ab 100644 --- a/tests/regression_tests/plot_projections/test.py +++ b/tests/regression_tests/plot_projections/test.py @@ -56,5 +56,5 @@ class PlotTestHarness(TestHarness): def test_plot(): - harness = PlotTestHarness(('plot_1.png', 'example1.png', 'example3.png', 'orthographic_example1.png')) + harness = PlotTestHarness(('plot_1.png', 'example1.png', 'example2.png', 'example3.png', 'orthographic_example1.png')) harness.main() From 31174736e97d110f628d9e8c982ef85b657672a3 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 19 Dec 2021 01:27:29 -0500 Subject: [PATCH 1721/2654] fix for non-OMP compile --- src/plot.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plot.cpp b/src/plot.cpp index f7d1224f2..2e849c907 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1161,8 +1161,8 @@ void ProjectionPlot::create_output() const const int n_threads = 1; #endif std::vector>> this_line_segments( - omp_get_max_threads()); - for (int t = 0; t < omp_get_max_threads(); ++t) { + n_threads); + for (int t = 0; t < n_threads; ++t) { this_line_segments[t].resize(pixels_[0]); } @@ -1195,7 +1195,7 @@ void ProjectionPlot::create_output() const s.u.z = 0.0; p.from_source(&s); - int vert = omp_get_thread_num(); + int vert = tid; for (int iter = 0; iter <= pixels_[1] / n_threads; iter++) { // Save bottom line of current work chunk to compare against later From 6726cc378f3025a9cd1c7dfe4245e245188204fd Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 9 Jan 2022 01:54:38 -0500 Subject: [PATCH 1722/2654] add unit test, select wireframing by id --- include/openmc/plot.h | 8 +- openmc/plots.py | 513 +++++++++++++++++++++++++-------- src/plot.cpp | 89 +++++- tests/unit_tests/test_plots.py | 52 +++- 4 files changed, 530 insertions(+), 132 deletions(-) diff --git a/include/openmc/plot.h b/include/openmc/plot.h index b076c0870..b09727835 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -282,6 +282,8 @@ private: void set_opacities(pugi::xml_node node); void set_orthographic_width(pugi::xml_node node); void set_wireframe_thickness(pugi::xml_node node); + void set_wireframe_ids(pugi::xml_node node); + void set_wireframe_color(pugi::xml_node node); /* Used for drawing wireframe and colors. We record the list of * surface/cell/material intersections and the corresponding lengths as a ray @@ -306,6 +308,8 @@ private: Position camera_position_; // where camera is Position look_at_; // point camera is centered looking at Direction up_ {0.0, 0.0, 1.0}; // which way is up + std::vector + wireframe_ids_; // which color IDs should be wireframed. If empty, all /* The horizontal thickness, if using an orthographic projection. * If set to zero, we assume using a perspective projection. @@ -329,8 +333,8 @@ private: * to mean not having matching intersection lengths, but rather having * a matching sequence of surface/cell/material intersections. */ - static bool trackstack_equivalent(const std::vector& track1, - const std::vector& track2); + bool trackstack_equivalent(const std::vector& track1, + const std::vector& track2) const; // Closed form 3x3 matrix inversion static std::vector invert_matrix(const std::vector& input); diff --git a/openmc/plots.py b/openmc/plots.py index 4b7d58e3b..7b67fee2c 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -178,14 +178,8 @@ def _get_plot_image(plot, cwd): return Image(str(png_file)) -class Plot(IDManagerMixin): - """Definition of a finite region of space to be plotted. - - OpenMC is capable of generating two-dimensional slice plots and - three-dimensional voxel plots. Colors that are used in plots can be given as - RGB tuples, e.g. (255, 255, 255) would be white, or by a string indicating a - valid `SVG color `_. - +class PlotBase(IDManagerMixin): + """ Parameters ---------- plot_id : int @@ -199,20 +193,12 @@ class Plot(IDManagerMixin): Unique identifier name : str Name of the plot - width : Iterable of float - Width of the plot in each basis direction pixels : Iterable of int Number of pixels to use in each basis direction - origin : tuple or list of ndarray - Origin (center) of the plot filename : Path to write the plot to color_by : {'cell', 'material'} Indicate whether the plot should be colored by cell or by material - type : {'slice', 'voxel'} - The type of the plot - basis : {'xy', 'xz', 'yz'} - The basis directions for the plot background : Iterable of int or str Color of the background mask_components : Iterable of openmc.Cell or openmc.Material or int @@ -230,10 +216,6 @@ class Plot(IDManagerMixin): cell/material). level : int Universe depth to plot at - meshlines : dict - Dictionary defining type, id, linewidth and color of a mesh to be - plotted on top of a plot - """ next_id = 1 @@ -243,13 +225,9 @@ class Plot(IDManagerMixin): # Initialize Plot class attributes self.id = plot_id self.name = name - self._width = [4.0, 4.0] self._pixels = [400, 400] - self._origin = [0., 0., 0.] self._filename = None self._color_by = 'cell' - self._type = 'slice' - self._basis = 'xy' self._background = None self._mask_components = None self._mask_background = None @@ -257,24 +235,15 @@ class Plot(IDManagerMixin): self._overlap_color = None self._colors = {} self._level = None - self._meshlines = None @property def name(self): return self._name - @property - def width(self): - return self._width - @property def pixels(self): return self._pixels - @property - def origin(self): - return self._origin - @property def filename(self): return self._filename @@ -283,14 +252,6 @@ class Plot(IDManagerMixin): def color_by(self): return self._color_by - @property - def type(self): - return self._type - - @property - def basis(self): - return self._basis - @property def background(self): return self._background @@ -319,27 +280,11 @@ class Plot(IDManagerMixin): def level(self): return self._level - @property - def meshlines(self): - return self._meshlines - @name.setter def name(self, name): cv.check_type('plot name', name, str) self._name = name - @width.setter - def width(self, width): - cv.check_type('plot width', width, Iterable, Real) - cv.check_length('plot width', width, 2, 3) - self._width = width - - @origin.setter - def origin(self, origin): - cv.check_type('plot origin', origin, Iterable, Real) - cv.check_length('plot origin', origin, 3) - self._origin = origin - @pixels.setter def pixels(self, pixels): cv.check_type('plot pixels', pixels, Iterable, Integral) @@ -358,16 +303,6 @@ class Plot(IDManagerMixin): cv.check_value('plot color_by', color_by, ['cell', 'material']) self._color_by = color_by - @type.setter - def type(self, plottype): - cv.check_value('plot type', plottype, ['slice', 'voxel']) - self._type = plottype - - @basis.setter - def basis(self, basis): - cv.check_value('plot basis', basis, _BASES) - self._basis = basis - @background.setter def background(self, background): self._check_color('plot background', background) @@ -410,6 +345,132 @@ class Plot(IDManagerMixin): cv.check_greater_than('plot level', plot_level, 0, equality=True) self._level = plot_level + @staticmethod + def _check_color(err_string, color): + cv.check_type(err_string, color, Iterable) + if isinstance(color, str): + if color.lower() not in _SVG_COLORS: + raise ValueError(f"'{color}' is not a valid color.") + else: + cv.check_length(err_string, color, 3) + for rgb in color: + cv.check_type(err_string, rgb, Real) + cv.check_greater_than('RGB component', rgb, 0, True) + cv.check_less_than('RGB component', rgb, 256) + + def colorize(self, geometry, seed=1): + """Generate a color scheme for each domain in the plot. + + This routine may be used to generate random, reproducible color schemes. + The colors generated are based upon cell/material IDs in the geometry. + + Parameters + ---------- + geometry : openmc.Geometry + The geometry for which the plot is defined + seed : Integral + The random number seed used to generate the color scheme + + """ + + cv.check_type('geometry', geometry, openmc.Geometry) + cv.check_type('seed', seed, Integral) + cv.check_greater_than('seed', seed, 1, equality=True) + + # Get collections of the domains which will be plotted + if self.color_by == 'material': + domains = geometry.get_all_materials().values() + else: + domains = geometry.get_all_cells().values() + + # Set the seed for the random number generator + np.random.seed(seed) + + # Generate random colors for each feature + for domain in domains: + self.colors[domain] = np.random.randint(0, 256, (3,)) + +class Plot(PlotBase): + '''Definition of a finite region of space to be plotted. + + OpenMC is capable of generating two-dimensional slice plots, or + three-dimensional voxel or projection plots. Colors that are used in plots can be given as + RGB tuples, e.g. (255, 255, 255) would be white, or by a string indicating a + valid `SVG color `_. + + Parameters + ---------- + plot_id : int + Unique identifier for the plot + name : str + Name of the plot + + Attributes + ---------- + width : Iterable of float + Width of the plot in each basis direction + origin : tuple or list of ndarray + Origin (center) of the plot + type : {'slice', 'voxel'} + The type of the plot + basis : {'xy', 'xz', 'yz'} + The basis directions for the plot + meshlines : dict + Dictionary defining type, id, linewidth and color of a mesh to be + plotted on top of a plot + + ''' + def __init__(self, plot_id=None, name=''): + super().__init__(plot_id, name) + self._width = [4.0, 4.0] + self._origin = [0., 0., 0.] + self._type = 'slice' + self._basis = 'xy' + self._meshlines = None + + @property + def width(self): + return self._width + + @property + def origin(self): + return self._origin + + @property + def type(self): + return self._type + + @property + def basis(self): + return self._basis + + @property + def meshlines(self): + return self._meshlines + + @width.setter + def width(self, width): + cv.check_type('plot width', width, Iterable, Real) + cv.check_length('plot width', width, 2, 3) + self._width = width + + @origin.setter + def origin(self, origin): + cv.check_type('plot origin', origin, Iterable, Real) + cv.check_length('plot origin', origin, 3) + self._origin = origin + + @type.setter + def type(self, plottype): + cv.check_value('plot type', plottype, ['slice', 'voxel']) + self._type = plottype + + @basis.setter + def basis(self, basis): + cv.check_value('plot basis', basis, _BASES) + self._basis = basis + + @meshlines.setter def meshlines(self, meshlines): cv.check_type('plot meshlines', meshlines, dict) @@ -438,19 +499,6 @@ class Plot(IDManagerMixin): self._meshlines = meshlines - @staticmethod - def _check_color(err_string, color): - cv.check_type(err_string, color, Iterable) - if isinstance(color, str): - if color.lower() not in _SVG_COLORS: - raise ValueError(f"'{color}' is not a valid color.") - else: - cv.check_length(err_string, color, 3) - for rgb in color: - cv.check_type(err_string, rgb, Real) - cv.check_greater_than('RGB component', rgb, 0, True) - cv.check_less_than('RGB component', rgb, 256) - def __repr__(self): string = 'Plot\n' string += '{: <16}=\t{}\n'.format('\tID', self._id) @@ -474,6 +522,7 @@ class Plot(IDManagerMixin): string += '{: <16}=\t{}\n'.format('\tMeshlines', self._meshlines) return string + @classmethod def from_geometry(cls, geometry, basis='xy', slice_coord=0.): """Return plot that encompasses a geometry. @@ -520,38 +569,6 @@ class Plot(IDManagerMixin): plot.basis = basis return plot - def colorize(self, geometry, seed=1): - """Generate a color scheme for each domain in the plot. - - This routine may be used to generate random, reproducible color schemes. - The colors generated are based upon cell/material IDs in the geometry. - - Parameters - ---------- - geometry : openmc.Geometry - The geometry for which the plot is defined - seed : Integral - The random number seed used to generate the color scheme - - """ - - cv.check_type('geometry', geometry, openmc.Geometry) - cv.check_type('seed', seed, Integral) - cv.check_greater_than('seed', seed, 1, equality=True) - - # Get collections of the domains which will be plotted - if self.color_by == 'material': - domains = geometry.get_all_materials().values() - else: - domains = geometry.get_all_cells().values() - - # Set the seed for the random number generator - np.random.seed(seed) - - # Generate random colors for each feature - for domain in domains: - self.colors[domain] = np.random.randint(0, 256, (3,)) - def highlight_domains(self, geometry, domains, seed=1, alpha=0.5, background='gray'): """Use alpha compositing to highlight one or more domains in the plot. @@ -604,7 +621,7 @@ class Plot(IDManagerMixin): self._colors[domain] = (r, g, b) def to_xml_element(self): - """Return XML representation of the plot + """Return XML representation of the slice/voxel plot Returns ------- @@ -802,13 +819,271 @@ class Plot(IDManagerMixin): # Return produced image return _get_plot_image(self, cwd) +class ProjectionPlot(PlotBase): + """Definition of a camera's view of OpenMC geometry + + Colors are defined in the same manner as the Plot class, but with the addition + of a coloring parameter resembling a macroscopic cross section in units of inverse + centimeters. The volume rendering technique is used to color regions of the model. + An infinite cross section denotes a fully opaque region, and zero represents a + transparent region which will expose the color of the regions behind it. + + The camera projection may either by orthographic or perspective. Perspective + projections are more similar to a pinhole camera, and orthographic projections + preserve parallel lines and distances. + + Parameters + ---------- + plot_id : int + Unique identifier for the plot + name : str + Name of the plot + + Attributes + ---------- + horizontal_field_of_view : float + Field of view horizontally, in units of degrees. + camera_position : tuple or list of ndarray + Position of the camera in 3D space + look_at : tuple or list of ndarray + The center of the camera's image points to this place in 3D space + up : tuple or list of ndarray + Which way is up for the camera. Must not be parallel to the + line between look_at and camera_position + orthographic_width : float + If set to a nonzero value, an orthographic projection is used. + All rays traced from the orthographic pixel array travel in the + same direction. The width of the starting array must be specified, + unlike with the default perspective projection. The height of the + array is deduced from the ratio of pixel dimensions for the image. + + wireframe_thickness : int + Line thickness employed for drawing wireframes around cells or + material regions. Can be set to zero for no wireframes + wireframe_color : tuple of ints + RGB color of the wireframe lines + wireframe_regions : iterable of either Material or Cells + If provided, the wireframe is only drawn around these. + If color_by is by material, it must be a list of materials, else cells. + + xs : dict + A mapping from cell/material IDs to floats. The floating point values + are macroscopic cross sections influencing the volume rendering opacity + of each geometric region. Zero corresponds to perfect transparency, and + infinity equivalent to opaque. + """ + + def __init__(self, plot_id=None, name=''): + # Initialize Plot class attributes + super().__init__(plot_id, name) + self._horizontal_field_of_view = 70.0 + self._camera_position = (1.0, 0.0, 0.0) + self._look_at = (0.0, 0.0, 0.0) + self._up = (0.0, 0.0, 1.0) + self._orthographic_width = 0.0 + self._wireframe_thickness = 1 + self._wireframe_color = _SVG_COLORS['black'] + self._wireframe_regions = [] + self._xs = {} + + @property + def horizontal_field_of_view(self): + return self._horizontal_field_of_view + + @property + def camera_position(self): + return self._camera_position + + @property + def look_at(self): + return self._look_at + + @property + def up(self): + return self._up + + @property + def orthographic_width(self): + return self._orthographic_width + + @property + def wireframe_thickness(self): + return self._wireframe_thickness + + @property + def wireframe_color(self): + return self._wireframe_color + + @property + def wireframe_regions(self): + return self._wireframe_regions + + @property + def xs(self): + return self._xs + + @horizontal_field_of_view.setter + def horizontal_field_of_view(self, horizontal_field_of_view): + cv.check_type('plot horizontal field of view', horizontal_field_of_view, + Real) + assert horizontal_field_of_view > 0.0 + assert horizontal_field_of_view < 180.0 + self._horizontal_field_of_view = horizontal_field_of_view + + @camera_position.setter + def camera_position(self, camera_position): + cv.check_type('plot camera position', camera_position, Iterable, Real) + cv.check_length('plot camera position', camera_position, 3) + self._camera_position = camera_position + + @look_at.setter + def look_at(self, look_at): + cv.check_type('plot look at', look_at, Iterable, Real) + cv.check_length('plot look at', look_at, 3) + self._look_at = look_at + + @up.setter + def up(self, up): + cv.check_type('plot up', up, Iterable, Real) + cv.check_length('plot up', up, 3) + self._up = up + + @orthographic_width.setter + def orthographic_width(self, orthographic_width): + cv.check_type('plot orthographic width', orthographic_width, Real) + self._orthographic_width = orthographic_width + + @wireframe_thickness.setter + def wireframe_thickness(self, wireframe_thickness): + cv.check_type('plot orthographic width', wireframe_thickness, Integral) + assert wireframe_thickness >= 0 + self._wireframe_thickness = wireframe_thickness + + @wireframe_color.setter + def wireframe_color(self, wireframe_color): + self._check_color('plot wireframe color', wireframe_color) + self._wireframe_color = wireframe_color + + @wireframe_regions.setter + def wireframe_regions(self, wireframe_regions): + for region in wireframe_regions: + if self._color_by == 'material': + if not isinstance(region, openmc.Material): + raise Exception('Must provide a list of materials for \ + wireframe_region if color_by=Material') + else: + if not isinstance(region, openmc.Cell): + raise Exception('Must provide a list of cells for \ + wireframe_region if color_by=cell') + self._wireframe_regions = wireframe_regions + + @xs.setter + def xs(self, xs): + cv.check_type('plot xs', xs, Mapping) + for key, value in xs.items(): + cv.check_type('plot xs key', key, (openmc.Cell, openmc.Material)) + cv.check_type('plot xs value', value, Real) + assert value >= 0.0 + self._xs = xs + + def set_transparent(self, geometry): + """Sets all volume rendering XS to zero for the model + + Parameters + ---------- + geometry : openmc.Geometry + The geometry for which the plot is defined + """ + + cv.check_type('geometry', geometry, openmc.Geometry) + + # Get collections of the domains which will be plotted + if self.color_by == 'material': + domains = geometry.get_all_materials().values() + else: + domains = geometry.get_all_cells().values() + + # Generate random colors for each feature + for domain in domains: + self.xs[domain] = 0.0 + + def to_xml_element(self): + """Return XML representation of the projection plot + + Returns + ------- + element : xml.etree.ElementTree.Element + XML element containing plot data + + """ + + element = ET.Element("plot") + element.set("id", str(self._id)) + if self._filename is not None: + element.set("filename", self._filename) + element.set("color_by", self._color_by) + element.set("type", "projection") + + subelement = ET.SubElement(element, "pixels") + subelement.text = ' '.join(map(str, self._pixels)) + + subelement = ET.SubElement(element, "camera_position") + subelement.text = ' '.join(map(str, self._camera_position)) + + subelement = ET.SubElement(element, "look_at") + subelement.text = ' '.join(map(str, self._look_at)) + + subelement = ET.SubElement(element, "wireframe_thickness") + subelement.text = str(self._wireframe_thickness) + + subelement = ET.SubElement(element, "wireframe_color") + color = self._wireframe_color + if isinstance(color, str): + color = _SVG_COLORS[color.lower()] + subelement.text = ' '.join(str(x) for x in color) + + if self._wireframe_regions: + id_list = [x.id for x in self._wireframe_regions] + subelement = ET.SubElement(element, "wireframe_ids") + subelement.text = ' '.join([str(x) for x in id_list]) + + if self._background is not None: + subelement = ET.SubElement(element, "background") + color = self._background + if isinstance(color, str): + color = _SVG_COLORS[color.lower()] + subelement.text = ' '.join(str(x) for x in color) + + if self._mask_components is not None: + subelement = ET.SubElement(element, "mask") + subelement.set("components", ' '.join( + str(d.id) for d in self._mask_components)) + color = self._mask_background + if color is not None: + if isinstance(color, str): + color = _SVG_COLORS[color.lower()] + subelement.set("background", ' '.join( + str(x) for x in color)) + + if self._colors: + for domain, color in sorted(self._colors.items(), + key=lambda x: x[0].id): + subelement = ET.SubElement(element, "color") + subelement.set("id", str(domain.id)) + if isinstance(color, str): + color = _SVG_COLORS[color.lower()] + subelement.set("rgb", ' '.join(str(x) for x in color)) + subelement.set("xs", str(self._xs[domain])) + + return element class Plots(cv.CheckedList): """Collection of Plots used for an OpenMC simulation. This class corresponds directly to the plots.xml input file. It can be - thought of as a normal Python list where each member is a :class:`Plot`. It - behaves like a list as the following example demonstrates: + thought of as a normal Python list where each member is inherits from + :class:`PlotBase`. It behaves like a list as the following example + demonstrates: >>> xz_plot = openmc.Plot() >>> big_plot = openmc.Plot() @@ -819,13 +1094,13 @@ class Plots(cv.CheckedList): Parameters ---------- - plots : Iterable of openmc.Plot - Plots to add to the collection + plots : Iterable of openmc.Plot or openmc.ProjectionPlot + plots to add to the collection """ def __init__(self, plots=None): - super().__init__(Plot, 'plots collection') + super().__init__((Plot, ProjectionPlot), 'plots collection') self._plots_file = ET.Element("plots") if plots is not None: self += plots @@ -835,7 +1110,7 @@ class Plots(cv.CheckedList): Parameters ---------- - plot : openmc.Plot + plot : openmc.Plot or openmc.ProjectionPlot Plot to append """ diff --git a/src/plot.cpp b/src/plot.cpp index 2e849c907..285f7f5a7 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1035,6 +1035,8 @@ ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) set_opacities(node); set_orthographic_width(node); set_wireframe_thickness(node); + set_wireframe_ids(node); + set_wireframe_color(node); if (check_for_node(node, "orthographic_width") && check_for_node(node, "field_of_view")) @@ -1042,6 +1044,19 @@ ProjectionPlot::ProjectionPlot(pugi::xml_node node) : PlottableInterface(node) "parameters."); } +void ProjectionPlot::set_wireframe_color(pugi::xml_node plot_node) +{ + // Copy plot background color + if (check_for_node(plot_node, "wireframe_color")) { + vector w_rgb = get_node_array(plot_node, "wireframe_color"); + if (w_rgb.size() == 3) { + wireframe_color_ = w_rgb; + } else { + fatal_error(fmt::format("Bad wireframe RGB in plot {}", id())); + } + } +} + void ProjectionPlot::set_output_path(pugi::xml_node node) { // Set output file path @@ -1091,17 +1106,55 @@ int ProjectionPlot::advance_to_boundary_from_void(Particle& p) bool ProjectionPlot::trackstack_equivalent( const std::vector& track1, - const std::vector& track2) + const std::vector& track2) const { - if (track1.size() != track2.size()) - return false; - for (int i = 0; i < track1.size(); ++i) { - if (track1[i].id != track2[i].id || - track1[i].surface != track2[i].surface) { - return false; + if (wireframe_ids_.empty()) { + // TODO old version + return true; + } else { + // This runs in O(nm) where n is the intersection stack size + // and m is the number of IDs we are wireframing. A simpler + // algorithm can likely be found. + for (const int id : wireframe_ids_) { + int t1_i = 0; + int t2_i = 0; + + // Advance to first instance of the ID + while (t1_i < track1.size() && t2_i < track2.size()) { + while (t1_i < track1.size() && track1[t1_i].id != id) + t1_i++; + while (t2_i < track2.size() && track2[t2_i].id != id) + t2_i++; + + // This one is really important! + if ((t1_i == track1.size() && t2_i != track2.size()) || + (t1_i != track1.size() && t2_i == track2.size())) + return false; + if (t1_i == track1.size() && t2_i == track2.size()) + break; + // Check if surface different + if (track1[t1_i].surface != track2[t2_i].surface) + return false; + + // Pretty sure this should not be used: + // if (t2_i != track2.size() - 1 && + // t1_i != track1.size() - 1 && + // track1[t1_i+1].id != track2[t2_i+1].id) return false; + if (t2_i != 0 && t1_i != 0 && + track1[t1_i - 1].surface != track2[t2_i - 1].surface) + return false; + + // Check if neighboring cells are different + // if (track1[t1_i ? t1_i - 1 : 0].id != track2[t2_i ? t2_i - 1 : 0].id) + // return false; if (track1[t1_i < track1.size() - 1 ? t1_i + 1 : t1_i + // ].id != + // track2[t2_i < track2.size() - 1 ? t2_i + 1 : t2_i].id) return + // false; + t1_i++, t2_i++; + } } + return true; } - return true; } void ProjectionPlot::create_output() const @@ -1247,7 +1300,10 @@ void ProjectionPlot::create_output() const // edges on the model boundary for the same cell. if (first_inside_model) { this_line_segments[tid][horiz].emplace_back( - 0, 0.0, first_surface); + color_by_ == PlotColorBy::mats + ? p.material() + : p.coord(p.n_coord() - 1).cell, + 0.0, first_surface); first_inside_model = false; } @@ -1435,6 +1491,21 @@ void ProjectionPlot::set_wireframe_thickness(pugi::xml_node node) } } +void ProjectionPlot::set_wireframe_ids(pugi::xml_node node) +{ + if (check_for_node(node, "wireframe_ids")) { + wireframe_ids_ = get_node_array(node, "wireframe_ids"); + // It is read in as actual ID values, but we have to convert to indices in + // mat/cell array + for (auto& x : wireframe_ids_) + x = color_by_ == PlotColorBy::mats ? model::material_map[x] + : model::cell_map[x]; + } + // We make sure the list is sorted in order to later use + // std::binary_search. + std::sort(wireframe_ids_.begin(), wireframe_ids_.end()); +} + void ProjectionPlot::set_pixels(pugi::xml_node node) { vector pxls = get_node_array(node, "pixels"); diff --git a/tests/unit_tests/test_plots.py b/tests/unit_tests/test_plots.py index 2db396cd5..183341c26 100644 --- a/tests/unit_tests/test_plots.py +++ b/tests/unit_tests/test_plots.py @@ -37,15 +37,47 @@ def myplot(): } return plot +@pytest.fixture(scope='module') +def myprojectionplot(): + plot = openmc.ProjectionPlot(name='myprojectionplot') + plot.look_at = (0.0, 0.0, 0.0) + plot.camera_position = (4.0, 3.0, 0.0) + plot.pixels = (500, 500) + plot.filename = 'myprojectionplot' + plot.background = (0, 0, 0) + plot.background = 'black' + + plot.color_by = 'material' + m1, m2 = openmc.Material(), openmc.Material() + plot.colors = {m1: (0, 255, 0), m2: (0, 0, 255)} + plot.colors = {m1: 'green', m2: 'blue'} + plot.xs = {m1: 1.0, m2: 0.01} + + plot.mask_components = [openmc.Material()] + plot.mask_background = (255, 255, 255) + plot.mask_background = 'white' + + plot.overlap_color = (255, 211, 0) + plot.overlap_color = 'yellow' + + plot.wireframe_thickness = 2 + + plot.level = 1 + return plot def test_attributes(myplot): assert myplot.name == 'myplot' +def test_attributes_proj(myprojectionplot): + assert myprojectionplot.name == 'myprojectionplot' def test_repr(myplot): r = repr(myplot) assert isinstance(r, str) +def test_repr_proj(myprojectionplot): + r = repr(myprojectionplot) + assert isinstance(r, str) def test_from_geometry(): width = 25. @@ -89,6 +121,18 @@ def test_xml_element(myplot): assert getattr(newplot, attr) == getattr(myplot, attr), attr +def test_to_xml_element_proj(myprojectionplot): + elem = myprojectionplot.to_xml_element() + assert 'id' in elem.attrib + assert 'color_by' in elem.attrib + assert 'type' in elem.attrib + assert elem.find('camera_position') is not None + assert elem.find('wireframe_thickness') is not None + assert elem.find('look_at') is not None + assert elem.find('pixels') is not None + assert elem.find('background').text == '0 0 0' + + def test_plots(run_in_tmpdir): p1 = openmc.Plot(name='plot1') p1.origin = (5., 5., 5.) @@ -99,10 +143,14 @@ def test_plots(run_in_tmpdir): plots = openmc.Plots([p1, p2]) assert len(plots) == 2 - p3 = openmc.Plot(name='plot3') - plots.append(p3) + p3 = openmc.ProjectionPlot(name='plot3') + plots = openmc.Plots([p1, p2, p3]) assert len(plots) == 3 + p4 = openmc.Plot(name='plot4') + plots.append(p4) + assert len(plots) == 4 + plots.export_to_xml() # from_xml From ed5837202b7c0a69f051e7c4b35375093e21a421 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 9 Jan 2022 17:08:34 -0500 Subject: [PATCH 1723/2654] add old wireframing behavior if not listing ids --- src/plot.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/plot.cpp b/src/plot.cpp index 285f7f5a7..73dd43533 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1109,7 +1109,15 @@ bool ProjectionPlot::trackstack_equivalent( const std::vector& track2) const { if (wireframe_ids_.empty()) { - // TODO old version + // Draw wireframe for all surfaces/cells/materials + if (track1.size() != track2.size()) + return false; + for (int i = 0; i < track1.size(); ++i) { + if (track1[i].id != track2[i].id || + track1[i].surface != track2[i].surface) { + return false; + } + } return true; } else { // This runs in O(nm) where n is the intersection stack size From f1b92603c80937104ed8e0f2948cb9237838cc46 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 9 Jan 2022 17:56:23 -0500 Subject: [PATCH 1724/2654] update projection plot regr test --- src/plot.cpp | 4 ++-- tests/regression_tests/plot_projections/plots.xml | 1 + tests/regression_tests/plot_projections/results_true.dat | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plot.cpp b/src/plot.cpp index 73dd43533..f3262185e 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1100,7 +1100,7 @@ int ProjectionPlot::advance_to_boundary_from_void(Particle& p) else { // advance the particle for (int j = 0; j < p.n_coord(); ++j) p.coord(j).r += (min_dist + scoot) * p.coord(j).u; - return intersected_surface; + return std::abs(intersected_surface); } } @@ -1321,7 +1321,7 @@ void ProjectionPlot::create_output() const this_line_segments[tid][horiz].emplace_back( color_by_ == PlotColorBy::mats ? p.material() : p.coord(p.n_coord() - 1).cell, - dist.distance, dist.surface_index); + dist.distance, std::abs(dist.surface_index)); // Advance particle for (int lev = 0; lev < p.n_coord(); ++lev) { diff --git a/tests/regression_tests/plot_projections/plots.xml b/tests/regression_tests/plot_projections/plots.xml index 11fa27211..85689da14 100644 --- a/tests/regression_tests/plot_projections/plots.xml +++ b/tests/regression_tests/plot_projections/plots.xml @@ -28,6 +28,7 @@ 200 200 240 240 240 example2.png + 2 diff --git a/tests/regression_tests/plot_projections/results_true.dat b/tests/regression_tests/plot_projections/results_true.dat index 7f41f6a40..f1f3d9276 100644 --- a/tests/regression_tests/plot_projections/results_true.dat +++ b/tests/regression_tests/plot_projections/results_true.dat @@ -1 +1 @@ -186d646c4959755bf809d35c9f33a931fbd5195145131ae6764955bf276d44acf24970dfff76001106b93a7ce239d67d569440136b13073082c8ee23419d721e \ No newline at end of file +18b85140df16cec9268e76d41430971be7f835b4ef84efdc0065012b2b341a6f369c14ad435a728d9224800882e4a923308859c5849cede0bc4b8ea4f3234f6f \ No newline at end of file From bd2de0372f95e663264fab670e44e2c9df639639 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Sun, 9 Jan 2022 18:33:53 -0500 Subject: [PATCH 1725/2654] projection plot docs --- docs/source/_images/hexlat_anim.gif | Bin 0 -> 1233034 bytes docs/source/usersguide/plots.rst | 76 ++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 docs/source/_images/hexlat_anim.gif diff --git a/docs/source/_images/hexlat_anim.gif b/docs/source/_images/hexlat_anim.gif new file mode 100644 index 0000000000000000000000000000000000000000..fceedc01047222c69613c2aefcaeb4e20f027baa GIT binary patch literal 1233034 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

qeDAI6D>OgGbi}SmE3`A3IAag*v5=|UDqmE z*Dt;$UYjMcSp{Df3 z?;xre`Vtp%ikOUKKD$Z<5~Mr2YdHZl^A0Ca&e)d7qoGS@>wC zyyhRM@LvN)*?&O=+TZ5?(O>**%=%hYwp?-V$D@YTM#jS3p1$1CuDqV{%9k%|KlIeF zS%uZ1rnOh?&lX$$tGuZEr@R=v|EsHE|9Rt&uIByG$NR6I?vJdFlOgE|36|2Y&c=y z|93b+(I@m(!Q%_K!lRI18~KkS=2}8})@nm_E_|S;s07=4>r}fpRn1Lrg>{~PQ(+hV zvnJQ4^?8BaJ@XOqNB7_N9xbiX`s{u7lEC`Lkcvd-`PX#m6XsL&z`?8xY3Db?Vp1{GA{5`c0PPKG-)kJO2B#M@rE_wKX3jH=hv&jvrP2MqBKP zUknoc8Wva=((I}624aqieUp*oqcSadFIW9dK+lNwps4eZa(#fPjj~vfrH#s(?sxYy z&vhU1oO;(UGJQ?_+Ov1w59~h7oM&nEOKQE#x;U-b?_oKlEIP=sl+>vOFHjpE4$M&# z?fo{0#+mO7DoN?J6h+7WDd*ORQ~BV2{4KdbCRNDOc`jf=r5}AROF<*u>$!q6w~Dyl z&S0Xku+^#fMjg?ED)z<-{S30TLh79>j<3_wa>kp*&KB+5kA6SV~}wB$(Yl(cM?M?-Ly6A$XV6_yvI{_%gQ1pgLG_E zK=y7n71hGlftBTMZfRBIC%aYXhf+^+eLKr^Ytkd4UMral7JlH->IXyuiY6&~%Z2qG z=5Li9_(RV(PeBLpk&R;~Dw=A$cEi>B0D46HIugN*)K)i1KMv6iJXHFD{xh9Twg++- z)=w%7B}kg+mMTBm4ST?nCdu0sioVhvUdwtg{H>TI^5)}Gq69KNx)YLM!s{9w zyDX&RuP%Snl`^n=h!A6_@U3rhgg>}hzBT+jYx3K0@t8!!HnLhRN2Q^GBzn+0vE-(r zdRw1(bSZXDzt24xBU3o`%F}Zn>|ak;QwmhR%8^_=Lz+zURXM!hYQeg_85Kdjy>d~8^Wt0@dwuVZoESZQ^B z%Ds~nr+u?+S&j5ut2q1E`5WIUyj=~6?X8O6_ohlH>Q9Ysp2sK}U7mhUklE4$|6v|X z@f)j6Ts(GP`eyjqgRcGd!Wss9FXHdW7FGYickr)u#uu-9yzqP3F?bCX*c53V{M@zr ztBNIYeJAa>#AIfq$2~E)_vo#C?>AN4MZ=V{Tyu%ciB35^`)FCY1+igPo4|+jH->lJ z`Gzj4)JU$xj6YncdlMl46JC3SS)3T#MmZrYqjp`Q+xtVxqwZSy7bFd?;$5a?&u>rM zjnV3P;r*4GxMUlN=c{~OZvu5>GA^7ddp6*#>?U+xdC=l!_sz`y!+m|APdB5PQd~`< zaNWzBH@s*45r07F$*(tpW)#_M^E zD%i_T`@D?{WwR!KdlNf%)xP8od=IE*26qYYAG3ZiHjPG9nu7T2#Cn2XwaWDA9vJ5c ze$$_BI~bMyN7VUf(i!vTo6P;;Bb~~5FO=mGCJJ?-UJWVb-Lo2x<4=xIcxeWw#&rxl z+iuyBBo?sdW6Z>sM~}aY4sZL}D)wsr)fqWjMdB&EXx;?f(TJbmuJ|UnTjlP;8||z~ zvbR&{alRNCuU9G~RrpIzIVHNlhv}qtb1~iDqt=sgus}KZp+e|poxIJA!wt4Ye7K?^ zx=ZZ<&3ABQSf#PXTTmJkUFA%E>ri|(d>!}D)g><7>Dsdf^qn;6qYY3Xgk%))_`a3B5G;t0|c{ctbm z`{jE_j*pOAdmBax zcD90V_zvS}i{Efo{AX*8M}MMI#!F?i)kMbZd&gM{yjAvQsq@RXFW$c|;mPRAcNbM3 zuaqmQ&~|KA2}9B3Q4qC*JF(JB)-TT8d<{+uX?s7^q|-X+zfKrJFNz(StW}S=ZvvHW zI?*KD6{EHEu?%VxK6raS+bU(r`YOgyoX4W3XBwqo(q}Yex5IJ`3Ug?X7*n}4#X4_x zf$qG6b8H`eeA!@ZtAOY$bx+Lt&`e~KXTlTldbJ$CD--wn!XGUCnc`N0t=WgwEQ6fg zdo`b)ws&sB>pb}sZG5==Z;%?6eWvXBuid*}>9QpIXvy2UH%sqp7!I}jVleUTr|6k! z+`;ox<1T4h-*KNp8#rjxg1Jv&Aq#07GK-bt{1=@T_72ktvR86KWv}1so;r|s?(s|C z;NZuzqn@Wv^qw94`LwlAmo9`P=?BJ4hjxy27*390#tzj-G)N`aVNN^Y0ZZS9uW_1?P}MpFDUeEmyt z&cX)A#HY%f=Rf;eB|q==>gUYx?mW4In|3-K*tuoF6(l%XdEipCnbvG!uBhr%S8>h{ za^H5nibG>WQd@%3p~aIcZ%0j%9ulJ;{5H&UU9EbmCMAEpAVR0@gMoc?Mi~Fa^LK82 z!d^Q1DEag+jz@E&6H=sok)wzFM;42IXZ1xHXCC?h<@8&a(UE-9^Kq8-rEqhjY+zwZ z=V#2>{kKvUSIr%wYl;9=0+O&ppXD$_GdF5dc+oB?$Y?g$0;1QV65;wwQZWI~0{; zY?kPu{*WiO49&`naQqd+F!MP|CqRPZmD!X+e}XNizXmnoUX#9Ng}%8(7+3S9!8*-8 zni-)F@11i)>m^SH-}${)H{!H{5630EUm-YKQZ7vrv|EyZ$aCyuKmf`mUX>cpM*mjg zuV62aVR_$fUd8Umg)GI&qWlG3^mX!hoDInlKGu7|RpSiVC_pM*zzp1U{n4+uyYQ5f zrlh;uR{|L+9IGjclSw0Rpq8HQ7s)vr#~Fu8rFf)HZC#g>J^CELj86DZaaiegCN}w9 z>k*AL*m5?1l;(>g6}Xc|G3nhF>2=zq32OQoRayWV7Olz|L*PVK(loXyZIQN}2uc?&B6G=H1B=BSU88j@0K#Nf&1>mzatzc;(v}i`=g;5xRLA$J) zIdKuDwT*0~rM3p+P|Y_N>IEdGRF>5I&4&FV$Por{w#NoVk+7&I*N zW40ze_gq~r7XpZn3|7~sUcr(+P;cI%=P~1D55)=C=}I|><#WbbH;Sc`9;Y1J*DcE4 z$@gd6zB54ApytvP3N#dGsXMo|s0G}Q3x;=6;#r*60j_#g(h@eqw2>GHR(c3H7&lRLdQyCDs&1u? zc&>>Tji?AquBr%QRYagU*(q}Ffzlp@3IqZk%RsiUkQ$aeRxM^o*L%?DdxjbJ=J?&} zMLc*yb-NKjx>cng`o7uaa(`UrR|QzAE+;XsI#aQfSXJ>O59Ss5;1sT=Z@Toe7b!1< zvz&#{p!2Zbk&nC7T4ibHtMP~rWW7L3g?y8(YqXR9QP3Ed(3)Gr>3KgjzNi*+|5$Q` z%n~$7r)DUNm38~nN!4wzN-Mxv_<1)zOEYYP#r8Zs_FBa0vULL%U z8%kLog!wQkd;pjas=>tTaknQl2i4pwejkWzu3|KI0KgpEUohW%W1jQEiAPak57~W{ zpF{;uW-(5_s;x%eCu1JX(>bqtG1oqpvO{cmTJ{I8`wC%A0KQGfs(G-w-a8)#!$Ij+ z5S~vS+vstIN486QkqXer8Z=L#^^>~&I%Ik3ld9?`8WnYe1X*JugYP#9xK}`4<-E3; zKHJiox&vL;Ei%<>>#MHNn1tS1zwbYgG(6Mv;$XYRBn+9GDSf%rV;2^wN}647*H}eX z)*)jz*|%lqHQdwdSh$8x6+~U|$_cRt@j5149kVT+NUQ7*yU^|5`Oe5TJnDWhyCkUw zCU=Syj%I03w!Jt7oQg!qPUq@=gfDFM;$QYs9t7wZi1W+5uLR zCLP9!gL0~N%ZhVem}iCT*Y$TPa-O0g^07#b{$|YzWJM&>HN59y-N3;;&Kp=byO6w`1hToAIqGi``J$jFspR7r$X&o98ebKY@*x{zk^^U1ln9SvN_A3_eRG3B_ z0LAs2asxNTInSeOp3m0j;1PNAhH6fqu%&5B{ z=~qfrb0)>1IH%ik^`;&)%=Ru=_bJ#6vycF<#Bdk@gm1n`EdU?}B;)XYHuJ_NMMgdi zZ;OxQZz32hu4kL=tt>n1``b%COPbhCBeL9Vtqc6g3a~mBRk*A+qs^OdLFAluMJ!RYiDN zfk%q_AWLZ@Qw2z|xgMV10&xD`h8eF~zZ&EeEVAz9w@;!^YIM;NXd!nngsiu8`4e)r4PFzW!gwSRnz!-(Q znQTBhg&&3j?QCC(Ga9O*3em=lXZlQe{FyC_L{_NI-B*1sO%arDx2!TQDD^=m@7H98 zDc469)@w;VcCv0;N{1mB(5rJ3oUFHL$gwAO0F*V;aShSoL+YM`IHI9PRY^%G?u@x{ zZR+?-gSjfytJ#HE6C=sP-Z~mOm`bHb3T%c$<;A(t2k#9YTYA6N(I?>vZ-3~K4D4op zA%QQ2uRr-f!K3fN_|bMA;1mmr=V}i{fK4Oetj%`K76hG!pl>c}Vdg4m^Y^?5%|K$P zgAy9SToGK4yoNb@t1>lK=bkE;EGyOnS6}PQH3j3@_KY^oH~{mxo@_f4a35k@_W{^^ zPuZI}I#WN|`p$XuoeCaeS_cvniBZh%Gi00(`K;9LTHs~{h zl^&m!en|**6t3BiEWsl482=cU{JODh)DnFZQK3qD%+3_23$hZp0UFmU!;QN6fugi0 zN!*>;H$U!IeDGzi z4ZHUUpuf5nMyLT`bu$gTfbC`zscp>~Tky^BOXL3YcQ_V@nks|}AT&jh3}6#DiNGG) zggp2s{+ZwgUe7m7@&H2&F8gC&1y1&e77PH4QIm5E=OdRjb%qHN?4%)pU;r8(ZE`QB zj~p1&e)oOW`~3(Rz~YY>y-qH_vhW(7a|p7X=4T9Odv(-S$93jZPx+ z(8!X=9{@{mmdy;z|9Ha2;YN{820e7|p6t*4n)EG~r(51iKdI@Hr%#f0z1vEkCY`SS zsq*f#%F~%&m$$weu5bCyI?TV*xxc8n4NnICwb81e_Ksq=4IPjr3@*!e+cqFzg22l@Z#A>8FT$e0040yMww|9QOhF`SQSvg|3jVth60!~>UaQ@ z>owa3nm4!a=P;^PJ@ZN~B}*7f)w~>!DM6tzxPrKhpJr*IiCChzyyL;nq}YwOJ^3iY zlhfDKzP%Sp5h%B(+ZLz9SuKs-K9bZNqx<86y_TZqTR|*4;8g=;w`r!tD1g9@cYEW( zLab~K*9Y33-ykXbsWMaMc$7)sa?B26W$K-DcI#} zn`uI^U;BH{P0k01sexY7H4tq9Av@}XVQTUT-Ry`w=mSyUmpy! z>|jW$HTHx#ocJ zqWA=&+-*zo5K}&fs+py3s^UTuKcJrRj7R@G2bS0mP%rd<=Z{oqyTdPfivap?rDU3_ z>`~Id4EDOfGfoZNP&}LfnRlA4`yt2~J6`%l`%IO$mhW;N*qq-p#E0B{9K?bUtP|=X zfK9^qF&Y1KAV3E!b;1hLmzWLw98{T?^NM<})kAbpM4!?hWv?D<*G25JCBLIAar2Y8bj@Xx5 zWRZ8KZJ+rASYgkBi4q1+MlpZ)?d9wX{YGPw!$PoU`R|&m$K5ZL-N`uxs(Y>nBo@iM zv~KRdb*8-7>>}uowf_qM#7&6#Dv^}Of(QUCbV;>^?1p?+bE0+X{r%U26g27r*;;AH z@Zh72J*B!I^Z-vBTgn&LUBske@Pp`3!sUl z70^6BVd#sJ-K$&0Q6^kq^S|P$XsMlLd6`kI*5yWvJN2${XOd1IJG0iF zu1F#=On@L*RR>i;+gv!NF!C&MqO4fL2n>u8VCJX{KHCkAdupsW#qa$4W2QY<=7+2W z>#)V&K=Y^-8~3$W=86wNvf^PWr@3<%6|F|knQjlA{tEyU3jItVWZrxBXT6TvekZBV0EV0h}*#6#PYCjgBL_O z9RPdwvZopLEc|Cb`7SpA`XZ5XY>HHK5*BTy!8!uaK1xyNOu6?p?dtLnNVm}=6cf+W z=K?-xNA%XEYcVC2+3bKIlcfy6iF&e892m_r8m??IA2n*TB>(A_h7k*(CKEC5HBtc9 zq(jB3gPN(SBE&^BKEW7)i!&BECT7gn9Mhar!;>Bw9=sRuYw+P7s}dWR%&89md@guo z{#2SJA3-NRFY8p2Efb=+^6DyYU>Q(R$=Os#p*L>H7cPCoF!=b)A)TD3o*4O_XFQ=Y zzg@FBx4id>@}PJUf82m-$rBpccLZXku>VEE$z6cc_B+!hQv#RXBOK>>wVoY^BY#kBY_1Di{1nxC%25pk z5w=W-oO|p_WaxSGH3Zf@E@8B2ZD~DkO^~J;=2h5 zmQ(~=6${5UXZTSF8}Az{wU4-F>VFns0I*~LtLowz_T!@H1fN3blSbP^;hgAu z-!V#jxn`!uj#N?RGDPeSdv(WvTeWO1qTOH9Vb!N@R}U?vZoNDk%nQhUI#}&t#T1~? zHbrfIPo;$~fs3|(!fmk}0%6AQDo`24ht_cV;^F}O!gT5JKTxre;M)%9t;*_C&paMY zIfcZ+AF9^DoPAu1Wn?yFv)bPkN3_oPU;R~Sp!(S!f_)Cc5}!DHLY&IzdMo?>(sX9E zXc)&YuA-v-xE>n=zMHs9S<*Kev@dVV>rL_xv84Ef`&U9m=Jg3?f4<1hUh}(ji_ocb z#PvW7K0)Ue9ASz3rP2U!t@L$`bDRCn;Z6{1IbSv=^zy=Y-n-jBz+AH3-P0-x%@Zz^ zO0$Pgxd?_Y(0bP!o+c*~;Ht!xc$p)+gadKtBY9H1lbRxtAg@r6NFC66DnnO{90CyD zGvq~ZAR)Hw0z(w)*8%8Hs!SArr|O@9C(cAd{(uSNC3Tr$%p6r>r6&vGeX`?33zS^M zJx}0Fp~CkFDE4kpWJ%#cq_B5t*(s2K2TQpi?+8AjG7cI>g*$9RxHUTk^o@kCBKlhO z_Qhst+8hK_B?{QQ|2K?TiR>u6N6-(@n5fP+0TDh8nXJ78xL1L3leU#k!XV$t^i*0; zX3=Uqf{UKO-q>aL%d@w89MKdjHp*K82m@w9ES4}8b;_P_sT)BJthVtxG$ zs8l%RR$IdbFzCQG0l`nqp`YL(^cAibBk1B+vp@x>jxJwj$_-)suc8TAMW{$EJ}faI z#+a;0MB*#~Dm2tXz(t4829?*A*^gl)SZ$MW+mxwk%b6-TyZXXWl;W&(+)ZhKGvNuf z|FP*9VFlE4=xQ=OhM+-`fvs9FW*@`r`&Oq2sBJ6srd2+-^;dr)l96ydm%?@`10ED7 zHukYC!dT3om4=>fLAkUI#&@zEo)mU5fTK>6s7Kp{E5&hd9+it%4vlq3!~Bkfh8;-$58U*&YD){Y5!dA;1Y5SQmxpse#zwp4*|Ir_qUv z^kMdT!DkfeU1y&X1}Z;6%uHkO;mVsKEke0cFRvo5^6R99S`5ac`7y-S0y{J+;ev^N z%%Hpoi^CcR1%hEw_(UW2<9;xBEE3EyonX^Kwq-%=N1@@Y?$xD!?>eYEZIl{J6dZ2h zS$+PcO>-C9W=)c*j{@LSxVIBX!TZI}C9CaEN1tl;?{;(8wLpP7SX2enh)O-dV3*^Q z_AGgHFcfEoJzoqiU%{5y3iTjR4(W;g_+;T-1X{R1%u==ThxIa3Ct0VCn=y8humQ`WOkN_W>29!Bqp9&E6wa?AYxBw0Vz{lmwA~ zvL3m8*9uDTwo`w=_J6Wm?B)pGYith&jJ+Y_I0rUBk30Ef`1QYWzaw%UoA?iVsB_)# z<`D593NWNTP62V}&ptAuocKtpr62gEv41_uRt%urGr{ z6a(hSL*9@0^G2i2<2(<hzfYEjVAVHe?M#j>^z@!aj*{L=1B4pmdQTy1B+5iRd(n%ECn2gJX zd6tf66p}O5Oum{JMSlY1Q>~b@j{{(V_m>!M8qlLR1rJJiY*{_wC1S`>ZknQ7d>bVRg$86I1dy zTBfnom!EzM9}kv$`F7*~qV2tdn*0}j+XqOagCHOX21Sa11P}xjMWjj*>7CGf?*f`a zLZ~9WiJ|x2i%9QHdR4lBfQW(!DkuK--tRr{z2}~}Gk4Am|4;{J9-hEA>$4U!dOvD< zD!k$fe*`lF-NdSaW5GuQHqb+0QI^4ifeU0v1m8~hsQVLQoji3`8`8SXQIJEv@bCk< z;#>NP6{vTX+C?-I0xcg#5!XhssT%Pnewk=gx?hDfV2ak{=ht_^_i%>LLso8Zg&4%( zjM!$F^%6e5ofr6XG0%B`mk3hle|7%G`6^#g`sIwf!FMJu7NAau6!#ji_m(*aj-vKC zF)}yFMK5Y!%w-^jzyTQ4^I+BIwdDn_5Ym3+hlJ5hy^E)>!M#UMr1;0oR5Uib<}hmV zH@YqMwbuv;Wztt84pQ8WhE+&c>01#+$l{bVL1t}`CZvUry0xI0wP7;OY73&Qm*8G8 ze-=!!#vDdI3<@3ApvfI%WK+?kvw^Ui{Bj{6)$bG5OrBdGAdvbh{r$GL*qJ^$u z!t7mzR?a7|NS)%ngEE&+d~_&ps5=p2tLZv&ynDR4YbEO{kpi)i#h>1XSf4C^>M`X= z*!LPJ(9c$X>)qivtS%D{+usCfo%GfFQ-96ds|O;Ba;QC)@eZ198@8^Sk`OCd{ErB? zTVElLq~-z=VuOUtUtIZJ_f%jk`?y7wndp$JNR~JzY_1t9{uSbsjJGAaowd4=8sxT8`}7|f+-Coo2_)k!50-Bn9|Bd^O^n)E2_EOy zq{!law{x9xl5U-$lWJNAAyP@-qHMhai4sq^5T^7&}ZsOgP?U6m8u zWxbu+JcUWSf(nSMzqZ^HCJ$Js+nA44^45*b9nKwYS8uc&(Ywwa&GoE@FS+YEbCIcH_4;Hor)ECfH7P=DW{#r6lD!nD5s=swmxK z-ii=40!&eHUg;g!ULUMWN=`0^sK@wf%=+o~;bb|W?tMO{=XiGps7HOux!bajcey2c zJI(Ry6-{?)%@dFSY&J8+FQ(1Xl!a8*!09UEbe0LEqeGnroG}qsEFS6s_X~Z&VU6?_ zsei9l0czcTeR<%@jjc4^nxv)Y?{P$micZvaVGP&lZa8X@qbkTt>qwjn9-!3l-j!Kl!4>k>D9*O)D% zVBEX&z*yy>^_mc|vSW4rvo86w`-lPBcV8?GW^zB}UbqR-pE}DCb6nM!A)qLvmDNDQ zX(s(3B$~A9!%8RMPNNU4X1BcSO#$S`%OZAG4MA;McuV5vb3>Tn(n}nn0_&ehp}pm& zwoK3>*xg;mN)Mab!n_?d@hW+%pFZpy3)`KP{l-^8tPNa8Hvh0k5lHjPyM)u1sAm&T zo=aW<8O0pAY~dXWa5q_3j$S{XdxP_8eXi#TIlYgk_4`F14Z9Bz?!SOs_}*zpPdYyZ zy}i*>x=`=F=-AE9!>>t{VZUw3d~0i}#CBaVR>KTlbmXbBW6mKaD86RVZyGZmUB)h7ylo$81RroGcQB^tF-%V6^RlCGM{2ZWcJ zXl+gsoIp7urz#pJ<9{{$=AQh5OPwy%T=;s_qbRXnHth&h&5+ntVJUWOq__Z;^t#IQ zZVy`}lWd;OD<=m3nArD!j~di*vrY>Gzwwx|`0#NvqpUp8&V_2p>p{n@pI0RyZS z>92uDwE5{q-!!G7!j0aLkg;pmqYGDO`NRg)Ce$CV#!Rcnx4Hg|60OP(ZMEd z;FdV;?d1~Y%Tg;e^^;}8u6$3`Z*NQ%RgCa76;#jB3B1pfY!gI0@4_uq{z0k)QL0+s3t7|GHq-BS4)8G3cG(T0b0xb^XmUu z0yKH&wmvIqepb{#iWT@Y*9Oe7ed42a5xzvIAywf+n;5J1YN^EEw_*|0h|18}j*Q2H^A03?MLe zASk&n`2R{4w7X?>1QoQu@cn=aT15Xd1BfKe08B{Lf*)c3Z3gfs-uyh-_7mz~GXTeb zW&lom5nihyLFVUQU!#!+p}zZZfuG}^@5Gaq0FK||EPwv37C4+|xcsda zBzhgC{>x{)_l;`qH*P+xveb{zvx)zpPFEhxPyTUzvjK<4^x0 z{twTO|EE&HZ&In?^yC|f`2YWj`~UAh{r^a*;D+fyO`&$ke3orms<7j2+)|ZAaZjzF zzVmF+ea>d}1&OlBJO$%H$@yE3lSQTzdIzcVw!?|rOU*Q2<{M_WVu$C1i&l!E)w<2i zkttP{F;OJPotmL}JqE02tSFRhha{o{j@3#IHyp7xjuYX&sq?jEYwVHJYL_Z4+GWq@ zhtF8;$A_t0xgfhqzNN?-%XZ%@=U=9ZT7K%i zO{TcU61=>**wg>!_M1QY2&=K2@_VX*b891w+tZg3okCc4((;PQEa=<&{11o$6ABjn z;SeP*!IBcpO3=`pzS^x~(`#7-Z3k@f^UJzS!(!dudg&f(3HopBhcvJ0O3vI8r@?-z z^fY@mIM>T!)_xM3c|(~uEazpZH(R9dWKFl8^Au8?HT)8-{-Ou%z-(qPX=9})`mV+^ zCzj(`W2VTEyyB2ZaY5{WKt9Nl?{#58)#JEkFgEQ)yp5fq`B;OljiiCmB#o%?fIe5; zrs%dR!hgG44N=;aGLY_HMDFm+;~6{BqohD9|1}!GIKuODs=}XTi=ML^*;n58o4Yjy zPu+Ti7p{gUy}DnNgKuS^K>B-RH0=nyIlWMH198>Pu?VH(#R4bALd^uJ~DN-$Ko#kH7Y(Atu!EUs)SNviUs zVX*j3iBBxn(@o_o39N{e8;yuozaq?HfR9Ekw>2s%#gKal=NnI8p zE7vY2r8)C7;SZ4fmQvS}-PZ?I7pnSv@lE0Q^gPSW@#4#G#RiKYS(z_w{*0^QM|Xa@ z253|%Y2LQ}>^E)dLe9VJnm2vvdo~B%YvIMx^c$YFp043JRga6#<@P3Zic{A!LiidB zKPb0;UJqTU*wjs!Axtq#PRMpd?%eR13>`*fJRLLB0yZ3jcn zuf+1L_M5)iOzHV$O2S{GMChN%8tstdiyWm7(ByYNp6)B&c~-f~YPk>@VZV`L5s$x= z6gDVv!ph8egT|GkBj#gKw^*aiOW$HIb_(H>wy)rQ{MFBy^ykA$okf{D_Dn%o*FuW!7=10eD=bnNHN*vS$?!R42J&r)ig}@oL z?YeZxgo5U^uNLd9RMeL`2~}ya=KCa7p^H#USRSOR1{S39W>M-9LXoFmLMJoc zOH+%qbgE1?!&~I!2Gh8LYU2021g`y^=dVOU}I z=Et3|;i7;@wxKqBdChUnm~g3Ku;u8mZ3p{nU8=i1VtPIIHmLp8Bk=t#c@(r%4|P?Z zT;w0_d_cxN7O=^k`s1?Ya^l8YRAD?Ju!deVkC99KsMPIC(aX@o&iADVUYFifU7jP5 z5ZP7H+?n`owcv)PmVS*qYnY&F|Lw6SR8PZl7neaV2C8K6p;|WMlVo=jq`o^xq!&pW zzc30(tCjI2wZuqQW4$7*NT=913SPXGqxdy}yTmf;8iew(_7fJ5;KB=R#+4gI^_Grq zo_DjpACsPQm=)rkZ&Qpv?6^nfFrwNzHj8V(cO{%dZWW(13*Mh#CmckHlvuG*TeR&p}K$!Ju| z@@1QKF-%3G;Y7|IKhb`f6cu-4TV0qJ@BG?r2P)Pbqwm$Pe`T6tMfS|{mzdu>7Z(rz z>1wK7hv~TD#WiU5Q(90xC`QH?F@u+A>ZU6_ulx~NVo{p}<>}SW_wcR4b5k2$IIFAr zVd~1JpI%!3XEn#krL6UPh}DB0YxeYjSI8M>DV~clsjX4fL7#%GW!6ZE^ygx4e&4f^ zyujFib|i@m z@r4;8G}AP9Ip*I>?pM`2?l@T)PgVCMMm(I|5G=0A4BS-^t)gaflsCG!`Ci9%Z=(k+7$59swMwRYq z4P)k3@-{nL0kas}_%7CzonaGSzw>JmGV)D z(*CR6>A^A~_}9`G!=Kj83m-h+_|fl09tI`41uA~3`J~#LW+A`lW|%82*c;4Lb(<{= zRZSXB-_<@Dxb#NZ@A&N(I?uh((-FQ<$@BG3ms{1&xK@I`4`()W{X$VkAJDw%UqOR+ zw>aWPQWZU|A6@qQ;&r9r_m5z>Uhn}JfcT>z$xo7W4A%7@pD}ZlCn^^CJ~xC251^h& zWIki~;YSUYimX@EPV(mN@fhg=n=E@juJ>)Q3%GLZe0cPv-3HZv{KOvxC7sa4>blU) zI(Ch@^sxr5>&py+IF;%s`5hF}X_tVuEy znvBgm4iNDTxxKC?yKxJb#B`yX{~mcT7Yy&ii}GdlBkcji3(O2*xCB-RRLTb+23uC( zObF0GO;V*6VCm7i$!gFnO2c=4-J8|g@b?BaYXj35(Tn-WuawWm-QLbqAE)adY7GE^ zY!C}DZp0Q9a}+wl3$X;Cz6=qS{(mO{k_3ZW*OkcYZ9MLbxw93t~8LhY3;+?cNoVi2!|L%Ps5Tfv&g(1c5^_PA2=^5EsW3Pm*fPxM#fsl;dEOkc9rwn*w?ODpA)y z(Yi1$2L@QH;M~XJdizr@I7G$hVgnD-14+l&20T5>Sf}fTQan=ch%_6MOqz}GLvA#1 z?x*rn!Sk#j&V~|d8;}?m7E7*zv#iKSY0T&*@%M&_wuPi)NmQD^D@g*>x((-70Sz95 zK3|4nP*hN58l}P{i)3Mm>ZdZ5{Jr+PGToX;u+NBpT!#uSVLJgP72}RdiKR?`VgIJM zA%k>k>NJ)GJ&7Ca$5k~zgW8~w9caM;RT-QHSSI8*z8dMKayVfs4dAXk*7hjK{GFd> zv7Gp-FrzVrWG4?_wNJcTn4$MLk$)!~03c=n#6AXM*#vQ|c;nHQf)I%Cb%#m}K)p4g z*#}f4r+Fn36%h8ilht7H67$D7WOlu|ic!V~Son#+n}osy&?O=;mSu2$Cnah=*MSn4 zgB6-FEz3 z#qfHd-fXftW#RY2grEjoL=(jEprFMO_3BQc8GBxGQ%UMTA!4odny%p=NOCwWf?;0)^!; zz!P3>iz+0YGCIdV(!%rJ{>*ay2Mi?wRLO0WIYes6ERlv^DL0;qOPV=&C$-gI{pIzT zX(dQg_?wo~MC*X6{nKz?0B}WA9NsAJam?Klhz1U-?9Le~jNlaz|2)BkG!J5-4nJiw z3gvU>k+SsTW`5sCl{8viUMRaKOKdLU{h_YgV9~o-U13$R?4(bI+&rriJxkPkmMakf zv5f(PH36t{g$EFE_pI7_9+Cm4gq~E?#gqcex7|}vO$~Q~FTIezk^J(oW|bmQ&>^mH zD@Q*NWpoxU`x8Q*Mp_r3&PWY`#(I+Z?p1T4ficcgkTTYtl75h~)}6Z79fdhaKk*{~ znn^{5%p8JcDc7Bb8gV9uDf>o=dV+Pk{S7vAX*W}=4Us6MQ={E>p^Z}=7y&p4R>*QB zwLi{-u{F^fQ#G|wLkLuuWoR(5X_PWG^V|V7Ur3`Nz^t}_R8(yay8#hRiE1!R2gbm_ zL2gV@MwdhS&1WdPgQ~cNj2^=}TX%@VLW?sJ^>ZQ1`jpiEZSonUd`+bGp#lm}RErC5 zN2Q5@h`X1ZNx!;qB}Q6jDPzuJ82|}gK8g7nPzBine{U}17kmdxt~RQ8hv2CG`Wbu{ zhB~~_Mo~fvlUG1@A#RASSF)6fCX`UNO2%JQ+3rLas@Iw=Pz(~a+M`qPS)EMB?BjF{ zyHbr~Tj;}2jjk(7yT zlz@9Zqgs)VEYxc(k6=QCo!{vOG-;L$nVGI9h)OoUD}d@MS4VQZLq<0K;3)A4>glHj z94mS(nhMSgJ1I&UJr`?z7Hge>##aDk^fD|(b1(&o$_qq=IQMzE_k~3g3y4%e1ySonMU#Z_ggx*S11GX{4wwiT%g5@B=yxH_&NMB2lP;a?2 z$~mUGQi!Be1J{*MrU5{UEKL=X3UWgEMzgPFanK81B)vlg01a{vY43cx`M|M1g9_^M zxx2vuWm*A76u&u}12e0?pDHPw34+)$v}NuNKTxY6izMmf0gASk`!s+Nq6<a%L#H|2r?|Mn0((QQTOw@>C0}@F?(egXz7xuhezO z;(lhA+V=4A`y~L3`2GP+^`TMQau5V23xH(DJ)EcbI4NI^jXymg$=xYL0g4bLEX;iZ z!cRqeMhV%Xy!Up-MYc2(Np(yER5~)lO;S5NQNlk;)M*R9QBNU_-={gZ>Cpm~>cBPO z#yHZY8(A1{ItL)y-UOpwAyF~1U{waNCX$>FMJ~$#lGB7i2orvLlsW|!C(fl%{xNoA znr;tnfB}X9U{8Og1MX0R=2<h1fuwBgRdxda#B&Fi|% zbD4Rl{ruBqkl+{v$sYgUfI=PsB4uatkTXPL#i9Cwu02(i?4%lFKV*w)-njj#S{O$bx`jy{3jZCFAPYsA1T+yf>Y;rV(!n2_X#4p`HeLTvWfDh!Ee`tp ziGjeDBsc&v#JKap@~^ZWw!Kb_D-iJq3DC1)Gh|f`?bim6JW?-47mw|fSj4DsIDDz+<^TwS1K&?&0aK_#o?9ZpTh0nUt zjbZn}5jVFSRe_?QacIHrl`?WE6h+cL3AY;s+9=bPdll6vXSlvD&;iFoG*1}!3)rbi z0hC;Fa>^^hSGULBj_0X&n z!oL+reH^F?7}5e{?kGt&KsL`4a}Kal8wVAN4?b-1I!Ro=mhbrrh+ovo$}2{ z8zB2}Ien}va0w!H>Tq{F<>TQ4lQ!)?KXo-pre2xx(EB41`*VZgBV^Ru#UD@0-)zH_ zVXm|jLI;29zKql^Qs%m&tk9_17})7Y%E{*_t3U4nGTCKWzmWR|XF=IzKYbT^9aNk)`BuR^NS$5R!3z6LOB z!T`{{RL}Ms@qKjM6vqQMJ89#rC`I|S3NqC=d<&upoZbxfq$)eAI+QEupM%mnBbT zFqsL;1AWdxlM^K$W3IOOVj@5Q%J``WP1`lv>*Uo}lj7YmASt(#OpSYFvhwQ24p{=K zuVdQ3>IbiU{@O~il6JjPf^ZoS$*YuID^wVXlB$jr2db1V&>NW{uwuA951x2k^Ln_D z4Y{dLK(aXOk$s^8Jiv=szme*Cm7MYTaH)QCT*r!b?1gwg4^kip)^IhpP2P3Dk@Zk{ z9(VsLa!??i%>o3ROEM4~c@jAa0Cz_Jf;G?DWXtgD>41d-7YgySi__JoQ8W#|Ob58z z*EQ~!V16^bI`VJLa(hQ+V95h8j9dT+jItW46zoAwmZZljBwVm!mjzYYcpN4C5=?cL z%VH`|22qC*@)avB7WkqR}s$X@_-sDVPqs6&i?eoyik-&UNNc^8;u@s$F2 z%Vwl$A&%z1a`EPG^ph6t$OL~3>}oFxatldD-Z-y_62C5fx$Bu_8y80nQKn61MJzcC z%_~KQIyVN0LAMwg-(F@CZ+ssWyxVEKi($wfvWAExHjj;eh`p7I4u?OsmxD?HDDY)X zIFmAbViw+l4nZ3-y+V?)%g3-bAmNoK;i*;ESc=K-rjRW|69S&HeX&E7 zibesUccaHs^;$YOH6gOrn0lC4k}$ALjqK03(D(_&L=$3H1@G1e#ZoX{^n^=1bcg*KHsYn8$!_+bol0#UqL)#%ND@_L&`ihHEz|pFT5@ z10x>At9f5F0QfPqj+)A5bf92yC!TBC1lVhu99{Pd1Tepyw78raJbm{g`-7jEjD&Mi z#%O(og9-L_*I<;Jb6{N4M04=V>@vh={@r6tcXJ86)DK_CRGC z_!Ui$u-vd58Lp`;*$??~wJFhN2__meuR)anB8NLeJ{L?rfa1Ea4tppxhN6>02{9uv zM%Vh8^(rvgFi?!SD5<&PMZsR;WGYh-C)>KBQ7|u*@!%>iFm0{Na6$gf`8(}x<8VJ< zfG&rUY=fJgzM=4%5Fe%Pf!-sU*b5o0Q~8>*!pvf#F@od(SlEb>*19-LdQRn4h_LhU zGZ25#$e<0EJC}j1O=pKG$O-5JZ2vCPn3q8Jp{{bS?RD)O(k?}t7=hN(I;0FCev zS&akf*;HB=2`zKiC;U?iA(QpOX=Dtvc`>W~9u3A>C5p)ufY9|Hse@nu%zLm16Mfjk zWjy9{e)U3|@QOha15VcdA%P9X16u#RNQrWRw%3h!wq6Ssi3L#@ z>%pyrmnrf#O*90!MWCCU;A@Ow6|_Vu3nmy3FE^!T3pr4$c@Dyv!xP#N zTmqaLIyt`sD6^m>hKDNNaZFJU<;E;owQtsypSNIkCnK$jbWmV@l-x%ms*v~I$~3_Lh-=`vFPbKc|L7VSuxqX|_!%8?BP09wN2=Tz%t;chq8 zt0nYznvrD*<-qbZ0KET9#!$pS;1z4fH0HsTh)}e;nhyF zRrd*t>f?r8k-x>n-+^XBQ~8rq2{k_eLbPEJ0FKLeMb1~zK2Ut0g$;yGPGbzJu|k0j z5nycq#o|wP4OADkCUwpl@(>dP>~at`JhCA%l|`y$SAqZtA)VH~byxP*1!c19As}Fk zf{zBI%MSsTL8?U1D<)Y%Z_H3LxjGRnbSURfjzV1SBx<2qfx0@YYBy|p>EH#)yYMRm z7vPJX>lervPXMk1vMcbH46?T_!n*j9K>(sldkbelS`oyA$Qfd;yUVY{kxvbT#HTc? zPQF4LfDb4D7I$n3_{wN&^GFn8h8#4@6kq7E(q9-U^ zA*}^LWX2|B0x=)}2;tMgSs+OCD)>nA()0i9%0? zb3M9vL;3dOiV!V#2+lE5q{1S4nh{2<`IJN9-A{PTPzHwDh%q@U=_X?cLN zyEkB;-V^azlH7BkL%zHF8>)+$z!hFu3_`IflkFI{xLH;4dR6%fV7TFf@huo7_kL|n zoE{AC0zk%_u@VLpjV6?m_E<^MEI|rFoK!urSJuoHyFnbJo!}2Du^#lzkN`6MsZ(UQD6@Ilg3Z zo#sRl9NZ20P4<4x?f;D zsmTXp6hdGBVttrp8}$jR zx3LB|97*=|15BD^ssQlBp28&UUaIBY^TSg;128=);V^b7 zm*IeGw#eWrKgPFx77ly!l?;M}L2QT+tAxp*U)Zv}`2cnBd*`{P_w&hM;C4lSnwsth zow3*54HM4 zC+B7$e}o7z1fp#0@%C-_a~I@{j=M=;unIrtq+@|eTEN`GufYkS`7AJsN|UVabKTg* zrP249>s4%3pEakhlhJa(?)0l+D&picK}K6dhXTCQEZ*?|tRkbcLJJzR#=XDyA@%)y z7LN=-sP{jMd3%wd2fEEdWq-gfTEWbF@^5d;#vb0pdak zw}B5N;}(N1e;5r_HQ}<) zCS;eNFM{))oUU+*4H%CWkmr>gYYGT0E01n}l3U|s(i^X_r* z{RdZu?(iAEGWZ2JO&X7ScLXuR9J-_z)U70VO%^0Vs7B%nPjGtviW^aecOb)haQwXw zNlpfMOE{i%3Ha^JlYVl6Sz~XWeg=X1h_~RXZ-OIQaO=4xdIp{zIQIXxFyKY zD*YPtWVu!wrDg9-q1i?fiiG?{^EW{n{9r={NK+%kIT~-|`=%I<*$ z^2IE-tmAFL=z@O90@Z8WVo!(^S9*JO3XJr4A-V7DSp`&JKl-^!2x^JI!Us3TRSZvm=v zw)PNv0>lxqdzoc@U$CoB7knyw)Y0*G05Qb{k-Pm}{L9|~lxDuY9!c9p*mjcIlHEVr z4_wza04H+!TE2wXx9!^i5dE8%|S#{672 zjpCwynA3;o_}2_^19^j;HrG-#S4#fyI*i%|+xNnSl3w{ZbXT>Yl4;xdkYF121fxTf3^&#Na7XWSmE|}?zZ~iRqnGoPH`-iR6JN*%F|Sb9`eEI0nIJ*zA)&0*Tz~io(y^{a&2665PkZSv_CY8j&7m za7k1y1$f|!-(ED{!Ql6@NXaWRn|JqrBT0s~li-qqeTNx8$8tzw?Q{BU$mDde-hQyn z>=KFYC>_K5nEP!$cyaXXxyPuh@u-h8;rt9ra3P0Y5VAk`r&Pc-q*uyb>o8HE+nE@} z-4n@v+jDp8>$ScZaI?c;BFR4T>c7SSVs_&t4&Qi3((m{k?rwkM8zahvUJ!Qt&Oe^> zuTp`)BnfNODs?>i*BD@L=SXn2!m>A3*y&hkzQ%E;%H{L1@L~g)g8YB&gMUu)!G8=2 z8u#^`@ei5~^j-{lHviWLPm;kquReEQeo^<@oP>bCO)_rGut=|Uh;R8TgMVFROX9y1 z-no-x@TGZH#YMIyC62kJw*NB0|K-1P9BYc48VX&qtDTEU8u)4l68zm<;`z4R|E~kS z$vdYtfJA;5H29Fn@0OaN+Pc8XO!JPv@V9kWnhgp5CXwGH8GL6F@-P3L_;3Du_>FsK z76}1&?auQY%=YRm^6f4S94rbP%J-ipQQ*13li2|smBA4mt|TRVM7IZa$SZ0%Fm%8t z?jIR^;=g6^L8<*Ou#>^z@1LW_{Ql*GFK7$)`G^i$#Qe(#uTP@Dzy77bjsIsE{GWt> zDDZ#F;QvK|JMTq$u3`gL@WE@5UOQ2~pCT;}BODH*eD-7iQs7&$HY6YX_js$*e^cPj zC&^x46G#+z;9;8A&)5H@gb(kQ9+AKf^R zkUx`LH=b5D@(Q~e6}J2myAd1yR}7z;xSE1J$f#W)h3o%X;X{w||80f;4

fdv)AF zVeWcv#co~J@|*6SLE-;TF8s&t`re1(|2^3K|NXrr z1ibtIfDfL8fKTLW+Qm|{?x*P%>u~7p_0)c@FL|1Y|J)O`Q0F{XQK*~dvLNaDp_TKy zFUvx0vwvl+@Pe?(Y?^U%fS~cTalP9*&GWUyz0?{9QUX1&r{r+GZ=%d*O>Zo%rY|8) z*m!!#^OpViEw9hVtedm#c3+H0!^6~Cr`ftn-sC;;YMVaH6%LJG2JSXPSt^2k!t7Nm zJz1((xPlB1htiG9OLiCygcU`-8HP)rKpw(bS+6fv+P>!ec?tkSG563d*JtE zH}Tx~TciFJ&l&st*xPdk6vN_!{NENu$7}gG#YUaA$0R@3>JPoRe5#}-dbGqhrn6$* zNh8MY+n0&zLtvxO0;Wvr;=6BWK8C~VPOgSs&zSuXb%VU`s(47k#bHs750-6PNffbM}@{byt>yQ1bZrdT2M? zVaV!L!kyt;h1*AZ=D~{08@HE`=hZZ^zX}WZ)9aOu3~l-rS8elBM^?9qH89md;SO3q z2W}k0su1^3kEal+%qO0T?TymAWZU4fMw?K2^}CUwU)IIEP|iQ$g_V8xrA#U-5!5c+ z)%-uNh#pX#WdzoA9qzsx85guJ*v~BBCcJ-|AL%n-nr++w4yG`+ihgb6nB_`7XWKHw z(jg#xcKG?rJM!C9$X2+Q)FB)TTNN7|n?AD$4$0f%E`YO#s)-NSTx0E8oI6UfUKOya zDevYwGfx|iy&Td1CrZupE$>=dVTJ66s;WT|dh)#*>FM;1ab9Zs%i<@s>~yBlD!fKj zj5h|hg?PmUj;e8&?`|%Q_MB@)q{Ym4RMv314oeIL+@`Y3QSoH^lqfBxjVxYw$40r) z$u*P*Ig<+t&0#2h)y8@}9Gy0Y;|P=RcAwLg{$@mC z&8lweXRxZln}PSiTd|2PM1?0FWJy|ejI=gmkFBh#7Tzt_3dl7Kp)hcHAZhZ!!`+AU zQX#}GGk;kS*GM3QCb{=KJwYH~W!Q>sNH>@#iMB6(K&SBiknw6&ysNC0-UD*eZ|O5_ z58*L^l0)2}H$6PYLzWD;yDaFQK�iU(F>$;0)BtRj9Ci!g!TJ^bPM^2&bLJv?#r! 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 z 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

-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�@A|wFJwjjDru&kDvNjRTa-kE1736g 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

2tj6MTO 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 hn~p@mMwh4qw|^; z=hq_Co`?BiXU4&HKv-h2-eB{jB5fc$)oTkq0Q(R?MlI5WT*gL~(0FrU9av7H3MtbR zG7n4rsZ39-d#W6SF?LcUFcJwvqG7S$A3jicH0nz8APr3$WS%&zGxe3B&QV6Bjh9B7 z%IM_gWPGG4KNVUulqw^VLarZji#;v3WZr|v1xw^OS9vn|~5=>OpDPD+7a5SQZB%RR~Y{e#Cj&q)%_A#ZaCDMDuxpk+} z=UPhlZ^zMxpp7trH<~T4lJJcO*6E{W5ikJn7PCkL6ul2zeICVy0VmymOh`k$f9IGG z;=zOT_?F|6ydQHW6eoE`ZG#9dA?X&3(ejkEB+oEp&s0Ts{qnZ7Xw8SJy>Bt zJ}d=YdB2FHJK0WG55OnVQa)#Jbuyve@6qj@LD?wPkCVsZrWyOOcDobSo;1MmL~1mp zVT8!!;|IY_Grt{xT*>U-n8#FmBZ6*ulyOkDT5m`t%m0-+1rXx%N#Nc85`+6X$C(GxC{Uy0N|y|4IF<$lkUz<|jUQCh#e zcn}`CX<*uLs?0Q$jX$k90e1_C3Hw2dug#;_t3gwE+N$6N37%+9-?0_lNl^Rj2I@JC zcPFoU@nDkQQ57UIgRfx<#A!0MnhP2Z3%-iww%X)MZ22c@(Q(%lULk<~SuK1K4o+VI zOPUq|{3(^VoY zF%6bPs!RufC*j#_V4$pvzBIwD&p)mfP4kKd;9K+JpF+JCD-a-nKNysYPn9d2lz-!_ z;3R>hFofOEik@0fmQp#FuJ>UcN@XQNlJM~Od8J7Y>|b()WH4Lf1F#GeWORBx;a

WG{!UWuM!@wD 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%0D0S|Cs5dEr^DSjECiFfcK41VQvBoZ; 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