diff --git a/.travis.yml b/.travis.yml index efdc457a1..acec278ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ before_script: - git clone --branch=master git://github.com/bhermanmit/nndc_xs nndc_xs - cat nndc_xs/nndc.tar.gza* | tar xzvf - - rm -rf nndc_xs - - export CROSS_SECTIONS=$PWD/nndc/cross_sections.xml + - export OPENMC_CROSS_SECTIONS=$PWD/nndc/cross_sections.xml - cd .. script: diff --git a/docs/source/index.rst b/docs/source/index.rst index 8dba92016..54ba825e5 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -4,9 +4,10 @@ The OpenMC Monte Carlo Code OpenMC is a Monte Carlo particle transport simulation code focused on neutron criticality calculations. It is capable of simulating 3D models based on -constructive solid geometry with second-order surfaces. The particle interaction -data is based on ACE format cross sections, also used in the MCNP and Serpent -Monte Carlo codes. +constructive solid geometry with second-order surfaces. OpenMC supports either +continuous-energy or multi-group transport. The continuous-energy +particle interaction data is based on ACE format cross sections, also used +in the MCNP and Serpent Monte Carlo codes. OpenMC was originally developed by members of the `Computational Reactor Physics Group`_ at the `Massachusetts Institute of Technology`_ starting diff --git a/docs/source/usersguide/beginners.rst b/docs/source/usersguide/beginners.rst index d65ee1f83..9ecffe3f6 100644 --- a/docs/source/usersguide/beginners.rst +++ b/docs/source/usersguide/beginners.rst @@ -12,7 +12,7 @@ In a nutshell, OpenMC simulates neutrons moving around randomly in a `nuclear reactor`_ (or other fissile system). This is what's known as `Monte Carlo`_ simulation. Neutrons are important in nuclear reactors because they are the particles that induce `fission`_ in uranium and other nuclides. Knowing the -behavior of neutrons allows you to figure out how often and where fission +behavior of neutrons allows you to determine how often and where fission occurs. The amount of energy released is then directly proportional to the fission reaction rate since most heat is produced by fission. By simulating many neutrons (millions or billions), it is possible to determine the average diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst index 5a7e7addf..0338c5cef 100644 --- a/docs/source/usersguide/index.rst +++ b/docs/source/usersguide/index.rst @@ -14,6 +14,7 @@ essential aspects of using OpenMC to perform simulations. beginners install input + mgxs_library output/index processing troubleshoot diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 85736334a..eb620b650 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -112,9 +112,11 @@ standard deviation. The ```` element has no attributes and simply indicates the path to an XML cross section listing file (usually named cross_sections.xml). If this -element is absent from the settings.xml file, the :envvar:`CROSS_SECTIONS` -environment variable will be used to find the path to the XML cross section -listing. +element is absent from the settings.xml file, the +:envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used to find the +path to the XML cross section listing when in continuous-energy mode, and the +:envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable will be used in +multi-group mode. ```` Element -------------------- @@ -212,8 +214,21 @@ cross section values between. *Default*: logarithm + .. note:: This element is not used in the multi-group :ref:`energy_mode`. + .. _LA-UR-14-24530: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-14-24530.pdf +.. _energy_mode: + +```` Element +------------------------- + +The ```` element tells OpenMC if the run-mode should be +continuous-energy or multi-group. Options for entry are: ``continuous-energy`` +or ``multi-group``. + + *Default*: continuous-energy + ```` Element --------------------- @@ -264,6 +279,20 @@ based on the recommended value in LA-UR-14-24530_. *Default*: 8000 + .. note:: This element is not used in the multi-group :ref:`energy_mode`. + +```` Element +--------------------------- + +The ```` element allows the user to set a maximum scattering order +to apply to every nuclide/material in the problem. That is, if the data +library has :math:`P_3` data available, but ```` was set to ``1``, +then, OpenMC will only use up to the :math:`P_1` data. + + *Default*: Use the maximum order in the data library + + .. note:: This element is not used in the continuous-energy :ref:`energy_mode`. + .. _natural_elements: ```` Element @@ -343,6 +372,8 @@ or sub-elements and can be set to either "false" or "true". *Default*: true + .. note:: This element is not used in the multi-group :ref:`energy_mode`. + ```` Element ---------------------------------- @@ -402,6 +433,8 @@ attributes or sub-elements: *Defaults*: None (scatterer), ARES (method), 0.01 eV (E_min), 1.0 keV (E_max) + .. note:: This element is not used in the multi-group :ref:`energy_mode`. + ```` Element ---------------------- @@ -579,6 +612,8 @@ variable and whose sub-elements/attributes are as follows: number :math:`a` that parameterizes the distribution :math:`p(x) dx = c x e^{-x/a} dx`. + .. note:: The above format should be used even when using the multi-group + :ref:`energy_mode`. :interpolation: For a "tabular" distribution, ``interpolation`` can be set to "histogram" or "linear-linear" thereby specifying how tabular points are to be interpolated. @@ -1184,10 +1219,18 @@ Each ``material`` element can have the following attributes or sub-elements: ```` sub-elements are to be interpreted as nuclide/element densities in atom/b-cm, and the total density of the material is taken as the sum of all nuclides/elements. The "sum" option cannot be used in - conjunction with weight percents. + conjunction with weight percents. The "macro" unit is used with + a ``macroscopic`` quantity to indicate that the density is already included + in the library and thus not needed here. However, if a value is provided + for the ``value``, then this is treated as a number density multiplier on + the macroscopic cross sections in the multi-group data. This can be used, + for example, when perturbing the density slightly. *Default*: None + .. note:: A ``macroscopic`` quantity can not be used in conjunction with a + ``nuclide``, ``element``, or ``sab`` quantity. + :nuclide: An element with attributes/sub-elements called ``name``, ``xs``, and ``ao`` or ``wo``. The ``name`` attribute is the name of the cross-section for a @@ -1258,6 +1301,24 @@ Each ``material`` element can have the following attributes or sub-elements: *Default*: None + :macroscopic: + The ``macroscopic`` element is similar to the ``nuclide`` element, but, + recognizes that some multi-group libraries may be providing material + specific macroscopic cross sections instead of always providing nuclide + specific data like in the continuous-energy case. To that end, the + macroscopic element has attributes/sub-elements called ``name``, and ``xs``. + The ``name`` attribute is the name of the cross-section for a + desired nuclide while the ``xs`` attribute is the cross-section + identifier. One example would be as follows: + + .. code-block:: xml + + + + .. note:: This element is only used in the multi-group :ref:`energy_mode`. + + *Default*: None + .. _IUPAC Isotopic Compositions of the Elements 2009: http://pac.iupac.org/publications/pac/pdf/2011/pdf/8302x0397.pdf @@ -1344,7 +1405,8 @@ The ```` element accepts the following sub-elements: A list of universes for which the tally should be accumulated. :energy: - A monotonically increasing list of bounding **pre-collision** energies + In continuous-energy mode, this filter should be provided as a + monotonically increasing list of bounding **pre-collision** energies for a number of groups. For example, if this filter is specified as .. code-block:: xml @@ -1354,17 +1416,24 @@ The ```` element accepts the following sub-elements: then two energy bins will be created, one with energies between 0 and 1 MeV and the other with energies between 1 and 20 MeV. + In multi-group mode the bins provided must match group edges + defined in the multi-group library. + :energyout: - A monotonically increasing list of bounding **post-collision** - energies for a number of groups. For example, if this filter is - specified as + In continuous-energy mode, this filter should be provided as a + monotonically increasing list of bounding **post-collision** energies + for a number of groups. For example, if this filter is specified as .. code-block:: xml - then two post-collision energy bins will be created, one with energies - between 0 and 1 MeV and the other with energies between 1 and 20 MeV. + then two post-collision energy bins will be created, one with + energies between 0 and 1 MeV and the other with energies between + 1 and 20 MeV. + + In multi-group mode the bins provided must match group edges + defined in the multi-group library. :mu: A monotonically increasing list of bounding **post-collision** cosines @@ -1448,6 +1517,8 @@ The ```` element accepts the following sub-elements: + .. note:: This filter type is not used in the multi-group :ref:`energy_mode`. + :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 @@ -1627,7 +1698,8 @@ The ```` element accepts the following sub-elements: |Score | Description | +======================+===================================================+ |delayed-nu-fission |Total production of delayed neutrons due to | - | |fission. | + | |fission. This score type is not used in the | + | |multi-group :ref:`energy_mode`. | +----------------------+---------------------------------------------------+ |nu-fission |Total production of neutrons due to fission. | +----------------------+---------------------------------------------------+ @@ -1656,6 +1728,8 @@ The ```` element accepts the following sub-elements: +----------------------+---------------------------------------------------+ |inverse-velocity |The flux-weighted inverse velocity where the | | |velocity is in units of centimeters per second. | + | |This score type is not used in the | + | |multi-group :ref:`energy_mode`. | +----------------------+---------------------------------------------------+ |kappa-fission |The recoverable energy production rate due to | | |fission. The recoverable energy is defined as the | diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index be8bc3cf8..1a0569148 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -356,7 +356,7 @@ Testing Build ------------- If you have ENDF/B-VII.1 cross sections from NNDC_ you can test your build. -Make sure the **CROSS_SECTIONS** environmental variable is set to the +Make sure the **OPENMC_CROSS_SECTIONS** environmental variable is set to the *cross_sections.xml* file in the *data/nndc* directory. There are two ways to run tests. The first is to use the Makefile present in the source directory and run the following: @@ -381,11 +381,17 @@ Cross Section Configuration --------------------------- In order to run a simulation with OpenMC, you will need cross section data for -each nuclide in your problem. Since OpenMC uses ACE format cross sections, you -can use nuclear data that was processed with NJOY_, such as that distributed -with MCNP_ or Serpent_. Several sources provide free processed ACE data as -described below. The TALYS-based evaluated nuclear data library, TENDL_, is also -openly available in ACE format. +each nuclide or material in your problem. OpenMC can be run in +continuous-energy or multi-group mode. + +In continuous-energy mode OpenMC uses ACE format cross sections; in this case +you can use nuclear data that was processed with NJOY_, such as that +distributed with MCNP_ or Serpent_. Several sources provide free processed +ACE data as described below. The TALYS-based evaluated nuclear data library, +TENDL_, is also openly available in ACE format. + +In multi-group mode, OpenMC utilizes an XML-based library format which can be +used to describe nuclide- or material-specific quantities. Using ENDF/B-VII.1 Cross Sections from NNDC ------------------------------------------- @@ -400,9 +406,10 @@ extract, and set up a confiuration file: cd openmc/data python get_nndc_data.py -At this point, you should set the :envvar:`CROSS_SECTIONS` environment variable -to the absolute path of the file ``openmc/data/nndc/cross_sections.xml``. This -cross section set is used by the test suite. +At this point, you should set the :envvar:`OPENMC_CROSS_SECTIONS` environment +variable to the absolute path of the file +``openmc/data/nndc/cross_sections.xml``. This cross section set is used by the +test suite. Using JEFF Cross Sections from OECD/NEA --------------------------------------- @@ -428,8 +435,8 @@ the following steps must be taken: 4. Additionally, you may need to change any occurrences of upper-case "ACE" within the ``cross_sections.xml`` file to lower-case. 5. Either set the :ref:`cross_sections` in a settings.xml file or the - :envvar:`CROSS_SECTIONS` environment variable to the absolute path of the - ``cross_sections.xml`` file. + :envvar:`OPENMC_CROSS_SECTIONS` environment variable to the absolute path of + the ``cross_sections.xml`` file. Using Cross Sections from MCNP ------------------------------ @@ -437,8 +444,9 @@ Using Cross Sections from MCNP To use cross sections distributed with MCNP, change the element in the ``cross_sections.xml`` file in the root directory of the OpenMC distribution to the location of the MCNP cross sections. Then, either set the -:ref:`cross_sections` in a settings.xml file or the :envvar:`CROSS_SECTIONS` -environment variable to the absolute path of the ``cross_sections.xml`` file. +:ref:`cross_sections` in a settings.xml file or the +:envvar:`OPENMC_CROSS_SECTIONS` environment variable to the absolute path of +the ``cross_sections.xml`` file. Using Cross Sections from Serpent --------------------------------- @@ -446,10 +454,21 @@ Using Cross Sections from Serpent To use cross sections distributed with Serpent, change the element in the ``cross_sections_serpent.xml`` file in the root directory of the OpenMC distribution to the location of the Serpent cross sections. Then, either set the -:ref:`cross_sections` in a settings.xml file or the :envvar:`CROSS_SECTIONS` -environment variable to the absolute path of the ``cross_sections_serpent.xml`` +:ref:`cross_sections` in a settings.xml file or the +:envvar:`OPENMC_CROSS_SECTIONS` environment variable to the absolute path of +the ``cross_sections_serpent.xml`` file. +Using Multi-Group Cross Sections +-------------------------------- + +Multi-group 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 the user has 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. + .. _NJOY: http://t2.lanl.gov/nis/codes.shtml .. _NNDC: http://www.nndc.bnl.gov/endf/b7.1/acefiles.html .. _NEA: http://www.oecd-nea.org diff --git a/docs/source/usersguide/mgxs_library.rst b/docs/source/usersguide/mgxs_library.rst new file mode 100644 index 000000000..a5d2ec0d0 --- /dev/null +++ b/docs/source/usersguide/mgxs_library.rst @@ -0,0 +1,302 @@ +.. _usersguide_mgxs_library: + +======================================== +Multi-Group Cross Section Library Format +======================================== + +OpenMC can be run in continuous-energy mode or multi-group mode, provided the +nuclear data is available. In continuous-energy mode, the +``cross_sections.xml`` file contains necessary meta-data for each data set, +including the name and a file system location where the complete library +can be found. In multi-group mode, this ``cross_sections.xml`` file contains +this same meta-data describing the nuclide or material, but also contains the +group-wise nuclear data. This portion of the manual describes the format of +the multi-group data library required to be used in the ``cross_sections.xml`` +file. + +Similar to the other input file types, the multi-group library is provided in +the XML_ format. This library must provide some meta-data about the library +itself (such as the number of groups and the group structure, etc.) as well as +the actual cross section data itself for each of the necessary nuclides or +materials. + +.. _XML: http://www.w3.org/XML/ + +------------------------------------------------ +MGXS Library Specification -- cross_sections.xml +------------------------------------------------ + +The multi-group library meta-data is contained within the groups_, +group_structure_, and inverse_velocities_ elements. +The actual multi-group data itself is contained within the xsdata_ element. + +.. _groups: + +```` Element +---------------------------------- + +The ```` element has no attributes and simply provides the number of +energy groups contained within the library. + + *Default*: None, this must be provided. + +.. _group_structure: + +```` Element +----------------------------- + +The ```` element has no attributes and should be provided as a +monotonically increasing list of bounding energies, in MeV, for a number of +groups. To provide proper energy boundaries, the length of the data within the +```` element should be one more than the number of groups in +the problem. For example, a two-group problem could be specified as: + +.. code-block:: xml + + 0.0 0.625E-6 20.0 + +*Default*: None, this must be provided. + +.. _inverse_velocities: + +```` Element +-------------------------------- + +The ```` element optionally indicates the average +inverse velocity corresponding to each of the groups in the problem. +This element should therefore be an array with a length which matches the +number of groups set in the groups_ element. + +*Default*: Should this be needed by the presence of an ``inverse-velocity`` +score in the ``tallies.xml`` file and not provided in this element, OpenMC +will simply convert the group mid-point energy to an inverse of the velocity +and use this information for tallying. + +.. _xsdata: + +```` Element +-------------------- + +The ```` element contains the nuclide or material-specific meta-data as +well as the actual cross section data. The following are the +attributes/sub-elements required to describe the meta-data: + + :name: + The name of the microscopic or macroscopic data set. An extension to the + name must be provided (e.g., the ``.300K`` in ``UO2.300K``). The name and + extension together must be twelve or less characters in length. This + extension must follow a period and be five characters or less in length. + similar to the equivalent in the continuous-energy ``cross_sections.xml`` + file, is used to denote variants of the particular nuclide or material of + interest (i.e. the ``UO2`` data in this example could have been generated + at a temperature of 300K). + + *Default*: None, this must be provided. + + :alias: + An alternative name to use for the microscopic or macroscopic data set. + + *Default*: If no alias is provided, it will adopt the value of ``name``. + + :kT: + The temperature times Boltzmann's constant (in units of MeV) at which the + data was generated. + + *Default*: Room temperature, 2.53E-8 MeV + + :fissionable: + This element states whether or not the data in question is fissionable. + Accepted values are "true" or "false". + + *Default*: None, this element must be provided. + + :representation: + This element provides the method used to generate and represent the + multi-group cross sections. That is, whether they were generated with + scalar flux weighting (or reduced to an equivalent representation) + and thus are angle-independent, or if the data was generated with angular + dependent fluxes and thus the data is angle-dependent. The options are + either "isotropic" or "angle". + + *Default*: "isotropic" + + :num_azimuthal: + This element provides the number of equal width angular bins that the + azimuthal angular domain is subdivided in the case of angle-dependent + cross sections (i.e., "angle" is passed to the ``representation`` element). + Note that these bins are equal in azimuthal angle widths, not equal in the + cosine of the azimuthal angle widths. + + *Default*: If ``representation`` is "angle", this must be provided. This + parameter is not used for other ``representation`` types. + + :num_polar: + This element provides the number of equal width angular bins that the + polar angular domain is subdivided in the case of angle-dependent + cross sections (i.e., "angle" is passed to the ``representation`` element). + Note that these bins are equal in polar angle widths, not equal in the + cosine of the polar angle widths. + + + *Default*: If ``representation`` is "angle", this must be provided. This + parameter is not used for other ``representation`` types. + + :scatt_type: + This element provides the representation of the angular distribution + associated with each group-to-group transfer probability. The options are + either "legendre", "histogram", or "tabular". + The "legendre" option means the angular distribution has been + expanded via Legendre polynomials of the order provided in the "order" + element. + The "histogram" option means the angular distribution is provided in + an equi-width histogram format with a number of bins as provided in the + "order" element. This is useful when the angular distribution was + obtained from a Monte Carlo tally and thus is natively in the histogram + format. + The "tabular" option means the angular distribution is provided in an + equi-spaced point-wise representation. + + *Default*: "legendre" + + :order: + This element provides either the Legendre order, number of bins, or number + of points used to describe the angular distribution associated with each + group-to-group transfer probability. The specific meaning of this bin + depends upon the value of ``scatt_type`` as discussed above. + + *Default*: None, this element must be provided. + + :tabular_legendre: + This optional element is used to set how the Legendre scattering kernel, if + provided via the ``scatt_type`` element above, is represented and thus used + during the scattering process. Specifically, the options are to either + convert the Legendre expansion to a tabular representation or leave it as + a set of Legendre coefficients. Converting to a tabular representation will + cost memory but is likely to decrease runtime compared to leaving as a + set of Legendre coefficients. This element has the following + attributes/sub-elements: + + :enable: + This attribute/sub-element denotes whether or not the conversion to the + tabular format should be performed or not. A value of "true" means + the conversion should be performed, "false" means it should not. + + *Default*: "true" + + :num_points: + If the conversion is to take place the number of tabular points is + required. This attribute/sub-element allows the user to set the desired + number of points. + + *Default*: 33 + + The following attributes/sub-elements are the cross section values to + be used during the transport process. + + :total: + This element requires the group-wise total cross section ordered by + increasing group index (i.e., fast to thermal). If ``representation`` is + "isotropic", then the length of this list should equal the number of + groups described in the ``groups`` element. If ``representation`` is + "angle", then the length of this list should equal the number of groups + times the number of azimuthal angles times the number of polar angles, + with the inner-dimension being groups, intermediate-dimension being + azimuthal angles and outer-dimension being the polar angles. + + *Default*: If not provided, it will be determined by summing the + absorption and scattering cross sections. + + :absorption: + This element requires the group-wise absorption cross section ordered by + increasing group index (i.e., fast to thermal). If ``representation`` is + "isotropic", then the length of this list should equal the number of + groups described in the ``groups`` element. If ``representation`` is + "angle", then the length of this list should equal the number of groups + times the number of azimuthal angles times the number of polar angles, + with the inner-dimension being groups, intermediate-dimension being + azimuthal angles and outer-dimension being the polar angles. + + *Default*: None, this must be provided. + + :scatter: + This element requires the scattering moment matrices presented with the + columns representing incoming group and rows representing the outgoing + group. That is, down-scatter will be above the diagonal of the resultant + matrix. This matrix is repeated for every Legendre order (in order of + increasing orders) if ``scatt_type`` is "legendre"; otherwise, this + matrix is repeated for every bin of the histogram or tabular + representation. Finally, if ``representation`` is "angle", the above + is repeated for every azimuthal angle and every polar angle, in that + order. + + *Default*: None, this must be provided. + + :multiplicity: + This element provides the ratio of neutrons produced in scattering + collisions to the neutrons which undergo scattering collisions; that is, + the multiplicity provides the code with a scaling factor to account for + neutrons being produced in (n,xn) reactions. This information is assumed + isotropic and therefore does not need to be repeated for every Legendre + moment or histogram/tabular bin. This matrix follows the same arrangement + as described for the ``scatter`` element, with the exception of the + data needed to provide the scattering type information. + + *Default*: Multiplicities of 1.0 are assumed (i.e., (n,xn) reactions are + neglected). + + The following fission-specific data are only needed should ``fissionable`` + be "true". + + :fission: + This element requires the group-wise fission cross section ordered by + increasing group index (i.e., fast to thermal). If ``representation`` is + "isotropic", then the length of this list should equal the number of + groups described in the ``groups`` element. If ``representation`` is + "angle", then the length of this list should equal the number of groups + times the number of azimuthal angles times the number of polar angles, + with the inner-dimension being groups, intermediate-dimension being + azimuthal angles and outer-dimension being the polar angles. + + *Default*: None, this is required only if fission tallies are + requested and the material is fissionable. + + :kappa_fission: + This element requires the group-wise kappa-fission cross section ordered by + increasing group index (i.e., fast to thermal). If ``representation`` is + "isotropic", then the length of this list should equal the number of + groups described in the ``groups`` element. If ``representation`` is + "angle", then the length of this list should equal the number of groups + times the number of azimuthal angles times the number of polar angles, + with the inner-dimension being groups, intermediate-dimension being + azimuthal angles and outer-dimension being the polar angles. + + *Default*: None, this is required only if kappa_fission tallies are + requested and the material is fissionable. + + :chi: + This element requires the group-wise fission spectra ordered by + increasing group index (i.e., fast to thermal). This element should be + used if making the common approximation that the fission spectra does + not depend on incoming energy. If the user does not wish to make this + approximation, then this should not be provided and this information + included in the ``nu_fission`` element instead. If ``representation`` is + "isotropic", then the length of this list should equal the number of + groups described in the ``groups`` element. If ``representation`` is + "angle", then the length of this list should equal the number of groups + times the number of azimuthal angles times the number of polar angles, + with the inner-dimension being groups, intermediate-dimension being + azimuthal angles and outer-dimension being the polar angles. + + *Default*: None, either this element is provided or ``nu_fission`` is + provided in fission matrix form, or the material is not fissionable. + + :nu_fission: + This element provides either the group-wise fission production cross + section vector (i.e., if ``chi`` is provided), or is the group-wise fission + production matrix. If providing the vector, it should be ordered the same + as the ``fission`` data. If providing the matrix, it should be ordered + the same as the ``multiplicity`` matrix. + + *Default*: None, either this element must be provided if the material + is fissionable. + diff --git a/docs/source/usersguide/output/particle_restart.rst b/docs/source/usersguide/output/particle_restart.rst index e0d89a515..70f00a930 100644 --- a/docs/source/usersguide/output/particle_restart.rst +++ b/docs/source/usersguide/output/particle_restart.rst @@ -46,7 +46,8 @@ The current revision of the particle restart file format is 1. **/energy** (*double*) - Energy of the particle in MeV. + Energy of the particle in MeV for continuous-energy mode, or the energy + group of the particle for multi-group mode. **/xyz** (*double[3]*) diff --git a/docs/source/usersguide/output/source.rst b/docs/source/usersguide/output/source.rst index 2981b0f66..53841a5eb 100644 --- a/docs/source/usersguide/output/source.rst +++ b/docs/source/usersguide/output/source.rst @@ -15,5 +15,6 @@ is that documented here. **/source_bank** (Compound type) Source bank information for each particle. The compound type has fields - ``wgt``, ``xyz``, ``uvw``, and ``E`` which represent the weight, position, - direction, and energy of the source particle, respectively. + ``wgt``, ``xyz``, ``uvw``, ``E``, and ``delayed_group``, which + represent the weight, position, direction, energy, energy group, and + delayed_group of the source particle, respectively. diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index 15bc79f73..225161965 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -4,7 +4,7 @@ State Point File Format ======================= -The current revision of the statepoint file format is 14. +The current revision of the statepoint file format is 15. **/filetype** (*char[]*) @@ -39,6 +39,12 @@ The current revision of the statepoint file format is 14. Pseudo-random number generator seed. +**/run_CE** (*int*) + + Flag to denote continuous-energy or multi-group mode. A value of 1 + indicates a continuous-energy run while a value of 0 indicates a + multi-group run. + **/run_mode** (*char[]*) Run mode used. A value of 1 indicates a fixed-source run and a value of 2 @@ -251,5 +257,6 @@ if (run_mode == 'k-eigenvalue' and source_present > 0) **/source_bank** (Compound type) Source bank information for each particle. The compound type has fields - ``wgt``, ``xyz``, ``uvw``, and ``E`` which represent the weight, - position, direction, and energy of the source particle, respectively. + ``wgt``, ``xyz``, ``uvw``, ``E``, ``g``, and ``delayed_group``, which + represent the weight, position, direction, energy, energy group, and + delayed_group of the source particle, respectively. diff --git a/examples/python/pincell_multigroup/build-xml.py b/examples/python/pincell_multigroup/build-xml.py new file mode 100644 index 000000000..ff75a64d9 --- /dev/null +++ b/examples/python/pincell_multigroup/build-xml.py @@ -0,0 +1,180 @@ +import openmc +import openmc.mgxs +from openmc.source import Source +from openmc.stats import Box +import numpy as np + +############################################################################### +# Simulation Input File Parameters +############################################################################### + +# OpenMC simulation parameters +batches = 100 +inactive = 10 +particles = 1000 + +############################################################################### +# Exporting to OpenMC mg_cross_sections.xml File +############################################################################### + +# Instantiate the energy group data +groups = openmc.mgxs.EnergyGroups(group_edges=[1E-11, 0.0635E-6, 10.0E-6, + 1.0E-4, 1.0E-3, 0.5, 1.0, 20.0]) + +# Instantiate the 7-group (C5G7) cross section data +uo2_xsdata = openmc.XSdata('UO2.300K', groups) +uo2_xsdata.order = 0 +uo2_xsdata.total = np.array([0.1779492, 0.3298048, 0.4803882, 0.5543674, + 0.3118013, 0.3951678, 0.5644058]) +uo2_xsdata.absorption = np.array([8.0248E-03, 3.7174E-03, 2.6769E-02, 9.6236E-02, + 3.0020E-02, 1.1126E-01, 2.8278E-01]) +scatter = [[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]] +uo2_xsdata.scatter = np.array(scatter[:][:]) +uo2_xsdata.fission = np.array([7.21206E-03, 8.19301E-04, 6.45320E-03, + 1.85648E-02, 1.78084E-02, 8.30348E-02, + 2.16004E-01]) +uo2_xsdata.nu_fission = np.array([2.005998E-02, 2.027303E-03, 1.570599E-02, + 4.518301E-02, 4.334208E-02, 2.020901E-01, + 5.257105E-01]) +uo2_xsdata.chi = np.array([5.8791E-01, 4.1176E-01, 3.3906E-04, 1.1761E-07, + 0.0000E+00, 0.0000E+00, 0.0000E+00]) + +h2o_xsdata = openmc.XSdata('LWTR.300K', groups) +h2o_xsdata.order = 0 +h2o_xsdata.total = np.array([0.15920605, 0.412969593, 0.59030986, 0.58435, + 0.718, 1.2544497, 2.650379]) +h2o_xsdata.absorption = np.array([6.0105E-04, 1.5793E-05, 3.3716E-04, + 1.9406E-03, 5.7416E-03, 1.5001E-02, + 3.7239E-02]) +scatter = [[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000], + [0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010], + [0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034], + [0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390], + [0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]] +h2o_xsdata.scatter = np.array(scatter) + +mg_cross_sections_file = openmc.MGXSLibraryFile(groups) +mg_cross_sections_file.add_xsdatas([uo2_xsdata,h2o_xsdata]) +mg_cross_sections_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC materials.xml File +############################################################################### + +# Instantiate some Macroscopic Data +uo2_data = openmc.Macroscopic('UO2', '300K') +h2o_data = openmc.Macroscopic('LWTR', '300K') + +# Instantiate some Materials and register the appropriate Macroscopic objects +uo2 = openmc.Material(material_id=1, name='UO2 fuel') +uo2.set_density('macro', 1.0) +uo2.add_macroscopic(uo2_data) + +water = openmc.Material(material_id=2, name='Water') +water.set_density('macro', 1.0) +water.add_macroscopic(h2o_data) + +# Instantiate a MaterialsFile, register all Materials, and export to XML +materials_file = openmc.MaterialsFile() +materials_file.default_xs = '300K' +materials_file.add_materials([uo2, water]) +materials_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC geometry.xml File +############################################################################### + +# Instantiate ZCylinder surfaces +fuel_or = openmc.ZCylinder(surface_id=1, x0=0, y0=0, R=0.54, name='Fuel OR') +left = openmc.XPlane(surface_id=4, x0=-0.63, name='left') +right = openmc.XPlane(surface_id=5, x0=0.63, name='right') +bottom = openmc.YPlane(surface_id=6, y0=-0.63, name='bottom') +top = openmc.YPlane(surface_id=7, y0=0.63, name='top') + +left.boundary_type = 'reflective' +right.boundary_type = 'reflective' +top.boundary_type = 'reflective' +bottom.boundary_type = 'reflective' + +# Instantiate Cells +fuel = openmc.Cell(cell_id=1, name='cell 1') +moderator = openmc.Cell(cell_id=2, name='cell 2') + +# Use surface half-spaces to define regions +fuel.region = -fuel_or +moderator.region = +fuel_or & +left & -right & +bottom & -top + +# Register Materials with Cells +fuel.fill = uo2 +moderator.fill = water + +# Instantiate Universe +root = openmc.Universe(universe_id=0, name='root universe') + +# Register Cells with Universe +root.add_cells([fuel, moderator]) + +# Instantiate a Geometry and register the root Universe +geometry = openmc.Geometry() +geometry.root_universe = root + +# Instantiate a GeometryFile, register Geometry, and export to XML +geometry_file = openmc.GeometryFile() +geometry_file.geometry = geometry +geometry_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC settings.xml File +############################################################################### + +# Instantiate a SettingsFile, set all runtime parameters, and export to XML +settings_file = openmc.SettingsFile() +settings_file.energy_mode = "multi-group" +settings_file.cross_sections = "./mg_cross_sections.xml" +settings_file.batches = batches +settings_file.inactive = inactive +settings_file.particles = particles +settings_file.source = Source(space=Box([-0.63, -0.63, -1.], [0.63, 0.63, 1.])) + +############################################################################### +# Exporting to OpenMC tallies.xml File +############################################################################### + +# Instantiate a tally mesh +mesh = openmc.Mesh(mesh_id=1) +mesh.type = 'regular' +mesh.dimension = [100, 100, 1] +mesh.lower_left = [-0.63, -0.63, -1.e50] +mesh.upper_right = [0.63, 0.63, 1.e50] + +# Instantiate some tally Filters +energy_filter = openmc.Filter(type='energy', + bins=[1E-11, 0.0635E-6, 10.0E-6, 1.0E-4, 1.0E-3, + 0.5, 1.0, 20.0]) +mesh_filter = openmc.Filter() +mesh_filter.mesh = mesh + +# Instantiate the Tally +tally = openmc.Tally(tally_id=1, name='tally 1') +tally.add_filter(energy_filter) +tally.add_filter(mesh_filter) +tally.add_score('flux') +tally.add_score('fission') +tally.add_score('nu-fission') + +# Instantiate a TalliesFile, register all Tallies, and export to XML +tallies_file = openmc.TalliesFile() +tallies_file.add_mesh(mesh) +tallies_file.add_tally(tally) +tallies_file.export_to_xml() diff --git a/examples/xml/pincell_multigroup/geometry.xml b/examples/xml/pincell_multigroup/geometry.xml new file mode 100644 index 000000000..94c70cb34 --- /dev/null +++ b/examples/xml/pincell_multigroup/geometry.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/examples/xml/pincell_multigroup/materials.xml b/examples/xml/pincell_multigroup/materials.xml new file mode 100644 index 000000000..696116654 --- /dev/null +++ b/examples/xml/pincell_multigroup/materials.xml @@ -0,0 +1,54 @@ + + + + 300K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/xml/pincell_multigroup/mg_cross_sections.xml b/examples/xml/pincell_multigroup/mg_cross_sections.xml new file mode 100644 index 000000000..3c671a192 --- /dev/null +++ b/examples/xml/pincell_multigroup/mg_cross_sections.xml @@ -0,0 +1,383 @@ + + + + 7 + + 1E-11 0.0635E-6 10.0E-6 1.0E-4 1.0E-3 0.5 1.0 20.0 + + + + + + UO2.300K + UO2.300K + 2.53E-8 + 0 + true + + isotropic + + + + 8.0248E-03 3.7174E-03 2.6769E-02 9.6236E-02 3.0020E-02 1.1126E-01 2.8278E-01 + + + + 2.005998E-02 2.027303E-03 1.570599E-02 4.518301E-02 4.334208E-02 2.020901E-01 5.257105E-01 + + + + 5.8791E-01 4.1176E-01 3.3906E-04 1.1761E-07 0.0000E+00 0.0000E+00 0.0000E+00 + + + 7.21206E-03 8.19301E-04 6.45320E-03 1.85648E-02 1.78084E-02 8.30348E-02 2.16004E-01 + + + + + + 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + + + + + + 0.1275370 0.0423780 0.0000094 0.0000000 0.0000000 0.0000000 0.0000000 + 0.0000000 0.3244560 0.0016314 0.0000000 0.0000000 0.0000000 0.0000000 + 0.0000000 0.0000000 0.4509400 0.0026792 0.0000000 0.0000000 0.0000000 + 0.0000000 0.0000000 0.0000000 0.4525650 0.0055664 0.0000000 0.0000000 + 0.0000000 0.0000000 0.0000000 0.0001253 0.2714010 0.0102550 0.0000000 + 0.0000000 0.0000000 0.0000000 0.0000000 0.0012968 0.2658020 0.0168090 + 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0085458 0.2730800 + + + + + 0.1779492 0.3298048 0.4803882 0.5543674000000001 0.3118013 0.39516779999999996 0.5644058 + + + + + + + MOX1.300K + MOX1.300K + 2.53E-8 + 0 + true + + + + 8.4339E-03 3.7577E-03 2.7970E-02 1.0421E-01 1.3994E-01 4.0918E-01 4.0935E-01 + + + + 1.27888062E-02 8.95701528E-03 7.37557218E-06 2.55837033E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 1.49041240E-03 1.04385401E-03 8.59552023E-07 2.98153464E-10 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 9.56411400E-03 6.69850756E-03 5.51582469E-06 1.91327830E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 3.84928781E-02 2.69596154E-02 2.21996483E-05 7.70040890E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 1.80629998E-02 1.26509513E-02 1.04173100E-05 3.61346022E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 3.91930789E-01 2.74500216E-01 2.26034688E-04 7.84048241E-08 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 4.19762096E-01 2.93992687E-01 2.42085585E-04 8.39724109E-08 0.00000000E+00 0.00000000E+00 0.00000000E+00 + + + + 7.62704E-03 8.76898E-04 5.69835E-03 2.28872E-02 1.07635E-02 2.32757E-01 2.48968E-01 + + + + + 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + + + + + + 1.27537000E-01 4.23780000E-02 9.43740000E-06 5.51630000E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 3.24456000E-01 1.63140000E-03 3.14270000E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 4.50940000E-01 2.67920000E-03 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 4.52565000E-01 5.56640000E-03 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 1.25250000E-04 2.71401000E-01 1.02550000E-02 1.00210000E-08 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 1.29680000E-03 2.65802000E-01 1.68090000E-02 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 8.54580000E-03 2.73080000E-01 + + + + 0.1783583429163 0.3298451031427 0.4815892 0.5623414 0.421721260021 0.6930878 0.6909757999999999 + + + + + + + MOX2.300K + MOX2.300K + 2.53E-8 + 0 + true + + + + 0.0090657 0.0042967 0.032881 0.12203 0.18298 0.56846 0.58521 + + + + 1.40004593E-02 9.80563205E-03 8.07435789E-06 2.80075866E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 2.26856185E-03 1.58885378E-03 1.30832709E-06 4.53820413E-10 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 1.41886199E-02 9.93741584E-03 8.18287404E-06 2.83839974E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 5.54788444E-02 3.88562347E-02 3.19958106E-05 1.10984111E-08 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 2.69085702E-02 1.88462058E-02 1.55187355E-05 5.38299559E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 5.45687127E-01 3.82187973E-01 3.14709185E-04 1.09163414E-07 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 6.13307712E-01 4.29548032E-01 3.53707392E-04 1.22690752E-07 0.00000000E+00 0.00000000E+00 0.00000000E+00 + + + + 0.00825446 0.00132565 0.00842156 0.032873 0.0159636 0.323794 0.362803 + + + + + 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + + + + + + 1.30457000E-01 4.17920000E-02 8.51050000E-06 5.13290000E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 3.28428000E-01 1.64360000E-03 2.20170000E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 4.58371000E-01 2.53310000E-03 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 4.63709000E-01 5.47660000E-03 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 1.76190000E-04 2.82313000E-01 8.72890000E-03 9.00160000E-09 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 2.27600000E-03 2.49751000E-01 1.31140000E-02 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 8.86450000E-03 2.59529000E-01 + + + + 0.1813232156329 0.3343683022017 0.4937851 0.5912156 0.47419809900160004 0.833601 0.8536035 + + + + + + + MOX3.300K + MOX3.300K + 2.53E-8 + 0 + true + + + + 9.48620000E-03 4.65560000E-03 3.62400000E-02 1.32720000E-01 2.08400000E-01 6.58700000E-01 6.90170000E-01 + + + + 1.48071013E-02 1.03705874E-02 8.53956516E-06 2.96212546E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 2.78640474E-03 1.95154023E-03 1.60697792E-06 5.57413653E-10 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 1.73304404E-02 1.21378819E-02 9.99482763E-06 3.46691346E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 6.59928975E-02 4.62200600E-02 3.80594850E-05 1.32017225E-08 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 3.25131926E-02 2.27715674E-02 1.87510386E-05 6.50418701E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 6.32002662E-01 4.42641588E-01 3.64489161E-04 1.26430632E-07 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 7.28595687E-01 5.10293344E-01 4.20196380E-04 1.45753838E-07 0.00000000E+00 0.00000000E+00 0.00000000E+00 + + + + 8.67209000E-03 1.62426000E-03 1.02716000E-02 3.90447000E-02 1.92576000E-02 3.74888000E-01 4.30599000E-01 + + + + + 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + + + + + + 1.31504000E-01 4.20460000E-02 8.69720000E-06 5.19380000E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 3.30403000E-01 1.64630000E-03 2.60060000E-09 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 4.61792000E-01 2.47490000E-03 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 4.68021000E-01 5.43300000E-03 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 1.85970000E-04 2.85771000E-01 8.39730000E-03 8.92800000E-09 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 2.39160000E-03 2.47614000E-01 1.23220000E-02 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 8.96810000E-03 2.56093000E-01 + + + + 1.83044902E-01 3.36704903E-01 5.00506900E-01 6.06174000E-01 5.02754279E-01 9.21027600E-01 9.55231100E-01 + + + + + + + FC.300K + FC.300K + 2.53E-8 + 0 + true + + + + 5.1132E-04 7.5813E-05 3.1643E-04 1.1675E-03 3.3977E-03 9.1886E-03 2.3244E-02 + + + + 1.323401E-08 1.434500E-08 1.128599E-06 1.276299E-05 3.538502E-07 1.740099E-06 5.063302E-06 + + + + 5.8791E-01 4.1176E-01 3.3906E-04 1.1761E-07 0.0000E+00 0.0000E+00 0.0000E+00 + + + + 4.79002E-09 5.82564E-09 4.63719E-07 5.24406E-06 1.45390E-07 7.14972E-07 2.08041E-06 + + + + + 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + + + + + + 6.61659000E-02 5.90700000E-02 2.83340000E-04 1.46220000E-06 2.06420000E-08 0.00000000E00 0.00000000E00 + 0.00000000E00 2.40377000E-01 5.24350000E-02 2.49900000E-04 1.92390000E-05 2.98750000E-06 4.21400000E-07 + 0.00000000E00 0.00000000E00 1.83425000E-01 9.22880000E-02 6.93650000E-03 1.07900000E-03 2.05430000E-04 + 0.00000000E00 0.00000000E00 0.00000000E00 7.90769000E-02 1.69990000E-01 2.58600000E-02 4.92560000E-03 + 0.00000000E00 0.00000000E00 0.00000000E00 3.73400000E-05 9.97570000E-02 2.06790000E-01 2.44780000E-02 + 0.00000000E00 0.00000000E00 0.00000000E00 0.00000000E00 9.17420000E-04 3.16774000E-01 2.38760000E-01 + 0.00000000E00 0.00000000E00 0.00000000E00 0.00000000E00 0.00000000E00 4.97930000E-02 1.09910000E00 + + + + 1.26032048E-01 2.93160367E-01 2.84250824E-01 2.81025244E-01 3.34460185E-01 5.65640735E-01 1.17213908E00 + + + + + + + GT.300K + GT.300K + 2.53E-8 + 0 + false + + + + 5.11320000E-04 7.58010000E-05 3.15720000E-04 1.15820000E-03 3.39750000E-03 9.18780000E-03 2.32420000E-02 + + + + + + 6.61659000E-02 5.90700000E-02 2.83340000E-04 1.46220000E-06 2.06420000E-08 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 2.40377000E-01 5.24350000E-02 2.49900000E-04 1.92390000E-05 2.98750000E-06 4.21400000E-07 + 0.00000000E+00 0.00000000E+00 1.83297000E-01 9.23970000E-02 6.94460000E-03 1.08030000E-03 2.05670000E-04 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 7.88511000E-02 1.70140000E-01 2.58810000E-02 4.92970000E-03 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 3.73330000E-05 9.97372000E-02 2.06790000E-01 2.44780000E-02 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 9.17260000E-04 3.16765000E-01 2.38770000E-01 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 4.97920000E-02 1.09912000E+00 + + + + 1.26032043E-01 2.93160349E-01 2.84240290E-01 2.80960000E-01 3.34440033E-01 5.65640060E-01 1.17215400E+00 + + + + + + LWTR.300K + LWTR.300K + 2.53E-8 + 0 + false + + + + 6.0105E-04 1.5793E-05 3.3716E-04 1.9406E-03 5.7416E-03 1.5001E-02 3.7239E-02 + + + + + + 0.0444777 0.1134000 0.0007235 0.0000037 0.0000001 0.0000000 0.0000000 + 0.0000000 0.2823340 0.1299400 0.0006234 0.0000480 0.0000074 0.0000010 + 0.0000000 0.0000000 0.3452560 0.2245700 0.0169990 0.0026443 0.0005034 + 0.0000000 0.0000000 0.0000000 0.0910284 0.4155100 0.0637320 0.0121390 + 0.0000000 0.0000000 0.0000000 0.0000714 0.1391380 0.5118200 0.0612290 + 0.0000000 0.0000000 0.0000000 0.0000000 0.0022157 0.6999130 0.5373200 + 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.1324400 2.4807000 + + + + 0.15920605 0.41296959299999997 0.59030986 0.5843499999999999 0.7180000000000001 1.2544497000000001 2.650379 + + + + + + + CR.300K + CR.300K + 2.53E-8 + 0 + false + + + + 1.70490000E-03 8.36224000E-03 8.37901000E-02 3.97797000E-01 6.98763000E-01 9.29508000E-01 1.17836000E+00 + + + + + + 1.70563000E-01 4.44012000E-02 9.83670000E-05 1.27786000E-07 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 4.71050000E-01 6.85480000E-04 3.91395000E-10 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 8.01859000E-01 7.20132000E-04 0.00000000E+00 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 5.70752000E-01 1.46015000E-03 0.00000000E+00 0.00000000E+00 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 6.55562000E-05 2.07838000E-01 3.81486000E-03 3.69760000E-09 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 1.02427000E-03 2.02465000E-01 4.75290000E-03 + 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 3.53043000E-03 6.58597000E-01 + + + + 2.16767595E-01 4.80097720E-01 8.86369232E-01 9.70009150E-01 9.10481420E-01 1.13775017E+00 1.84048743E+00 + + + diff --git a/examples/xml/pincell_multigroup/plots.xml b/examples/xml/pincell_multigroup/plots.xml new file mode 100644 index 000000000..cbb8e532c --- /dev/null +++ b/examples/xml/pincell_multigroup/plots.xml @@ -0,0 +1,28 @@ + + + + + 1 + mat + material + 0 0 0 + 1.26 1.26 + slice + 1000 1000 + + + + + + + + 2 + cell + cell + 0 0 0 + 1.26 1.26 + slice + 1000 1000 + + + diff --git a/examples/xml/pincell_multigroup/settings.xml b/examples/xml/pincell_multigroup/settings.xml new file mode 100644 index 000000000..dfd2fac81 --- /dev/null +++ b/examples/xml/pincell_multigroup/settings.xml @@ -0,0 +1,40 @@ + + + + multi-group + + + + 100 + 10 + 1000 + + + + + + + -0.63 -0.63 -1E50 + 0.63 0.63 1E50 + + + + + + true + true + true + + + false + + ./mg_cross_sections.xml + + diff --git a/examples/xml/pincell_multigroup/tallies.xml b/examples/xml/pincell_multigroup/tallies.xml new file mode 100644 index 000000000..df65b461d --- /dev/null +++ b/examples/xml/pincell_multigroup/tallies.xml @@ -0,0 +1,13 @@ + + + + 100 100 1 + -0.63 -0.63 -1e+50 + 0.63 0.63 1e+50 + + + + + flux fission nu-fission + + diff --git a/openmc/__init__.py b/openmc/__init__.py index 397d9f3e2..5bdc3f089 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -1,11 +1,13 @@ from openmc.element import * from openmc.geometry import * from openmc.nuclide import * +from openmc.macroscopic import * from openmc.material import * from openmc.plots import * from openmc.settings import * from openmc.surface import * from openmc.universe import * +from openmc.mgxs_library import * from openmc.mesh import * from openmc.filter import * from openmc.trigger import * diff --git a/openmc/checkvalue.py b/openmc/checkvalue.py index 787052f5d..303f78407 100644 --- a/openmc/checkvalue.py +++ b/openmc/checkvalue.py @@ -127,7 +127,7 @@ def check_iterable_type(name, value, expected_type, min_depth=1, max_depth=1): # But first, have we exceeded the max depth? if len(tree) > max_depth: msg = 'Error setting {0}: Found an iterable at {1}, items '\ - 'in that iterable excceed the maximum depth of {2}' \ + 'in that iterable exceed the maximum depth of {2}' \ .format(name, ind_str, max_depth) raise ValueError(msg) diff --git a/openmc/macroscopic.py b/openmc/macroscopic.py new file mode 100644 index 000000000..9f67a50ba --- /dev/null +++ b/openmc/macroscopic.py @@ -0,0 +1,85 @@ +from numbers import Integral +import sys + +from openmc.checkvalue import check_type + +if sys.version_info[0] >= 3: + basestring = str + + +class Macroscopic(object): + """A Macroscopic object that can be used in a material. + + Parameters + ---------- + name : str + Name of the macroscopic data, e.g. UO2 + xs : str + Cross section identifier, e.g. 71c + + Attributes + ---------- + name : str + Name of the nuclide, e.g. UO2 + xs : str + Cross section identifier, e.g. 71c + + """ + + def __init__(self, name='', xs=None): + # Initialize class attributes + self._name = '' + self._xs = None + + # Set the Material class attributes + self.name = name + + if xs is not None: + self.xs = xs + + def __eq__(self, other): + if isinstance(other, Macroscopic): + if self._name != other._name: + return False + elif self._xs != other._xs: + return False + else: + return True + elif isinstance(other, basestring) and other == self.name: + return True + else: + return False + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self._name, self._xs)) + + def __repr__(self): + string = 'Nuclide - {0}\n'.format(self._name) + string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs) + return string + + @property + def name(self): + return self._name + + @property + def xs(self): + return self._xs + + @name.setter + def name(self, name): + check_type('name', name, basestring) + self._name = name + + @xs.setter + def xs(self, xs): + check_type('cross-section identifier', xs, basestring) + self._xs = xs + + def __repr__(self): + string = 'Macroscopic - {0}\n'.format(self._name) + string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self.xs) + return string diff --git a/openmc/material.py b/openmc/material.py index 542078c7c..e51586205 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -22,14 +22,15 @@ def reset_auto_material_id(): # Units for density supported by OpenMC -DENSITY_UNITS = ['g/cm3', 'g/cc', 'kg/cm3', 'atom/b-cm', 'atom/cm3', 'sum'] +DENSITY_UNITS = ['g/cm3', 'g/cc', 'kg/cm3', 'atom/b-cm', 'atom/cm3', 'sum', + 'macro'] # Constant for density when not needed NO_DENSITY = 99999. class Material(object): - """A material composed of a collection of nuclides/elements that can be + """A material composed of a collection of nuclides/elements that can be assigned to a region of space. Parameters @@ -49,7 +50,8 @@ class Material(object): Density of the material (units defined separately) density_units : str Units used for `density`. Can be one of 'g/cm3', 'g/cc', 'kg/cm3', - 'atom/b-cm', 'atom/cm3', or 'sum'. + 'atom/b-cm', 'atom/cm3', 'sum', or 'macro'. The 'macro' unit only + applies in the case of a multi-group calculation. """ @@ -65,6 +67,10 @@ class Material(object): # Values - tuple (nuclide, percent, percent type) self._nuclides = OrderedDict() + # The single instance of Macroscopic data present in this material + # (only one is allowed, hence this is different than _nuclides, etc) + self._macroscopic = None + # An ordered dictionary of Elements (order affects OpenMC results) # Keys - Element names # Values - tuple (element, percent, percent type) @@ -128,6 +134,10 @@ class Material(object): string += '{0: <16}'.format('\t{0}'.format(nuclide)) string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type) + if self._macroscopic is not None: + string += '{0: <16}\n'.format('\tMacroscopic Data') + string += '{0: <16}'.format('\t{0}'.format(self._macroscopic)) + string += '{0: <16}\n'.format('\tElements') for element in self._elements: @@ -149,6 +159,7 @@ class Material(object): clone._density = self._density clone._density_units = self._density_units clone._nuclides = deepcopy(self._nuclides, memo) + clone._macroscopic = self._macroscopic clone._elements = deepcopy(self._elements, memo) clone._sab = deepcopy(self._sab, memo) clone._convert_to_distrib_comps = self._convert_to_distrib_comps @@ -268,6 +279,11 @@ class Material(object): """ + if self._macroscopic is not None: + msg = 'Unable to add a Nuclide to Material ID="{0}" as a ' \ + 'macroscopic data-set has already been added'.format(self._id) + raise ValueError(msg) + if not isinstance(nuclide, (openmc.Nuclide, str)): msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \ 'non-Nuclide value "{1}"'.format(self._id, nuclide) @@ -311,6 +327,64 @@ class Material(object): if nuclide._name in self._nuclides: del self._nuclides[nuclide._name] + def add_macroscopic(self, macroscopic): + """Add a macroscopic to the material + + Parameters + ---------- + macroscopic : str or Macroscopic + Macroscopic to add + + """ + + # Ensure no nuclides, elements, or sab are added since these would be + # incompatible with macroscopics + if self._nuclides or self._elements or self._sab: + msg = 'Unable to add a Macroscopic data set to Material ID="{0}" ' \ + 'with a macroscopic value "{1}" as an incompatible data ' \ + 'member (i.e., nuclide, element, or S(a,b) table) ' \ + 'has already been added'.format(self._id, macroscopic) + raise ValueError(msg) + + if not isinstance(macroscopic, (openmc.Macroscopic, basestring)): + msg = 'Unable to add a Macroscopic to Material ID="{0}" with a ' \ + 'non-Macroscopic value "{1}"'.format(self._id, macroscopic) + raise ValueError(msg) + + if isinstance(macroscopic, openmc.Macroscopic): + # Copy this Macroscopic to separate it from the Macroscopic in + # other Materials + macroscopic = deepcopy(macroscopic) + else: + macroscopic = openmc.Macroscopic(macroscopic) + + if self._macroscopic is None: + self._macroscopic = macroscopic + else: + msg = 'Unable to add a Macroscopic to Material ID="{0}", ' \ + 'Only One Macroscopic allowed per ' \ + 'Material!'.format(self._id, macroscopic) + raise ValueError(msg) + + def remove_macroscopic(self, macroscopic): + """Remove a macroscopic from the material + + Parameters + ---------- + macroscopic : Macroscopic + Macroscopic to remove + + """ + + if not isinstance(macroscopic, openmc.Macroscopic): + msg = 'Unable to remove a Macroscopic "{0}" in Material ID="{1}" ' \ + 'since it is not a Macroscopic'.format(self._id, macroscopic) + raise ValueError(msg) + + # If the Material contains the Macroscopic, delete it + if macroscopic._name == self._macroscopic.name: + self._macroscopic = None + def add_element(self, element, percent, percent_type='ao'): """Add a natural element to the material @@ -325,6 +399,11 @@ class Material(object): """ + if self._macroscopic is not None: + msg = 'Unable to add an Element to Material ID="{0}" as a ' \ + 'macroscopic data-set has already been added'.format(self._id) + raise ValueError(msg) + if not isinstance(element, openmc.Element): msg = 'Unable to add an Element to Material ID="{0}" with a ' \ 'non-Element value "{1}"'.format(self._id, element) @@ -371,6 +450,11 @@ class Material(object): """ + if self._macroscopic is not None: + msg = 'Unable to add an S(a,b) table to Material ID="{0}" as a ' \ + 'macroscopic data-set has already been added'.format(self._id) + raise ValueError(msg) + if not isinstance(name, basestring): msg = 'Unable to add an S(a,b) table to Material ID="{0}" with a ' \ 'non-string table name "{1}"'.format(self._id, name) @@ -427,6 +511,15 @@ class Material(object): return xml_element + def _get_macroscopic_xml(self, macroscopic): + xml_element = ET.Element("macroscopic") + xml_element.set("name", macroscopic._name) + + if macroscopic.xs is not None: + xml_element.set("xs", macroscopic.xs) + + return xml_element + def _get_element_xml(self, element, distrib=False): xml_element = ET.Element("element") xml_element.set("name", str(element[0]._name)) @@ -482,14 +575,19 @@ class Material(object): subelement.set("units", self._density_units) if not self._convert_to_distrib_comps: - # Create nuclide XML subelements - subelements = self._get_nuclides_xml(self._nuclides) - for subelement in subelements: - element.append(subelement) + if self._macroscopic is None: + # Create nuclide XML subelements + subelements = self._get_nuclides_xml(self._nuclides) + for subelement in subelements: + element.append(subelement) - # Create element XML subelements - subelements = self._get_elements_xml(self._elements) - for subelement in subelements: + # Create element XML subelements + subelements = self._get_elements_xml(self._elements) + for subelement in subelements: + element.append(subelement) + else: + # Create macroscopic XML subelements + subelement = self._get_macroscopic_xml(self._macroscopic) element.append(subelement) else: @@ -516,15 +614,21 @@ class Material(object): subsubelement = ET.SubElement(subelement, "otf_file_path") subsubelement.text = self._distrib_otf_file - # Create nuclide XML subelements - subelements = self.get_nuclides_xml(self._nuclides, distrib=True) - for subelement_nuc in subelements: - subelement.append(subelement_nuc) + if self._macroscopic is None: + # Create nuclide XML subelements + subelements = self.get_nuclides_xml(self._nuclides, distrib=True) + for subelement_nuc in subelements: + subelement.append(subelement_nuc) - # Create element XML subelements - subelements = self._get_elements_xml(self._elements, distrib=True) - for subelement_ele in subelements: - subelement.append(subelement_ele) + # Create element XML subelements + subelements = self._get_elements_xml(self._elements, distrib=True) + for subsubelement in subelements: + subelement.append(subsubelement) + else: + # Create macroscopic XML subelements + subsubelement = self._get_macroscopic_xml(self._macroscopic, + distrib=True) + subelement.append(subsubelement) if len(self._sab) > 0: for sab in self._sab: diff --git a/openmc/mgxs/groups.py b/openmc/mgxs/groups.py index 3436c0e03..253df520e 100644 --- a/openmc/mgxs/groups.py +++ b/openmc/mgxs/groups.py @@ -24,7 +24,7 @@ class EnergyGroups(object): ---------- group_edges : Iterable of Real The energy group boundaries [MeV] - num_group : Integral + num_groups : Integral The number of energy groups """ @@ -54,7 +54,7 @@ class EnergyGroups(object): def __eq__(self, other): if not isinstance(other, EnergyGroups): return False - elif self.group_edges != other.group_edges: + elif (self.group_edges != other.group_edges).all(): return False else: return True diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py new file mode 100644 index 000000000..06b369c68 --- /dev/null +++ b/openmc/mgxs_library.py @@ -0,0 +1,722 @@ +from collections import Iterable +from numbers import Real, Integral +from xml.etree import ElementTree as ET +import warnings +import sys +if sys.version_info[0] >= 3: + basestring = str + +import numpy as np + +import openmc +from openmc.mgxs import EnergyGroups +from openmc.checkvalue import check_type, check_value, check_greater_than, \ + check_iterable_type +from openmc.clean_xml import * + +# Supported incoming particle MGXS angular treatment representations +_REPRESENTATIONS = ['isotropic', 'angle'] + + +def ndarray_to_string(arr): + """Converts a numpy ndarray in to a join with spaces between entries + similar to ' '.join(map(str,arr)) but applied to all sub-dimensions. + + Parameters + ---------- + arr : ndarray + Array to combine in to a string + + Returns + ------- + text : str + String representation of array in arr + + """ + + shape = arr.shape + ndim = arr.ndim + tab = ' ' + indent = '\n' + tab + tab + text = indent + + if ndim == 1: + text += tab + for i in range(shape[0]): + text += '{:.7E} '.format(arr[i]) + text += indent + elif ndim == 2: + for i in range(shape[0]): + text += tab + for j in range(shape[1]): + text += '{:.7E} '.format(arr[i, j]) + text += indent + elif ndim == 3: + for i in range(shape[0]): + for j in range(shape[1]): + text += tab + for k in range(shape[2]): + text += '{:.7E} '.format(arr[i, j, k]) + text += indent + elif ndim == 4: + for i in range(shape[0]): + for j in range(shape[1]): + for k in range(shape[2]): + text += tab + for l in range(shape[3]): + text += '{:.7E} '.format(arr[i, j, k, l]) + text += indent + elif ndim == 5: + for i in range(shape[0]): + for j in range(shape[1]): + for k in range(shape[2]): + for l in range(shape[3]): + text += tab + for m in range(shape[4]): + text += '{:.7E} '.format(arr[i, j, k, l, m]) + text += indent + + return text + + +class XSdata(object): + """A multi-group cross section data set providing all the + multi-group data necessary for a multi-group OpenMC calculation. + + Parameters + ---------- + name : str, optional + Name of the mgxs data set. + + representation : {'isotropic', 'angle'} + Method used in generating the MGXS (isotropic or angle-dependent flux + weighting). Defaults to 'isotropic' + + Attributes + ---------- + name : str + Unique identifier for the xsdata object + alias : str + Separate unique identifier for the xsdata object + kT : float + Temperature (in units of MeV) of this data set. + energy_groups : EnergyGroups + Energy group structure + fissionable : boolean + Whether or not this is a fissionable data set. + scatt_type : {'legendre', 'histogram', or 'tabular'} + Angular distribution representation (legendre, histogram, or tabular) + order : int + Either the Legendre order, number of bins, or number of points used to + describe the angular distribution associated with each group-to-group + transfer probability. + tabular_legendre : dict + Set how to treat the Legendre scattering kernel (tabular or leave in + Legendre polynomial form). Dict contains two keys: 'enable' and + 'num_points'. 'enable' is a boolean and 'num_points' is the + number of points to use, if 'enable' is True. + + """ + def __init__(self, name, energy_groups, representation="isotropic"): + # Initialize class attributes + self._name = name + self._energy_groups = energy_groups + self._representation = representation + self._alias = None + self._kT = None + self._fissionable = False + self._scatt_type = 'legendre' + self._order = None + self._tabular_legendre = None + self._num_polar = None + self._num_azimuthal = None + self._total = None + self._absorption = None + self._scatter = None + self._multiplicity = None + self._fission = None + self._nu_fission = None + self._k_fission = None + self._chi = None + self._use_chi = None + + @property + def name(self): + return self._name + + @property + def energy_groups(self): + return self._energy_groups + + @property + def representation(self): + return self._representation + + @property + def alias(self): + return self._alias + + @property + def kT(self): + return self._kT + + @property + def scatt_type(self): + return self._scatt_type + + @property + def order(self): + return self._order + + @property + def tabular_legendre(self): + return self._tabular_legendre + + @property + def num_polar(self): + return self._num_polar + + @property + def num_azimuthal(self): + return self._num_azimuthal + + @property + def total(self): + return self._total + + @property + def absorption(self): + return self._absorption + + @property + def scatter(self): + return self._scatter + + @property + def multiplicity(self): + return self._multiplicity + + @property + def fission(self): + return self._fission + + @property + def nu_fission(self): + return self._nu_fission + + @property + def k_fission(self): + return self._k_fission + + @property + def chi(self): + return self._chi + + @property + def num_orders(self): + if (self._order is not None) and (self._scatt_type is not None): + if self._scatt_type is 'legendre': + return self._order + 1 + else: + return self._order + + @name.setter + def name(self, name): + check_type('name for XSdata', name, basestring) + self._name = name + + @energy_groups.setter + def energy_groups(self, energy_groups): + # Check validity of energy_groups + check_type("energy_groups", energy_groups, EnergyGroups) + + # Check that there is one or more groups + if ((energy_groups.num_groups is None) or + (energy_groups.num_groups < 1)): + + msg = 'energy_groups object incorrectly initialized.' + raise ValueError(msg) + + self._energy_groups = energy_groups + + @representation.setter + def representation(self, representation): + # Check it is of valid type. + check_value('representation', representation, _REPRESENTATIONS) + self._representation = representation + + @alias.setter + def alias(self, alias): + if alias is not None: + check_type('alias', alias, basestring) + self._alias = alias + else: + self._alias = self._name + + @kT.setter + def kT(self, kT): + # Check validity of type and that the kT value is >= 0 + check_type("kT", kT, Real) + check_greater_than("kT", kT, 0.0, equality=True) + self._kT = kT + + @scatt_type.setter + def scatt_type(self, scatt_type): + # check to see it is of a valid type and value + check_value("scatt_type", scatt_type, ['legendre', 'histogram', + 'tabular']) + self._scatt_type = scatt_type + + @order.setter + def order(self, order): + # Check type and value + check_type("order", order, Integral) + check_greater_than("order", order, 0, equality=True) + self._order = order + + @tabular_legendre.setter + def tabular_legendre(self, tabular_legendre): + # Check to make sure this is a dict and it has our keys with the + # right values. + check_type("tabular_legendre", tabular_legendre, dict) + if 'enable' in tabular_legendre: + enable = tabular_legendre['enable'] + check_type('enable', enable, bool) + else: + msg = "enable must be provided in tabular_legendre" + raise ValueError(msg) + if 'num_points' in tabular_legendre: + num_points = tabular_legendre['num_points'] + check_value('num_points', num_points, Integral) + check_greater_than('num_points', num_points, 0) + else: + if not enable: + num_points = 1 + else: + num_points = 33 + self._tabular_legendre = {'enable': enable, 'num_points': num_points} + + @num_polar.setter + def num_polar(self, num_polar): + # Make sure we have positive ints + check_value("num_polar", num_polar, Integral) + check_greater_than("num_polar", num_polar, 0) + self._num_polar = num_polar + + @num_azimuthal.setter + def num_azimuthal(self, num_azimuthal): + check_value("num_azimuthal", num_azimuthal, Integral) + check_greater_than("num_azimuthal", num_azimuthal, 0) + self._num_azimuthal = num_azimuthal + + @total.setter + def total(self, total): + if self._representation is 'isotropic': + shape = (self._energy_groups.num_groups,) + elif self._representation is 'angle': + shape = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups) + # check we have a numpy list + check_type("total", total, np.ndarray, expected_iter_type=Real) + if total.shape == shape: + self._total = np.copy(total) + else: + msg = 'Shape of provided total "{0}" does not match shape ' \ + 'required, "{1}"'.format(total.shape, shape) + raise ValueError(msg) + + @absorption.setter + def absorption(self, absorption): + if self._representation is 'isotropic': + shape = (self._energy_groups.num_groups,) + elif self._representation is 'angle': + shape = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups) + # check we have a numpy list + check_type("absorption", absorption, np.ndarray, expected_iter_type=Real) + if absorption.shape == shape: + self._absorption = np.copy(absorption) + else: + msg = 'Shape of provided absorption "{0}" does not match shape ' \ + 'required, "{1}"'.format(absorption.shape, shape) + raise ValueError(msg) + + @fission.setter + def fission(self, fission): + if self._representation is 'isotropic': + shape = (self._energy_groups.num_groups,) + elif self._representation is 'angle': + shape = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups) + # check we have a numpy list + check_type("fission", fission, np.ndarray, expected_iter_type=Real) + if fission.shape == shape: + self._fission = np.copy(fission) + if np.sum(self._fission) > 0.0: + self._fissionable = True + else: + msg = 'Shape of provided fission "{0}" does not match shape ' \ + 'required, "{1}"'.format(fission.shape, shape) + raise ValueError(msg) + + @k_fission.setter + def k_fission(self, k_fission): + if self._representation is 'isotropic': + shape = (self._energy_groups.num_groups,) + elif self._representation is 'angle': + shape = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups) + # check we have a numpy list + check_type("k_fission", k_fission, np.ndarray, expected_iter_type=Real) + if k_fission.shape == shape: + self._k_fission = np.copy(k_fission) + if np.sum(self._k_fission) > 0.0: + self._fissionable = True + else: + msg = 'Shape of provided k_fission "{0}" does not match shape ' \ + 'required, "{1}"'.format(k_fission.shape, shape) + raise ValueError(msg) + + @chi.setter + def chi(self, chi): + if not self._use_chi: + msg = 'Providing chi when nu_fission already provided as matrix!' + raise ValueError(msg) + if self._representation is 'isotropic': + shape = (self._energy_groups.num_groups,) + elif self._representation is 'angle': + shape = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups) + # check we have a numpy list + check_type("chi", chi, np.ndarray, expected_iter_type=Real) + if chi.shape == shape: + self._chi = np.copy(chi) + else: + msg = 'Shape of provided chi "{0}" does not match shape ' \ + 'required, "{1}"'.format(chi.shape, shape) + raise ValueError(msg) + if self._use_chi is not None: + self._use_chi = True + + @scatter.setter + def scatter(self, scatter): + if self._representation is 'isotropic': + shape = (self.num_orders, self._energy_groups.num_groups, + self._energy_groups.num_groups) + max_depth = 3 + elif self._representation is 'angle': + shape = (self._num_polar, self._num_azimuthal, self.num_orders, + self._energy_groups.num_groups, + self._energy_groups.num_groups) + max_depth = 5 + # check we have a numpy list + check_iterable_type("scatter", scatter, expected_type=Real, + max_depth=max_depth) + if scatter.shape == shape: + self._scatter = np.copy(scatter) + else: + msg = 'Shape of provided scatter "{0}" does not match shape ' \ + 'required, "{1}"'.format(scatter.shape, shape) + raise ValueError(msg) + + @multiplicity.setter + def multiplicity(self, multiplicity): + if self._representation is 'isotropic': + shape = (self._energy_groups.num_groups, + self._energy_groups.num_groups) + max_depth = 2 + elif self._representation is 'angle': + shape = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups, + self._energy_groups.num_groups) + max_depth = 4 + # check we have a numpy list + check_iterable_type("multiplicity", multiplicity, expected_type=Real, + max_depth=max_depth) + if multiplicity.shape == shape: + self._multiplicity = np.copy(multiplicity) + else: + msg = 'Shape of provided multiplicity "{0}" does not match shape ' \ + 'required, "{1}"'.format(multiplicity.shape, shape) + raise ValueError(msg) + + @nu_fission.setter + def nu_fission(self, nu_fission): + # nu_fission can be given as a vector or a matrix + # Vector is used when chi also exists. + # Matrix is used when chi does not exist. + # We have to check that the correct form is given, but only if + # chi already has been set. If not, we just check that this is OK + # and set the use_chi flag. + + # First lets set our dimensions here since they get used repeatedly + # throughout this code. + if self._representation is 'isotropic': + shape_vec = (self._energy_groups.num_groups,) + shape_mat = (self._energy_groups.num_groups, + self._energy_groups.num_groups) + elif self._representation is 'angle': + shape_vec = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups) + shape_mat = (self._num_polar, self._num_azimuthal, + self._energy_groups.num_groups, + self._energy_groups.num_groups) + + # Begin by checking the case when chi has already been given and thus + # the rules for filling in nu_fission are set. + if self._use_chi is not None: + if self._use_chi: + shape = shape_vec + else: + shape = shape_mat + if nu_fission.shape != shape: + msg = "Invalid Shape of Nu_fission!" + raise ValueError(msg) + else: + # Get shape of nu_fission so we can figure if we need chi or not + if nu_fission.shape == shape_vec: + self._use_chi = True + shape = shape_vec + elif nu_fission.shape == shape_mat: + self._use_chi = False + shape = shape_mat + else: + msg = "Invalid Shape of Nu_fission!" + raise ValueError(msg) + + # check we have a numpy list + check_type("nu_fission", nu_fission, np.ndarray, expected_iter_type=Real) + self._nu_fission = np.copy(nu_fission) + if np.sum(self._nu_fission) > 0.0: + self._fissionable = True + + def _get_xsdata_xml(self): + element = ET.Element("xsdata") + element.set("name", self._name) + + if self._alias is not None: + subelement = ET.SubElement(element, 'alias') + subelement.text = self.alias + + if self._kT is not None: + subelement = ET.SubElement(element, 'kT') + subelement.text = str(self._kT) + + if self._fissionable is not None: + subelement = ET.SubElement(element, 'fissionable') + subelement.text = str(self._fissionable) + + if self._representation is not None: + subelement = ET.SubElement(element, 'representation') + subelement.text = self._representation + + if self._representation == 'angle': + if self._num_azimuthal is not None: + subelement = ET.SubElement(element, 'num_azimuthal') + subelement.text = str(self._num_azimuthal) + if self._num_polar is not None: + subelement = ET.SubElement(element, 'num_polar') + subelement.text = str(self._num_polar) + + if self._scatt_type is not None: + subelement = ET.SubElement(element, 'scatt_type') + subelement.text = self._scatt_type + + if self._order is not None: + subelement = ET.SubElement(element, 'order') + subelement.text = str(self._order) + + if self._tabular_legendre is not None: + subelement = ET.SubElement(element, 'tabular_legendre') + subelement.set('enable', str(self._tabular_legendre['enable'])) + subelement.set('num_points', str(self._tabular_legendre['num_points'])) + + if self._total is not None: + subelement = ET.SubElement(element, 'total') + subelement.text = ndarray_to_string(self._total) + + if self._absorption is not None: + subelement = ET.SubElement(element, 'absorption') + subelement.text = ndarray_to_string(self._absorption) + + if self._scatter is not None: + subelement = ET.SubElement(element, 'scatter') + subelement.text = ndarray_to_string(self._scatter) + + if self._multiplicity is not None: + subelement = ET.SubElement(element, 'multiplicity') + subelement.text = ndarray_to_string(self._multiplicity) + + if self._fissionable: + if self._fission is not None: + subelement = ET.SubElement(element, 'fission') + subelement.text = ndarray_to_string(self._fission) + + if self._k_fission is not None: + subelement = ET.SubElement(element, 'k_fission') + subelement.text = ndarray_to_string(self._k_fission) + + if self._nu_fission is not None: + subelement = ET.SubElement(element, 'nu_fission') + subelement.text = ndarray_to_string(self._nu_fission) + + if self._chi is not None: + subelement = ET.SubElement(element, 'chi') + subelement.text = ndarray_to_string(self._chi) + + return element + + +class MGXSLibraryFile(object): + """Multi-Group Cross Sections file used for an OpenMC simulation. + Corresponds directly to the MG version of the cross_sections.xml input file. + + Attributes + ---------- + energy_groups : openmc.mgxs.EnergyGroups + Energy group structure. + inverse_velocities : Iterable of Real + Inverse of velocities, units of sec/cm + filename : str + XML file to write to. + xsdatas : Iterable of XSdata + Iterable of multi-Group cross section data objects + """ + + def __init__(self, energy_groups): + # Initialize MGXSLibraryFile class attributes + self._xsdatas = [] + self._energy_groups = energy_groups + self._inverse_velocities = None + self._cross_sections_file = ET.Element("cross_sections") + + @property + def inverse_velocities(self): + return self._inverse_velocities + + @property + def energy_groups(self): + return self._energy_groups + + @inverse_velocities.setter + def inverse_velocities(self, inverse_velocities): + cv.check_type('inverse_velocities', inverse_velocities, Iterable, Real) + cv.check_greater_than('number of inverse_velocities', + len(inverse_velocities), 0.0) + self._inverse_velocities = np.array(inverse_velocities) + + @energy_groups.setter + def energy_groups(self, energy_groups): + check_type("energy groups", energy_groups, EnergyGroups) + self._energy_groups = energy_groups + + def add_xsdata(self, xsdata): + """Add an XSdata entry to the file. + + Parameters + ---------- + xsdata : XSdata + MGXS information to add + + """ + + # Check the type + if not isinstance(xsdata, XSdata): + msg = 'Unable to add a non-XSdata "{0}" to the ' \ + 'MGXSLibraryFile'.format(xsdata) + raise ValueError(msg) + + # Make sure energy groups match. + if xsdata.energy_groups != self._energy_groups: + msg = 'Energy groups of XSdata do not match that of MGXSLibraryFile!' + raise ValueError(msg) + + self._xsdatas.append(xsdata) + + def add_xsdatas(self, xsdatas): + """Add multiple xsdatas to the file. + + Parameters + ---------- + xsdatas : tuple or list of XSdata + XSdatas to add + + """ + + if not isinstance(xsdatas, Iterable): + msg = 'Unable to create OpenMC xsdatas.xml file from "{0}" which ' \ + 'is not iterable'.format(xsdatas) + raise ValueError(msg) + + for xsdata in xsdatas: + self.add_xsdata(xsdata) + + def remove_xsdata(self, xsdata): + """Remove a xsdata from the file + + Parameters + ---------- + xsdata : XSdata + XSdata to remove + + """ + + if not isinstance(xsdata, XSdata): + msg = 'Unable to remove a non-XSdata "{0}" from the ' \ + 'XSdatasFile'.format(xsdata) + raise ValueError(msg) + + self._xsdatas.remove(xsdata) + + def _create_groups_subelement(self): + if self._energy_groups is not None: + element = ET.SubElement(self._cross_sections_file, "groups") + element.text = str(self._energy_groups.num_groups) + + def _create_group_structure_subelement(self): + if self._energy_groups is not None: + element = ET.SubElement(self._cross_sections_file, + "group_structure") + element.text = ' '.join(map(str, self._energy_groups.group_edges)) + + def _create_inverse_velocities_subelement(self): + if self._inverse_velocities is not None: + element = ET.SubElement(self._cross_sections_file, + "inverse_velocities") + element.text = ' '.join(map(str, self._inverse_velocities)) + + def _create_xsdata_subelements(self): + for xsdata in self._xsdatas: + xml_element = xsdata._get_xsdata_xml() + self._cross_sections_file.append(xml_element) + + def export_to_xml(self, filename='mg_cross_sections.xml'): + """Create an mg_cross_sections.xml file that can be used for a + simulation. + + Parameters + ---------- + filename : str, optional + filename of file, default is mg_cross_sections.xml + + """ + + # Reset xml element tree + self._cross_sections_file.clear() + + self._create_groups_subelement() + self._create_group_structure_subelement() + self._create_inverse_velocities_subelement() + self._create_xsdata_subelements() + + # Clean the indentation in the file to be user-readable + sort_xml_elements(self._cross_sections_file) + clean_xml_indentation(self._cross_sections_file) + + # Write the XML Tree to the xsdatas.xml file + tree = ET.ElementTree(self._cross_sections_file) + tree.write(filename, xml_declaration=True, + encoding='utf-8', method="xml") + + + diff --git a/openmc/settings.py b/openmc/settings.py index 3d9ec72b9..cb0207e71 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -70,11 +70,15 @@ class SettingsFile(object): cross_sections : str Indicates the path to an XML cross section listing file (usually named cross_sections.xml). If it is not set, the :envvar:`CROSS_SECTIONS` - environment variable will be used to find the path to the XML cross - section listing. - energy_grid : str - Set the method used to search energy grids. Acceptable values are - 'nuclide', 'logarithm', and 'material-union'. + environment variable will be used for continuous-energy calculations + and :envvar:`MG_CROSS_SECTIONS` will be used for multi-group + calculations to find the path to the XML cross section file. + energy_grid : {'nuclide', 'logarithm', 'material-union'} + Set the method used to search energy grids. + energy_mode : {'continuous-energy', 'multi-group'} + Set whether the calculation should be continuous-energy or multi-group. + max_order : int + Maximum scattering order to apply globally when in multi-group mode. ptables : bool Determine whether probability tables are used. run_cmfd : bool @@ -134,6 +138,10 @@ class SettingsFile(object): self._particles = None self._keff_trigger = None + # Energy mode subelement + self._energy_mode = None + self._max_order = None + # Source subelement self._source = None @@ -221,6 +229,14 @@ class SettingsFile(object): def keff_trigger(self): return self._keff_trigger + @property + def energy_mode(self): + return self._energy_mode + + @property + def max_order(self): + return self._max_order + @property def source(self): return self._source @@ -438,6 +454,18 @@ class SettingsFile(object): self._keff_trigger = keff_trigger + @energy_mode.setter + def energy_mode(self, energy_mode): + check_value('energy mode', energy_mode, + ['continuous-energy', 'multi-group']) + self._energy_mode = energy_mode + + @max_order.setter + def max_order(self, max_order): + check_type('maximum scattering order', max_order, Integral) + check_greater_than('maximum scattering order', max_order, 0, True) + self._max_order = max_order + @source.setter def source(self, source): if isinstance(source, Source): @@ -782,6 +810,16 @@ class SettingsFile(object): subelement = ET.SubElement(element, key) subelement.text = str(self._keff_trigger[key]).lower() + def _create_energy_mode_subelement(self): + if self._energy_mode is not None: + element = ET.SubElement(self._settings_file, "energy_mode") + element.text = str(self._energy_mode) + + def _create_max_order_subelement(self): + if self._max_order is not None: + element = ET.SubElement(self._settings_file, "max_order") + element.text = str(self._max_order) + def _create_source_subelement(self): if self.source is not None: for source in self.source: @@ -1025,6 +1063,8 @@ class SettingsFile(object): self._create_confidence_intervals() self._create_cross_sections_subelement() self._create_energy_grid_subelement() + self._create_energy_mode_subelement() + self._create_max_order_subelement() self._create_ptables_subelement() self._create_run_cmfd_subelement() self._create_seed_subelement() diff --git a/openmc/statepoint.py b/openmc/statepoint.py index f5b5b2e72..003b08818 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -103,11 +103,11 @@ class StatePoint(object): raise IOError('Could not read statepoint file. This most likely ' 'means the statepoint file was produced by a different ' 'version of OpenMC than the one you are using.') - if self._f['revision'].value != 14: + if self._f['revision'].value != 15: raise IOError('Statepoint file has a file revision of {} ' 'which is not consistent with the revision this ' 'version of OpenMC expects ({}).'.format( - self._f['revision'].value, 14)) + self._f['revision'].value, 15)) # Set flags for what data has been read self._meshes_read = False diff --git a/openmc/summary.py b/openmc/summary.py index d22e367c9..0d232fb07 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -60,6 +60,9 @@ class Summary(object): # Read date and time self.date_and_time = self._f['date_and_time'][...] + # Read if continuous-energy or multi-group + self.run_CE = (self._f['run_CE'].value == 1) + self.n_batches = self._f['n_batches'].value self.n_particles = self._f['n_particles'].value self.n_active = self._f['n_active'].value @@ -276,7 +279,7 @@ class Summary(object): # Get the distribcell index ind = self._f['geometry/cells'][key]['distribcell_index'].value if ind != 0: - cell.distribcell_index = ind + cell.distribcell_index = ind # Add the Cell to the global dictionary of all Cells self.cells[index] = cell diff --git a/src/ace.F90 b/src/ace.F90 index 8d73f8bd4..5012c9b88 100644 --- a/src/ace.F90 +++ b/src/ace.F90 @@ -1,6 +1,6 @@ module ace - use ace_header, only: Nuclide, Reaction, SAlphaBeta, XsListing + use ace_header, only: Reaction use constants use distribution_univariate, only: Uniform, Equiprobable, Tabular use endf, only: is_fission, is_disappearance @@ -11,7 +11,9 @@ module ace use global use list_header, only: ListInt use material_header, only: Material + use nuclide_header use output, only: write_message + use sab_header use set_header, only: SetChar use secondary_header, only: AngleEnergy use secondary_correlated, only: CorrelatedAngleEnergy @@ -33,11 +35,11 @@ module ace contains !=============================================================================== -! READ_XS reads all the cross sections for the problem and stores them in +! READ_ACE_XS reads all the cross sections for the problem and stores them in ! nuclides and sab_tables arrays !=============================================================================== - subroutine read_xs() + subroutine read_ace_xs() integer :: i ! index in materials array integer :: j ! index over nuclides in material @@ -52,7 +54,7 @@ contains character(12) :: name ! name of isotope, e.g. 92235.03c character(12) :: alias ! alias of nuclide, e.g. U-235.03c type(Material), pointer :: mat - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc type(SAlphaBeta), pointer :: sab type(SetChar) :: already_read @@ -231,7 +233,7 @@ contains end if end do - end subroutine read_xs + end subroutine read_ace_xs !=============================================================================== ! READ_ACE_TABLE reads a single cross section table in either ASCII or binary @@ -263,9 +265,9 @@ contains character(10) :: mat ! material identifier character(70) :: comment ! comment for ACE table character(MAX_FILE_LEN) :: filename ! path to ACE cross section library - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc type(SAlphaBeta), pointer :: sab - type(XsListing), pointer :: listing + type(XsListing), pointer :: listing ! determine path, record length, and location of table listing => xs_listings(i_listing) @@ -420,8 +422,8 @@ contains !=============================================================================== subroutine read_esz(nuc, data_0K) - type(Nuclide), intent(inout) :: nuc - logical, intent(in) :: data_0K ! are we reading 0K data? + type(NuclideCE), intent(inout) :: nuc + logical, intent(in) :: data_0K ! are we reading 0K data? integer :: NE ! number of energy points for total and elastic cross sections integer :: i ! index in 0K elastic xs array for this nuclide @@ -508,7 +510,7 @@ contains !=============================================================================== subroutine read_nu_data(nuc) - type(Nuclide), intent(inout) :: nuc + type(NuclideCE), intent(inout) :: nuc integer :: i ! loop index integer :: JXS2 ! location for fission nu data @@ -712,7 +714,7 @@ contains !=============================================================================== subroutine read_reactions(nuc) - type(Nuclide), intent(inout) :: nuc + type(NuclideCE), intent(inout) :: nuc integer :: i ! loop indices integer :: i_fission ! index in nuc % index_fission @@ -892,7 +894,7 @@ contains !=============================================================================== subroutine read_angular_dist(nuc) - type(Nuclide), intent(inout) :: nuc + type(NuclideCE), intent(inout) :: nuc integer :: LOCB ! location of angular distribution for given MT integer :: NE ! number of incoming energies @@ -996,7 +998,7 @@ contains !=============================================================================== subroutine read_energy_dist(nuc) - type(Nuclide), intent(inout) :: nuc + type(NuclideCE), intent(inout) :: nuc integer :: i ! loop index integer :: n @@ -1384,7 +1386,7 @@ contains !=============================================================================== subroutine read_unr_res(nuc) - type(Nuclide), intent(inout) :: nuc + type(NuclideCE), intent(inout) :: nuc integer :: JXS23 ! location of URR data integer :: lc ! locator @@ -1472,7 +1474,7 @@ contains !=============================================================================== subroutine generate_nu_fission(nuc) - type(Nuclide), intent(inout) :: nuc + type(NuclideCE), intent(inout) :: nuc integer :: i ! index on nuclide energy grid real(8) :: E ! energy diff --git a/src/ace_header.F90 b/src/ace_header.F90 index 2331f9117..ae5000e5a 100644 --- a/src/ace_header.F90 +++ b/src/ace_header.F90 @@ -24,9 +24,8 @@ module ace_header real(8), allocatable :: sigma(:) ! Cross section values type(SecondaryDistribution) :: secondary - ! Type-Bound procedures - contains - procedure :: clear => reaction_clear ! Deallocates Reaction + contains + procedure :: clear => reaction_clear ! Deallocates Reaction end type Reaction !=============================================================================== @@ -44,210 +43,6 @@ module ace_header real(8), allocatable :: prob(:,:,:) ! actual probabibility tables end type UrrData -!=============================================================================== -! NUCLIDE contains all the data for an ACE-format continuous-energy cross -! section. The ACE format (A Compact ENDF format) is used in MCNP and several -! other Monte Carlo codes. -!=============================================================================== - - type Nuclide - character(10) :: name ! name of nuclide, e.g. 92235.03c - integer :: zaid ! Z and A identifier, e.g. 92235 - integer :: listing ! index in xs_listings - real(8) :: awr ! weight of nucleus in neutron masses - real(8) :: kT ! temperature in MeV (k*T) - - ! Linked list of indices in nuclides array of instances of this same nuclide - type(VectorInt) :: nuc_list - - ! Energy grid information - integer :: n_grid ! # of nuclide grid points - integer, allocatable :: grid_index(:) ! log grid mapping indices - real(8), allocatable :: energy(:) ! energy values corresponding to xs - - ! Microscopic cross sections - real(8), allocatable :: total(:) ! total cross section - real(8), allocatable :: elastic(:) ! elastic scattering - real(8), allocatable :: fission(:) ! fission - real(8), allocatable :: nu_fission(:) ! neutron production - real(8), allocatable :: absorption(:) ! absorption (MT > 100) - real(8), allocatable :: heating(:) ! heating - - ! Resonance scattering info - logical :: resonant = .false. ! resonant scatterer? - character(10) :: name_0K = '' ! name of 0K nuclide, e.g. 92235.00c - character(16) :: scheme ! target velocity sampling scheme - integer :: n_grid_0K ! number of 0K energy grid points - real(8), allocatable :: energy_0K(:) ! energy grid for 0K xs - real(8), allocatable :: elastic_0K(:) ! Microscopic elastic cross section - real(8), allocatable :: xs_cdf(:) ! CDF of v_rel times cross section - real(8) :: E_min ! lower cutoff energy for res scattering - real(8) :: E_max ! upper cutoff energy for res scattering - - ! Fission information - logical :: fissionable ! nuclide is fissionable? - logical :: has_partial_fission ! nuclide has partial fission reactions? - integer :: n_fission ! # of fission reactions - integer, allocatable :: index_fission(:) ! indices in reactions - - ! Total fission neutron emission - integer :: nu_t_type - real(8), allocatable :: nu_t_data(:) - - ! Prompt fission neutron emission - integer :: nu_p_type - real(8), allocatable :: nu_p_data(:) - - ! Delayed fission neutron emission - integer :: nu_d_type - integer :: n_precursor ! # of delayed neutron precursors - real(8), allocatable :: nu_d_data(:) - real(8), allocatable :: nu_d_precursor_data(:) - type(AngleEnergyContainer), allocatable :: nu_d_edist(:) - - ! Unresolved resonance data - logical :: urr_present - integer :: urr_inelastic - type(UrrData), pointer :: urr_data => null() - - ! Reactions - integer :: n_reaction ! # of reactions - type(Reaction), allocatable :: reactions(:) - type(DictIntInt) :: reaction_index ! map MT values to index in reactions - ! array; used at tally-time - - ! Type-Bound procedures - contains - procedure :: clear => nuclide_clear ! Deallocates Nuclide - end type Nuclide - -!=============================================================================== -! NUCLIDE0K temporarily contains all 0K cross section data and other parameters -! needed to treat resonance scattering before transferring them to NUCLIDE -!=============================================================================== - - type Nuclide0K - character(10) :: nuclide ! name of nuclide, e.g. U-238 - character(16) :: scheme = 'ares' ! target velocity sampling scheme - character(10) :: name ! name of nuclide, e.g. 92235.03c - character(10) :: name_0K ! name of 0K nuclide, e.g. 92235.00c - real(8) :: E_min = 0.01e-6_8 ! lower cutoff energy for res scattering - real(8) :: E_max = 1000.0e-6_8 ! upper cutoff energy for res scattering - end type Nuclide0K - -!=============================================================================== -! DISTENERGYSAB contains the secondary energy/angle distributions for inelastic -! thermal scattering collisions which utilize a continuous secondary energy -! representation. -!=============================================================================== - - type DistEnergySab - integer :: n_e_out - real(8), allocatable :: e_out(:) - real(8), allocatable :: e_out_pdf(:) - real(8), allocatable :: e_out_cdf(:) - real(8), allocatable :: mu(:,:) - end type DistEnergySab - -!=============================================================================== -! SALPHABETA contains S(a,b) data for thermal neutron scattering, typically off -! of light isotopes such as water, graphite, Be, etc -!=============================================================================== - - type SAlphaBeta - character(10) :: name ! name of table, e.g. lwtr.10t - real(8) :: awr ! weight of nucleus in neutron masses - real(8) :: kT ! temperature in MeV (k*T) - integer :: n_zaid ! Number of valid zaids - integer, allocatable :: zaid(:) ! List of valid Z and A identifiers, e.g. 6012 - - ! threshold for S(a,b) treatment (usually ~4 eV) - real(8) :: threshold_inelastic - real(8) :: threshold_elastic = ZERO - - ! Inelastic scattering data - integer :: n_inelastic_e_in ! # of incoming E for inelastic - integer :: n_inelastic_e_out ! # of outgoing E for inelastic - integer :: n_inelastic_mu ! # of outgoing angles for inelastic - integer :: secondary_mode ! secondary mode (equal/skewed/continuous) - real(8), allocatable :: inelastic_e_in(:) - real(8), allocatable :: inelastic_sigma(:) - ! The following are used only if secondary_mode is 0 or 1 - real(8), allocatable :: inelastic_e_out(:,:) - real(8), allocatable :: inelastic_mu(:,:,:) - ! The following is used only if secondary_mode is 3 - ! The different implementation is necessary because the continuous - ! representation has a variable number of outgoing energy points for each - ! incoming energy - type(DistEnergySab), allocatable :: inelastic_data(:) ! One for each Ein - - ! Elastic scattering data - integer :: elastic_mode ! elastic mode (discrete/exact) - integer :: n_elastic_e_in ! # of incoming E for elastic - integer :: n_elastic_mu ! # of outgoing angles for elastic - real(8), allocatable :: elastic_e_in(:) - real(8), allocatable :: elastic_P(:) - real(8), allocatable :: elastic_mu(:,:) - end type SAlphaBeta - -!=============================================================================== -! XSLISTING contains data read from a cross_sections.xml file -!=============================================================================== - - type XsListing - character(12) :: name ! table name, e.g. 92235.70c - character(12) :: alias ! table alias, e.g. U-235.70c - integer :: type ! type of table (cont-E neutron, S(A,b), etc) - integer :: zaid ! ZAID identifier = 1000*Z + A - integer :: filetype ! ASCII or BINARY - integer :: location ! location of table within library - integer :: recl ! record length for library - integer :: entries ! number of entries per record - real(8) :: awr ! atomic weight ratio (# of neutron masses) - real(8) :: kT ! Boltzmann constant * temperature (MeV) - logical :: metastable ! is this nuclide metastable? - character(MAX_FILE_LEN) :: path ! path to library containing table - end type XsListing - -!=============================================================================== -! NUCLIDEMICROXS contains cached microscopic cross sections for a -! particular nuclide at the current energy -!=============================================================================== - - type NuclideMicroXS - integer :: index_grid ! index on nuclide energy grid - integer :: index_temp ! temperature index for nuclide - real(8) :: last_E = ZERO ! last evaluated energy - real(8) :: interp_factor ! interpolation factor on nuc. energy grid - real(8) :: total ! microscropic total xs - real(8) :: elastic ! microscopic elastic scattering xs - real(8) :: absorption ! microscopic absorption xs - real(8) :: fission ! microscopic fission xs - real(8) :: nu_fission ! microscopic production xs - - ! Information for S(a,b) use - integer :: index_sab ! index in sab_tables (zero means no table) - integer :: last_index_sab = 0 ! index in sab_tables last used by this nuclide - real(8) :: elastic_sab ! microscopic elastic scattering on S(a,b) table - - ! Information for URR probability table use - logical :: use_ptable ! in URR range with probability tables? - real(8) :: last_prn - end type NuclideMicroXS - -!=============================================================================== -! MATERIALMACROXS contains cached macroscopic cross sections for the material a -! particle is traveling through -!=============================================================================== - - type MaterialMacroXS - real(8) :: total ! macroscopic total xs - real(8) :: elastic ! macroscopic elastic scattering xs - real(8) :: absorption ! macroscopic absorption xs - real(8) :: fission ! macroscopic fission xs - real(8) :: nu_fission ! macroscopic production xs - end type MaterialMacroXS - contains !=============================================================================== @@ -260,25 +55,4 @@ module ace_header if (associated(this % multiplicity_E)) deallocate(this % multiplicity_E) end subroutine reaction_clear -!=============================================================================== -! NUCLIDE_CLEAR resets and deallocates data in Nuclide. -!=============================================================================== - - subroutine nuclide_clear(this) - class(Nuclide), intent(inout) :: this - - integer :: i ! Loop counter - - if (associated(this % urr_data)) deallocate(this % urr_data) - - if (allocated(this % reactions)) then - do i = 1, size(this % reactions) - call this % reactions(i) % clear() - end do - end if - - call this % reaction_index % clear() - - end subroutine nuclide_clear - end module ace_header diff --git a/src/bank_header.F90 b/src/bank_header.F90 index 0cb49af35..97fb1f11f 100644 --- a/src/bank_header.F90 +++ b/src/bank_header.F90 @@ -14,7 +14,7 @@ module bank_header real(C_DOUBLE) :: wgt ! weight of bank site real(C_DOUBLE) :: xyz(3) ! location of bank particle real(C_DOUBLE) :: uvw(3) ! diretional cosines - real(C_DOUBLE) :: E ! energy + real(C_DOUBLE) :: E ! energy / energy group if in MG mode. integer(C_INT) :: delayed_group ! delayed group end type Bank diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index 19fe39572..347351e31 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -49,13 +49,13 @@ contains subroutine compute_xs() - use constants, only: FILTER_MESH, FILTER_ENERGYIN, FILTER_ENERGYOUT, & - FILTER_SURFACE, IN_RIGHT, OUT_RIGHT, IN_FRONT, & - OUT_FRONT, IN_TOP, OUT_TOP, CMFD_NOACCEL, ZERO, & - ONE, TINY_BIT + use constants, only: FILTER_MESH, FILTER_ENERGYIN, FILTER_ENERGYOUT, & + FILTER_SURFACE, IN_RIGHT, OUT_RIGHT, IN_FRONT, & + OUT_FRONT, IN_TOP, OUT_TOP, CMFD_NOACCEL, ZERO, & + ONE, TINY_BIT use error, only: fatal_error use global, only: cmfd, n_cmfd_tallies, cmfd_tallies, meshes,& - matching_bins + matching_bins use mesh, only: mesh_indices_to_bin use mesh_header, only: RegularMesh use string, only: to_str @@ -625,10 +625,10 @@ contains subroutine compute_dhat() - use constants, only: CMFD_NOACCEL, ZERO - use global, only: cmfd, cmfd_coremap, dhat_reset - use output, only: write_message - use string, only: to_str + use constants, only: CMFD_NOACCEL, ZERO + use global, only: cmfd, cmfd_coremap, dhat_reset + use output, only: write_message + use string, only: to_str integer :: nx ! maximum number of cells in x direction integer :: ny ! maximum number of cells in y direction diff --git a/src/cmfd_execute.F90 b/src/cmfd_execute.F90 index 4dfe99d77..b7d0cc387 100644 --- a/src/cmfd_execute.F90 +++ b/src/cmfd_execute.F90 @@ -89,9 +89,9 @@ contains subroutine calc_fission_source() - use constants, only: CMFD_NOACCEL, ZERO, TWO - use global, only: cmfd, cmfd_coremap, master, entropy_on, current_batch - use string, only: to_str + use constants, only: CMFD_NOACCEL, ZERO, TWO + use global, only: cmfd, cmfd_coremap, master, entropy_on, current_batch + use string, only: to_str #ifdef MPI use global, only: mpi_err diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index dac74c9c3..2d9df4182 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -45,14 +45,14 @@ contains subroutine read_cmfd_xml() use constants, only: ZERO, ONE - use error, only: fatal_error, warning + use error, only: fatal_error, warning use global - use output, only: write_message - use string, only: to_lower + use output, only: write_message + use string, only: to_lower use xml_interface use, intrinsic :: ISO_FORTRAN_ENV - integer :: i + integer :: i, g integer :: ng integer :: n_params integer, allocatable :: iarray(:) @@ -102,6 +102,23 @@ contains if(.not.allocated(cmfd%egrid)) allocate(cmfd%egrid(ng)) call get_node_array(node_mesh, "energy", cmfd%egrid) cmfd % indices(4) = ng - 1 ! sets energy group dimension + ! If using MG mode, check to see if these egrid points at least match + ! the MG Data breakpoints + if (.not. run_CE) then + do i = 1, ng + found = .false. + do g = 1, energy_groups + 1 + if (cmfd % egrid(i) == energy_bins(g)) then + found = .true. + exit + end if + end do + if (.not. found) then + call fatal_error("CMFD energy mesh boundaries must align with& + & boundaries of multi-group data!") + end if + end do + end if else if(.not.allocated(cmfd % egrid)) allocate(cmfd % egrid(2)) cmfd % egrid = [ ZERO, 20.0_8 ] diff --git a/src/constants.F90 b/src/constants.F90 index 123867719..0c6f09cdd 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -11,10 +11,10 @@ module constants integer, parameter :: VERSION_RELEASE = 1 ! Revision numbers for binary files - integer, parameter :: REVISION_STATEPOINT = 14 + integer, parameter :: REVISION_STATEPOINT = 15 integer, parameter :: REVISION_PARTICLE_RESTART = 1 integer, parameter :: REVISION_TRACK = 1 - integer, parameter :: REVISION_SUMMARY = 2 + integer, parameter :: REVISION_SUMMARY = 3 ! ============================================================================ ! ADJUSTABLE PARAMETERS @@ -161,9 +161,14 @@ module constants ! Angular distribution type integer, parameter :: & - ANGLE_ISOTROPIC = 1, & ! Isotropic angular distribution - ANGLE_32_EQUI = 2, & ! 32 equiprobable bins - ANGLE_TABULAR = 3 ! Tabular angular distribution + ANGLE_ISOTROPIC = 1, & ! Isotropic angular distribution (CE) + ANGLE_32_EQUI = 2, & ! 32 equiprobable bins (CE) + ANGLE_TABULAR = 3, & ! Tabular angular distribution (CE or MG) + ANGLE_LEGENDRE = 4, & ! Legendre angular distribution (MG) + ANGLE_HISTOGRAM = 5 ! Histogram angular distribution (MG) + + ! Number of mu bins to use when converting Legendres to tabular type + integer, parameter :: DEFAULT_NMU = 33 ! Secondary energy mode for S(a,b) inelastic scattering integer, parameter :: & @@ -207,6 +212,11 @@ module constants ACE_THERMAL = 2, & ! thermal S(a,b) scattering data ACE_DOSIMETRY = 3 ! dosimetry cross sections + ! MGXS Table Types + integer, parameter :: & + MGXS_ISOTROPIC = 1, & ! Isotropically Weighted Data + MGXS_ANGLE = 2 ! Data by Angular Bins + ! Fission neutron emission (nu) type integer, parameter :: & NU_NONE = 0, & ! No nu values (non-fissionable) diff --git a/src/cross_section.F90 b/src/cross_section.F90 index f874eb2a7..4f5d2252c 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -1,6 +1,6 @@ module cross_section - use ace_header, only: Nuclide, SAlphaBeta, Reaction, UrrData + use ace_header, only: Reaction, UrrData use constants use energy_grid, only: grid_method, log_spacing use error, only: fatal_error @@ -8,8 +8,10 @@ module cross_section use global use list_header, only: ListElemInt use material_header, only: Material + use nuclide_header use particle_header, only: Particle use random_lcg, only: prn + use sab_header, only: SAlphaBeta use search, only: binary_search implicit none @@ -146,8 +148,8 @@ contains integer :: i_low ! lower logarithmic mapping index integer :: i_high ! upper logarithmic mapping index real(8) :: f ! interp factor on nuclide energy grid - type(Nuclide), pointer :: nuc - type(Material), pointer :: mat + type(NuclideCE), pointer :: nuc + type(Material), pointer :: mat ! Set pointer to nuclide and material nuc => nuclides(i_nuclide) @@ -364,8 +366,8 @@ contains real(8) :: fission ! fission cross section real(8) :: inelastic ! inelastic cross section logical :: same_nuc ! do we know the xs for this nuclide at this energy? - type(UrrData), pointer :: urr - type(Nuclide), pointer :: nuc + type(UrrData), pointer :: urr + type(NuclideCE), pointer :: nuc micro_xs(i_nuclide) % use_ptable = .true. @@ -531,9 +533,9 @@ contains !=============================================================================== pure function elastic_xs_0K(E, nuc) result(xs_out) - real(8), intent(in) :: E ! trial energy - type(Nuclide), intent(in) :: nuc ! target nuclide at temperature - real(8) :: xs_out ! 0K xs at trial energy + real(8), intent(in) :: E ! trial energy + type(NuclideCE), intent(in) :: nuc ! target nuclide at temperature + real(8) :: xs_out ! 0K xs at trial energy integer :: i_grid ! index on nuclide energy grid real(8) :: f ! interp factor on nuclide energy grid diff --git a/src/distribution_multivariate.F90 b/src/distribution_multivariate.F90 index c288c40c1..694fac301 100644 --- a/src/distribution_multivariate.F90 +++ b/src/distribution_multivariate.F90 @@ -1,9 +1,9 @@ module distribution_multivariate - use constants, only: ONE, TWO, PI + use constants, only: ONE, TWO, PI use distribution_univariate, only: Distribution - use math, only: rotate_angle - use random_lcg, only: prn + use random_lcg, only: prn + use math, only: rotate_angle implicit none diff --git a/src/distribution_univariate.F90 b/src/distribution_univariate.F90 index f596536d0..f3e4fdee2 100644 --- a/src/distribution_univariate.F90 +++ b/src/distribution_univariate.F90 @@ -1,11 +1,11 @@ module distribution_univariate - use constants, only: ZERO, ONE, HALF, HISTOGRAM, LINEAR_LINEAR, & + use constants, only: ZERO, ONE, HALF, HISTOGRAM, LINEAR_LINEAR, & MAX_LINE_LEN, MAX_WORD_LEN - use error, only: fatal_error - use math, only: maxwell_spectrum, watt_spectrum + use error, only: fatal_error use random_lcg, only: prn - use string, only: to_lower + use math, only: maxwell_spectrum, watt_spectrum + use string, only: to_lower use xml_interface implicit none diff --git a/src/eigenvalue.F90 b/src/eigenvalue.F90 index 403347caa..e735bc8d8 100644 --- a/src/eigenvalue.F90 +++ b/src/eigenvalue.F90 @@ -4,16 +4,15 @@ module eigenvalue use message_passing #endif - use constants, only: ZERO - use error, only: fatal_error, warning + use constants, only: ZERO + use error, only: fatal_error, warning use global - use math, only: t_percentile - use mesh, only: count_bank_sites - use mesh_header, only: RegularMesh - use particle_header, only: Particle - use random_lcg, only: prn, set_particle_seed, prn_skip - use search, only: binary_search - use string, only: to_str + use math, only: t_percentile + use mesh, only: count_bank_sites + use mesh_header, only: RegularMesh + use random_lcg, only: prn, set_particle_seed, prn_skip + use search, only: binary_search + use string, only: to_str implicit none diff --git a/src/energy_distribution.F90 b/src/energy_distribution.F90 index db3dcc441..2cfc1b184 100644 --- a/src/energy_distribution.F90 +++ b/src/energy_distribution.F90 @@ -1,11 +1,11 @@ module energy_distribution - use constants, only: ZERO, ONE, TWO, PI, HISTOGRAM, LINEAR_LINEAR - use endf_header, only: Tab1 + use constants, only: ZERO, ONE, TWO, PI, HISTOGRAM, LINEAR_LINEAR + use endf_header, only: Tab1 use interpolation, only: interpolate_tab1 - use math, only: maxwell_spectrum, watt_spectrum - use random_lcg, only: prn - use search, only: binary_search + use math, only: maxwell_spectrum, watt_spectrum + use random_lcg, only: prn + use search, only: binary_search !=============================================================================== ! ENERGYDISTRIBUTION (abstract) defines an energy distribution that is a diff --git a/src/energy_grid.F90 b/src/energy_grid.F90 index 66419f83c..248462f70 100644 --- a/src/energy_grid.F90 +++ b/src/energy_grid.F90 @@ -27,7 +27,7 @@ contains integer :: i ! index in nuclides array integer :: j ! index in materials array type(ListReal) :: list - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc type(Material), pointer :: mat call write_message("Creating unionized energy grid...", 5) @@ -70,7 +70,7 @@ contains real(8) :: E_max ! Maximum energy in MeV real(8) :: E_min ! Minimum energy in MeV real(8), allocatable :: umesh(:) ! Equally log-spaced energy grid - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc ! Set minimum/maximum energies E_max = energy_max_neutron @@ -179,7 +179,7 @@ contains integer :: index_e ! index on union energy grid real(8) :: union_energy ! energy on union grid real(8) :: energy ! energy on nuclide grid - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc type(Material), pointer :: mat do k = 1, n_materials diff --git a/src/fission.F90 b/src/fission.F90 index a005d9f5b..77ee64178 100644 --- a/src/fission.F90 +++ b/src/fission.F90 @@ -1,10 +1,10 @@ module fission - use ace_header, only: Nuclide + use nuclide_header, only: NuclideCE use constants - use error, only: fatal_error - use interpolation, only: interpolate_tab1 - use search, only: binary_search + use error, only: fatal_error + use interpolation, only: interpolate_tab1 + use search, only: binary_search implicit none @@ -16,7 +16,7 @@ contains !=============================================================================== pure function nu_total(nuc, E) result(nu) - type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu real(8), intent(in) :: E ! energy of incoming neutron real(8) :: nu ! number of total neutrons emitted per fission @@ -49,7 +49,7 @@ contains !=============================================================================== pure function nu_prompt(nuc, E) result(nu) - type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu real(8), intent(in) :: E ! energy of incoming neutron real(8) :: nu ! number of prompt neutrons emitted per fission @@ -86,7 +86,7 @@ contains !=============================================================================== pure function nu_delayed(nuc, E) result(nu) - type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu real(8), intent(in) :: E ! energy of incoming neutron real(8) :: nu ! number of delayed neutrons emitted per fission @@ -109,7 +109,7 @@ contains !=============================================================================== pure function yield_delayed(nuc, E, g) result(yield) - type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu real(8), intent(in) :: E ! energy of incoming neutron real(8) :: yield ! delayed neutron precursor yield integer, intent(in) :: g ! the delayed neutron precursor group diff --git a/src/global.F90 b/src/global.F90 index 7652d1580..2abbe4212 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -1,15 +1,16 @@ module global - use ace_header, only: Nuclide, SAlphaBeta, xsListing, NuclideMicroXS, & - MaterialMacroXS, Nuclide0K use bank_header, only: Bank use cmfd_header use constants use dict_header, only: DictCharInt, DictIntInt use geometry_header, only: Cell, Universe, Lattice, LatticeContainer + use macroxs_header, only: MacroXSContainer use material_header, only: Material use mesh_header, only: RegularMesh + use nuclide_header use plot_header, only: ObjectPlot + use sab_header, only: SAlphaBeta use set_header, only: SetInt use surface_header, only: SurfaceContainer use source_header, only: SourceDistribution @@ -58,39 +59,75 @@ module global integer :: n_lost_particles ! ============================================================================ - ! CROSS SECTION RELATED VARIABLES + ! ENERGY TREATMENT RELATED VARIABLES + logical :: run_CE = .true. ! Run in CE mode? + + ! ============================================================================ + ! CROSS SECTION RELATED VARIABLES NEEDED REGARDLESS OF CE OR MG ! Cross section arrays - type(Nuclide), allocatable, target :: nuclides(:) ! Nuclide cross-sections - type(SAlphaBeta), allocatable, target :: sab_tables(:) ! S(a,b) tables type(XsListing), allocatable, target :: xs_listings(:) ! cross_sections.xml listings + integer :: n_nuclides_total ! Number of nuclide cross section tables + integer :: n_listings ! Number of listings in cross_sections.xml + ! Cross section caches type(NuclideMicroXS), allocatable :: micro_xs(:) ! Cache for each nuclide type(MaterialMacroXS) :: material_xs ! Cache for current material - integer :: n_nuclides_total ! Number of nuclide cross section tables + ! Dictionaries to look up cross sections and listings + type(DictCharInt) :: nuclide_dict + type(DictCharInt) :: xs_listing_dict + + ! Default xs identifier (e.g. 70c or 300K) + character(5):: default_xs + + ! ============================================================================ + ! CONTINUOUS-ENERGY CROSS SECTION RELATED VARIABLES + + ! Cross section arrays + type(NuclideCE), allocatable, target :: nuclides(:) ! Nuclide cross-sections + type(SAlphaBeta), allocatable, target :: sab_tables(:) ! S(a,b) tables + integer :: n_sab_tables ! Number of S(a,b) thermal scattering tables - integer :: n_listings ! Number of listings in cross_sections.xml ! Minimum/maximum energies real(8) :: energy_min_neutron = ZERO real(8) :: energy_max_neutron = INFINITY ! Dictionaries to look up cross sections and listings - type(DictCharInt) :: nuclide_dict type(DictCharInt) :: sab_dict - type(DictCharInt) :: xs_listing_dict ! Unreoslved resonance probablity tables logical :: urr_ptables_on = .true. - ! Default xs identifier (e.g. 70c) - character(3):: default_xs - ! What to assume for expanding natural elements integer :: default_expand = ENDF_BVII1 + ! ============================================================================ + ! MULTI-GROUP CROSS SECTION RELATED VARIABLES + + ! Cross section arrays + type(NuclideMGContainer), allocatable, target :: nuclides_MG(:) + + ! Cross section caches + type(MacroXSContainer), target, allocatable :: macro_xs(:) + + ! Number of energy groups + integer :: energy_groups + + ! Energy group structure + real(8), allocatable :: energy_bins(:) + + ! Midpoint of the energy group structure + real(8), allocatable :: energy_bin_avg(:) + + ! Inverse velocities of the energy groups (provided or estimated) + real(8), allocatable :: inverse_velocities(:) + + ! Maximum Data Order + integer :: max_order + ! ============================================================================ ! TALLY-RELATED VARIABLES @@ -444,6 +481,14 @@ contains deallocate(nuclides_0K) end if + if (allocated(nuclides_MG)) then + deallocate(nuclides_MG) + end if + + if (allocated(macro_xs)) then + deallocate(macro_xs) + end if + if (allocated(sab_tables)) deallocate(sab_tables) if (allocated(xs_listings)) deallocate(xs_listings) if (allocated(micro_xs)) deallocate(micro_xs) diff --git a/src/initialize.F90 b/src/initialize.F90 index de681fb94..52853f72f 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -1,30 +1,31 @@ module initialize - use ace, only: read_xs, same_nuclide_list - use bank_header, only: Bank + use ace, only: read_ace_xs, same_nuclide_list + use bank_header, only: Bank use constants - use dict_header, only: DictIntInt, ElemKeyValueII - use set_header, only: SetInt - use energy_grid, only: logarithmic_grid, grid_method, unionized_grid - use error, only: fatal_error, warning - use geometry, only: neighbor_lists, count_instance, calc_offsets, & - maximum_levels - use geometry_header, only: Cell, Universe, Lattice, RectLattice, HexLattice,& - &BASE_UNIVERSE + use dict_header, only: DictIntInt, ElemKeyValueII + use set_header, only: SetInt + use energy_grid, only: logarithmic_grid, grid_method, unionized_grid + use error, only: fatal_error, warning + use geometry, only: neighbor_lists, count_instance, calc_offsets, & + maximum_levels + use geometry_header, only: Cell, Universe, Lattice, RectLattice, HexLattice,& + &BASE_UNIVERSE use global - use hdf5_interface, only: file_open, read_dataset, file_close, hdf5_bank_t,& - hdf5_tallyresult_t, hdf5_integer8_t - use input_xml, only: read_input_xml, read_cross_sections_xml, & - cells_in_univ_dict, read_plots_xml - use material_header, only: Material - use output, only: title, header, print_version, write_message, & - print_usage, write_xs_summary, print_plot - use random_lcg, only: initialize_prng - use state_point, only: load_state_point - use string, only: to_str, str_to_int, starts_with, ends_with - use summary, only: write_summary - use tally_header, only: TallyObject, TallyResult, TallyFilter - use tally_initialize, only: configure_tallies + use hdf5_interface, only: file_open, read_dataset, file_close, hdf5_bank_t,& + hdf5_tallyresult_t, hdf5_integer8_t + use input_xml, only: read_input_xml, cells_in_univ_dict, read_plots_xml + use material_header, only: Material + use mgxs_data, only: read_mgxs, same_NuclideMG_list, create_macro_xs + use output, only: title, header, print_version, write_message, & + print_usage, write_xs_summary, print_plot + use random_lcg, only: initialize_prng + use state_point, only: load_state_point + use string, only: to_str, starts_with, ends_with, str_to_int + use summary, only: write_summary + use tally_header, only: TallyObject, TallyResult, TallyFilter + use tally_initialize,only: configure_tallies + use tally, only: init_tally_routines #ifdef MPI use message_passing @@ -114,27 +115,44 @@ contains ! Read ACE-format cross sections call time_read_xs%start() - call read_xs() + if (run_CE) then + call read_ace_xs() + else + call read_mgxs() + end if call time_read_xs%stop() ! Create linked lists for multiple instances of the same nuclide - call same_nuclide_list() + if (run_CE) then + call same_nuclide_list() + else + call same_nuclidemg_list() + end if - ! Construct unionized or log energy grid for cross-sections - select case (grid_method) - case (GRID_NUCLIDE) - continue - case (GRID_MAT_UNION) - call time_unionize%start() - call unionized_grid() - call time_unionize%stop() - case (GRID_LOGARITHM) - call logarithmic_grid() - end select + ! Construct information needed for nuclear data + if (run_CE) then + ! Construct unionized or log energy grid for cross-sections + select case (grid_method) + case (GRID_NUCLIDE) + continue + case (GRID_MAT_UNION) + call time_unionize%start() + call unionized_grid() + call time_unionize%stop() + case (GRID_LOGARITHM) + call logarithmic_grid() + end select + else + ! Create material macroscopic data for MGXS + call create_macro_xs() + end if ! Allocate and setup tally stride, matching_bins, and tally maps call configure_tallies() + ! Set up tally procedure pointers + call init_tally_routines() + ! Determine how much work each processor should do call calculate_work() diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 92840db5a..9ef439bb0 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -17,8 +17,8 @@ module input_xml use random_lcg, only: prn, seed use surface_header use stl_vector, only: VectorInt - use string, only: to_lower, to_str, str_to_int, str_to_real, & - starts_with, ends_with, tokenize + use string, only: str_to_int, str_to_real, tokenize, & + to_lower, to_str, starts_with, ends_with use tally_header, only: TallyObject, TallyFilter use tally_initialize, only: add_tallies use xml_interface @@ -39,7 +39,13 @@ contains subroutine read_input_xml() call read_settings_xml() - if (run_mode /= MODE_PLOTTING) call read_cross_sections_xml() + if (run_mode /= MODE_PLOTTING) then + if (run_CE) then + call read_ce_cross_sections_xml() + else + call read_mg_cross_sections_xml() + end if + end if call read_geometry_xml() call read_materials_xml() call read_tallies_xml() @@ -103,6 +109,17 @@ contains ! Parse settings.xml file call open_xmldoc(doc, filename) + ! Find if a multi-group or continuous-energy simulation is desired + if (check_for_node(doc, "energy_mode")) then + call get_node_value(doc, "energy_mode", temp_str) + temp_str = trim(to_lower(temp_str)) + if (temp_str == "mg" .or. temp_str == "multi-group") then + run_CE = .false. + else if (temp_str == "ce" .or. temp_str == "continuous-energy") then + run_CE = .true. + end if + end if + ! Find cross_sections.xml file -- the first place to look is the ! settings.xml file. If no file is found there, then we check the ! CROSS_SECTIONS environment variable @@ -111,22 +128,48 @@ contains run_mode /= MODE_PLOTTING) then ! No cross_sections.xml file specified in settings.xml, check ! environment variable - call get_environment_variable("CROSS_SECTIONS", env_variable) - if (len_trim(env_variable) == 0) then - call fatal_error("No cross_sections.xml file was specified in & - &settings.xml or in the CROSS_SECTIONS environment variable. & - &OpenMC needs a cross_sections.xml file to identify where to & - &find ACE cross section libraries. Please consult the user's & - &guide at http://mit-crpg.github.io/openmc for information on & - &how to set up ACE cross section libraries.") + if (run_CE) then + call get_environment_variable("OPENMC_CROSS_SECTIONS", env_variable) + if (len_trim(env_variable) == 0) then + call fatal_error("No cross_sections.xml file was specified in & + &settings.xml or in the OPENMC_CROSS_SECTIONS environment & + &variable. OpenMC needs such a file to identify where to & + &find ACE cross section libraries. Please consult the user's & + &guide at http://mit-crpg.github.io/openmc for information on & + &how to set up ACE cross section libraries.") + else + path_cross_sections = trim(env_variable) + end if else - path_cross_sections = trim(env_variable) + call get_environment_variable("OPENMC_MG_CROSS_SECTIONS", env_variable) + if (len_trim(env_variable) == 0) then + call fatal_error("No cross_sections.xml file was specified in & + &settings.xml or in the OPENMC_MG_CROSS_SECTIONS environment & + &variable. OpenMC needs such a file to identify where to & + &find the cross section libraries. Please consult the user's & + &guide at http://mit-crpg.github.io/openmc for information on & + &how to set up the cross section libraries.") + else + path_cross_sections = trim(env_variable) + end if end if else call get_node_value(doc, "cross_sections", path_cross_sections) end if end if + if (.not. run_CE) then + ! Scattering Treatments + if (check_for_node(doc, "max_order")) then + call get_node_value(doc, "max_order", max_order) + else + ! Set to default of largest int, which means to use whatever is contained in library + max_order = huge(0) + end if + else + max_order = 0 + end if + ! Set output directory if a path has been specified on the ! element if (check_for_node(doc, "output_path")) then @@ -173,8 +216,8 @@ contains end if ! Make sure that either eigenvalue or fixed source was specified - if (.not.check_for_node(doc, "eigenvalue") .and. & - .not.check_for_node(doc, "fixed_source")) then + if (.not. check_for_node(doc, "eigenvalue") .and. & + .not. check_for_node(doc, "fixed_source")) then call fatal_error(" or not specified.") end if @@ -187,7 +230,7 @@ contains call get_node_ptr(doc, "eigenvalue", node_mode) ! Check number of particles - if (.not.check_for_node(node_mode, "particles")) then + if (.not. check_for_node(node_mode, "particles")) then call fatal_error("Need to specify number of particles per generation.") end if @@ -257,7 +300,7 @@ contains call get_node_ptr(doc, "fixed_source", node_mode) ! Check number of particles - if (.not.check_for_node(node_mode, "particles")) then + if (.not. check_for_node(node_mode, "particles")) then call fatal_error("Need to specify number of particles per batch.") end if @@ -953,7 +996,7 @@ contains ! check to make sure a nuclide is specified if (.not. check_for_node(node_scatterer, "nuclide")) then call fatal_error("No nuclide specified for scatterer " & - &// trim(to_str(i)) // " in settings.xml file!") + // trim(to_str(i)) // " in settings.xml file!") end if call get_node_value(node_scatterer, "nuclide", & nuclides_0K(i) % nuclide) @@ -967,7 +1010,7 @@ contains if (.not. check_for_node(node_scatterer, "xs_label")) then call fatal_error("Must specify the temperature dependent name of & &scatterer " // trim(to_str(i)) & - &// " given in cross_sections.xml") + // " given in cross_sections.xml") end if call get_node_value(node_scatterer, "xs_label", & nuclides_0K(i) % name) @@ -975,7 +1018,7 @@ contains ! check to make sure 0K xs name for which method is applied is given if (.not. check_for_node(node_scatterer, "xs_label_0K")) then call fatal_error("Must specify the 0K name of scatterer " & - &// trim(to_str(i)) // " given in cross_sections.xml") + // trim(to_str(i)) // " given in cross_sections.xml") end if call get_node_value(node_scatterer, "xs_label_0K", & nuclides_0K(i) % name_0K) @@ -1035,7 +1078,7 @@ contains default_expand = JENDL_40 case default call fatal_error("Unknown natural element expansion option: " & - &// trim(temp_str)) + // trim(temp_str)) end select end if @@ -1152,7 +1195,7 @@ contains ! Check to make sure 'id' hasn't been used if (cell_dict % has_key(c % id)) then call fatal_error("Two or more cells use the same unique ID: " & - &// to_str(c % id)) + // to_str(c % id)) end if ! Read material @@ -1254,7 +1297,7 @@ contains n = get_arraysize_double(node_cell, "rotation") if (n /= 3) then call fatal_error("Incorrect number of rotation parameters on cell " & - &// to_str(c % id)) + // to_str(c % id)) end if ! Copy rotation angles in x,y,z directions @@ -1282,7 +1325,7 @@ contains ! another universe if (c % fill == NONE) then call fatal_error("Cannot apply a translation to cell " & - &// trim(to_str(c % id)) // " because it is not filled with & + // trim(to_str(c % id)) // " because it is not filled with & &another universe") end if @@ -1398,7 +1441,7 @@ contains ! Check to make sure 'id' hasn't been used if (surface_dict % has_key(s%id)) then call fatal_error("Two or more surfaces use the same unique ID: " & - &// to_str(s%id)) + // to_str(s%id)) end if ! Copy surface name @@ -1413,10 +1456,10 @@ contains n = get_arraysize_double(node_surf, "coeffs") if (n < coeffs_reqd) then call fatal_error("Not enough coefficients specified for surface: " & - &// trim(to_str(s%id))) + // trim(to_str(s%id))) elseif (n > coeffs_reqd) then call fatal_error("Too many coefficients specified for surface: " & - &// trim(to_str(s%id))) + // trim(to_str(s%id))) end if allocate(coeffs(n)) @@ -1542,7 +1585,7 @@ contains ! Check to make sure 'id' hasn't been used if (lattice_dict % has_key(lat % id)) then call fatal_error("Two or more lattices use the same unique ID: " & - &// to_str(lat % id)) + // to_str(lat % id)) end if ! Copy lattice name @@ -1670,7 +1713,7 @@ contains ! Check to make sure 'id' hasn't been used if (lattice_dict % has_key(lat % id)) then call fatal_error("Two or more lattices use the same unique ID: " & - &// to_str(lat % id)) + // to_str(lat % id)) end if ! Copy lattice name @@ -1872,6 +1915,7 @@ contains type(Node), pointer :: node_sab => null() type(NodeList), pointer :: node_mat_list => null() type(NodeList), pointer :: node_nuc_list => null() + type(NodeList), pointer :: node_macro_list => null() type(NodeList), pointer :: node_ele_list => null() type(NodeList), pointer :: node_sab_list => null() @@ -1923,12 +1967,13 @@ contains ! Check to make sure 'id' hasn't been used if (material_dict % has_key(mat % id)) then call fatal_error("Two or more materials use the same unique ID: " & - &// to_str(mat % id)) + // to_str(mat % id)) end if ! Copy material name if (check_for_node(node_mat, "name")) then call get_node_value(node_mat, "name", mat % name) + mat % name = to_lower(mat % name) end if if (run_mode == MODE_PLOTTING) then @@ -1945,7 +1990,7 @@ contains call get_node_ptr(node_mat, "density", node_dens) else call fatal_error("Must specify density element in material " & - &// trim(to_str(mat % id))) + // trim(to_str(mat % id))) end if ! Initialize value to zero @@ -1961,6 +2006,19 @@ contains sum_density = .true. + else if (units == 'macro') then + if (check_for_node(node_dens, "value")) then + ! Copy value + call get_node_value(node_dens, "value", val) + else + val = ONE + end if + + ! Set density + mat % density = val + + sum_density = .false. + else ! Copy value call get_node_value(node_dens, "value", val) @@ -1969,7 +2027,7 @@ contains sum_density = .false. if (val <= ZERO) then call fatal_error("Need to specify a positive density on material " & - &// trim(to_str(mat % id)) // ".") + // trim(to_str(mat % id)) // ".") end if ! Adjust material density based on specified units @@ -1984,7 +2042,7 @@ contains mat % density = 1.0e-24_8 * val case default call fatal_error("Unkwown units '" // trim(units) & - &// "' specified on material " // trim(to_str(mat % id))) + // "' specified on material " // trim(to_str(mat % id))) end select end if @@ -1993,32 +2051,41 @@ contains ! Check to ensure material has at least one nuclide if (.not. check_for_node(node_mat, "nuclide") .and. & - .not. check_for_node(node_mat, "element")) then - call fatal_error("No nuclides or natural elements specified on & - &material " // trim(to_str(mat % id))) + .not. check_for_node(node_mat, "element") .and. & + .not. check_for_node(node_mat, "macroscopic")) then + call fatal_error("No macroscopic data, nuclides or natural elements & + &specified on material " // trim(to_str(mat % id))) end if - ! Get pointer list of XML - call get_node_list(node_mat, "nuclide", node_nuc_list) + ! Create list of macroscopic x/s based on those specified, just treat + ! them as nuclides. This is all really a facade so the user thinks they + ! are entering in macroscopic data but the code treats them the same + ! as nuclides internally. + ! Get pointer list of XML + call get_node_list(node_mat, "macroscopic", node_macro_list) + if (run_CE .and. (get_list_size(node_macro_list) > 0)) then + call fatal_error("Macroscopic can not be used in continuous-energy& + & mode!") + else if (get_list_size(node_macro_list) > 1) then + call fatal_error("Only one macroscopic object permitted per material, " & + // trim(to_str(mat % id))) + else if (get_list_size(node_macro_list) == 1) then - ! Create list of nuclides based on those specified plus natural elements - INDIVIDUAL_NUCLIDES: do j = 1, get_list_size(node_nuc_list) - ! Combine nuclide identifier and cross section and copy into names - call get_list_item(node_nuc_list, j, node_nuc) + call get_list_item(node_macro_list, 1, node_nuc) ! Check for empty name on nuclide - if (.not.check_for_node(node_nuc, "name")) then - call fatal_error("No name specified on nuclide in material " & - &// trim(to_str(mat % id))) + if (.not. check_for_node(node_nuc, "name")) then + call fatal_error("No name specified on macroscopic data in material " & + // trim(to_str(mat % id))) end if ! Check for cross section - if (.not.check_for_node(node_nuc, "xs")) then + if (.not. check_for_node(node_nuc, "xs")) then if (default_xs == '') then - call fatal_error("No cross section specified for nuclide in & - &material " // trim(to_str(mat % id))) + call fatal_error("No cross section specified for macroscopic data & + & in material " // trim(to_str(mat % id))) else - name = trim(default_xs) + name = to_lower(trim(default_xs)) end if end if @@ -2042,31 +2109,81 @@ contains if (check_for_node(node_nuc, "xs")) & call get_node_value(node_nuc, "xs", name) name = trim(temp_str) // "." // trim(name) + name = to_lower(name) ! save name and density to list call list_names % append(name) ! Check if no atom/weight percents were specified or if both atom and ! weight percents were specified - if (.not.check_for_node(node_nuc, "ao") .and. & - .not.check_for_node(node_nuc, "wo")) then - call fatal_error("No atom or weight percent specified for nuclide " & - &// trim(name)) - elseif (check_for_node(node_nuc, "ao") .and. & - check_for_node(node_nuc, "wo")) then - call fatal_error("Cannot specify both atom and weight percents for a & - &nuclide: " // trim(name)) - end if - - ! Copy atom/weight percents - if (check_for_node(node_nuc, "ao")) then - call get_node_value(node_nuc, "ao", temp_dble) - call list_density % append(temp_dble) + if (units == 'macro') then + call list_density % append(ONE) else - call get_node_value(node_nuc, "wo", temp_dble) - call list_density % append(-temp_dble) + call fatal_error("Units can only be macro for macroscopic data " & + // trim(name)) end if - end do INDIVIDUAL_NUCLIDES + else + + ! Get pointer list of XML + call get_node_list(node_mat, "nuclide", node_nuc_list) + + ! Create list of nuclides based on those specified plus natural elements + INDIVIDUAL_NUCLIDES: do j = 1, get_list_size(node_nuc_list) + ! Combine nuclide identifier and cross section and copy into names + call get_list_item(node_nuc_list, j, node_nuc) + + ! Check for empty name on nuclide + if (.not. check_for_node(node_nuc, "name")) then + call fatal_error("No name specified on nuclide in material " & + // trim(to_str(mat % id))) + end if + + ! Check for cross section + if (.not. check_for_node(node_nuc, "xs")) then + if (default_xs == '') then + call fatal_error("No cross section specified for nuclide in & + &material " // trim(to_str(mat % id))) + else + name = to_lower(trim(default_xs)) + end if + end if + + ! store full name + call get_node_value(node_nuc, "name", temp_str) + if (check_for_node(node_nuc, "xs")) & + call get_node_value(node_nuc, "xs", name) + name = trim(temp_str) // "." // trim(name) + name = to_lower(name) + + ! save name and density to list + call list_names % append(name) + + ! Check if no atom/weight percents were specified or if both atom and + ! weight percents were specified + if (units == 'macro') then + call list_density % append(ONE) + else + if (.not. check_for_node(node_nuc, "ao") .and. & + .not. check_for_node(node_nuc, "wo")) then + call fatal_error("No atom or weight percent specified for nuclide " & + // trim(name)) + elseif (check_for_node(node_nuc, "ao") .and. & + check_for_node(node_nuc, "wo")) then + call fatal_error("Cannot specify both atom and weight percents for a & + &nuclide: " // trim(name)) + end if + + ! Copy atom/weight percents + if (check_for_node(node_nuc, "ao")) then + call get_node_value(node_nuc, "ao", temp_dble) + call list_density % append(temp_dble) + else + call get_node_value(node_nuc, "wo", temp_dble) + call list_density % append(-temp_dble) + end if + end if + end do INDIVIDUAL_NUCLIDES + end if ! ======================================================================= ! READ AND PARSE TAGS @@ -2078,9 +2195,9 @@ contains call get_list_item(node_ele_list, j, node_ele) ! Check for empty name on natural element - if (.not.check_for_node(node_ele, "name")) then + if (.not. check_for_node(node_ele, "name")) then call fatal_error("No name specified on nuclide in material " & - &// trim(to_str(mat % id))) + // trim(to_str(mat % id))) end if call get_node_value(node_ele, "name", name) @@ -2092,16 +2209,16 @@ contains call fatal_error("No cross section specified for nuclide in & &material " // trim(to_str(mat % id))) else - temp_str = trim(default_xs) + temp_str = to_lower(trim(default_xs)) end if end if ! Check if no atom/weight percents were specified or if both atom and ! weight percents were specified - if (.not.check_for_node(node_ele, "ao") .and. & - .not.check_for_node(node_ele, "wo")) then + if (.not. check_for_node(node_ele, "ao") .and. & + .not. check_for_node(node_ele, "wo")) then call fatal_error("No atom or weight percent specified for element " & - &// trim(name)) + // trim(name)) elseif (check_for_node(node_ele, "ao") .and. & check_for_node(node_ele, "wo")) then call fatal_error("Cannot specify both atom and weight percents for & @@ -2161,14 +2278,16 @@ contains name = trim(list_names % get_item(j)) if (.not. xs_listing_dict % has_key(to_lower(name))) then call fatal_error("Could not find nuclide " // trim(name) & - &// " in cross_sections.xml file!") + // " in cross_sections data file!") end if - ! Check to make sure cross-section is continuous energy neutron table - n = len_trim(name) - if (name(n:n) /= 'c') then - call fatal_error("Cross-section table " // trim(name) & - &// " is not a continuous-energy neutron table.") + if (run_CE) then + ! Check to make sure cross-section is continuous energy neutron table + n = len_trim(name) + if (name(n:n) /= 'c') then + call fatal_error("Cross-section table " // trim(name) & + // " is not a continuous-energy neutron table.") + end if end if ! Find xs_listing and set the name/alias according to the listing @@ -2206,7 +2325,7 @@ contains if (.not. (all(mat % atom_density >= ZERO) .or. & all(mat % atom_density <= ZERO))) then call fatal_error("Cannot mix atom and weight percents in material " & - &// to_str(mat % id)) + // to_str(mat % id)) end if ! Determine density if it is a sum value @@ -2219,59 +2338,60 @@ contains ! ======================================================================= ! READ AND PARSE TAG FOR S(a,b) DATA + if (run_CE) then + ! Get pointer list to XML + call get_node_list(node_mat, "sab", node_sab_list) - ! Get pointer list to XML - call get_node_list(node_mat, "sab", node_sab_list) + n_sab = get_list_size(node_sab_list) + if (n_sab > 0) then + ! Set number of S(a,b) tables + mat % n_sab = n_sab - n_sab = get_list_size(node_sab_list) - if (n_sab > 0) then - ! Set number of S(a,b) tables - mat % n_sab = n_sab + ! Allocate names and indices for nuclides and tables + allocate(mat % sab_names(n_sab)) + allocate(mat % i_sab_nuclides(n_sab)) + allocate(mat % i_sab_tables(n_sab)) - ! Allocate names and indices for nuclides and tables - allocate(mat % sab_names(n_sab)) - allocate(mat % i_sab_nuclides(n_sab)) - allocate(mat % i_sab_tables(n_sab)) + ! Initialize i_sab_nuclides + mat % i_sab_nuclides = NONE - ! Initialize i_sab_nuclides - mat % i_sab_nuclides = NONE + do j = 1, n_sab + ! Get pointer to S(a,b) table + call get_list_item(node_sab_list, j, node_sab) - do j = 1, n_sab - ! Get pointer to S(a,b) table - call get_list_item(node_sab_list, j, node_sab) + ! Determine name of S(a,b) table + if (.not. check_for_node(node_sab, "name") .or. & + .not. check_for_node(node_sab, "xs")) then + call fatal_error("Need to specify and for S(a,b) & + &table.") + end if + call get_node_value(node_sab, "name", name) + call get_node_value(node_sab, "xs", temp_str) + name = trim(name) // "." // trim(temp_str) + mat % sab_names(j) = name - ! Determine name of S(a,b) table - if (.not.check_for_node(node_sab, "name") .or. & - .not.check_for_node(node_sab, "xs")) then - call fatal_error("Need to specify and for S(a,b) & - &table.") - end if - call get_node_value(node_sab, "name", name) - call get_node_value(node_sab, "xs", temp_str) - name = trim(name) // "." // trim(temp_str) - mat % sab_names(j) = name + ! Check that this nuclide is listed in the cross_sections.xml file + if (.not. xs_listing_dict % has_key(to_lower(name))) then + call fatal_error("Could not find S(a,b) table " // trim(name) & + // " in cross_sections.xml file!") + end if - ! Check that this nuclide is listed in the cross_sections.xml file - if (.not. xs_listing_dict % has_key(to_lower(name))) then - call fatal_error("Could not find S(a,b) table " // trim(name) & - &// " in cross_sections.xml file!") - end if + ! Find index in xs_listing and set the name and alias according to the + ! listing + index_list = xs_listing_dict % get_key(to_lower(name)) + name = xs_listings(index_list) % name - ! Find index in xs_listing and set the name and alias according to the - ! listing - index_list = xs_listing_dict % get_key(to_lower(name)) - name = xs_listings(index_list) % name - - ! If this S(a,b) table hasn't been encountered yet, we need to add its - ! name and alias to the sab_dict - if (.not. sab_dict % has_key(to_lower(name))) then - index_sab = index_sab + 1 - mat % i_sab_tables(j) = index_sab - call sab_dict % add_key(to_lower(name), index_sab) - else - mat % i_sab_tables(j) = sab_dict % get_key(to_lower(name)) - end if - end do + ! If this S(a,b) table hasn't been encountered yet, we need to add its + ! name and alias to the sab_dict + if (.not. sab_dict % has_key(to_lower(name))) then + index_sab = index_sab + 1 + mat % i_sab_tables(j) = index_sab + call sab_dict % add_key(to_lower(name), index_sab) + else + mat % i_sab_tables(j) = sab_dict % get_key(to_lower(name)) + end if + end do + end if end if ! Add material to dictionary @@ -2415,7 +2535,7 @@ contains ! Check to make sure 'id' hasn't been used if (mesh_dict % has_key(m % id)) then call fatal_error("Two or more meshes use the same unique ID: " & - &// to_str(m % id)) + // to_str(m % id)) end if ! Read mesh type @@ -2471,8 +2591,8 @@ contains end if ! Make sure either upper-right or width was specified - if (.not.check_for_node(node_mesh, "upper_right") .and. & - .not.check_for_node(node_mesh, "width")) then + if (.not. check_for_node(node_mesh, "upper_right") .and. & + .not. check_for_node(node_mesh, "width")) then call fatal_error("Must specify either and on a & &tally mesh.") end if @@ -2556,7 +2676,7 @@ contains ! Check to make sure 'id' hasn't been used if (tally_dict % has_key(t % id)) then call fatal_error("Two or more tallies use the same unique ID: " & - &// to_str(t % id)) + // to_str(t % id)) end if ! Copy tally name @@ -2597,7 +2717,7 @@ contains end if else call fatal_error("Bins not set in filter on tally " & - &// trim(to_str(t % id))) + // trim(to_str(t % id))) end if ! Determine type of filter @@ -2689,7 +2809,7 @@ contains m => meshes(i_mesh) else call fatal_error("Could not find mesh " // trim(to_str(id)) & - &// " specified on tally " // trim(to_str(t % id))) + // " specified on tally " // trim(to_str(t % id))) end if ! Determine number of bins -- this is assuming that the tally is @@ -2712,6 +2832,14 @@ contains allocate(t % filters(j) % real_bins(n_words)) call get_node_array(node_filt, "bins", t % filters(j) % real_bins) + if (.not. run_CE) then + if (n_words /= energy_groups + 1) then + t % energy_matches_groups = .false. + else if (all(t % filters(j) % real_bins == energy_bins)) then + t % energy_matches_groups = .false. + end if + end if + case ('energyout') ! Set type of filter t % filters(j) % type = FILTER_ENERGYOUT @@ -2723,10 +2851,27 @@ contains allocate(t % filters(j) % real_bins(n_words)) call get_node_array(node_filt, "bins", t % filters(j) % real_bins) + if (.not. run_CE) then + if (n_words /= energy_groups + 1) then + t % energy_matches_groups = .false. + else if (all(t % filters(j) % real_bins == energy_bins)) then + t % energy_matches_groups = .false. + end if + end if + ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG case ('delayedgroup') + ! Check to see if running in MG mode, because if so, the current + ! system isnt set up yet to support delayed group data and thus + ! these tallies + if (.not. run_CE) then + call fatal_error("delayedgroup filter on tally " & + // trim(to_str(t % id)) // " not yet supported& + & for multi-group mode.") + end if + ! Set type of filter t % filters(j) % type = FILTER_DELAYEDGROUP @@ -2848,8 +2993,8 @@ contains case default ! Specified tally filter is invalid, raise error call fatal_error("Unknown filter type '" & - &// trim(temp_str) // "' on tally " & - &// trim(to_str(t % id)) // ".") + // trim(temp_str) // "' on tally " & + // trim(to_str(t % id)) // ".") end select @@ -2927,7 +3072,7 @@ contains ! Append default_xs specifier to nuclide if needed if ((default_xs /= '') .and. (.not. ends_with(sarray(j), 'c'))) then - word = trim(word) // "." // default_xs + word = trim(word) // "." // trim(default_xs) end if ! Search through nuclides @@ -2945,8 +3090,8 @@ contains ! Check if no nuclide was found if (.not. associated(pair_list)) then call fatal_error("Could not find the nuclide " & - &// trim(word) // " specified in tally " & - &// trim(to_str(t % id)) // " in any material.") + // trim(word) // " specified in tally " & + // trim(to_str(t % id)) // " in any material.") end if deallocate(pair_list) @@ -3014,12 +3159,12 @@ contains ! maximum order. ! The above scheme will essentially take the absolute value if (master) call warning("Invalid scattering order of " & - &// trim(to_str(n_order)) // " requested. Setting to the & + // trim(to_str(n_order)) // " requested. Setting to the & &maximum permissible value, " & - &// trim(to_str(MAX_ANG_ORDER))) + // trim(to_str(MAX_ANG_ORDER))) n_order = MAX_ANG_ORDER sarray(j) = trim(MOMENT_STRS(imomstr)) & - &// trim(to_str(MAX_ANG_ORDER)) + // trim(to_str(MAX_ANG_ORDER)) end if ! Find total number of bins for this case if (imomstr >= YN_LOC) then @@ -3081,9 +3226,9 @@ contains ! maximum order. ! The above scheme will essentially take the absolute value if (master) call warning("Invalid scattering order of " & - &// trim(to_str(n_order)) // " requested. Setting to & + // trim(to_str(n_order)) // " requested. Setting to & &the maximum permissible value, " & - &// trim(to_str(MAX_ANG_ORDER))) + // trim(to_str(MAX_ANG_ORDER))) n_order = MAX_ANG_ORDER end if score_name = trim(MOMENT_N_STRS(imomstr)) // "n" @@ -3265,6 +3410,12 @@ contains ! Set tally estimator to analog t % estimator = ESTIMATOR_ANALOG end if + + ! Disallow for MG mode since data not present + if (.not. run_CE) then + call fatal_error("Cannot tally delayed nu-fission rate in & + &multi-group mode") + end if case ('kappa-fission') t % score_bins(j) = SCORE_KAPPA_FISSION case ('inverse-velocity') @@ -3410,16 +3561,24 @@ contains t % score_bins(j) = MT else call fatal_error("Invalid MT on : " & - &// trim(sarray(l))) + // trim(sarray(l))) end if else ! Specified score was not an integer call fatal_error("Unknown scoring function: " & - &// trim(sarray(l))) + // trim(sarray(l))) end if end select + + ! Do a check at the end (instead of for every case) to make sure + ! the tallies are compatible with MG mode where we have less detailed + ! nuclear data + if (.not. run_CE .and. t % score_bins(j) > 0) then + call fatal_error("Cannot tally " // trim(score_name) // & + " reaction rate in multi-group mode") + end if end do t % n_score_bins = n_scores @@ -3455,7 +3614,7 @@ contains end do else call fatal_error("No specified on tally " & - &// trim(to_str(t % id)) // ".") + // trim(to_str(t % id)) // ".") end if ! If settings.xml trigger is turned on, create tally triggers @@ -3716,7 +3875,7 @@ contains inquire(FILE=filename, EXIST=file_exists) if (.not. file_exists) then call fatal_error("Plots XML file '" // trim(filename) & - &// "' does not exist!") + // "' does not exist!") end if ! Display output message @@ -3748,7 +3907,7 @@ contains ! Check to make sure 'id' hasn't been used if (plot_dict % has_key(pl % id)) then call fatal_error("Two or more plots use the same unique ID: " & - &// to_str(pl % id)) + // to_str(pl % id)) end if ! Copy plot type @@ -3763,7 +3922,7 @@ contains pl % type = PLOT_TYPE_VOXEL case default call fatal_error("Unsupported plot type '" // trim(temp_str) & - &// "' in plot " // trim(to_str(pl % id))) + // "' in plot " // trim(to_str(pl % id))) end select ! Set output file path @@ -3783,14 +3942,14 @@ contains call get_node_array(node_plot, "pixels", pl % pixels(1:2)) else call fatal_error(" must be length 2 in slice plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if else if (pl % type == PLOT_TYPE_VOXEL) then if (get_arraysize_integer(node_plot, "pixels") == 3) then call get_node_array(node_plot, "pixels", pl % pixels(1:3)) else call fatal_error(" must be length 3 in voxel plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if end if @@ -3798,13 +3957,13 @@ contains if (check_for_node(node_plot, "background")) then if (pl % type == PLOT_TYPE_VOXEL) then if (master) call warning("Background color ignored in voxel plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if if (get_arraysize_integer(node_plot, "background") == 3) then call get_node_array(node_plot, "background", pl % not_found % rgb) else call fatal_error("Bad background RGB in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if else pl % not_found % rgb = (/ 255, 255, 255 /) @@ -3825,7 +3984,7 @@ contains pl % basis = PLOT_BASIS_YZ case default call fatal_error("Unsupported plot basis '" // trim(temp_str) & - &// "' in plot " // trim(to_str(pl % id))) + // "' in plot " // trim(to_str(pl % id))) end select end if @@ -3834,7 +3993,7 @@ contains call get_node_array(node_plot, "origin", pl % origin) else call fatal_error("Origin must be length 3 in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if ! Copy plotting width @@ -3843,14 +4002,14 @@ contains call get_node_array(node_plot, "width", pl % width(1:2)) else call fatal_error(" must be length 2 in slice plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if else if (pl % type == PLOT_TYPE_VOXEL) then if (get_arraysize_double(node_plot, "width") == 3) then call get_node_array(node_plot, "width", pl % width(1:3)) else call fatal_error(" must be length 3 in voxel plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if end if @@ -3860,7 +4019,7 @@ contains if (pl % level < 0) then call fatal_error("Bad universe level in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if else pl % level = PLOT_LEVEL_LOWEST @@ -3894,7 +4053,7 @@ contains case default call fatal_error("Unsupported plot color type '" // trim(temp_str) & - &// "' in plot " // trim(to_str(pl % id))) + // "' in plot " // trim(to_str(pl % id))) end select ! Get the number of nodes and get a list of them @@ -3917,7 +4076,7 @@ contains ! Check and make sure 3 values are specified for RGB if (get_arraysize_double(node_col, "rgb") /= 3) then call fatal_error("Bad RGB in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if ! Ensure that there is an id for this color specification @@ -3936,7 +4095,7 @@ contains call get_node_array(node_col, "rgb", pl % colors(col_id) % rgb) else call fatal_error("Could not find cell " // trim(to_str(col_id)) & - &// " specified in plot " // trim(to_str(pl % id))) + // " specified in plot " // trim(to_str(pl % id))) end if else if (pl % color_by == PLOT_COLOR_MATS) then @@ -3946,8 +4105,8 @@ contains call get_node_array(node_col, "rgb", pl % colors(col_id) % rgb) else call fatal_error("Could not find material " & - &// trim(to_str(col_id)) // " specified in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(col_id)) // " specified in plot " & + // trim(to_str(pl % id))) end if end if @@ -3961,7 +4120,7 @@ contains if (pl % type == PLOT_TYPE_VOXEL) then call warning("Meshlines ignored in voxel plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if select case(n_meshlines) @@ -3995,7 +4154,7 @@ contains ! Check and make sure 3 values are specified for RGB if (get_arraysize_double(node_meshlines, "color") /= 3) then call fatal_error("Bad RGB for meshlines color in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if call get_node_array(node_meshlines, "color", & @@ -4012,7 +4171,7 @@ contains if (.not. associated(ufs_mesh)) then call fatal_error("No UFS mesh for meshlines on plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if pl % meshlines_mesh => ufs_mesh @@ -4033,7 +4192,7 @@ contains if (.not. associated(entropy_mesh)) then call fatal_error("No entropy mesh for meshlines on plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if if (.not. allocated(entropy_mesh % dimension)) then @@ -4062,18 +4221,18 @@ contains end if else call fatal_error("Could not find mesh " & - &// trim(to_str(meshid)) // " specified in meshlines for & + // trim(to_str(meshid)) // " specified in meshlines for & &plot " // trim(to_str(pl % id))) end if case default call fatal_error("Invalid type for meshlines on plot " & - &// trim(to_str(pl % id)) // ": " // trim(meshtype)) + // trim(to_str(pl % id)) // ": " // trim(meshtype)) end select case default call fatal_error("Mutliple meshlines specified in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end select end if @@ -4085,13 +4244,13 @@ contains if (pl % type == PLOT_TYPE_VOXEL) then if (master) call warning("Mask ignored in voxel plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if select case(n_masks) case default call fatal_error("Mutliple masks specified in plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) case (1) ! Get pointer to mask @@ -4102,7 +4261,7 @@ contains n_comp = get_arraysize_integer(node_mask, "components") if (n_comp == 0) then call fatal_error("Missing in mask of plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if allocate(iarray(n_comp)) call get_node_array(node_mask, "components", iarray) @@ -4118,7 +4277,7 @@ contains iarray(j) = cell_dict % get_key(col_id) else call fatal_error("Could not find cell " & - &// trim(to_str(col_id)) // " specified in the mask in & + // trim(to_str(col_id)) // " specified in the mask in & &plot " // trim(to_str(pl % id))) end if @@ -4128,7 +4287,7 @@ contains iarray(j) = material_dict % get_key(col_id) else call fatal_error("Could not find material " & - &// trim(to_str(col_id)) // " specified in the mask in & + // trim(to_str(col_id)) // " specified in the mask in & &plot " // trim(to_str(pl % id))) end if @@ -4142,7 +4301,7 @@ contains call get_node_array(node_mask, "background", pl % colors(j) % rgb) else call fatal_error("Missing in mask of plot " & - &// trim(to_str(pl % id))) + // trim(to_str(pl % id))) end if end if end do @@ -4164,11 +4323,11 @@ contains end subroutine read_plots_xml !=============================================================================== -! READ_CROSS_SECTIONS_XML reads information from a cross_sections.xml file. This -! file contains a listing of the ACE cross sections that may be used. +! READ_*_CROSS_SECTIONS_XML reads information from a cross_sections.xml file. This +! file contains a listing of the CE and MG cross sections that may be used. !=============================================================================== - subroutine read_cross_sections_xml() + subroutine read_ce_cross_sections_xml() integer :: i ! loop index integer :: filetype ! default file type @@ -4187,7 +4346,7 @@ contains if (.not. file_exists) then ! Could not find cross_sections.xml file call fatal_error("Cross sections XML file '" & - &// trim(path_cross_sections) // "' does not exist!") + // trim(path_cross_sections) // "' does not exist!") end if call write_message("Reading cross sections XML file...", 5) @@ -4217,7 +4376,7 @@ contains filetype = ASCII else call fatal_error("Unknown filetype in cross_sections.xml: " & - &// trim(temp_str)) + // trim(temp_str)) end if ! copy default record length and entries for binary files @@ -4281,7 +4440,7 @@ contains end if ! determine metastable state - if (.not.check_for_node(node_ace, "metastable")) then + if (.not. check_for_node(node_ace, "metastable")) then listing % metastable = .false. else listing % metastable = .true. @@ -4315,15 +4474,129 @@ contains do i = 1, n_res_scatterers_total if (.not. xs_listing_dict % has_key(trim(nuclides_0K(i) % name_0K))) then call fatal_error("Could not find nuclide " & - &// trim(nuclides_0K(i) % name_0K) & - &// " in cross_sections.xml file!") + // trim(nuclides_0K(i) % name_0K) & + // " in cross_sections.xml file!") end if end do ! Close cross sections XML file call close_xmldoc(doc) - end subroutine read_cross_sections_xml + end subroutine read_ce_cross_sections_xml + + subroutine read_mg_cross_sections_xml() + + integer :: i ! loop index + logical :: file_exists ! does cross_sections.xml exist? + type(XsListing), pointer :: listing => null() + type(Node), pointer :: doc => null() + type(Node), pointer :: node_xsdata => null() + type(NodeList), pointer :: node_xsdata_list => null() + + ! Check if cross_sections.xml exists + inquire(FILE=path_cross_sections, EXIST=file_exists) + if (.not. file_exists) then + ! Could not find cross_sections.xml file + call fatal_error("Cross sections XML file '" & + // trim(path_cross_sections) // "' does not exist!") + end if + + call write_message("Reading cross sections XML file...", 5) + + ! Parse cross_sections.xml file + call open_xmldoc(doc, path_cross_sections) + + if (check_for_node(doc, "groups")) then + ! Get neutron group count + call get_node_value(doc, "groups", energy_groups) + else + call fatal_error("groups element must exist!") + end if + + allocate(energy_bins(energy_groups + 1)) + if (check_for_node(doc, "group_structure")) then + ! Get neutron group structure + call get_node_array(doc, "group_structure", energy_bins) + else + call fatal_error("group_structures element must exist!") + end if + + allocate(energy_bin_avg(energy_groups)) + do i = 1, energy_groups + energy_bin_avg(i) = HALF * (energy_bins(i) + energy_bins(i + 1)) + end do + + allocate(inverse_velocities(energy_groups)) + if (check_for_node(doc, "inverse_velocities")) then + ! Get inverse velocities + call get_node_array(doc, "inverse_velocities", inverse_velocities) + else + ! If not given, estimate them by using average energy in group which is + ! assumed to be the midpoint + do i = 1, energy_groups + inverse_velocities(i) = & + (sqrt(TWO * energy_bin_avg(i) / (MASS_NEUTRON_MEV)) * & + C_LIGHT * 100.0_8) + end do + end if + + ! Get node list of all + call get_node_list(doc, "xsdata", node_xsdata_list) + n_listings = get_list_size(node_xsdata_list) + + ! Allocate xs_listings array + if (n_listings == 0) then + call fatal_error("At least one element must be present in & + &cross_sections.xml file!") + else + allocate(xs_listings(n_listings)) + end if + + do i = 1, n_listings + listing => xs_listings(i) + + ! Get pointer to xsdata table XML node + call get_list_item(node_xsdata_list, i, node_xsdata) + + ! copy a number of attributes + call get_node_value(node_xsdata, "name", listing % name) + listing % name = to_lower(listing % name) + listing % alias = listing % name + if (check_for_node(node_xsdata, "alias")) & + call get_node_value(node_xsdata, "alias", listing % alias) + listing % alias = to_lower(listing % alias) + if (check_for_node(node_xsdata, "zaid")) then + call get_node_value(node_xsdata, "zaid", listing % zaid) + else + listing % zaid = -1 + end if + if (check_for_node(node_xsdata, "awr")) then + call get_node_value(node_xsdata, "awr", listing % awr) + else + ! Set to a default of 1; this allows a macroscopic library to still + ! be used with materials with atom/b-cm units for testing purposes + listing % awr = ONE + end if + if (check_for_node(node_xsdata, "kT")) then + call get_node_value(node_xsdata, "kT", listing % kT) + else + listing % kT = 293.6_8 * K_BOLTZMANN + end if + + ! determine type of cross section + if (ends_with(listing % name, 'c')) then + listing % type = NEUTRON + end if + + ! create dictionary entry for both name and alias + call xs_listing_dict % add_key(to_lower(listing % name), i) + call xs_listing_dict % add_key(to_lower(listing % alias), i) + end do + + ! Close cross sections XML file + call close_xmldoc(doc) + + end subroutine read_mg_cross_sections_xml !=============================================================================== ! EXPAND_NATURAL_ELEMENT converts natural elements specified using an diff --git a/src/macroxs_header.F90 b/src/macroxs_header.F90 new file mode 100644 index 000000000..2a1234510 --- /dev/null +++ b/src/macroxs_header.F90 @@ -0,0 +1,860 @@ +module macroxs_header + + use constants, only: MAX_FILE_LEN, ZERO, ONE, TWO, PI + use list_header, only: ListInt + use material_header, only: material + use math, only: calc_pn, calc_rn, expand_harmonic, find_angle + use nuclide_header + use random_lcg, only: prn + use scattdata_header + + implicit none + +!=============================================================================== +! MACROXS_* contains cached macroscopic cross sections for the material a +! particle is traveling through +!=============================================================================== + + type, abstract :: MacroXS + ! Data Order + integer :: order + + contains + procedure(macroxs_init_), deferred :: init ! initializes object + procedure(macroxs_get_xs_), deferred :: get_xs ! Return xs + ! Sample the outgoing energy from a fission event + procedure(macroxs_sample_fission_), deferred :: sample_fission_energy + ! Sample the outgoing energy and angle from a scatter event + procedure(macroxs_sample_scatter_), deferred :: sample_scatter + ! Calculate the material specific MGXS data from the nuclides + procedure(macroxs_calculate_xs_), deferred :: calculate_xs + end type MacroXS + + abstract interface + subroutine macroxs_init_(this, mat, nuclides, groups, get_kfiss, get_fiss, & + max_order, scatt_type, legendre_mu_points, & + error_code, error_text) + import MacroXS, Material, NuclideMGContainer, MAX_LINE_LEN + class(MacroXS), intent(inout) :: this ! The MacroXS to initialize + type(Material), pointer, intent(in) :: mat ! base material + type(NuclideMGContainer), intent(in) :: nuclides(:) ! List of nuclides to harvest from + integer, intent(in) :: groups ! Number of E groups + logical, intent(in) :: get_kfiss ! Should we get kfiss data? + logical, intent(in) :: get_fiss ! Should we get fiss data? + integer, intent(in) :: max_order ! Maximum requested order + integer, intent(in) :: scatt_type ! Legendre or Tabular Scatt? + integer, intent(in) :: legendre_mu_points ! Treat as Leg or Tabular? + integer, intent(inout) :: error_code ! Code signifying error + character(MAX_LINE_LEN), intent(inout) :: error_text ! Error message to print + end subroutine macroxs_init_ + + function macroxs_get_xs_(this, g, xstype, gout, uvw) result(xs) + import MacroXS + class(MacroXS), intent(in) :: this ! The MacroXS to initialize + integer, intent(in) :: g ! Incoming Energy group + character(*) , intent(in) :: xstype ! Cross Section Type + integer, optional, intent(in) :: gout ! Outgoing Energy group + real(8), optional, intent(in) :: uvw(3) ! Requested Angle + real(8) :: xs ! Resultant xs + end function macroxs_get_xs_ + + function macroxs_sample_fission_(this, gin, uvw) result(gout) + import MacroXS + class(MacroXS), intent(in) :: this ! Data to work with + integer, intent(in) :: gin ! Incoming energy group + real(8), intent(in) :: uvw(3) ! Particle Direction + integer :: gout ! Sampled outgoing group + + end function macroxs_sample_fission_ + + subroutine macroxs_sample_scatter_(this, uvw, gin, gout, mu, wgt) + import MacroXS + class(MacroXS), intent(in) :: this + real(8), intent(in) :: uvw(3) ! Incoming neutron direction + integer, intent(in) :: gin ! Incoming neutron group + integer, intent(out) :: gout ! Sampled outgoin group + real(8), intent(out) :: mu ! Sampled change in angle + real(8), intent(inout) :: wgt ! Particle weight + end subroutine macroxs_sample_scatter_ + + subroutine macroxs_calculate_xs_(this, gin, uvw, xs) + import MacroXS, MaterialMacroXS + class(MacroXS), intent(in) :: this + integer, intent(in) :: gin ! Incoming neutron group + real(8), intent(in) :: uvw(3) ! Incoming neutron direction + type(MaterialMacroXS), intent(inout) :: xs + end subroutine macroxs_calculate_xs_ + end interface + + type, extends(MacroXS) :: MacroXSIso + ! Microscopic cross sections + real(8), allocatable :: total(:) ! total cross section + real(8), allocatable :: absorption(:) ! absorption cross section + class(ScattData), allocatable :: scatter ! scattering information + real(8), allocatable :: nu_fission(:) ! nu-fission + real(8), allocatable :: k_fission(:) ! kappa-fission + real(8), allocatable :: fission(:) ! fission x/s + real(8), allocatable :: scattxs(:) ! scattering xs + real(8), allocatable :: chi(:,:) ! fission spectra + + contains + procedure :: init => macroxsiso_init ! inits object + procedure :: get_xs => macroxsiso_get_xs ! Returns xs + procedure :: sample_fission_energy => macroxsiso_sample_fission_energy + procedure :: sample_scatter => macroxsiso_sample_scatter + procedure :: calculate_xs => macroxsiso_calculate_xs + end type MacroXSIso + + type, extends(MacroXS) :: MacroXSAngle + ! Macroscopic cross sections + real(8), allocatable :: total(:,:,:) ! total cross section + real(8), allocatable :: absorption(:,:,:) ! absorption cross section + type(ScattDataContainer), allocatable :: scatter(:,:) ! scattering information + real(8), allocatable :: nu_fission(:,:,:) ! nu-fission + real(8), allocatable :: k_fission(:,:,:) ! kappa-fission + real(8), allocatable :: fission(:,:,:) ! fission x/s + real(8), allocatable :: chi(:,:,:,:) ! fission spectra + real(8), allocatable :: scattxs(:,:,:) ! scattering xs + real(8), allocatable :: polar(:) ! polar angles + real(8), allocatable :: azimuthal(:) ! azimuthal angles + + contains + procedure :: init => macroxsangle_init ! inits object + procedure :: get_xs => macroxsangle_get_xs ! Returns xs + procedure :: sample_fission_energy => macroxsangle_sample_fission_energy + procedure :: sample_scatter => macroxsangle_sample_scatter + procedure :: calculate_xs => macroxsangle_calculate_xs + end type MacroXSAngle + +!=============================================================================== +! MACROXSCONTAINER pointer array for storing MacroXS objects. +!=============================================================================== + + type MacroXSContainer + class(MacroXS), allocatable :: obj + end type MacroXSContainer + +contains + +!=============================================================================== +! MACROXS*_INIT sets the MacroXS Data +!=============================================================================== + + subroutine macroxsiso_init(this, mat, nuclides, groups, get_kfiss, get_fiss, & + max_order, scatt_type, legendre_mu_points, error_code, error_text) + class(MacroXSIso), intent(inout) :: this ! The MacroXS to initialize + type(Material), pointer, intent(in) :: mat ! base material + type(NuclideMGContainer), intent(in) :: nuclides(:) ! List of nuclides to harvest from + integer, intent(in) :: groups ! Number of E groups + logical, intent(in) :: get_kfiss ! Should we get kfiss data? + logical, intent(in) :: get_fiss ! Should we get fiss data? + integer, intent(in) :: max_order ! Maximum requested order + integer, intent(in) :: scatt_type ! How is data presented + integer, intent(in) :: legendre_mu_points ! Treat as Leg or Tabular? + integer, intent(inout) :: error_code ! Code signifying error + character(MAX_LINE_LEN), intent(inout) :: error_text ! Error message to print + + integer :: i ! loop index over nuclides + integer :: gin, gout ! group indices + real(8) :: atom_density ! atom density of a nuclide + integer :: imu + real(8) :: norm + integer :: mat_max_order, order, l + real(8), allocatable :: temp_mult(:,:) + real(8), allocatable :: temp_energy(:,:) + real(8), allocatable :: scatt_coeffs(:,:,:) + + ! Initialize error data + error_code = 0 + error_text = '' + + ! If we have tabular only data, then make sure all datasets have same size + if (scatt_type == ANGLE_HISTOGRAM) then + ! Check all scattering data of same size + order = nuclides(mat % nuclide(1)) % obj % order + do i = 2, mat % n_nuclides + if (order /= nuclides(mat % nuclide(i)) % obj % order) then + error_code = 1 + error_text = "All Histogram Scattering Entries Must Be Same Length!" + return + end if + end do + ! Ok, got our order, store it + this % order = order + + ! Allocate stuff for later + allocate(scatt_coeffs(order, groups, groups)) + scatt_coeffs = ZERO + allocate(ScattDataHistogram :: this % scatter) + + else if (scatt_type == ANGLE_TABULAR) then + ! Check all scattering data of same size + order = nuclides(mat % nuclide(1)) % obj % order + do i = 2, mat % n_nuclides + if (order /= nuclides(mat % nuclide(i)) % obj % order) then + error_code = 1 + error_text = "All Tabular Scattering Entries Must Be Same Length!" + return + end if + end do + ! Ok, got our order, store it + this % order = order + + ! Allocate stuff for later + allocate(scatt_coeffs(order, groups, groups)) + scatt_coeffs = ZERO + allocate(ScattDataTabular :: this % scatter) + + else if (scatt_type == ANGLE_LEGENDRE) then + ! Otherwise find the maximum scattering order + ! Need to determine the maximum scattering order of all data in this material + mat_max_order = 0 + do i = 1, mat % n_nuclides + if (nuclides(mat % nuclide(i)) % obj % order > mat_max_order) then + mat_max_order = nuclides(mat % nuclide(i)) % obj % order + end if + end do + + ! Now need to compare this material maximum scattering order with + ! the problem wide max scatt order and use whichever is lower + order = min(mat_max_order, max_order) + this % order = order + 1 + + ! Now we can allocate our scatt_coeffs object accordingly + allocate(scatt_coeffs(order + 1, groups, groups)) + scatt_coeffs = ZERO + if (legendre_mu_points == 1) then + allocate(ScattDataLegendre :: this % scatter) + else + allocate(ScattDataTabular :: this % scatter) + end if + end if + + ! Allocate and initialize data within macro_xs(i_mat) object + allocate(this % total(groups)) + this % total = ZERO + allocate(this % absorption(groups)) + this % absorption = ZERO + if (get_fiss) then + allocate(this % fission(groups)) + this % fission = ZERO + end if + if (get_kfiss) then + allocate(this % k_fission(groups)) + this % k_fission = ZERO + end if + allocate(this % nu_fission(groups)) + this % nu_fission = ZERO + allocate(this % chi(groups, groups)) + this % chi = ZERO + allocate(temp_energy(groups, groups)) + temp_energy = ZERO + allocate(temp_mult(groups, groups)) + temp_mult = ZERO + allocate(this % scattxs(groups)) + + ! Add contribution from each nuclide in material + do i = 1, mat % n_nuclides + ! Copy atom density of nuclide in material + atom_density = mat % atom_density(i) + + ! Perform our operations which depend upon the type + select type(nuc => nuclides(mat % nuclide(i)) % obj) + type is (NuclideIso) + + ! Add contributions to total, absorption, and fission data (if necessary) + this % total = this % total + atom_density * nuc % total + this % absorption = this % absorption + & + atom_density * nuc % absorption + if (nuc % fissionable) then + if (allocated(nuc % chi)) then + do gin = 1, groups + do gout = 1, groups + this % chi(gout,gin) = this % chi(gout,gin) + atom_density * & + nuc % chi(gout) * nuc % nu_fission(gin,1) + end do + end do + this % nu_fission = this % nu_fission + atom_density * & + nuc % nu_fission(:,1) + else + this % chi = this % chi + atom_density * nuc % nu_fission + do gin = 1, groups + this % nu_fission(gin) = this % nu_fission(gin) + atom_density * & + sum(nuc % nu_fission(:,gin)) + end do + end if + if (get_fiss) then + this % fission = this % fission + atom_density * nuc % fission + end if + if (get_kfiss) then + this % k_fission = this % k_fission + atom_density * nuc % k_fission + end if + end if + + ! Now time to do the scattering + do gin = 1, groups + do gout = 1, groups + if (scatt_type == ANGLE_HISTOGRAM .or. scatt_type == ANGLE_TABULAR) then + ! Transfer matrix + temp_energy(gout,gin) = temp_energy(gout,gin) + atom_density * & + sum(nuc % scatter(gout,gin,:)) + + ! Determine the angular distribution + do imu = 1, order + scatt_coeffs(imu, gout, gin) = scatt_coeffs(imu, gout, gin) + & + nuc % scatter(gout,gin,imu) * & + atom_density + end do + + else if (scatt_type == ANGLE_LEGENDRE) then + ! Transfer matrix + temp_energy(gout,gin) = temp_energy(gout,gin) + atom_density * & + nuc % scatter(gout,gin,1) + + ! Determine the angular distribution coefficients so we can later + ! expand do the complete distribution + do l = 1, min(nuc % order, order) + 1 + scatt_coeffs(l, gout, gin) = scatt_coeffs(l, gout, gin) + & + nuc % scatter(gout,gin,l) * & + atom_density + end do + + end if + + ! Multiplicity matrix + temp_mult(gout,gin) = temp_mult(gout,gin) + atom_density * & + nuc % mult(gout,gin) + end do + end do + type is (NuclideAngle) + error_code = 1 + error_text = "Invalid Passing of NuclideAngle to MacroXSIso Object" + return + end select + end do + + ! Store the scattering xs + if (scatt_type == ANGLE_HISTOGRAM .or. scatt_type == ANGLE_TABULAR) then + this % scattxs(:) = sum(sum(scatt_coeffs(:,:,:),dim=1),dim=1) + else if (scatt_type == ANGLE_LEGENDRE) then + this % scattxs(:) = sum(scatt_coeffs(1,:,:),dim=1) + end if + + ! Normalize the scatt_coeffs + do gin = 1, groups + do gout = 1, groups + if (scatt_type == ANGLE_HISTOGRAM .or. scatt_type == ANGLE_TABULAR) then + norm = sum(scatt_coeffs(:,gout,gin)) + else if (scatt_type == ANGLE_LEGENDRE) then + norm = scatt_coeffs(1,gout,gin) + end if + if (norm /= ZERO) then + scatt_coeffs(:, gout, gin) = scatt_coeffs(:, gout,gin) / norm + end if + end do + ! Now normalize temp_energy (outgoing scattering energy probabilities) + norm = sum(temp_energy(:,gin)) + if (norm > ZERO) then + temp_energy(:,gin) = temp_energy(:,gin) / norm + end if + end do + + if (scatt_type == ANGLE_LEGENDRE .and. legendre_mu_points /= 1) then + call this % scatter % init(legendre_mu_points, temp_energy, temp_mult, & + scatt_coeffs) + else + call this % scatter % init(this % order, temp_energy, temp_mult, & + scatt_coeffs) + end if + + ! Now normalize chi + if (mat % fissionable) then + do gin = 1, groups + ! Normalize Chi + norm = sum(this % chi(:,gin)) + if (norm > ZERO) then + this % chi(:,gin) = this % chi(:,gin) / norm + end if + end do + end if + + ! Deallocate temporaries for the next material + deallocate(scatt_coeffs, temp_energy, temp_mult) + + end subroutine macroxsiso_init + + subroutine macroxsangle_init(this, mat, nuclides, groups, get_kfiss, get_fiss, & + max_order, scatt_type, legendre_mu_points, error_code, error_text) + class(MacroXSAngle), intent(inout) :: this ! The MacroXS to initialize + type(Material), pointer, intent(in) :: mat ! base material + type(NuclideMGContainer), intent(in) :: nuclides(:) ! List of nuclides to harvest from + integer, intent(in) :: groups ! Number of E groups + logical, intent(in) :: get_kfiss ! Should we get kfiss data? + logical, intent(in) :: get_fiss ! Should we get fiss data? + integer, intent(in) :: max_order ! Maximum requested order + integer, intent(in) :: scatt_type ! Legendre or Tabular Scatt? + integer, intent(in) :: legendre_mu_points ! Treat as Leg or Tabular? + integer, intent(inout) :: error_code ! Code signifying error + character(MAX_LINE_LEN), intent(inout) :: error_text ! Error message to print + + integer :: i ! loop index over nuclides + integer :: gin, gout ! group indices + real(8) :: atom_density ! atom density of a nuclide + integer :: ipol, iazi, npol, nazi + integer :: imu + real(8) :: norm + integer :: mat_max_order, order, l + real(8), allocatable :: temp_mult(:,:,:,:) + real(8), allocatable :: temp_energy(:,:,:,:) + real(8), allocatable :: scatt_coeffs(:,:,:,:,:) + + ! Initialize error data + error_code = 0 + error_text = '' + + ! Get the number of each polar and azi angles and make sure all the + ! NuclideAngle types have the same number of these angles + npol = -1 + nazi = -1 + do i = 1, mat % n_nuclides + select type(nuc => nuclides(mat % nuclide(i)) % obj) + type is (NuclideAngle) + if (npol == -1) then + npol = nuc % n_pol + nazi = nuc % n_azi + allocate(this % polar(npol)) + this % polar = nuc % polar + allocate(this % azimuthal(nazi)) + this % azimuthal = nuc % azimuthal + else + if ((npol /= nuc % n_pol) .or. (nazi /= nuc % n_azi)) then + error_code = 1 + error_text = "All Angular Data Must Be Same Length!" + end if + end if + end select + end do + + ! If we have tabular only data, then make sure all datasets have same size + if (scatt_type == ANGLE_HISTOGRAM) then + ! Check all scattering data of same size + order = nuclides(mat % nuclide(1)) % obj % order + do i = 2, mat % n_nuclides + if (order /= nuclides(mat % nuclide(i)) % obj % order) then + error_code = 1 + error_text = "All Histogram Scattering Entries Must Be Same Length!" + return + end if + end do + ! Ok, got our order, store it + this % order = order + + ! Allocate stuff for later + allocate(scatt_coeffs(order, groups, groups, nazi, npol)) + scatt_coeffs = ZERO + allocate(this % scatter(nazi, npol)) + do ipol = 1, npol + do iazi = 1, nazi + allocate(ScattDataHistogram :: this % scatter(iazi, ipol) % obj) + end do + end do + + else if (scatt_type == ANGLE_TABULAR) then + ! Check all scattering data of same size + order = nuclides(mat % nuclide(1)) % obj % order + do i = 2, mat % n_nuclides + if (order /= nuclides(mat % nuclide(i)) % obj % order) then + error_code = 1 + error_text = "All Tabular Scattering Entries Must Be Same Length!" + return + end if + end do + ! Ok, got our order, store it + this % order = order + + ! Allocate stuff for later + allocate(scatt_coeffs(order, groups, groups, nazi, npol)) + scatt_coeffs = ZERO + allocate(this % scatter(nazi, npol)) + do ipol = 1, npol + do iazi = 1, nazi + allocate(ScattDataTabular :: this % scatter(iazi, ipol) % obj) + end do + end do + + else if (scatt_type == ANGLE_LEGENDRE) then + ! Otherwise find the maximum scattering order + ! Need to determine the maximum scattering order of all data in this material + mat_max_order = 0 + do i = 1, mat % n_nuclides + if (nuclides(mat % nuclide(i)) % obj % order > mat_max_order) then + mat_max_order = nuclides(mat % nuclide(i)) % obj % order + end if + end do + + ! Now need to compare this material maximum scattering order with + ! the problem wide max scatt order and use whichever is lower + order = min(mat_max_order, max_order) + this % order = order + 1 + + ! Now we can allocate our scatt_coeffs object accordingly + allocate(scatt_coeffs(order + 1, groups, groups, nazi, npol)) + scatt_coeffs = ZERO + allocate(this % scatter(nazi, npol)) + do ipol = 1, npol + do iazi = 1, nazi + if (legendre_mu_points == 1) then + allocate(ScattDataLegendre :: this % scatter(iazi, ipol) % obj) + else + allocate(ScattDataTabular :: this % scatter(iazi, ipol) % obj) + end if + end do + end do + end if + + ! Allocate and initialize data within macro_xs(i_mat) object + allocate(this % total(groups,nazi,npol)) + this % total = ZERO + allocate(this % absorption(groups,nazi,npol)) + this % absorption = ZERO + if (get_fiss) then + allocate(this % fission(groups,nazi,npol)) + this % fission = ZERO + end if + if (get_kfiss) then + allocate(this % k_fission(groups,nazi,npol)) + this % k_fission = ZERO + end if + allocate(this % nu_fission(groups,nazi,npol)) + this % nu_fission = ZERO + allocate(this % chi(groups, groups, nazi, npol)) + this % chi = ZERO + allocate(temp_energy(groups,groups,nazi,npol)) + temp_energy = ZERO + allocate(temp_mult(groups,groups,nazi,npol)) + temp_mult = ZERO + allocate(this % scattxs(groups,nazi,npol)) + + ! Add contribution from each nuclide in material + do i = 1, mat % n_nuclides + ! Copy atom density of nuclide in material + atom_density = mat % atom_density(i) + + ! Perform our operations which depend upon the type + select type(nuc => nuclides(mat % nuclide(i)) % obj) + type is (NuclideIso) + error_code = 1 + error_text = "Invalid Passing of NuclideIso to MacroXSAngle Object" + return + type is (NuclideAngle) + ! Add contributions to total, absorption, and fission data (if necessary) + this % total = this % total + atom_density * nuc % total + this % absorption = this % absorption + & + atom_density * nuc % absorption + if (nuc % fissionable) then + if (allocated(nuc % chi)) then + do gin = 1, groups + do gout = 1, groups + this % chi(gout,gin,:,:) = this % chi(gout,gin,:,:) + atom_density * & + nuc % chi(gout,:,:) * nuc % nu_fission(gin,1,:,:) + end do + end do + this % nu_fission = this % nu_fission + atom_density * & + nuc % nu_fission(:,1,:,:) + else + this % chi = this % chi + atom_density * nuc % nu_fission + do gin = 1, groups + this % nu_fission(gin,:,:) = this % nu_fission(gin,:,:) + atom_density * & + sum(nuc % nu_fission(:,gin,:,:),dim=1) + end do + end if + if (get_fiss) then + this % fission = this % fission + atom_density * nuc % fission + end if + if (get_kfiss) then + this % k_fission = this % k_fission + atom_density * nuc % k_fission + end if + end if + + ! Now time to do the scattering + do gin = 1, groups + do gout = 1, groups + if (scatt_type == ANGLE_HISTOGRAM .or. scatt_type == ANGLE_TABULAR) then + ! Transfer matrix + temp_energy(gout,gin,:,:) = temp_energy(gout,gin,:,:) + atom_density * & + sum(nuc % scatter(gout,gin,:,:,:),dim=1) + + ! Determine the angular distribution + do imu = 1, order + scatt_coeffs(imu,gout,gin,:,:) = scatt_coeffs(imu,gout,gin,:,:) + & + nuc % scatter(gout,gin,imu,:,:) * & + atom_density + end do + else if (scatt_type == ANGLE_LEGENDRE) then + ! Transfer matrix + temp_energy(gout,gin,:,:) = temp_energy(gout,gin,:,:) + atom_density * & + nuc % scatter(gout,gin,1,:,:) + + ! Determine the angular distribution coefficients so we can later + ! expand do the complete distribution + do l = 1, min(nuc % order, order) + 1 + scatt_coeffs(l, gout, gin,:,:) = scatt_coeffs(l, gout, gin,:,:) + & + nuc % scatter(gout,gin,l,:,:) * & + atom_density + end do + end if + + ! Multiplicity matrix + temp_mult(gout,gin,:,:) = temp_mult(gout,gin,:,:) + atom_density * & + nuc % mult(gout,gin,:,:) + end do + end do + end select + end do + + ! Store the scattering xs + if (scatt_type == ANGLE_HISTOGRAM .or. scatt_type == ANGLE_TABULAR) then + this % scattxs(:,:,:) = sum(sum(scatt_coeffs(:,:,:,:,:),dim=1),dim=1) + else if (scatt_type == ANGLE_LEGENDRE) then + this % scattxs(:,:,:) = sum(scatt_coeffs(1,:,:,:,:),dim=1) + end if + + ! Normalize the scatt_coeffs + do ipol = 1, npol + do iazi = 1, nazi + do gin = 1, groups + do gout = 1, groups + if (scatt_type == ANGLE_HISTOGRAM .or. scatt_type == ANGLE_TABULAR) then + norm = sum(scatt_coeffs(:,gout,gin,iazi,ipol)) + else if (scatt_type == ANGLE_LEGENDRE) then + norm = scatt_coeffs(1,gout,gin,iazi,ipol) + end if + if (norm /= ZERO) then + scatt_coeffs(:,gout,gin,iazi,ipol) = & + scatt_coeffs(:,gout,gin,iazi,ipol) / norm + end if + end do + ! Now normalize temp_energy (outgoing scattering energy probabilities) + norm = sum(temp_energy(:,gin,iazi,ipol)) + if (norm > ZERO) then + temp_energy(:,gin,iazi,ipol) = temp_energy(:,gin,iazi,ipol) / norm + end if + end do + + if (scatt_type == ANGLE_LEGENDRE .and. legendre_mu_points /= 1) then + call this % scatter(iazi, ipol) % obj % init(legendre_mu_points, & + temp_energy(:,:,iazi,ipol), temp_mult(:,:,iazi,ipol), & + scatt_coeffs(:,:,:,iazi,ipol)) + else + call this % scatter(iazi, ipol) % obj % init(this % order, & + temp_energy(:,:,iazi,ipol), temp_mult(:,:,iazi,ipol), & + scatt_coeffs(:,:,:,iazi,ipol)) + end if + + end do + end do + + ! Now go through and normalize chi + if (mat % fissionable) then + do ipol = 1, npol + do iazi = 1, nazi + do gin = 1, groups + ! Normalize Chi + norm = sum(this % chi(:,gin,iazi,ipol)) + if (norm > ZERO) then + this % chi(:,gin,iazi,ipol) = this % chi(:,gin,iazi,ipol) / norm + end if + end do + end do + end do + end if + + ! Deallocate temporaries for the next material + deallocate(scatt_coeffs, temp_energy, temp_mult) + + end subroutine macroxsangle_init + +!=============================================================================== +! MACROXS_*_GET_XS returns the requested data type +!=============================================================================== + + function macroxsiso_get_xs(this, g, xstype, gout, uvw) result(xs) + class(MacroXSIso), intent(in) :: this ! The MacroXS to initialize + integer, intent(in) :: g ! Incoming Energy group + character(*) , intent(in) :: xstype ! Type of xs requested + integer, optional, intent(in) :: gout ! Outgoing Energy group + real(8), optional, intent(in) :: uvw(3) ! Requested Angle + real(8) :: xs ! Requested x/s + + select case(xstype) + case('total') + xs = this % total(g) + case('absorption') + xs = this % absorption(g) + case('fission') + xs = this % fission(g) + case('k_fission') + xs = this % k_fission(g) + case('nu_fission') + xs = this % nu_fission(g) + case('scatter') + xs = this % scattxs(g) + case('mult') + if (present(gout)) then + xs = this % scatter % mult(gout,g) + else + xs = sum(this % scatter % mult(:,g)) + end if + end select + + end function macroxsiso_get_xs + + function macroxsangle_get_xs(this, g, xstype, gout,uvw) result(xs) + class(MacroXSAngle), intent(in) :: this ! The MacroXS to initialize + integer, intent(in) :: g ! Incoming Energy group + character(*) , intent(in) :: xstype ! Type of xs requested + integer, optional, intent(in) :: gout ! Outgoing Energy group + real(8), optional, intent(in) :: uvw(3) ! Requested Angle + real(8) :: xs ! Requested x/s + + integer :: iazi, ipol + + if (present(uvw)) then + call find_angle(this % polar, this % azimuthal, uvw, iazi, ipol) + select case(xstype) + case('total') + xs = this % total(g,iazi,ipol) + case('absorption') + xs = this % absorption(g,iazi,ipol) + case('fission') + xs = this % fission(g,iazi,ipol) + case('k_fission') + xs = this % k_fission(g,iazi,ipol) + case('nu_fission') + xs = this % nu_fission(g,iazi,ipol) + case('scatter') + xs = this % scattxs(g,iazi,ipol) + case('mult') + if (present(gout)) then + xs = this % scatter(iazi,ipol) % obj % mult(gout,g) + else + xs = sum(this % scatter(iazi,ipol) % obj % mult(:,g)) + end if + end select + end if + + end function macroxsangle_get_xs + +!=============================================================================== +! MACROXS_*_SAMPLE_FISSION_ENERGY samples the outgoing energy from a fission +! event +!=============================================================================== + + function macroxsiso_sample_fission_energy(this, gin, uvw) result(gout) + class(MacroXSIso), intent(in) :: this ! Data to work with + integer, intent(in) :: gin ! Incoming energy group + real(8), intent(in) :: uvw(3) ! Particle Direction + integer :: gout ! Sampled outgoing group + real(8) :: xi ! Our random number + real(8) :: prob ! Running probability + + xi = prn() + prob = ZERO + gout = 0 + + do while (prob < xi) + gout = gout + 1 + prob = prob + this % chi(gout,gin) + end do + + end function macroxsiso_sample_fission_energy + + function macroxsangle_sample_fission_energy(this, gin, uvw) result(gout) + class(MacroXSAngle), intent(in) :: this ! Data to work with + integer, intent(in) :: gin ! Incoming energy group + real(8), intent(in) :: uvw(3) ! Particle Direction + integer :: gout ! Sampled outgoing group + real(8) :: xi ! Our random number + real(8) :: prob ! Running probability + integer :: iazi, ipol + + call find_angle(this % polar, this % azimuthal, uvw, iazi, ipol) + + xi = prn() + prob = ZERO + gout = 0 + + do while (prob < xi) + gout = gout + 1 + prob = prob + this % chi(gout,gin,iazi,ipol) + end do + + end function macroxsangle_sample_fission_energy + +!=============================================================================== +! MACROXS*_SAMPLE_SCATTER Selects outgoing energy and angle after a scatter +! event +!=============================================================================== + + subroutine macroxsiso_sample_scatter(this, uvw, gin, gout, mu, wgt) + class(MacroXSIso), intent(in) :: this + real(8), intent(in) :: uvw(3) ! Incoming neutron direction + integer, intent(in) :: gin ! Incoming neutron group + integer, intent(out) :: gout ! Sampled outgoin group + real(8), intent(out) :: mu ! Sampled change in angle + real(8), intent(inout) :: wgt ! Particle weight + + call this % scatter % sample(gin, gout, mu, wgt) + + end subroutine macroxsiso_sample_scatter + + subroutine macroxsangle_sample_scatter(this, uvw, gin, gout, mu, wgt) + class(MacroXSAngle), intent(in) :: this + real(8), intent(in) :: uvw(3) ! Incoming neutron direction + integer, intent(in) :: gin ! Incoming neutron group + integer, intent(out) :: gout ! Sampled outgoin group + real(8), intent(out) :: mu ! Sampled change in angle + real(8), intent(inout) :: wgt ! Particle weight + + integer :: iazi, ipol ! Angular indices + + call find_angle(this % polar, this % azimuthal, uvw, iazi, ipol) + call this % scatter(iazi,ipol) % obj % sample(gin,gout,mu,wgt) + + end subroutine macroxsangle_sample_scatter + +!=============================================================================== +! MACROXS*_CALCULATE_XS determines the multi-group macroscopic cross sections +! for the material the particle is currently traveling through. +!=============================================================================== + + subroutine macroxsiso_calculate_xs(this, gin, uvw, xs) + class(MacroXSIso), intent(in) :: this + integer, intent(in) :: gin ! Incoming neutron group + real(8), intent(in) :: uvw(3) ! Incoming neutron direction + type(MaterialMacroXS), intent(inout) :: xs ! Resultant MacroXS Data + + xs % total = this % total(gin) + xs % elastic = this % scattxs(gin) + xs % absorption = this % absorption(gin) + xs % nu_fission = this % nu_fission(gin) + + end subroutine macroxsiso_calculate_xs + + subroutine macroxsangle_calculate_xs(this, gin, uvw, xs) + class(MacroXSAngle), intent(in) :: this + integer, intent(in) :: gin ! Incoming neutron group + real(8), intent(in) :: uvw(3) ! Incoming neutron direction + type(MaterialMacroXS), intent(inout) :: xs ! Resultant MacroXS Data + + integer :: iazi, ipol + + call find_angle(this % polar, this % azimuthal, uvw, iazi, ipol) + xs % total = this % total(gin, iazi, ipol) + xs % elastic = this % scattxs(gin, iazi, ipol) + xs % absorption = this % absorption(gin, iazi, ipol) + xs % nu_fission = this % nu_fission(gin, iazi, ipol) + + end subroutine macroxsangle_calculate_xs + +end module macroxs_header diff --git a/src/math.F90 b/src/math.F90 index 9a64c88d7..f49220da7 100644 --- a/src/math.F90 +++ b/src/math.F90 @@ -557,6 +557,49 @@ contains end function calc_rn +!=============================================================================== +! EXPAND_HARMONIC expands a given series of real spherical harmonics +!=============================================================================== + + pure function expand_harmonic(data, order, uvw) result(val) + real(8), intent(in) :: data(:) + integer, intent(in) :: order + real(8), intent(in) :: uvw(3) + real(8) :: val + + integer :: l, lm_lo, lm_hi + + val = data(1) + lm_lo = 2 + lm_hi = 4 + do l = 1, order - 1 + val = val + sqrt(TWO * real(l,8) + ONE) * & + dot_product(calc_rn(l,uvw), data(lm_lo:lm_hi)) + lm_lo = lm_hi + 1 + lm_hi = lm_lo + 2 * (l + 1) + end do + + end function expand_harmonic + +!=============================================================================== +! EVALUATE_LEGENDRE Find the value of f(x) given a set of Legendre coefficients +! and the value of x +!=============================================================================== + + pure function evaluate_legendre(data, x) result(val) + real(8), intent(in) :: data(:) + real(8), intent(in) :: x + real(8) :: val + + integer :: l + + val = HALF * data(1) + do l = 1, size(data) - 1 + val = val + (real(l,8) + HALF) * data(l + 1) * calc_pn(l,x) + end do + + end function evaluate_legendre + !=============================================================================== ! ROTATE_ANGLE rotates direction cosines through a polar angle whose cosine is ! mu and through an azimuthal angle sampled uniformly. Note that this is done @@ -659,4 +702,31 @@ contains end function watt_spectrum + +!=============================================================================== +! find_angle finds the closest angle on the data grid and returns that index +!=============================================================================== + + pure subroutine find_angle(polar, azimuthal, uvw, i_azi, i_pol) + real(8), intent(in) :: polar(:) ! Polar angles [0,pi] + real(8), intent(in) :: azimuthal(:) ! Azi. angles [-pi,pi] + real(8), intent(in) :: uvw(3) ! Direction of motion + integer, intent(inout) :: i_pol ! Closest polar bin + integer, intent(inout) :: i_azi ! Closest azi bin + + real(8) :: my_pol, my_azi, dangle + + ! Convert uvw to polar and azi + + my_pol = acos(uvw(3)) + my_azi = atan2(uvw(2), uvw(1)) + + ! Search for equi-binned angles + dangle = PI / real(size(polar),8) + i_pol = floor(my_pol / dangle + ONE) + dangle = TWO * PI / real(size(azimuthal),8) + i_azi = floor((my_azi + PI) / dangle + ONE) + + end subroutine find_angle + end module math diff --git a/src/mesh.F90 b/src/mesh.F90 index 905772eb0..4ec84345b 100644 --- a/src/mesh.F90 +++ b/src/mesh.F90 @@ -3,7 +3,6 @@ module mesh use constants use global use mesh_header - use particle_header, only: Particle use search, only: binary_search #ifdef MPI @@ -160,10 +159,10 @@ contains sites_outside) type(RegularMesh), pointer :: m ! mesh to count sites - type(Bank), intent(in) :: bank_array(:) ! fission or source bank - real(8), intent(out) :: cnt(:,:,:,:) ! weight of sites in each + type(Bank), intent(in) :: bank_array(:) ! fission or source bank + real(8), intent(out) :: cnt(:,:,:,:) ! weight of sites in each ! cell and energy group - real(8), intent(in), optional :: energies(:) ! energy grid to search + real(8), intent(in), optional :: energies(:) ! energy grid to search integer(8), intent(in), optional :: size_bank ! # of bank sites (on each proc) logical, intent(inout), optional :: sites_outside ! were there sites outside mesh? diff --git a/src/mgxs_data.F90 b/src/mgxs_data.F90 new file mode 100644 index 000000000..796269151 --- /dev/null +++ b/src/mgxs_data.F90 @@ -0,0 +1,246 @@ +module mgxs_data + +use constants + use error, only: fatal_error + use global + use macroxs_header + use material_header, only: Material + use nuclide_header + use output, only: write_message + use set_header, only: SetChar + use string, only: to_lower + use xml_interface + + implicit none + +contains + +!=============================================================================== +! READ_XS reads all the cross sections for the problem and stores them in +! nuclides and sab_tables arrays +!=============================================================================== + + subroutine read_mgxs() + + integer :: i ! index in materials array + integer :: j ! index over nuclides in material + integer :: i_listing ! index in xs_listings array + integer :: i_nuclide ! index in nuclides + character(12) :: name ! name of isotope, e.g. 92235.03c + character(12) :: alias ! alias of isotope, e.g. U-235.03c + integer :: representation ! Data representation + type(Material), pointer :: mat + type(SetChar) :: already_read + type(Node), pointer :: doc => null() + type(Node), pointer :: node_xsdata + type(NodeList), pointer :: node_xsdata_list => null() + logical :: file_exists + character(MAX_LINE_LEN) :: temp_str + logical :: get_kfiss, get_fiss + integer :: l + + ! Check if cross_sections.xml exists + inquire(FILE=path_cross_sections, EXIST=file_exists) + if (.not. file_exists) then + ! Could not find cross_sections.xml file + call fatal_error("Cross sections XML file '" & + &// trim(path_cross_sections) // "' does not exist!") + end if + + call write_message("Loading Cross Section Data...", 5) + + ! Parse cross_sections.xml file + call open_xmldoc(doc, path_cross_sections) + + ! Get node list of all + call get_node_list(doc, "xsdata", node_xsdata_list) + n_listings = get_list_size(node_xsdata_list) + + ! allocate arrays for ACE table storage and cross section cache + allocate(nuclides_MG(n_nuclides_total)) +!$omp parallel + allocate(micro_xs(n_nuclides_total)) +!$omp end parallel + + ! Find out if we need fission & kappa fission + ! (i.e., are there any SCORE_FISSION or SCORE_KAPPA_FISSION tallies?) + get_kfiss = .false. + get_fiss = .false. + do i = 1, n_tallies + do l = 1, tallies(i) % n_score_bins + if (tallies(i) % score_bins(l) == SCORE_KAPPA_FISSION) then + get_kfiss = .true. + end if + if (tallies(i) % score_bins(l) == SCORE_FISSION) then + get_fiss = .true. + end if + end do + if (get_kfiss .and. get_fiss) exit + end do + + ! ========================================================================== + ! READ ALL ACE CROSS SECTION TABLES + + ! Loop over all files + MATERIAL_LOOP: do i = 1, n_materials + mat => materials(i) + + NUCLIDE_LOOP: do j = 1, mat % n_nuclides + name = mat % names(j) + + if (.not. already_read % contains(name)) then + i_listing = xs_listing_dict % get_key(to_lower(name)) + i_nuclide = mat % nuclide(j) + name = xs_listings(i_listing) % name + alias = xs_listings(i_listing) % alias + + ! Get pointer to xsdata table XML node + call get_list_item(node_xsdata_list, i_listing, node_xsdata) + + call write_message("Loading " // trim(name) // " Data...", 5) + + ! First find out the data representation + if (check_for_node(node_xsdata, "representation")) then + call get_node_value(node_xsdata, "representation", temp_str) + temp_str = trim(to_lower(temp_str)) + if (temp_str == 'isotropic' .or. temp_str == 'iso') then + representation = MGXS_ISOTROPIC + else if (temp_str == 'angle') then + representation = MGXS_ANGLE + else + call fatal_error("Invalid Data Representation!") + end if + else + ! Default to isotropic representation + representation = MGXS_ISOTROPIC + end if + + ! Now allocate accordingly + select case(representation) + case(MGXS_ISOTROPIC) + allocate(NuclideIso :: nuclides_MG(i_nuclide) % obj) + case(MGXS_ANGLE) + allocate(NuclideAngle :: nuclides_MG(i_nuclide) % obj) + end select + + ! Now read in the data specific to the type we just declared + call nuclides_MG(i_nuclide) % obj % init(node_xsdata, energy_groups, & + get_kfiss, get_fiss) + + ! Keep track of what listing is associated with this nuclide + nuclides_MG(i_nuclide) % obj % listing = i_listing + + ! Add name and alias to dictionary + call already_read % add(name) + call already_read % add(alias) + end if + end do NUCLIDE_LOOP + end do MATERIAL_LOOP + + ! Avoid some valgrind leak errors + call already_read % clear() + + ! Loop around material + MATERIAL_LOOP3: do i = 1, n_materials + + ! Get material + mat => materials(i) + + ! Loop around nuclides in material + NUCLIDE_LOOP2: do j = 1, mat % n_nuclides + ! Is this fissionable? + if (nuclides_MG(mat % nuclide(j)) % obj % fissionable) then + mat % fissionable = .true. + end if + if (mat % fissionable) then + exit NUCLIDE_LOOP2 + end if + + end do NUCLIDE_LOOP2 + end do MATERIAL_LOOP3 + + end subroutine read_mgxs + +!=============================================================================== +! SAME_NUCLIDEMG_LIST creates a linked list for each nuclide containing the +! indices in the nuclides array of all other instances of that nuclide. For +! example, the same nuclide may exist at multiple temperatures resulting +! in multiple entries in the nuclides array for a single zaid number. +!=============================================================================== + + subroutine same_nuclidemg_list() + + integer :: i ! index in nuclides array + integer :: j ! index in nuclides array + + do i = 1, n_nuclides_total + do j = 1, n_nuclides_total + if (nuclides_MG(i) % obj % zaid == nuclides_MG(j) % obj % zaid) then + call nuclides_MG(i) % obj % nuc_list % push_back(j) + end if + end do + end do + + end subroutine same_nuclidemg_list + +!=============================================================================== +! CREATE_MACRO_XS generates the macroscopic x/s from the microscopic input data +!=============================================================================== + + subroutine create_macro_xs() + integer :: i_mat ! index in materials array + integer :: i ! loop index over nuclides + integer :: l ! Loop over score bins + type(Material), pointer :: mat ! current material + logical :: get_kfiss, get_fiss + integer :: error_code + character(MAX_LINE_LEN) :: error_text + integer :: scatt_type + integer :: legendre_mu_points + + ! Find out if we need fission & kappa fission + ! (i.e., are there any SCORE_FISSION or SCORE_KAPPA_FISSION tallies?) + get_kfiss = .false. + get_fiss = .false. + do i = 1, n_tallies + do l = 1, tallies(i) % n_score_bins + if (tallies(i) % score_bins(l) == SCORE_KAPPA_FISSION) then + get_kfiss = .true. + end if + if (tallies(i) % score_bins(l) == SCORE_FISSION) then + get_fiss = .true. + end if + end do + if (get_kfiss .and. get_fiss) & + exit + end do + + allocate(macro_xs(n_materials)) + + do i_mat = 1, n_materials + mat => materials(i_mat) + + ! Check to see how our nuclides are represented + ! Force all to be the same type + ! Therefore type(nuclides(mat % nuclide(1)) % obj) dictates type(macroxs) + ! At the same time, we will find the scattering type, as that will dictate + ! how we allocate the scatter object within macroxs + legendre_mu_points = nuclides_MG(mat % nuclide(1)) % obj % legendre_mu_points + scatt_type = nuclides_MG(mat % nuclide(1)) % obj % scatt_type + select type(nuc => nuclides_MG(mat % nuclide(1)) % obj) + type is (NuclideIso) + allocate(MacroXSIso :: macro_xs(i_mat) % obj) + type is (NuclideAngle) + allocate(MacroXSAngle :: macro_xs(i_mat) % obj) + end select + + call macro_xs(i_mat) % obj % init(mat, nuclides_MG, energy_groups, & + get_kfiss, get_fiss, max_order, & + scatt_type, legendre_mu_points, & + error_code, error_text) + ! Handle any errors + if (error_code /= 0) call fatal_error(trim(error_text)) + end do + end subroutine create_macro_xs + +end module mgxs_data \ No newline at end of file diff --git a/src/nuclide_header.F90 b/src/nuclide_header.F90 new file mode 100644 index 000000000..9bcce57a7 --- /dev/null +++ b/src/nuclide_header.F90 @@ -0,0 +1,1128 @@ +module nuclide_header + + use, intrinsic :: ISO_FORTRAN_ENV + + use ace_header + use constants + use endf, only: reaction_name + use error, only: fatal_error + use list_header, only: ListInt + use math, only: evaluate_legendre, find_angle + use string + use xml_interface + + implicit none + +!=============================================================================== +! Nuclide contains the base nuclidic data for a nuclide, which does not depend +! upon how the nuclear data is represented (i.e., CE, or any variant of MG). +! The extended types, NuclideCE and NuclideMG deal with the rest +!=============================================================================== + + type, abstract :: Nuclide + character(12) :: name ! name of nuclide, e.g. 92235.03c + integer :: zaid ! Z and A identifier, e.g. 92235 + real(8) :: awr ! Atomic Weight Ratio + integer :: listing ! index in xs_listings + real(8) :: kT ! temperature in MeV (k*T) + + ! Linked list of indices in nuclides array of instances of this same nuclide + type(VectorInt) :: nuc_list + + ! Fission information + logical :: fissionable ! nuclide is fissionable? + + contains + procedure(print_nuclide_), deferred :: print ! Writes nuclide info + end type Nuclide + + abstract interface + + subroutine print_nuclide_(this, unit) + import Nuclide + class(Nuclide),intent(in) :: this + integer, optional, intent(in) :: unit + end subroutine print_nuclide_ + + end interface + + type, extends(Nuclide) :: NuclideCE + ! Energy grid information + integer :: n_grid ! # of nuclide grid points + integer, allocatable :: grid_index(:) ! log grid mapping indices + real(8), allocatable :: energy(:) ! energy values corresponding to xs + + ! Microscopic cross sections + real(8), allocatable :: total(:) ! total cross section + real(8), allocatable :: elastic(:) ! elastic scattering + real(8), allocatable :: fission(:) ! fission + real(8), allocatable :: nu_fission(:) ! neutron production + real(8), allocatable :: absorption(:) ! absorption (MT > 100) + real(8), allocatable :: heating(:) ! heating + + ! Resonance scattering info + logical :: resonant = .false. ! resonant scatterer? + character(10) :: name_0K = '' ! name of 0K nuclide, e.g. 92235.00c + character(16) :: scheme ! target velocity sampling scheme + integer :: n_grid_0K ! number of 0K energy grid points + real(8), allocatable :: energy_0K(:) ! energy grid for 0K xs + real(8), allocatable :: elastic_0K(:) ! Microscopic elastic cross section + real(8), allocatable :: xs_cdf(:) ! CDF of v_rel times cross section + real(8) :: E_min ! lower cutoff energy for res scattering + real(8) :: E_max ! upper cutoff energy for res scattering + + ! Fission information + logical :: has_partial_fission ! nuclide has partial fission reactions? + integer :: n_fission ! # of fission reactions + integer, allocatable :: index_fission(:) ! indices in reactions + + ! Total fission neutron emission + integer :: nu_t_type + real(8), allocatable :: nu_t_data(:) + + ! Prompt fission neutron emission + integer :: nu_p_type + real(8), allocatable :: nu_p_data(:) + + ! Delayed fission neutron emission + integer :: nu_d_type + integer :: n_precursor ! # of delayed neutron precursors + real(8), allocatable :: nu_d_data(:) + real(8), allocatable :: nu_d_precursor_data(:) + type(AngleEnergyContainer), allocatable :: nu_d_edist(:) + + ! Unresolved resonance data + logical :: urr_present + integer :: urr_inelastic + type(UrrData), pointer :: urr_data => null() + + ! Reactions + integer :: n_reaction ! # of reactions + type(Reaction), allocatable :: reactions(:) + type(DictIntInt) :: reaction_index ! map MT values to index in reactions + ! array; used at tally-time + + contains + procedure :: clear => nuclidece_clear + procedure :: print => nuclidece_print + end type NuclideCE + + type, abstract, extends(Nuclide) :: NuclideMG + ! Scattering Order Information + integer :: order ! Order of data (Scattering for NuclideIso, + ! Number of angles for all in NuclideAngle) + integer :: scatt_type ! either legendre, histogram, or tabular. + integer :: legendre_mu_points ! Number of tabular points to use to represent + ! Legendre distribs, -1 if sample with the + ! Legendres themselves + contains + procedure(nuclidemg_init_), deferred :: init ! Initialize the data + procedure(nuclidemg_get_xs_), deferred :: get_xs ! Get the requested xs + procedure(nuclidemg_calc_f_), deferred :: calc_f ! Calculates f, given mu + end type NuclideMG + + abstract interface + + subroutine nuclidemg_init_(this, node_xsdata, groups, get_kfiss, get_fiss) + import NuclideMG, Node + class(NuclideMG), intent(inout) :: this ! Working Object + type(Node), pointer, intent(in) :: node_xsdata ! Data from MGXS xml + integer, intent(in) :: groups ! Number of Energy groups + logical, intent(in) :: get_kfiss ! Need Kappa-Fission? + logical, intent(in) :: get_fiss ! Should we get fiss data? + end subroutine nuclidemg_init_ + + function nuclidemg_get_xs_(this, g, xstype, gout, uvw, mu, i_azi, i_pol) & + result(xs) + import NuclideMG + class(NuclideMG), intent(in) :: this + integer, intent(in) :: g ! Incoming Energy group + character(*), intent(in) :: xstype ! Cross Section Type + integer, optional, intent(in) :: gout ! Outgoing Group + real(8), optional, intent(in) :: uvw(3) ! Requested Angle + real(8), optional, intent(in) :: mu ! Change in angle + integer, optional, intent(in) :: i_azi ! Azimuthal Index + integer, optional, intent(in) :: i_pol ! Polar Index + real(8) :: xs ! Resultant xs + end function nuclidemg_get_xs_ + + pure function nuclidemg_calc_f_(this, gin, gout, mu, uvw, i_azi, i_pol) result(f) + import NuclideMG + class(NuclideMG), intent(in) :: this + integer, intent(in) :: gin ! Incoming Energy Group + integer, intent(in) :: gout ! Outgoing Energy Group + real(8), intent(in) :: mu ! Angle of interest + real(8), intent(in), optional :: uvw(3) ! Direction vector + integer, intent(in), optional :: i_azi ! Incoming Energy Group + integer, intent(in), optional :: i_pol ! Outgoing Energy Group + real(8) :: f ! Return value of f(mu) + + end function nuclidemg_calc_f_ + end interface + +!=============================================================================== +! NuclideIso contains the base MGXS data for a nuclide specifically for +! isotropically weighted MGXS +!=============================================================================== + + type, extends(NuclideMG) :: NuclideIso + + ! Microscopic cross sections + real(8), allocatable :: total(:) ! total cross section + real(8), allocatable :: absorption(:) ! absorption cross section + real(8), allocatable :: scatter(:,:,:) ! scattering information + real(8), allocatable :: nu_fission(:,:) ! fission matrix (Gout x Gin) + real(8), allocatable :: k_fission(:) ! kappa-fission + real(8), allocatable :: fission(:) ! neutron production + real(8), allocatable :: chi(:) ! Fission Spectra + real(8), allocatable :: mult(:,:) ! Scatter multiplicity (Gout x Gin) + + contains + procedure :: init => nuclideiso_init ! Initialize Nuclidic MGXS Data + procedure :: print => nuclideiso_print ! Writes nuclide info + procedure :: get_xs => nuclideiso_get_xs ! Gets Size of Data w/in Object + procedure :: calc_f => nuclideiso_calc_f ! Calcs f given mu + end type NuclideIso + +!=============================================================================== +! NuclideAngle contains the base MGXS data for a nuclide specifically for +! explicit angle-dependent weighted MGXS +!=============================================================================== + + type, extends(NuclideMG) :: NuclideAngle + + ! Microscopic cross sections. Dimensions are: (n_pol, n_azi, Nl, Ng, Ng) + real(8), allocatable :: total(:,:,:) ! total cross section + real(8), allocatable :: absorption(:,:,:) ! absorption cross section + real(8), allocatable :: scatter(:,:,:,:,:) ! scattering information + real(8), allocatable :: nu_fission(:,:,:,:) ! fission matrix (Gout x Gin) + real(8), allocatable :: k_fission(:,:,:) ! kappa-fission + real(8), allocatable :: fission(:,:,:) ! neutron production + real(8), allocatable :: chi(:,:,:) ! Fission Spectra + real(8), allocatable :: mult(:,:,:,:) ! Scatter multiplicity (Gout x Gin) + + ! In all cases, right-most indices are theta, phi + integer :: n_pol ! Number of polar angles + integer :: n_azi ! Number of azimuthal angles + real(8), allocatable :: polar(:) ! polar angles + real(8), allocatable :: azimuthal(:) ! azimuthal angles + + contains + procedure :: init => nuclideangle_init ! Initialize Nuclidic MGXS Data + procedure :: print => nuclideangle_print ! Gets Size of Data w/in Object + procedure :: get_xs => nuclideangle_get_xs ! Gets Size of Data w/in Object + procedure :: calc_f => nuclideangle_calc_f ! Calcs f given mu + end type NuclideAngle + +!=============================================================================== +! NUCLIDEMGCONTAINER pointer array for storing Nuclides +!=============================================================================== + + type NuclideMGContainer + class(NuclideMG), pointer :: obj + end type NuclideMGContainer + +!=============================================================================== +! NUCLIDE0K temporarily contains all 0K cross section data and other parameters +! needed to treat resonance scattering before transferring them to NuclideCE +!=============================================================================== + + type Nuclide0K + character(10) :: nuclide ! name of nuclide, e.g. U-238 + character(16) :: scheme = 'ares' ! target velocity sampling scheme + character(10) :: name ! name of nuclide, e.g. 92235.03c + character(10) :: name_0K ! name of 0K nuclide, e.g. 92235.00c + real(8) :: E_min = 0.01e-6_8 ! lower cutoff energy for res scattering + real(8) :: E_max = 1000.0e-6_8 ! upper cutoff energy for res scattering + end type Nuclide0K + +!=============================================================================== +! NUCLIDEMICROXS contains cached microscopic cross sections for a +! particular nuclide at the current energy +!=============================================================================== + + type NuclideMicroXS + integer :: index_grid ! index on nuclide energy grid + integer :: index_temp ! temperature index for nuclide + real(8) :: last_E = ZERO ! last evaluated energy + real(8) :: interp_factor ! interpolation factor on nuc. energy grid + real(8) :: total ! microscropic total xs + real(8) :: elastic ! microscopic elastic scattering xs + real(8) :: absorption ! microscopic absorption xs + real(8) :: fission ! microscopic fission xs + real(8) :: nu_fission ! microscopic production xs + + ! Information for S(a,b) use + integer :: index_sab ! index in sab_tables (zero means no table) + integer :: last_index_sab = 0 ! index in sab_tables last used by this nuclide + real(8) :: elastic_sab ! microscopic elastic scattering on S(a,b) table + + ! Information for URR probability table use + logical :: use_ptable ! in URR range with probability tables? + real(8) :: last_prn + end type NuclideMicroXS + +!=============================================================================== +! MATERIALMACROXS contains cached macroscopic cross sections for the material a +! particle is traveling through +!=============================================================================== + + type MaterialMacroXS + real(8) :: total ! macroscopic total xs + real(8) :: elastic ! macroscopic elastic scattering xs + real(8) :: absorption ! macroscopic absorption xs + real(8) :: fission ! macroscopic fission xs + real(8) :: nu_fission ! macroscopic production xs + end type MaterialMacroXS + +!=============================================================================== +! XSLISTING contains data read from a CE or MG cross_sections.xml file +! (or equivalent) +!=============================================================================== + + type XsListing + character(12) :: name ! table name, e.g. 92235.70c + character(12) :: alias ! table alias, e.g. U-235.70c + integer :: type ! type of table (cont-E neutron, S(A,b), etc) + integer :: zaid ! ZAID identifier = 1000*Z + A + integer :: filetype ! ASCII or BINARY + integer :: location ! location of table within library + integer :: recl ! record length for library + integer :: entries ! number of entries per record + real(8) :: awr ! atomic weight ratio (# of neutron masses) + real(8) :: kT ! Boltzmann constant * temperature (MeV) + logical :: metastable ! is this nuclide metastable? + character(MAX_FILE_LEN) :: path ! path to library containing table + end type XsListing + + contains + +!=============================================================================== +! NUCLIDE_*_INIT reads in the data from the XML file, as already accessed +!=============================================================================== + + subroutine nuclidemg_init(this, node_xsdata) + class(NuclideMG), intent(inout) :: this ! Working Object + type(Node), pointer, intent(in) :: node_xsdata ! Data from MGXS xml + + type(Node), pointer :: node_legendre_mu + character(MAX_LINE_LEN) :: temp_str + logical :: enable_leg_mu + + ! Load the data + call get_node_value(node_xsdata, "name", this % name) + this % name = to_lower(this % name) + if (check_for_node(node_xsdata, "kT")) then + call get_node_value(node_xsdata, "kT", this % kT) + else + this % kT = ZERO + end if + if (check_for_node(node_xsdata, "zaid")) then + call get_node_value(node_xsdata, "zaid", this % zaid) + else + this % zaid = -1 + end if + if (check_for_node(node_xsdata, "scatt_type")) then + call get_node_value(node_xsdata, "scatt_type", temp_str) + temp_str = trim(to_lower(temp_str)) + if (temp_str == 'legendre') then + this % scatt_type = ANGLE_LEGENDRE + else if (temp_str == 'histogram') then + this % scatt_type = ANGLE_HISTOGRAM + else if (temp_str == 'tabular') then + this % scatt_type = ANGLE_TABULAR + else + call fatal_error("Invalid Scatt Type Option!") + end if + else + this % scatt_type = ANGLE_LEGENDRE + end if + + if (check_for_node(node_xsdata, "order")) then + call get_node_value(node_xsdata, "order", this % order) + else + call fatal_error("Order Must Be Provided!") + end if + + ! Get scattering treatment + if (check_for_node(node_xsdata, "tabular_legendre")) then + call get_node_ptr(node_xsdata, "tabular_legendre", node_legendre_mu) + if (check_for_node(node_legendre_mu, "enable")) then + call get_node_value(node_legendre_mu, "enable", temp_str) + temp_str = trim(to_lower(temp_str)) + if (temp_str == 'true' .or. temp_str == '1') then + enable_leg_mu = .true. + elseif (temp_str == 'false' .or. temp_str == '0') then + enable_leg_mu = .false. + this % legendre_mu_points = 1 + else + call fatal_error("Unrecognized tabular_legendre/enable: " // temp_str) + end if + else + enable_leg_mu = .true. + this % legendre_mu_points = 33 + end if + if (enable_leg_mu .and. & + check_for_node(node_legendre_mu, "num_points")) then + call get_node_value(node_legendre_mu, "num_points", & + this % legendre_mu_points) + if (this % legendre_mu_points <= 0) then + call fatal_error("num_points element must be positive and non-zero!") + end if + this % legendre_mu_points = -1 * this % legendre_mu_points + end if + else + this % legendre_mu_points = 1 + end if + + if (check_for_node(node_xsdata, "fissionable")) then + call get_node_value(node_xsdata, "fissionable", temp_str) + temp_str = to_lower(temp_str) + if (trim(temp_str) == 'true' .or. trim(temp_str) == '1') then + this % fissionable = .true. + else + this % fissionable = .false. + end if + else + call fatal_error("Fissionable element must be set!") + end if + + end subroutine nuclidemg_init + + subroutine nuclideiso_init(this, node_xsdata, groups, get_kfiss, get_fiss) + class(NuclideIso), intent(inout) :: this ! Working Object + type(Node), pointer, intent(in) :: node_xsdata ! Data from MGXS xml + integer, intent(in) :: groups ! Number of Energy groups + logical, intent(in) :: get_kfiss ! Need Kappa-Fission? + logical, intent(in) :: get_fiss ! Need fiss data? + + real(8), allocatable :: temp_arr(:) + integer :: arr_len + integer :: order_dim + + ! Call generic data gathering routine + call nuclidemg_init(this, node_xsdata) + + ! Load the more specific data + if (this % fissionable) then + + if (check_for_node(node_xsdata, "chi")) then + ! Get chi + allocate(this % chi(groups)) + call get_node_array(node_xsdata, "chi", this % chi) + + ! Get nu_fission (as a vector) + if (check_for_node(node_xsdata, "nu_fission")) then + allocate(temp_arr(groups * 1)) + call get_node_array(node_xsdata, "nu_fission", temp_arr) + allocate(this % nu_fission(groups, 1)) + this % nu_fission = reshape(temp_arr, (/groups, 1/)) + deallocate(temp_arr) + else + call fatal_error("If fissionable, must provide nu_fission!") + end if + + else + ! Get nu_fission (as a matrix) + if (check_for_node(node_xsdata, "nu_fission")) then + + allocate(temp_arr(groups*groups)) + call get_node_array(node_xsdata, "nu_fission", temp_arr) + allocate(this % nu_fission(groups, groups)) + this % nu_fission = reshape(temp_arr, (/groups, groups/)) + deallocate(temp_arr) + else + call fatal_error("If fissionable, must provide nu_fission!") + end if + end if + if (get_fiss) then + allocate(this % fission(groups)) + if (check_for_node(node_xsdata, "fission")) then + call get_node_array(node_xsdata, "fission", this % fission) + else + call fatal_error("Fission data missing, required due to fission& + & tallies in tallies.xml file!") + end if + end if + if (get_kfiss) then + allocate(this % k_fission(groups)) + if (check_for_node(node_xsdata, "kappa_fission")) then + call get_node_array(node_xsdata, "kappa_fission", this % k_fission) + else + call fatal_error("kappa_fission data missing, required due to & + &kappa-fission tallies in tallies.xml file!") + end if + end if + end if + + allocate(this % absorption(groups)) + if (check_for_node(node_xsdata, "absorption")) then + call get_node_array(node_xsdata, "absorption", this % absorption) + else + call fatal_error("Must provide absorption!") + end if + + if (this % scatt_type == ANGLE_LEGENDRE) then + order_dim = this % order + 1 + else if (this % scatt_type == ANGLE_HISTOGRAM) then + order_dim = this % order + else if (this % scatt_type == ANGLE_TABULAR) then + order_dim = this % order + end if + + allocate(this % scatter(groups, groups, order_dim)) + if (check_for_node(node_xsdata, "scatter")) then + allocate(temp_arr(groups * groups * order_dim)) + call get_node_array(node_xsdata, "scatter", temp_arr) + this % scatter = reshape(temp_arr, (/groups, groups, order_dim/)) + deallocate(temp_arr) + else + call fatal_error("Must provide scatter!") + return + end if + + + allocate(this % total(groups)) + if (check_for_node(node_xsdata, "total")) then + call get_node_array(node_xsdata, "total", this % total) + else + this % total = this % absorption + sum(this%scatter(:,:,1),dim=1) + end if + + ! Get Mult Data + allocate(this % mult(groups, groups)) + if (check_for_node(node_xsdata, "multiplicity")) then + arr_len = get_arraysize_double(node_xsdata, "multiplicity") + if (arr_len == groups * groups) then + allocate(temp_arr(arr_len)) + call get_node_array(node_xsdata, "multiplicity", temp_arr) + this % mult = reshape(temp_arr, (/groups, groups/)) + deallocate(temp_arr) + else + call fatal_error("Multiplicity length not same as number of groups& + & squared!") + return + end if + else + this % mult = ONE + end if + + end subroutine nuclideiso_init + + subroutine nuclideangle_init(this, node_xsdata, groups, get_kfiss, get_fiss) + class(NuclideAngle), intent(inout) :: this ! Working Object + type(Node), pointer, intent(in) :: node_xsdata ! Data from MGXS xml + integer, intent(in) :: groups ! Number of Energy groups + logical, intent(in) :: get_kfiss ! Need Kappa-Fission? + logical, intent(in) :: get_fiss ! Should we get fiss data? + + real(8), allocatable :: temp_arr(:) + integer :: arr_len + real(8) :: dangle + integer :: iangle + integer :: order_dim + + ! Call generic data gathering routine + call nuclidemg_init(this, node_xsdata) + + if (this % scatt_type == ANGLE_LEGENDRE) then + order_dim = this % order + 1 + else if (this % scatt_type == ANGLE_HISTOGRAM) then + order_dim = this % order + else if (this % scatt_type == ANGLE_TABULAR) then + order_dim = this % order + end if + + if (check_for_node(node_xsdata, "num_polar")) then + call get_node_value(node_xsdata, "num_polar", this % n_pol) + else + call fatal_error("num_polar Must Be Provided!") + end if + + if (check_for_node(node_xsdata, "num_azimuthal")) then + call get_node_value(node_xsdata, "num_azimuthal", this % n_azi) + else + call fatal_error("num_azimuthal Must Be Provided!") + end if + + ! Load angle data, if present (else equally spaced) + allocate(this % polar(this % n_pol)) + allocate(this % azimuthal(this % n_azi)) + if (check_for_node(node_xsdata, "polar")) then + call fatal_error("User-Specified polar angle bins not yet supported!") + ! When this feature is supported, this line will be activated + call get_node_array(node_xsdata, "polar", this % polar) + else + dangle = PI / real(this % n_pol,8) + do iangle = 1, this % n_pol + this % polar(iangle) = (real(iangle,8) - HALF) * dangle + end do + end if + if (check_for_node(node_xsdata, "azimuthal")) then + call fatal_error("User-Specified azimuthal angle bins not yet supported!") + ! When this feature is supported, this line will be activated + call get_node_array(node_xsdata, "azimuthal", this % azimuthal) + else + dangle = TWO * PI / real(this % n_azi,8) + do iangle = 1, this % n_azi + this % azimuthal(iangle) = -PI + (real(iangle,8) - HALF) * dangle + end do + end if + + ! Load the more specific data + if (this % fissionable) then + + if (check_for_node(node_xsdata, "chi")) then + ! Get chi + allocate(temp_arr(groups * this % n_azi * this % n_pol)) + call get_node_array(node_xsdata, "chi", temp_arr) + allocate(this % chi(groups, this % n_azi, this % n_pol)) + this % chi = reshape(temp_arr, (/groups, this % n_azi, this % n_pol/)) + deallocate(temp_arr) + + ! Get nu_fission (as a vector) + if (check_for_node(node_xsdata, "nu_fission")) then + allocate(temp_arr(groups * this % n_azi * this % n_pol)) + call get_node_array(node_xsdata, "nu_fission", temp_arr) + allocate(this % nu_fission(groups, 1, this % n_azi, this % n_pol)) + this % nu_fission = reshape(temp_arr, (/groups, 1, this % n_azi, & + this % n_pol/)) + deallocate(temp_arr) + else + call fatal_error("If fissionable, must provide nu_fission!") + end if + + else + ! Get nu_fission (as a matrix) + if (check_for_node(node_xsdata, "nu_fission")) then + + allocate(temp_arr(groups * this % n_azi * this % n_pol)) + call get_node_array(node_xsdata, "nu_fission", temp_arr) + allocate(this % nu_fission(groups, groups, this % n_azi, this % n_pol)) + this % nu_fission = reshape(temp_arr, (/groups, groups, & + this % n_azi, this % n_pol/)) + deallocate(temp_arr) + else + call fatal_error("If fissionable, must provide nu_fission!") + end if + end if + if (get_fiss) then + if (check_for_node(node_xsdata, "fission")) then + allocate(temp_arr(groups * this % n_azi * this % n_pol)) + call get_node_array(node_xsdata, "fission", temp_arr) + allocate(this % fission(groups, this % n_azi, this % n_pol)) + this % fission = reshape(temp_arr, (/groups, this % n_azi, this % n_pol/)) + deallocate(temp_arr) + else + call fatal_error("Fission data missing, required due to fission& + & tallies in tallies.xml file!") + end if + end if + if (get_kfiss) then + if (check_for_node(node_xsdata, "kappa_fission")) then + allocate(temp_arr(groups * this % n_azi * this % n_pol)) + call get_node_array(node_xsdata, "kappa_fission", temp_arr) + allocate(this % k_fission(groups, this % n_azi, this % n_pol)) + this % k_fission = reshape(temp_arr, (/groups, this % n_azi, this % n_pol/)) + deallocate(temp_arr) + else + call fatal_error("kappa_fission data missing, required due to & + &kappa-fission tallies in tallies.xml file!") + end if + end if + end if + + if (check_for_node(node_xsdata, "absorption")) then + allocate(temp_arr(groups * this % n_azi * this % n_pol)) + call get_node_array(node_xsdata, "absorption", temp_arr) + allocate(this % absorption(groups, this % n_azi, this % n_pol)) + this % absorption = reshape(temp_arr, (/groups, this % n_azi, this % n_pol/)) + deallocate(temp_arr) + else + call fatal_error("Must provide absorption!") + end if + + allocate(this % scatter(groups, groups, order_dim, this % n_azi, this % n_pol)) + if (check_for_node(node_xsdata, "scatter")) then + allocate(temp_arr(groups * groups * order_dim * this % n_azi * this%n_pol)) + call get_node_array(node_xsdata, "scatter", temp_arr) + this % scatter = reshape(temp_arr, (/groups, groups, order_dim, & + this%n_azi,this%n_pol/)) + deallocate(temp_arr) + else + call fatal_error("Must provide scatter!") + end if + + if (check_for_node(node_xsdata, "total")) then + allocate(temp_arr(groups * this % n_azi * this % n_pol)) + call get_node_array(node_xsdata, "total", temp_arr) + allocate(this % total(groups, this % n_azi, this % n_pol)) + this % total = reshape(temp_arr, (/groups, this % n_azi, this % n_pol/)) + deallocate(temp_arr) + else + this % total = this % absorption + sum(this%scatter(:,:,1,:,:),dim=1) + end if + + ! Get Mult Data + allocate(this % mult(groups, groups, this % n_azi, this % n_pol)) + if (check_for_node(node_xsdata, "multiplicity")) then + arr_len = get_arraysize_double(node_xsdata, "multiplicity") + if (arr_len == groups * groups * this % n_azi * this % n_pol) then + allocate(temp_arr(arr_len)) + call get_node_array(node_xsdata, "multiplicity", temp_arr) + this % mult = reshape(temp_arr, (/groups, groups, this % n_azi, this % n_pol/)) + deallocate(temp_arr) + else + call fatal_error("Multiplicity Length Does Not Match!") + end if + else + this % mult = ONE + end if + + end subroutine nuclideangle_init + +!=============================================================================== +! NUCLIDECE_CLEAR resets and deallocates data in Nuclide, NuclideIso +! or NuclideAngle +!=============================================================================== + + subroutine nuclidece_clear(this) + + class(NuclideCE), intent(inout) :: this ! The Nuclide object to clear + + integer :: i ! Loop counter + + if (associated(this % urr_data)) deallocate(this % urr_data) + + if (allocated(this % reactions)) then + do i = 1, size(this % reactions) + call this % reactions(i) % clear() + end do + end if + + call this % reaction_index % clear() + + end subroutine nuclidece_clear + +!=============================================================================== +! NUCLIDE*_PRINT displays information about a continuous-energy neutron +! cross_section table and its reactions and secondary angle/energy distributions +!=============================================================================== + + subroutine nuclidece_print(this, unit) + class(NuclideCE), intent(in) :: this + integer, intent(in), optional :: unit + + integer :: i ! loop index over nuclides + integer :: unit_ ! unit to write to + integer :: size_xs ! memory used for cross-sections (bytes) + integer :: size_urr ! memory used for probability tables (bytes) + type(UrrData), pointer :: urr + + ! set default unit for writing information + if (present(unit)) then + unit_ = unit + else + unit_ = OUTPUT_UNIT + end if + + ! Initialize totals + size_urr = 0 + size_xs = 0 + + ! Basic nuclide information + write(unit_,*) 'Nuclide ' // trim(this % name) + write(unit_,*) ' zaid = ' // trim(to_str(this % zaid)) + write(unit_,*) ' awr = ' // trim(to_str(this % awr)) + write(unit_,*) ' kT = ' // trim(to_str(this % kT)) + write(unit_,*) ' # of grid points = ' // trim(to_str(this % n_grid)) + write(unit_,*) ' Fissionable = ', this % fissionable + write(unit_,*) ' # of fission reactions = ' // trim(to_str(this % n_fission)) + write(unit_,*) ' # of reactions = ' // trim(to_str(this % n_reaction)) + + ! Information on each reaction + write(unit_,*) ' Reaction Q-value COM IE' + do i = 1, this % n_reaction + associate (rxn => this % reactions(i)) + write(unit_,'(3X,A11,1X,F8.3,3X,L1,3X,I6)') & + reaction_name(rxn % MT), rxn % Q_value, rxn % scatter_in_cm, & + rxn % threshold + + ! Accumulate data size + size_xs = size_xs + (this % n_grid - rxn%threshold + 1) * 8 + end associate + end do + + ! Add memory required for summary reactions (total, absorption, fission, + ! nu-fission) + size_xs = 8 * this % n_grid * 4 + + ! Write information about URR probability tables + size_urr = 0 + if (this % urr_present) then + urr => this % urr_data + write(unit_,*) ' Unresolved resonance probability table:' + write(unit_,*) ' # of energies = ' // trim(to_str(urr % n_energy)) + write(unit_,*) ' # of probabilities = ' // trim(to_str(urr % n_prob)) + write(unit_,*) ' Interpolation = ' // trim(to_str(urr % interp)) + write(unit_,*) ' Inelastic flag = ' // trim(to_str(urr % inelastic_flag)) + write(unit_,*) ' Absorption flag = ' // trim(to_str(urr % absorption_flag)) + write(unit_,*) ' Multiply by smooth? ', urr % multiply_smooth + write(unit_,*) ' Min energy = ', trim(to_str(urr % energy(1))) + write(unit_,*) ' Max energy = ', trim(to_str(urr % energy(urr % n_energy))) + + ! Calculate memory used by probability tables and add to total + size_urr = urr % n_energy * (urr % n_prob * 6 + 1) * 8 + end if + + ! Write memory used + write(unit_,*) ' Memory Requirements' + write(unit_,*) ' Cross sections = ' // trim(to_str(size_xs)) // ' bytes' + write(unit_,*) ' Probability Tables = ' // & + trim(to_str(size_urr)) // ' bytes' + + ! Blank line at end of nuclide + write(unit_,*) + end subroutine nuclidece_print + + subroutine nuclidemg_print(this, unit_) + class(NuclideMG), intent(in) :: this + integer, intent(in) :: unit_ + + character(MAX_LINE_LEN) :: temp_str + + ! Basic nuclide information + write(unit_,*) 'Nuclide ' // trim(this % name) + if (this % zaid > 0) then + ! Dont print if data was macroscopic and thus zaid & AWR would be nonsense + write(unit_,*) ' zaid = ' // trim(to_str(this % zaid)) + write(unit_,*) ' awr = ' // trim(to_str(this % awr)) + end if + write(unit_,*) ' kT = ' // trim(to_str(this % kT)) + if (this % scatt_type == ANGLE_LEGENDRE) then + temp_str = "Legendre" + write(unit_,*) ' Scattering Type = ' // trim(temp_str) + write(unit_,*) ' # of Scatter Moments = ' // & + trim(to_str(this % order)) + else if (this % scatt_type == ANGLE_HISTOGRAM) then + temp_str = "Histogram" + write(unit_,*) ' Scattering Type = ' // trim(temp_str) + write(unit_,*) ' # of Scatter Bins = ' // & + trim(to_str(this % order)) + else if (this % scatt_type == ANGLE_TABULAR) then + temp_str = "Tabular" + write(unit_,*) ' Scattering Type = ' // trim(temp_str) + write(unit_,*) ' # of Scatter Points = ' // trim(to_str(this % order)) + end if + write(unit_,*) ' Fissionable = ', this % fissionable + + end subroutine nuclidemg_print + + subroutine nuclideiso_print(this, unit) + + class(NuclideIso), intent(in) :: this + integer, optional, intent(in) :: unit + + integer :: unit_ ! unit to write to + integer :: size_total, size_scattmat, size_mgxs + + ! set default unit for writing information + if (present(unit)) then + unit_ = unit + else + unit_ = OUTPUT_UNIT + end if + + ! Write Basic Nuclide Information + call nuclidemg_print(this, unit_) + + ! Determine size of mgxs and scattering matrices + size_scattmat = (size(this % scatter) + size(this % mult)) * 8 + size_mgxs = size(this % total) + size(this % absorption) + & + size(this % nu_fission) + size(this % k_fission) + & + size(this % fission) + size(this % chi) + size_mgxs = size_mgxs * 8 + + ! Calculate total memory + size_total = size_scattmat + size_mgxs + + ! Write memory used + write(unit_,*) ' Memory Requirements' + write(unit_,*) ' Cross sections = ' // trim(to_str(size_mgxs)) // ' bytes' + write(unit_,*) ' Scattering Matrices = ' // & + trim(to_str(size_scattmat)) // ' bytes' + write(unit_,*) ' Total = ' // trim(to_str(size_total)) // ' bytes' + + ! Blank line at end of nuclide + write(unit_,*) + + end subroutine nuclideiso_print + + subroutine nuclideangle_print(this, unit) + + class(NuclideAngle), intent(in) :: this + integer, optional, intent(in) :: unit + + integer :: unit_ ! unit to write to + integer :: size_total, size_scattmat, size_mgxs + + ! set default unit for writing information + if (present(unit)) then + unit_ = unit + else + unit_ = OUTPUT_UNIT + end if + + ! Write Basic Nuclide Information + call nuclidemg_print(this, unit_) + write(unit_,*) ' # of Polar Angles = ' // trim(to_str(this % n_pol)) + write(unit_,*) ' # of Azimuthal Angles = ' // trim(to_str(this % n_azi)) + + ! Determine size of mgxs and scattering matrices + size_scattmat = (size(this % scatter) + size(this % mult)) * 8 + size_mgxs = size(this % total) + size(this % absorption) + & + size(this % nu_fission) + size(this % k_fission) + & + size(this % fission) + size(this % chi) + size_mgxs = size_mgxs * 8 + + ! Calculate total memory + size_total = size_scattmat + size_mgxs + + ! Write memory used + write(unit_,*) ' Memory Requirements' + write(unit_,*) ' Cross sections = ' // trim(to_str(size_mgxs)) // ' bytes' + write(unit_,*) ' Scattering Matrices = ' // & + trim(to_str(size_scattmat)) // ' bytes' + write(unit_,*) ' Total = ' // trim(to_str(size_total)) // ' bytes' + + ! Blank line at end of nuclide + write(unit_,*) + + + end subroutine nuclideangle_print + +!=============================================================================== +! NUCLIDE*_GET_XS Returns the requested data type +!=============================================================================== + + function nuclideiso_get_xs(this, g, xstype, gout, uvw, mu, i_azi, i_pol) & + result(xs) + class(NuclideIso), intent(in) :: this + integer, intent(in) :: g ! Incoming Energy group + character(*), intent(in) :: xstype ! Cross Section Type + integer, optional, intent(in) :: gout ! Outgoing Group + real(8), optional, intent(in) :: uvw(3) ! Requested Angle + real(8), optional, intent(in) :: mu ! Change in angle + integer, optional, intent(in) :: i_azi ! Azimuthal Index + integer, optional, intent(in) :: i_pol ! Polar Index + real(8) :: xs ! Resultant xs + + xs = ZERO + + if ((xstype == 'nu_fission' .or. xstype == 'fission' .or. xstype =='chi' & + .or. xstype =='k_fission') .and. (.not. this % fissionable)) then + return + end if + + if (present(gout)) then + select case(xstype) + case('mult') + xs = this % mult(gout,g) + case('nu_fission') + xs = this % nu_fission(gout,g) + case('f_mu', 'f_mu/mult') + xs = this % calc_f(g, gout, mu) + if (xstype == 'f_mu/mult') then + xs = xs / this % mult(gout,g) + end if + end select + else + select case(xstype) + case('total') + xs = this % total(g) + case('absorption') + xs = this % absorption(g) + case('fission') + xs = this % fission(g) + case('k_fission') + if (allocated(this % k_fission)) then + xs = this % k_fission(g) + end if + case('chi') + xs = this % chi(g) + case('scatter') + xs = this % total(g) - this % absorption(g) + end select + end if + end function nuclideiso_get_xs + + function nuclideangle_get_xs(this, g, xstype, gout, uvw, mu, i_azi, i_pol) & + result(xs) + class(NuclideAngle), intent(in) :: this + integer, intent(in) :: g ! Incoming Energy group + character(*), intent(in) :: xstype ! Cross Section Type + integer, optional, intent(in) :: gout ! Outgoing Group + real(8), optional, intent(in) :: mu ! Change in angle + real(8), optional, intent(in) :: uvw(3) ! Requested Angle + integer, optional, intent(in) :: i_azi ! Azimuthal Index + integer, optional, intent(in) :: i_pol ! Polar Index + real(8) :: xs ! Resultant xs + + integer :: i_azi_, i_pol_ + + xs = ZERO + + if ((xstype == 'nu_fission' .or. xstype == 'fission' .or. xstype =='chi' & + .or. xstype =='k_fission') .and. (.not. this % fissionable)) then + return + end if + + if (present(i_azi) .and. present(i_pol)) then + i_azi_ = i_azi + i_pol_ = i_pol + else + call find_angle(this % polar, this % azimuthal, uvw, i_azi_, i_pol_) + end if + + if (present(gout)) then + select case(xstype) + case('mult') + xs = this % mult(gout,g,i_azi_,i_pol_) + case('nu_fission') + xs = this % nu_fission(gout,g,i_azi_,i_pol_) + case('chi') + xs = this % chi(gout,i_azi_,i_pol_) + case('f_mu', 'f_mu/mult') + xs = this % calc_f(g, gout, mu, I_AZI=i_azi_, I_POL=i_pol_) + if (xstype == 'f_mu/mult') then + xs = xs / this % mult(gout,g,i_azi_,i_pol_) + end if + end select + else + select case(xstype) + case('total') + xs = this % total(g,i_azi_,i_pol_) + case('absorption') + xs = this % absorption(g,i_azi_,i_pol_) + case('fission') + xs = this % fission(g,i_azi_,i_pol_) + case('k_fission') + if (allocated(this % k_fission)) then + xs = this % k_fission(g,i_azi_,i_pol_) + end if + case('chi') + xs = this % chi(g,i_azi_,i_pol_) + case('scatter') + xs = this % total(g,i_azi_,i_pol_) - this % absorption(g,i_azi_,i_pol_) + end select + end if + + end function nuclideangle_get_xs + +!=============================================================================== +! NUCLIDE*_CALC_F Finds the value of f(mu), the scattering angle probability, +! given mu +!=============================================================================== + + pure function nuclideiso_calc_f(this, gin, gout, mu, uvw, i_azi, i_pol) & + result(f) + class(NuclideIso), intent(in) :: this + integer, intent(in) :: gin ! Incoming Energy Group + integer, intent(in) :: gout ! Outgoing Energy Group + real(8), intent(in) :: mu ! Angle of interest + real(8), intent(in), optional :: uvw(3) ! Direction vector + integer, intent(in), optional :: i_azi ! Incoming Energy Group + integer, intent(in), optional :: i_pol ! Outgoing Energy Group + real(8) :: f ! Return value of f(mu) + + real(8) :: dmu, r + integer :: imu + + if (this % scatt_type == ANGLE_LEGENDRE) then + f = evaluate_legendre(this % scatter(gout,gin,:), mu) + else if (this % scatt_type == ANGLE_TABULAR) then + dmu = TWO / real(this % order - 1,8) + ! Find mu bin algebraically, knowing that the spacing is equal + f = (mu + ONE) / dmu + ONE + imu = floor(f) + ! But save the amount that mu is past the previous index + ! so we can use interpolation later. + f = f - real(imu,8) + ! Adjust so interpolation works on the last bin if necessary + if (imu == size(this % scatter, dim=3)) then + imu = imu - 1 + end if + + ! Now intepolate to find f(mu) + r = f / dmu + f = (ONE - r) * this % scatter(gout,gin,imu) + & + r * this % scatter(gout,gin,imu+1) + else ! (ANGLE_HISTOGRAM) + dmu = TWO / real(this % order,8) + ! Find mu bin algebraically, knowing that the spacing is equal + imu = floor((mu + ONE) / dmu + ONE) + ! Adjust so interpolation works on the last bin if necessary + if (imu == size(this % scatter, dim=3)) then + imu = imu - 1 + end if + f = this % scatter(gout, gin, imu) + + end if + + end function nuclideiso_calc_f + + pure function nuclideangle_calc_f(this, gin, gout, mu, uvw, i_azi, & + i_pol) result(f) + class(NuclideAngle), intent(in) :: this + integer, intent(in) :: gin ! Incoming Energy Group + integer, intent(in) :: gout ! Outgoing Energy Group + real(8), intent(in) :: mu ! Angle of interest + real(8), intent(in), optional :: uvw(3) ! Direction vector + integer, intent(in), optional :: i_azi ! Incoming Energy Group + integer, intent(in), optional :: i_pol ! Outgoing Energy Group + real(8) :: f ! Return value of f(mu) + + real(8) :: dmu, r + integer :: imu + integer :: i_azi_, i_pol_ + if (present(i_azi) .and. present(i_pol)) then + i_azi_ = i_azi + i_pol_ = i_pol + else if (present(uvw)) then + call find_angle(this % polar, this % azimuthal, uvw, i_azi_, i_pol_) + end if + + if (this % scatt_type == ANGLE_LEGENDRE) then + f = evaluate_legendre(this % scatter(gout,gin,:,i_azi_,i_pol_), mu) + else if (this % scatt_type == ANGLE_TABULAR) then + dmu = TWO / real(this % order - 1,8) + ! Find mu bin algebraically, knowing that the spacing is equal + f = (mu + ONE) / dmu + ONE + imu = floor(f) + ! But save the amount that mu is past the previous index + ! so we can use interpolation later. + f = f - real(imu,8) + ! Adjust so interpolation works on the last bin if necessary + if (imu == size(this % scatter, dim=3)) then + imu = imu - 1 + end if + + ! Now intepolate to find f(mu) + r = f / dmu + f = (ONE - r) * this % scatter(gout,gin,imu,i_azi_,i_pol_) + & + r * this % scatter(gout,gin,imu+1,i_azi_,i_pol_) + else ! (ANGLE_HISTOGRAM) + dmu = TWO / real(this % order,8) + ! Find mu bin algebraically, knowing that the spacing is equal + imu = floor((mu + ONE) / dmu + ONE) + ! Adjust so interpolation works on the last bin if necessary + if (imu == size(this % scatter, dim=3)) then + imu = imu - 1 + end if + f = this % scatter(gout, gin, imu,i_azi_,i_pol_) + + end if + + end function nuclideangle_calc_f + +end module nuclide_header diff --git a/src/output.F90 b/src/output.F90 index f133bad4b..125fe010b 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -2,7 +2,7 @@ module output use, intrinsic :: ISO_FORTRAN_ENV - use ace_header, only: Nuclide, Reaction, UrrData + use ace_header, only: Reaction, UrrData use constants use endf, only: reaction_name use error, only: fatal_error, warning @@ -12,8 +12,10 @@ module output use math, only: t_percentile use mesh_header, only: RegularMesh use mesh, only: mesh_indices_to_bin, bin_to_mesh_indices + use nuclide_header use particle_header, only: LocalCoord, Particle use plot_header + use sab_header, only: SAlphaBeta use string, only: to_upper, to_str use tally_header, only: TallyObject @@ -100,9 +102,9 @@ contains !=============================================================================== subroutine header(msg, unit, level) - character(*), intent(in) :: msg ! header message - integer, intent(in), optional :: unit ! unit to write to - integer, intent(in), optional :: level ! specified header level + character(*), intent(in) :: msg ! header message + integer, intent(in), optional :: unit ! unit to write to + integer, intent(in), optional :: level ! specified header level integer :: n ! number of = signs on left integer :: m ! number of = signs on right @@ -305,175 +307,16 @@ contains ! Display weight, energy, grid index, and interpolation factor write(ou,*) ' Weight = ' // to_str(p % wgt) - write(ou,*) ' Energy = ' // to_str(p % E) + if (run_CE) then + write(ou,*) ' Energy = ' // to_str(p % E) + else + write(ou,*) ' Energy Group = ' // to_str(p % g) + end if write(ou,*) ' Delayed Group = ' // to_str(p % delayed_group) write(ou,*) end subroutine print_particle -!=============================================================================== -! PRINT_NUCLIDE displays information about a continuous-energy neutron -! cross_section table and its reactions and secondary angle/energy distributions -!=============================================================================== - - subroutine print_nuclide(nuc, unit) - type(Nuclide), intent(in) :: nuc - integer, intent(in), optional :: unit - - integer :: i ! loop index over nuclides - integer :: unit_ ! unit to write to - integer :: size_xs ! memory used for cross-sections (bytes) - integer :: size_urr ! memory used for probability tables (bytes) - type(UrrData), pointer :: urr - - ! set default unit for writing information - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Initialize totals - size_urr = 0 - size_xs = 0 - - ! Basic nuclide information - write(unit_,*) 'Nuclide ' // trim(nuc % name) - write(unit_,*) ' zaid = ' // trim(to_str(nuc % zaid)) - write(unit_,*) ' awr = ' // trim(to_str(nuc % awr)) - write(unit_,*) ' kT = ' // trim(to_str(nuc % kT)) - write(unit_,*) ' # of grid points = ' // trim(to_str(nuc % n_grid)) - write(unit_,*) ' Fissionable = ', nuc % fissionable - write(unit_,*) ' # of fission reactions = ' // trim(to_str(nuc % n_fission)) - write(unit_,*) ' # of reactions = ' // trim(to_str(nuc % n_reaction)) - - ! Information on each reaction - write(unit_,*) ' Reaction Q-value COM IE' - do i = 1, nuc % n_reaction - associate (rxn => nuc % reactions(i)) - write(unit_,'(3X,A11,1X,F8.3,3X,L1,3X,I6)') & - reaction_name(rxn % MT), rxn % Q_value, rxn % scatter_in_cm, & - rxn % threshold - - ! Accumulate data size - size_xs = size_xs + (nuc % n_grid - rxn%threshold + 1) * 8 - end associate - end do - - ! Add memory required for summary reactions (total, absorption, fission, - ! nu-fission) - size_xs = 8 * nuc % n_grid * 4 - - ! Write information about URR probability tables - size_urr = 0 - if (nuc % urr_present) then - urr => nuc % urr_data - write(unit_,*) ' Unresolved resonance probability table:' - write(unit_,*) ' # of energies = ' // trim(to_str(urr % n_energy)) - write(unit_,*) ' # of probabilities = ' // trim(to_str(urr % n_prob)) - write(unit_,*) ' Interpolation = ' // trim(to_str(urr % interp)) - write(unit_,*) ' Inelastic flag = ' // trim(to_str(urr % inelastic_flag)) - write(unit_,*) ' Absorption flag = ' // trim(to_str(urr % absorption_flag)) - write(unit_,*) ' Multiply by smooth? ', urr % multiply_smooth - write(unit_,*) ' Min energy = ', trim(to_str(urr % energy(1))) - write(unit_,*) ' Max energy = ', trim(to_str(urr % energy(urr % n_energy))) - - ! Calculate memory used by probability tables and add to total - size_urr = urr % n_energy * (urr % n_prob * 6 + 1) * 8 - end if - - ! Write memory used - write(unit_,*) ' Memory Requirements' - write(unit_,*) ' Cross sections = ' // trim(to_str(size_xs)) // ' bytes' - write(unit_,*) ' Probability Tables = ' // & - trim(to_str(size_urr)) // ' bytes' - - ! Blank line at end of nuclide - write(unit_,*) - - end subroutine print_nuclide - -!=============================================================================== -! PRINT_SAB_TABLE displays information about a S(a,b) table containing data -! describing thermal scattering from bound materials such as hydrogen in water. -!=============================================================================== - - subroutine print_sab_table(sab, unit) - type(SAlphaBeta), intent(in) :: sab - integer, intent(in), optional :: unit - - integer :: size_sab ! memory used by S(a,b) table - integer :: unit_ ! unit to write to - integer :: i ! Loop counter for parsing through sab % zaid - integer :: char_count ! Counter for the number of characters on a line - - ! set default unit for writing information - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Basic S(a,b) table information - write(unit_,*) 'S(a,b) Table ' // trim(sab % name) - write(unit_,'(A)',advance="no") ' zaids = ' - ! Initialize the counter based on the above string - char_count = 11 - do i = 1, sab % n_zaid - ! Deal with a line thats too long - if (char_count >= 73) then ! 73 = 80 - (5 ZAID chars + 1 space + 1 comma) - ! End the line - write(unit_,*) "" - ! Add 11 leading blanks - write(unit_,'(A)', advance="no") " " - ! reset the counter to 11 - char_count = 11 - end if - if (i < sab % n_zaid) then - ! Include a comma - write(unit_,'(A)',advance="no") trim(to_str(sab % zaid(i))) // ", " - char_count = char_count + len(trim(to_str(sab % zaid(i)))) + 2 - else - ! Don't include a comma, since we are all done - write(unit_,'(A)',advance="no") trim(to_str(sab % zaid(i))) - end if - - end do - write(unit_,*) "" ! Move to next line - write(unit_,*) ' awr = ' // trim(to_str(sab % awr)) - write(unit_,*) ' kT = ' // trim(to_str(sab % kT)) - - ! Inelastic data - write(unit_,*) ' # of Incoming Energies (Inelastic) = ' // & - trim(to_str(sab % n_inelastic_e_in)) - write(unit_,*) ' # of Outgoing Energies (Inelastic) = ' // & - trim(to_str(sab % n_inelastic_e_out)) - write(unit_,*) ' # of Outgoing Angles (Inelastic) = ' // & - trim(to_str(sab % n_inelastic_mu)) - write(unit_,*) ' Threshold for Inelastic = ' // & - trim(to_str(sab % threshold_inelastic)) - - ! Elastic data - if (sab % n_elastic_e_in > 0) then - write(unit_,*) ' # of Incoming Energies (Elastic) = ' // & - trim(to_str(sab % n_elastic_e_in)) - write(unit_,*) ' # of Outgoing Angles (Elastic) = ' // & - trim(to_str(sab % n_elastic_mu)) - write(unit_,*) ' Threshold for Elastic = ' // & - trim(to_str(sab % threshold_elastic)) - end if - - ! Determine memory used by S(a,b) table and write out - size_sab = 8 * (sab % n_inelastic_e_in * (2 + sab % n_inelastic_e_out * & - (1 + sab % n_inelastic_mu)) + sab % n_elastic_e_in * & - (2 + sab % n_elastic_mu)) - write(unit_,*) ' Memory Used = ' // trim(to_str(size_sab)) // ' bytes' - - ! Blank line at end - write(unit_,*) - - end subroutine print_sab_table - !=============================================================================== ! WRITE_XS_SUMMARY writes information about each nuclide and S(a,b) table to a ! file called cross_sections.out. This file shows the list of reactions as well @@ -486,8 +329,6 @@ contains integer :: i ! loop index integer :: unit_xs ! cross_sections.out file unit character(MAX_FILE_LEN) :: path ! path of summary file - type(Nuclide), pointer :: nuc - type(SAlphaBeta), pointer :: sab ! Create filename for log file path = trim(path_output) // "cross_sections.out" @@ -498,21 +339,22 @@ contains ! Write header call header("CROSS SECTION TABLES", unit=unit_xs) - NUCLIDE_LOOP: do i = 1, n_nuclides_total - ! Get pointer to nuclide - nuc => nuclides(i) + if (run_CE) then + NUCLIDE_LOOP: do i = 1, n_nuclides_total + ! Print information about nuclide + call nuclides(i) % print(unit=unit_xs) + end do NUCLIDE_LOOP - ! Print information about nuclide - call print_nuclide(nuc, unit=unit_xs) - end do NUCLIDE_LOOP - - SAB_TABLES_LOOP: do i = 1, n_sab_tables - ! Get pointer to S(a,b) table - sab => sab_tables(i) - - ! Print information about S(a,b) table - call print_sab_table(sab, unit=unit_xs) - end do SAB_TABLES_LOOP + SAB_TABLES_LOOP: do i = 1, n_sab_tables + ! Print information about S(a,b) table + call sab_tables(i) % print(unit=unit_xs) + end do SAB_TABLES_LOOP + else + NuclideMG_LOOP: do i = 1, n_nuclides_total + ! Print information about nuclide + call nuclides_mg(i) % obj % print(unit=unit_xs) + end do NuclideMG_LOOP + end if ! Close cross section summary file close(unit_xs) diff --git a/src/particle_header.F90 b/src/particle_header.F90 index 30f5e8bb6..c1f02eca2 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -47,9 +47,14 @@ module particle_header integer :: n_coord ! number of current coordinates type(LocalCoord) :: coord(MAX_COORD) ! coordinates for all levels + ! Energy Data + real(8) :: E ! post-collision energy + real(8) :: last_E ! pre-collision energy + integer :: g ! post-collision energy group (MG only) + integer :: last_g ! pre-collision energy group (MG only) + ! Other physical data real(8) :: wgt ! particle weight - real(8) :: E ! energy real(8) :: mu ! angle of scatter logical :: alive ! is particle alive? @@ -57,7 +62,6 @@ module particle_header real(8) :: last_xyz(3) ! previous coordinates real(8) :: last_uvw(3) ! previous direction coordinates real(8) :: last_wgt ! pre-collision particle weight - real(8) :: last_E ! pre-collision energy real(8) :: absorb_wgt ! weight absorbed for survival biasing ! What event last took place @@ -128,6 +132,7 @@ contains this % fission = .false. this % delayed_group = 0 this % n_delayed_bank(:) = 0 + this % g = 1 ! Set up base level coordinates this % coord(1) % universe = BASE_UNIVERSE @@ -174,9 +179,11 @@ contains ! fission, or simply as a secondary particle. !=============================================================================== - subroutine initialize_from_source(this, src) - class(Particle), intent(inout) :: this - type(Bank), intent(in) :: src + subroutine initialize_from_source(this, src, run_CE, energy_bin_avg) + class(Particle), intent(inout) :: this + type(Bank), intent(in) :: src + logical, intent(in) :: run_CE + real(8), allocatable, intent(in) :: energy_bin_avg(:) ! set defaults call this % initialize() @@ -188,8 +195,14 @@ contains this % coord(1) % uvw = src % uvw this % last_xyz = src % xyz this % last_uvw = src % uvw - this % E = src % E - this % last_E = src % E + if (run_CE) then + this % E = src % E + else + this % g = int(src % E) + this % last_g = int(src % E) + this % E = energy_bin_avg(this % g) + end if + this % last_E = src % E end subroutine initialize_from_source @@ -198,10 +211,11 @@ contains ! the secondary bank and increments the number of sites in the secondary bank. !=============================================================================== - subroutine create_secondary(this, uvw, type) + subroutine create_secondary(this, uvw, type, run_CE) class(Particle), intent(inout) :: this real(8), intent(in) :: uvw(3) integer, intent(in) :: type + logical, intent(in) :: run_CE integer :: n @@ -215,8 +229,11 @@ contains this % secondary_bank(n) % wgt = this % wgt this % secondary_bank(n) % xyz(:) = this % coord(1) % xyz this % secondary_bank(n) % uvw(:) = uvw - this % secondary_bank(n) % E = this % E this % n_secondary = n + this % secondary_bank(this % n_secondary) % E = this % E + if (.not. run_CE) then + this % secondary_bank(this % n_secondary) % E = real(this % g, 8) + end if end subroutine create_secondary diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index 2e0523d48..9d49a4f97 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -97,6 +97,7 @@ contains call read_dataset(file_id, 'id', p%id) call read_dataset(file_id, 'weight', p%wgt) call read_dataset(file_id, 'energy', p%E) + call read_dataset(file_id, 'energy_group', p%g) call read_dataset(file_id, 'xyz', p%coord(1)%xyz) call read_dataset(file_id, 'uvw', p%coord(1)%uvw) @@ -105,6 +106,7 @@ contains p%last_xyz = p%coord(1)%xyz p%last_uvw = p%coord(1)%uvw p%last_E = p%E + p%last_g = p%g ! Close hdf5 file call file_close(file_id) diff --git a/src/particle_restart_write.F90 b/src/particle_restart_write.F90 index edd779df0..d983b3db8 100644 --- a/src/particle_restart_write.F90 +++ b/src/particle_restart_write.F90 @@ -1,10 +1,10 @@ module particle_restart_write - use bank_header, only: Bank + use bank_header, only: Bank use global use hdf5_interface - use particle_header, only: Particle - use string, only: to_str + use particle_header, only: Particle + use string, only: to_str use hdf5 diff --git a/src/physics.F90 b/src/physics.F90 index da2682ebf..e41b3b4e9 100644 --- a/src/physics.F90 +++ b/src/physics.F90 @@ -1,6 +1,6 @@ module physics - use ace_header, only: Nuclide, Reaction + use ace_header, only: Reaction use constants use cross_section, only: elastic_xs_0K use endf, only: reaction_name @@ -9,15 +9,17 @@ module physics use global use interpolation, only: interpolate_tab1 use material_header, only: Material - use math, only: rotate_angle, maxwell_spectrum, watt_spectrum + use math use mesh, only: get_mesh_indices + use nuclide_header use output, only: write_message use particle_header, only: Particle use particle_restart_write, only: write_particle_restart + use physics_common use random_lcg, only: prn use search, only: binary_search - use string, only: to_str use secondary_uncorrelated, only: UncorrelatedAngleEnergy + use string, only: to_str implicit none @@ -73,7 +75,7 @@ contains integer :: i_nuclide ! index in nuclides array integer :: i_nuc_mat ! index in material's nuclides array integer :: i_reaction ! index in nuc % reactions array - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc call sample_nuclide(p, 'total ', i_nuclide, i_nuc_mat) @@ -196,7 +198,7 @@ contains real(8) :: f real(8) :: prob real(8) :: cutoff - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc ! Get pointer to nuclide nuc => nuclides(i_nuclide) @@ -242,7 +244,6 @@ contains !=============================================================================== subroutine absorption(p, i_nuclide) - type(Particle), intent(inout) :: p integer, intent(in) :: i_nuclide @@ -278,33 +279,11 @@ contains end subroutine absorption -!=============================================================================== -! RUSSIAN_ROULETTE -!=============================================================================== - - subroutine russian_roulette(p) - - type(Particle), intent(inout) :: p - - if (p % wgt < weight_cutoff) then - if (prn() < p % wgt / weight_survive) then - p % wgt = weight_survive - p % last_wgt = p % wgt - else - p % wgt = ZERO - p % last_wgt = ZERO - p % alive = .false. - end if - end if - - end subroutine russian_roulette - !=============================================================================== ! SCATTER !=============================================================================== subroutine scatter(p, i_nuclide, i_nuc_mat) - type(Particle), intent(inout) :: p integer, intent(in) :: i_nuclide integer, intent(in) :: i_nuc_mat @@ -317,7 +296,7 @@ contains real(8) :: uvw_new(3) ! outgoing uvw for iso-in-lab scattering real(8) :: uvw_old(3) ! incoming uvw for iso-in-lab scattering real(8) :: phi ! azimuthal angle for iso-in-lab scattering - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc ! copy incoming direction uvw_old(:) = p % coord(1) % uvw @@ -432,7 +411,7 @@ contains real(8) :: v_cm(3) ! velocity of center-of-mass real(8) :: v_t(3) ! velocity of target nucleus real(8) :: uvw_cm(3) ! directional cosines in center-of-mass - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc ! get pointer to nuclide nuc => nuclides(i_nuclide) @@ -501,7 +480,6 @@ contains !=============================================================================== subroutine sab_scatter(i_nuclide, i_sab, E, uvw, mu) - integer, intent(in) :: i_nuclide ! index in micro_xs integer, intent(in) :: i_sab ! index in sab_tables real(8), intent(inout) :: E ! incoming/outgoing energy @@ -759,7 +737,7 @@ contains !=============================================================================== subroutine sample_target_velocity(nuc, v_target, E, uvw, v_neut, wgt, xs_eff) - type(Nuclide), intent(in) :: nuc ! target nuclide at temperature T + type(NuclideCE), intent(in) :: nuc ! target nuclide at temperature T real(8), intent(out) :: v_target(3) ! target velocity real(8), intent(in) :: v_neut(3) ! neutron velocity real(8), intent(in) :: E ! particle energy @@ -1004,10 +982,10 @@ contains !=============================================================================== subroutine sample_cxs_target_velocity(nuc, v_target, E, uvw) - type(Nuclide), intent(in) :: nuc ! target nuclide at temperature - real(8), intent(out) :: v_target(3) - real(8), intent(in) :: E - real(8), intent(in) :: uvw(3) + type(NuclideCE), intent(in) :: nuc ! target nuclide at temperature + real(8), intent(out) :: v_target(3) + real(8), intent(in) :: E + real(8), intent(in) :: uvw(3) real(8) :: kT ! equilibrium temperature of target in MeV real(8) :: awr ! target/neutron mass ratio @@ -1092,7 +1070,7 @@ contains real(8) :: phi ! fission neutron azimuthal angle real(8) :: weight ! weight adjustment for ufs method logical :: in_mesh ! source site in ufs mesh? - type(Nuclide), pointer :: nuc + type(NuclideCE), pointer :: nuc ! Get pointers nuc => nuclides(i_nuclide) @@ -1202,8 +1180,8 @@ contains function sample_fission_energy(nuc, rxn, p) result(E_out) - type(Nuclide), intent(in) :: nuc - type(Reaction), intent(in) :: rxn + type(NuclideCE), intent(in) :: nuc + type(Reaction), intent(in) :: rxn type(Particle), intent(inout) :: p ! Particle causing fission real(8) :: E_out ! outgoing energy of fission neutron @@ -1315,9 +1293,9 @@ contains !=============================================================================== subroutine inelastic_scatter(nuc, rxn, p) - type(Nuclide), intent(in) :: nuc - type(Reaction), intent(in) :: rxn - type(Particle), intent(inout) :: p + type(NuclideCE), intent(in) :: nuc + type(Reaction), intent(in) :: rxn + type(Particle), intent(inout) :: p integer :: i ! loop index real(8) :: E ! energy in lab (incoming/outgoing) @@ -1365,7 +1343,7 @@ contains p % wgt = yield * p % wgt else do i = 1, rxn % multiplicity - 1 - call p % create_secondary(p % coord(1) % uvw, NEUTRON) + call p % create_secondary(p % coord(1) % uvw, NEUTRON, run_CE=.True.) end do end if diff --git a/src/physics_common.F90 b/src/physics_common.F90 new file mode 100644 index 000000000..98d240c07 --- /dev/null +++ b/src/physics_common.F90 @@ -0,0 +1,33 @@ +module physics_common + + use constants + use global, only: weight_cutoff, weight_survive + use particle_header, only: Particle + use random_lcg, only: prn + + implicit none + +contains + +!=============================================================================== +! RUSSIAN_ROULETTE +!=============================================================================== + + subroutine russian_roulette(p) + + type(Particle), intent(inout) :: p + + if (p % wgt < weight_cutoff) then + if (prn() < p % wgt / weight_survive) then + p % wgt = weight_survive + p % last_wgt = p % wgt + else + p % wgt = ZERO + p % last_wgt = ZERO + p % alive = .false. + end if + end if + + end subroutine russian_roulette + +end module physics_common diff --git a/src/physics_mg.F90 b/src/physics_mg.F90 new file mode 100644 index 000000000..6a58540c1 --- /dev/null +++ b/src/physics_mg.F90 @@ -0,0 +1,271 @@ +module physics_mg + ! This module contains the multi-group specific physics routines so as to not + ! hinder performance of the CE versions with multiple if-thens. + + use constants + use error, only: fatal_error, warning + use global + use macroxs_header, only: MacroXS, MacroXSContainer + use material_header, only: Material + use math, only: rotate_angle + use mesh, only: get_mesh_indices + use output, only: write_message + use particle_header, only: Particle + use particle_restart_write, only: write_particle_restart + use physics_common + use random_lcg, only: prn + use scattdata_header + use string, only: to_str + + implicit none + +contains + +!=============================================================================== +! COLLISION_MG samples a nuclide and reaction and then calls the appropriate +! routine for that reaction +!=============================================================================== + + subroutine collision_mg(p) + + type(Particle), intent(inout) :: p + + ! Store pre-collision particle properties + p % last_wgt = p % wgt + p % last_g = p % g + p % last_E = p % E + p % last_uvw = p % coord(1) % uvw + + ! Add to collision counter for particle + p % n_collision = p % n_collision + 1 + + ! Sample nuclide/reaction for the material the particle is in + call sample_reaction(p) + + ! Display information about collision + if (verbosity >= 10 .or. trace) then + call write_message(" " // "Energy Group = " // trim(to_str(p % g))) + end if + + end subroutine collision_mg + +!=============================================================================== +! SAMPLE_REACTION samples a nuclide based on the macroscopic cross sections for +! each nuclide within a material and then samples a reaction for that nuclide +! and calls the appropriate routine to process the physics. Note that there is +! special logic when suvival biasing is turned on since fission and +! disappearance are treated implicitly. +!=============================================================================== + + subroutine sample_reaction(p) + + type(Particle), intent(inout) :: p + + type(Material), pointer :: mat + + mat => materials(p % material) + + ! Create fission bank sites. Note that while a fission reaction is sampled, + ! it never actually "happens", i.e. the weight of the particle does not + ! change when sampling fission sites. The following block handles all + ! absorption (including fission) + + if (mat % fissionable) then + if (run_mode == MODE_EIGENVALUE) then + call create_fission_sites(p, fission_bank, n_bank) + elseif (run_mode == MODE_FIXEDSOURCE) then + call create_fission_sites(p, p % secondary_bank, p % n_secondary) + end if + end if + ! If survival biasing is being used, the following subroutine adjusts the + ! weight of the particle. Otherwise, it checks to see if absorption occurs + + if (material_xs % absorption > ZERO) then + call absorption(p) + else + p % absorb_wgt = ZERO + end if + if (.not. p % alive) return + + ! Sample a scattering reaction and determine the secondary energy of the + ! exiting neutron + call scatter(p) + + ! Play russian roulette if survival biasing is turned on + if (survival_biasing) then + call russian_roulette(p) + if (.not. p % alive) return + end if + + end subroutine sample_reaction + +!=============================================================================== +! ABSORPTION +!=============================================================================== + + subroutine absorption(p) + + type(Particle), intent(inout) :: p + + if (survival_biasing) then + ! Determine weight absorbed in survival biasing + p % absorb_wgt = (p % wgt * & + material_xs % absorption / material_xs % total) + + ! Adjust weight of particle by probability of absorption + p % wgt = p % wgt - p % absorb_wgt + p % last_wgt = p % wgt + + ! Score implicit absorption estimate of keff +!$omp atomic + global_tallies(K_ABSORPTION) % value = & + global_tallies(K_ABSORPTION) % value + p % absorb_wgt * & + material_xs % nu_fission / material_xs % absorption + else + ! See if disappearance reaction happens + if (material_xs % absorption > prn() * material_xs % total) then + ! Score absorption estimate of keff +!$omp atomic + global_tallies(K_ABSORPTION) % value = & + global_tallies(K_ABSORPTION) % value + p % wgt * & + material_xs % nu_fission / material_xs % absorption + + p % alive = .false. + p % event = EVENT_ABSORB + end if + end if + + end subroutine absorption + +!=============================================================================== +! SCATTER +!=============================================================================== + + subroutine scatter(p) + + type(Particle), intent(inout) :: p + + call macro_xs(p % material) % obj % sample_scatter(p % coord(1) % uvw, & + p % last_g, p % g, & + p % mu, p % wgt) + + ! Update energy value for downstream compatability (in tallying) + p % E = energy_bin_avg(p % g) + + ! Convert change in angle (mu) to new direction + p % coord(1) % uvw = rotate_angle(p % coord(1) % uvw, p % mu) + + ! Set event component + p % event = EVENT_SCATTER + + end subroutine scatter + +!=============================================================================== +! CREATE_FISSION_SITES determines the average total, prompt, and delayed +! neutrons produced from fission and creates appropriate bank sites. +!=============================================================================== + + subroutine create_fission_sites(p, bank_array, size_bank) + type(Particle), intent(inout) :: p + type(Bank), intent(inout) :: bank_array(:) + integer(8), intent(inout) :: size_bank + + integer :: i ! loop index + integer :: nu ! actual number of neutrons produced + integer :: ijk(3) ! indices in ufs mesh + real(8) :: nu_t ! total nu + real(8) :: mu ! fission neutron angular cosine + real(8) :: phi ! fission neutron azimuthal angle + real(8) :: weight ! weight adjustment for ufs method + logical :: in_mesh ! source site in ufs mesh? + class(MacroXS), pointer :: xs + + ! Get Pointers + xs => macro_xs(p % material) % obj + + ! TODO: Heat generation from fission + + ! If uniform fission source weighting is turned on, we increase of decrease + ! the expected number of fission sites produced + + if (ufs) then + ! Determine indices on ufs mesh for current location + call get_mesh_indices(ufs_mesh, p % coord(1) % xyz, ijk, in_mesh) + if (.not. in_mesh) then + call write_particle_restart(p) + call fatal_error("Source site outside UFS mesh!") + end if + + if (source_frac(1,ijk(1),ijk(2),ijk(3)) /= ZERO) then + weight = ufs_mesh % volume_frac / source_frac(1,ijk(1),ijk(2),ijk(3)) + else + weight = ONE + end if + else + weight = ONE + end if + + ! Determine expected number of neutrons produced + nu_t = p % wgt / keff * weight * & + material_xs % nu_fission / material_xs % total + ! Sample number of neutrons produced + if (prn() > nu_t - int(nu_t)) then + nu = int(nu_t) + else + nu = int(nu_t) + 1 + end if + + ! Check for bank size getting hit. For fixed source calculations, this is a + ! fatal error. For eigenvalue calculations, it just means that k-effective + ! was too high for a single batch. + if (size_bank + nu > size(bank_array)) then + if (run_mode == MODE_FIXEDSOURCE) then + call fatal_error("Secondary particle bank size limit reached. If you & + &are running a subcritical multiplication problem, k-effective & + &may be too close to one.") + else + if (master) call warning("Maximum number of sites in fission bank & + &reached. This can result in irreproducible results using different & + &numbers of processes/threads.") + end if + end if + + ! Bank source neutrons + if (nu == 0 .or. size_bank == size(bank_array)) return + + p % fission = .true. ! Fission neutrons will be banked + do i = int(size_bank,4) + 1, int(min(size_bank + nu, int(size(bank_array),8)),4) + ! Bank source neutrons by copying particle data + bank_array(i) % xyz = p % coord(1) % xyz + + ! Set weight of fission bank site + bank_array(i) % wgt = ONE/weight + + ! Sample cosine of angle -- fission neutrons are always emitted + ! isotropically. Sometimes in ACE data, fission reactions actually have + ! an angular distribution listed, but for those that do, it's simply just + ! a uniform distribution in mu + mu = TWO * prn() - ONE + + ! Sample azimuthal angle uniformly in [0,2*pi) + phi = TWO*PI*prn() + bank_array(i) % uvw(1) = mu + bank_array(i) % uvw(2) = sqrt(ONE - mu*mu) * cos(phi) + bank_array(i) % uvw(3) = sqrt(ONE - mu*mu) * sin(phi) + + ! Sample secondary energy distribution for fission reaction and set energy + ! in fission bank + bank_array(i) % E = & + real(xs % sample_fission_energy(p % g, fission_bank(i) % uvw), 8) + end do + + ! increment number of bank sites + size_bank = min(size_bank + nu, int(size(bank_array),8)) + + ! Store total weight banked for analog fission tallies + p % n_bank = nu + p % wgt_bank = nu/weight + + end subroutine create_fission_sites + +end module physics_mg diff --git a/src/plot.F90 b/src/plot.F90 index 75d0bc944..796cce6af 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -9,7 +9,7 @@ module plot use mesh, only: get_mesh_indices use mesh_header, only: RegularMesh use output, only: write_message - use particle_header, only: Particle, LocalCoord + use particle_header, only: LocalCoord, Particle use plot_header use ppmlib, only: Image, init_image, allocate_image, & deallocate_image, set_pixel @@ -56,7 +56,7 @@ contains subroutine position_rgb(p, pl, rgb, id) - type(Particle), intent(inout) :: p + type(Particle), intent(inout) :: p type(ObjectPlot), pointer, intent(in) :: pl integer, intent(out) :: rgb(3) integer, intent(out) :: id @@ -364,7 +364,7 @@ contains real(8) :: ll(3) ! lower left starting point for each sweep direction type(Particle) :: p type(ProgressBar) :: progress - type(c_ptr) :: f_ptr + type(c_ptr) :: f_ptr ! compute voxel widths in each direction vox = pl % width/dble(pl % pixels) diff --git a/src/relaxng/materials.rnc b/src/relaxng/materials.rnc index da68ebf9e..21b36c07e 100644 --- a/src/relaxng/materials.rnc +++ b/src/relaxng/materials.rnc @@ -11,10 +11,10 @@ element materials { } & element nuclide { - (element name { xsd:string { maxLength = "7" } } | + (element name { xsd:string { maxLength = "7" } } | attribute name { xsd:string { maxLength = "7" } }) & - (element xs { xsd:string { maxLength = "3" } } | - attribute xs { xsd:string { maxLength = "3" } })? & + (element xs { xsd:string { maxLength = "5" } } | + attribute xs { xsd:string { maxLength = "5" } })? & (element scattering { ( "data" | "iso-in-lab" ) } | attribute scattering { ( "data" | "iso-in-lab" ) })? & ( @@ -23,11 +23,18 @@ element materials { ) }* & + element macroscopic { + (element name { xsd:string } | + attribute name { xsd:string }) & + (element xs { xsd:string { maxLength = "5" } } | + attribute xs { xsd:string { maxLength = "5" } }) + }* & + element element { - (element name { xsd:string { maxLength = "2" } } | + (element name { xsd:string { maxLength = "2" } } | attribute name { xsd:string { maxLength = "2" } }) & - (element xs { xsd:string { maxLength = "3" } } | - attribute xs { xsd:string { maxLength = "3" } })? & + (element xs { xsd:string { maxLength = "5" } } | + attribute xs { xsd:string { maxLength = "5" } })? & (element scattering { ( "data" | "iso-in-lab" ) } | attribute scattering { ( "data" | "iso-in-lab" ) })? & ( @@ -37,12 +44,12 @@ element materials { }* & element sab { - (element name { xsd:string { maxLength = "7" } } | + (element name { xsd:string { maxLength = "7" } } | attribute name { xsd:string { maxLength = "7" } }) & - (element xs { xsd:string { maxLength = "3" } } | - attribute xs { xsd:string { maxLength = "3" } })? + (element xs { xsd:string { maxLength = "5" } } | + attribute xs { xsd:string { maxLength = "5" } })? }* }+ & - element default_xs { xsd:string { maxLength = "3" } }? + element default_xs { xsd:string { maxLength = "5" } }? } diff --git a/src/relaxng/materials.rng b/src/relaxng/materials.rng index 7aba5f738..6a4bc3964 100644 --- a/src/relaxng/materials.rng +++ b/src/relaxng/materials.rng @@ -118,6 +118,36 @@ + + + + + + + 7 + + + + + 7 + + + + + + + 3 + + + + + 3 + + + + + + diff --git a/src/relaxng/mg_cross_sections.rnc b/src/relaxng/mg_cross_sections.rnc new file mode 100644 index 000000000..b2aaec4d4 --- /dev/null +++ b/src/relaxng/mg_cross_sections.rnc @@ -0,0 +1,61 @@ +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 new file mode 100644 index 000000000..b293cddbe --- /dev/null +++ b/src/relaxng/mg_cross_sections.rng @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/settings.rnc b/src/relaxng/settings.rnc index 68f221f67..4e055a7f2 100644 --- a/src/relaxng/settings.rnc +++ b/src/relaxng/settings.rnc @@ -34,6 +34,8 @@ element settings { element energy_grid { ( "nuclide" | "log" | "logarithm" | "logarithmic" | "material-union" | "union" ) }? & + element energy_mode { ( "continuous-energy" | "ce" | "CE" | "multi-group" | "mg" | "MG" ) }? & + element entropy { (element dimension { list { xsd:int+ } } | attribute dimension { list { xsd:int+ } })? & @@ -45,6 +47,8 @@ element settings { element log_grid_bins { xsd:positiveInteger }? & + element max_order { xsd:nonNegativeInteger }? & + element natural_elements { xsd:string { maxLength = "20" } }? & element no_reduce { xsd:boolean }? & diff --git a/src/relaxng/settings.rng b/src/relaxng/settings.rng index ea3efaff9..527aa6904 100644 --- a/src/relaxng/settings.rng +++ b/src/relaxng/settings.rng @@ -133,6 +133,18 @@ + + + + continuous-energy + ce + CE + multi-group + mg + MG + + + @@ -194,6 +206,11 @@ + + + + + diff --git a/src/sab_header.F90 b/src/sab_header.F90 new file mode 100644 index 000000000..695f735c0 --- /dev/null +++ b/src/sab_header.F90 @@ -0,0 +1,150 @@ +module sab_header + + use, intrinsic :: ISO_FORTRAN_ENV + + use constants + use string, only: to_str + + implicit none + +!=============================================================================== +! DISTENERGYSAB contains the secondary energy/angle distributions for inelastic +! thermal scattering collisions which utilize a continuous secondary energy +! representation. +!=============================================================================== + + type DistEnergySab + integer :: n_e_out + real(8), allocatable :: e_out(:) + real(8), allocatable :: e_out_pdf(:) + real(8), allocatable :: e_out_cdf(:) + real(8), allocatable :: mu(:,:) + end type DistEnergySab + +!=============================================================================== +! SALPHABETA contains S(a,b) data for thermal neutron scattering, typically off +! of light isotopes such as water, graphite, Be, etc +!=============================================================================== + + type SAlphaBeta + character(10) :: name ! name of table, e.g. lwtr.10t + real(8) :: awr ! weight of nucleus in neutron masses + real(8) :: kT ! temperature in MeV (k*T) + integer :: n_zaid ! Number of valid zaids + integer, allocatable :: zaid(:) ! List of valid Z and A identifiers, e.g. 6012 + + ! threshold for S(a,b) treatment (usually ~4 eV) + real(8) :: threshold_inelastic + real(8) :: threshold_elastic = ZERO + + ! Inelastic scattering data + integer :: n_inelastic_e_in ! # of incoming E for inelastic + integer :: n_inelastic_e_out ! # of outgoing E for inelastic + integer :: n_inelastic_mu ! # of outgoing angles for inelastic + integer :: secondary_mode ! secondary mode (equal/skewed/continuous) + real(8), allocatable :: inelastic_e_in(:) + real(8), allocatable :: inelastic_sigma(:) + ! The following are used only if secondary_mode is 0 or 1 + real(8), allocatable :: inelastic_e_out(:,:) + real(8), allocatable :: inelastic_mu(:,:,:) + ! The following is used only if secondary_mode is 3 + ! The different implementation is necessary because the continuous + ! representation has a variable number of outgoing energy points for each + ! incoming energy + type(DistEnergySab), allocatable :: inelastic_data(:) ! One for each Ein + + ! Elastic scattering data + integer :: elastic_mode ! elastic mode (discrete/exact) + integer :: n_elastic_e_in ! # of incoming E for elastic + integer :: n_elastic_mu ! # of outgoing angles for elastic + real(8), allocatable :: elastic_e_in(:) + real(8), allocatable :: elastic_P(:) + real(8), allocatable :: elastic_mu(:,:) + contains + procedure :: print => print_sab_table + end type SAlphaBeta + + contains + +!=============================================================================== +! PRINT_SAB_TABLE displays information about a S(a,b) table containing data +! describing thermal scattering from bound materials such as hydrogen in water. +!=============================================================================== + + subroutine print_sab_table(this, unit) + class(SAlphaBeta), intent(in) :: this + integer, intent(in), optional :: unit + + integer :: size_sab ! memory used by S(a,b) table + integer :: unit_ ! unit to write to + integer :: i ! Loop counter for parsing through this % zaid + integer :: char_count ! Counter for the number of characters on a line + + ! set default unit for writing information + if (present(unit)) then + unit_ = unit + else + unit_ = OUTPUT_UNIT + end if + + ! Basic S(a,b) table information + write(unit_,*) 'S(a,b) Table ' // trim(this % name) + write(unit_,'(A)',advance="no") ' zaids = ' + ! Initialize the counter based on the above string + char_count = 11 + do i = 1, this % n_zaid + ! Deal with a line thats too long + if (char_count >= 73) then ! 73 = 80 - (5 ZAID chars + 1 space + 1 comma) + ! End the line + write(unit_,*) "" + ! Add 11 leading blanks + write(unit_,'(A)', advance="no") " " + ! reset the counter to 11 + char_count = 11 + end if + if (i < this % n_zaid) then + ! Include a comma + write(unit_,'(A)',advance="no") trim(to_str(this % zaid(i))) // ", " + char_count = char_count + len(trim(to_str(this % zaid(i)))) + 2 + else + ! Don't include a comma, since we are all done + write(unit_,'(A)',advance="no") trim(to_str(this % zaid(i))) + end if + + end do + write(unit_,*) "" ! Move to next line + write(unit_,*) ' awr = ' // trim(to_str(this % awr)) + write(unit_,*) ' kT = ' // trim(to_str(this % kT)) + + ! Inelastic data + write(unit_,*) ' # of Incoming Energies (Inelastic) = ' // & + trim(to_str(this % n_inelastic_e_in)) + write(unit_,*) ' # of Outgoing Energies (Inelastic) = ' // & + trim(to_str(this % n_inelastic_e_out)) + write(unit_,*) ' # of Outgoing Angles (Inelastic) = ' // & + trim(to_str(this % n_inelastic_mu)) + write(unit_,*) ' Threshold for Inelastic = ' // & + trim(to_str(this % threshold_inelastic)) + + ! Elastic data + if (this % n_elastic_e_in > 0) then + write(unit_,*) ' # of Incoming Energies (Elastic) = ' // & + trim(to_str(this % n_elastic_e_in)) + write(unit_,*) ' # of Outgoing Angles (Elastic) = ' // & + trim(to_str(this % n_elastic_mu)) + write(unit_,*) ' Threshold for Elastic = ' // & + trim(to_str(this % threshold_elastic)) + end if + + ! Determine memory used by S(a,b) table and write out + size_sab = 8 * (this % n_inelastic_e_in * (2 + this % n_inelastic_e_out * & + (1 + this % n_inelastic_mu)) + this % n_elastic_e_in * & + (2 + this % n_elastic_mu)) + write(unit_,*) ' Memory Used = ' // trim(to_str(size_sab)) // ' bytes' + + ! Blank line at end + write(unit_,*) + + end subroutine print_sab_table + +end module sab_header diff --git a/src/scattdata_header.F90 b/src/scattdata_header.F90 new file mode 100644 index 000000000..b04115e57 --- /dev/null +++ b/src/scattdata_header.F90 @@ -0,0 +1,489 @@ +module scattdata_header + + use constants + use error, only: fatal_error + use math + use random_lcg, only: prn + use search, only: binary_search + + implicit none + +!=============================================================================== +! SCATTDATA contains all the data to describe the scattering energy and +! angular distribution +!=============================================================================== + + type, abstract :: ScattData + ! p0 matrix on its own for sampling energy + real(8), allocatable :: energy(:,:) ! (Gout x Gin) + real(8), allocatable :: mult(:,:) ! (Gout x Gin) + real(8), allocatable :: data(:,:,:) ! (Order/Nmu x Gout x Gin) + + contains + procedure(init_), deferred :: init ! Initializes ScattData + procedure(calc_f_), deferred :: calc_f ! Calculates f, given mu + procedure(sample_), deferred :: sample ! sample the scatter event + end type ScattData + + abstract interface + subroutine init_(this, order, energy, mult, coeffs) + import ScattData + class(ScattData), intent(inout) :: this ! Object to work on + integer, intent(in) :: order ! Data Order + real(8), intent(in) :: energy(:,:) ! Energy Transfer Matrix + real(8), intent(in) :: mult(:,:) ! Scatter Prod'n Matrix + real(8), intent(in) :: coeffs(:,:,:) ! Coefficients to use + end subroutine init_ + + pure function calc_f_(this, gin, gout, mu) result(f) + import ScattData + class(ScattData), intent(in) :: this ! The ScattData to evaluate + integer, intent(in) :: gin ! Incoming Energy Group + integer, intent(in) :: gout ! Outgoing Energy Group + real(8), intent(in) :: mu ! Angle of interest + real(8) :: f ! Return value of f(mu) + + end function calc_f_ + + subroutine sample_(this, gin, gout, mu, wgt) + import ScattData + class(ScattData), intent(in) :: this ! Scattering Object to Use + integer, intent(in) :: gin ! Incoming neutron group + integer, intent(out) :: gout ! Sampled outgoin group + real(8), intent(out) :: mu ! Sampled change in angle + real(8), intent(inout) :: wgt ! Particle weight + end subroutine sample_ + end interface + + type, extends(ScattData) :: ScattDataLegendre + ! Maximal value for rejection sampling from rectangle + real(8), allocatable :: max_val(:,:) + contains + procedure :: init => scattdatalegendre_init + procedure :: calc_f => scattdatalegendre_calc_f + procedure :: sample => scattdatalegendre_sample + end type ScattDataLegendre + + type, extends(ScattData) :: ScattDataHistogram + real(8), allocatable :: mu(:) ! Mu bins + real(8) :: dmu ! Mu spacing + contains + procedure :: init => scattdatahistogram_init + procedure :: calc_f => scattdatahistogram_calc_f + procedure :: sample => scattdatahistogram_sample + end type ScattDataHistogram + + type, extends(ScattData) :: ScattDataTabular + real(8), allocatable :: mu(:) ! Mu bins + real(8) :: dmu ! Mu spacing + real(8), allocatable :: fmu(:,:,:) ! PDF of f(mu) + contains + procedure :: init => scattdatatabular_init + procedure :: calc_f => scattdatatabular_calc_f + procedure :: sample => scattdatatabular_sample + end type ScattDataTabular + +!=============================================================================== +! SCATTDATACONTAINER allocatable array for storing ScattData Objects (for angle) +!=============================================================================== + + type ScattDataContainer + class(ScattData), allocatable :: obj + end type ScattDataContainer + +contains + +!=============================================================================== +! SCATTDATA_INIT builds the scattdata object +!=============================================================================== + + subroutine scattdata_init(this, order, energy, mult) + class(ScattData), intent(inout) :: this ! Object to work on + integer, intent(in) :: order ! Data Order + real(8), intent(in) :: energy(:,:) ! Energy Transfer Matrix + real(8), intent(in) :: mult(:,:) ! Scatter Prod'n Matrix + + integer :: groups + + groups = size(energy, dim=1) + + allocate(this % energy(groups, groups)) + this % energy = energy + allocate(this % mult(groups, groups)) + this % mult = mult + allocate(this % data(order, groups, groups)) + this % data = ZERO + + end subroutine scattdata_init + + subroutine scattdatalegendre_init(this, order, energy, mult, coeffs) + class(ScattDataLegendre), intent(inout) :: this ! Object to work on + integer, intent(in) :: order ! Data Order + real(8), intent(in) :: energy(:,:) ! Energy Transfer Matrix + real(8), intent(in) :: mult(:,:) ! Scatter Prod'n Matrix + real(8), intent(in) :: coeffs(:,:,:) ! Coefficients to use + + real(8) :: dmu, mu, f + integer :: imu, Nmu, gout, gin, groups + + call scattdata_init(this, order, energy, mult) + + this % data = coeffs + + groups = size(this % energy,dim=1) + + allocate(this % max_val(groups, groups)) + this % max_val = ZERO + ! Step through the polynomial with fixed number of points to identify + ! the maximal value. + Nmu = 1001 + dmu = TWO / real(Nmu,8) + do imu = 1, Nmu + ! Update mu. Do first and last seperate to avoid float errors + if (imu == 1) then + mu = -ONE + else if (imu == Nmu) then + mu = ONE + end if + mu = -ONE + real(imu - 1,8) * dmu + do gin = 1, groups + do gout = 1, groups + ! Calculate probability + f = this % calc_f(gin,gout,mu) + ! If this is a new max, store it. + if (f > this % max_val(gout,gin)) this % max_val(gout,gin) = f + end do + end do + end do + + ! Finally, since we may not have caught the exact max, add 10% margin + this % max_val = this % max_val * 1.1_8 + + end subroutine scattdatalegendre_init + + subroutine scattdatahistogram_init(this, order, energy, mult, coeffs) + class(ScattDataHistogram), intent(inout) :: this ! Object to work on + integer, intent(in) :: order ! Data Order + real(8), intent(in) :: energy(:,:) ! Energy Transfer Matrix + real(8), intent(in) :: mult(:,:) ! Scatter Prod'n Matrix + real(8), intent(in) :: coeffs(:,:,:) ! Coefficients to use + + integer :: imu, gin, gout, groups + real(8) :: norm + + groups = size(energy,dim=1) + + call scattdata_init(this, order, energy, mult) + + allocate(this % mu(order)) + this % dmu = TWO / real(order,8) + this % mu(1) = -ONE + do imu = 2, order + this % mu(imu) = -ONE + real(imu - 1,8) * this % dmu + end do + + ! Best to integrate this histogram so we can avoid rejection sampling + do gin = 1, groups + do gout = 1, groups + if (energy(gout,gin) > ZERO) then + ! Integrate the histogram + this % data(1,gout,gin) = this % dmu * coeffs(1,gout,gin) + do imu = 2, order + this % data(imu,gout,gin) = this % dmu * coeffs(imu,gout,gin) + & + this % data(imu-1,gout,gin) + end do + ! Now make sure integral norms to zero + norm = this % data(order,gout,gin) + if (norm > ZERO) then + this % data(:,gout,gin) = this % data(:,gout,gin) / norm + end if + end if + end do + end do + + end subroutine scattdatahistogram_init + + subroutine scattdatatabular_init(this, order, energy, mult, coeffs) + class(ScattDataTabular), intent(inout) :: this ! Object to work on + integer, intent(in) :: order ! Data Order + real(8), intent(in) :: energy(:,:) ! Energy Transfer Matrix + real(8), intent(in) :: mult(:,:) ! Scatter Prod'n Matrix + real(8), intent(in) :: coeffs(:,:,:) ! Coefficients to use + + integer :: imu, gin, gout, groups + real(8) :: norm + logical :: legendre_flag + integer :: this_order + + if (order < 0) then + legendre_flag = .true. + this_order = -1 * order + else + legendre_flag = .false. + this_order = order + end if + + groups = size(energy,dim=1) + + call scattdata_init(this, this_order, energy, mult) + + allocate(this % mu(this_order)) + this % dmu = TWO / real(this_order - 1) + do imu = 1, this_order - 1 + this % mu(imu) = -ONE + real(imu - 1) * this % dmu + end do + this % mu(this_order) = ONE + + ! Best to integrate this histogram so we can avoid rejection sampling + allocate(this % fmu(this_order,groups,groups)) + do gin = 1, groups + do gout = 1, groups + if (energy(gout,gin) > ZERO) then + if (legendre_flag) then + ! Coeffs are legendre coeffs. Need to build f(mu) then integrate + ! and store the integral in this % data + ! Ensure the coeffs are normalized + norm = ONE / coeffs(1,gout,gin) + do imu = 1, this_order + this % fmu(imu,gout,gin) = evaluate_legendre(norm * coeffs(:,gout,gin), this % mu(imu)) + ! Force positivity + if (this % fmu(imu,gout,gin) < ZERO) then + this % fmu(imu,gout,gin) = ZERO + end if + end do + else + ! Coeffs contain f(mu), put in f(mu) to save duplicate. + this % fmu(:,gout,gin) = this % data(:,gout,gin) + end if + + ! Re-normalize fmu for numerical integration issues and in case + ! the negative fix-up introduced un-normalized data + norm = ZERO + do imu = 2, this_order + norm = norm + HALF * this % dmu * (this % fmu(imu-1,gout,gin) + this % fmu(imu,gout,gin)) + end do + if (norm > ZERO) then + this % fmu(:,gout,gin) = this % fmu(:,gout,gin) / norm + end if + + ! Now create CDF from fmu with trapezoidal rule + this % data(1,gout,gin) = ZERO + do imu = 2, this_order - 1 + this % data(imu,gout,gin) = this % data(imu-1,gout,gin) + & + HALF * this % dmu * (this % fmu(imu-1,gout,gin) + this % fmu(imu,gout,gin)) + end do + this % data(this_order,gout,gin) = ONE + end if + end do + end do + + end subroutine scattdatatabular_init + +!=============================================================================== +! SCATTDATA_*_CALC_F Calculates the value of f given mu (and gin,gout pair) +!=============================================================================== + + pure function scattdatalegendre_calc_f(this, gin, gout, mu) result(f) + class(ScattDataLegendre), intent(in) :: this ! The ScattData to evaluate + integer, intent(in) :: gin ! Incoming Energy Group + integer, intent(in) :: gout ! Outgoing Energy Group + real(8), intent(in) :: mu ! Angle of interest + real(8) :: f ! Return value of f(mu) + + ! Plug mu in to the legendre expansion and go from there + f = evaluate_legendre(this % data(:, gout, gin), mu) + + end function scattdatalegendre_calc_f + + pure function scattdatahistogram_calc_f(this, gin, gout, mu) result(f) + class(ScattDataHistogram), intent(in) :: this ! The ScattData to evaluate + integer, intent(in) :: gin ! Incoming Energy Group + integer, intent(in) :: gout ! Outgoing Energy Group + real(8), intent(in) :: mu ! Angle of interest + real(8) :: f ! Return value of f(mu) + + integer :: imu + + ! Find mu bin + imu = floor((mu + ONE)/ this % dmu + ONE) + ! Adjust so interpolation works on the last bin if necessary + if (imu == size(this % data, dim=1)) then + imu = imu - 1 + end if + + ! Use histogram interpolation to find f(mu) + f = this % data(imu, gout, gin) + + end function scattdatahistogram_calc_f + + pure function scattdatatabular_calc_f(this, gin, gout, mu) result(f) + class(ScattDataTabular), intent(in) :: this ! The ScattData to evaluate + integer, intent(in) :: gin ! Incoming Energy Group + integer, intent(in) :: gout ! Outgoing Energy Group + real(8), intent(in) :: mu ! Angle of interest + real(8) :: f ! Return value of f(mu) + + integer :: imu + real(8) :: r + + ! Find mu bin + imu = floor((mu + ONE)/ this % dmu + ONE) + ! Adjust so interpolation works on the last bin if necessary + if (imu == size(this % data, dim=1)) then + imu = imu - 1 + end if + + ! ! Now interpolate to find f(mu) + r = (mu - this % mu(imu)) / (this % mu(imu + 1) - this % mu(imu)) + f = (ONE - r) * this % data(imu, gout, gin) + & + r * this % data(imu + 1, gout, gin) + + end function scattdatatabular_calc_f + +!=============================================================================== +! SCATTDATA*_SCATTER Samples the outgoing energy and change in angle. +!=============================================================================== + + subroutine scattdatalegendre_sample(this, gin, gout, mu, wgt) + class(ScattDataLegendre), intent(in) :: this ! Scattering object to use + integer, intent(in) :: gin ! Incoming neutron group + integer, intent(out) :: gout ! Sampled outgoin group + real(8), intent(out) :: mu ! Sampled change in angle + real(8), intent(inout) :: wgt ! Particle weight + + real(8) :: xi ! Our random number + real(8) :: prob ! Running probability + real(8) :: u, f, M + integer :: samples + + xi = prn() + prob = ZERO + gout = 0 + + do while (prob < xi) + gout = gout + 1 + prob = prob + this % energy(gout,gin) + end do + + ! Now we can sample mu using the legendre representation of the thisering + ! kernel in data(1:this % order) + + ! Do with rejection sampling + ! Set maximal value + M = this % max_val(gout,gin) + samples = 0 + do + mu = TWO * prn() - ONE + f = this % calc_f(gin,gout,mu) + if (f > ZERO) then + u = prn() * M + if (u <= f) then + exit + end if + end if + samples = samples + 1 + if (samples > MAX_SAMPLE) then + call fatal_error("Maximum number of Legendre expansion samples reached!") + end if + end do + + wgt = wgt * this % mult(gout,gin) + + end subroutine scattdatalegendre_sample + + subroutine scattdatahistogram_sample(this, gin, gout, mu, wgt) + class(ScattDataHistogram), intent(in) :: this ! Scattering object to use + integer, intent(in) :: gin ! Incoming neutron group + integer, intent(out) :: gout ! Sampled outgoin group + real(8), intent(out) :: mu ! Sampled change in angle + real(8), intent(inout) :: wgt ! Particle weight + + real(8) :: xi ! Our random number + real(8) :: prob ! Running probability + integer :: imu + + xi = prn() + prob = ZERO + gout = 0 + + do while (prob < xi) + gout = gout + 1 + prob = prob + this % energy(gout,gin) + end do + + xi = prn() + if (xi < this % data(1,gout,gin)) then + imu = 1 + else + imu = binary_search(this % data(:,gout,gin), & + size(this % data(:,gout,gin)), xi) + end if + + ! Randomly select a mu in this bin. + mu = prn() * this % dmu + this % mu(imu) + + wgt = wgt * this % mult(gout,gin) + + end subroutine scattdatahistogram_sample + + subroutine scattdatatabular_sample(this, gin, gout, mu, wgt) + class(ScattDataTabular), intent(in) :: this ! Scattering object to use + integer, intent(in) :: gin ! Incoming neutron group + integer, intent(out) :: gout ! Sampled outgoin group + real(8), intent(out) :: mu ! Sampled change in angle + real(8), intent(inout) :: wgt ! Particle weight + + real(8) :: xi ! Our random number + real(8) :: prob ! Running probability + real(8) :: mu0, frac, mu1 + real(8) :: c_k, c_k1, p0, p1 + integer :: k, NP + + xi = prn() + prob = ZERO + gout = 0 + + do while (prob < xi) + gout = gout + 1 + prob = prob + this % energy(gout,gin) + end do + + ! determine outgoing cosine bin + NP = size(this % data(:,gout,gin)) + xi = prn() + + c_k = this % data(1,gout,gin) + do k = 1, NP - 1 + c_k1 = this % data(k+1,gout,gin) + if (xi < c_k1) exit + c_k = c_k1 + end do + + ! check to make sure k is <= NP - 1 + k = min(k, NP - 1) + + p0 = this % fmu(k,gout,gin) + mu0 = this % mu(k) + ! Linear-linear interpolation to find mu value w/in bin. + p1 = this % fmu(k+1,gout,gin) + mu1 = this % mu(k+1) + + frac = (p1 - p0)/(mu1 - mu0) + + if (frac == ZERO) then + mu = mu0 + (xi - c_k)/p0 + else + mu = mu0 + (sqrt(max(ZERO, p0*p0 + TWO*frac*(xi - c_k))) - p0)/frac + end if + + if (mu <= -ONE) then + mu = -ONE + else if (mu >= ONE) then + mu = ONE + end if + + wgt = wgt * this % mult(gout,gin) + + end subroutine scattdatatabular_sample + +end module scattdata_header \ No newline at end of file diff --git a/src/simulation.F90 b/src/simulation.F90 index cc230d645..41a28741c 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -4,26 +4,26 @@ module simulation use mpi #endif - use cmfd_execute, only: cmfd_init_batch, execute_cmfd - use constants, only: ZERO - use eigenvalue, only: count_source_for_ufs, calculate_average_keff, & - calculate_combined_keff, calculate_generation_keff, & - shannon_entropy, synchronize_bank, keff_generation + use cmfd_execute, only: cmfd_init_batch, execute_cmfd + use constants, only: ZERO + use eigenvalue, only: count_source_for_ufs, calculate_average_keff, & + calculate_combined_keff, calculate_generation_keff, & + shannon_entropy, synchronize_bank, keff_generation #ifdef _OPENMP - use eigenvalue, only: join_bank_from_threads + use eigenvalue, only: join_bank_from_threads #endif use global - use output, only: write_message, header, print_columns, & - print_batch_keff, print_generation + use output, only: write_message, header, print_columns, & + print_batch_keff, print_generation use particle_header, only: Particle - use random_lcg, only: set_particle_seed - use source, only: initialize_source - use state_point, only: write_state_point, write_source_point - use string, only: to_str - use tally, only: synchronize_tallies, setup_active_usertallies, & - reset_result - use trigger, only: check_triggers - use tracking, only: transport + use random_lcg, only: set_particle_seed + use source, only: initialize_source + use state_point, only: write_state_point, write_source_point + use string, only: to_str + use tally, only: synchronize_tallies, setup_active_usertallies, & + reset_result + use trigger, only: check_triggers + use tracking, only: transport implicit none private @@ -131,7 +131,8 @@ contains integer :: i ! set defaults - call p % initialize_from_source(source_bank(index_source)) + call p % initialize_from_source(source_bank(index_source), run_CE, & + energy_bin_avg) ! set identifier for particle p % id = work_index(rank) + index_source diff --git a/src/source.F90 b/src/source.F90 index d1bead380..ad565c95c 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -9,12 +9,13 @@ module source use geometry_header, only: BASE_UNIVERSE use global use hdf5_interface, only: file_create, file_open, file_close, read_dataset - use math, only: maxwell_spectrum, watt_spectrum use output, only: write_message use particle_header, only: Particle use random_lcg, only: prn, set_particle_seed, prn_set_stream - use state_point, only: read_source_bank, write_source_bank + use search, only: binary_search use string, only: to_str + use math + use state_point, only: read_source_bank, write_source_bank #ifdef MPI use message_passing @@ -109,7 +110,7 @@ contains integer, save :: num_resamples = 0 ! Number of resamples encountered ! Set weight to one by default - site%wgt = ONE + site % wgt = ONE ! Set the random number generator to the source stream. call prn_set_stream(STREAM_SOURCE) @@ -117,10 +118,10 @@ contains ! Sample from among multiple source distributions n_source = size(external_source) if (n_source > 1) then - r(1) = prn()*sum(external_source(:)%strength) + r(1) = prn()*sum(external_source(:) % strength) c = ZERO do i = 1, n_source - c = c + external_source(i)%strength + c = c + external_source(i) % strength if (r(1) < c) exit end do else @@ -131,14 +132,14 @@ contains found = .false. do while (.not.found) ! Set particle defaults - call p%initialize() + call p % initialize() ! Sample spatial distribution - site%xyz(:) = external_source(i)%space%sample() + site % xyz(:) = external_source(i) % space % sample() ! Fill p with needed data - p%coord(1)%xyz(:) = site%xyz - p%coord(1)%uvw(:) = [ ONE, ZERO, ZERO ] + p % coord(1) % xyz(:) = site % xyz + p % coord(1) % uvw(:) = [ ONE, ZERO, ZERO ] ! Now search to see if location exists in geometry call find_cell(p, found) @@ -151,27 +152,27 @@ contains end if ! Check if spatial site is in fissionable material - select type (space => external_source(i)%space) + select type (space => external_source(i) % space) type is (SpatialBox) - if (space%only_fissionable) then - if (p%material == MATERIAL_VOID) then + if (space % only_fissionable) then + if (p % material == MATERIAL_VOID) then found = .false. - elseif (.not. materials(p%material)%fissionable) then + elseif (.not. materials(p % material) % fissionable) then found = .false. end if end if end select end do - call p%clear() + call p % clear() ! Sample angle - site%uvw(:) = external_source(i)%angle%sample() + site % uvw(:) = external_source(i) % angle % sample() ! Check for monoenergetic source above maximum neutron energy - select type (energy => external_source(i)%energy) + select type (energy => external_source(i) % energy) type is (Discrete) - if (any(energy%x >= energy_max_neutron)) then + if (any(energy % x >= energy_max_neutron)) then call fatal_error("Source energy above range of energies of at least & &one cross section table") end if @@ -179,14 +180,26 @@ contains do ! Sample energy spectrum - site%E = external_source(i)%energy%sample() + site % E = external_source(i) % energy % sample() ! resample if energy is greater than maximum neutron energy - if (site%E < energy_max_neutron) exit + if (site % E < energy_max_neutron) exit end do ! Set delayed group - site%delayed_group = 0 + site % delayed_group = 0 + + ! If running in MG, convert site % E to group + if (.not. run_CE) then + if (site % E <= energy_bins(1)) then + site % E = real(1, 8) + else if (site % E > energy_bins(energy_groups + 1)) then + site % E = real(energy_groups, 8) + else + site % E = real(binary_search(energy_bins, energy_groups + 1, & + site % E), 8) + end if + end if ! Set the random number generator back to the tracking stream. call prn_set_stream(STREAM_TRACKING) diff --git a/src/state_point.F90 b/src/state_point.F90 index bb674e2cd..6c0e309e2 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -18,7 +18,7 @@ module state_point use global use hdf5_interface use output, only: write_message, time_stamp - use string, only: to_str, zero_padded, count_digits + use string, only: to_str, count_digits, zero_padded use tally_header, only: TallyObject use mesh_header, only: RegularMesh use dict_header, only: ElemKeyValueII, ElemKeyValueCI @@ -93,6 +93,11 @@ contains call write_dataset(file_id, "seed", seed) ! Write run information + if (run_CE) then + call write_dataset(file_id, "run_CE", 1) + else + call write_dataset(file_id, "run_CE", 0) + end if select case(run_mode) case (MODE_FIXEDSOURCE) call write_dataset(file_id, "run_mode", "fixed source") @@ -647,6 +652,7 @@ contains integer(HID_T) :: tally_group real(8) :: real_array(3) logical :: source_present + integer :: sp_run_CE character(MAX_WORD_LEN) :: word type(TallyObject), pointer :: tally @@ -674,6 +680,17 @@ contains ! Read and overwrite random number seed call read_dataset(file_id, "seed", seed) + ! It is not impossible for a state point to be generated from a CE run but + ! to be loaded in to an MG run (or vice versa), check to prevent that. + call read_dataset(file_id, "run_CE", sp_run_CE) + if (sp_run_CE == 0 .and. run_CE) then + call fatal_error("State point file is from multi-group run but & + & current run is continous-energy!") + else if (sp_run_CE == 1 .and. .not. run_CE) then + call fatal_error("State point file is from continuous-energy run but & + & current run is multi-group!") + end if + ! Read and overwrite run information except number of batches call read_dataset(file_id, "run_mode", word) select case(word) diff --git a/src/summary.F90 b/src/summary.F90 index c31068eb9..e662aa473 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -1,6 +1,6 @@ module summary - use ace_header, only: Reaction, UrrData, Nuclide + use ace_header, only: Reaction, UrrData use constants use endf, only: reaction_name use geometry_header, only: Cell, Universe, Lattice, RectLattice, & @@ -9,6 +9,7 @@ module summary use hdf5_interface use material_header, only: Material use mesh_header, only: RegularMesh + use nuclide_header use output, only: time_stamp use surface_header use string, only: to_str @@ -37,6 +38,12 @@ contains ! Write header information call write_header(file_id) + if (run_CE) then + call write_dataset(file_id, "run_CE", 1) + else + call write_dataset(file_id, "run_CE", 0) + end if + ! Write number of particles call write_dataset(file_id, "n_particles", n_particles) call write_dataset(file_id, "n_batches", n_batches) @@ -480,7 +487,11 @@ contains ! Copy ZAID for each nuclide to temporary array allocate(nucnames(m%n_nuclides)) do j = 1, m%n_nuclides - i_list = nuclides(m%nuclide(j))%listing + if (run_CE) then + i_list = nuclides(m%nuclide(j))%listing + else + i_list = nuclides_MG(m%nuclide(j))%obj%listing + end if nucnames(j) = xs_listings(i_list)%alias end do diff --git a/src/tally.F90 b/src/tally.F90 index 7210efc5c..f265bdb27 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -25,17 +25,59 @@ module tally implicit none integer :: position(N_FILTER_TYPES - 3) = 0 ! Tally map positioning array + !$omp threadprivate(position) + procedure(score_general_intfc), pointer :: score_general => null() + procedure(get_scoring_bins_intfc), pointer :: get_scoring_bins => null() + + abstract interface + subroutine score_general_intfc(p, t, start_index, filter_index, i_nuclide, & + atom_density, flux) + import Particle + import TallyObject + type(Particle), intent(in) :: p + type(TallyObject), intent(inout) :: t + integer, intent(in) :: start_index + integer, intent(in) :: i_nuclide + integer, intent(in) :: filter_index ! for % results + real(8), intent(in) :: flux ! flux estimate + real(8), intent(in) :: atom_density ! atom/b-cm + end subroutine score_general_intfc + + subroutine get_scoring_bins_intfc(p, i_tally, found_bin) + import Particle + type(Particle), intent(in) :: p + integer, intent(in) :: i_tally + logical, intent(out) :: found_bin + end subroutine get_scoring_bins_intfc + + end interface + contains !=============================================================================== -! SCORE_GENERAL adds scores to the tally array for the given filter and nuclide. -! This will work for either analog or tracklength tallies. Note that +! INIT_TALLY_ROUTINES Sets the procedure pointers needed for minimizing code +! with the CE and MG modes. +!=============================================================================== + + subroutine init_tally_routines() + if (run_CE) then + score_general => score_general_ce + get_scoring_bins => get_scoring_bins_ce + else + score_general => score_general_mg + get_scoring_bins => get_scoring_bins_mg + end if + end subroutine init_tally_routines + +!=============================================================================== +! SCORE_GENERAL* adds scores to the tally array for the given filter and +! nuclide. This will work for either analog or tracklength tallies. Note that ! atom_density and flux are not used for analog tallies. !=============================================================================== - subroutine score_general(p, t, start_index, filter_index, i_nuclide, & + subroutine score_general_ce(p, t, start_index, filter_index, i_nuclide, & atom_density, flux) type(Particle), intent(in) :: p type(TallyObject), intent(inout) :: t @@ -48,8 +90,6 @@ contains integer :: i ! loop index for scoring bins integer :: l ! loop index for nuclides in material integer :: m ! loop index for reactions - integer :: n ! loop index for legendre order - integer :: num_nm ! Number of N,M orders in harmonic integer :: q ! loop index for scoring bins integer :: i_nuc ! index in nuclides array (from material) integer :: i_energy ! index in nuclide energy grid @@ -64,7 +104,6 @@ contains real(8) :: score ! analog tally score real(8) :: macro_total ! material macro total xs real(8) :: macro_scatt ! material macro scatt xs - real(8) :: uvw(3) ! particle direction real(8) :: E ! particle energy i = 0 @@ -126,7 +165,6 @@ contains case (SCORE_INVERSE_VELOCITY) - ! make sure the correct energy is used if (t % estimator == ESTIMATOR_TRACKLENGTH) then E = p % E @@ -387,7 +425,7 @@ contains ! neutrons were emitted with different energies, multiple ! outgoing energy bins may have been scored to. The following ! logic treats this special case and results to multiple bins - call score_fission_eout(p, t, score_index) + call score_fission_eout_ce(p, t, score_index) cycle SCORE_LOOP end if end if @@ -740,106 +778,574 @@ contains end if end if + end select + + !######################################################################### + ! Expand score if necessary and add to tally results. + call expand_and_score(p, t, score_index, filter_index, score_bin, & + score, i) + + end do SCORE_LOOP + end subroutine score_general_ce + + subroutine score_general_mg(p, t, start_index, filter_index, i_nuclide, & + atom_density, flux) + type(Particle), intent(in) :: p + type(TallyObject), intent(inout) :: t + integer, intent(in) :: start_index + integer, intent(in) :: i_nuclide + integer, intent(in) :: filter_index ! for % results + real(8), intent(in) :: flux ! flux estimate + real(8), intent(in) :: atom_density ! atom/b-cm + + integer :: i ! loop index for scoring bins + integer :: q ! loop index for scoring bins + integer :: score_bin ! scoring bin, e.g. SCORE_FLUX + integer :: score_index ! scoring bin index + real(8) :: score ! analog tally score + real(8) :: macro_total ! material macro total xs + real(8) :: macro_scatt ! material macro scatt xs + real(8) :: micro_abs ! nuclidic microscopic abs + real(8) :: p_uvw(3) ! Particle's current uvw + + ! Set the direction, if needed for nuclidic data, so that nuc % get_xs + ! knows wihch direction it should be using for direction-dependent + ! mgxs + if (i_nuclide > 0) then + p_uvw = p % coord(p % n_coord) % uvw + end if + + i = 0 + SCORE_LOOP: do q = 1, t % n_user_score_bins + i = i + 1 + + ! determine what type of score bin + score_bin = t % score_bins(i) + + ! determine scoring bin index + score_index = start_index + i + + !######################################################################### + ! Determine appropirate scoring value. + + select case(score_bin) + + + case (SCORE_FLUX, SCORE_FLUX_YN) + if (t % estimator == ESTIMATOR_ANALOG) then + ! 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 (survival_biasing) then + ! We need to account for the fact that some weight was already + ! absorbed + score = p % last_wgt + p % absorb_wgt + else + score = p % last_wgt + end if + score = score / material_xs % total + + else + ! For flux, we need no cross section + score = flux + end if + + + case (SCORE_TOTAL, SCORE_TOTAL_YN) + if (t % estimator == ESTIMATOR_ANALOG) then + ! All events will score to the total reaction rate. We can just + ! use the weight of the particle entering the collision as the + ! score + if (survival_biasing) then + ! We need to account for the fact that some weight was already + ! absorbed + score = p % last_wgt + p % absorb_wgt + else + score = p % last_wgt + end if + + else + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = nuc % get_xs(p % g, 'total', UVW=p_uvw) * & + atom_density * flux + end associate + else + score = material_xs % total * flux + end if + end if + + + case (SCORE_INVERSE_VELOCITY) + if (t % estimator == ESTIMATOR_ANALOG) then + ! 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 (survival_biasing) then + ! We need to account for the fact that some weight was already + ! absorbed + score = p % last_wgt + p % absorb_wgt + else + score = p % last_wgt + end if + score = score * inverse_velocities(p % last_g) + + else + ! For inverse velocity, we need no cross section + score = score * inverse_velocities(p % g) + end if + + + case (SCORE_SCATTER, SCORE_SCATTER_N) + if (t % estimator == ESTIMATOR_ANALOG) then + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP + ! 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 % last_wgt + + else + ! Note SCORE_SCATTER_N not available for tracklength/collision. + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = nuc % get_xs(p % g, 'scatter', UVW=p_uvw) * & + atom_density * flux + end associate + else + ! Get the scattering x/s (stored in % elastic) + score = material_xs % elastic * flux + end if + end if + + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = score * nuc % get_xs(p % g, 'f_mu/mult', p % last_g, & + p % last_uvw, p % mu) + end associate + else + score = score / & + macro_xs(p % material) % obj % get_xs(p % g, 'mult', & + p % last_g, & + p % last_uvw) + end if + + + case (SCORE_SCATTER_PN) + ! Only analog estimators are available. + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) then + i = i + t % moment_order(i) + cycle SCORE_LOOP + end if + ! 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 % last_wgt + + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = score * nuc % get_xs(p % g, 'f_mu/mult', p % last_g, & + p % last_uvw, p % mu) + end associate + else + score = score / & + macro_xs(p % material) % obj % get_xs(p % g, 'mult', & + p % last_g, & + p % last_uvw) + end if + + + case (SCORE_SCATTER_YN) + ! Only analog estimators are available. + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) then + i = i + (t % moment_order(i) + 1)**2 - 1 + cycle SCORE_LOOP + end if + ! 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 % last_wgt + + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = score * nuc % get_xs(p % g, 'f_mu/mult', p % last_g, & + p % last_uvw, p % mu) + end associate + else + score = score / & + macro_xs(p % material) % obj % get_xs(p % g, 'mult', & + p % last_g, & + p % last_uvw) + end if + + + case (SCORE_NU_SCATTER, SCORE_NU_SCATTER_N) + ! Only analog estimators are available. + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP + ! 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 + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = score * nuc % get_xs(p % g, 'f_mu', p % last_g, & + p % last_uvw, p % mu) + end associate + end if + + + case (SCORE_NU_SCATTER_PN) + ! Only analog estimators are available. + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) then + i = i + t % moment_order(i) + cycle SCORE_LOOP + end if + ! 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 + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = score * nuc % get_xs(p % g, 'f_mu', p % last_g, & + p % last_uvw, p % mu) + end associate + end if + + + case (SCORE_NU_SCATTER_YN) + ! Only analog estimators are available. + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) then + i = i + (t % moment_order(i) + 1)**2 - 1 + cycle SCORE_LOOP + end if + ! 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 + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = score * nuc % get_xs(p % g, 'f_mu', p % last_g, & + p % last_uvw, p % mu) + end associate + end if + + + case (SCORE_TRANSPORT) + ! Only analog estimators are available. + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP + ! get material macros + macro_total = material_xs % total + macro_scatt = material_xs % elastic + ! Score total rate - p1 scatter rate Note estimator needs to be + ! adjusted since tallying is only occuring when a scatter has + ! happened. Effectively this means multiplying the estimator by + ! total/scatter macro + score = (macro_total - p % mu * macro_scatt) * (ONE / macro_scatt) + + + case (SCORE_N_1N) + ! Only analog estimators are available. + ! Skip any event where the particle didn't scatter + if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP + ! Skip any events where weight of particle changed + if (p % wgt /= p % last_wgt) cycle SCORE_LOOP + ! All events that reach this point are (n,1n) reactions + score = p % last_wgt + + + case (SCORE_ABSORPTION) + if (t % estimator == ESTIMATOR_ANALOG) then + if (survival_biasing) then + ! No absorption events actually occur if survival biasing is on -- + ! just use weight absorbed in survival biasing + score = p % absorb_wgt + else + ! Skip any event where the particle wasn't absorbed + if (p % event == EVENT_SCATTER) cycle SCORE_LOOP + ! All fission and absorption events will contribute here, so we + ! can just use the particle's weight entering the collision + score = p % last_wgt + end if + + else + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = nuc % get_xs(p % g, 'absorption', UVW=p_uvw) & + * atom_density * flux + end associate + else + score = material_xs % absorption * flux + end if + end if + + + case (SCORE_FISSION) + if (t % estimator == ESTIMATOR_ANALOG) then + if (survival_biasing) then + ! No fission events occur if survival biasing is on -- need to + ! calculate fraction of absorptions that would have resulted in + ! fission + associate (nuc => nuclides_MG(i_nuclide) % obj) + micro_abs = nuc % get_xs(p % g, 'absorption', UVW=p_uvw) + if (micro_abs > ZERO) then + score = p % absorb_wgt * & + nuc % get_xs(p % g, 'fission', UVW=p_uvw) & + / micro_abs + else + score = ZERO + end if + end associate + else + ! Skip any non-absorption events + if (p % event == EVENT_SCATTER) cycle SCORE_LOOP + ! All fission events will contribute, so again we can use + ! particle's weight entering the collision as the estimate for the + ! fission reaction rate + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = p % last_wgt & + * nuc % get_xs(p % g, 'fission', UVW=p_uvw) & + / nuc % get_xs(p % g, 'absorption', UVW=p_uvw) + end associate + end if + + else + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = nuc % get_xs(p % g, 'fission', UVW=p_uvw) * & + atom_density * flux + end associate + else + score = flux * macro_xs(p % material) % obj % get_xs(p % g, & + 'fission', UVW=p_uvw) + + end if + end if + + + case (SCORE_NU_FISSION) + if (t % estimator == ESTIMATOR_ANALOG) then + if (survival_biasing .or. p % fission) then + if (t % find_filter(FILTER_ENERGYOUT) > 0) then + ! Normally, we only need to make contributions to one scoring + ! bin. However, in the case of fission, since multiple fission + ! neutrons were emitted with different energies, multiple + ! outgoing energy bins may have been scored to. The following + ! logic treats this special case and results to multiple bins + call score_fission_eout_mg(p, t, score_index) + cycle SCORE_LOOP + end if + end if + if (survival_biasing) then + ! No fission events occur if survival biasing is on -- need to + ! calculate fraction of absorptions that would have resulted in + ! nu-fission + associate (nuc => nuclides_MG(i_nuclide) % obj) + micro_abs = nuc % get_xs(p % g, 'absorption', UVW=p_uvw) + if (micro_abs > ZERO) then + score = p % absorb_wgt * & + nuc % get_xs(p % g, 'fission', UVW=p_uvw) / & + micro_abs + else + score = ZERO + end if + end associate + else + ! Skip any non-fission events + if (.not. p % fission) cycle SCORE_LOOP + ! 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 = keff * p % wgt_bank + end if + + else + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = nuc % get_xs(p % g, 'nu_fission', UVW=p_uvw) & + * atom_density * flux + end associate + else + score = material_xs % nu_fission * flux + end if + end if + + + case (SCORE_KAPPA_FISSION) + ! Determine kappa-fission cross section + score = ZERO + if (t % estimator == ESTIMATOR_ANALOG) then + if (survival_biasing) then + ! No fission events occur if survival biasing is on -- need to + ! calculate fraction of absorptions that would have resulted in + ! fission scale by kappa-fission + associate (nuc => nuclides_MG(i_nuclide) % obj) + micro_abs = nuc % get_xs(p % g, 'absorption', UVW=p_uvw) + if (micro_abs > ZERO) then + score = p % absorb_wgt * & + nuc % get_xs(p % g, 'k_fission', UVW=p_uvw) / & + micro_abs + end if + end associate + else + ! Skip any non-absorption events + if (p % event == EVENT_SCATTER) cycle SCORE_LOOP + ! All fission events will contribute, so again we can use + ! particle's weight entering the collision as the estimate for + ! the fission energy production rate + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = p % last_wgt * & + nuc % get_xs(p % g, 'k_fission', UVW=p_uvw) / & + nuc % get_xs(p % g, 'absorption', UVW=p_uvw) + end associate + end if + + else + if (i_nuclide > 0) then + associate (nuc => nuclides_MG(i_nuclide) % obj) + score = nuc % get_xs(p % g, 'k_fission', UVW=p_uvw) & + * atom_density * flux + end associate + else + score = flux * macro_xs(p % material) % obj % get_xs(p % g, & + 'k_fission', UVW=p_uvw) + end if + end if + + + case (SCORE_EVENTS) + ! Simply count number of scoring events + score = ONE end select !######################################################################### ! Expand score if necessary and add to tally results. + call expand_and_score(p, t, score_index, filter_index, score_bin, & + score, i) - select case(score_bin) - - - case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - ! Find the scattering order for a singly requested moment, and - ! store its moment contribution. - if (t % moment_order(i) == 1) then - score = score * p % mu ! avoid function call overhead - else - score = score * calc_pn(t % moment_order(i), p % mu) - endif -!$omp atomic - t % results(score_index, filter_index) % value = & - t % results(score_index, filter_index) % value + score - - - case(SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN) - score_index = score_index - 1 - num_nm = 1 - ! Find the order for a collection of requested moments - ! and store the moment contribution of each - do n = 0, t % moment_order(i) - ! determine scoring bin index - score_index = score_index + num_nm - ! Update number of total n,m bins for this n (m = [-n: n]) - num_nm = 2 * n + 1 - - ! multiply score by the angular flux moments and store -!$omp critical (score_general_scatt_yn) - t % results(score_index: score_index + num_nm - 1, filter_index) & - % value = t & - % results(score_index: score_index + num_nm - 1, filter_index)& - % value & - + score * calc_pn(n, p % mu) * calc_rn(n, p % last_uvw) -!$omp end critical (score_general_scatt_yn) - end do - i = i + (t % moment_order(i) + 1)**2 - 1 - - - case(SCORE_FLUX_YN, SCORE_TOTAL_YN) - score_index = score_index - 1 - num_nm = 1 - if (t % estimator == ESTIMATOR_ANALOG .or. & - t % estimator == ESTIMATOR_COLLISION) then - uvw = p % last_uvw - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then - uvw = p % coord(1) % uvw - end if - ! Find the order for a collection of requested moments - ! and store the moment contribution of each - do n = 0, t % moment_order(i) - ! determine scoring bin index - score_index = score_index + num_nm - ! Update number of total n,m bins for this n (m = [-n: n]) - num_nm = 2 * n + 1 - - ! multiply score by the angular flux moments and store -!$omp critical (score_general_flux_tot_yn) - t % results(score_index: score_index + num_nm - 1, filter_index) & - % value = t & - % results(score_index: score_index + num_nm - 1, filter_index)& - % value & - + score * calc_rn(n, uvw) -!$omp end critical (score_general_flux_tot_yn) - end do - i = i + (t % moment_order(i) + 1)**2 - 1 - - - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - score_index = score_index - 1 - ! Find the scattering order for a collection of requested moments - ! and store the moment contribution of each - do n = 0, t % moment_order(i) - ! determine scoring bin index - score_index = score_index + 1 - - ! get the score and tally it -!$omp atomic - t % results(score_index, filter_index) % value = & - t % results(score_index, filter_index) % value & - + score * calc_pn(n, p % mu) - end do - i = i + t % moment_order(i) - - - case default -!$omp atomic - t % results(score_index, filter_index) % value = & - t % results(score_index, filter_index) % value + score - - - end select end do SCORE_LOOP - end subroutine score_general + end subroutine score_general_mg + +!=============================================================================== +! EXPAND_AND_SCORE takes a previously determined score value and adjusts it +! if necessary (for functional expansion weighting), and then adds the resultant +! value to the tally results array. +!=============================================================================== + + subroutine expand_and_score(p, t, score_index, filter_index, score_bin, & + score, i) + type(Particle), intent(in) :: p + type(TallyObject), intent(inout) :: t + integer, intent(inout) :: score_index + integer, intent(in) :: filter_index ! for % results + integer, intent(in) :: score_bin ! score of concern + real(8), intent(inout) :: score ! data to score + integer, intent(inout) :: i ! Working index + + integer :: num_nm ! Number of N,M orders in harmonic + integer :: n ! Moment loop index + real(8) :: uvw(3) + + select case(score_bin) + case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) + ! Find the scattering order for a singly requested moment, and + ! store its moment contribution. + if (t % moment_order(i) == 1) then + score = score * p % mu ! avoid function call overhead + else + score = score * calc_pn(t % moment_order(i), p % mu) + endif +!$omp atomic + t % results(score_index, filter_index) % value = & + t % results(score_index, filter_index) % value + score + + + case(SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN) + score_index = score_index - 1 + num_nm = 1 + ! Find the order for a collection of requested moments + ! and store the moment contribution of each + do n = 0, t % moment_order(i) + ! determine scoring bin index + score_index = score_index + num_nm + ! Update number of total n,m bins for this n (m = [-n: n]) + num_nm = 2 * n + 1 + + ! multiply score by the angular flux moments and store +!$omp critical (score_general_scatt_yn) + t % results(score_index: score_index + num_nm - 1, filter_index) & + % value = t & + % results(score_index: score_index + num_nm - 1, filter_index)& + % value & + + score * calc_pn(n, p % mu) * calc_rn(n, p % last_uvw) +!$omp end critical (score_general_scatt_yn) + end do + i = i + (t % moment_order(i) + 1)**2 - 1 + + + case(SCORE_FLUX_YN, SCORE_TOTAL_YN) + score_index = score_index - 1 + num_nm = 1 + if (t % estimator == ESTIMATOR_ANALOG .or. & + t % estimator == ESTIMATOR_COLLISION) then + uvw = p % last_uvw + else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + uvw = p % coord(1) % uvw + end if + ! Find the order for a collection of requested moments + ! and store the moment contribution of each + do n = 0, t % moment_order(i) + ! determine scoring bin index + score_index = score_index + num_nm + ! Update number of total n,m bins for this n (m = [-n: n]) + num_nm = 2 * n + 1 + + ! multiply score by the angular flux moments and store +!$omp critical (score_general_flux_tot_yn) + t % results(score_index: score_index + num_nm - 1, filter_index) & + % value = t & + % results(score_index: score_index + num_nm - 1, filter_index)& + % value & + + score * calc_rn(n, uvw) +!$omp end critical (score_general_flux_tot_yn) + end do + i = i + (t % moment_order(i) + 1)**2 - 1 + + + case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) + score_index = score_index - 1 + ! Find the scattering order for a collection of requested moments + ! and store the moment contribution of each + do n = 0, t % moment_order(i) + ! determine scoring bin index + score_index = score_index + 1 + + ! get the score and tally it +!$omp atomic + t % results(score_index, filter_index) % value = & + t % results(score_index, filter_index) % value & + + score * calc_pn(n, p % mu) + end do + i = i + t % moment_order(i) + + + case default +!$omp atomic + t % results(score_index, filter_index) % value = & + t % results(score_index, filter_index) % value + score + + + end select + + end subroutine expand_and_score !=============================================================================== ! SCORE_ALL_NUCLIDES tallies individual nuclide reaction rates specifically when @@ -1008,7 +1514,7 @@ contains ! neutrons produced with different energies. !=============================================================================== - subroutine score_fission_eout(p, t, i_score) + subroutine score_fission_eout_ce(p, t, i_score) type(Particle), intent(in) :: p type(TallyObject), intent(inout) :: t integer, intent(in) :: i_score ! index for score @@ -1060,7 +1566,70 @@ contains ! reset outgoing energy bin and score index matching_bins(i) = bin_energyout - end subroutine score_fission_eout + end subroutine score_fission_eout_ce + + subroutine score_fission_eout_mg(p, t, i_score) + type(Particle), intent(in) :: p + type(TallyObject), intent(inout) :: t + integer, intent(in) :: i_score ! index for score + + integer :: i ! index of outgoing energy filter + integer :: n ! number of energies on filter + integer :: k ! loop index for bank sites + integer :: bin_energyout ! original outgoing energy bin + integer :: i_filter ! index for matching filter bin combination + real(8) :: score ! actual score + integer :: gout ! energy group of fission bank site + real(8) :: E_out + + ! save original outgoing energy bin and score index + i = t % find_filter(FILTER_ENERGYOUT) + bin_energyout = matching_bins(i) + + ! Get number of energies on filter + n = size(t % filters(i) % real_bins) + + ! Since the creation of fission sites is weighted such that it is + ! expected to create n_particles sites, we need to multiply the + ! score by keff to get the true nu-fission rate. Otherwise, the sum + ! of all nu-fission rates would be ~1.0. + + ! loop over number of particles banked + do k = 1, p % n_bank + ! determine score based on bank site weight and keff + score = keff * fission_bank(n_bank - p % n_bank + k) % wgt + + if (t % energyout_matches_groups) then + ! determine outgoing energy from fission bank + gout = int(fission_bank(n_bank - p % n_bank + k) % E) + + ! change outgoing energy bin + matching_bins(i) = gout + else + ! determine outgoing energy from fission bank + E_out = fission_bank(n_bank - p % n_bank + k) % E + + ! check if outgoing energy is within specified range on filter + if (E_out < t % filters(i) % real_bins(1) .or. & + E_out > t % filters(i) % real_bins(n)) cycle + + ! change outgoing energy bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, n, E_out) + end if + + ! determine scoring index + i_filter = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 + + ! Add score to tally +!$omp atomic + t % results(i_score, i_filter) % value = & + t % results(i_score, i_filter) % value + score + end do + + ! reset outgoing energy bin and score index + matching_bins(i) = bin_energyout + + end subroutine score_fission_eout_mg !=============================================================================== ! SCORE_FISSION_DELAYED_EOUT handles a special case where we need to store @@ -1340,7 +1909,7 @@ contains real(8) :: phi type(TallyObject), pointer :: t type(RegularMesh), pointer :: m - type(Material), pointer :: mat + type(Material), pointer :: mat t => tallies(i_tally) matching_bins(1:t%n_filters) = 1 @@ -1702,7 +2271,7 @@ contains ! for a tally based on the particle's current attributes. !=============================================================================== - subroutine get_scoring_bins(p, i_tally, found_bin) + subroutine get_scoring_bins_ce(p, i_tally, found_bin) type(Particle), intent(in) :: p integer, intent(in) :: i_tally @@ -1908,7 +2477,223 @@ contains end do FILTER_LOOP - end subroutine get_scoring_bins + end subroutine get_scoring_bins_ce + + subroutine get_scoring_bins_mg(p, i_tally, found_bin) + + type(Particle), intent(in) :: p + integer, intent(in) :: i_tally + logical, intent(out) :: found_bin + + integer :: i ! loop index for filters + integer :: j + integer :: n ! number of bins for single filter + integer :: distribcell_index ! index in distribcell arrays + integer :: offset ! offset for distribcell + real(8) :: theta, phi ! Polar and Azimuthal Angles, respectively + real(8) :: E + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m + + found_bin = .true. + t => tallies(i_tally) + matching_bins(1:t%n_filters) = 1 + + FILTER_LOOP: do i = 1, t % n_filters + + select case (t % filters(i) % type) + case (FILTER_MESH) + ! determine mesh bin + m => meshes(t % filters(i) % int_bins(1)) + + ! Determine if we're in the mesh first + call get_mesh_bin(m, p % coord(1) % xyz, matching_bins(i)) + + case (FILTER_UNIVERSE) + ! determine next universe bin + ! TODO: Account for multiple universes when performing this filter + matching_bins(i) = get_next_bin(FILTER_UNIVERSE, & + p % coord(p % n_coord) % universe, i_tally) + + case (FILTER_MATERIAL) + if (p % material == MATERIAL_VOID) then + matching_bins(i) = NO_BIN_FOUND + else + matching_bins(i) = get_next_bin(FILTER_MATERIAL, & + p % material, i_tally) + endif + + case (FILTER_CELL) + ! determine next cell bin + do j = 1, p % n_coord + position(FILTER_CELL) = 0 + matching_bins(i) = get_next_bin(FILTER_CELL, & + p % coord(j) % cell, i_tally) + if (matching_bins(i) /= NO_BIN_FOUND) exit + end do + + case (FILTER_DISTRIBCELL) + ! determine next distribcell bin + distribcell_index = cells(t % filters(i) % int_bins(1)) & + % distribcell_index + matching_bins(i) = NO_BIN_FOUND + offset = 0 + do j = 1, p % n_coord + if (cells(p % coord(j) % cell) % type == CELL_FILL) then + offset = offset + cells(p % coord(j) % cell) % & + offset(distribcell_index) + elseif(cells(p % coord(j) % cell) % type == CELL_LATTICE) then + if (lattices(p % coord(j + 1) % lattice) % obj & + % are_valid_indices([& + p % coord(j + 1) % lattice_x, & + p % coord(j + 1) % lattice_y, & + p % coord(j + 1) % lattice_z])) then + offset = offset + lattices(p % coord(j + 1) % lattice) % obj % & + offset(distribcell_index, & + p % coord(j + 1) % lattice_x, & + p % coord(j + 1) % lattice_y, & + p % coord(j + 1) % lattice_z) + end if + end if + if (t % filters(i) % int_bins(1) == p % coord(j) % cell) then + matching_bins(i) = offset + 1 + exit + end if + end do + + case (FILTER_CELLBORN) + ! determine next cellborn bin + matching_bins(i) = get_next_bin(FILTER_CELLBORN, & + p % cell_born, i_tally) + + case (FILTER_SURFACE) + ! determine next surface bin + matching_bins(i) = get_next_bin(FILTER_SURFACE, & + p % surface, i_tally) + + case (FILTER_ENERGYIN) + if (t % energy_matches_groups) then + ! make sure the correct energy group is used + ! Since all groups are filters, the filter bin is the group + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + matching_bins(i) = p % g + else + matching_bins(i) = p % last_g + end if + ! Tallies are ordered in increasing groups, group indices + ! however are the opposite, so switch + matching_bins(i) = energy_groups - matching_bins(i) + 1 + else + ! make sure the correct energy is used + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + E = p % E + else + E = p % last_E + end if + n = t % filters(i) % n_bins + + ! check if energy of the particle is within energy bins + if (E < t % filters(i) % real_bins(1) .or. & + E > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find incoming energy bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, E) + end if + end if + + + case (FILTER_ENERGYOUT) + if (t % energyout_matches_groups) then + ! Since all groups are filters, the filter bin is the group + matching_bins(i) = p % g + + ! Tallies are ordered in increasing groups, group indices + ! however are the opposite, so switch + matching_bins(i) = energy_groups - matching_bins(i) + 1 + else + ! determine outgoing energy bin + n = t % filters(i) % n_bins + + ! check if energy of the particle is within energy bins + if (p % E < t % filters(i) % real_bins(1) .or. & + p % E > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find incoming energy bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, p % E) + end if + end if + + + case (FILTER_MU) + ! determine mu bin + n = t % filters(i) % n_bins + + ! check if particle is within mu bins + if (p % mu < t % filters(i) % real_bins(1) .or. & + p % mu > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find mu bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, p % mu) + end if + + case (FILTER_POLAR) + ! make sure the correct direction vector is used + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + theta = acos(p % coord(1) % uvw(3)) + else + theta = acos(p % last_uvw(3)) + end if + + ! determine polar angle bin + n = t % filters(i) % n_bins + + ! check if particle is within polar angle bins + if (theta < t % filters(i) % real_bins(1) .or. & + theta > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find polar angle bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, theta) + end if + + case (FILTER_AZIMUTHAL) + ! make sure the correct direction vector is used + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + phi = atan2(p % coord(1) % uvw(2), p % coord(1) % uvw(1)) + else + phi = atan2(p % last_uvw(2), p % last_uvw(1)) + end if + ! determine mu bin + n = t % filters(i) % n_bins + + ! check if particle is within azimuthal angle bins + if (phi < t % filters(i) % real_bins(1) .or. & + phi > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find azimuthal angle bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, phi) + end if + + end select + + ! If the current filter didn't match, exit this subroutine + if (matching_bins(i) == NO_BIN_FOUND) then + found_bin = .false. + return + end if + + end do FILTER_LOOP + + end subroutine get_scoring_bins_mg !=============================================================================== ! SCORE_SURFACE_CURRENT tallies surface crossings in a mesh tally by manually diff --git a/src/tally_header.F90 b/src/tally_header.F90 index dcbba3d89..8db9ab0e1 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -124,6 +124,10 @@ module tally_header ! Tally precision triggers integer :: n_triggers = 0 ! # of triggers type(TriggerObject), allocatable :: triggers(:) ! Array of triggers + + ! Multi-Group Specific Information To Enable Rapid Tallying + logical :: energy_matches_groups = .false. + logical :: energyout_matches_groups = .false. end type TallyObject end module tally_header diff --git a/src/track_output.F90 b/src/track_output.F90 index 1665ac25e..141173862 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -7,8 +7,8 @@ module track_output use global use hdf5_interface - use particle_header, only: Particle - use string, only: to_str + use particle_header, only: Particle + use string, only: to_str use hdf5 diff --git a/src/tracking.F90 b/src/tracking.F90 index 7cc761055..e634112bc 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -1,21 +1,23 @@ module tracking - use constants, only: MODE_EIGENVALUE - use cross_section, only: calculate_xs - use error, only: fatal_error, warning - use geometry, only: find_cell, distance_to_boundary, cross_surface, & - cross_lattice, check_cell_overlap - use geometry_header, only: Universe, BASE_UNIVERSE + use constants, only: MODE_EIGENVALUE + use cross_section, only: calculate_xs + use error, only: fatal_error, warning + use geometry, only: find_cell, distance_to_boundary, cross_surface, & + cross_lattice, check_cell_overlap + use geometry_header, only: Universe, BASE_UNIVERSE use global - use output, only: write_message - use particle_header, only: LocalCoord, Particle - use physics, only: collision - use random_lcg, only: prn - use string, only: to_str - use tally, only: score_analog_tally, score_tracklength_tally, & - score_collision_tally, score_surface_current - use track_output, only: initialize_particle_track, write_particle_track, & - add_particle_track, finalize_particle_track + use macroxs_header, only: MacroXS + use output, only: write_message + use particle_header, only: LocalCoord, Particle + use physics, only: collision + use physics_mg, only: collision_mg + use random_lcg, only: prn + use string, only: to_str + use tally, only: score_analog_tally, score_tracklength_tally, & + score_collision_tally, score_surface_current + use track_output, only: initialize_particle_track, write_particle_track, & + add_particle_track, finalize_particle_track implicit none @@ -53,7 +55,9 @@ contains total_weight = total_weight + p % wgt ! Force calculation of cross-sections by setting last energy to zero - micro_xs % last_E = ZERO + if (run_CE) then + micro_xs % last_E = ZERO + end if ! Prepare to write out particle track. if (p % write_track) then @@ -79,11 +83,24 @@ contains if (check_overlaps) call check_cell_overlap(p) - ! Calculate microscopic and macroscopic cross sections -- note: if the - ! material is the same as the last material and the energy of the - ! particle hasn't changed, we don't need to lookup cross sections again. - - if (p % material /= p % last_material) call calculate_xs(p) + ! Calculate microscopic and macroscopic cross sections + if (run_CE) then + ! If the material is the same as the last material and the energy of the + ! particle hasn't changed, we don't need to lookup cross sections again. + if (p % material /= p % last_material) call calculate_xs(p) + else + ! Since the MGXS can be angle dependent, this needs to be done + ! After every collision for the MGXS mode + if (p % material /= MATERIAL_VOID) then + call macro_xs(p % material) % obj % calculate_xs(p % g, & + p % coord(p % n_coord) % uvw, material_xs) + else + material_xs % total = ZERO + material_xs % elastic = ZERO + material_xs % absorption = ZERO + material_xs % nu_fission = ZERO + end if + end if ! Find the distance to the nearest boundary call distance_to_boundary(p, d_boundary, surface_crossed, & @@ -105,8 +122,10 @@ contains end do ! Score track-length tallies - if (active_tracklength_tallies % size() > 0) & - call score_tracklength_tally(p, distance) + if (active_tracklength_tallies % size() > 0) then + call score_tracklength_tally(p, distance) + end if + ! Score track-length estimate of k-eff if (run_mode == MODE_EIGENVALUE) then @@ -151,12 +170,15 @@ contains ! Clear surface component p % surface = NONE - call collision(p) + if (run_CE) then + call collision(p) + else + call collision_mg(p) + end if ! Score collision estimator tallies -- this is done after a collision ! has occurred rather than before because we need information on the ! outgoing energy for any tallies with an outgoing energy filter - if (active_collision_tallies % size() > 0) call score_collision_tally(p) if (active_analog_tallies % size() > 0) call score_analog_tally(p) @@ -200,7 +222,8 @@ contains ! Check for secondary particles if this particle is dead if (.not. p % alive) then if (p % n_secondary > 0) then - call p % initialize_from_source(p % secondary_bank(p % n_secondary)) + call p % initialize_from_source(p % secondary_bank(p % n_secondary), & + run_CE, energy_bin_avg) p % n_secondary = p % n_secondary - 1 n_event = 0 diff --git a/src/trigger.F90 b/src/trigger.F90 index 73cb0c7ef..ed362154b 100644 --- a/src/trigger.F90 +++ b/src/trigger.F90 @@ -6,12 +6,12 @@ module trigger use constants use global - use string, only: to_str - use output, only: warning, write_message - use mesh, only: mesh_indices_to_bin - use mesh_header, only: RegularMesh - use trigger_header, only: TriggerObject - use tally, only: TallyObject + use string, only: to_str + use output, only: warning, write_message + use mesh, only: mesh_indices_to_bin + use mesh_header, only: RegularMesh + use trigger_header, only: TriggerObject + use tally, only: TallyObject implicit none diff --git a/tests/1d_mgxs.xml b/tests/1d_mgxs.xml new file mode 100644 index 000000000..33b20464b --- /dev/null +++ b/tests/1d_mgxs.xml @@ -0,0 +1,9859 @@ + + + 1 + 0.0000000E+00 2.0000000E+01 + + + uo2_iso.71c + uo2_iso.71c + 2.5300000E-08 + 5 + true + isotropic + + 4.1022364E-01 + + + 3.4687432E-02 + + + 4.9631431E-02 + + + 1.0000000E+00 + + + 2.0019027E-02 + + + 3.7564339E-01 + + 4.4983802E-02 + + 2.2781624E-02 + + 1.1639469E-02 + + 7.1975833E-03 + + 3.5887673E-03 + + + 1.0002764E+00 + + + + + clad_iso.71c + clad_iso.71c + 2.5300000E-08 + 5 + false + isotropic + + 3.0736836E-01 + + + 1.7027907E-03 + + + 3.0566993E-01 + + 4.1625057E-02 + + 2.2287832E-02 + + 3.9580806E-03 + + 3.3420849E-03 + + 1.3963828E-03 + + + 1.0000372E+00 + + + + + lwtr_iso.71c + lwtr_iso.71c + 2.5300000E-08 + 5 + false + isotropic + + 9.6904862E-01 + + + 1.0230968E-02 + + + 9.5881780E-01 + + 3.9202760E-01 + + 1.2865356E-01 + + 9.5231115E-03 + + -1.9647208E-02 + + 5.9291968E-04 + + + 1.0000000E+00 + + + + + uo2_iso_mu.71c + uo2_iso_mu.71c + 2.5300000E-08 + 32 + true + isotropic + histogram + + 4.1022364E-01 + + + 3.4687432E-02 + + + 4.9631431E-02 + + + 1.0000000E+00 + + + 2.0019027E-02 + + + 9.7621928E-03 + + 9.6669975E-03 + + 9.6217012E-03 + + 9.6029285E-03 + + 9.6155223E-03 + + 9.6417022E-03 + + 9.6845888E-03 + + 9.7355785E-03 + + 9.7971852E-03 + + 9.8708684E-03 + + 9.9451996E-03 + + 1.0026273E-02 + + 1.0121536E-02 + + 1.0227606E-02 + + 1.0340467E-02 + + 1.0461281E-02 + + 1.0600371E-02 + + 1.0742182E-02 + + 1.0892295E-02 + + 1.1062409E-02 + + 1.1236639E-02 + + 1.1440302E-02 + + 1.1662283E-02 + + 1.1931512E-02 + + 1.2259589E-02 + + 1.2696194E-02 + + 1.3272953E-02 + + 1.4078939E-02 + + 1.5238289E-02 + + 1.6956791E-02 + + 1.9602217E-02 + + 2.3848802E-02 + + + 1.0002764E+00 + + + + + clad_iso_mu.71c + clad_iso_mu.71c + 2.5300000E-08 + 32 + false + isotropic + histogram + + 3.0736836E-01 + + + 1.7027907E-03 + + + 8.7275040E-03 + + 8.3252599E-03 + + 8.0120655E-03 + + 7.7711039E-03 + + 7.5947251E-03 + + 7.4705350E-03 + + 7.3804037E-03 + + 7.3241515E-03 + + 7.3010244E-03 + + 7.3107188E-03 + + 7.3487081E-03 + + 7.4144814E-03 + + 7.5104992E-03 + + 7.6438156E-03 + + 7.7974114E-03 + + 7.9812213E-03 + + 8.1816102E-03 + + 8.4284406E-03 + + 8.6892059E-03 + + 8.9675370E-03 + + 9.2626673E-03 + + 9.6121293E-03 + + 9.9669464E-03 + + 1.0354054E-02 + + 1.0794903E-02 + + 1.1296566E-02 + + 1.1883978E-02 + + 1.2592532E-02 + + 1.3494682E-02 + + 1.4666635E-02 + + 1.6229823E-02 + + 1.8334594E-02 + + + 1.0000372E+00 + + + + + lwtr_iso_mu.71c + lwtr_iso_mu.71c + 2.5300000E-08 + 32 + false + isotropic + histogram + + 9.6904862E-01 + + + 1.0230968E-02 + + + 5.8755233E-03 + + 1.0934725E-02 + + 1.1142414E-02 + + 1.0437139E-02 + + 1.0756915E-02 + + 1.0623054E-02 + + 1.1295335E-02 + + 1.1326212E-02 + + 1.1795885E-02 + + 1.2179916E-02 + + 1.2528003E-02 + + 1.3121696E-02 + + 1.3563685E-02 + + 1.4242846E-02 + + 1.4567732E-02 + + 1.5913317E-02 + + 1.6851680E-02 + + 2.0792196E-02 + + 2.4129531E-02 + + 2.8258248E-02 + + 3.2040957E-02 + + 3.6266761E-02 + + 4.0455247E-02 + + 4.4731350E-02 + + 4.8820583E-02 + + 5.3746086E-02 + + 5.7743648E-02 + + 6.3513540E-02 + + 6.7353451E-02 + + 7.2430683E-02 + + 8.0723820E-02 + + 8.0655621E-02 + + + 1.0000000E+00 + + + + + uo2_ang.71c + uo2_ang.71c + 2.5300000E-08 + 5 + true + 32 + 1 + angle + + 4.0734790E-01 + + 4.0709470E-01 + + 4.0665280E-01 + + 4.0605122E-01 + + 4.0509226E-01 + + 4.0399893E-01 + + 4.0264927E-01 + + 4.0112684E-01 + + 3.9937450E-01 + + 3.9743081E-01 + + 3.9533879E-01 + + 3.9307550E-01 + + 3.9084961E-01 + + 3.8878017E-01 + + 3.8751931E-01 + + 3.8693825E-01 + + 3.9039929E-01 + + 4.0037023E-01 + + 4.1057791E-01 + + 4.1924835E-01 + + 4.2629128E-01 + + 4.3202621E-01 + + 4.3673213E-01 + + 4.4062993E-01 + + 4.4385222E-01 + + 4.4647166E-01 + + 4.4861335E-01 + + 4.5026817E-01 + + 4.5165329E-01 + + 4.5255720E-01 + + 4.5310208E-01 + + 4.5337269E-01 + + + 3.1599020E-02 + + 3.1371085E-02 + + 3.1023091E-02 + + 3.0539250E-02 + + 2.9839460E-02 + + 2.9013479E-02 + + 2.8058288E-02 + + 2.7047229E-02 + + 2.5977776E-02 + + 2.4952391E-02 + + 2.4009896E-02 + + 2.3244570E-02 + + 2.2725200E-02 + + 2.2489873E-02 + + 2.2624168E-02 + + 2.3059735E-02 + + 2.4782557E-02 + + 2.8553081E-02 + + 3.3194318E-02 + + 3.8038660E-02 + + 4.2666012E-02 + + 4.6923885E-02 + + 5.0708283E-02 + + 5.3996846E-02 + + 5.6845491E-02 + + 5.9213445E-02 + + 6.1182604E-02 + + 6.2742563E-02 + + 6.3985293E-02 + + 6.4852148E-02 + + 6.5364227E-02 + + 6.5703785E-02 + + + 4.5146530E-02 + + 4.4766687E-02 + + 4.4155441E-02 + + 4.3323960E-02 + + 4.2141314E-02 + + 4.0739637E-02 + + 3.9143652E-02 + + 3.7465300E-02 + + 3.5735871E-02 + + 3.4113931E-02 + + 3.2678644E-02 + + 3.1591060E-02 + + 3.0966537E-02 + + 3.0821062E-02 + + 3.1238242E-02 + + 3.2075654E-02 + + 3.4603728E-02 + + 3.9898114E-02 + + 4.6725370E-02 + + 5.4142159E-02 + + 6.1436273E-02 + + 6.8238302E-02 + + 7.4365771E-02 + + 7.9727018E-02 + + 8.4398863E-02 + + 8.8315890E-02 + + 9.1574736E-02 + + 9.4183896E-02 + + 9.6266615E-02 + + 9.7706019E-02 + + 9.8564505E-02 + + 9.9171965E-02 + + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + + 1.8183034E-02 + + 1.8028751E-02 + + 1.7777081E-02 + + 1.7434939E-02 + + 1.6947918E-02 + + 1.6371445E-02 + + 1.5714505E-02 + + 1.5023310E-02 + + 1.4310527E-02 + + 1.3640363E-02 + + 1.3045308E-02 + + 1.2590537E-02 + + 1.2323486E-02 + + 1.2250235E-02 + + 1.2408325E-02 + + 1.2741816E-02 + + 1.3791905E-02 + + 1.6011218E-02 + + 1.8846275E-02 + + 2.1907807E-02 + + 2.4909120E-02 + + 2.7704245E-02 + + 3.0220623E-02 + + 3.2422114E-02 + + 3.4339614E-02 + + 3.5947934E-02 + + 3.7286018E-02 + + 3.8357139E-02 + + 3.9212858E-02 + + 3.9804080E-02 + + 4.0156625E-02 + + 4.0404918E-02 + + + 3.7585902E-01 + + 4.4872720E-02 + + 2.2814276E-02 + + 1.1556342E-02 + + 7.2018303E-03 + + 3.6175403E-03 + + + + 3.7582315E-01 + + 4.4995749E-02 + + 2.2725116E-02 + + 1.1466478E-02 + + 7.0875483E-03 + + 3.5308164E-03 + + + + 3.7572011E-01 + + 4.4992452E-02 + + 2.2759820E-02 + + 1.1516099E-02 + + 7.0323440E-03 + + 3.5020003E-03 + + + + 3.7562995E-01 + + 4.5132914E-02 + + 2.2777514E-02 + + 1.1548988E-02 + + 7.0831467E-03 + + 3.5299129E-03 + + + + 3.7536612E-01 + + 4.5293164E-02 + + 2.2890080E-02 + + 1.1675089E-02 + + 7.1438522E-03 + + 3.5771809E-03 + + + + 3.7510372E-01 + + 4.5594244E-02 + + 2.2986083E-02 + + 1.1616892E-02 + + 7.1593645E-03 + + 3.5827527E-03 + + + + 3.7471139E-01 + + 4.5893399E-02 + + 2.3129097E-02 + + 1.1710573E-02 + + 7.2294990E-03 + + 3.6035030E-03 + + + + 3.7417853E-01 + + 4.6212271E-02 + + 2.3407493E-02 + + 1.1803607E-02 + + 7.2768873E-03 + + 3.6185275E-03 + + + + 3.7350485E-01 + + 4.6653124E-02 + + 2.3603271E-02 + + 1.1928427E-02 + + 7.3368483E-03 + + 3.6311780E-03 + + + + 3.7257204E-01 + + 4.7127424E-02 + + 2.3927026E-02 + + 1.2138279E-02 + + 7.4376541E-03 + + 3.6855451E-03 + + + + 3.7144563E-01 + + 4.7675499E-02 + + 2.4252831E-02 + + 1.2320100E-02 + + 7.5749097E-03 + + 3.7669728E-03 + + + + 3.6996977E-01 + + 4.8300830E-02 + + 2.4647138E-02 + + 1.2560662E-02 + + 7.7886594E-03 + + 3.8654464E-03 + + + + 3.6821602E-01 + + 4.8824396E-02 + + 2.5017750E-02 + + 1.2840163E-02 + + 7.9274823E-03 + + 3.9779025E-03 + + + + 3.6638016E-01 + + 4.9306135E-02 + + 2.5474307E-02 + + 1.3192593E-02 + + 8.2112330E-03 + + 4.1160831E-03 + + + + 3.6503713E-01 + + 4.9560796E-02 + + 2.5756337E-02 + + 1.3455138E-02 + + 8.3858370E-03 + + 4.2114689E-03 + + + + 3.6400368E-01 + + 4.9633132E-02 + + 2.5987536E-02 + + 1.3659891E-02 + + 8.5714354E-03 + + 4.3181256E-03 + + + + 3.6576117E-01 + + 4.8863049E-02 + + 2.5525363E-02 + + 1.3370670E-02 + + 8.3567729E-03 + + 4.1905625E-03 + + + + 3.7192172E-01 + + 4.6844936E-02 + + 2.3959446E-02 + + 1.2270393E-02 + + 7.5751281E-03 + + 3.7309644E-03 + + + + 3.7748124E-01 + + 4.4748629E-02 + + 2.2514789E-02 + + 1.1348962E-02 + + 6.9297472E-03 + + 3.4104693E-03 + + + + 3.8128097E-01 + + 4.3075850E-02 + + 2.1398961E-02 + + 1.0675116E-02 + + 6.5306660E-03 + + 3.2210938E-03 + + + + 3.8373406E-01 + + 4.1672472E-02 + + 2.0547117E-02 + + 1.0330913E-02 + + 6.3048028E-03 + + 3.1386749E-03 + + + + 3.8520439E-01 + + 4.0681902E-02 + + 2.0057126E-02 + + 1.0056063E-02 + + 6.1829817E-03 + + 3.0802737E-03 + + + + 3.8614505E-01 + + 3.9879282E-02 + + 1.9626439E-02 + + 9.9375963E-03 + + 6.1229946E-03 + + 3.0426688E-03 + + + + 3.8675390E-01 + + 3.9278504E-02 + + 1.9339777E-02 + + 9.8184985E-03 + + 6.0956157E-03 + + 3.0580002E-03 + + + + 3.8705360E-01 + + 3.8883125E-02 + + 1.9159064E-02 + + 9.7301477E-03 + + 6.0595588E-03 + + 3.0225068E-03 + + + + 3.8731880E-01 + + 3.8576519E-02 + + 1.9045072E-02 + + 9.7127863E-03 + + 6.0463869E-03 + + 3.0519472E-03 + + + + 3.8756725E-01 + + 3.8382695E-02 + + 1.8916082E-02 + + 9.6925622E-03 + + 6.0590015E-03 + + 2.9913798E-03 + + + + 3.8761982E-01 + + 3.8249486E-02 + + 1.8841512E-02 + + 9.6699646E-03 + + 6.0488356E-03 + + 3.0212480E-03 + + + + 3.8779017E-01 + + 3.8052198E-02 + + 1.8815974E-02 + + 9.5833623E-03 + + 5.9965640E-03 + + 2.9751261E-03 + + + + 3.8780028E-01 + + 3.7931450E-02 + + 1.8735581E-02 + + 9.6072395E-03 + + 5.9416328E-03 + + 3.0080955E-03 + + + + 3.8782277E-01 + + 3.7963999E-02 + + 1.8776116E-02 + + 9.6491264E-03 + + 5.9087373E-03 + + 3.0066367E-03 + + + + 3.8767898E-01 + + 3.7876954E-02 + + 1.8837344E-02 + + 9.7088929E-03 + + 5.9136976E-03 + + 3.0171235E-03 + + + 1.0002763E+00 + + + 1.0002760E+00 + + + 1.0002658E+00 + + + 1.0002710E+00 + + + 1.0002776E+00 + + + 1.0002767E+00 + + + 1.0002833E+00 + + + 1.0002791E+00 + + + 1.0002788E+00 + + + 1.0002858E+00 + + + 1.0002884E+00 + + + 1.0002916E+00 + + + 1.0003039E+00 + + + 1.0003181E+00 + + + 1.0003365E+00 + + + 1.0003544E+00 + + + 1.0003372E+00 + + + 1.0002764E+00 + + + 1.0002508E+00 + + + 1.0002343E+00 + + + 1.0002360E+00 + + + 1.0002375E+00 + + + 1.0002331E+00 + + + 1.0002344E+00 + + + 1.0002385E+00 + + + 1.0002316E+00 + + + 1.0002360E+00 + + + 1.0002360E+00 + + + 1.0002354E+00 + + + 1.0002349E+00 + + + 1.0002325E+00 + + + 1.0002268E+00 + + + + + clad_ang.71c + clad_ang.71c + 2.5300000E-08 + 5 + false + 32 + 1 + angle + + 3.1005638E-01 + + 3.0999067E-01 + + 3.0994879E-01 + + 3.0987779E-01 + + 3.0961631E-01 + + 3.0948272E-01 + + 3.0913340E-01 + + 3.0868239E-01 + + 3.0799925E-01 + + 3.0712597E-01 + + 3.0590948E-01 + + 3.0432728E-01 + + 3.0235012E-01 + + 2.9996873E-01 + + 2.9743091E-01 + + 2.9739624E-01 + + 3.0835788E-01 + + 3.1305337E-01 + + 3.1379599E-01 + + 3.1314506E-01 + + 3.1216249E-01 + + 3.1129786E-01 + + 3.1059203E-01 + + 3.1009561E-01 + + 3.0977837E-01 + + 3.0951041E-01 + + 3.0930940E-01 + + 3.0929712E-01 + + 3.0925741E-01 + + 3.0917641E-01 + + 3.0919741E-01 + + 3.0912502E-01 + + + 1.3490691E-03 + + 1.3463259E-03 + + 1.3498512E-03 + + 1.3366347E-03 + + 1.3288899E-03 + + 1.3176269E-03 + + 1.3059971E-03 + + 1.2891508E-03 + + 1.2713136E-03 + + 1.2555332E-03 + + 1.2394055E-03 + + 1.2170158E-03 + + 1.1969201E-03 + + 1.1849620E-03 + + 1.1899173E-03 + + 1.2761137E-03 + + 1.6244505E-03 + + 1.9090551E-03 + + 2.0837409E-03 + + 2.1976011E-03 + + 2.2746911E-03 + + 2.3308251E-03 + + 2.3700744E-03 + + 2.3981231E-03 + + 2.4248079E-03 + + 2.4441792E-03 + + 2.4510541E-03 + + 2.4640212E-03 + + 2.4741885E-03 + + 2.4697219E-03 + + 2.4721421E-03 + + 2.4729172E-03 + + + 3.0860746E-01 + + 5.0621457E-02 + + 2.7347709E-02 + + 4.7204795E-03 + + 4.0838896E-03 + + 1.6974585E-03 + + + + 3.0865194E-01 + + 5.0806752E-02 + + 2.6916586E-02 + + 4.8439138E-03 + + 4.1728626E-03 + + 1.7130886E-03 + + + + 3.0861586E-01 + + 5.0757624E-02 + + 2.7196188E-02 + + 4.8679553E-03 + + 4.0626181E-03 + + 1.7815988E-03 + + + + 3.0850283E-01 + + 5.0925397E-02 + + 2.7204505E-02 + + 4.8109149E-03 + + 4.1177685E-03 + + 1.7500469E-03 + + + + 3.0831737E-01 + + 5.1138142E-02 + + 2.7308021E-02 + + 4.8683307E-03 + + 4.0620680E-03 + + 1.6728150E-03 + + + + 3.0815133E-01 + + 5.1220538E-02 + + 2.7286345E-02 + + 4.8715905E-03 + + 4.0963982E-03 + + 1.6783881E-03 + + + + 3.0777979E-01 + + 5.1536936E-02 + + 2.7522750E-02 + + 4.9751865E-03 + + 4.1461347E-03 + + 1.7481718E-03 + + + + 3.0740186E-01 + + 5.1745014E-02 + + 2.7548398E-02 + + 4.9705992E-03 + + 4.2128374E-03 + + 1.7852471E-03 + + + + 3.0674467E-01 + + 5.2102012E-02 + + 2.7721735E-02 + + 4.9326171E-03 + + 4.2065723E-03 + + 1.7520577E-03 + + + + 3.0588587E-01 + + 5.2410298E-02 + + 2.7935183E-02 + + 5.1068594E-03 + + 4.2771962E-03 + + 1.7875734E-03 + + + + 3.0465659E-01 + + 5.2543078E-02 + + 2.7962434E-02 + + 5.0839680E-03 + + 4.3050048E-03 + + 1.8499733E-03 + + + + 3.0312229E-01 + + 5.2483292E-02 + + 2.8137041E-02 + + 5.2734764E-03 + + 4.4574974E-03 + + 1.8578935E-03 + + + + 3.0117092E-01 + + 5.2332000E-02 + + 2.8003257E-02 + + 5.2432554E-03 + + 4.5485878E-03 + + 1.8980534E-03 + + + + 2.9880209E-01 + + 5.1679340E-02 + + 2.7750518E-02 + + 5.3056401E-03 + + 4.5878997E-03 + + 1.9401945E-03 + + + + 2.9627667E-01 + + 5.0169523E-02 + + 2.7059202E-02 + + 5.2026216E-03 + + 4.5921641E-03 + + 1.8856744E-03 + + + + 2.9609986E-01 + + 4.6032461E-02 + + 2.4630572E-02 + + 4.5841577E-03 + + 3.9297754E-03 + + 1.6420383E-03 + + + + 3.0675667E-01 + + 3.7400062E-02 + + 1.9426565E-02 + + 2.7294131E-03 + + 2.0654845E-03 + + 6.7157182E-04 + + + + 3.1112942E-01 + + 3.2514340E-02 + + 1.7042298E-02 + + 2.2975512E-03 + + 1.7171252E-03 + + 6.1586296E-04 + + + + 3.1168284E-01 + + 2.9994361E-02 + + 1.5982971E-02 + + 2.2082409E-03 + + 1.7621544E-03 + + 6.7848731E-04 + + + + 3.1094402E-01 + + 2.9043011E-02 + + 1.5559822E-02 + + 2.3867453E-03 + + 1.8805422E-03 + + 8.0257257E-04 + + + + 3.0988917E-01 + + 2.8642621E-02 + + 1.5527633E-02 + + 2.5363175E-03 + + 2.0667848E-03 + + 8.9512793E-04 + + + + 3.0900783E-01 + + 2.8683967E-02 + + 1.5531635E-02 + + 2.6907133E-03 + + 2.2374989E-03 + + 9.9838820E-04 + + + + 3.0823110E-01 + + 2.8772506E-02 + + 1.5617343E-02 + + 2.7855260E-03 + + 2.3324886E-03 + + 1.0334317E-03 + + + + 3.0768619E-01 + + 2.9118421E-02 + + 1.5860568E-02 + + 2.8469804E-03 + + 2.4600144E-03 + + 1.0754851E-03 + + + + 3.0729355E-01 + + 2.9429106E-02 + + 1.6138063E-02 + + 2.9901807E-03 + + 2.5154903E-03 + + 1.1139796E-03 + + + + 3.0707342E-01 + + 2.9773340E-02 + + 1.6110013E-02 + + 2.9606704E-03 + + 2.6433692E-03 + + 1.1310602E-03 + + + + 3.0685025E-01 + + 3.0055483E-02 + + 1.6246774E-02 + + 3.1035410E-03 + + 2.6316501E-03 + + 1.1158252E-03 + + + + 3.0681469E-01 + + 3.0238686E-02 + + 1.6524723E-02 + + 3.0402635E-03 + + 2.6108287E-03 + + 1.1691486E-03 + + + + 3.0690606E-01 + + 3.0618190E-02 + + 1.6493402E-02 + + 3.0268029E-03 + + 2.5956288E-03 + + 1.0751657E-03 + + + + 3.0676357E-01 + + 3.0613175E-02 + + 1.6679358E-02 + + 2.8764512E-03 + + 2.5398735E-03 + + 1.0482210E-03 + + + + 3.0676223E-01 + + 3.0798581E-02 + + 1.6764686E-02 + + 3.1471928E-03 + + 2.7160881E-03 + + 1.2265875E-03 + + + + 3.0687178E-01 + + 3.0702117E-02 + + 1.6628813E-02 + + 2.8692462E-03 + + 2.4997850E-03 + + 9.3974161E-04 + + + 1.0000416E+00 + + + 1.0000513E+00 + + + 1.0000397E+00 + + + 1.0000409E+00 + + + 1.0000455E+00 + + + 1.0000417E+00 + + + 1.0000452E+00 + + + 1.0000431E+00 + + + 1.0000455E+00 + + + 1.0000451E+00 + + + 1.0000445E+00 + + + 1.0000482E+00 + + + 1.0000507E+00 + + + 1.0000542E+00 + + + 1.0000545E+00 + + + 1.0000461E+00 + + + 1.0000114E+00 + + + 1.0000112E+00 + + + 1.0000195E+00 + + + 1.0000216E+00 + + + 1.0000279E+00 + + + 1.0000307E+00 + + + 1.0000302E+00 + + + 1.0000313E+00 + + + 1.0000334E+00 + + + 1.0000309E+00 + + + 1.0000325E+00 + + + 1.0000318E+00 + + + 1.0000346E+00 + + + 1.0000335E+00 + + + 1.0000285E+00 + + + 1.0000358E+00 + + + + + lwtr_ang.71c + lwtr_ang.71c + 2.5300000E-08 + 5 + false + 32 + 1 + angle + + 8.3129229E-01 + + 8.3203829E-01 + + 8.3332424E-01 + + 8.3539719E-01 + + 8.3799288E-01 + + 8.4156597E-01 + + 8.4594074E-01 + + 8.5122773E-01 + + 8.5788274E-01 + + 8.6633387E-01 + + 8.7719846E-01 + + 8.9195077E-01 + + 9.1326621E-01 + + 9.4469159E-01 + + 9.9368716E-01 + + 1.0616854E+00 + + 1.0982938E+00 + + 1.0997200E+00 + + 1.0855410E+00 + + 1.0676695E+00 + + 1.0508172E+00 + + 1.0369337E+00 + + 1.0255762E+00 + + 1.0162841E+00 + + 1.0086633E+00 + + 1.0025783E+00 + + 9.9737297E-01 + + 9.9326768E-01 + + 9.9030852E-01 + + 9.8792719E-01 + + 9.8610453E-01 + + 9.8540665E-01 + + + 7.7368065E-03 + + 7.7519393E-03 + + 7.7819449E-03 + + 7.8285240E-03 + + 7.8881877E-03 + + 7.9652685E-03 + + 8.0588251E-03 + + 8.1724303E-03 + + 8.3079937E-03 + + 8.4749946E-03 + + 8.6811506E-03 + + 8.9456784E-03 + + 9.3049336E-03 + + 9.8025199E-03 + + 1.0529992E-02 + + 1.1498571E-02 + + 1.2065971E-02 + + 1.2168395E-02 + + 1.2053690E-02 + + 1.1870414E-02 + + 1.1678759E-02 + + 1.1516371E-02 + + 1.1377145E-02 + + 1.1262809E-02 + + 1.1166687E-02 + + 1.1090107E-02 + + 1.1022668E-02 + + 1.0968772E-02 + + 1.0931381E-02 + + 1.0898236E-02 + + 1.0872094E-02 + + 1.0866295E-02 + + + 8.2371185E-01 + + 3.5234207E-01 + + 1.1927931E-01 + + 7.4555729E-03 + + -1.8093822E-02 + + 4.7584668E-04 + + + + 8.2420033E-01 + + 3.5255993E-01 + + 1.1937026E-01 + + 7.2853742E-03 + + -1.8313481E-02 + + 4.3042936E-04 + + + + 8.2554395E-01 + + 3.5269171E-01 + + 1.1923224E-01 + + 7.3701368E-03 + + -1.8272340E-02 + + 4.4800957E-04 + + + + 8.2759297E-01 + + 3.5316566E-01 + + 1.1927088E-01 + + 7.3660347E-03 + + -1.8328170E-02 + + 4.1130682E-04 + + + + 8.3010220E-01 + + 3.5369971E-01 + + 1.1938537E-01 + + 7.4104975E-03 + + -1.8303317E-02 + + 4.1953876E-04 + + + + 8.3343687E-01 + + 3.5441436E-01 + + 1.1949872E-01 + + 7.5322327E-03 + + -1.8306753E-02 + + 4.5747101E-04 + + + + 8.3787092E-01 + + 3.5551997E-01 + + 1.1969232E-01 + + 7.5811660E-03 + + -1.8329166E-02 + + 4.7852748E-04 + + + + 8.4310387E-01 + + 3.5672367E-01 + + 1.1987885E-01 + + 7.6564988E-03 + + -1.8365527E-02 + + 4.5067238E-04 + + + + 8.4958953E-01 + + 3.5843887E-01 + + 1.2018528E-01 + + 7.7892315E-03 + + -1.8386164E-02 + + 4.8596316E-04 + + + + 8.5783406E-01 + + 3.6063097E-01 + + 1.2066889E-01 + + 7.9351893E-03 + + -1.8471175E-02 + + 4.7399741E-04 + + + + 8.6863002E-01 + + 3.6377631E-01 + + 1.2139807E-01 + + 8.1733217E-03 + + -1.8540490E-02 + + 5.0406643E-04 + + + + 8.8306988E-01 + + 3.6819641E-01 + + 1.2250274E-01 + + 8.4479144E-03 + + -1.8664160E-02 + + 5.3786229E-04 + + + + 9.0387733E-01 + + 3.7488040E-01 + + 1.2420959E-01 + + 8.7500816E-03 + + -1.8976448E-02 + + 4.9664889E-04 + + + + 9.3478951E-01 + + 3.8530100E-01 + + 1.2704555E-01 + + 9.1818403E-03 + + -1.9402464E-02 + + 5.3777400E-04 + + + + 9.8306151E-01 + + 4.0212328E-01 + + 1.3182489E-01 + + 9.8420986E-03 + + -2.0147587E-02 + + 5.9236718E-04 + + + + 1.0501953E+00 + + 4.2587762E-01 + + 1.3867637E-01 + + 1.0689470E-02 + + -2.1155894E-02 + + 6.5005469E-04 + + + + 1.0862685E+00 + + 4.3797788E-01 + + 1.4197736E-01 + + 1.1172759E-02 + + -2.1737067E-02 + + 6.5599084E-04 + + + + 1.0874414E+00 + + 4.3717092E-01 + + 1.4142760E-01 + + 1.1235986E-02 + + -2.1646253E-02 + + 6.5585383E-04 + + + + 1.0736455E+00 + + 4.3084349E-01 + + 1.3933736E-01 + + 1.1186759E-02 + + -2.1309779E-02 + + 6.3989000E-04 + + + + 1.0558960E+00 + + 4.2321090E-01 + + 1.3684390E-01 + + 1.1034633E-02 + + -2.0842589E-02 + + 6.8339604E-04 + + + + 1.0391120E+00 + + 4.1635648E-01 + + 1.3463939E-01 + + 1.0869743E-02 + + -2.0503958E-02 + + 6.5877305E-04 + + + + 1.0254663E+00 + + 4.1079355E-01 + + 1.3288830E-01 + + 1.0692002E-02 + + -2.0222325E-02 + + 7.2411022E-04 + + + + 1.0142449E+00 + + 4.0621344E-01 + + 1.3145072E-01 + + 1.0526222E-02 + + -1.9995334E-02 + + 6.8891812E-04 + + + + 1.0049846E+00 + + 4.0236090E-01 + + 1.3022093E-01 + + 1.0429641E-02 + + -1.9811424E-02 + + 7.3287561E-04 + + + + 9.9758865E-01 + + 3.9933064E-01 + + 1.2934518E-01 + + 1.0285856E-02 + + -1.9735216E-02 + + 6.4095239E-04 + + + + 9.9137092E-01 + + 3.9669204E-01 + + 1.2850897E-01 + + 1.0180247E-02 + + -1.9595919E-02 + + 7.4239863E-04 + + + + 9.8633885E-01 + + 3.9464706E-01 + + 1.2782783E-01 + + 1.0115679E-02 + + -1.9489063E-02 + + 6.7732699E-04 + + + + 9.8241480E-01 + + 3.9293162E-01 + + 1.2725328E-01 + + 1.0076113E-02 + + -1.9411729E-02 + + 6.7080378E-04 + + + + 9.7912906E-01 + + 3.9164180E-01 + + 1.2687293E-01 + + 9.9947816E-03 + + -1.9390105E-02 + + 6.8484948E-04 + + + + 9.7702901E-01 + + 3.9079267E-01 + + 1.2678305E-01 + + 1.0006132E-02 + + -1.9296574E-02 + + 7.3827259E-04 + + + + 9.7553202E-01 + + 3.9010913E-01 + + 1.2644932E-01 + + 9.9292219E-03 + + -1.9314591E-02 + + 7.3482134E-04 + + + + 9.7483429E-01 + + 3.8985598E-01 + + 1.2640804E-01 + + 9.9206549E-03 + + -1.9266376E-02 + + 7.6472379E-04 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + + + uo2_ang_mu.71c + uo2_ang_mu.71c + 2.5300000E-08 + 32 + true + 32 + 1 + angle + histogram + + 4.0734790E-01 + + 4.0709470E-01 + + 4.0665280E-01 + + 4.0605122E-01 + + 4.0509226E-01 + + 4.0399893E-01 + + 4.0264927E-01 + + 4.0112684E-01 + + 3.9937450E-01 + + 3.9743081E-01 + + 3.9533879E-01 + + 3.9307550E-01 + + 3.9084961E-01 + + 3.8878017E-01 + + 3.8751931E-01 + + 3.8693825E-01 + + 3.9039929E-01 + + 4.0037023E-01 + + 4.1057791E-01 + + 4.1924835E-01 + + 4.2629128E-01 + + 4.3202621E-01 + + 4.3673213E-01 + + 4.4062993E-01 + + 4.4385222E-01 + + 4.4647166E-01 + + 4.4861335E-01 + + 4.5026817E-01 + + 4.5165329E-01 + + 4.5255720E-01 + + 4.5310208E-01 + + 4.5337269E-01 + + + 3.1599020E-02 + + 3.1371085E-02 + + 3.1023091E-02 + + 3.0539250E-02 + + 2.9839460E-02 + + 2.9013479E-02 + + 2.8058288E-02 + + 2.7047229E-02 + + 2.5977776E-02 + + 2.4952391E-02 + + 2.4009896E-02 + + 2.3244570E-02 + + 2.2725200E-02 + + 2.2489873E-02 + + 2.2624168E-02 + + 2.3059735E-02 + + 2.4782557E-02 + + 2.8553081E-02 + + 3.3194318E-02 + + 3.8038660E-02 + + 4.2666012E-02 + + 4.6923885E-02 + + 5.0708283E-02 + + 5.3996846E-02 + + 5.6845491E-02 + + 5.9213445E-02 + + 6.1182604E-02 + + 6.2742563E-02 + + 6.3985293E-02 + + 6.4852148E-02 + + 6.5364227E-02 + + 6.5703785E-02 + + + 4.5146530E-02 + + 4.4766687E-02 + + 4.4155441E-02 + + 4.3323960E-02 + + 4.2141314E-02 + + 4.0739637E-02 + + 3.9143652E-02 + + 3.7465300E-02 + + 3.5735871E-02 + + 3.4113931E-02 + + 3.2678644E-02 + + 3.1591060E-02 + + 3.0966537E-02 + + 3.0821062E-02 + + 3.1238242E-02 + + 3.2075654E-02 + + 3.4603728E-02 + + 3.9898114E-02 + + 4.6725370E-02 + + 5.4142159E-02 + + 6.1436273E-02 + + 6.8238302E-02 + + 7.4365771E-02 + + 7.9727018E-02 + + 8.4398863E-02 + + 8.8315890E-02 + + 9.1574736E-02 + + 9.4183896E-02 + + 9.6266615E-02 + + 9.7706019E-02 + + 9.8564505E-02 + + 9.9171965E-02 + + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + 1.0000000E+00 + + + 1.8183034E-02 + + 1.8028751E-02 + + 1.7777081E-02 + + 1.7434939E-02 + + 1.6947918E-02 + + 1.6371445E-02 + + 1.5714505E-02 + + 1.5023310E-02 + + 1.4310527E-02 + + 1.3640363E-02 + + 1.3045308E-02 + + 1.2590537E-02 + + 1.2323486E-02 + + 1.2250235E-02 + + 1.2408325E-02 + + 1.2741816E-02 + + 1.3791905E-02 + + 1.6011218E-02 + + 1.8846275E-02 + + 2.1907807E-02 + + 2.4909120E-02 + + 2.7704245E-02 + + 3.0220623E-02 + + 3.2422114E-02 + + 3.4339614E-02 + + 3.5947934E-02 + + 3.7286018E-02 + + 3.8357139E-02 + + 3.9212858E-02 + + 3.9804080E-02 + + 4.0156625E-02 + + 4.0404918E-02 + + + 9.8066123E-03 + + 9.6646401E-03 + + 9.6663597E-03 + + 9.6289590E-03 + + 9.6096138E-03 + + 9.6458323E-03 + + 9.7060173E-03 + + 9.7686742E-03 + + 9.7497590E-03 + + 9.8863575E-03 + + 9.9653503E-03 + + 1.0024461E-02 + + 1.0143433E-02 + + 1.0224038E-02 + + 1.0343441E-02 + + 1.0433289E-02 + + 1.0526146E-02 + + 1.0783759E-02 + + 1.0949268E-02 + + 1.1096291E-02 + + 1.1232675E-02 + + 1.1455467E-02 + + 1.1650746E-02 + + 1.1903201E-02 + + 1.2297735E-02 + + 1.2748370E-02 + + 1.3264457E-02 + + 1.4048689E-02 + + 1.5280440E-02 + + 1.6908123E-02 + + 1.9601832E-02 + + 2.3844984E-02 + + + + 9.7708240E-03 + + 9.6914019E-03 + + 9.6149267E-03 + + 9.5973173E-03 + + 9.6433893E-03 + + 9.6506128E-03 + + 9.7039801E-03 + + 9.6956785E-03 + + 9.7873194E-03 + + 9.8654118E-03 + + 9.9413480E-03 + + 1.0063248E-02 + + 1.0102923E-02 + + 1.0232802E-02 + + 1.0308882E-02 + + 1.0501651E-02 + + 1.0589986E-02 + + 1.0719182E-02 + + 1.0893048E-02 + + 1.1057750E-02 + + 1.1303383E-02 + + 1.1462120E-02 + + 1.1668725E-02 + + 1.1965138E-02 + + 1.2270967E-02 + + 1.2704483E-02 + + 1.3318045E-02 + + 1.4113776E-02 + + 1.5284443E-02 + + 1.6903540E-02 + + 1.9623766E-02 + + 2.3773086E-02 + + + + 9.7573912E-03 + + 9.6754767E-03 + + 9.6414920E-03 + + 9.5888776E-03 + + 9.6229707E-03 + + 9.6517720E-03 + + 9.7047117E-03 + + 9.7260741E-03 + + 9.8017859E-03 + + 9.8536413E-03 + + 9.9389825E-03 + + 1.0024606E-02 + + 1.0138509E-02 + + 1.0234629E-02 + + 1.0324330E-02 + + 1.0453936E-02 + + 1.0578467E-02 + + 1.0739823E-02 + + 1.0879319E-02 + + 1.1046986E-02 + + 1.1241981E-02 + + 1.1441204E-02 + + 1.1664457E-02 + + 1.1957610E-02 + + 1.2276940E-02 + + 1.2759947E-02 + + 1.3279607E-02 + + 1.4124886E-02 + + 1.5267698E-02 + + 1.6982394E-02 + + 1.9550155E-02 + + 2.3789453E-02 + + + + 9.7595941E-03 + + 9.6406785E-03 + + 9.6091241E-03 + + 9.6094212E-03 + + 9.6096714E-03 + + 9.6231813E-03 + + 9.6784094E-03 + + 9.7493834E-03 + + 9.7951671E-03 + + 9.8514115E-03 + + 9.9241369E-03 + + 1.0012170E-02 + + 1.0117529E-02 + + 1.0213412E-02 + + 1.0335767E-02 + + 1.0447944E-02 + + 1.0584231E-02 + + 1.0753231E-02 + + 1.0883138E-02 + + 1.1065663E-02 + + 1.1250080E-02 + + 1.1439297E-02 + + 1.1646700E-02 + + 1.1958053E-02 + + 1.2287514E-02 + + 1.2721568E-02 + + 1.3290189E-02 + + 1.4110041E-02 + + 1.5281715E-02 + + 1.6979118E-02 + + 1.9608566E-02 + + 2.3793845E-02 + + + + 9.7316881E-03 + + 9.6194631E-03 + + 9.6065192E-03 + + 9.5773341E-03 + + 9.6080573E-03 + + 9.6136679E-03 + + 9.6707217E-03 + + 9.7207622E-03 + + 9.7745677E-03 + + 9.8542855E-03 + + 9.9290325E-03 + + 1.0013807E-02 + + 1.0087705E-02 + + 1.0212493E-02 + + 1.0318553E-02 + + 1.0440413E-02 + + 1.0586043E-02 + + 1.0693482E-02 + + 1.0881032E-02 + + 1.1028668E-02 + + 1.1236016E-02 + + 1.1448039E-02 + + 1.1645248E-02 + + 1.1940864E-02 + + 1.2280554E-02 + + 1.2704859E-02 + + 1.3284908E-02 + + 1.4087561E-02 + + 1.5269781E-02 + + 1.6974160E-02 + + 1.9647654E-02 + + 2.3878185E-02 + + + + 9.7161201E-03 + + 9.6202380E-03 + + 9.5797790E-03 + + 9.5545189E-03 + + 9.5785124E-03 + + 9.5970413E-03 + + 9.6077970E-03 + + 9.7078158E-03 + + 9.7457417E-03 + + 9.8241572E-03 + + 9.9053715E-03 + + 9.9664533E-03 + + 1.0069700E-02 + + 1.0182303E-02 + + 1.0310258E-02 + + 1.0426742E-02 + + 1.0561490E-02 + + 1.0707708E-02 + + 1.0863937E-02 + + 1.1051125E-02 + + 1.1221704E-02 + + 1.1442069E-02 + + 1.1658848E-02 + + 1.1941489E-02 + + 1.2275743E-02 + + 1.2702110E-02 + + 1.3323051E-02 + + 1.4108176E-02 + + 1.5289516E-02 + + 1.6993392E-02 + + 1.9675117E-02 + + 2.3895695E-02 + + + + 9.6862964E-03 + + 9.6118860E-03 + + 9.5204994E-03 + + 9.5427943E-03 + + 9.5461966E-03 + + 9.5657839E-03 + + 9.5949449E-03 + + 9.6654696E-03 + + 9.7413833E-03 + + 9.7999604E-03 + + 9.8652718E-03 + + 9.9395415E-03 + + 1.0066252E-02 + + 1.0162957E-02 + + 1.0288525E-02 + + 1.0410136E-02 + + 1.0544012E-02 + + 1.0683294E-02 + + 1.0857487E-02 + + 1.1034643E-02 + + 1.1202400E-02 + + 1.1413244E-02 + + 1.1649707E-02 + + 1.1927823E-02 + + 1.2268032E-02 + + 1.2711207E-02 + + 1.3301163E-02 + + 1.4107114E-02 + + 1.5299888E-02 + + 1.7035047E-02 + + 1.9688248E-02 + + 2.3980184E-02 + + + + 9.6789320E-03 + + 9.5794368E-03 + + 9.5136834E-03 + + 9.4987637E-03 + + 9.5122403E-03 + + 9.5462846E-03 + + 9.5893599E-03 + + 9.6291844E-03 + + 9.6755880E-03 + + 9.7758823E-03 + + 9.8512097E-03 + + 9.9153183E-03 + + 1.0010492E-02 + + 1.0132751E-02 + + 1.0249082E-02 + + 1.0374304E-02 + + 1.0525789E-02 + + 1.0647590E-02 + + 1.0816183E-02 + + 1.1002705E-02 + + 1.1172733E-02 + + 1.1391942E-02 + + 1.1634015E-02 + + 1.1896152E-02 + + 1.2250313E-02 + + 1.2701494E-02 + + 1.3297953E-02 + + 1.4128277E-02 + + 1.5304878E-02 + + 1.7057822E-02 + + 1.9759949E-02 + + 2.4058227E-02 + + + + 9.6295658E-03 + + 9.5389047E-03 + + 9.4742925E-03 + + 9.4575039E-03 + + 9.4670086E-03 + + 9.5016333E-03 + + 9.5287576E-03 + + 9.5962610E-03 + + 9.6450345E-03 + + 9.7355000E-03 + + 9.8168240E-03 + + 9.8832939E-03 + + 9.9783337E-03 + + 1.0096077E-02 + + 1.0226691E-02 + + 1.0343925E-02 + + 1.0478576E-02 + + 1.0624400E-02 + + 1.0795052E-02 + + 1.0971506E-02 + + 1.1155210E-02 + + 1.1359948E-02 + + 1.1600072E-02 + + 1.1891155E-02 + + 1.2217464E-02 + + 1.2687949E-02 + + 1.3279851E-02 + + 1.4139232E-02 + + 1.5331088E-02 + + 1.7109049E-02 + + 1.9804341E-02 + + 2.4140346E-02 + + + + 9.5761863E-03 + + 9.4820918E-03 + + 9.4335419E-03 + + 9.4124923E-03 + + 9.4238881E-03 + + 9.4447526E-03 + + 9.4999957E-03 + + 9.5315541E-03 + + 9.6078277E-03 + + 9.7003335E-03 + + 9.7574525E-03 + + 9.8379436E-03 + + 9.9462733E-03 + + 1.0053971E-02 + + 1.0174903E-02 + + 1.0296178E-02 + + 1.0416178E-02 + + 1.0598338E-02 + + 1.0736969E-02 + + 1.0921999E-02 + + 1.1103049E-02 + + 1.1337535E-02 + + 1.1560952E-02 + + 1.1844754E-02 + + 1.2186109E-02 + + 1.2650980E-02 + + 1.3288356E-02 + + 1.4113781E-02 + + 1.5336174E-02 + + 1.7136757E-02 + + 1.9885917E-02 + + 2.4274812E-02 + + + + 9.5122168E-03 + + 9.4370370E-03 + + 9.3789842E-03 + + 9.3641793E-03 + + 9.3461446E-03 + + 9.3736151E-03 + + 9.4378621E-03 + + 9.4888307E-03 + + 9.5578870E-03 + + 9.6287585E-03 + + 9.7018579E-03 + + 9.7842398E-03 + + 9.8853931E-03 + + 9.9928939E-03 + + 1.0118830E-02 + + 1.0234335E-02 + + 1.0390558E-02 + + 1.0549529E-02 + + 1.0695492E-02 + + 1.0871300E-02 + + 1.1074656E-02 + + 1.1276285E-02 + + 1.1528116E-02 + + 1.1795259E-02 + + 1.2170410E-02 + + 1.2620687E-02 + + 1.3248447E-02 + + 1.4113310E-02 + + 1.5330992E-02 + + 1.7146317E-02 + + 1.9971083E-02 + + 2.4420125E-02 + + + + 9.4655965E-03 + + 9.3472543E-03 + + 9.3135845E-03 + + 9.2723897E-03 + + 9.2802062E-03 + + 9.3207904E-03 + + 9.3438769E-03 + + 9.4089282E-03 + + 9.4772470E-03 + + 9.5593066E-03 + + 9.6350349E-03 + + 9.7156422E-03 + + 9.8254749E-03 + + 9.9256153E-03 + + 1.0046422E-02 + + 1.0170127E-02 + + 1.0324109E-02 + + 1.0494779E-02 + + 1.0643991E-02 + + 1.0830850E-02 + + 1.1006031E-02 + + 1.1226896E-02 + + 1.1461160E-02 + + 1.1751421E-02 + + 1.2117075E-02 + + 1.2580807E-02 + + 1.3191655E-02 + + 1.4078045E-02 + + 1.5308284E-02 + + 1.7194422E-02 + + 2.0045307E-02 + + 2.4607445E-02 + + + + 9.3803794E-03 + + 9.2679518E-03 + + 9.2244314E-03 + + 9.2113545E-03 + + 9.2138570E-03 + + 9.2462589E-03 + + 9.2883856E-03 + + 9.3378797E-03 + + 9.4087558E-03 + + 9.4791189E-03 + + 9.5459849E-03 + + 9.6532937E-03 + + 9.7407231E-03 + + 9.8542750E-03 + + 9.9718785E-03 + + 1.0102253E-02 + + 1.0257191E-02 + + 1.0422947E-02 + + 1.0576154E-02 + + 1.0751370E-02 + + 1.0937694E-02 + + 1.1150504E-02 + + 1.1403363E-02 + + 1.1690271E-02 + + 1.2041631E-02 + + 1.2515941E-02 + + 1.3148002E-02 + + 1.4030663E-02 + + 1.5293666E-02 + + 1.7182409E-02 + + 2.0111404E-02 + + 2.4776028E-02 + + + + 9.3172617E-03 + + 9.2089569E-03 + + 9.1486659E-03 + + 9.1277777E-03 + + 9.1461098E-03 + + 9.1678665E-03 + + 9.2093270E-03 + + 9.2630599E-03 + + 9.3084731E-03 + + 9.4133582E-03 + + 9.4836368E-03 + + 9.5792942E-03 + + 9.6772510E-03 + + 9.7775420E-03 + + 9.9042034E-03 + + 1.0042269E-02 + + 1.0180349E-02 + + 1.0339342E-02 + + 1.0499500E-02 + + 1.0689206E-02 + + 1.0856780E-02 + + 1.1064872E-02 + + 1.1313606E-02 + + 1.1607748E-02 + + 1.1964604E-02 + + 1.2435691E-02 + + 1.3060461E-02 + + 1.3974178E-02 + + 1.5269813E-02 + + 1.7174181E-02 + + 2.0168154E-02 + + 2.5006625E-02 + + + + 9.2675186E-03 + + 9.1560947E-03 + + 9.1099682E-03 + + 9.0686023E-03 + + 9.0949282E-03 + + 9.1189359E-03 + + 9.1587135E-03 + + 9.2079644E-03 + + 9.2872523E-03 + + 9.3678425E-03 + + 9.4331971E-03 + + 9.5255074E-03 + + 9.6234797E-03 + + 9.7408756E-03 + + 9.8464228E-03 + + 9.9839770E-03 + + 1.0134229E-02 + + 1.0296950E-02 + + 1.0437157E-02 + + 1.0621205E-02 + + 1.0805038E-02 + + 1.1016214E-02 + + 1.1261528E-02 + + 1.1539985E-02 + + 1.1895722E-02 + + 1.2371092E-02 + + 1.3001136E-02 + + 1.3913205E-02 + + 1.5214879E-02 + + 1.7172526E-02 + + 2.0220324E-02 + + 2.5144658E-02 + + + + 9.2487420E-03 + + 9.1281258E-03 + + 9.0754703E-03 + + 9.0528962E-03 + + 9.0607826E-03 + + 9.0836186E-03 + + 9.1336267E-03 + + 9.1791302E-03 + + 9.2456080E-03 + + 9.3262261E-03 + + 9.3970635E-03 + + 9.4814471E-03 + + 9.5988170E-03 + + 9.7082444E-03 + + 9.8223867E-03 + + 9.9431245E-03 + + 1.0105918E-02 + + 1.0235908E-02 + + 1.0399441E-02 + + 1.0585520E-02 + + 1.0757015E-02 + + 1.0981562E-02 + + 1.1194196E-02 + + 1.1486474E-02 + + 1.1845432E-02 + + 1.2322129E-02 + + 1.2940763E-02 + + 1.3835543E-02 + + 1.5166292E-02 + + 1.7159569E-02 + + 2.0241404E-02 + + 2.5261208E-02 + + + + 9.3326963E-03 + + 9.2136145E-03 + + 9.1672115E-03 + + 9.1448034E-03 + + 9.1509378E-03 + + 9.1710414E-03 + + 9.2163629E-03 + + 9.2665486E-03 + + 9.3325121E-03 + + 9.4016396E-03 + + 9.5034088E-03 + + 9.5773816E-03 + + 9.6674816E-03 + + 9.7850853E-03 + + 9.9014422E-03 + + 1.0023693E-02 + + 1.0166562E-02 + + 1.0315995E-02 + + 1.0472398E-02 + + 1.0641203E-02 + + 1.0830711E-02 + + 1.1048828E-02 + + 1.1263336E-02 + + 1.1551095E-02 + + 1.1894787E-02 + + 1.2358496E-02 + + 1.2983340E-02 + + 1.3874895E-02 + + 1.5186930E-02 + + 1.7144384E-02 + + 2.0133533E-02 + + 2.5038814E-02 + + + + 9.5906528E-03 + + 9.4714149E-03 + + 9.4373276E-03 + + 9.4092245E-03 + + 9.4080878E-03 + + 9.4464166E-03 + + 9.4856267E-03 + + 9.5436808E-03 + + 9.6059463E-03 + + 9.6771305E-03 + + 9.7582049E-03 + + 9.8361595E-03 + + 9.9382461E-03 + + 1.0051079E-02 + + 1.0152805E-02 + + 1.0287101E-02 + + 1.0441087E-02 + + 1.0565078E-02 + + 1.0711502E-02 + + 1.0891178E-02 + + 1.1071184E-02 + + 1.1292859E-02 + + 1.1522246E-02 + + 1.1788324E-02 + + 1.2135266E-02 + + 1.2615017E-02 + + 1.3201487E-02 + + 1.4060330E-02 + + 1.5281894E-02 + + 1.7084038E-02 + + 1.9845860E-02 + + 2.4315267E-02 + + + + 9.8248104E-03 + + 9.7323237E-03 + + 9.6774360E-03 + + 9.6780777E-03 + + 9.6806071E-03 + + 9.7078157E-03 + + 9.7458638E-03 + + 9.8100671E-03 + + 9.8562275E-03 + + 9.9244575E-03 + + 1.0022233E-02 + + 1.0083426E-02 + + 1.0184960E-02 + + 1.0286955E-02 + + 1.0393298E-02 + + 1.0523934E-02 + + 1.0674383E-02 + + 1.0799950E-02 + + 1.0950769E-02 + + 1.1117330E-02 + + 1.1304368E-02 + + 1.1511486E-02 + + 1.1731876E-02 + + 1.2009368E-02 + + 1.2343059E-02 + + 1.2776813E-02 + + 1.3375541E-02 + + 1.4170942E-02 + + 1.5323633E-02 + + 1.7010159E-02 + + 1.9570530E-02 + + 2.3678539E-02 + + + + 1.0003922E-02 + + 9.9126090E-03 + + 9.8710015E-03 + + 9.8670066E-03 + + 9.8659781E-03 + + 9.8893674E-03 + + 9.9377144E-03 + + 9.9843851E-03 + + 1.0043716E-02 + + 1.0114248E-02 + + 1.0187530E-02 + + 1.0267347E-02 + + 1.0358552E-02 + + 1.0462167E-02 + + 1.0591882E-02 + + 1.0702606E-02 + + 1.0831901E-02 + + 1.0977238E-02 + + 1.1108339E-02 + + 1.1308120E-02 + + 1.1462407E-02 + + 1.1644185E-02 + + 1.1896695E-02 + + 1.2152261E-02 + + 1.2470909E-02 + + 1.2904242E-02 + + 1.3463705E-02 + + 1.4217800E-02 + + 1.5306830E-02 + + 1.6913123E-02 + + 1.9352840E-02 + + 2.3210338E-02 + + + + 1.0110150E-02 + + 1.0038689E-02 + + 1.0006487E-02 + + 9.9882512E-03 + + 1.0012465E-02 + + 1.0038003E-02 + + 1.0080385E-02 + + 1.0133099E-02 + + 1.0195776E-02 + + 1.0230495E-02 + + 1.0337794E-02 + + 1.0414378E-02 + + 1.0494026E-02 + + 1.0600307E-02 + + 1.0712290E-02 + + 1.0823942E-02 + + 1.0947285E-02 + + 1.1079870E-02 + + 1.1237336E-02 + + 1.1392659E-02 + + 1.1573008E-02 + + 1.1782567E-02 + + 1.1965944E-02 + + 1.2231191E-02 + + 1.2530296E-02 + + 1.2940908E-02 + + 1.3487030E-02 + + 1.4206747E-02 + + 1.5258559E-02 + + 1.6813287E-02 + + 1.9165344E-02 + + 2.2905494E-02 + + + + 1.0214736E-02 + + 1.0132229E-02 + + 1.0105238E-02 + + 1.0076016E-02 + + 1.0102342E-02 + + 1.0126079E-02 + + 1.0166649E-02 + + 1.0211271E-02 + + 1.0274414E-02 + + 1.0328594E-02 + + 1.0415141E-02 + + 1.0493084E-02 + + 1.0583179E-02 + + 1.0679080E-02 + + 1.0785554E-02 + + 1.0896861E-02 + + 1.1025180E-02 + + 1.1151734E-02 + + 1.1308616E-02 + + 1.1460250E-02 + + 1.1631030E-02 + + 1.1818829E-02 + + 1.2020589E-02 + + 1.2270878E-02 + + 1.2564608E-02 + + 1.2974969E-02 + + 1.3498179E-02 + + 1.4207601E-02 + + 1.5228538E-02 + + 1.6730509E-02 + + 1.9011440E-02 + + 2.2710972E-02 + + + + 1.0268267E-02 + + 1.0196885E-02 + + 1.0157361E-02 + + 1.0140649E-02 + + 1.0169437E-02 + + 1.0183304E-02 + + 1.0243979E-02 + + 1.0276945E-02 + + 1.0343732E-02 + + 1.0412311E-02 + + 1.0476453E-02 + + 1.0547309E-02 + + 1.0646659E-02 + + 1.0745962E-02 + + 1.0848409E-02 + + 1.0960759E-02 + + 1.1082990E-02 + + 1.1214082E-02 + + 1.1358598E-02 + + 1.1499661E-02 + + 1.1661477E-02 + + 1.1836025E-02 + + 1.2058652E-02 + + 1.2293116E-02 + + 1.2566338E-02 + + 1.2977505E-02 + + 1.3480636E-02 + + 1.4176526E-02 + + 1.5190195E-02 + + 1.6660100E-02 + + 1.8910243E-02 + + 2.2560488E-02 + + + + 1.0317792E-02 + + 1.0247350E-02 + + 1.0209518E-02 + + 1.0176974E-02 + + 1.0202003E-02 + + 1.0234569E-02 + + 1.0290041E-02 + + 1.0329819E-02 + + 1.0401460E-02 + + 1.0453530E-02 + + 1.0512745E-02 + + 1.0606160E-02 + + 1.0688319E-02 + + 1.0769020E-02 + + 1.0865579E-02 + + 1.0991642E-02 + + 1.1131957E-02 + + 1.1257621E-02 + + 1.1387433E-02 + + 1.1532542E-02 + + 1.1687029E-02 + + 1.1880598E-02 + + 1.2082924E-02 + + 1.2307513E-02 + + 1.2595319E-02 + + 1.2957554E-02 + + 1.3464867E-02 + + 1.4143088E-02 + + 1.5132042E-02 + + 1.6579665E-02 + + 1.8862731E-02 + + 2.2454495E-02 + + + + 1.0353436E-02 + + 1.0273106E-02 + + 1.0227967E-02 + + 1.0220784E-02 + + 1.0226684E-02 + + 1.0260876E-02 + + 1.0312588E-02 + + 1.0358157E-02 + + 1.0401938E-02 + + 1.0498406E-02 + + 1.0534029E-02 + + 1.0633113E-02 + + 1.0711786E-02 + + 1.0806930E-02 + + 1.0902341E-02 + + 1.1005862E-02 + + 1.1140903E-02 + + 1.1256190E-02 + + 1.1418216E-02 + + 1.1551704E-02 + + 1.1699315E-02 + + 1.1876316E-02 + + 1.2095791E-02 + + 1.2321059E-02 + + 1.2598778E-02 + + 1.2945785E-02 + + 1.3441410E-02 + + 1.4150310E-02 + + 1.5110707E-02 + + 1.6555004E-02 + + 1.8801362E-02 + + 2.2362745E-02 + + + + 1.0368488E-02 + + 1.0298130E-02 + + 1.0243651E-02 + + 1.0237480E-02 + + 1.0271825E-02 + + 1.0283702E-02 + + 1.0344999E-02 + + 1.0388950E-02 + + 1.0443402E-02 + + 1.0499057E-02 + + 1.0554275E-02 + + 1.0647638E-02 + + 1.0712690E-02 + + 1.0827382E-02 + + 1.0931601E-02 + + 1.1018556E-02 + + 1.1152881E-02 + + 1.1290059E-02 + + 1.1420028E-02 + + 1.1563732E-02 + + 1.1705467E-02 + + 1.1895794E-02 + + 1.2092710E-02 + + 1.2310135E-02 + + 1.2594991E-02 + + 1.2963713E-02 + + 1.3446042E-02 + + 1.4105472E-02 + + 1.5078624E-02 + + 1.6548015E-02 + + 1.8734322E-02 + + 2.2344993E-02 + + + + 1.0381081E-02 + + 1.0306858E-02 + + 1.0277150E-02 + + 1.0252664E-02 + + 1.0290401E-02 + + 1.0294657E-02 + + 1.0329546E-02 + + 1.0392619E-02 + + 1.0438626E-02 + + 1.0515024E-02 + + 1.0591864E-02 + + 1.0665572E-02 + + 1.0764627E-02 + + 1.0867664E-02 + + 1.0949159E-02 + + 1.1055591E-02 + + 1.1176115E-02 + + 1.1296618E-02 + + 1.1417920E-02 + + 1.1572450E-02 + + 1.1714864E-02 + + 1.1894815E-02 + + 1.2080388E-02 + + 1.2311306E-02 + + 1.2600200E-02 + + 1.2956245E-02 + + 1.3438289E-02 + + 1.4113577E-02 + + 1.5087407E-02 + + 1.6503410E-02 + + 1.8740374E-02 + + 2.2290166E-02 + + + + 1.0379499E-02 + + 1.0316828E-02 + + 1.0280998E-02 + + 1.0282758E-02 + + 1.0275605E-02 + + 1.0306117E-02 + + 1.0348208E-02 + + 1.0378745E-02 + + 1.0464787E-02 + + 1.0530463E-02 + + 1.0608232E-02 + + 1.0674147E-02 + + 1.0763998E-02 + + 1.0837280E-02 + + 1.0949195E-02 + + 1.1058508E-02 + + 1.1190589E-02 + + 1.1322242E-02 + + 1.1432422E-02 + + 1.1582770E-02 + + 1.1718207E-02 + + 1.1912632E-02 + + 1.2075287E-02 + + 1.2309263E-02 + + 1.2598203E-02 + + 1.2947275E-02 + + 1.3422204E-02 + + 1.4101792E-02 + + 1.5074531E-02 + + 1.6493963E-02 + + 1.8703917E-02 + + 2.2279156E-02 + + + + 1.0425160E-02 + + 1.0318223E-02 + + 1.0301788E-02 + + 1.0294047E-02 + + 1.0284686E-02 + + 1.0349566E-02 + + 1.0366017E-02 + + 1.0397170E-02 + + 1.0476721E-02 + + 1.0527169E-02 + + 1.0602826E-02 + + 1.0679945E-02 + + 1.0766188E-02 + + 1.0868516E-02 + + 1.0967919E-02 + + 1.1069388E-02 + + 1.1166089E-02 + + 1.1293657E-02 + + 1.1442396E-02 + + 1.1579055E-02 + + 1.1756181E-02 + + 1.1901153E-02 + + 1.2075228E-02 + + 1.2329489E-02 + + 1.2582177E-02 + + 1.2965246E-02 + + 1.3451596E-02 + + 1.4114325E-02 + + 1.5048259E-02 + + 1.6478843E-02 + + 1.8702139E-02 + + 2.2209013E-02 + + + + 1.0403120E-02 + + 1.0338330E-02 + + 1.0290627E-02 + + 1.0277361E-02 + + 1.0322671E-02 + + 1.0363565E-02 + + 1.0362094E-02 + + 1.0440786E-02 + + 1.0485173E-02 + + 1.0557958E-02 + + 1.0608779E-02 + + 1.0701287E-02 + + 1.0735526E-02 + + 1.0841760E-02 + + 1.0953485E-02 + + 1.1083460E-02 + + 1.1193252E-02 + + 1.1297597E-02 + + 1.1457508E-02 + + 1.1572681E-02 + + 1.1742409E-02 + + 1.1907920E-02 + + 1.2078022E-02 + + 1.2328222E-02 + + 1.2585186E-02 + + 1.2967887E-02 + + 1.3432333E-02 + + 1.4108413E-02 + + 1.5033330E-02 + + 1.6472418E-02 + + 1.8651936E-02 + + 2.2205180E-02 + + + + 1.0383972E-02 + + 1.0327340E-02 + + 1.0320447E-02 + + 1.0278943E-02 + + 1.0322805E-02 + + 1.0366993E-02 + + 1.0395218E-02 + + 1.0418111E-02 + + 1.0463460E-02 + + 1.0564171E-02 + + 1.0601357E-02 + + 1.0671268E-02 + + 1.0756633E-02 + + 1.0863620E-02 + + 1.0982943E-02 + + 1.1088262E-02 + + 1.1182298E-02 + + 1.1297412E-02 + + 1.1404871E-02 + + 1.1585288E-02 + + 1.1730768E-02 + + 1.1878353E-02 + + 1.2074551E-02 + + 1.2333404E-02 + + 1.2612428E-02 + + 1.2970577E-02 + + 1.3454326E-02 + + 1.4077858E-02 + + 1.5040384E-02 + + 1.6507810E-02 + + 1.8671362E-02 + + 2.2195534E-02 + + + + 1.0393621E-02 + + 1.0343827E-02 + + 1.0278122E-02 + + 1.0307024E-02 + + 1.0321853E-02 + + 1.0374136E-02 + + 1.0395136E-02 + + 1.0457919E-02 + + 1.0485306E-02 + + 1.0588898E-02 + + 1.0597124E-02 + + 1.0623537E-02 + + 1.0731134E-02 + + 1.0828231E-02 + + 1.0959209E-02 + + 1.1072327E-02 + + 1.1248877E-02 + + 1.1263490E-02 + + 1.1402046E-02 + + 1.1566689E-02 + + 1.1767919E-02 + + 1.1861445E-02 + + 1.2076314E-02 + + 1.2322575E-02 + + 1.2537228E-02 + + 1.2963070E-02 + + 1.3353083E-02 + + 1.4108968E-02 + + 1.5044977E-02 + + 1.6501651E-02 + + 1.8769742E-02 + + 2.2133504E-02 + + + 1.0002763E+00 + + + 1.0002760E+00 + + + 1.0002658E+00 + + + 1.0002710E+00 + + + 1.0002776E+00 + + + 1.0002767E+00 + + + 1.0002833E+00 + + + 1.0002791E+00 + + + 1.0002788E+00 + + + 1.0002858E+00 + + + 1.0002884E+00 + + + 1.0002916E+00 + + + 1.0003039E+00 + + + 1.0003181E+00 + + + 1.0003365E+00 + + + 1.0003544E+00 + + + 1.0003372E+00 + + + 1.0002764E+00 + + + 1.0002508E+00 + + + 1.0002343E+00 + + + 1.0002360E+00 + + + 1.0002375E+00 + + + 1.0002331E+00 + + + 1.0002344E+00 + + + 1.0002385E+00 + + + 1.0002316E+00 + + + 1.0002360E+00 + + + 1.0002360E+00 + + + 1.0002354E+00 + + + 1.0002349E+00 + + + 1.0002325E+00 + + + 1.0002268E+00 + + + + + clad_ang_mu.71c + clad_ang_mu.71c + 2.5300000E-08 + 32 + false + 32 + 1 + angle + histogram + + 3.1005638E-01 + + 3.0999067E-01 + + 3.0994879E-01 + + 3.0987779E-01 + + 3.0961631E-01 + + 3.0948272E-01 + + 3.0913340E-01 + + 3.0868239E-01 + + 3.0799925E-01 + + 3.0712597E-01 + + 3.0590948E-01 + + 3.0432728E-01 + + 3.0235012E-01 + + 2.9996873E-01 + + 2.9743091E-01 + + 2.9739624E-01 + + 3.0835788E-01 + + 3.1305337E-01 + + 3.1379599E-01 + + 3.1314506E-01 + + 3.1216249E-01 + + 3.1129786E-01 + + 3.1059203E-01 + + 3.1009561E-01 + + 3.0977837E-01 + + 3.0951041E-01 + + 3.0930940E-01 + + 3.0929712E-01 + + 3.0925741E-01 + + 3.0917641E-01 + + 3.0919741E-01 + + 3.0912502E-01 + + + 1.3490691E-03 + + 1.3463259E-03 + + 1.3498512E-03 + + 1.3366347E-03 + + 1.3288899E-03 + + 1.3176269E-03 + + 1.3059971E-03 + + 1.2891508E-03 + + 1.2713136E-03 + + 1.2555332E-03 + + 1.2394055E-03 + + 1.2170158E-03 + + 1.1969201E-03 + + 1.1849620E-03 + + 1.1899173E-03 + + 1.2761137E-03 + + 1.6244505E-03 + + 1.9090551E-03 + + 2.0837409E-03 + + 2.1976011E-03 + + 2.2746911E-03 + + 2.3308251E-03 + + 2.3700744E-03 + + 2.3981231E-03 + + 2.4248079E-03 + + 2.4441792E-03 + + 2.4510541E-03 + + 2.4640212E-03 + + 2.4741885E-03 + + 2.4697219E-03 + + 2.4721421E-03 + + 2.4729172E-03 + + + 8.6638893E-03 + + 8.2719674E-03 + + 7.8055649E-03 + + 7.4105610E-03 + + 7.2544086E-03 + + 7.0854147E-03 + + 6.9965517E-03 + + 7.0314805E-03 + + 6.8552954E-03 + + 6.9138525E-03 + + 6.9528906E-03 + + 7.0689776E-03 + + 7.0720596E-03 + + 7.2523539E-03 + + 7.5405167E-03 + + 7.7624175E-03 + + 7.9838046E-03 + + 8.1702629E-03 + + 8.4784584E-03 + + 8.8970906E-03 + + 9.3105862E-03 + + 9.7826390E-03 + + 1.0253151E-02 + + 1.0659455E-02 + + 1.1134076E-02 + + 1.1649276E-02 + + 1.2603655E-02 + + 1.3342297E-02 + + 1.4372697E-02 + + 1.5779610E-02 + + 1.7933383E-02 + + 2.0318816E-02 + + + + 8.6137649E-03 + + 8.0815773E-03 + + 7.7778880E-03 + + 7.4879636E-03 + + 7.2446680E-03 + + 7.0652074E-03 + + 6.9244607E-03 + + 6.9131046E-03 + + 6.9017486E-03 + + 6.9408066E-03 + + 6.9814132E-03 + + 7.0440438E-03 + + 7.1589812E-03 + + 7.3353447E-03 + + 7.5896522E-03 + + 7.7529390E-03 + + 8.0199791E-03 + + 8.3484454E-03 + + 8.5960425E-03 + + 8.9554799E-03 + + 9.2763754E-03 + + 9.7440398E-03 + + 1.0084034E-02 + + 1.0634976E-02 + + 1.1176800E-02 + + 1.1768004E-02 + + 1.2488944E-02 + + 1.3414293E-02 + + 1.4307639E-02 + + 1.5845012E-02 + + 1.7838866E-02 + + 2.0339442E-02 + + + + 8.6069286E-03 + + 8.1600584E-03 + + 7.7753343E-03 + + 7.5082514E-03 + + 7.2541589E-03 + + 7.1052368E-03 + + 7.0049508E-03 + + 6.9087178E-03 + + 6.8877253E-03 + + 6.9276318E-03 + + 6.9580813E-03 + + 7.0116019E-03 + + 7.1577180E-03 + + 7.3369857E-03 + + 7.5182280E-03 + + 7.7277374E-03 + + 7.9440018E-03 + + 8.2744779E-03 + + 8.6378977E-03 + + 8.8881451E-03 + + 9.2653867E-03 + + 9.6492794E-03 + + 1.0205685E-02 + + 1.0657959E-02 + + 1.1210208E-02 + + 1.1713716E-02 + + 1.2497402E-02 + + 1.3347079E-02 + + 1.4469243E-02 + + 1.5835834E-02 + + 1.7754882E-02 + + 2.0415319E-02 + + + + 8.6357058E-03 + + 8.1456937E-03 + + 7.7155413E-03 + + 7.4818571E-03 + + 7.2524325E-03 + + 7.0736756E-03 + + 7.0115740E-03 + + 6.8735456E-03 + + 6.8726489E-03 + + 6.9218219E-03 + + 6.9136015E-03 + + 7.0770385E-03 + + 7.1125358E-03 + + 7.2947303E-03 + + 7.5540473E-03 + + 7.7247333E-03 + + 7.9593143E-03 + + 8.2175104E-03 + + 8.5783123E-03 + + 8.9662416E-03 + + 9.2850446E-03 + + 9.7500218E-03 + + 1.0192206E-02 + + 1.0589252E-02 + + 1.1196518E-02 + + 1.1754610E-02 + + 1.2477858E-02 + + 1.3364244E-02 + + 1.4489097E-02 + + 1.5799582E-02 + + 1.7806262E-02 + + 2.0415575E-02 + + + + 8.6187094E-03 + + 8.1028888E-03 + + 7.7502930E-03 + + 7.4368288E-03 + + 7.2053294E-03 + + 7.0754195E-03 + + 6.9609624E-03 + + 6.9199506E-03 + + 6.8721819E-03 + + 6.9170716E-03 + + 6.9278240E-03 + + 7.0082024E-03 + + 7.1469258E-03 + + 7.2928174E-03 + + 7.4578635E-03 + + 7.7005853E-03 + + 7.9397817E-03 + + 8.2897923E-03 + + 8.5642424E-03 + + 8.9336425E-03 + + 9.2822429E-03 + + 9.6866617E-03 + + 1.0169638E-02 + + 1.0601319E-02 + + 1.1134062E-02 + + 1.1797713E-02 + + 1.2521413E-02 + + 1.3398584E-02 + + 1.4465948E-02 + + 1.5920693E-02 + + 1.7831503E-02 + + 2.0386280E-02 + + + + 8.5957828E-03 + + 8.0917421E-03 + + 7.7483058E-03 + + 7.4335661E-03 + + 7.2051598E-03 + + 7.0542832E-03 + + 6.9482999E-03 + + 6.8660522E-03 + + 6.8566650E-03 + + 6.8895446E-03 + + 6.9769966E-03 + + 7.0151292E-03 + + 7.1289919E-03 + + 7.2728159E-03 + + 7.4843447E-03 + + 7.6904746E-03 + + 7.9728210E-03 + + 8.2376090E-03 + + 8.5714149E-03 + + 8.9027889E-03 + + 9.2973443E-03 + + 9.6952072E-03 + + 1.0177798E-02 + + 1.0619290E-02 + + 1.1136220E-02 + + 1.1749356E-02 + + 1.2532485E-02 + + 1.3371645E-02 + + 1.4476030E-02 + + 1.5936887E-02 + + 1.7814576E-02 + + 2.0401706E-02 + + + + 8.5762717E-03 + + 8.0787798E-03 + + 7.6957274E-03 + + 7.4218081E-03 + + 7.1969403E-03 + + 7.0456914E-03 + + 6.9243998E-03 + + 6.8670339E-03 + + 6.8410876E-03 + + 6.8440959E-03 + + 6.9114894E-03 + + 6.9709444E-03 + + 7.1246584E-03 + + 7.2467020E-03 + + 7.4540634E-03 + + 7.6790984E-03 + + 7.9072251E-03 + + 8.2202101E-03 + + 8.5598098E-03 + + 8.9093117E-03 + + 9.2775317E-03 + + 9.6625479E-03 + + 1.0156279E-02 + + 1.0632045E-02 + + 1.1116292E-02 + + 1.1767916E-02 + + 1.2489983E-02 + + 1.3349302E-02 + + 1.4524155E-02 + + 1.5953415E-02 + + 1.7870641E-02 + + 2.0504336E-02 + + + + 8.5580155E-03 + + 8.0552826E-03 + + 7.6847006E-03 + + 7.3901486E-03 + + 7.1714794E-03 + + 6.9956094E-03 + + 6.8966894E-03 + + 6.8584904E-03 + + 6.8074847E-03 + + 6.8182305E-03 + + 6.8700458E-03 + + 6.9598760E-03 + + 7.0775275E-03 + + 7.2721659E-03 + + 7.4256244E-03 + + 7.6626570E-03 + + 7.8956048E-03 + + 8.2476025E-03 + + 8.5876768E-03 + + 8.8916497E-03 + + 9.2599869E-03 + + 9.6607086E-03 + + 1.0104818E-02 + + 1.0621057E-02 + + 1.1139577E-02 + + 1.1789513E-02 + + 1.2505652E-02 + + 1.3335138E-02 + + 1.4480446E-02 + + 1.5926378E-02 + + 1.7926012E-02 + + 2.0526011E-02 + + + + 8.5161659E-03 + + 8.0446298E-03 + + 7.6545410E-03 + + 7.3722009E-03 + + 7.1148071E-03 + + 6.9727284E-03 + + 6.8574133E-03 + + 6.7687628E-03 + + 6.7671107E-03 + + 6.8028617E-03 + + 6.8012426E-03 + + 6.9205557E-03 + + 7.0398688E-03 + + 7.2416867E-03 + + 7.3960899E-03 + + 7.6495518E-03 + + 7.9006016E-03 + + 8.1906074E-03 + + 8.4993478E-03 + + 8.8863636E-03 + + 9.2483009E-03 + + 9.6547452E-03 + + 1.0109959E-02 + + 1.0588004E-02 + + 1.1123575E-02 + + 1.1768480E-02 + + 1.2510924E-02 + + 1.3377043E-02 + + 1.4514862E-02 + + 1.5985046E-02 + + 1.7920853E-02 + + 2.0545741E-02 + + + + 8.4881904E-03 + + 8.0008968E-03 + + 7.5800933E-03 + + 7.3219921E-03 + + 7.0930406E-03 + + 6.9243759E-03 + + 6.8395166E-03 + + 6.7595356E-03 + + 6.7209304E-03 + + 6.7524289E-03 + + 6.7924495E-03 + + 6.8886916E-03 + + 7.0061035E-03 + + 7.1949742E-03 + + 7.3557793E-03 + + 7.6015942E-03 + + 7.8273839E-03 + + 8.1635087E-03 + + 8.4872268E-03 + + 8.8563257E-03 + + 9.1982925E-03 + + 9.6315629E-03 + + 1.0058991E-02 + + 1.0542942E-02 + + 1.1120245E-02 + + 1.1716127E-02 + + 1.2496242E-02 + + 1.3357995E-02 + + 1.4520670E-02 + + 1.5968277E-02 + + 1.7999571E-02 + + 2.0619911E-02 + + + + 8.4547550E-03 + + 7.9415583E-03 + + 7.5504996E-03 + + 7.2492760E-03 + + 7.0388623E-03 + + 6.9114334E-03 + + 6.7880701E-03 + + 6.7298137E-03 + + 6.6707776E-03 + + 6.6865113E-03 + + 6.7469676E-03 + + 6.8440431E-03 + + 6.9530093E-03 + + 7.1334872E-03 + + 7.3320937E-03 + + 7.5447909E-03 + + 7.7926035E-03 + + 8.1024597E-03 + + 8.4776176E-03 + + 8.7989469E-03 + + 9.1860513E-03 + + 9.6106103E-03 + + 1.0035921E-02 + + 1.0516926E-02 + + 1.1111883E-02 + + 1.1693054E-02 + + 1.2421315E-02 + + 1.3359879E-02 + + 1.4448956E-02 + + 1.5939312E-02 + + 1.7946680E-02 + + 2.0638422E-02 + + + + 8.4199682E-03 + + 7.9132357E-03 + + 7.5289024E-03 + + 7.2000914E-03 + + 6.9952420E-03 + + 6.8508371E-03 + + 6.7532303E-03 + + 6.6833325E-03 + + 6.6177839E-03 + + 6.6622382E-03 + + 6.7105208E-03 + + 6.7909136E-03 + + 6.9136513E-03 + + 7.0763901E-03 + + 7.2891302E-03 + + 7.5133811E-03 + + 7.7798727E-03 + + 8.0728234E-03 + + 8.3719982E-03 + + 8.7418259E-03 + + 9.0827206E-03 + + 9.5593221E-03 + + 9.9725625E-03 + + 1.0449294E-02 + + 1.0985324E-02 + + 1.1627712E-02 + + 1.2345830E-02 + + 1.3279892E-02 + + 1.4416720E-02 + + 1.5897541E-02 + + 1.7949472E-02 + + 2.0670535E-02 + + + + 8.3808798E-03 + + 7.8549469E-03 + + 7.4548947E-03 + + 7.1338816E-03 + + 6.9441484E-03 + + 6.7971643E-03 + + 6.6772004E-03 + + 6.6034372E-03 + + 6.5689962E-03 + + 6.6291014E-03 + + 6.6629260E-03 + + 6.7229080E-03 + + 6.8650107E-03 + + 7.0400011E-03 + + 7.2281319E-03 + + 7.4627838E-03 + + 7.7395439E-03 + + 8.0343750E-03 + + 8.3395359E-03 + + 8.6563579E-03 + + 9.0736921E-03 + + 9.4975103E-03 + + 9.9294641E-03 + + 1.0370071E-02 + + 1.0916688E-02 + + 1.1554450E-02 + + 1.2270239E-02 + + 1.3181629E-02 + + 1.4291357E-02 + + 1.5819158E-02 + + 1.7859062E-02 + + 2.0611377E-02 + + + + 8.3161285E-03 + + 7.8077760E-03 + + 7.3959293E-03 + + 7.1090603E-03 + + 6.8980291E-03 + + 6.7587447E-03 + + 6.6504860E-03 + + 6.5749792E-03 + + 6.5613818E-03 + + 6.5416597E-03 + + 6.6015118E-03 + + 6.7070747E-03 + + 6.8290963E-03 + + 7.0031900E-03 + + 7.1846853E-03 + + 7.4125063E-03 + + 7.6750420E-03 + + 7.9813021E-03 + + 8.2806571E-03 + + 8.6141119E-03 + + 8.9704813E-03 + + 9.3882871E-03 + + 9.8368112E-03 + + 1.0298412E-02 + + 1.0822136E-02 + + 1.1413491E-02 + + 1.2145337E-02 + + 1.3048321E-02 + + 1.4114237E-02 + + 1.5706737E-02 + + 1.7654188E-02 + + 2.0500295E-02 + + + + 8.3192873E-03 + + 7.7697531E-03 + + 7.3819594E-03 + + 7.0971817E-03 + + 6.8836908E-03 + + 6.7313952E-03 + + 6.6234836E-03 + + 6.5684539E-03 + + 6.5572540E-03 + + 6.5781759E-03 + + 6.6163018E-03 + + 6.6999200E-03 + + 6.8297696E-03 + + 6.9564324E-03 + + 7.1572917E-03 + + 7.4359960E-03 + + 7.6444528E-03 + + 7.9171531E-03 + + 8.2232683E-03 + + 8.5632604E-03 + + 8.9017284E-03 + + 9.3233527E-03 + + 9.7185361E-03 + + 1.0167756E-02 + + 1.0690318E-02 + + 1.1287654E-02 + + 1.1955699E-02 + + 1.2797701E-02 + + 1.3915636E-02 + + 1.5417831E-02 + + 1.7413631E-02 + + 2.0132344E-02 + + + + 8.3402366E-03 + + 7.8783074E-03 + + 7.5306252E-03 + + 7.2763123E-03 + + 7.0815582E-03 + + 6.9389151E-03 + + 6.8574149E-03 + + 6.7982581E-03 + + 6.7740232E-03 + + 6.7825822E-03 + + 6.8155653E-03 + + 6.8794036E-03 + + 7.0109342E-03 + + 7.1732489E-03 + + 7.3504593E-03 + + 7.5193707E-03 + + 7.7780813E-03 + + 8.0399365E-03 + + 8.3133536E-03 + + 8.6051891E-03 + + 8.9148994E-03 + + 9.3197524E-03 + + 9.7034206E-03 + + 1.0115863E-02 + + 1.0600845E-02 + + 1.1142903E-02 + + 1.1780624E-02 + + 1.2556047E-02 + + 1.3579729E-02 + + 1.4891180E-02 + + 1.6672103E-02 + + 1.9078712E-02 + + + + 8.8088395E-03 + + 8.4507679E-03 + + 8.1708811E-03 + + 7.9801672E-03 + + 7.8027326E-03 + + 7.7405325E-03 + + 7.6178992E-03 + + 7.5796349E-03 + + 7.5729815E-03 + + 7.5709385E-03 + + 7.6313441E-03 + + 7.6551420E-03 + + 7.7197992E-03 + + 7.8770525E-03 + + 7.9879526E-03 + + 8.1371998E-03 + + 8.3342910E-03 + + 8.5247565E-03 + + 8.7962504E-03 + + 9.0806648E-03 + + 9.3313150E-03 + + 9.6858805E-03 + + 1.0017311E-02 + + 1.0396502E-02 + + 1.0810783E-02 + + 1.1308495E-02 + + 1.1873348E-02 + + 1.2517849E-02 + + 1.3292300E-02 + + 1.4204872E-02 + + 1.5413040E-02 + + 1.6865149E-02 + + + + 9.0402122E-03 + + 8.7656934E-03 + + 8.5418137E-03 + + 8.3375574E-03 + + 8.2205328E-03 + + 8.0954859E-03 + + 8.0140696E-03 + + 7.9720195E-03 + + 7.9707073E-03 + + 7.9496524E-03 + + 7.9729738E-03 + + 8.0286530E-03 + + 8.0949490E-03 + + 8.2040408E-03 + + 8.3348436E-03 + + 8.4638271E-03 + + 8.5967473E-03 + + 8.8120082E-03 + + 9.0406595E-03 + + 9.2571730E-03 + + 9.4741636E-03 + + 9.7864082E-03 + + 1.0105154E-02 + + 1.0426882E-02 + + 1.0815324E-02 + + 1.1263114E-02 + + 1.1718090E-02 + + 1.2294266E-02 + + 1.2954841E-02 + + 1.3732023E-02 + + 1.4787929E-02 + + 1.6057604E-02 + + + + 9.1615425E-03 + + 8.8847745E-03 + + 8.6630839E-03 + + 8.4765570E-03 + + 8.3309009E-03 + + 8.2383585E-03 + + 8.1836800E-03 + + 8.1120640E-03 + + 8.1261785E-03 + + 8.0708249E-03 + + 8.1480561E-03 + + 8.1784637E-03 + + 8.2346151E-03 + + 8.3274337E-03 + + 8.4147598E-03 + + 8.5448285E-03 + + 8.7091710E-03 + + 8.8843142E-03 + + 9.0949279E-03 + + 9.2936363E-03 + + 9.5389840E-03 + + 9.7958383E-03 + + 1.0086138E-02 + + 1.0400309E-02 + + 1.0727798E-02 + + 1.1115580E-02 + + 1.1556966E-02 + + 1.2062390E-02 + + 1.2723933E-02 + + 1.3461879E-02 + + 1.4407800E-02 + + 1.5727050E-02 + + + + 9.1377654E-03 + + 8.8751018E-03 + + 8.6821226E-03 + + 8.4858221E-03 + + 8.3554460E-03 + + 8.2804350E-03 + + 8.2266991E-03 + + 8.1758459E-03 + + 8.1472390E-03 + + 8.1455783E-03 + + 8.1349878E-03 + + 8.1925776E-03 + + 8.2538648E-03 + + 8.3264317E-03 + + 8.4644531E-03 + + 8.6009391E-03 + + 8.7147401E-03 + + 8.9206598E-03 + + 9.1064325E-03 + + 9.2780740E-03 + + 9.4991589E-03 + + 9.7677443E-03 + + 1.0040842E-02 + + 1.0310399E-02 + + 1.0637483E-02 + + 1.1002699E-02 + + 1.1454957E-02 + + 1.1928711E-02 + + 1.2543618E-02 + + 1.3315003E-02 + + 1.4311921E-02 + + 1.5626273E-02 + + + + 9.1477964E-03 + + 8.8569131E-03 + + 8.6480911E-03 + + 8.4806682E-03 + + 8.3743826E-03 + + 8.2509863E-03 + + 8.2112855E-03 + + 8.1583830E-03 + + 8.1332616E-03 + + 8.1132990E-03 + + 8.1560439E-03 + + 8.1779291E-03 + + 8.2488074E-03 + + 8.3305803E-03 + + 8.4259072E-03 + + 8.5822114E-03 + + 8.7017305E-03 + + 8.8788944E-03 + + 9.0655429E-03 + + 9.2582475E-03 + + 9.4805275E-03 + + 9.7278007E-03 + + 9.9553998E-03 + + 1.0269546E-02 + + 1.0586672E-02 + + 1.0921006E-02 + + 1.1328973E-02 + + 1.1802691E-02 + + 1.2450626E-02 + + 1.3255698E-02 + + 1.4251456E-02 + + 1.5657809E-02 + + + + 9.0883340E-03 + + 8.8433984E-03 + + 8.6289182E-03 + + 8.4439323E-03 + + 8.3093188E-03 + + 8.2332632E-03 + + 8.1799745E-03 + + 8.1280446E-03 + + 8.0845653E-03 + + 8.1128997E-03 + + 8.1014997E-03 + + 8.1603558E-03 + + 8.2532133E-03 + + 8.3021938E-03 + + 8.4337253E-03 + + 8.5567067E-03 + + 8.6772027E-03 + + 8.8890649E-03 + + 9.0381936E-03 + + 9.2474046E-03 + + 9.4507499E-03 + + 9.7047326E-03 + + 9.9402566E-03 + + 1.0205441E-02 + + 1.0504990E-02 + + 1.0882385E-02 + + 1.1274627E-02 + + 1.1783289E-02 + + 1.2386232E-02 + + 1.3164784E-02 + + 1.4270026E-02 + + 1.5728107E-02 + + + + 9.0807708E-03 + + 8.8015024E-03 + + 8.5814276E-03 + + 8.4248165E-03 + + 8.2946254E-03 + + 8.2126919E-03 + + 8.1370075E-03 + + 8.0715301E-03 + + 8.0815288E-03 + + 8.0835771E-03 + + 8.1054492E-03 + + 8.1477700E-03 + + 8.2076231E-03 + + 8.2545960E-03 + + 8.4024583E-03 + + 8.5599026E-03 + + 8.6575633E-03 + + 8.8233051E-03 + + 9.0064404E-03 + + 9.2354725E-03 + + 9.4557209E-03 + + 9.6788857E-03 + + 9.8947250E-03 + + 1.0174410E-02 + + 1.0498117E-02 + + 1.0823664E-02 + + 1.1218924E-02 + + 1.1737640E-02 + + 1.2318916E-02 + + 1.3224386E-02 + + 1.4293237E-02 + + 1.5742419E-02 + + + + 9.0662532E-03 + + 8.7875937E-03 + + 8.5608939E-03 + + 8.3990606E-03 + + 8.2689578E-03 + + 8.1502455E-03 + + 8.0945876E-03 + + 8.0499873E-03 + + 8.0046473E-03 + + 8.0312744E-03 + + 8.0845285E-03 + + 8.0864516E-03 + + 8.1794243E-03 + + 8.2886692E-03 + + 8.3753921E-03 + + 8.5095259E-03 + + 8.6235784E-03 + + 8.8149234E-03 + + 9.0064533E-03 + + 9.1933604E-03 + + 9.4366281E-03 + + 9.6340012E-03 + + 9.8577424E-03 + + 1.0162178E-02 + + 1.0489950E-02 + + 1.0830480E-02 + + 1.1216758E-02 + + 1.1718234E-02 + + 1.2372964E-02 + + 1.3217004E-02 + + 1.4300060E-02 + + 1.5874384E-02 + + + + 9.0385593E-03 + + 8.7911739E-03 + + 8.5398942E-03 + + 8.3506015E-03 + + 8.2438909E-03 + + 8.1613890E-03 + + 8.0460870E-03 + + 8.0305903E-03 + + 8.0028889E-03 + + 8.0232434E-03 + + 8.0276194E-03 + + 8.1064278E-03 + + 8.1288298E-03 + + 8.2312446E-03 + + 8.3452218E-03 + + 8.4759402E-03 + + 8.6203085E-03 + + 8.7737100E-03 + + 8.9852040E-03 + + 9.1640184E-03 + + 9.3706145E-03 + + 9.6371098E-03 + + 9.8385671E-03 + + 1.0187163E-02 + + 1.0453859E-02 + + 1.0791575E-02 + + 1.1239213E-02 + + 1.1704998E-02 + + 1.2413952E-02 + + 1.3197580E-02 + + 1.4388298E-02 + + 1.5983777E-02 + + + + 9.0381972E-03 + + 8.7249421E-03 + + 8.5299403E-03 + + 8.3296610E-03 + + 8.1906552E-03 + + 8.0856852E-03 + + 8.0084895E-03 + + 7.9976213E-03 + + 7.9681027E-03 + + 7.9954298E-03 + + 8.0300023E-03 + + 8.0899341E-03 + + 8.1518784E-03 + + 8.2341280E-03 + + 8.3101161E-03 + + 8.4644180E-03 + + 8.6281121E-03 + + 8.7991411E-03 + + 8.9588100E-03 + + 9.1981791E-03 + + 9.3869641E-03 + + 9.6145258E-03 + + 9.9132005E-03 + + 1.0156461E-02 + + 1.0475933E-02 + + 1.0810611E-02 + + 1.1229999E-02 + + 1.1691965E-02 + + 1.2394061E-02 + + 1.3229214E-02 + + 1.4413895E-02 + + 1.6023151E-02 + + + + 8.9900779E-03 + + 8.7242101E-03 + + 8.4738461E-03 + + 8.3135886E-03 + + 8.1704723E-03 + + 8.0916227E-03 + + 8.0054050E-03 + + 7.9890825E-03 + + 7.9822260E-03 + + 7.9494275E-03 + + 8.0343148E-03 + + 8.0498187E-03 + + 8.1090198E-03 + + 8.2328458E-03 + + 8.3082672E-03 + + 8.4585469E-03 + + 8.6087756E-03 + + 8.8041342E-03 + + 8.9504229E-03 + + 9.1682953E-03 + + 9.3389911E-03 + + 9.6352014E-03 + + 9.8666333E-03 + + 1.0149489E-02 + + 1.0464017E-02 + + 1.0804437E-02 + + 1.1200629E-02 + + 1.1730829E-02 + + 1.2396625E-02 + + 1.3311556E-02 + + 1.4467897E-02 + + 1.6069551E-02 + + + + 9.0103050E-03 + + 8.7325667E-03 + + 8.5095225E-03 + + 8.3198922E-03 + + 8.1828827E-03 + + 8.0755069E-03 + + 7.9981914E-03 + + 7.9413633E-03 + + 7.9823990E-03 + + 7.9246563E-03 + + 7.9815454E-03 + + 8.0345931E-03 + + 8.0725191E-03 + + 8.2341012E-03 + + 8.3041608E-03 + + 8.3831836E-03 + + 8.6106789E-03 + + 8.7518346E-03 + + 8.9641474E-03 + + 9.0978032E-03 + + 9.3592003E-03 + + 9.5996223E-03 + + 9.9237621E-03 + + 1.0175830E-02 + + 1.0455459E-02 + + 1.0836548E-02 + + 1.1244650E-02 + + 1.1760188E-02 + + 1.2384627E-02 + + 1.3346254E-02 + + 1.4480133E-02 + + 1.6136563E-02 + + + + 9.0228604E-03 + + 8.6804828E-03 + + 8.4614534E-03 + + 8.2426545E-03 + + 8.1392111E-03 + + 8.0814949E-03 + + 7.9912702E-03 + + 7.9974952E-03 + + 7.9421615E-03 + + 7.9138029E-03 + + 7.9451587E-03 + + 8.0340001E-03 + + 8.0954821E-03 + + 8.1764077E-03 + + 8.3095930E-03 + + 8.4157262E-03 + + 8.6168490E-03 + + 8.7576427E-03 + + 8.9333274E-03 + + 9.1895534E-03 + + 9.3857577E-03 + + 9.6418300E-03 + + 9.8564788E-03 + + 1.0150132E-02 + + 1.0487898E-02 + + 1.0870470E-02 + + 1.1271947E-02 + + 1.1778020E-02 + + 1.2502739E-02 + + 1.3339816E-02 + + 1.4543555E-02 + + 1.6130789E-02 + + + + 9.0622003E-03 + + 8.7178702E-03 + + 8.4596226E-03 + + 8.2747360E-03 + + 8.1644825E-03 + + 8.0165944E-03 + + 7.9932716E-03 + + 7.9360246E-03 + + 7.9425974E-03 + + 7.9418553E-03 + + 7.9541528E-03 + + 8.0182907E-03 + + 8.0812624E-03 + + 8.0915456E-03 + + 8.2908500E-03 + + 8.4101146E-03 + + 8.5246086E-03 + + 8.7454336E-03 + + 8.9623361E-03 + + 9.1273983E-03 + + 9.3738784E-03 + + 9.6552369E-03 + + 9.8941901E-03 + + 1.0161555E-02 + + 1.0501008E-02 + + 1.0866011E-02 + + 1.1314128E-02 + + 1.1790338E-02 + + 1.2447300E-02 + + 1.3396964E-02 + + 1.4531939E-02 + + 1.6115773E-02 + + + + 8.9679455E-03 + + 8.7523346E-03 + + 8.4194831E-03 + + 8.2562897E-03 + + 8.2501744E-03 + + 8.0453964E-03 + + 7.9636250E-03 + + 7.9278064E-03 + + 7.9395130E-03 + + 7.8808053E-03 + + 7.8942591E-03 + + 7.9779525E-03 + + 8.1203535E-03 + + 8.1780129E-03 + + 8.2976996E-03 + + 8.3927501E-03 + + 8.5693973E-03 + + 8.7760972E-03 + + 8.9639268E-03 + + 9.1777904E-03 + + 9.3233365E-03 + + 9.6757573E-03 + + 9.8043550E-03 + + 1.0142972E-02 + + 1.0460099E-02 + + 1.0900581E-02 + + 1.1166513E-02 + + 1.1798843E-02 + + 1.2569032E-02 + + 1.3335377E-02 + + 1.4567713E-02 + + 1.6266042E-02 + + + + 9.0235493E-03 + + 8.7359753E-03 + + 8.4400355E-03 + + 8.2314136E-03 + + 8.1409585E-03 + + 8.0562549E-03 + + 8.0165174E-03 + + 7.9631855E-03 + + 7.9527283E-03 + + 7.9590026E-03 + + 7.9558654E-03 + + 7.9982172E-03 + + 7.9903743E-03 + + 8.1472328E-03 + + 8.3527175E-03 + + 8.3019999E-03 + + 8.5775481E-03 + + 8.8353190E-03 + + 8.9853803E-03 + + 9.0836784E-03 + + 9.4481131E-03 + + 9.5401367E-03 + + 9.8920227E-03 + + 1.0186917E-02 + + 1.0500634E-02 + + 1.0833697E-02 + + 1.1379042E-02 + + 1.1793671E-02 + + 1.2553389E-02 + + 1.3369577E-02 + + 1.4595165E-02 + + 1.6031466E-02 + + + 1.0000416E+00 + + + 1.0000513E+00 + + + 1.0000397E+00 + + + 1.0000409E+00 + + + 1.0000455E+00 + + + 1.0000417E+00 + + + 1.0000452E+00 + + + 1.0000431E+00 + + + 1.0000455E+00 + + + 1.0000451E+00 + + + 1.0000445E+00 + + + 1.0000482E+00 + + + 1.0000507E+00 + + + 1.0000542E+00 + + + 1.0000545E+00 + + + 1.0000461E+00 + + + 1.0000114E+00 + + + 1.0000112E+00 + + + 1.0000195E+00 + + + 1.0000216E+00 + + + 1.0000279E+00 + + + 1.0000307E+00 + + + 1.0000302E+00 + + + 1.0000313E+00 + + + 1.0000334E+00 + + + 1.0000309E+00 + + + 1.0000325E+00 + + + 1.0000318E+00 + + + 1.0000346E+00 + + + 1.0000335E+00 + + + 1.0000285E+00 + + + 1.0000358E+00 + + + + + lwtr_ang_mu.71c + lwtr_ang_mu.71c + 2.5300000E-08 + 32 + false + 32 + 1 + angle + histogram + + 8.3129229E-01 + + 8.3203829E-01 + + 8.3332424E-01 + + 8.3539719E-01 + + 8.3799288E-01 + + 8.4156597E-01 + + 8.4594074E-01 + + 8.5122773E-01 + + 8.5788274E-01 + + 8.6633387E-01 + + 8.7719846E-01 + + 8.9195077E-01 + + 9.1326621E-01 + + 9.4469159E-01 + + 9.9368716E-01 + + 1.0616854E+00 + + 1.0982938E+00 + + 1.0997200E+00 + + 1.0855410E+00 + + 1.0676695E+00 + + 1.0508172E+00 + + 1.0369337E+00 + + 1.0255762E+00 + + 1.0162841E+00 + + 1.0086633E+00 + + 1.0025783E+00 + + 9.9737297E-01 + + 9.9326768E-01 + + 9.9030852E-01 + + 9.8792719E-01 + + 9.8610453E-01 + + 9.8540665E-01 + + + 7.7368065E-03 + + 7.7519393E-03 + + 7.7819449E-03 + + 7.8285240E-03 + + 7.8881877E-03 + + 7.9652685E-03 + + 8.0588251E-03 + + 8.1724303E-03 + + 8.3079937E-03 + + 8.4749946E-03 + + 8.6811506E-03 + + 8.9456784E-03 + + 9.3049336E-03 + + 9.8025199E-03 + + 1.0529992E-02 + + 1.1498571E-02 + + 1.2065971E-02 + + 1.2168395E-02 + + 1.2053690E-02 + + 1.1870414E-02 + + 1.1678759E-02 + + 1.1516371E-02 + + 1.1377145E-02 + + 1.1262809E-02 + + 1.1166687E-02 + + 1.1090107E-02 + + 1.1022668E-02 + + 1.0968772E-02 + + 1.0931381E-02 + + 1.0898236E-02 + + 1.0872094E-02 + + 1.0866295E-02 + + + 5.0690953E-03 + + 8.8284325E-03 + + 9.0078067E-03 + + 8.3473577E-03 + + 8.6118779E-03 + + 8.5008333E-03 + + 9.0278160E-03 + + 9.0320024E-03 + + 9.3778370E-03 + + 9.6052477E-03 + + 9.9703821E-03 + + 1.0342612E-02 + + 1.0646441E-02 + + 1.1197549E-02 + + 1.1382812E-02 + + 1.2469275E-02 + + 1.3368771E-02 + + 1.7162734E-02 + + 2.0335842E-02 + + 2.4108518E-02 + + 2.7585384E-02 + + 3.1409361E-02 + + 3.5211839E-02 + + 3.9132244E-02 + + 4.2882641E-02 + + 4.7206070E-02 + + 5.1012876E-02 + + 5.6053305E-02 + + 5.9624825E-02 + + 6.4222850E-02 + + 7.1113785E-02 + + 7.1863425E-02 + + + + 5.0668773E-03 + + 8.8623444E-03 + + 8.9736897E-03 + + 8.4193826E-03 + + 8.6200366E-03 + + 8.5331711E-03 + + 9.0253536E-03 + + 9.0024868E-03 + + 9.3587966E-03 + + 9.6337679E-03 + + 9.9001048E-03 + + 1.0351369E-02 + + 1.0700823E-02 + + 1.1172796E-02 + + 1.1445656E-02 + + 1.2427412E-02 + + 1.3375674E-02 + + 1.7104580E-02 + + 2.0306601E-02 + + 2.4056263E-02 + + 2.7577305E-02 + + 3.1469932E-02 + + 3.5286392E-02 + + 3.9182103E-02 + + 4.2943152E-02 + + 4.7360483E-02 + + 5.1005109E-02 + + 5.6171187E-02 + + 5.9667108E-02 + + 6.4232789E-02 + + 7.1121280E-02 + + 7.1846306E-02 + + + + 5.0585819E-03 + + 8.8480548E-03 + + 9.0578095E-03 + + 8.4267843E-03 + + 8.6269032E-03 + + 8.5421136E-03 + + 9.0526837E-03 + + 9.0736449E-03 + + 9.4245294E-03 + + 9.6888060E-03 + + 9.9567766E-03 + + 1.0375670E-02 + + 1.0725481E-02 + + 1.1243110E-02 + + 1.1484936E-02 + + 1.2521826E-02 + + 1.3438046E-02 + + 1.7151864E-02 + + 2.0343472E-02 + + 2.4110251E-02 + + 2.7659343E-02 + + 3.1511614E-02 + + 3.5309076E-02 + + 3.9196826E-02 + + 4.3043312E-02 + + 4.7345488E-02 + + 5.1124137E-02 + + 5.6080519E-02 + + 5.9764341E-02 + + 6.4292466E-02 + + 7.1165161E-02 + + 7.1900319E-02 + + + + 5.0739533E-03 + + 8.8878014E-03 + + 9.0739746E-03 + + 8.4571184E-03 + + 8.6763187E-03 + + 8.5845734E-03 + + 9.0893274E-03 + + 9.1072493E-03 + + 9.4607350E-03 + + 9.7370233E-03 + + 1.0006337E-02 + + 1.0437546E-02 + + 1.0767301E-02 + + 1.1309766E-02 + + 1.1552543E-02 + + 1.2572863E-02 + + 1.3499221E-02 + + 1.7217227E-02 + + 2.0383163E-02 + + 2.4178222E-02 + + 2.7731888E-02 + + 3.1561770E-02 + + 3.5431417E-02 + + 3.9298803E-02 + + 4.3075219E-02 + + 4.7440921E-02 + + 5.1196928E-02 + + 5.6281715E-02 + + 5.9863517E-02 + + 6.4363763E-02 + + 7.1290039E-02 + + 7.1984722E-02 + + + + 5.0933569E-03 + + 8.9571748E-03 + + 9.1350789E-03 + + 8.5026806E-03 + + 8.7154122E-03 + + 8.6182850E-03 + + 9.1387403E-03 + + 9.1503576E-03 + + 9.5054271E-03 + + 9.8046510E-03 + + 1.0063015E-02 + + 1.0512898E-02 + + 1.0850976E-02 + + 1.1369711E-02 + + 1.1602210E-02 + + 1.2644534E-02 + + 1.3573331E-02 + + 1.7276147E-02 + + 2.0485160E-02 + + 2.4267827E-02 + + 2.7795345E-02 + + 3.1650606E-02 + + 3.5516413E-02 + + 3.9384282E-02 + + 4.3193261E-02 + + 4.7565933E-02 + + 5.1283045E-02 + + 5.6364736E-02 + + 5.9999740E-02 + + 6.4499325E-02 + + 7.1460960E-02 + + 7.2121578E-02 + + + + 5.1073627E-03 + + 9.0205393E-03 + + 9.1796662E-03 + + 8.5645656E-03 + + 8.7990379E-03 + + 8.7021912E-03 + + 9.2162069E-03 + + 9.2138958E-03 + + 9.5751521E-03 + + 9.8799162E-03 + + 1.0149817E-02 + + 1.0595940E-02 + + 1.0925157E-02 + + 1.1451227E-02 + + 1.1697295E-02 + + 1.2747125E-02 + + 1.3679064E-02 + + 1.7388258E-02 + + 2.0589616E-02 + + 2.4369432E-02 + + 2.7920510E-02 + + 3.1792267E-02 + + 3.5621878E-02 + + 3.9491661E-02 + + 4.3278532E-02 + + 4.7679951E-02 + + 5.1436615E-02 + + 5.6547886E-02 + + 6.0145268E-02 + + 6.4662138E-02 + + 7.1681806E-02 + + 7.2326892E-02 + + + + 5.1442091E-03 + + 9.0852521E-03 + + 9.2735609E-03 + + 8.6388628E-03 + + 8.8708740E-03 + + 8.7690933E-03 + + 9.2934119E-03 + + 9.3186161E-03 + + 9.6592707E-03 + + 9.9678700E-03 + + 1.0236163E-02 + + 1.0694734E-02 + + 1.1025890E-02 + + 1.1566030E-02 + + 1.1820104E-02 + + 1.2881706E-02 + + 1.3817409E-02 + + 1.7525018E-02 + + 2.0707299E-02 + + 2.4504049E-02 + + 2.8056398E-02 + + 3.1942086E-02 + + 3.5781215E-02 + + 3.9676732E-02 + + 4.3508487E-02 + + 4.7899374E-02 + + 5.1653601E-02 + + 5.6724194E-02 + + 6.0363176E-02 + + 6.4884496E-02 + + 7.1995314E-02 + + 7.2586420E-02 + + + + 5.1859947E-03 + + 9.1884111E-03 + + 9.3553722E-03 + + 8.7326674E-03 + + 8.9615831E-03 + + 8.8682756E-03 + + 9.3981872E-03 + + 9.4022342E-03 + + 9.7833217E-03 + + 1.0082626E-02 + + 1.0346345E-02 + + 1.0823172E-02 + + 1.1169852E-02 + + 1.1713674E-02 + + 1.1957780E-02 + + 1.3030310E-02 + + 1.3974055E-02 + + 1.7679518E-02 + + 2.0873339E-02 + + 2.4674002E-02 + + 2.8233633E-02 + + 3.2098518E-02 + + 3.5967409E-02 + + 3.9901149E-02 + + 4.3708564E-02 + + 4.8163155E-02 + + 5.1864987E-02 + + 5.6965609E-02 + + 6.0598955E-02 + + 6.5237827E-02 + + 7.2317026E-02 + + 7.2846315E-02 + + + + 5.2179276E-03 + + 9.2840460E-03 + + 9.4689692E-03 + + 8.8426310E-03 + + 9.0784020E-03 + + 8.9710561E-03 + + 9.5058449E-03 + + 9.5242525E-03 + + 9.8985438E-03 + + 1.0230104E-02 + + 1.0489612E-02 + + 1.0966586E-02 + + 1.1313882E-02 + + 1.1867051E-02 + + 1.2127596E-02 + + 1.3217267E-02 + + 1.4158489E-02 + + 1.7874095E-02 + + 2.1071639E-02 + + 2.4904630E-02 + + 2.8444961E-02 + + 3.2350782E-02 + + 3.6218293E-02 + + 4.0127228E-02 + + 4.3958446E-02 + + 4.8412743E-02 + + 5.2176893E-02 + + 5.7339635E-02 + + 6.0969984E-02 + + 6.5571180E-02 + + 7.2752295E-02 + + 7.3254466E-02 + + + + 5.2716442E-03 + + 9.4281164E-03 + + 9.6132026E-03 + + 8.9742401E-03 + + 9.2100433E-03 + + 9.1094424E-03 + + 9.6671272E-03 + + 9.6893875E-03 + + 1.0054424E-02 + + 1.0384782E-02 + + 1.0663088E-02 + + 1.1145331E-02 + + 1.1502660E-02 + + 1.2069220E-02 + + 1.2330654E-02 + + 1.3451168E-02 + + 1.4376732E-02 + + 1.8119744E-02 + + 2.1312268E-02 + + 2.5156150E-02 + + 2.8702855E-02 + + 3.2612605E-02 + + 3.6519082E-02 + + 4.0492357E-02 + + 4.4282144E-02 + + 4.8807320E-02 + + 5.2599863E-02 + + 5.7759050E-02 + + 6.1395630E-02 + + 6.6046712E-02 + + 7.3333461E-02 + + 7.3753560E-02 + + + + 5.3238344E-03 + + 9.5970913E-03 + + 9.7854600E-03 + + 9.1224140E-03 + + 9.3984166E-03 + + 9.2843910E-03 + + 9.8479041E-03 + + 9.8775712E-03 + + 1.0248815E-02 + + 1.0588076E-02 + + 1.0866467E-02 + + 1.1377201E-02 + + 1.1745016E-02 + + 1.2324752E-02 + + 1.2591933E-02 + + 1.3738942E-02 + + 1.4661945E-02 + + 1.8420789E-02 + + 2.1616210E-02 + + 2.5483933E-02 + + 2.9053296E-02 + + 3.3018657E-02 + + 3.6902567E-02 + + 4.0918920E-02 + + 4.4768920E-02 + + 4.9324206E-02 + + 5.3104469E-02 + + 5.8346792E-02 + + 6.2007342E-02 + + 6.6700912E-02 + + 7.4111114E-02 + + 7.4471661E-02 + + + + 5.4122500E-03 + + 9.8114809E-03 + + 9.9988824E-03 + + 9.3373137E-03 + + 9.6193550E-03 + + 9.5022652E-03 + + 1.0091629E-02 + + 1.0102292E-02 + + 1.0507181E-02 + + 1.0845994E-02 + + 1.1145961E-02 + + 1.1663724E-02 + + 1.2054675E-02 + + 1.2641320E-02 + + 1.2925378E-02 + + 1.4109631E-02 + + 1.5019788E-02 + + 1.8801255E-02 + + 2.2007215E-02 + + 2.5928762E-02 + + 2.9530128E-02 + + 3.3525210E-02 + + 3.7488914E-02 + + 4.1518826E-02 + + 4.5409731E-02 + + 5.0007891E-02 + + 5.3821041E-02 + + 5.9155539E-02 + + 6.2863258E-02 + + 6.7589912E-02 + + 7.5149452E-02 + + 7.5483624E-02 + + + + 5.5291381E-03 + + 1.0106920E-02 + + 1.0289680E-02 + + 9.6380580E-03 + + 9.9265277E-03 + + 9.8058620E-03 + + 1.0411771E-02 + + 1.0436031E-02 + + 1.0855919E-02 + + 1.1210324E-02 + + 1.1523264E-02 + + 1.2064653E-02 + + 1.2477020E-02 + + 1.3073068E-02 + + 1.3372106E-02 + + 1.4596687E-02 + + 1.5522669E-02 + + 1.9346144E-02 + + 2.2590235E-02 + + 2.6577078E-02 + + 3.0198519E-02 + + 3.4263702E-02 + + 3.8312940E-02 + + 4.2417033E-02 + + 4.6331184E-02 + + 5.1039786E-02 + + 5.4923952E-02 + + 6.0373272E-02 + + 6.4126997E-02 + + 6.8933518E-02 + + 7.6721947E-02 + + 7.6881324E-02 + + + + 5.7051926E-03 + + 1.0534340E-02 + + 1.0734999E-02 + + 1.0047973E-02 + + 1.0355258E-02 + + 1.0218464E-02 + + 1.0877782E-02 + + 1.0922582E-02 + + 1.1349348E-02 + + 1.1717445E-02 + + 1.2048634E-02 + + 1.2622834E-02 + + 1.3044209E-02 + + 1.3697572E-02 + + 1.4007429E-02 + + 1.5297796E-02 + + 1.6229092E-02 + + 2.0130646E-02 + + 2.3419720E-02 + + 2.7507372E-02 + + 3.1241243E-02 + + 3.5411821E-02 + + 3.9541855E-02 + + 4.3748213E-02 + + 4.7789294E-02 + + 5.2605069E-02 + + 5.6580575E-02 + + 6.2218120E-02 + + 6.6002923E-02 + + 7.0996802E-02 + + 7.9059610E-02 + + 7.9125302E-02 + + + + 5.9798621E-03 + + 1.1178770E-02 + + 1.1398960E-02 + + 1.0686315E-02 + + 1.1015007E-02 + + 1.0888426E-02 + + 1.1578312E-02 + + 1.1599595E-02 + + 1.2096215E-02 + + 1.2485774E-02 + + 1.2847301E-02 + + 1.3454293E-02 + + 1.3910042E-02 + + 1.4624946E-02 + + 1.4951480E-02 + + 1.6345303E-02 + + 1.7294576E-02 + + 2.1305917E-02 + + 2.4724135E-02 + + 2.8975117E-02 + + 3.2851405E-02 + + 3.7179235E-02 + + 4.1473071E-02 + + 4.5870569E-02 + + 5.0061541E-02 + + 5.5118747E-02 + + 5.9217709E-02 + + 6.5121185E-02 + + 6.9056004E-02 + + 7.4268036E-02 + + 8.2796332E-02 + + 8.2707329E-02 + + + + 6.3814382E-03 + + 1.2092503E-02 + + 1.2307256E-02 + + 1.1538828E-02 + + 1.1908080E-02 + + 1.1757836E-02 + + 1.2534374E-02 + + 1.2563508E-02 + + 1.3099926E-02 + + 1.3526120E-02 + + 1.3927022E-02 + + 1.4604411E-02 + + 1.5096848E-02 + + 1.5885767E-02 + + 1.6230507E-02 + + 1.7756050E-02 + + 1.8747181E-02 + + 2.2956423E-02 + + 2.6549953E-02 + + 3.1007445E-02 + + 3.5079178E-02 + + 3.9663485E-02 + + 4.4205438E-02 + + 4.8827182E-02 + + 5.3252335E-02 + + 5.8585422E-02 + + 6.2916830E-02 + + 6.9202743E-02 + + 7.3345048E-02 + + 7.8865458E-02 + + 8.8060504E-02 + + 8.7720181E-02 + + + + 6.5814203E-03 + + 1.2589556E-02 + + 1.2831098E-02 + + 1.2021990E-02 + + 1.2420962E-02 + + 1.2274328E-02 + + 1.3072229E-02 + + 1.3125790E-02 + + 1.3684984E-02 + + 1.4120320E-02 + + 1.4541810E-02 + + 1.5241834E-02 + + 1.5792664E-02 + + 1.6581300E-02 + + 1.6973815E-02 + + 1.8580511E-02 + + 1.9572617E-02 + + 2.3865583E-02 + + 2.7520381E-02 + + 3.2101383E-02 + + 3.6273771E-02 + + 4.0991031E-02 + + 4.5628107E-02 + + 5.0375712E-02 + + 5.4927552E-02 + + 6.0463390E-02 + + 6.4846891E-02 + + 7.1361573E-02 + + 7.5574981E-02 + + 8.1252683E-02 + + 9.0772914E-02 + + 9.0305344E-02 + + + + 6.5954047E-03 + + 1.2649872E-02 + + 1.2894758E-02 + + 1.2088299E-02 + + 1.2500706E-02 + + 1.2323868E-02 + + 1.3135140E-02 + + 1.3183877E-02 + + 1.3757540E-02 + + 1.4215358E-02 + + 1.4630076E-02 + + 1.5341576E-02 + + 1.5875377E-02 + + 1.6697400E-02 + + 1.7075964E-02 + + 1.8685615E-02 + + 1.9688554E-02 + + 2.3959638E-02 + + 2.7582865E-02 + + 3.2154359E-02 + + 3.6319478E-02 + + 4.0991674E-02 + + 4.5627244E-02 + + 5.0390376E-02 + + 5.4901681E-02 + + 6.0435636E-02 + + 6.4805706E-02 + + 7.1338882E-02 + + 7.5494665E-02 + + 8.1186566E-02 + + 9.0719563E-02 + + 9.0193680E-02 + + + + 6.5336047E-03 + + 1.2512090E-02 + + 1.2764479E-02 + + 1.1984145E-02 + + 1.2375802E-02 + + 1.2210337E-02 + + 1.3005945E-02 + + 1.3053548E-02 + + 1.3626485E-02 + + 1.4068961E-02 + + 1.4494598E-02 + + 1.5200428E-02 + + 1.5722617E-02 + + 1.6508783E-02 + + 1.6910525E-02 + + 1.8489314E-02 + + 1.9473998E-02 + + 2.3688731E-02 + + 2.7256893E-02 + + 3.1731269E-02 + + 3.5822276E-02 + + 4.0457390E-02 + + 4.5020879E-02 + + 4.9721896E-02 + + 5.4161674E-02 + + 5.9588663E-02 + + 6.3895979E-02 + + 7.0351683E-02 + + 7.4478980E-02 + + 8.0093110E-02 + + 8.9495166E-02 + + 8.8945256E-02 + + + + 6.4468824E-03 + + 1.2344191E-02 + + 1.2577769E-02 + + 1.1799198E-02 + + 1.2185250E-02 + + 1.2024671E-02 + + 1.2823561E-02 + + 1.2867050E-02 + + 1.3414223E-02 + + 1.3868383E-02 + + 1.4274902E-02 + + 1.4957665E-02 + + 1.5477639E-02 + + 1.6280478E-02 + + 1.6660201E-02 + + 1.8210099E-02 + + 1.9176459E-02 + + 2.3317865E-02 + + 2.6814611E-02 + + 3.1226187E-02 + + 3.5261695E-02 + + 3.9778054E-02 + + 4.4282066E-02 + + 4.8849080E-02 + + 5.3188035E-02 + + 5.8562223E-02 + + 6.2824222E-02 + + 6.9127893E-02 + + 7.3188187E-02 + + 7.8690046E-02 + + 8.7933862E-02 + + 8.7463314E-02 + + + + 6.3504172E-03 + + 1.2150642E-02 + + 1.2387727E-02 + + 1.1620660E-02 + + 1.2007755E-02 + + 1.1841239E-02 + + 1.2616226E-02 + + 1.2659354E-02 + + 1.3210608E-02 + + 1.3647237E-02 + + 1.4056090E-02 + + 1.4738601E-02 + + 1.5248667E-02 + + 1.6022604E-02 + + 1.6399027E-02 + + 1.7924821E-02 + + 1.8865800E-02 + + 2.2962104E-02 + + 2.6396869E-02 + + 3.0722714E-02 + + 3.4680261E-02 + + 3.9148700E-02 + + 4.3549586E-02 + + 4.8057389E-02 + + 5.2369847E-02 + + 5.7634643E-02 + + 6.1797568E-02 + + 6.8018235E-02 + + 7.1991375E-02 + + 7.7432633E-02 + + 8.6562066E-02 + + 8.6040544E-02 + + + + 6.2807225E-03 + + 1.2005102E-02 + + 1.2236833E-02 + + 1.1484849E-02 + + 1.1844265E-02 + + 1.1694745E-02 + + 1.2469442E-02 + + 1.2503258E-02 + + 1.3035750E-02 + + 1.3456731E-02 + + 1.3869786E-02 + + 1.4538788E-02 + + 1.5043345E-02 + + 1.5804904E-02 + + 1.6173155E-02 + + 1.7678967E-02 + + 1.8617817E-02 + + 2.2640680E-02 + + 2.6043512E-02 + + 3.0350793E-02 + + 3.4235767E-02 + + 3.8635112E-02 + + 4.3006209E-02 + + 4.7438737E-02 + + 5.1680206E-02 + + 5.6869882E-02 + + 6.0948428E-02 + + 6.7112720E-02 + + 7.1046470E-02 + + 7.6389984E-02 + + 8.5416908E-02 + + 8.4912400E-02 + + + + 6.2384011E-03 + + 1.1883626E-02 + + 1.2102819E-02 + + 1.1362792E-02 + + 1.1727085E-02 + + 1.1577991E-02 + + 1.2321572E-02 + + 1.2368887E-02 + + 1.2886627E-02 + + 1.3323476E-02 + + 1.3712662E-02 + + 1.4368905E-02 + + 1.4867001E-02 + + 1.5621404E-02 + + 1.6001770E-02 + + 1.7495457E-02 + + 1.8410484E-02 + + 2.2403739E-02 + + 2.5792442E-02 + + 3.0003874E-02 + + 3.3860219E-02 + + 3.8194472E-02 + + 4.2513447E-02 + + 4.6944801E-02 + + 5.1102508E-02 + + 5.6230364E-02 + + 6.0282905E-02 + + 6.6396185E-02 + + 7.0267237E-02 + + 7.5567209E-02 + + 8.4430462E-02 + + 8.3984117E-02 + + + + 6.1845926E-03 + + 1.1774745E-02 + + 1.2008907E-02 + + 1.1282463E-02 + + 1.1630642E-02 + + 1.1486008E-02 + + 1.2212483E-02 + + 1.2255192E-02 + + 1.2777462E-02 + + 1.3204562E-02 + + 1.3600398E-02 + + 1.4255316E-02 + + 1.4736561E-02 + + 1.5470029E-02 + + 1.5845176E-02 + + 1.7313807E-02 + + 1.8247178E-02 + + 2.2230316E-02 + + 2.5531152E-02 + + 2.9731972E-02 + + 3.3558284E-02 + + 3.7872884E-02 + + 4.2109048E-02 + + 4.6517240E-02 + + 5.0645413E-02 + + 5.5683251E-02 + + 5.9750465E-02 + + 6.5766931E-02 + + 6.9579667E-02 + + 7.4872290E-02 + + 8.3643239E-02 + + 8.3206968E-02 + + + + 6.1719734E-03 + + 1.1719545E-02 + + 1.1917909E-02 + + 1.1189341E-02 + + 1.1548606E-02 + + 1.1416064E-02 + + 1.2129643E-02 + + 1.2168083E-02 + + 1.2694983E-02 + + 1.3100793E-02 + + 1.3481593E-02 + + 1.4146417E-02 + + 1.4630389E-02 + + 1.5367839E-02 + + 1.5730917E-02 + + 1.7184516E-02 + + 1.8089440E-02 + + 2.2023196E-02 + + 2.5336832E-02 + + 2.9501303E-02 + + 3.3286048E-02 + + 3.7579302E-02 + + 4.1818920E-02 + + 4.6160226E-02 + + 5.0276169E-02 + + 5.5322377E-02 + + 5.9292479E-02 + + 6.5292838E-02 + + 6.9134443E-02 + + 7.4296625E-02 + + 8.3006295E-02 + + 8.2573545E-02 + + + + 6.1382782E-03 + + 1.1652027E-02 + + 1.1858603E-02 + + 1.1149474E-02 + + 1.1500153E-02 + + 1.1352538E-02 + + 1.2052433E-02 + + 1.2104328E-02 + + 1.2615826E-02 + + 1.3028027E-02 + + 1.3393814E-02 + + 1.4056119E-02 + + 1.4520800E-02 + + 1.5244525E-02 + + 1.5619872E-02 + + 1.7065448E-02 + + 1.7976677E-02 + + 2.1928655E-02 + + 2.5188600E-02 + + 2.9345474E-02 + + 3.3098490E-02 + + 3.7352890E-02 + + 4.1577882E-02 + + 4.5851588E-02 + + 4.9907550E-02 + + 5.5007580E-02 + + 5.8924848E-02 + + 6.4866195E-02 + + 6.8653679E-02 + + 7.3799695E-02 + + 8.2491620E-02 + + 8.2047228E-02 + + + + 6.1241006E-03 + + 1.1590726E-02 + + 1.1801215E-02 + + 1.1080585E-02 + + 1.1434054E-02 + + 1.1286311E-02 + + 1.2000496E-02 + + 1.2020032E-02 + + 1.2555074E-02 + + 1.2968561E-02 + + 1.3345040E-02 + + 1.3984260E-02 + + 1.4471501E-02 + + 1.5187071E-02 + + 1.5527587E-02 + + 1.6969733E-02 + + 1.7880430E-02 + + 2.1827072E-02 + + 2.5070882E-02 + + 2.9204178E-02 + + 3.2920367E-02 + + 3.7138445E-02 + + 4.1355200E-02 + + 4.5651496E-02 + + 4.9686415E-02 + + 5.4664866E-02 + + 5.8632525E-02 + + 6.4518086E-02 + + 6.8341097E-02 + + 7.3449748E-02 + + 8.2031901E-02 + + 8.1619798E-02 + + + + 6.1062727E-03 + + 1.1540200E-02 + + 1.1761046E-02 + + 1.1040109E-02 + + 1.1412932E-02 + + 1.1240736E-02 + + 1.1950046E-02 + + 1.1997678E-02 + + 1.2505989E-02 + + 1.2930265E-02 + + 1.3303213E-02 + + 1.3935054E-02 + + 1.4397122E-02 + + 1.5128867E-02 + + 1.5487202E-02 + + 1.6938379E-02 + + 1.7810772E-02 + + 2.1723430E-02 + + 2.4973244E-02 + + 2.9068452E-02 + + 3.2834028E-02 + + 3.7010997E-02 + + 4.1148015E-02 + + 4.5454526E-02 + + 4.9470264E-02 + + 5.4447102E-02 + + 5.8392796E-02 + + 6.4249338E-02 + + 6.8034422E-02 + + 7.3189468E-02 + + 8.1672467E-02 + + 8.1260364E-02 + + + + 6.0833777E-03 + + 1.1517436E-02 + + 1.1712978E-02 + + 1.1032819E-02 + + 1.1358893E-02 + + 1.1208870E-02 + + 1.1912352E-02 + + 1.1958737E-02 + + 1.2469851E-02 + + 1.2881147E-02 + + 1.3237414E-02 + + 1.3873203E-02 + + 1.4346868E-02 + + 1.5065060E-02 + + 1.5417558E-02 + + 1.6865782E-02 + + 1.7748238E-02 + + 2.1647065E-02 + + 2.4885779E-02 + + 2.8999390E-02 + + 3.2709869E-02 + + 3.6878634E-02 + + 4.1028900E-02 + + 4.5288735E-02 + + 4.9351482E-02 + + 5.4263443E-02 + + 5.8208019E-02 + + 6.4026596E-02 + + 6.7817431E-02 + + 7.2944166E-02 + + 8.1408951E-02 + + 8.0980011E-02 + + + + 6.0960595E-03 + + 1.1509277E-02 + + 1.1717750E-02 + + 1.1016084E-02 + + 1.1324287E-02 + + 1.1181299E-02 + + 1.1926512E-02 + + 1.1924795E-02 + + 1.2430825E-02 + + 1.2836520E-02 + + 1.3191644E-02 + + 1.3847845E-02 + + 1.4306693E-02 + + 1.5047376E-02 + + 1.5361189E-02 + + 1.6797970E-02 + + 1.7681035E-02 + + 2.1572902E-02 + + 2.4843981E-02 + + 2.8950004E-02 + + 3.2646669E-02 + + 3.6798605E-02 + + 4.0927881E-02 + + 4.5165770E-02 + + 4.9225435E-02 + + 5.4165928E-02 + + 5.8066998E-02 + + 6.3897046E-02 + + 6.7667188E-02 + + 7.2785603E-02 + + 8.1253392E-02 + + 8.0864443E-02 + + + + 6.0706294E-03 + + 1.1507691E-02 + + 1.1695334E-02 + + 1.0977998E-02 + + 1.1320263E-02 + + 1.1167309E-02 + + 1.1887145E-02 + + 1.1908635E-02 + + 1.2405259E-02 + + 1.2838152E-02 + + 1.3210507E-02 + + 1.3849960E-02 + + 1.4283591E-02 + + 1.5028182E-02 + + 1.5329706E-02 + + 1.6759635E-02 + + 1.7685388E-02 + + 2.1572849E-02 + + 2.4772494E-02 + + 2.8864133E-02 + + 3.2582677E-02 + + 3.6784719E-02 + + 4.0900801E-02 + + 4.5137865E-02 + + 4.9135372E-02 + + 5.4093178E-02 + + 5.8034149E-02 + + 6.3786244E-02 + + 6.7502120E-02 + + 7.2584553E-02 + + 8.1167082E-02 + + 8.0688398E-02 + + + + 6.0461907E-03 + + 1.1481547E-02 + + 1.1737058E-02 + + 1.0999643E-02 + + 1.1361089E-02 + + 1.1125441E-02 + + 1.1866202E-02 + + 1.1842566E-02 + + 1.2424994E-02 + + 1.2799184E-02 + + 1.3219862E-02 + + 1.3773742E-02 + + 1.4257782E-02 + + 1.4972557E-02 + + 1.5426839E-02 + + 1.6740630E-02 + + 1.7654390E-02 + + 2.1573482E-02 + + 2.4801577E-02 + + 2.8800263E-02 + + 3.2583876E-02 + + 3.6801622E-02 + + 4.0806074E-02 + + 4.5107401E-02 + + 4.9075545E-02 + + 5.3960225E-02 + + 5.7982974E-02 + + 6.3859228E-02 + + 6.7502946E-02 + + 7.2470281E-02 + + 8.1149466E-02 + + 8.0629616E-02 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + 1.0000000E+00 + + + + + \ No newline at end of file diff --git a/tests/input_set.py b/tests/input_set.py index c13a4f9cc..daff38ba1 100644 --- a/tests/input_set.py +++ b/tests/input_set.py @@ -572,3 +572,92 @@ class InputSet(object): plot.color = 'mat' self.plots.add_plot(plot) + +class MGInputSet(InputSet): + def build_default_materials_and_geometry(self): + # Define materials needed for 1D/1G slab problem + uo2_data = openmc.Macroscopic('uo2_iso', '71c') + uo2 = openmc.Material(name='UO2', material_id=1) + uo2.set_density('macro', 1.0) + uo2.add_macroscopic(uo2_data) + + clad_data = openmc.Macroscopic('clad_ang_mu', '71c') + clad = openmc.Material(name='Clad', material_id=2) + clad.set_density('macro', 1.0) + clad.add_macroscopic(clad_data) + + water_data = openmc.Macroscopic('lwtr_iso_mu', '71c') + water = openmc.Material(name='LWTR', material_id=3) + water.set_density('macro', 1.0) + water.add_macroscopic(water_data) + + # Define the materials file. + self.materials.default_xs = '71c' + self.materials.add_materials((uo2, clad, water)) + + # Define surfaces. + + # Assembly/Problem Boundary + left = openmc.XPlane(x0=0.0, surface_id=200, + boundary_type='reflective') + right = openmc.XPlane(x0=10.0, surface_id=201, + boundary_type='reflective') + bottom = openmc.YPlane(y0=0.0, surface_id=300, + boundary_type='reflective') + top = openmc.YPlane(y0=10.0, surface_id=301, + boundary_type='reflective') + + down = openmc.ZPlane(z0=0.0, surface_id=0, + boundary_type='reflective') + fuel_clad_intfc = openmc.ZPlane(z0=2.0, surface_id=1) + clad_lwtr_intfc = openmc.ZPlane(z0=2.4, surface_id=2) + up = openmc.ZPlane(z0=5.0, surface_id=3, + boundary_type='reflective') + + # Define cells + c1 = openmc.Cell(cell_id=1) + c1.region = +left & -right & +bottom & -top & +down & -fuel_clad_intfc + c1.fill = uo2 + c2 = openmc.Cell(cell_id=2) + c2.region = +left & -right & +bottom & -top & +fuel_clad_intfc & -clad_lwtr_intfc + c2.fill = clad + c3 = openmc.Cell(cell_id=3) + c3.region = +left & -right & +bottom & -top & +clad_lwtr_intfc & -up + c3.fill = water + + # Define root universe. + root = openmc.Universe(universe_id=0, name='root universe') + + root.add_cells((c1,c2,c3)) + + # Define the geometry file. + geometry = openmc.Geometry() + geometry.root_universe = root + + self.geometry.geometry = geometry + + + def build_default_settings(self): + self.settings.batches = 10 + self.settings.inactive = 5 + self.settings.particles = 100 + self.settings.source = Source(space=Box([0.0, 0.0, 0.0], + [10.0, 10.0, 2.0])) + self.settings.energy_mode = "multi-group" + self.settings.cross_sections = "../1d_mgxs.xml" + + def build_defualt_plots(self): + plot = openmc.Plot() + plot.filename = 'mat' + plot.origin = (5.0, 5.0, 2.5) + plot.width = (2.5, 2.5) + plot.basis = 'xz' + plot.pixels = (3000, 3000) + plot.color = 'mat' + + self.plots.add_plot(plot) + + + + + diff --git a/tests/test_mg_basic/inputs_true.dat b/tests/test_mg_basic/inputs_true.dat new file mode 100644 index 000000000..fdbdb1c96 --- /dev/null +++ b/tests/test_mg_basic/inputs_true.dat @@ -0,0 +1 @@ +04b4a5099f0097bbe02983c67dea691d0d0d4ece7fb7c264b9b2c29955baa9e870b6fa999480da08ead1e5a0c078ae33ce1b0a5c8594ad465aedf9bf3933e104 \ No newline at end of file diff --git a/tests/test_mg_basic/results_true.dat b/tests/test_mg_basic/results_true.dat new file mode 100644 index 000000000..35f3e73d4 --- /dev/null +++ b/tests/test_mg_basic/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +1.045320E+00 5.851680E-02 diff --git a/tests/test_mg_basic/test_mg_basic.py b/tests/test_mg_basic/test_mg_basic.py new file mode 100644 index 000000000..1a49ee8a8 --- /dev/null +++ b/tests/test_mg_basic/test_mg_basic.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class MGBasicTestHarness(PyAPITestHarness): + def _build_inputs(self): + super(MGBasicTestHarness, self)._build_inputs() + + +if __name__ == '__main__': + harness = MGBasicTestHarness('statepoint.10.*', False, mg=True) + harness.main() diff --git a/tests/test_mg_max_order/inputs_true.dat b/tests/test_mg_max_order/inputs_true.dat new file mode 100644 index 000000000..1ad336e19 --- /dev/null +++ b/tests/test_mg_max_order/inputs_true.dat @@ -0,0 +1 @@ +abe20c626d613e73ccb1a3f8468ad1b9aecca528afa9e8131a411d754eb86b8ab64a6fb1fdc9c0b8b8158ff7c82f548de5912041bf035aa5a2d4532cfe0c9510 \ No newline at end of file diff --git a/tests/test_mg_max_order/results_true.dat b/tests/test_mg_max_order/results_true.dat new file mode 100644 index 000000000..1b2300560 --- /dev/null +++ b/tests/test_mg_max_order/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +1.083030E+00 1.855038E-02 diff --git a/tests/test_mg_max_order/test_mg_max_order.py b/tests/test_mg_max_order/test_mg_max_order.py new file mode 100644 index 000000000..2f5ee4e4e --- /dev/null +++ b/tests/test_mg_max_order/test_mg_max_order.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +from input_set import MGInputSet +import openmc + +class MGNuclideInputSet(MGInputSet): + def build_default_materials_and_geometry(self): + # Define materials needed for 1D/1G slab problem + uo2_data = openmc.Macroscopic('uo2_iso', '71c') + uo2 = openmc.Material(name='UO2', material_id=1) + uo2.set_density('macro', 1.0) + uo2.add_macroscopic(uo2_data) + + clad_data = openmc.Macroscopic('clad_iso', '71c') + clad = openmc.Material(name='Clad', material_id=2) + clad.set_density('macro', 1.0) + clad.add_macroscopic(clad_data) + + water_data = openmc.Macroscopic('lwtr_iso', '71c') + water = openmc.Material(name='LWTR', material_id=3) + water.set_density('macro', 1.0) + water.add_macroscopic(water_data) + + # Define the materials file. + self.materials.default_xs = '71c' + self.materials.add_materials((uo2, clad, water)) + + # Define surfaces. + + # Assembly/Problem Boundary + left = openmc.XPlane(x0=0.0, surface_id=200, + boundary_type='reflective') + right = openmc.XPlane(x0=10.0, surface_id=201, + boundary_type='reflective') + bottom = openmc.YPlane(y0=0.0, surface_id=300, + boundary_type='reflective') + top = openmc.YPlane(y0=10.0, surface_id=301, + boundary_type='reflective') + + down = openmc.ZPlane(z0=0.0, surface_id=0, + boundary_type='reflective') + fuel_clad_intfc = openmc.ZPlane(z0=2.0, surface_id=1) + clad_lwtr_intfc = openmc.ZPlane(z0=2.4, surface_id=2) + up = openmc.ZPlane(z0=5.0, surface_id=3, + boundary_type='reflective') + + # Define cells + c1 = openmc.Cell(cell_id=1) + c1.region = +left & -right & +bottom & -top & +down & -fuel_clad_intfc + c1.fill = uo2 + c2 = openmc.Cell(cell_id=2) + c2.region = +left & -right & +bottom & -top & +fuel_clad_intfc & -clad_lwtr_intfc + c2.fill = clad + c3 = openmc.Cell(cell_id=3) + c3.region = +left & -right & +bottom & -top & +clad_lwtr_intfc & -up + c3.fill = water + + # Define root universe. + root = openmc.Universe(universe_id=0, name='root universe') + + root.add_cells((c1,c2,c3)) + + # Define the geometry file. + geometry = openmc.Geometry() + geometry.root_universe = root + + self.geometry.geometry = geometry + +class MGMaxOrderTestHarness(PyAPITestHarness): + def __init__(self, statepoint_name, tallies_present, mg=False): + PyAPITestHarness.__init__(self, statepoint_name, tallies_present) + self._input_set = MGNuclideInputSet() + + def _build_inputs(self): + super(MGMaxOrderTestHarness, self)._build_inputs() + # Set P1 scattering + self._input_set.settings.max_order = 1 + +if __name__ == '__main__': + harness = MGMaxOrderTestHarness('statepoint.10.*', False, mg=True) + harness.main() diff --git a/tests/test_mg_nuclide/inputs_true.dat b/tests/test_mg_nuclide/inputs_true.dat new file mode 100644 index 000000000..eb643bbaf --- /dev/null +++ b/tests/test_mg_nuclide/inputs_true.dat @@ -0,0 +1 @@ +c9f9e7211bfb2af58130bedfd64592d093b7bfa424953eba433ecf08940595a96b8de7a892f12d1ab465cebd8e5dd784114c1b1299b534ed329df92752c9ed1f \ No newline at end of file diff --git a/tests/test_mg_nuclide/results_true.dat b/tests/test_mg_nuclide/results_true.dat new file mode 100644 index 000000000..5b60cef22 --- /dev/null +++ b/tests/test_mg_nuclide/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +1.380785E-01 5.556526E-03 diff --git a/tests/test_mg_nuclide/test_mg_nuclide.py b/tests/test_mg_nuclide/test_mg_nuclide.py new file mode 100644 index 000000000..deb784bad --- /dev/null +++ b/tests/test_mg_nuclide/test_mg_nuclide.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +from input_set import MGInputSet +import openmc + +class MGNuclideInputSet(MGInputSet): + def build_default_materials_and_geometry(self): + # Define materials needed for 1D/1G slab problem + # This time do using nuclide, not macroscopic + uo2 = openmc.Material(name='UO2', material_id=1) + uo2.set_density('g/cm3', 1.0) + uo2.add_nuclide("uo2_iso", 1.0) + + clad = openmc.Material(name='Clad', material_id=2) + clad.set_density('g/cm3', 1.0) + clad.add_nuclide("clad_ang_mu", 1.0) + + water_data = openmc.Nuclide('lwtr_iso_mu', '71c') + water = openmc.Material(name='LWTR', material_id=3) + water.set_density('g/cm3', 1.0) + water.add_nuclide("lwtr_iso_mu", 1.0) + + # Define the materials file. + self.materials.default_xs = '71c' + self.materials.add_materials((uo2, clad, water)) + + # Define surfaces. + + # Assembly/Problem Boundary + left = openmc.XPlane(x0=0.0, surface_id=200, + boundary_type='reflective') + right = openmc.XPlane(x0=10.0, surface_id=201, + boundary_type='reflective') + bottom = openmc.YPlane(y0=0.0, surface_id=300, + boundary_type='reflective') + top = openmc.YPlane(y0=10.0, surface_id=301, + boundary_type='reflective') + + down = openmc.ZPlane(z0=0.0, surface_id=0, + boundary_type='reflective') + fuel_clad_intfc = openmc.ZPlane(z0=2.0, surface_id=1) + clad_lwtr_intfc = openmc.ZPlane(z0=2.4, surface_id=2) + up = openmc.ZPlane(z0=5.0, surface_id=3, + boundary_type='reflective') + + # Define cells + c1 = openmc.Cell(cell_id=1) + c1.region = +left & -right & +bottom & -top & +down & -fuel_clad_intfc + c1.fill = uo2 + c2 = openmc.Cell(cell_id=2) + c2.region = +left & -right & +bottom & -top & +fuel_clad_intfc & -clad_lwtr_intfc + c2.fill = clad + c3 = openmc.Cell(cell_id=3) + c3.region = +left & -right & +bottom & -top & +clad_lwtr_intfc & -up + c3.fill = water + + # Define root universe. + root = openmc.Universe(universe_id=0, name='root universe') + + root.add_cells((c1,c2,c3)) + + # Define the geometry file. + geometry = openmc.Geometry() + geometry.root_universe = root + + self.geometry.geometry = geometry + +class MGNuclideTestHarness(PyAPITestHarness): + def __init__(self, statepoint_name, tallies_present, mg=False): + PyAPITestHarness.__init__(self, statepoint_name, tallies_present) + self._input_set = MGNuclideInputSet() + + def _build_inputs(self): + super(MGNuclideTestHarness, self)._build_inputs() + + + +if __name__ == '__main__': + harness = MGNuclideTestHarness('statepoint.10.*', False, mg=True) + harness.main() diff --git a/tests/test_mg_tallies/inputs_true.dat b/tests/test_mg_tallies/inputs_true.dat new file mode 100644 index 000000000..304d2e888 --- /dev/null +++ b/tests/test_mg_tallies/inputs_true.dat @@ -0,0 +1 @@ +ca8490e0e4549fed727ddc75b6d92cfe5162e11b905218a0afaa3ce2ee0763e2ff38074de27aaa678818624f49c5823650475dfa8f66f502a98fc03145399c0d \ No newline at end of file diff --git a/tests/test_mg_tallies/results_true.dat b/tests/test_mg_tallies/results_true.dat new file mode 100644 index 000000000..0cb47a712 --- /dev/null +++ b/tests/test_mg_tallies/results_true.dat @@ -0,0 +1,2906 @@ +k-combined: +1.045320E+00 5.851680E-02 +tally 1: +2.286064E+00 +1.057353E+00 +6.503987E-02 +8.851627E-04 +3.376363E+00 +2.323627E+00 +2.733240E-02 +1.607534E-04 +6.776283E-02 +9.880704E-04 +2.391658E+00 +1.201477E+00 +7.241106E-02 +1.103780E-03 +3.614949E+00 +2.730438E+00 +3.146867E-02 +2.110753E-04 +7.801752E-02 +1.297373E-03 +2.762725E+00 +1.705088E+00 +8.684520E-02 +1.654173E-03 +4.172232E+00 +3.847245E+00 +3.834947E-02 +3.212662E-04 +9.507651E-02 +1.974662E-03 +2.802290E+00 +1.773339E+00 +8.347451E-02 +1.574952E-03 +4.206829E+00 +3.971225E+00 +3.593646E-02 +2.967708E-04 +8.909414E-02 +1.824101E-03 +2.383708E+00 +1.176784E+00 +7.337273E-02 +1.097240E-03 +3.624903E+00 +2.690697E+00 +3.213890E-02 +2.139948E-04 +7.967917E-02 +1.315319E-03 +2.398216E+00 +1.234567E+00 +6.905889E-02 +9.879327E-04 +3.479138E+00 +2.538252E+00 +2.911091E-02 +1.750648E-04 +7.217215E-02 +1.076035E-03 +2.563998E+00 +1.354089E+00 +7.357381E-02 +1.097086E-03 +3.753156E+00 +2.867475E+00 +3.097034E-02 +1.948794E-04 +7.678206E-02 +1.197826E-03 +2.293243E+00 +1.172767E+00 +6.702582E-02 +9.267762E-04 +3.407144E+00 +2.469472E+00 +2.857514E-02 +1.688581E-04 +7.084385E-02 +1.037886E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +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.604127E+00 +1.442914E+00 +7.142299E-02 +1.083324E-03 +3.786547E+00 +2.990260E+00 +2.935394E-02 +1.905369E-04 +7.277467E-02 +1.171135E-03 +2.457755E+00 +1.228862E+00 +6.655630E-02 +9.411086E-04 +3.528688E+00 +2.561047E+00 +2.709124E-02 +1.640319E-04 +6.716494E-02 +1.008221E-03 +2.450846E+00 +1.295337E+00 +6.779278E-02 +9.992248E-04 +3.519409E+00 +2.693620E+00 +2.793186E-02 +1.714064E-04 +6.924902E-02 +1.053549E-03 +2.469234E+00 +1.300419E+00 +7.347034E-02 +1.175743E-03 +3.675903E+00 +2.880386E+00 +3.155996E-02 +2.200036E-04 +7.824386E-02 +1.352252E-03 +2.576106E+00 +1.365945E+00 +7.241428E-02 +1.090052E-03 +3.719498E+00 +2.861357E+00 +3.008961E-02 +1.906170E-04 +7.459854E-02 +1.171627E-03 +2.503651E+00 +1.290812E+00 +7.432507E-02 +1.132918E-03 +3.702398E+00 +2.813425E+00 +3.186491E-02 +2.091477E-04 +7.899991E-02 +1.285525E-03 +2.395349E+00 +1.202098E+00 +7.095925E-02 +1.051988E-03 +3.559388E+00 +2.628753E+00 +3.041477E-02 +1.959992E-04 +7.540470E-02 +1.204709E-03 +1.910174E+00 +7.331782E-01 +6.366813E-02 +8.166135E-04 +2.966770E+00 +1.762376E+00 +2.893278E-02 +1.712979E-04 +7.173053E-02 +1.052882E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +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.593479E+00 +1.421618E+00 +7.731733E-02 +1.249860E-03 +3.880469E+00 +3.167768E+00 +3.330331E-02 +2.319171E-04 +8.256599E-02 +1.425478E-03 +2.563470E+00 +1.449702E+00 +7.411043E-02 +1.158986E-03 +3.692974E+00 +2.935486E+00 +3.125554E-02 +2.061246E-04 +7.748913E-02 +1.266944E-03 +2.657580E+00 +1.493736E+00 +7.749682E-02 +1.277831E-03 +3.892576E+00 +3.190262E+00 +3.289903E-02 +2.334764E-04 +8.156370E-02 +1.435062E-03 +2.701357E+00 +1.517431E+00 +8.804410E-02 +1.639744E-03 +4.161224E+00 +3.606273E+00 +3.959674E-02 +3.345554E-04 +9.816875E-02 +2.056343E-03 +2.745200E+00 +1.523378E+00 +7.925308E-02 +1.270874E-03 +3.962649E+00 +3.165021E+00 +3.340000E-02 +2.283904E-04 +8.280570E-02 +1.403801E-03 +2.678775E+00 +1.492394E+00 +8.646776E-02 +1.554919E-03 +4.147456E+00 +3.551060E+00 +3.875994E-02 +3.125295E-04 +9.609415E-02 +1.920962E-03 +2.678888E+00 +1.497390E+00 +7.616647E-02 +1.203778E-03 +3.868905E+00 +3.108718E+00 +3.186093E-02 +2.136540E-04 +7.899003E-02 +1.313223E-03 +2.189117E+00 +9.756340E-01 +6.824988E-02 +9.549688E-04 +3.259136E+00 +2.150849E+00 +2.997262E-02 +1.883650E-04 +7.430850E-02 +1.157785E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +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.761165E+00 +1.657839E+00 +7.810542E-02 +1.334149E-03 +4.026290E+00 +3.495574E+00 +3.264226E-02 +2.359256E-04 +8.092710E-02 +1.450116E-03 +2.601284E+00 +1.465130E+00 +7.485486E-02 +1.239170E-03 +3.829638E+00 +3.199488E+00 +3.159745E-02 +2.288567E-04 +7.833681E-02 +1.406667E-03 +2.419174E+00 +1.228134E+00 +7.422066E-02 +1.117508E-03 +3.667795E+00 +2.787048E+00 +3.244938E-02 +2.129012E-04 +8.044893E-02 +1.308597E-03 +2.491535E+00 +1.259222E+00 +7.470359E-02 +1.133979E-03 +3.773164E+00 +2.887196E+00 +3.234132E-02 +2.142511E-04 +8.018101E-02 +1.316894E-03 +2.430358E+00 +1.305969E+00 +7.236826E-02 +1.077801E-03 +3.691969E+00 +2.914191E+00 +3.123416E-02 +2.001679E-04 +7.743613E-02 +1.230332E-03 +3.133682E+00 +1.984584E+00 +8.337467E-02 +1.392595E-03 +4.451265E+00 +3.978527E+00 +3.354318E-02 +2.282172E-04 +8.316070E-02 +1.402736E-03 +2.662704E+00 +1.448336E+00 +7.530385E-02 +1.164529E-03 +3.880423E+00 +3.054138E+00 +3.144058E-02 +2.085301E-04 +7.794791E-02 +1.281730E-03 +2.130205E+00 +9.297660E-01 +6.583066E-02 +8.790174E-04 +3.226341E+00 +2.120506E+00 +2.889944E-02 +1.698754E-04 +7.164788E-02 +1.044139E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +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.599461E+00 +1.458035E+00 +7.809884E-02 +1.305214E-03 +3.901359E+00 +3.258238E+00 +3.379142E-02 +2.432493E-04 +8.377612E-02 +1.495131E-03 +2.748044E+00 +1.595569E+00 +8.641555E-02 +1.591494E-03 +4.133038E+00 +3.610482E+00 +3.815976E-02 +3.125423E-04 +9.460617E-02 +1.921040E-03 +2.827693E+00 +1.681951E+00 +9.214026E-02 +1.815952E-03 +4.343252E+00 +3.980138E+00 +4.139309E-02 +3.763771E-04 +1.026223E-01 +2.313401E-03 +2.848302E+00 +1.709266E+00 +8.618471E-02 +1.555247E-03 +4.293029E+00 +3.893924E+00 +3.742129E-02 +2.947160E-04 +9.277535E-02 +1.811471E-03 +3.107129E+00 +1.985180E+00 +9.390982E-02 +1.778566E-03 +4.705512E+00 +4.502266E+00 +4.077729E-02 +3.361217E-04 +1.010956E-01 +2.065971E-03 +3.176743E+00 +2.076916E+00 +9.535836E-02 +1.843238E-03 +4.782883E+00 +4.655802E+00 +4.125628E-02 +3.453802E-04 +1.022831E-01 +2.122878E-03 +3.158364E+00 +2.020031E+00 +9.047734E-02 +1.652565E-03 +4.641857E+00 +4.326900E+00 +3.809128E-02 +2.983406E-04 +9.443638E-02 +1.833749E-03 +2.750064E+00 +1.515295E+00 +7.550745E-02 +1.157933E-03 +4.022702E+00 +3.249004E+00 +3.106532E-02 +2.005988E-04 +7.701755E-02 +1.232980E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +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.571690E+00 +1.405222E+00 +6.998368E-02 +1.010782E-03 +3.645470E+00 +2.775516E+00 +2.848750E-02 +1.694087E-04 +7.062657E-02 +1.041270E-03 +3.305320E+00 +2.344814E+00 +9.985328E-02 +2.111130E-03 +4.992554E+00 +5.332303E+00 +4.332586E-02 +3.970490E-04 +1.074140E-01 +2.440461E-03 +2.746305E+00 +1.652960E+00 +9.402849E-02 +1.982149E-03 +4.315533E+00 +4.099428E+00 +4.322622E-02 +4.235148E-04 +1.071670E-01 +2.603132E-03 +2.975372E+00 +1.824531E+00 +9.627993E-02 +1.863677E-03 +4.624041E+00 +4.351874E+00 +4.324350E-02 +3.743520E-04 +1.072099E-01 +2.300953E-03 +2.968077E+00 +1.807761E+00 +9.337061E-02 +1.790184E-03 +4.455263E+00 +4.056544E+00 +4.122926E-02 +3.540009E-04 +1.022161E-01 +2.175865E-03 +3.337278E+00 +2.233238E+00 +1.017763E-01 +2.083989E-03 +4.981699E+00 +4.981154E+00 +4.428100E-02 +3.964318E-04 +1.097820E-01 +2.436667E-03 +3.083638E+00 +1.958766E+00 +9.111141E-02 +1.726305E-03 +4.546082E+00 +4.260420E+00 +3.895365E-02 +3.200133E-04 +9.657439E-02 +1.966961E-03 +2.644733E+00 +1.407404E+00 +8.635553E-02 +1.527997E-03 +4.094426E+00 +3.382785E+00 +3.888081E-02 +3.161126E-04 +9.639381E-02 +1.942985E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +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.316522E+00 +2.302876E+00 +8.987919E-02 +1.676655E-03 +4.716109E+00 +4.596488E+00 +3.654407E-02 +2.855910E-04 +9.060053E-02 +1.755384E-03 +3.091331E+00 +2.117646E+00 +8.528196E-02 +1.564336E-03 +4.492326E+00 +4.405850E+00 +3.513814E-02 +2.665883E-04 +8.711494E-02 +1.638584E-03 +2.649730E+00 +1.444519E+00 +8.510948E-02 +1.506094E-03 +4.117595E+00 +3.501517E+00 +3.810553E-02 +3.052819E-04 +9.447172E-02 +1.876414E-03 +2.875773E+00 +1.758531E+00 +9.127582E-02 +1.780419E-03 +4.328266E+00 +3.989840E+00 +4.045386E-02 +3.513542E-04 +1.002937E-01 +2.159598E-03 +3.102792E+00 +1.949906E+00 +9.153879E-02 +1.691646E-03 +4.578530E+00 +4.235906E+00 +3.913672E-02 +3.094156E-04 +9.702826E-02 +1.901822E-03 +3.238743E+00 +2.146355E+00 +8.902551E-02 +1.593536E-03 +4.683916E+00 +4.438028E+00 +3.660342E-02 +2.683183E-04 +9.074766E-02 +1.649218E-03 +3.006635E+00 +1.887385E+00 +8.716712E-02 +1.586834E-03 +4.383965E+00 +4.008888E+00 +3.688262E-02 +2.862513E-04 +9.143987E-02 +1.759443E-03 +2.749904E+00 +1.550561E+00 +9.244273E-02 +1.748082E-03 +4.241273E+00 +3.669144E+00 +4.208622E-02 +3.633241E-04 +1.043407E-01 +2.233170E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +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.556952E+00 +1.416458E+00 +8.087467E-02 +1.431667E-03 +3.806748E+00 +3.158182E+00 +3.571995E-02 +2.831832E-04 +8.855737E-02 +1.740585E-03 +2.546384E+00 +1.446967E+00 +8.000281E-02 +1.363415E-03 +3.844739E+00 +3.222133E+00 +3.533522E-02 +2.621956E-04 +8.760354E-02 +1.611584E-03 +2.474418E+00 +1.302438E+00 +7.728372E-02 +1.265047E-03 +3.818517E+00 +3.076074E+00 +3.414744E-02 +2.483215E-04 +8.465877E-02 +1.526307E-03 +2.478272E+00 +1.299434E+00 +7.866430E-02 +1.293627E-03 +3.758685E+00 +2.973817E+00 +3.491240E-02 +2.542033E-04 +8.655529E-02 +1.562460E-03 +2.941937E+00 +1.842278E+00 +9.491310E-02 +1.902183E-03 +4.564730E+00 +4.427111E+00 +4.252722E-02 +3.828960E-04 +1.054340E-01 +2.353469E-03 +2.850564E+00 +1.719152E+00 +8.118192E-02 +1.404765E-03 +4.190858E+00 +3.722715E+00 +3.411695E-02 +2.522778E-04 +8.458318E-02 +1.550625E-03 +2.726097E+00 +1.648250E+00 +7.879124E-02 +1.424955E-03 +3.940978E+00 +3.461222E+00 +3.322044E-02 +2.688615E-04 +8.236053E-02 +1.652557E-03 +2.304822E+00 +1.153775E+00 +7.500010E-02 +1.314077E-03 +3.542935E+00 +2.786864E+00 +3.369367E-02 +2.798215E-04 +8.353377E-02 +1.719922E-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 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +tally 2: +4.283244E+01 +3.698890E+02 +4.285612E+01 +3.702981E+02 +6.926001E+00 +9.669342E+00 +6.926497E+00 +9.670727E+00 +1.223563E+02 +3.025594E+03 +1.223563E+02 +3.025594E+03 diff --git a/tests/test_mg_tallies/test_mg_tallies.py b/tests/test_mg_tallies/test_mg_tallies.py new file mode 100644 index 000000000..c54fb4d32 --- /dev/null +++ b/tests/test_mg_tallies/test_mg_tallies.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class MGTalliesTestHarness(PyAPITestHarness): + def _build_inputs(self): + # Instantiate a tally mesh + mesh = openmc.Mesh(mesh_id=1) + mesh.type = 'regular' + mesh.dimension = [17, 17, 1] + mesh.lower_left = [0.0, 0.0, 0.0] + mesh.upper_right = [21.42, 21.42, 100.0] + + # Instantiate some tally filters + energy_filter = openmc.Filter(type='energy', + bins=[0.0, 20.0]) + energyout_filter = openmc.Filter(type='energyout', + bins=[0.0, 20.0]) + mesh_filter = openmc.Filter() + mesh_filter.mesh = mesh + + mat_filter = openmc.Filter(type='material', bins=[1,2,3]) + + tally1 = openmc.Tally(tally_id=1) + tally1.add_filter(mesh_filter) + tally1.add_score('total') + tally1.add_score('absorption') + tally1.add_score('flux') + tally1.add_score('fission') + tally1.add_score('nu-fission') + + tally2 = openmc.Tally(tally_id=2) + tally2.add_filter(mat_filter) + tally2.add_filter(energy_filter) + tally2.add_filter(energyout_filter) + tally2.add_score('scatter') + tally2.add_score('nu-scatter') + + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_mesh(mesh) + self._input_set.tallies.add_tally(tally1) + self._input_set.tallies.add_tally(tally2) + + super(MGTalliesTestHarness, self)._build_inputs() + + def _cleanup(self): + super(MGTalliesTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = MGTalliesTestHarness('statepoint.10.*', True, mg=True) + harness.main() diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 66cadfe63..7d6dbc914 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -12,7 +12,7 @@ import sys import numpy as np sys.path.insert(0, os.path.join(os.pardir, os.pardir)) -from input_set import InputSet +from input_set import InputSet, MGInputSet from openmc.statepoint import StatePoint from openmc.executor import Executor import openmc.particle_restart as pr @@ -243,12 +243,14 @@ class ParticleRestartTestHarness(TestHarness): class PyAPITestHarness(TestHarness): - def __init__(self, statepoint_name, tallies_present=False): + def __init__(self, statepoint_name, tallies_present=False, mg=False): super(PyAPITestHarness, self).__init__(statepoint_name, tallies_present) self.parser.add_option('--build-inputs', dest='build_only', action='store_true', default=False) - self._input_set = InputSet() - + if mg: + self._input_set = MGInputSet() + else: + self._input_set = InputSet() def main(self): """Accept commandline arguments and either run or update tests.""" (self._opts, self._args) = self.parser.parse_args()