From 199d4af9c5e7a274faf36363c9e9e10076376bcf Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 8 Nov 2015 17:24:16 -0500 Subject: [PATCH 01/60] Add diff tally for keff---density or nuc. density --- src/constants.F90 | 10 +- src/initialize.F90 | 1 + src/input_xml.F90 | 60 ++++++- src/material_header.F90 | 1 + src/output.F90 | 1 + src/tally.F90 | 110 ++++++++++++ src/tally_header.F90 | 18 ++ src/tracking.F90 | 9 +- tests/test_diff_density/build_xml.py | 150 ++++++++++++++++ tests/test_diff_density/geometry.xml | 16 ++ tests/test_diff_density/materials.xml | 45 +++++ tests/test_diff_density/results_true.dat | 5 + tests/test_diff_density/settings.xml | 18 ++ tests/test_diff_density/tallies.xml | 7 + tests/test_diff_density/test_diff_density.py | 11 ++ tests/test_diff_nuclide_density/build_xml.py | 164 ++++++++++++++++++ tests/test_diff_nuclide_density/geometry.xml | 16 ++ tests/test_diff_nuclide_density/materials.xml | 50 ++++++ .../results_true.dat | 5 + tests/test_diff_nuclide_density/settings.xml | 18 ++ tests/test_diff_nuclide_density/tallies.xml | 10 ++ .../test_diff_nuclide_density.py | 11 ++ 22 files changed, 732 insertions(+), 4 deletions(-) create mode 100644 tests/test_diff_density/build_xml.py create mode 100644 tests/test_diff_density/geometry.xml create mode 100644 tests/test_diff_density/materials.xml create mode 100644 tests/test_diff_density/results_true.dat create mode 100644 tests/test_diff_density/settings.xml create mode 100644 tests/test_diff_density/tallies.xml create mode 100755 tests/test_diff_density/test_diff_density.py create mode 100644 tests/test_diff_nuclide_density/build_xml.py create mode 100644 tests/test_diff_nuclide_density/geometry.xml create mode 100644 tests/test_diff_nuclide_density/materials.xml create mode 100644 tests/test_diff_nuclide_density/results_true.dat create mode 100644 tests/test_diff_nuclide_density/settings.xml create mode 100644 tests/test_diff_nuclide_density/tallies.xml create mode 100755 tests/test_diff_nuclide_density/test_diff_nuclide_density.py diff --git a/src/constants.F90 b/src/constants.F90 index 375c517e7..8e8e2db76 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -259,7 +259,7 @@ module constants EVENT_ABSORB = 2 ! Tally score type - integer, parameter :: N_SCORE_TYPES = 22 + integer, parameter :: N_SCORE_TYPES = 23 integer, parameter :: & SCORE_FLUX = -1, & ! flux SCORE_TOTAL = -2, & ! total reaction rate @@ -282,7 +282,8 @@ module constants SCORE_NU_SCATTER_YN = -19, & ! angular flux-weighted nu-scattering moment (0:N) SCORE_EVENTS = -20, & ! number of events SCORE_DELAYED_NU_FISSION = -21, & ! delayed neutron production rate - SCORE_INVERSE_VELOCITY = -22 ! flux-weighted inverse velocity + SCORE_INVERSE_VELOCITY = -22, & ! flux-weighted inverse velocity + SCORE_KEFF = -23 ! multiplication factor ! Maximum scattering order supported integer, parameter :: MAX_ANG_ORDER = 10 @@ -348,6 +349,11 @@ module constants K_TRACKLENGTH = 3, & LEAKAGE = 4 + ! Differential tally dependent variables + integer, parameter :: & + DIFF_DENSITY = 1, & + DIFF_NUCLIDE_DENSITY = 2 + ! ============================================================================ ! RANDOM NUMBER STREAM CONSTANTS diff --git a/src/initialize.F90 b/src/initialize.F90 index 9d63eb4e9..6130be0e2 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -831,6 +831,7 @@ contains ! Change density in g/cm^3 to atom/b-cm. Since all values are now in atom ! percent, the sum needs to be re-evaluated as 1/sum(x*awr) if (.not. density_in_atom) then + mat % density_gpcc = -mat % density sum_percent = ZERO do j = 1, mat%n_nuclides index_list = xs_listing_dict%get_key(mat%names(j)) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 58e401335..052748d13 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2197,6 +2197,7 @@ contains type(Node), pointer :: node_tal => null() type(Node), pointer :: node_filt => null() type(Node), pointer :: node_trigger=>null() + type(Node), pointer :: node_deriv => null() type(NodeList), pointer :: node_mesh_list => null() type(NodeList), pointer :: node_tal_list => null() type(NodeList), pointer :: node_filt_list => null() @@ -2407,7 +2408,7 @@ contains t % estimator = ESTIMATOR_TRACKLENGTH - ! Copy material id + ! Copy tally id if (check_for_node(node_tal, "id")) then call get_node_value(node_tal, "id", t % id) else @@ -2843,6 +2844,52 @@ contains end do end if + ! ======================================================================= + ! READ DATA FOR DERIVATIVES + + if (check_for_node(node_tal, "derivative")) then + call get_node_ptr(node_tal, "derivative", node_deriv) + allocate(t % deriv) + + temp_str = "" + call get_node_value(node_deriv, "variable", temp_str) + temp_str = to_lower(temp_str) + + select case(temp_str) + + case("density") + t % deriv % dep_var = DIFF_DENSITY + call get_node_value(node_deriv, "material", t % deriv % diff_material) + + case("nuclide_density") + t % deriv % dep_var = DIFF_NUCLIDE_DENSITY + call get_node_value(node_deriv, "material", t % deriv % diff_material) + + call get_node_value(node_deriv, "nuclide", word) + word = trim(to_lower(word)) + pair_list => nuclide_dict % keys() + do while (associated(pair_list)) + if (starts_with(pair_list % key, word)) then + word = pair_list % key(1:150) + exit + end if + + ! Advance to next + pair_list => pair_list % next + end do + + ! 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.") + end if + deallocate(pair_list) + + t % deriv % diff_nuclide = nuclide_dict % get_key(word) + end select + end if + ! ======================================================================= ! READ DATA FOR SCORES @@ -2991,6 +3038,11 @@ contains call fatal_error("Cannot tally flux with an outgoing energy & &filter.") end if + + if (allocated(t % deriv)) then + t % estimator = ESTIMATOR_COLLISION + end if + case ('flux-yn') ! Prohibit user from tallying flux for an individual nuclide if (.not. (t % n_nuclide_bins == 1 .and. & @@ -3188,6 +3240,12 @@ contains case ('events') t % score_bins(j) = SCORE_EVENTS + case ('keff') + t % score_bins(j) = SCORE_KEFF + if (allocated(t % deriv)) then + t % estimator = ESTIMATOR_COLLISION + end if + case ('elastic', '(n,elastic)') t % score_bins(j) = ELASTIC case ('(n,2nd)') diff --git a/src/material_header.F90 b/src/material_header.F90 index c2f4b51bc..24e459cbb 100644 --- a/src/material_header.F90 +++ b/src/material_header.F90 @@ -13,6 +13,7 @@ module material_header integer, allocatable :: nuclide(:) ! index in nuclides array real(8) :: density ! total atom density in atom/b-cm real(8), allocatable :: atom_density(:) ! nuclide atom density in atom/b-cm + real(8) :: density_gpcc ! total density in g/cm^3 ! Energy grid information integer :: n_grid ! # of union material grid points diff --git a/src/output.F90 b/src/output.F90 index 55cd5b2a5..0f667c121 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -986,6 +986,7 @@ contains score_names(abs(SCORE_NU_SCATTER_YN)) = "Scattering Prod. Rate Moment" score_names(abs(SCORE_DELAYED_NU_FISSION)) = "Delayed-Nu-Fission Rate" score_names(abs(SCORE_INVERSE_VELOCITY)) = "Flux-Weighted Inverse Velocity" + score_names(abs(SCORE_KEFF)) = "k_eff, multiplaction factor" ! Create filename for tally output filename = trim(path_output) // "tallies.out" diff --git a/src/tally.F90 b/src/tally.F90 index fcd6dfdd9..7fce90cce 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -654,6 +654,13 @@ contains end if end if + case (SCORE_KEFF) + if (t % estimator == ESTIMATOR_COLLISION) then + score = p % last_wgt * material_xs % nu_fission / material_xs % total + else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + score = flux * material_xs % nu_fission + end if + case default if (t % estimator == ESTIMATOR_ANALOG) then ! Any other score is assumed to be a MT number. Thus, we just need @@ -732,6 +739,35 @@ contains end select + !######################################################################### + ! Add derivative information on score for differential tallies. + + if (allocated(t % deriv) .and. t % estimator == ESTIMATOR_COLLISION) then + select case (score_bin) + + case (SCORE_KEFF) + select case (t % deriv % dep_var) + + case (DIFF_DENSITY) + score = score * t % deriv % accumulator + + case (DIFF_NUCLIDE_DENSITY) + mat => materials(p % material) + if (mat % id == t % deriv % diff_material .and. & + micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO) then + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == t % deriv % diff_nuclide) exit + end do + score = score * (t % deriv % accumulator + ONE & + / mat % atom_density(l)) + else + score = score * t % deriv % accumulator + end if + + end select + end select + end if + !######################################################################### ! Expand score if necessary and add to tally results. @@ -2210,6 +2246,80 @@ contains end subroutine score_surface_current +!=============================================================================== +! SCORE_DIFF_ACCUMULATORS +!=============================================================================== + + subroutine score_diff_accumulators(p, distance, collision) + type(particle), intent(in) :: p + real(8), intent(in) :: distance + logical, intent(in) :: collision + + integer :: i, j + type(TallyObject), pointer :: t + type(Material), pointer :: mat + + do i = 1, n_user_tallies + t => user_tallies(i) + + if (allocated(t % deriv)) then + select case (t % deriv % dep_var) + + case (DIFF_DENSITY) + if (p % material == MATERIAL_VOID) cycle + mat => materials(p % material) + if (mat % id == t % deriv % diff_material) then + if (collision) then + t % deriv % accumulator = t % deriv % accumulator & + + ONE / mat % density_gpcc & + - distance * material_xs % total / mat % density_gpcc + else + t % deriv % accumulator = t % deriv % accumulator & + - distance * material_xs % total / mat % density_gpcc + end if + end if + + case (DIFF_NUCLIDE_DENSITY) + if (p % material == MATERIAL_VOID) cycle + mat => materials(p % material) + if (mat % id == t % deriv % diff_material) then + do j = 1, mat % n_nuclides + if (mat % nuclide(j) == t % deriv % diff_nuclide) exit + end do + if (mat % nuclide(j) /= t % deriv % diff_nuclide) then + call fatal_error("Couldn't find the right nuclide.") + end if + t % deriv % accumulator = t % deriv % accumulator & + - distance * micro_xs(t % deriv % diff_nuclide) % total + if (collision) then + if (p % event == EVENT_SCATTER) then + t % deriv % accumulator = t % deriv % accumulator & + + micro_xs(t % deriv % diff_nuclide) % elastic & + / material_xs % elastic + else if (p % event == EVENT_ABSORB) then + t % deriv % accumulator = t % deriv % accumulator & + + micro_xs(t % deriv % diff_nuclide) % absorption & + / material_xs % absorption + end if + end if + end if + end select + end if + end do + end subroutine + + subroutine clear_diff_accumulators() + integer :: i + type(TallyObject), pointer :: t + + do i = 1, n_user_tallies + t => user_tallies(i) + if (allocated(t % deriv)) then + t % deriv % accumulator = ZERO + end if + end do + end subroutine + !=============================================================================== ! GET_NEXT_BIN determines the next scoring bin for a particular filter variable !=============================================================================== diff --git a/src/tally_header.F90 b/src/tally_header.F90 index 01dcd9bdb..cfbe0d537 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -64,6 +64,18 @@ module tally_header procedure :: clear => tallyfilter_clear ! Deallocates TallyFilter end type TallyFilter + +!=============================================================================== +! TALLYDERIVATIVE +!=============================================================================== + + type TallyDerivative + real(8) :: accumulator + integer :: dep_var + integer :: diff_material + integer :: diff_nuclide + end type TallyDerivative + !=============================================================================== ! TALLYOBJECT describes a user-specified tally. The region of phase space to ! tally in is given by the TallyFilters and the results are stored in a @@ -130,6 +142,9 @@ module tally_header integer :: n_triggers = 0 ! # of triggers type(TriggerObject), allocatable :: triggers(:) ! Array of triggers + ! Derivative for differentially tallies + type(TallyDerivative), allocatable :: deriv + ! Type-Bound procedures contains procedure :: clear => tallyobject_clear ! Deallocates TallyObject @@ -204,6 +219,9 @@ module tally_header this % n_triggers = 0 + if (allocated(this % deriv)) & + deallocate (this % deriv) + end subroutine tallyobject_clear end module tally_header diff --git a/src/tracking.F90 b/src/tracking.F90 index 2e4503e13..9502746da 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -13,7 +13,8 @@ module tracking 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 + score_collision_tally, score_surface_current, & + score_diff_accumulators, clear_diff_accumulators use track_output, only: initialize_particle_track, write_particle_track, & add_particle_track, finalize_particle_track @@ -60,6 +61,9 @@ contains call initialize_particle_track() endif + ! Every particle starts with no accumulated flux derivative. + call clear_diff_accumulators() + EVENT_LOOP: do ! If the cell hasn't been determined based on the particle's location, ! initiate a search for the current cell. This generally happens at the @@ -114,6 +118,9 @@ contains distance * material_xs % nu_fission end if + ! Score flux derivative accumulators for differential tallies. + call score_diff_accumulators(p, distance, d_boundary > d_collision) + if (d_collision > d_boundary) then ! ==================================================================== ! PARTICLE CROSSES SURFACE diff --git a/tests/test_diff_density/build_xml.py b/tests/test_diff_density/build_xml.py new file mode 100644 index 000000000..d5e50c7e8 --- /dev/null +++ b/tests/test_diff_density/build_xml.py @@ -0,0 +1,150 @@ +import openmc + + +def make_mats(mod_density=0.7420582): + water = openmc.Material(name='water') + water.set_density('g/cm3', mod_density) + water.add_nuclide(openmc.Nuclide('H-1'), 2.0) + water.add_nuclide(openmc.Nuclide('O-16'), 1.0) + + fuel = openmc.Material(name='fuel 2.4%') + fuel.set_density('g/cm3', 10.29769) + fuel.add_nuclide(openmc.Nuclide('U-234'), 5.7987e-06) + fuel.add_nuclide(openmc.Nuclide('U-235'), 7.2175e-04) + fuel.add_nuclide(openmc.Nuclide('U-238'), 2.2253e-02) + fuel.add_nuclide(openmc.Nuclide('O-16'), 4.5750e-02) + fuel.add_nuclide(openmc.Nuclide('O-17'), 9.4222e-05) + + zirc4 = openmc.Material(name='zircaloy 4') + zirc4.set_density('g/cm3', 6.55) + zirc4.add_nuclide(openmc.Nuclide('O-16'), 3.0743e-04) + zirc4.add_nuclide(openmc.Nuclide('O-17'), 1.1711e-07) + # O-18 omitted + zirc4.add_nuclide(openmc.Nuclide('Cr-50'), 3.2962e-06) + zirc4.add_nuclide(openmc.Nuclide('Cr-52'), 6.3564e-05) + zirc4.add_nuclide(openmc.Nuclide('Cr-53'), 7.2076e-06) + zirc4.add_nuclide(openmc.Nuclide('Cr-54'), 1.7941e-06) + zirc4.add_nuclide(openmc.Nuclide('Fe-54'), 8.6699e-06) + zirc4.add_nuclide(openmc.Nuclide('Fe-56'), 1.3610e-04) + zirc4.add_nuclide(openmc.Nuclide('Fe-57'), 3.1431e-06) + zirc4.add_nuclide(openmc.Nuclide('Fe-58'), 4.1829e-07) + zirc4.add_nuclide(openmc.Nuclide('Zr-90'), 2.1827e-02) + zirc4.add_nuclide(openmc.Nuclide('Zr-91'), 4.7600e-03) + zirc4.add_nuclide(openmc.Nuclide('Zr-92'), 7.2758e-03) + zirc4.add_nuclide(openmc.Nuclide('Zr-94'), 7.3734e-03) + zirc4.add_nuclide(openmc.Nuclide('Zr-96'), 1.1879e-03) + zirc4.add_nuclide(openmc.Nuclide('Sn-112'), 4.6735e-06) + zirc4.add_nuclide(openmc.Nuclide('Sn-114'), 3.1799e-06) + zirc4.add_nuclide(openmc.Nuclide('Sn-115'), 1.6381e-06) + zirc4.add_nuclide(openmc.Nuclide('Sn-116'), 7.0055e-05) + zirc4.add_nuclide(openmc.Nuclide('Sn-117'), 3.7003e-05) + zirc4.add_nuclide(openmc.Nuclide('Sn-118'), 1.1669e-04) + zirc4.add_nuclide(openmc.Nuclide('Sn-119'), 4.1387e-05) + zirc4.add_nuclide(openmc.Nuclide('Sn-120'), 1.5697e-04) + zirc4.add_nuclide(openmc.Nuclide('Sn-122'), 2.2308e-05) + zirc4.add_nuclide(openmc.Nuclide('Sn-124'), 2.7897e-05) + + materials_file = openmc.MaterialsFile() + materials_file.default_xs = '71c' + materials_file.add_materials([water, fuel, zirc4]) + + return (materials_file, + {'mod':water, + 'fuel':fuel, + 'clad':zirc4}) + + +def make_geom(mats): + # Instantiate surfaces. + rfo = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218, name='fuel outer') + rci = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.40005, name='clad inner') + rco = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720, name='clad outer') + + x0 = openmc.XPlane(x0=-0.62992) + x1 = openmc.XPlane(x0=0.62992) + y0 = openmc.YPlane(y0=-0.62992) + y1 = openmc.YPlane(y0=0.62992) + z0 = openmc.ZPlane(z0=-1.0) + z1 = openmc.ZPlane(z0=1.0) + x0.boundary_type = 'reflective' + x1.boundary_type = 'reflective' + y0.boundary_type = 'reflective' + y1.boundary_type = 'reflective' + z0.boundary_type = 'reflective' + z1.boundary_type = 'reflective' + + # Instantiate cells. + fuel_c = openmc.Cell(name='fuel') + fuel_c.add_surface(rfo, halfspace=-1) + fuel_c.add_surface(z0, halfspace=+1) + fuel_c.add_surface(z1, halfspace=-1) + + gap = openmc.Cell(name='gap') + gap.add_surface(rci, halfspace=-1) + gap.add_surface(rfo, halfspace=+1) + gap.add_surface(z0, halfspace=+1) + gap.add_surface(z1, halfspace=-1) + + clad_c = openmc.Cell(name='clad') + clad_c.add_surface(rco, halfspace=-1) + clad_c.add_surface(rci, halfspace=+1) + clad_c.add_surface(z0, halfspace=+1) + clad_c.add_surface(z1, halfspace=-1) + + mod_c = openmc.Cell(name='moderator') + mod_c.add_surface(rco, halfspace=+1) + mod_c.add_surface(x0, halfspace=+1) + mod_c.add_surface(x1, halfspace=-1) + mod_c.add_surface(y0, halfspace=+1) + mod_c.add_surface(y1, halfspace=-1) + mod_c.add_surface(z0, halfspace=+1) + mod_c.add_surface(z1, halfspace=-1) + + # Add materials to cells. + fuel_c.fill = mats['fuel'] + gap.fill = 'void' + clad_c.fill = mats['clad'] + mod_c.fill = mats['mod'] + + # Instantiate universes. + u0 = openmc.Universe(universe_id=0) + u0.add_cells([fuel_c, gap, clad_c, mod_c]) + + # Write the XML file. + geometry = openmc.Geometry() + geometry.root_universe = u0 + geometry_file = openmc.GeometryFile() + geometry_file.geometry = geometry + + return geometry_file + + +def make_settings(**kwargs): + if 'batches' in kwargs: + batches = kwargs['batches'] + + settings_file = openmc.SettingsFile() + settings_file.batches = kwargs.setdefault('batches', 100) + settings_file.inactive = kwargs.setdefault('inactive', 10) + settings_file.particles = kwargs.setdefault('particles', 1000) + settings_file.set_source_space('box', (-0.6, -0.6, -0.9, + 0.6, 0.6, 0.9)) + settings_file.entropy_lower_left = (-0.7, -0.7, -1.1) + settings_file.entropy_upper_right = (0.7, 0.7, 1.1) + settings_file.entropy_dimension = (10, 10, 10) + return settings_file + + +def make_inputs(mod_density=0.7420582, **kwargs): + (mat_file, mats) = make_mats(mod_density) + mat_file.export_to_xml() + + geo_file = make_geom(mats) + geo_file.export_to_xml() + + sets_file = make_settings(**kwargs) + sets_file.export_to_xml() + + +if __name__ == '__main__': + make_inputs(inactive=5, batches=10, particles=100) diff --git a/tests/test_diff_density/geometry.xml b/tests/test_diff_density/geometry.xml new file mode 100644 index 000000000..e7e5b097b --- /dev/null +++ b/tests/test_diff_density/geometry.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/test_diff_density/materials.xml b/tests/test_diff_density/materials.xml new file mode 100644 index 000000000..955ea92e7 --- /dev/null +++ b/tests/test_diff_density/materials.xml @@ -0,0 +1,45 @@ + + + 71c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_diff_density/results_true.dat b/tests/test_diff_density/results_true.dat new file mode 100644 index 000000000..5e515c461 --- /dev/null +++ b/tests/test_diff_density/results_true.dat @@ -0,0 +1,5 @@ +k-combined: +1.502605E+00 2.273838E-02 +tally 1: +5.280104E+00 +1.379258E+01 diff --git a/tests/test_diff_density/settings.xml b/tests/test_diff_density/settings.xml new file mode 100644 index 000000000..a41ba9725 --- /dev/null +++ b/tests/test_diff_density/settings.xml @@ -0,0 +1,18 @@ + + + + 100 + 10 + 5 + + + + -0.6 -0.6 -0.9 0.6 0.6 0.9 + + + + 10 10 10 + -0.7 -0.7 -1.1 + 0.7 0.7 1.1 + + diff --git a/tests/test_diff_density/tallies.xml b/tests/test_diff_density/tallies.xml new file mode 100644 index 000000000..214f33ab3 --- /dev/null +++ b/tests/test_diff_density/tallies.xml @@ -0,0 +1,7 @@ + + + + keff + + + diff --git a/tests/test_diff_density/test_diff_density.py b/tests/test_diff_density/test_diff_density.py new file mode 100755 index 000000000..ed6addec4 --- /dev/null +++ b/tests/test_diff_density/test_diff_density.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness + + +if __name__ == '__main__': + harness = TestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_diff_nuclide_density/build_xml.py b/tests/test_diff_nuclide_density/build_xml.py new file mode 100644 index 000000000..f77a337cb --- /dev/null +++ b/tests/test_diff_nuclide_density/build_xml.py @@ -0,0 +1,164 @@ +import openmc + + +def make_mats(**kwargs): + water_dict = { + 'B-10': 8.0042e-06, + 'B-11': 3.2218e-05, + 'H-1': 4.9457e-02, + 'H-2': 7.4196e-06, + 'O-16': 2.4672e-02, + 'O-17': 9.3982e-06 + 5.0701e-05} + water = openmc.Material(name='water') + water.set_density('sum') + for nuclide in water_dict: + water.add_nuclide(nuclide, water_dict[nuclide]) + + U235_dens = kwargs.setdefault('U235_dens', 5.5814e-04) + fuel_dict = { + 'B-10': 8.0042e-06, + 'U-234': 4.4842e-06, + 'U-235': U235_dens, + 'U-238': 2.2407e-02, + 'O-16': 4.5828e-02, + 'O-17': 1.7457e-05 + 9.4176e-05} + fuel = openmc.Material(name='fuel 2.4%') + fuel.set_density('sum') + for nuclide in fuel_dict: + fuel.add_nuclide(nuclide, fuel_dict[nuclide]) + + zirc4_dict = { + 'O-16': 3.0743e-04, + 'O-17': 1.1711e-07 + 6.3176e-07, + 'Cr-50': 3.2962e-06, + 'Cr-52': 6.3564e-05, + 'Cr-53': 7.2076e-06, + 'Cr-54': 1.7941e-06, + 'Fe-54': 8.6699e-06, + 'Fe-56': 1.3610e-04, + 'Fe-57': 3.1431e-06, + 'Fe-58': 4.1829e-07, + 'Zr-90': 2.1827e-02, + 'Zr-91': 4.7600e-03, + 'Zr-92': 7.2758e-03, + 'Zr-94': 7.3734e-03, + 'Zr-96': 1.1879e-03, + 'Sn-112': 4.6735e-06, + 'Sn-114': 3.1799e-06, + 'Sn-115': 1.6381e-06, + 'Sn-116': 7.0055e-05, + 'Sn-117': 3.7003e-05, + 'Sn-118': 1.1669e-04, + 'Sn-119': 4.1387e-05, + 'Sn-120': 1.5697e-04, + 'Sn-122': 2.2308e-05, + 'Sn-124': 2.7897e-05} + zirc4 = openmc.Material(name='zircaloy 4') + zirc4.set_density('sum') + for nuclide in zirc4_dict: + zirc4.add_nuclide(nuclide, zirc4_dict[nuclide]) + + materials_file = openmc.MaterialsFile() + materials_file.default_xs = '71c' + materials_file.add_materials([water, fuel, zirc4]) + + return (materials_file, + {'mod':water, + 'fuel':fuel, + 'clad':zirc4}) + + +def make_geom(mats): + # Instantiate surfaces. + rfo = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218, name='fuel outer') + rci = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.40005, name='clad inner') + rco = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720, name='clad outer') + + x0 = openmc.XPlane(x0=-0.62992) + x1 = openmc.XPlane(x0=0.62992) + y0 = openmc.YPlane(y0=-0.62992) + y1 = openmc.YPlane(y0=0.62992) + z0 = openmc.ZPlane(z0=-1.0) + z1 = openmc.ZPlane(z0=1.0) + x0.boundary_type = 'reflective' + x1.boundary_type = 'reflective' + y0.boundary_type = 'reflective' + y1.boundary_type = 'reflective' + z0.boundary_type = 'reflective' + z1.boundary_type = 'reflective' + + # Instantiate cells. + fuel_c = openmc.Cell(name='fuel') + fuel_c.add_surface(rfo, halfspace=-1) + fuel_c.add_surface(z0, halfspace=+1) + fuel_c.add_surface(z1, halfspace=-1) + + gap = openmc.Cell(name='gap') + gap.add_surface(rci, halfspace=-1) + gap.add_surface(rfo, halfspace=+1) + gap.add_surface(z0, halfspace=+1) + gap.add_surface(z1, halfspace=-1) + + clad_c = openmc.Cell(name='clad') + clad_c.add_surface(rco, halfspace=-1) + clad_c.add_surface(rci, halfspace=+1) + clad_c.add_surface(z0, halfspace=+1) + clad_c.add_surface(z1, halfspace=-1) + + mod_c = openmc.Cell(name='moderator') + mod_c.add_surface(rco, halfspace=+1) + mod_c.add_surface(x0, halfspace=+1) + mod_c.add_surface(x1, halfspace=-1) + mod_c.add_surface(y0, halfspace=+1) + mod_c.add_surface(y1, halfspace=-1) + mod_c.add_surface(z0, halfspace=+1) + mod_c.add_surface(z1, halfspace=-1) + + # Add materials to cells. + fuel_c.fill = mats['fuel'] + gap.fill = 'void' + clad_c.fill = mats['clad'] + mod_c.fill = mats['mod'] + + # Instantiate universes. + u0 = openmc.Universe(universe_id=0) + u0.add_cells([fuel_c, gap, clad_c, mod_c]) + + # Write the XML file. + geometry = openmc.Geometry() + geometry.root_universe = u0 + geometry_file = openmc.GeometryFile() + geometry_file.geometry = geometry + + return geometry_file + + +def make_settings(**kwargs): + if 'batches' in kwargs: + batches = kwargs['batches'] + + settings_file = openmc.SettingsFile() + settings_file.batches = kwargs.setdefault('batches', 1610) + settings_file.inactive = kwargs.setdefault('inactive', 10) + settings_file.particles = kwargs.setdefault('particles', 1000) + settings_file.set_source_space('box', (-0.6, -0.6, -0.9, + 0.6, 0.6, 0.9)) + settings_file.entropy_lower_left = (-0.7, -0.7, -1.1) + settings_file.entropy_upper_right = (0.7, 0.7, 1.1) + settings_file.entropy_dimension = (10, 10, 10) + return settings_file + + +def make_inputs(**kwargs): + (mat_file, mats) = make_mats(**kwargs) + mat_file.export_to_xml() + + geo_file = make_geom(mats) + geo_file.export_to_xml() + + sets_file = make_settings(**kwargs) + sets_file.export_to_xml() + + +if __name__ == '__main__': + make_inputs(inactive=5, batches=10, particles=100) diff --git a/tests/test_diff_nuclide_density/geometry.xml b/tests/test_diff_nuclide_density/geometry.xml new file mode 100644 index 000000000..e7e5b097b --- /dev/null +++ b/tests/test_diff_nuclide_density/geometry.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/test_diff_nuclide_density/materials.xml b/tests/test_diff_nuclide_density/materials.xml new file mode 100644 index 000000000..02b55f452 --- /dev/null +++ b/tests/test_diff_nuclide_density/materials.xml @@ -0,0 +1,50 @@ + + + 71c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_diff_nuclide_density/results_true.dat b/tests/test_diff_nuclide_density/results_true.dat new file mode 100644 index 000000000..68b611ae1 --- /dev/null +++ b/tests/test_diff_nuclide_density/results_true.dat @@ -0,0 +1,5 @@ +k-combined: +1.055198E+00 5.785829E-02 +tally 1: +3.081784E+03 +1.905482E+06 diff --git a/tests/test_diff_nuclide_density/settings.xml b/tests/test_diff_nuclide_density/settings.xml new file mode 100644 index 000000000..a41ba9725 --- /dev/null +++ b/tests/test_diff_nuclide_density/settings.xml @@ -0,0 +1,18 @@ + + + + 100 + 10 + 5 + + + + -0.6 -0.6 -0.9 0.6 0.6 0.9 + + + + 10 10 10 + -0.7 -0.7 -1.1 + 0.7 0.7 1.1 + + diff --git a/tests/test_diff_nuclide_density/tallies.xml b/tests/test_diff_nuclide_density/tallies.xml new file mode 100644 index 000000000..321b2c9b0 --- /dev/null +++ b/tests/test_diff_nuclide_density/tallies.xml @@ -0,0 +1,10 @@ + + + + keff + + + + diff --git a/tests/test_diff_nuclide_density/test_diff_nuclide_density.py b/tests/test_diff_nuclide_density/test_diff_nuclide_density.py new file mode 100755 index 000000000..ed6addec4 --- /dev/null +++ b/tests/test_diff_nuclide_density/test_diff_nuclide_density.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness + + +if __name__ == '__main__': + harness = TestHarness('statepoint.10.*', True) + harness.main() From d31fd3470c43778ec29911ed9607b48be2ffe6e1 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 8 Nov 2015 22:03:30 -0500 Subject: [PATCH 02/60] Add diff tallies to statepoints, PyAPI --- openmc/statepoint.py | 23 +++++++++++ openmc/tallies.py | 92 +++++++++++++++++++++++++++++++++++++++++++- src/initialize.F90 | 10 ++++- src/output.F90 | 17 ++++++++ src/state_point.F90 | 32 ++++++++++++++- src/tally.F90 | 7 ++++ 6 files changed, 178 insertions(+), 3 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 2edf9badd..047581d1f 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -349,6 +349,29 @@ class StatePoint(object): base, tally_key)].value.decode() tally.num_realizations = n_realizations + # Read derivative information. + derivatives_present = self._f[ + '{0}{1}/derivative present'.format(base, tally_key)].value + assert derivatives_present in (0, 1) + if derivatives_present == 1: + tally.diff_variable = self._f[ + '{0}{1}/derivative/dependent variable'.format( + base, tally_key)].value.decode() + if tally.diff_variable == 'density': + tally.diff_material = self._f[ + '{0}{1}/derivative/material'.format( + base, tally_key)].value + elif tally.diff_variable == 'nuclide_density': + tally.diff_material = self._f[ + '{0}{1}/derivative/material'.format( + base, tally_key)].value + tally.diff_nuclide = self._f[ + '{0}{1}/derivative/nuclide'.format( + base, tally_key)].value.decode() + else: + raise RuntimeError('Unrecognized tally differential' + 'variable') + # Read the number of Filters n_filters = self._f['{0}{1}/n_filters'.format(base, tally_key)].value diff --git a/openmc/tallies.py b/openmc/tallies.py index 0661ab67b..4ada71519 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -93,6 +93,9 @@ class Tally(object): self._scores = [] self._estimator = None self._triggers = [] + self._diff_variable = None + self._diff_material = None + self._diff_nuclide = None self._num_score_bins = 0 self._num_realizations = 0 @@ -117,6 +120,9 @@ class Tally(object): clone.id = self.id clone.name = self.name clone.estimator = self.estimator + clone._diff_variable = self.diff_variable + clone._diff_material = self.diff_material + clone._diff_nuclide = self.diff_nuclide clone.num_score_bins = self.num_score_bins clone.num_realizations = self.num_realizations clone._sum = copy.deepcopy(self._sum, memo) @@ -173,6 +179,14 @@ class Tally(object): if nuclide not in other.nuclides: return False + # Check derivatives + if self.diff_variable != other.diff_variable: + return False + if self.diff_material != other.diff_material: + return False + if self.diff_nuclide != other.diff_nuclide: + return False + # Check all scores if len(self.scores) != len(other.scores): return False @@ -203,6 +217,9 @@ class Tally(object): hashable.append(self.estimator) hashable.append(self.name) + hashable.append(self._diff_variable) + hashable.append(self._diff_material) + hashable.append(self._diff_nuclide) return hash(tuple(hashable)) @@ -211,6 +228,21 @@ class Tally(object): string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self.name) + if self.diff_variable is not None: + string += '{0: <16}{1}{2}\n'.format('\tDerivative', '=\t', + self.diff_variable) + if self.diff_variable == 'density': + string += '{0: <16}{1}{2}\n'.format('\tDiff_material', '=\t', + self.diff_material) + elif self.diff_variable == 'nuclide_density': + string += '{0: <16}{1}{2}\n'.format('\tDiff_material', '=\t', + self.diff_material) + string += '{0: <16}{1}{2}\n'.format('\tDiff_nuclide', '=\t', + self.diff_nuclide) + else: + raise RuntimeError("Encountered unrecognized differential " + "variable in a tally.") + string += '{0: <16}{1}\n'.format('\tFilters', '=\t') for filter in self.filters: @@ -379,6 +411,18 @@ class Tally(object): def derived(self): return self._derived + @property + def diff_variable(self): + return self._diff_variable + + @property + def diff_material(self): + return self._diff_material + + @property + def diff_nuclide(self): + return self._diff_nuclide + @estimator.setter def estimator(self, estimator): cv.check_value('estimator', estimator, @@ -422,6 +466,27 @@ class Tally(object): else: self._name = '' + @diff_variable.setter + def diff_variable(self, var): + if var is not None: + cv.check_type('differential variable', var, basestring) + if var not in ('density', 'nuclide_density'): + raise ValueError("A tally differential variable must be either " + "'density' or 'nuclide_density'") + self._diff_variable = var + + @diff_material.setter + def diff_material(self, mat): + if mat is not None: + cv.check_type('differential material', mat, Integral) + self._diff_material = mat + + @diff_nuclide.setter + def diff_nuclide(self, nuc): + if nuc is not None: + cv.check_type('differential nuclide', nuc, basestring) + self._diff_nuclide = nuc + def add_filter(self, filter): """Add a filter to the tally @@ -703,6 +768,21 @@ class Tally(object): subelement = ET.SubElement(element, "nuclides") subelement.text = nuclides.rstrip(' ') + # Optional derivative + if self.diff_variable is not None: + if self.diff_variable == 'density': + subelement = ET.SubElement(element, "derivative") + subelement.set("variable", self.diff_variable) + subelement.set("material", str(self.diff_material)) + elif self.diff_variable == 'nuclide_density': + subelement = ET.SubElement(element, "derivative") + subelement.set("variable", self.diff_variable) + subelement.set("material", str(self.diff_material)) + subelement.set("nuclide", self.diff_nuclide) + else: + raise RuntimeError("Encountered unrecognized differential " + "variable in a tally.") + # Scores if len(self.scores) == 0: msg = 'Unable to get XML for Tally ID="{0}" since it does not ' \ @@ -1122,7 +1202,7 @@ class Tally(object): return data def get_pandas_dataframe(self, filters=True, nuclides=True, - scores=True, summary=None): + scores=True, derivative=True, summary=None): """Build a Pandas DataFrame for the Tally data. This method constructs a Pandas DataFrame object for the Tally data @@ -1140,6 +1220,8 @@ class Tally(object): Include columns with nuclide bin information (default is True). scores : bool Include columns with score bin information (default is True). + derivative : bool + Include columns with differential tally info (default is True). summary : None or Summary An optional Summary object to be used to construct columns for distribcell tally filters (default is None). The geometric @@ -1221,6 +1303,14 @@ class Tally(object): tile_factor = data_size / len(self.scores) df['score'] = np.tile(self.scores, tile_factor) + # Include columns for derivatives if user requested it + if derivative and (self.diff_variable is not None): + df['d_variable'] = self.diff_variable + if self.diff_material is not None: + df['d_material'] = self.diff_material + if self.diff_nuclide is not None: + df['d_nuclide'] = self.diff_nuclide + # Append columns with mean, std. dev. for each tally bin df['mean'] = self.mean.ravel() df['std. dev.'] = self.std_dev.ravel() diff --git a/src/initialize.F90 b/src/initialize.F90 index 6130be0e2..82252952d 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -831,7 +831,6 @@ contains ! Change density in g/cm^3 to atom/b-cm. Since all values are now in atom ! percent, the sum needs to be re-evaluated as 1/sum(x*awr) if (.not. density_in_atom) then - mat % density_gpcc = -mat % density sum_percent = ZERO do j = 1, mat%n_nuclides index_list = xs_listing_dict%get_key(mat%names(j)) @@ -846,6 +845,15 @@ contains ! Calculate nuclide atom densities mat%atom_density = mat%density * mat%atom_density + + ! Calculate density in g/cm^3. + mat%density_gpcc = ZERO + do j = 1, mat%n_nuclides + index_list = xs_listing_dict%get_key(mat%names(j)) + awr = xs_listings(index_list)%awr + mat%density_gpcc = mat%density_gpcc & + + mat%atom_density(j) * awr * MASS_NEUTRON / N_AVOGADRO + end do end do end subroutine normalize_ao diff --git a/src/output.F90 b/src/output.F90 index 0f667c121..004340480 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -1023,6 +1023,23 @@ contains // trim(t % name), unit=unit_tally, level=3) endif + ! Write derivative information. + if (allocated(t % deriv)) then + select case (t % deriv % dep_var) + case (DIFF_DENSITY) + write(unit=unit_tally, fmt="(' Density derivative Material ',A)") & + to_str(t % deriv % diff_material) + case (DIFF_NUCLIDE_DENSITY) + i_listing = nuclides(t % deriv % diff_nuclide) % listing + write(unit=unit_tally, fmt="(' Nuclide density derivative Material '& + &,A,' Nuclide ',A)") trim(to_str(t % deriv % diff_material)), & + trim(xs_listings(i_listing) % alias) + case default + call fatal_error("Differential tally dependent variable for tally " & + // trim(to_str(t % id)) // " not defined in output.F90.") + end select + end if + ! Handle surface current tallies separately if (t % type == TALLY_SURFACE_CURRENT) then call write_surface_current(t, unit_tally) diff --git a/src/state_point.F90 b/src/state_point.F90 index 046e7e666..84554cd94 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -51,7 +51,7 @@ contains integer(HID_T) :: cmfd_group integer(HID_T) :: tallies_group, tally_group integer(HID_T) :: meshes_group, mesh_group - integer(HID_T) :: filter_group + integer(HID_T) :: filter_group, deriv_group character(20), allocatable :: str_array(:) character(MAX_FILE_LEN) :: filename type(RegularMesh), pointer :: meshp @@ -307,6 +307,34 @@ contains call write_dataset(tally_group, "nuclides", str_array) deallocate(str_array) + ! Write derivative information. + if (allocated(tally % deriv)) then + call write_dataset(tally_group, "derivative present", 1) + deriv_group = create_group(tally_group, "derivative") + select case (tally % deriv % dep_var) + case (DIFF_DENSITY) + call write_dataset(deriv_group, "dependent variable", "density") + call write_dataset(deriv_group, "material", & + tally % deriv % diff_material) + case (DIFF_NUCLIDE_DENSITY) + call write_dataset(deriv_group, "dependent variable", & + "nuclide_density") + call write_dataset(deriv_group, "material", & + tally % deriv % diff_material) + i_list = nuclides(tally % deriv % diff_nuclide) % listing + call write_dataset(deriv_group, "nuclide", & + xs_listings(i_list) % alias) + case default + call fatal_error("Differential tally dependent variable for & + &tally " // trim(to_str(tally % id)) // " not defined in & + &state_point.F90.") + end select + call close_group(deriv_group) + else + call write_dataset(tally_group, "derivative present", 0) + end if + + ! Write scores. call write_dataset(tally_group, "n_score_bins", tally%n_score_bins) allocate(str_array(size(tally%score_bins))) do j = 1, size(tally%score_bins) @@ -355,6 +383,8 @@ contains str_array(j) = "events" case (SCORE_INVERSE_VELOCITY) str_array(j) = "inverse-velocity" + case (SCORE_KEFF) + str_array(j) = "keff" case default str_array(j) = reaction_name(tally%score_bins(j)) end select diff --git a/src/tally.F90 b/src/tally.F90 index 7fce90cce..d5f36bbe7 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -745,6 +745,9 @@ contains if (allocated(t % deriv) .and. t % estimator == ESTIMATOR_COLLISION) then select case (score_bin) + case (SCORE_FLUX) + score = score * t % deriv % accumulator + case (SCORE_KEFF) select case (t % deriv % dep_var) @@ -765,6 +768,10 @@ contains end if end select + + case default + call fatal_error('Tally derivative not defined for a score on tally '& + // trim(to_str(t % id))) end select end if From 7a17cd14acffff4226d821dcdb4efcdd8bef7ee8 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 21 Nov 2015 00:46:22 -0500 Subject: [PATCH 03/60] Add diff fission and absorption tallies --- src/input_xml.F90 | 14 ++++---- src/tally.F90 | 91 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 80 insertions(+), 25 deletions(-) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index bc2e56bb8..4b9a1b6e4 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3093,10 +3093,6 @@ contains &filter.") end if - if (allocated(t % deriv)) then - t % estimator = ESTIMATOR_COLLISION - end if - case ('flux-yn') ! Prohibit user from tallying flux for an individual nuclide if (.not. (t % n_nuclide_bins == 1 .and. & @@ -3296,9 +3292,6 @@ contains case ('keff') t % score_bins(j) = SCORE_KEFF - if (allocated(t % deriv)) then - t % estimator = ESTIMATOR_COLLISION - end if case ('elastic', '(n,elastic)') t % score_bins(j) = ELASTIC @@ -3405,6 +3398,13 @@ contains &// trim(to_str(t % id)) // ".") end if + ! If a derivative is present, we can only use analog or collision + ! estimators. + if (allocated(t % deriv) .and. t % estimator == ESTIMATOR_TRACKLENGTH) & + then + t % estimator = ESTIMATOR_COLLISION + end if + ! If settings.xml trigger is turned on, create tally triggers if (trigger_on) then diff --git a/src/tally.F90 b/src/tally.F90 index b4b6e7394..464379bbd 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -66,6 +66,7 @@ contains real(8) :: macro_scatt ! material macro scatt xs real(8) :: uvw(3) ! particle direction real(8) :: E ! particle energy + logical :: scoring_diff_nuclide type(Material), pointer :: mat type(Reaction), pointer :: rxn type(Nuclide), pointer :: nuc @@ -762,36 +763,87 @@ contains !######################################################################### ! Add derivative information on score for differential tallies. - if (allocated(t % deriv) .and. t % estimator == ESTIMATOR_COLLISION) then - select case (score_bin) + if (allocated(t % deriv)) then + select case (t % estimator) - case (SCORE_FLUX) + case (ESTIMATOR_ANALOG) score = score * t % deriv % accumulator - case (SCORE_KEFF) - select case (t % deriv % dep_var) - - case (DIFF_DENSITY) - score = score * t % deriv % accumulator - - case (DIFF_NUCLIDE_DENSITY) + case (ESTIMATOR_COLLISION) + if (t % deriv % dep_var == DIFF_NUCLIDE_DENSITY) then mat => materials(p % material) - if (mat % id == t % deriv % diff_material .and. & - micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO) then + scoring_diff_nuclide = (mat % id == t % deriv % diff_material) & + .and. (i_nuclide <= 0 & + .or. (i_nuclide == t % deriv % diff_nuclide)) + select case (score_bin) + case (SCORE_ABSORPTION) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % absorption /= ZERO + case (SCORE_FISSION) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % fission /= ZERO + case (SCORE_NU_FISSION) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO + case (SCORE_KAPPA_FISSION) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % kappa_fission & + /= ZERO + case (SCORE_KEFF) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO + end select + + if (scoring_diff_nuclide) then do l = 1, mat % n_nuclides if (mat % nuclide(l) == t % deriv % diff_nuclide) exit end do - score = score * (t % deriv % accumulator + ONE & - / mat % atom_density(l)) - else - score = score * t % deriv % accumulator end if + end if + select case (score_bin) + + case (SCORE_FLUX) + score = score * t % deriv % accumulator + + case (SCORE_ABSORPTION, SCORE_FISSION, SCORE_NU_FISSION, & + SCORE_KAPPA_FISSION) + select case (t % deriv % dep_var) + + case (DIFF_NUCLIDE_DENSITY) + if (scoring_diff_nuclide) then + score = score * (t % deriv % accumulator + ONE & + / mat % atom_density(l)) + else + score = score * t % deriv % accumulator + end if + + end select + + case (SCORE_KEFF) + select case (t % deriv % dep_var) + + case (DIFF_DENSITY) + score = score * t % deriv % accumulator + + case (DIFF_NUCLIDE_DENSITY) + if (scoring_diff_nuclide) then + score = score * (t % deriv % accumulator + ONE & + / mat % atom_density(l)) + else + score = score * t % deriv % accumulator + end if + + end select + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) end select case default - call fatal_error('Tally derivative not defined for a score on tally '& - // trim(to_str(t % id))) + call fatal_error("Differential tallies are only implemented for & + &analog and collision estimators.") end select end if @@ -1091,6 +1143,9 @@ contains ! determine score based on bank site weight and keff score = keff * fission_bank(n_bank - p % n_bank + k) % wgt + ! Add derivative information for differenetial tallies. + if (allocated(t % deriv)) score = score * t % deriv % accumulator + ! determine outgoing energy from fission bank E_out = fission_bank(n_bank - p % n_bank + k) % E From a4a47804f44b2df7374789e025ee60e2d6816885 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 26 Nov 2015 19:57:53 -0500 Subject: [PATCH 04/60] Fix total nuclide diff tallies --- src/tally.F90 | 71 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 464379bbd..1613972b2 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -773,8 +773,7 @@ contains if (t % deriv % dep_var == DIFF_NUCLIDE_DENSITY) then mat => materials(p % material) scoring_diff_nuclide = (mat % id == t % deriv % diff_material) & - .and. (i_nuclide <= 0 & - .or. (i_nuclide == t % deriv % diff_nuclide)) + .and. (i_nuclide == t % deriv % diff_nuclide) select case (score_bin) case (SCORE_ABSORPTION) scoring_diff_nuclide = scoring_diff_nuclide .and. & @@ -793,12 +792,6 @@ contains scoring_diff_nuclide = scoring_diff_nuclide .and. & micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO end select - - if (scoring_diff_nuclide) then - do l = 1, mat % n_nuclides - if (mat % nuclide(l) == t % deriv % diff_nuclide) exit - end do - end if end if select case (score_bin) @@ -806,14 +799,68 @@ contains case (SCORE_FLUX) score = score * t % deriv % accumulator - case (SCORE_ABSORPTION, SCORE_FISSION, SCORE_NU_FISSION, & - SCORE_KAPPA_FISSION) + case (SCORE_ABSORPTION) select case (t % deriv % dep_var) case (DIFF_NUCLIDE_DENSITY) - if (scoring_diff_nuclide) then + if (i_nuclide == -1) then + score = score * (t % deriv % accumulator & + + micro_xs(t % deriv % diff_nuclide) % absorption & + / material_xs % absorption) + else if (scoring_diff_nuclide) then score = score * (t % deriv % accumulator + ONE & - / mat % atom_density(l)) + / atom_density) + else + score = score * t % deriv % accumulator + end if + + end select + + case (SCORE_FISSION) + select case (t % deriv % dep_var) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1) then + score = score * (t % deriv % accumulator & + + micro_xs(t % deriv % diff_nuclide) % fission & + / material_xs % fission) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % accumulator + ONE & + / atom_density) + else + score = score * t % deriv % accumulator + end if + + end select + + case (SCORE_NU_FISSION) + select case (t % deriv % dep_var) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1) then + score = score * (t % deriv % accumulator & + + micro_xs(t % deriv % diff_nuclide) % nu_fission & + / material_xs % nu_fission) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % accumulator + ONE & + / atom_density) + else + score = score * t % deriv % accumulator + end if + + end select + + case (SCORE_KAPPA_FISSION) + select case (t % deriv % dep_var) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1) then + score = score * (t % deriv % accumulator & + + micro_xs(t % deriv % diff_nuclide) % kappa_fission & + / material_xs % kappa_fission) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % accumulator + ONE & + / atom_density) else score = score * t % deriv % accumulator end if From d75ed8454460d5b3071b84a529676a877fb23d98 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 26 Nov 2015 23:10:08 -0500 Subject: [PATCH 05/60] Add total score for nuclide diff tallies --- src/tally.F90 | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 1613972b2..4b2a56247 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -775,6 +775,9 @@ contains scoring_diff_nuclide = (mat % id == t % deriv % diff_material) & .and. (i_nuclide == t % deriv % diff_nuclide) select case (score_bin) + case (SCORE_TOTAL) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % total /= ZERO case (SCORE_ABSORPTION) scoring_diff_nuclide = scoring_diff_nuclide .and. & micro_xs(t % deriv % diff_nuclide) % absorption /= ZERO @@ -799,14 +802,33 @@ contains case (SCORE_FLUX) score = score * t % deriv % accumulator + case (SCORE_TOTAL) + select case (t % deriv % dep_var) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then + score = score * (t % deriv % accumulator & + + micro_xs(t % deriv % diff_nuclide) % total & + / material_xs % total) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % accumulator + ONE & + / atom_density) + else + score = score * t % deriv % accumulator + end if + + end select + case (SCORE_ABSORPTION) select case (t % deriv % dep_var) case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1) then + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then score = score * (t % deriv % accumulator & + micro_xs(t % deriv % diff_nuclide) % absorption & - / material_xs % absorption) + / material_xs % absorption ) else if (scoring_diff_nuclide) then score = score * (t % deriv % accumulator + ONE & / atom_density) @@ -820,7 +842,8 @@ contains select case (t % deriv % dep_var) case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1) then + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then score = score * (t % deriv % accumulator & + micro_xs(t % deriv % diff_nuclide) % fission & / material_xs % fission) @@ -837,7 +860,8 @@ contains select case (t % deriv % dep_var) case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1) then + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then score = score * (t % deriv % accumulator & + micro_xs(t % deriv % diff_nuclide) % nu_fission & / material_xs % nu_fission) @@ -854,7 +878,8 @@ contains select case (t % deriv % dep_var) case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1) then + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then score = score * (t % deriv % accumulator & + micro_xs(t % deriv % diff_nuclide) % kappa_fission & / material_xs % kappa_fission) From 6ab847be4d90f8afa8ed8c06285aaaa27054d86e Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 11 Jan 2016 13:07:08 -0500 Subject: [PATCH 06/60] Use better collision derivative estimate --- src/tally.F90 | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index ca12d41f6..23ebf1e21 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2414,14 +2414,9 @@ contains t % deriv % accumulator = t % deriv % accumulator & - distance * micro_xs(t % deriv % diff_nuclide) % total if (collision) then - if (p % event == EVENT_SCATTER) then - t % deriv % accumulator = t % deriv % accumulator & - + micro_xs(t % deriv % diff_nuclide) % elastic & - / material_xs % elastic - else if (p % event == EVENT_ABSORB) then - t % deriv % accumulator = t % deriv % accumulator & - + micro_xs(t % deriv % diff_nuclide) % absorption & - / material_xs % absorption + if (p % event_nuclide == t % deriv % diff_nuclide) then + t % deriv % accumulator = t % deriv % accumulator & + + ONE / mat % atom_density(j) end if end if end if From 7f3e6bdd8890a819ed96dbdcf07f5adee409dd7f Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Tue, 12 Jan 2016 00:49:18 -0500 Subject: [PATCH 07/60] Fix diff tally analog estimator --- src/input_xml.F90 | 4 +--- src/tally.F90 | 12 +++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 6d0e2d456..ef6b548e6 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3401,9 +3401,7 @@ contains ! If a derivative is present, we can only use analog or collision ! estimators. if (allocated(t % deriv) .and. t % estimator == ESTIMATOR_TRACKLENGTH) & - then - t % estimator = ESTIMATOR_COLLISION - end if + t % estimator = ESTIMATOR_COLLISION ! If settings.xml trigger is turned on, create tally triggers if (trigger_on) then diff --git a/src/tally.F90 b/src/tally.F90 index 23ebf1e21..3ab6fe520 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -758,7 +758,17 @@ contains select case (t % estimator) case (ESTIMATOR_ANALOG) - score = score * t % deriv % accumulator + if (p % event_nuclide == t % deriv % diff_nuclide) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == t % deriv % diff_nuclide) exit + end do + score = score * (t % deriv % accumulator & + + ONE / mat % atom_density(l)) + end associate + else + score = score * t % deriv % accumulator + end if case (ESTIMATOR_COLLISION) if (t % deriv % dep_var == DIFF_NUCLIDE_DENSITY) then From 509c4150d35ef87c5e8cf1766ffab99f12d069c6 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 17 Jan 2016 21:00:46 -0500 Subject: [PATCH 08/60] Split track and collison derivative accumulations --- src/tally.F90 | 147 ++++++++++-------- src/tally_header.F90 | 2 +- src/tracking.F90 | 10 +- .../results_true.dat | 4 +- 4 files changed, 94 insertions(+), 69 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 3ab6fe520..6a020eadb 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -763,11 +763,11 @@ contains do l = 1, mat % n_nuclides if (mat % nuclide(l) == t % deriv % diff_nuclide) exit end do - score = score * (t % deriv % accumulator & + score = score * (t % deriv % flux_deriv & + ONE / mat % atom_density(l)) end associate else - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv end if case (ESTIMATOR_COLLISION) @@ -797,7 +797,7 @@ contains select case (score_bin) case (SCORE_FLUX) - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv case (SCORE_TOTAL) select case (t % deriv % dep_var) @@ -805,14 +805,14 @@ contains case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % accumulator & + score = score * (t % deriv % flux_deriv & + micro_xs(t % deriv % diff_nuclide) % total & / material_xs % total) else if (scoring_diff_nuclide) then - score = score * (t % deriv % accumulator + ONE & + score = score * (t % deriv % flux_deriv + ONE & / atom_density) else - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv end if end select @@ -823,14 +823,14 @@ contains case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % accumulator & + score = score * (t % deriv % flux_deriv & + micro_xs(t % deriv % diff_nuclide) % absorption & / material_xs % absorption ) else if (scoring_diff_nuclide) then - score = score * (t % deriv % accumulator + ONE & + score = score * (t % deriv % flux_deriv + ONE & / atom_density) else - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv end if end select @@ -841,14 +841,14 @@ contains case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % accumulator & + score = score * (t % deriv % flux_deriv & + micro_xs(t % deriv % diff_nuclide) % fission & / material_xs % fission) else if (scoring_diff_nuclide) then - score = score * (t % deriv % accumulator + ONE & + score = score * (t % deriv % flux_deriv + ONE & / atom_density) else - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv end if end select @@ -859,14 +859,14 @@ contains case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % accumulator & + score = score * (t % deriv % flux_deriv & + micro_xs(t % deriv % diff_nuclide) % nu_fission & / material_xs % nu_fission) else if (scoring_diff_nuclide) then - score = score * (t % deriv % accumulator + ONE & + score = score * (t % deriv % flux_deriv + ONE & / atom_density) else - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv end if end select @@ -875,14 +875,14 @@ contains select case (t % deriv % dep_var) case (DIFF_DENSITY) - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv case (DIFF_NUCLIDE_DENSITY) if (scoring_diff_nuclide) then - score = score * (t % deriv % accumulator + ONE & + score = score * (t % deriv % flux_deriv + ONE & / materials(p % material) % atom_density(l)) else - score = score * t % deriv % accumulator + score = score * t % deriv % flux_deriv end if end select @@ -1194,7 +1194,7 @@ contains score = keff * fission_bank(n_bank - p % n_bank + k) % wgt ! Add derivative information for differenetial tallies. - if (allocated(t % deriv)) score = score * t % deriv % accumulator + if (allocated(t % deriv)) score = score * t % deriv % flux_deriv ! determine outgoing energy from fission bank E_out = fission_bank(n_bank - p % n_bank + k) % E @@ -2379,70 +2379,91 @@ contains end subroutine score_surface_current !=============================================================================== -! SCORE_DIFF_ACCUMULATORS +! SCORE_TRACK_DERIVATIVE !=============================================================================== - subroutine score_diff_accumulators(p, distance, collision) + subroutine score_track_derivative(p, distance) type(particle), intent(in) :: p real(8), intent(in) :: distance - logical, intent(in) :: collision - integer :: i, j - type(TallyObject), pointer :: t - type(Material), pointer :: mat + integer :: i - do i = 1, n_user_tallies - t => user_tallies(i) + if (p % material == MATERIAL_VOID) return + + do i = 1, active_tallies % size() + associate (t => tallies(active_tallies % get_item(i))) + if (.not. allocated(t % deriv)) cycle - if (allocated(t % deriv)) then select case (t % deriv % dep_var) case (DIFF_DENSITY) - if (p % material == MATERIAL_VOID) cycle - mat => materials(p % material) - if (mat % id == t % deriv % diff_material) then - if (collision) then - t % deriv % accumulator = t % deriv % accumulator & - + ONE / mat % density_gpcc & - - distance * material_xs % total / mat % density_gpcc - else - t % deriv % accumulator = t % deriv % accumulator & + associate (mat => materials(p % material)) + if (mat % id == t % deriv % diff_material) then + t % deriv % flux_deriv = t % deriv % flux_deriv & - distance * material_xs % total / mat % density_gpcc end if - end if + end associate case (DIFF_NUCLIDE_DENSITY) - if (p % material == MATERIAL_VOID) cycle - mat => materials(p % material) - if (mat % id == t % deriv % diff_material) then - do j = 1, mat % n_nuclides - if (mat % nuclide(j) == t % deriv % diff_nuclide) exit - end do - if (mat % nuclide(j) /= t % deriv % diff_nuclide) then - call fatal_error("Couldn't find the right nuclide.") + associate (mat => materials(p % material)) + if (mat % id == t % deriv % diff_material) then + t % deriv % flux_deriv = t % deriv % flux_deriv & + - distance * micro_xs(t % deriv % diff_nuclide) % total end if - t % deriv % accumulator = t % deriv % accumulator & - - distance * micro_xs(t % deriv % diff_nuclide) % total - if (collision) then - if (p % event_nuclide == t % deriv % diff_nuclide) then - t % deriv % accumulator = t % deriv % accumulator & - + ONE / mat % atom_density(j) - end if - end if - end if + end associate end select - end if + end associate end do end subroutine - subroutine clear_diff_accumulators() - integer :: i - type(TallyObject), pointer :: t +!=============================================================================== +! SCORE_COLLISION_DERIVATIVE +!=============================================================================== - do i = 1, n_user_tallies - t => user_tallies(i) - if (allocated(t % deriv)) then - t % deriv % accumulator = ZERO + subroutine score_collision_derivative(p) + type(particle), intent(in) :: p + + integer :: i, j + + if (p % material == MATERIAL_VOID) return + + do i = 1, active_tallies % size() + associate (t => tallies(active_tallies % get_item(i))) + if (.not. allocated(t % deriv)) cycle + select case (t % deriv % dep_var) + + case (DIFF_DENSITY) + associate (mat => materials(p % material)) + if (mat % id == t % deriv % diff_material) then + t % deriv % flux_deriv = t % deriv % flux_deriv & + + ONE / mat % density_gpcc + end if + end associate + + case (DIFF_NUCLIDE_DENSITY) + associate (mat => materials(p % material)) + if (mat % id == t % deriv % diff_material & + .and. p % event_nuclide == t % deriv % diff_nuclide) then + do j = 1, mat % n_nuclides + if (mat % nuclide(j) == t % deriv % diff_nuclide) exit + end do + if (mat % nuclide(j) /= t % deriv % diff_nuclide) then + call fatal_error("Couldn't find the right nuclide.") + end if + t % deriv % flux_deriv = t % deriv % flux_deriv & + + ONE / mat % atom_density(j) + end if + end associate + end select + end associate + end do + end subroutine + + subroutine clear_diff_flux_derivs() + integer :: i + do i = 1, n_tallies + if (allocated(tallies(i) % deriv)) then + tallies(i) % deriv % flux_deriv = ZERO end if end do end subroutine diff --git a/src/tally_header.F90 b/src/tally_header.F90 index 623fdde41..bbdce44f6 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -66,7 +66,7 @@ module tally_header !=============================================================================== type TallyDerivative - real(8) :: accumulator + real(8) :: flux_deriv integer :: dep_var integer :: diff_material integer :: diff_nuclide diff --git a/src/tracking.F90 b/src/tracking.F90 index 9502746da..1ad379490 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -14,7 +14,8 @@ module tracking use string, only: to_str use tally, only: score_analog_tally, score_tracklength_tally, & score_collision_tally, score_surface_current, & - score_diff_accumulators, clear_diff_accumulators + score_track_derivative, & + score_collision_derivative, clear_diff_flux_derivs use track_output, only: initialize_particle_track, write_particle_track, & add_particle_track, finalize_particle_track @@ -62,7 +63,7 @@ contains endif ! Every particle starts with no accumulated flux derivative. - call clear_diff_accumulators() + call clear_diff_flux_derivs() EVENT_LOOP: do ! If the cell hasn't been determined based on the particle's location, @@ -119,7 +120,7 @@ contains end if ! Score flux derivative accumulators for differential tallies. - call score_diff_accumulators(p, distance, d_boundary > d_collision) + call score_track_derivative(p, distance) if (d_collision > d_boundary) then ! ==================================================================== @@ -194,6 +195,9 @@ contains p % coord(j + 1) % uvw = p % coord(j) % uvw end if end do + + ! Score flux derivative accumulators for differential tallies. + call score_collision_derivative(p) end if ! If particle has too many events, display warning and kill it diff --git a/tests/test_diff_nuclide_density/results_true.dat b/tests/test_diff_nuclide_density/results_true.dat index 68b611ae1..e1c41bdfc 100644 --- a/tests/test_diff_nuclide_density/results_true.dat +++ b/tests/test_diff_nuclide_density/results_true.dat @@ -1,5 +1,5 @@ k-combined: 1.055198E+00 5.785829E-02 tally 1: -3.081784E+03 -1.905482E+06 +-6.741236E+03 +9.368011E+06 From 4942a2b19bb9028e2079349c257d585464690230 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 18 Jan 2016 11:45:36 -0500 Subject: [PATCH 09/60] Fix diff material bug --- src/tally.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tally.F90 b/src/tally.F90 index 6a020eadb..5d9c3fcd8 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -758,7 +758,8 @@ contains select case (t % estimator) case (ESTIMATOR_ANALOG) - if (p % event_nuclide == t % deriv % diff_nuclide) then + if (materials(p % material) % id == t % deriv % diff_material & + .and. p % event_nuclide == t % deriv % diff_nuclide) then associate(mat => materials(p % material)) do l = 1, mat % n_nuclides if (mat % nuclide(l) == t % deriv % diff_nuclide) exit From ed56a6821563fdea90d61a37e4679d5abfff4320 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Tue, 19 Jan 2016 20:39:23 -0500 Subject: [PATCH 10/60] Improve diff tally docs and comments --- docs/source/usersguide/input.rst | 21 ++++++++++++ src/input_xml.F90 | 4 +-- src/output.F90 | 2 +- src/relaxng/tallies.rnc | 8 ++++- src/relaxng/tallies.rng | 34 ++++++++++++++++++++ src/state_point.F90 | 2 +- src/tally.F90 | 55 ++++++++++++++++++++++---------- src/tally_header.F90 | 5 +-- src/tracking.F90 | 4 +-- 9 files changed, 109 insertions(+), 26 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 30e9ed07b..2553e856b 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1618,6 +1618,27 @@ The ```` element accepts the following sub-elements: *Default*: "all" + :derivative: + Tally the first-order derivative of the quantity of interest with respect to + some material perturbation. Differential tallies are currently only + implemented for collision and analog estimators. + + The ``derivative`` element has the following attributes/sub-elements: + + :variable: + The independent variable of the derivative. Accepted options are + "density" and "nuclide_density". A "density" derivative will give the + derivative with respect to the density of the material in [g / cm^3]. A + "nuclide_density" derivative will give the derivative with respect to + the density of a particular nuclide in units of [atom / b / cm]. + + :material: + The perturbed material. (Necessary for both "density" and + "nuclide_density") + + :nuclide: + The perturbed nuclide. (Necessary only for "nuclide_density") + ```` Element ------------------ diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 4cd803cb1..6f77fd96f 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2996,11 +2996,11 @@ contains select case(temp_str) case("density") - t % deriv % dep_var = DIFF_DENSITY + t % deriv % variable = DIFF_DENSITY call get_node_value(node_deriv, "material", t % deriv % diff_material) case("nuclide_density") - t % deriv % dep_var = DIFF_NUCLIDE_DENSITY + t % deriv % variable = DIFF_NUCLIDE_DENSITY call get_node_value(node_deriv, "material", t % deriv % diff_material) call get_node_value(node_deriv, "nuclide", word) diff --git a/src/output.F90 b/src/output.F90 index 5f1b86ef6..fde80f94f 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -1019,7 +1019,7 @@ contains ! Write derivative information. if (allocated(t % deriv)) then - select case (t % deriv % dep_var) + select case (t % deriv % variable) case (DIFF_DENSITY) write(unit=unit_tally, fmt="(' Density derivative Material ',A)") & to_str(t % deriv % diff_material) diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc index 0f3672c6f..11b5feec6 100644 --- a/src/relaxng/tallies.rnc +++ b/src/relaxng/tallies.rnc @@ -41,7 +41,13 @@ element tallies { (element type { xsd:string } | attribute type { xsd:string }) & (element threshold { xsd:double} | attribute threshold { xsd:double }) & (element scores { list { xsd:string { maxLength = "20" }+ } } | attribute scores { list { xsd:string { maxLength = "20"}+ } } )? - }* + }* & + element derivative { + (element variable { ( "density" | "nuclide_density") } | + attribute variable { ( "density" | "nuclide_density") } ) & + (element material { xsd:int } | attribute material { xsd:int }) & + (element nuclide { xsd:string } | attribute nuclide { xsd:string })? + }? }* & element assume_separate { xsd:boolean }? diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng index 36bd5cb85..83c532b79 100644 --- a/src/relaxng/tallies.rng +++ b/src/relaxng/tallies.rng @@ -260,5 +260,39 @@ + + + + + + density + nuclide_density + + + + + density + nuclide_density + + + + + + + + + + + + + + + + + + + + + diff --git a/src/state_point.F90 b/src/state_point.F90 index 5f33eaeb5..93eaaa69f 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -311,7 +311,7 @@ contains if (allocated(tally % deriv)) then call write_dataset(tally_group, "derivative present", 1) deriv_group = create_group(tally_group, "derivative") - select case (tally % deriv % dep_var) + select case (tally % deriv % variable) case (DIFF_DENSITY) call write_dataset(deriv_group, "dependent variable", "density") call write_dataset(deriv_group, "material", & diff --git a/src/tally.F90 b/src/tally.F90 index bd6716f25..ba7581a60 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -772,7 +772,7 @@ contains end if case (ESTIMATOR_COLLISION) - if (t % deriv % dep_var == DIFF_NUCLIDE_DENSITY) then + if (t % deriv % variable == DIFF_NUCLIDE_DENSITY) then scoring_diff_nuclide = & (materials(p % material) % id == t % deriv % diff_material) & .and. (i_nuclide == t % deriv % diff_nuclide) @@ -801,7 +801,7 @@ contains score = score * t % deriv % flux_deriv case (SCORE_TOTAL) - select case (t % deriv % dep_var) + select case (t % deriv % variable) case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & @@ -819,7 +819,7 @@ contains end select case (SCORE_ABSORPTION) - select case (t % deriv % dep_var) + select case (t % deriv % variable) case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & @@ -837,7 +837,7 @@ contains end select case (SCORE_FISSION) - select case (t % deriv % dep_var) + select case (t % deriv % variable) case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & @@ -855,7 +855,7 @@ contains end select case (SCORE_NU_FISSION) - select case (t % deriv % dep_var) + select case (t % deriv % variable) case (DIFF_NUCLIDE_DENSITY) if (i_nuclide == -1 .and. & @@ -873,7 +873,7 @@ contains end select case (SCORE_KEFF) - select case (t % deriv % dep_var) + select case (t % deriv % variable) case (DIFF_DENSITY) score = score * t % deriv % flux_deriv @@ -2383,12 +2383,13 @@ contains end subroutine score_surface_current !=============================================================================== -! SCORE_TRACK_DERIVATIVE +! SCORE_TRACK_DERIVATIVE Adjust flux derivatives on differential tallies to +! account for a neutron travelling through a perturbed material. !=============================================================================== subroutine score_track_derivative(p, distance) type(particle), intent(in) :: p - real(8), intent(in) :: distance + real(8), intent(in) :: distance ! Neutron flight distance integer :: i @@ -2396,13 +2397,16 @@ contains do i = 1, active_tallies % size() associate (t => tallies(active_tallies % get_item(i))) - if (.not. allocated(t % deriv)) cycle + if (.not. allocated(t % deriv)) cycle ! Ignore non-differential tallies - select case (t % deriv % dep_var) + select case (t % deriv % variable) case (DIFF_DENSITY) associate (mat => materials(p % material)) if (mat % id == t % deriv % diff_material) then + ! phi = e^(-Sigma_tot * dist) + ! (1 / phi) * (d_phi / d_rho) = - (d_Sigma_tot / d_rho) * dist + ! (1 / phi) * (d_phi / d_rho) = - Sigma_tot / rho * dist t % deriv % flux_deriv = t % deriv % flux_deriv & - distance * material_xs % total / mat % density_gpcc end if @@ -2411,6 +2415,9 @@ contains case (DIFF_NUCLIDE_DENSITY) associate (mat => materials(p % material)) if (mat % id == t % deriv % diff_material) then + ! phi = e^(-Sigma_tot * dist) + ! (1 / phi) * (d_phi / d_N) = - (d_Sigma_tot / d_N) * dist + ! (1 / phi) * (d_phi / d_N) = - sigma_tot * dist t % deriv % flux_deriv = t % deriv % flux_deriv & - distance * micro_xs(t % deriv % diff_nuclide) % total end if @@ -2418,10 +2425,11 @@ contains end select end associate end do - end subroutine + end subroutine score_track_derivative !=============================================================================== -! SCORE_COLLISION_DERIVATIVE +! SCORE_COLLISION_DERIVATIVE Adjust flux derivatives on differential tallies to +! account for a neutron colliding in the perturbed material. !=============================================================================== subroutine score_collision_derivative(p) @@ -2433,12 +2441,15 @@ contains do i = 1, active_tallies % size() associate (t => tallies(active_tallies % get_item(i))) - if (.not. allocated(t % deriv)) cycle - select case (t % deriv % dep_var) + if (.not. allocated(t % deriv)) cycle ! Ignore non-differential tallies + select case (t % deriv % variable) case (DIFF_DENSITY) associate (mat => materials(p % material)) if (mat % id == t % deriv % diff_material) then + ! phi = Sigma_MT + ! (1 / phi) * (d_phi / d_rho) = (d_Sigma_MT / d_rho) / Sigma_MT + ! (1 / phi) * (d_phi / d_rho) = 1 / rho t % deriv % flux_deriv = t % deriv % flux_deriv & + ONE / mat % density_gpcc end if @@ -2448,12 +2459,18 @@ contains associate (mat => materials(p % material)) if (mat % id == t % deriv % diff_material & .and. p % event_nuclide == t % deriv % diff_nuclide) then + ! Find the index in this material for the diff_nuclide. do j = 1, mat % n_nuclides if (mat % nuclide(j) == t % deriv % diff_nuclide) exit end do + ! Make sure we found the nuclide. if (mat % nuclide(j) /= t % deriv % diff_nuclide) then call fatal_error("Couldn't find the right nuclide.") end if + ! phi = Sigma_MT + ! (1 / phi) * (d_phi / d_N) = (d_Sigma_MT / d_N) / Sigma_MT + ! (1 / phi) * (d_phi / d_N) = sigma_MT / Sigma_MT + ! (1 / phi) * (d_phi / d_N) = 1 / N t % deriv % flux_deriv = t % deriv % flux_deriv & + ONE / mat % atom_density(j) end if @@ -2461,16 +2478,20 @@ contains end select end associate end do - end subroutine + end subroutine score_collision_derivative - subroutine clear_diff_flux_derivs() +!=============================================================================== +! ZERO_FLUX_DERIVS Set the flux derivatives on differential tallies to zero. +!=============================================================================== + + subroutine zero_flux_derivs() integer :: i do i = 1, n_tallies if (allocated(tallies(i) % deriv)) then tallies(i) % deriv % flux_deriv = ZERO end if end do - end subroutine + end subroutine zero_flux_derivs !=============================================================================== ! GET_NEXT_BIN determines the next scoring bin for a particular filter variable diff --git a/src/tally_header.F90 b/src/tally_header.F90 index 9acd05a5e..a7b455d74 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -61,12 +61,13 @@ module tally_header !=============================================================================== -! TALLYDERIVATIVE +! TALLYDERIVATIVE describes a first-order derivative that can be applied to +! tallies. !=============================================================================== type TallyDerivative real(8) :: flux_deriv - integer :: dep_var + integer :: variable integer :: diff_material integer :: diff_nuclide end type TallyDerivative diff --git a/src/tracking.F90 b/src/tracking.F90 index 1ad379490..587b67809 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -15,7 +15,7 @@ module tracking use tally, only: score_analog_tally, score_tracklength_tally, & score_collision_tally, score_surface_current, & score_track_derivative, & - score_collision_derivative, clear_diff_flux_derivs + score_collision_derivative, zero_flux_derivs use track_output, only: initialize_particle_track, write_particle_track, & add_particle_track, finalize_particle_track @@ -63,7 +63,7 @@ contains endif ! Every particle starts with no accumulated flux derivative. - call clear_diff_flux_derivs() + call zero_flux_derivs() EVENT_LOOP: do ! If the cell hasn't been determined based on the particle's location, From 81b280551aff96594a6a2b95dc5fad48e4dd7923 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 22 Jan 2016 20:06:38 -0500 Subject: [PATCH 11/60] Pull derivative multiplier out of score_general --- src/tally.F90 | 306 +++++++++++++++++++++++++++----------------------- 1 file changed, 163 insertions(+), 143 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index ba7581a60..05c7b2b08 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -66,7 +66,6 @@ contains real(8) :: macro_scatt ! material macro scatt xs real(8) :: uvw(3) ! particle direction real(8) :: E ! particle energy - logical :: scoring_diff_nuclide i = 0 SCORE_LOOP: do q = 1, t % n_user_score_bins @@ -755,148 +754,8 @@ contains ! Add derivative information on score for differential tallies. if (allocated(t % deriv)) then - select case (t % estimator) - - case (ESTIMATOR_ANALOG) - if (materials(p % material) % id == t % deriv % diff_material & - .and. p % event_nuclide == t % deriv % diff_nuclide) then - associate(mat => materials(p % material)) - do l = 1, mat % n_nuclides - if (mat % nuclide(l) == t % deriv % diff_nuclide) exit - end do - score = score * (t % deriv % flux_deriv & - + ONE / mat % atom_density(l)) - end associate - else - score = score * t % deriv % flux_deriv - end if - - case (ESTIMATOR_COLLISION) - if (t % deriv % variable == DIFF_NUCLIDE_DENSITY) then - scoring_diff_nuclide = & - (materials(p % material) % id == t % deriv % diff_material) & - .and. (i_nuclide == t % deriv % diff_nuclide) - select case (score_bin) - case (SCORE_TOTAL) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % total /= ZERO - case (SCORE_ABSORPTION) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % absorption /= ZERO - case (SCORE_FISSION) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % fission /= ZERO - case (SCORE_NU_FISSION) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO - case (SCORE_KEFF) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO - end select - end if - - select case (score_bin) - - case (SCORE_FLUX) - score = score * t % deriv % flux_deriv - - case (SCORE_TOTAL) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % total & - / material_xs % total) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE & - / atom_density) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case (SCORE_ABSORPTION) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % absorption & - / material_xs % absorption ) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE & - / atom_density) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case (SCORE_FISSION) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % fission & - / material_xs % fission) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE & - / atom_density) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case (SCORE_NU_FISSION) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % nu_fission & - / material_xs % nu_fission) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE & - / atom_density) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case (SCORE_KEFF) - select case (t % deriv % variable) - - case (DIFF_DENSITY) - score = score * t % deriv % flux_deriv - - case (DIFF_NUCLIDE_DENSITY) - if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE & - / materials(p % material) % atom_density(l)) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case default - call fatal_error('Tally derivative not defined for a score on & - &tally ' // trim(to_str(t % id))) - end select - - case default - call fatal_error("Differential tallies are only implemented for & - &analog and collision estimators.") - end select + call apply_derivative_to_score(p, t, i_nuclide, atom_density, & + score_bin, score) end if !######################################################################### @@ -2382,6 +2241,167 @@ contains end subroutine score_surface_current +!=============================================================================== +! APPLY_DERIVATIVE_TO_SCORE multiply the given score by its relative derivative +!=============================================================================== + + subroutine apply_derivative_to_score(p, t, i_nuclide, atom_density, & + score_bin, score) + type(Particle), intent(in) :: p + type(TallyObject), intent(in) :: t + integer, intent(in) :: i_nuclide + real(8), intent(in) :: atom_density ! atom/b-cm + integer, intent(in) :: score_bin + real(8), intent(inout) :: score + + integer :: l ! loop index for nuclides in material + logical :: scoring_diff_nuclide + + select case (t % estimator) + + case (ESTIMATOR_ANALOG) + if (materials(p % material) % id == t % deriv % diff_material & + .and. p % event_nuclide == t % deriv % diff_nuclide) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == t % deriv % diff_nuclide) exit + end do + score = score * (t % deriv % flux_deriv & + + ONE / mat % atom_density(l)) + end associate + else + score = score * t % deriv % flux_deriv + end if + + case (ESTIMATOR_COLLISION) + if (t % deriv % variable == DIFF_NUCLIDE_DENSITY) then + scoring_diff_nuclide = & + (materials(p % material) % id == t % deriv % diff_material) & + .and. (i_nuclide == t % deriv % diff_nuclide) + select case (score_bin) + case (SCORE_TOTAL) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % total /= ZERO + case (SCORE_ABSORPTION) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % absorption /= ZERO + case (SCORE_FISSION) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % fission /= ZERO + case (SCORE_NU_FISSION) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO + case (SCORE_KEFF) + scoring_diff_nuclide = scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO + end select + end if + + select case (score_bin) + + case (SCORE_FLUX) + score = score * t % deriv % flux_deriv + + case (SCORE_TOTAL) + select case (t % deriv % variable) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % total & + / material_xs % total) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + end select + + case (SCORE_ABSORPTION) + select case (t % deriv % variable) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % absorption & + / material_xs % absorption ) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + end select + + case (SCORE_FISSION) + select case (t % deriv % variable) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % fission & + / material_xs % fission) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + end select + + case (SCORE_NU_FISSION) + select case (t % deriv % variable) + + case (DIFF_NUCLIDE_DENSITY) + if (i_nuclide == -1 .and. & + materials(p % material)%id== t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % nu_fission & + / material_xs % nu_fission) + else if (scoring_diff_nuclide) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + end select + + case (SCORE_KEFF) + select case (t % deriv % variable) + + case (DIFF_DENSITY) + if (materials(p % material) % id == t % deriv % diff_material & + .and. material_xs % nu_fission /= ZERO) then + score = score * (t % deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * t % deriv % flux_deriv + end if + + case (DIFF_NUCLIDE_DENSITY) + if (scoring_diff_nuclide) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + end select + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + end select + + case default + call fatal_error("Differential tallies are only implemented for & + &analog and collision estimators.") + end select + end subroutine apply_derivative_to_score + !=============================================================================== ! SCORE_TRACK_DERIVATIVE Adjust flux derivatives on differential tallies to ! account for a neutron travelling through a perturbed material. From cbe4c55e65b34082be6f57cd2c378605fb3b137d Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 22 Jan 2016 21:20:27 -0500 Subject: [PATCH 12/60] Add more scores to density derivatives --- src/tally.F90 | 245 ++++++++++-------- .../results_true.dat | 4 +- 2 files changed, 133 insertions(+), 116 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 05c7b2b08..f290670c0 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2257,123 +2257,54 @@ contains integer :: l ! loop index for nuclides in material logical :: scoring_diff_nuclide - select case (t % estimator) + select case (t % deriv % variable) - case (ESTIMATOR_ANALOG) - if (materials(p % material) % id == t % deriv % diff_material & - .and. p % event_nuclide == t % deriv % diff_nuclide) then - associate(mat => materials(p % material)) - do l = 1, mat % n_nuclides - if (mat % nuclide(l) == t % deriv % diff_nuclide) exit - end do - score = score * (t % deriv % flux_deriv & - + ONE / mat % atom_density(l)) - end associate - else - score = score * t % deriv % flux_deriv - end if + case (DIFF_DENSITY) + select case (t % estimator) + + case (ESTIMATOR_ANALOG) + if (materials(p % material) % id == t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * t % deriv % flux_deriv + end if + + case (ESTIMATOR_COLLISION) - case (ESTIMATOR_COLLISION) - if (t % deriv % variable == DIFF_NUCLIDE_DENSITY) then - scoring_diff_nuclide = & - (materials(p % material) % id == t % deriv % diff_material) & - .and. (i_nuclide == t % deriv % diff_nuclide) select case (score_bin) + + case (SCORE_FLUX) + score = score * t % deriv % flux_deriv + case (SCORE_TOTAL) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % total /= ZERO + if (materials(p % material) % id == t % deriv % diff_material & + .and. material_xs % total /= ZERO) then + score = score * (t % deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * t % deriv % flux_deriv + end if + case (SCORE_ABSORPTION) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % absorption /= ZERO + if (materials(p % material) % id == t % deriv % diff_material & + .and. material_xs % absorption /= ZERO) then + score = score * (t % deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * t % deriv % flux_deriv + end if + case (SCORE_FISSION) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % fission /= ZERO - case (SCORE_NU_FISSION) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO - case (SCORE_KEFF) - scoring_diff_nuclide = scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO - end select - end if - - select case (score_bin) - - case (SCORE_FLUX) - score = score * t % deriv % flux_deriv - - case (SCORE_TOTAL) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % total & - / material_xs % total) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) + if (materials(p % material) % id == t % deriv % diff_material & + .and. material_xs % fission /= ZERO) then + score = score * (t % deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) else score = score * t % deriv % flux_deriv end if - end select - - case (SCORE_ABSORPTION) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % absorption & - / material_xs % absorption ) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case (SCORE_FISSION) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % fission & - / material_xs % fission) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case (SCORE_NU_FISSION) - select case (t % deriv % variable) - - case (DIFF_NUCLIDE_DENSITY) - if (i_nuclide == -1 .and. & - materials(p % material)%id== t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % nu_fission & - / material_xs % nu_fission) - else if (scoring_diff_nuclide) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) - else - score = score * t % deriv % flux_deriv - end if - - end select - - case (SCORE_KEFF) - select case (t % deriv % variable) - - case (DIFF_DENSITY) + case (SCORE_NU_FISSION, SCORE_KEFF) if (materials(p % material) % id == t % deriv % diff_material & .and. material_xs % nu_fission /= ZERO) then score = score * (t % deriv % flux_deriv + ONE & @@ -2382,23 +2313,109 @@ contains score = score * t % deriv % flux_deriv end if - case (DIFF_NUCLIDE_DENSITY) - if (scoring_diff_nuclide) then + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + + end select + + case default + call fatal_error("Differential tallies are only implemented for & + &analog and collision estimators.") + + end select + + case (DIFF_NUCLIDE_DENSITY) + select case (t % estimator) + + case (ESTIMATOR_ANALOG) + if (materials(p % material) % id == t % deriv % diff_material & + .and. p % event_nuclide == t % deriv % diff_nuclide) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == t % deriv % diff_nuclide) exit + end do + score = score * (t % deriv % flux_deriv & + + ONE / mat % atom_density(l)) + end associate + else + score = score * t % deriv % flux_deriv + end if + + case (ESTIMATOR_COLLISION) + scoring_diff_nuclide = & + (materials(p % material) % id == t % deriv % diff_material) & + .and. (i_nuclide == t % deriv % diff_nuclide) + + select case (score_bin) + + case (SCORE_FLUX) + score = score * t % deriv % flux_deriv + + case (SCORE_TOTAL) + if (i_nuclide == -1 .and. & + materials(p % material) % id == t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % total & + / material_xs % total) + else if (scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % total /= ZERO) then score = score * (t % deriv % flux_deriv + ONE / atom_density) else score = score * t % deriv % flux_deriv end if + case (SCORE_ABSORPTION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % absorption & + / material_xs % absorption ) + else if (scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % absorption /= ZERO) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + case (SCORE_FISSION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % fission & + / material_xs % fission) + else if (scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % fission /= ZERO) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + case (SCORE_NU_FISSION, SCORE_KEFF) + if (i_nuclide == -1 .and. & + materials(p % material) % id == t % deriv % diff_material) then + score = score * (t % deriv % flux_deriv & + + micro_xs(t % deriv % diff_nuclide) % nu_fission & + / material_xs % nu_fission) + else if (scoring_diff_nuclide .and. & + micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO) then + score = score * (t % deriv % flux_deriv + ONE / atom_density) + else + score = score * t % deriv % flux_deriv + end if + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + end select case default - call fatal_error('Tally derivative not defined for a score on & - &tally ' // trim(to_str(t % id))) + call fatal_error("Differential tallies are only implemented for & + &analog and collision estimators.") + end select - case default - call fatal_error("Differential tallies are only implemented for & - &analog and collision estimators.") end select end subroutine apply_derivative_to_score diff --git a/tests/test_diff_nuclide_density/results_true.dat b/tests/test_diff_nuclide_density/results_true.dat index e1c41bdfc..d0c2e3ad1 100644 --- a/tests/test_diff_nuclide_density/results_true.dat +++ b/tests/test_diff_nuclide_density/results_true.dat @@ -1,5 +1,5 @@ k-combined: 1.055198E+00 5.785829E-02 tally 1: --6.741236E+03 -9.368011E+06 +2.547151E+03 +1.303757E+06 From 453d395bcdd9cfdea42dfb9bff4387ee533827d3 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 23 Jan 2016 21:38:44 -0500 Subject: [PATCH 13/60] Update the diff tally testing --- tests/test_diff_density/build_xml.py | 150 ---------------- tests/test_diff_density/geometry.xml | 16 -- tests/test_diff_density/materials.xml | 45 ----- tests/test_diff_density/results_true.dat | 5 - tests/test_diff_density/settings.xml | 18 -- tests/test_diff_density/tallies.xml | 7 - tests/test_diff_density/test_diff_density.py | 11 -- tests/test_diff_nuclide_density/build_xml.py | 164 ------------------ tests/test_diff_nuclide_density/geometry.xml | 16 -- tests/test_diff_nuclide_density/materials.xml | 50 ------ .../results_true.dat | 5 - tests/test_diff_nuclide_density/settings.xml | 18 -- tests/test_diff_nuclide_density/tallies.xml | 10 -- .../test_diff_nuclide_density.py | 11 -- tests/test_diff_tally/inputs_true.dat | 1 + tests/test_diff_tally/results_true.dat | 97 +++++++++++ tests/test_diff_tally/test_diff_tally.py | 123 +++++++++++++ 17 files changed, 221 insertions(+), 526 deletions(-) delete mode 100644 tests/test_diff_density/build_xml.py delete mode 100644 tests/test_diff_density/geometry.xml delete mode 100644 tests/test_diff_density/materials.xml delete mode 100644 tests/test_diff_density/results_true.dat delete mode 100644 tests/test_diff_density/settings.xml delete mode 100644 tests/test_diff_density/tallies.xml delete mode 100755 tests/test_diff_density/test_diff_density.py delete mode 100644 tests/test_diff_nuclide_density/build_xml.py delete mode 100644 tests/test_diff_nuclide_density/geometry.xml delete mode 100644 tests/test_diff_nuclide_density/materials.xml delete mode 100644 tests/test_diff_nuclide_density/results_true.dat delete mode 100644 tests/test_diff_nuclide_density/settings.xml delete mode 100644 tests/test_diff_nuclide_density/tallies.xml delete mode 100755 tests/test_diff_nuclide_density/test_diff_nuclide_density.py create mode 100644 tests/test_diff_tally/inputs_true.dat create mode 100644 tests/test_diff_tally/results_true.dat create mode 100644 tests/test_diff_tally/test_diff_tally.py diff --git a/tests/test_diff_density/build_xml.py b/tests/test_diff_density/build_xml.py deleted file mode 100644 index d5e50c7e8..000000000 --- a/tests/test_diff_density/build_xml.py +++ /dev/null @@ -1,150 +0,0 @@ -import openmc - - -def make_mats(mod_density=0.7420582): - water = openmc.Material(name='water') - water.set_density('g/cm3', mod_density) - water.add_nuclide(openmc.Nuclide('H-1'), 2.0) - water.add_nuclide(openmc.Nuclide('O-16'), 1.0) - - fuel = openmc.Material(name='fuel 2.4%') - fuel.set_density('g/cm3', 10.29769) - fuel.add_nuclide(openmc.Nuclide('U-234'), 5.7987e-06) - fuel.add_nuclide(openmc.Nuclide('U-235'), 7.2175e-04) - fuel.add_nuclide(openmc.Nuclide('U-238'), 2.2253e-02) - fuel.add_nuclide(openmc.Nuclide('O-16'), 4.5750e-02) - fuel.add_nuclide(openmc.Nuclide('O-17'), 9.4222e-05) - - zirc4 = openmc.Material(name='zircaloy 4') - zirc4.set_density('g/cm3', 6.55) - zirc4.add_nuclide(openmc.Nuclide('O-16'), 3.0743e-04) - zirc4.add_nuclide(openmc.Nuclide('O-17'), 1.1711e-07) - # O-18 omitted - zirc4.add_nuclide(openmc.Nuclide('Cr-50'), 3.2962e-06) - zirc4.add_nuclide(openmc.Nuclide('Cr-52'), 6.3564e-05) - zirc4.add_nuclide(openmc.Nuclide('Cr-53'), 7.2076e-06) - zirc4.add_nuclide(openmc.Nuclide('Cr-54'), 1.7941e-06) - zirc4.add_nuclide(openmc.Nuclide('Fe-54'), 8.6699e-06) - zirc4.add_nuclide(openmc.Nuclide('Fe-56'), 1.3610e-04) - zirc4.add_nuclide(openmc.Nuclide('Fe-57'), 3.1431e-06) - zirc4.add_nuclide(openmc.Nuclide('Fe-58'), 4.1829e-07) - zirc4.add_nuclide(openmc.Nuclide('Zr-90'), 2.1827e-02) - zirc4.add_nuclide(openmc.Nuclide('Zr-91'), 4.7600e-03) - zirc4.add_nuclide(openmc.Nuclide('Zr-92'), 7.2758e-03) - zirc4.add_nuclide(openmc.Nuclide('Zr-94'), 7.3734e-03) - zirc4.add_nuclide(openmc.Nuclide('Zr-96'), 1.1879e-03) - zirc4.add_nuclide(openmc.Nuclide('Sn-112'), 4.6735e-06) - zirc4.add_nuclide(openmc.Nuclide('Sn-114'), 3.1799e-06) - zirc4.add_nuclide(openmc.Nuclide('Sn-115'), 1.6381e-06) - zirc4.add_nuclide(openmc.Nuclide('Sn-116'), 7.0055e-05) - zirc4.add_nuclide(openmc.Nuclide('Sn-117'), 3.7003e-05) - zirc4.add_nuclide(openmc.Nuclide('Sn-118'), 1.1669e-04) - zirc4.add_nuclide(openmc.Nuclide('Sn-119'), 4.1387e-05) - zirc4.add_nuclide(openmc.Nuclide('Sn-120'), 1.5697e-04) - zirc4.add_nuclide(openmc.Nuclide('Sn-122'), 2.2308e-05) - zirc4.add_nuclide(openmc.Nuclide('Sn-124'), 2.7897e-05) - - materials_file = openmc.MaterialsFile() - materials_file.default_xs = '71c' - materials_file.add_materials([water, fuel, zirc4]) - - return (materials_file, - {'mod':water, - 'fuel':fuel, - 'clad':zirc4}) - - -def make_geom(mats): - # Instantiate surfaces. - rfo = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218, name='fuel outer') - rci = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.40005, name='clad inner') - rco = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720, name='clad outer') - - x0 = openmc.XPlane(x0=-0.62992) - x1 = openmc.XPlane(x0=0.62992) - y0 = openmc.YPlane(y0=-0.62992) - y1 = openmc.YPlane(y0=0.62992) - z0 = openmc.ZPlane(z0=-1.0) - z1 = openmc.ZPlane(z0=1.0) - x0.boundary_type = 'reflective' - x1.boundary_type = 'reflective' - y0.boundary_type = 'reflective' - y1.boundary_type = 'reflective' - z0.boundary_type = 'reflective' - z1.boundary_type = 'reflective' - - # Instantiate cells. - fuel_c = openmc.Cell(name='fuel') - fuel_c.add_surface(rfo, halfspace=-1) - fuel_c.add_surface(z0, halfspace=+1) - fuel_c.add_surface(z1, halfspace=-1) - - gap = openmc.Cell(name='gap') - gap.add_surface(rci, halfspace=-1) - gap.add_surface(rfo, halfspace=+1) - gap.add_surface(z0, halfspace=+1) - gap.add_surface(z1, halfspace=-1) - - clad_c = openmc.Cell(name='clad') - clad_c.add_surface(rco, halfspace=-1) - clad_c.add_surface(rci, halfspace=+1) - clad_c.add_surface(z0, halfspace=+1) - clad_c.add_surface(z1, halfspace=-1) - - mod_c = openmc.Cell(name='moderator') - mod_c.add_surface(rco, halfspace=+1) - mod_c.add_surface(x0, halfspace=+1) - mod_c.add_surface(x1, halfspace=-1) - mod_c.add_surface(y0, halfspace=+1) - mod_c.add_surface(y1, halfspace=-1) - mod_c.add_surface(z0, halfspace=+1) - mod_c.add_surface(z1, halfspace=-1) - - # Add materials to cells. - fuel_c.fill = mats['fuel'] - gap.fill = 'void' - clad_c.fill = mats['clad'] - mod_c.fill = mats['mod'] - - # Instantiate universes. - u0 = openmc.Universe(universe_id=0) - u0.add_cells([fuel_c, gap, clad_c, mod_c]) - - # Write the XML file. - geometry = openmc.Geometry() - geometry.root_universe = u0 - geometry_file = openmc.GeometryFile() - geometry_file.geometry = geometry - - return geometry_file - - -def make_settings(**kwargs): - if 'batches' in kwargs: - batches = kwargs['batches'] - - settings_file = openmc.SettingsFile() - settings_file.batches = kwargs.setdefault('batches', 100) - settings_file.inactive = kwargs.setdefault('inactive', 10) - settings_file.particles = kwargs.setdefault('particles', 1000) - settings_file.set_source_space('box', (-0.6, -0.6, -0.9, - 0.6, 0.6, 0.9)) - settings_file.entropy_lower_left = (-0.7, -0.7, -1.1) - settings_file.entropy_upper_right = (0.7, 0.7, 1.1) - settings_file.entropy_dimension = (10, 10, 10) - return settings_file - - -def make_inputs(mod_density=0.7420582, **kwargs): - (mat_file, mats) = make_mats(mod_density) - mat_file.export_to_xml() - - geo_file = make_geom(mats) - geo_file.export_to_xml() - - sets_file = make_settings(**kwargs) - sets_file.export_to_xml() - - -if __name__ == '__main__': - make_inputs(inactive=5, batches=10, particles=100) diff --git a/tests/test_diff_density/geometry.xml b/tests/test_diff_density/geometry.xml deleted file mode 100644 index e7e5b097b..000000000 --- a/tests/test_diff_density/geometry.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/tests/test_diff_density/materials.xml b/tests/test_diff_density/materials.xml deleted file mode 100644 index 955ea92e7..000000000 --- a/tests/test_diff_density/materials.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_diff_density/results_true.dat b/tests/test_diff_density/results_true.dat deleted file mode 100644 index 5e515c461..000000000 --- a/tests/test_diff_density/results_true.dat +++ /dev/null @@ -1,5 +0,0 @@ -k-combined: -1.502605E+00 2.273838E-02 -tally 1: -5.280104E+00 -1.379258E+01 diff --git a/tests/test_diff_density/settings.xml b/tests/test_diff_density/settings.xml deleted file mode 100644 index a41ba9725..000000000 --- a/tests/test_diff_density/settings.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - 100 - 10 - 5 - - - - -0.6 -0.6 -0.9 0.6 0.6 0.9 - - - - 10 10 10 - -0.7 -0.7 -1.1 - 0.7 0.7 1.1 - - diff --git a/tests/test_diff_density/tallies.xml b/tests/test_diff_density/tallies.xml deleted file mode 100644 index 214f33ab3..000000000 --- a/tests/test_diff_density/tallies.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - keff - - - diff --git a/tests/test_diff_density/test_diff_density.py b/tests/test_diff_density/test_diff_density.py deleted file mode 100755 index ed6addec4..000000000 --- a/tests/test_diff_density/test_diff_density.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -sys.path.insert(0, os.pardir) -from testing_harness import TestHarness - - -if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) - harness.main() diff --git a/tests/test_diff_nuclide_density/build_xml.py b/tests/test_diff_nuclide_density/build_xml.py deleted file mode 100644 index f77a337cb..000000000 --- a/tests/test_diff_nuclide_density/build_xml.py +++ /dev/null @@ -1,164 +0,0 @@ -import openmc - - -def make_mats(**kwargs): - water_dict = { - 'B-10': 8.0042e-06, - 'B-11': 3.2218e-05, - 'H-1': 4.9457e-02, - 'H-2': 7.4196e-06, - 'O-16': 2.4672e-02, - 'O-17': 9.3982e-06 + 5.0701e-05} - water = openmc.Material(name='water') - water.set_density('sum') - for nuclide in water_dict: - water.add_nuclide(nuclide, water_dict[nuclide]) - - U235_dens = kwargs.setdefault('U235_dens', 5.5814e-04) - fuel_dict = { - 'B-10': 8.0042e-06, - 'U-234': 4.4842e-06, - 'U-235': U235_dens, - 'U-238': 2.2407e-02, - 'O-16': 4.5828e-02, - 'O-17': 1.7457e-05 + 9.4176e-05} - fuel = openmc.Material(name='fuel 2.4%') - fuel.set_density('sum') - for nuclide in fuel_dict: - fuel.add_nuclide(nuclide, fuel_dict[nuclide]) - - zirc4_dict = { - 'O-16': 3.0743e-04, - 'O-17': 1.1711e-07 + 6.3176e-07, - 'Cr-50': 3.2962e-06, - 'Cr-52': 6.3564e-05, - 'Cr-53': 7.2076e-06, - 'Cr-54': 1.7941e-06, - 'Fe-54': 8.6699e-06, - 'Fe-56': 1.3610e-04, - 'Fe-57': 3.1431e-06, - 'Fe-58': 4.1829e-07, - 'Zr-90': 2.1827e-02, - 'Zr-91': 4.7600e-03, - 'Zr-92': 7.2758e-03, - 'Zr-94': 7.3734e-03, - 'Zr-96': 1.1879e-03, - 'Sn-112': 4.6735e-06, - 'Sn-114': 3.1799e-06, - 'Sn-115': 1.6381e-06, - 'Sn-116': 7.0055e-05, - 'Sn-117': 3.7003e-05, - 'Sn-118': 1.1669e-04, - 'Sn-119': 4.1387e-05, - 'Sn-120': 1.5697e-04, - 'Sn-122': 2.2308e-05, - 'Sn-124': 2.7897e-05} - zirc4 = openmc.Material(name='zircaloy 4') - zirc4.set_density('sum') - for nuclide in zirc4_dict: - zirc4.add_nuclide(nuclide, zirc4_dict[nuclide]) - - materials_file = openmc.MaterialsFile() - materials_file.default_xs = '71c' - materials_file.add_materials([water, fuel, zirc4]) - - return (materials_file, - {'mod':water, - 'fuel':fuel, - 'clad':zirc4}) - - -def make_geom(mats): - # Instantiate surfaces. - rfo = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218, name='fuel outer') - rci = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.40005, name='clad inner') - rco = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720, name='clad outer') - - x0 = openmc.XPlane(x0=-0.62992) - x1 = openmc.XPlane(x0=0.62992) - y0 = openmc.YPlane(y0=-0.62992) - y1 = openmc.YPlane(y0=0.62992) - z0 = openmc.ZPlane(z0=-1.0) - z1 = openmc.ZPlane(z0=1.0) - x0.boundary_type = 'reflective' - x1.boundary_type = 'reflective' - y0.boundary_type = 'reflective' - y1.boundary_type = 'reflective' - z0.boundary_type = 'reflective' - z1.boundary_type = 'reflective' - - # Instantiate cells. - fuel_c = openmc.Cell(name='fuel') - fuel_c.add_surface(rfo, halfspace=-1) - fuel_c.add_surface(z0, halfspace=+1) - fuel_c.add_surface(z1, halfspace=-1) - - gap = openmc.Cell(name='gap') - gap.add_surface(rci, halfspace=-1) - gap.add_surface(rfo, halfspace=+1) - gap.add_surface(z0, halfspace=+1) - gap.add_surface(z1, halfspace=-1) - - clad_c = openmc.Cell(name='clad') - clad_c.add_surface(rco, halfspace=-1) - clad_c.add_surface(rci, halfspace=+1) - clad_c.add_surface(z0, halfspace=+1) - clad_c.add_surface(z1, halfspace=-1) - - mod_c = openmc.Cell(name='moderator') - mod_c.add_surface(rco, halfspace=+1) - mod_c.add_surface(x0, halfspace=+1) - mod_c.add_surface(x1, halfspace=-1) - mod_c.add_surface(y0, halfspace=+1) - mod_c.add_surface(y1, halfspace=-1) - mod_c.add_surface(z0, halfspace=+1) - mod_c.add_surface(z1, halfspace=-1) - - # Add materials to cells. - fuel_c.fill = mats['fuel'] - gap.fill = 'void' - clad_c.fill = mats['clad'] - mod_c.fill = mats['mod'] - - # Instantiate universes. - u0 = openmc.Universe(universe_id=0) - u0.add_cells([fuel_c, gap, clad_c, mod_c]) - - # Write the XML file. - geometry = openmc.Geometry() - geometry.root_universe = u0 - geometry_file = openmc.GeometryFile() - geometry_file.geometry = geometry - - return geometry_file - - -def make_settings(**kwargs): - if 'batches' in kwargs: - batches = kwargs['batches'] - - settings_file = openmc.SettingsFile() - settings_file.batches = kwargs.setdefault('batches', 1610) - settings_file.inactive = kwargs.setdefault('inactive', 10) - settings_file.particles = kwargs.setdefault('particles', 1000) - settings_file.set_source_space('box', (-0.6, -0.6, -0.9, - 0.6, 0.6, 0.9)) - settings_file.entropy_lower_left = (-0.7, -0.7, -1.1) - settings_file.entropy_upper_right = (0.7, 0.7, 1.1) - settings_file.entropy_dimension = (10, 10, 10) - return settings_file - - -def make_inputs(**kwargs): - (mat_file, mats) = make_mats(**kwargs) - mat_file.export_to_xml() - - geo_file = make_geom(mats) - geo_file.export_to_xml() - - sets_file = make_settings(**kwargs) - sets_file.export_to_xml() - - -if __name__ == '__main__': - make_inputs(inactive=5, batches=10, particles=100) diff --git a/tests/test_diff_nuclide_density/geometry.xml b/tests/test_diff_nuclide_density/geometry.xml deleted file mode 100644 index e7e5b097b..000000000 --- a/tests/test_diff_nuclide_density/geometry.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/tests/test_diff_nuclide_density/materials.xml b/tests/test_diff_nuclide_density/materials.xml deleted file mode 100644 index 02b55f452..000000000 --- a/tests/test_diff_nuclide_density/materials.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_diff_nuclide_density/results_true.dat b/tests/test_diff_nuclide_density/results_true.dat deleted file mode 100644 index d0c2e3ad1..000000000 --- a/tests/test_diff_nuclide_density/results_true.dat +++ /dev/null @@ -1,5 +0,0 @@ -k-combined: -1.055198E+00 5.785829E-02 -tally 1: -2.547151E+03 -1.303757E+06 diff --git a/tests/test_diff_nuclide_density/settings.xml b/tests/test_diff_nuclide_density/settings.xml deleted file mode 100644 index a41ba9725..000000000 --- a/tests/test_diff_nuclide_density/settings.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - 100 - 10 - 5 - - - - -0.6 -0.6 -0.9 0.6 0.6 0.9 - - - - 10 10 10 - -0.7 -0.7 -1.1 - 0.7 0.7 1.1 - - diff --git a/tests/test_diff_nuclide_density/tallies.xml b/tests/test_diff_nuclide_density/tallies.xml deleted file mode 100644 index 321b2c9b0..000000000 --- a/tests/test_diff_nuclide_density/tallies.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - keff - - - - diff --git a/tests/test_diff_nuclide_density/test_diff_nuclide_density.py b/tests/test_diff_nuclide_density/test_diff_nuclide_density.py deleted file mode 100755 index ed6addec4..000000000 --- a/tests/test_diff_nuclide_density/test_diff_nuclide_density.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -sys.path.insert(0, os.pardir) -from testing_harness import TestHarness - - -if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) - harness.main() diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat new file mode 100644 index 000000000..22656a483 --- /dev/null +++ b/tests/test_diff_tally/inputs_true.dat @@ -0,0 +1 @@ +cb132b2211831bf333bc9be0b10d092ad3bbe9a188743cf4c430ae97037987763b268997757a0602c164d8c2deb3eb9843590d860ba5a4858092a9ad0b8adeba \ No newline at end of file diff --git a/tests/test_diff_tally/results_true.dat b/tests/test_diff_tally/results_true.dat new file mode 100644 index 000000000..8b33b8293 --- /dev/null +++ b/tests/test_diff_tally/results_true.dat @@ -0,0 +1,97 @@ +d_material,d_nuclide,d_variable,score,mean,std. dev. +3,,density,flux,-5.12e+00,8.94e-01 +3,,density,flux,-1.07e+01,8.84e-01 +1,,density,flux,-3.14e-01,4.48e-02 +1,,density,flux,-2.73e-01,8.51e-02 +1,O-16.71c,nuclide_density,flux,-3.58e+00,7.77e+00 +1,O-16.71c,nuclide_density,flux,-7.64e+00,1.09e+01 +1,U-235.71c,nuclide_density,flux,-1.19e+03,1.18e+02 +1,U-235.71c,nuclide_density,flux,-1.25e+03,1.63e+02 +3,,density,total,-1.92e+00,4.49e-01 +3,,density,absorption,5.89e-02,6.68e-02 +3,,density,fission,8.55e-02,3.33e-02 +3,,density,nu-fission,2.20e-01,8.60e-02 +3,,density,total,4.49e-02,3.15e-02 +3,,density,absorption,6.66e-02,2.74e-02 +3,,density,fission,6.12e-02,2.24e-02 +3,,density,nu-fission,1.49e-01,5.45e-02 +3,,density,total,7.72e+00,9.45e-01 +3,,density,absorption,1.26e-01,2.24e-02 +3,,density,fission,0.00e+00,0.00e+00 +3,,density,nu-fission,0.00e+00,0.00e+00 +3,,density,total,0.00e+00,0.00e+00 +3,,density,absorption,0.00e+00,0.00e+00 +3,,density,fission,0.00e+00,0.00e+00 +3,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,total,3.79e-01,1.14e-02 +1,,density,absorption,1.27e-02,4.48e-03 +1,,density,fission,1.88e-03,1.96e-03 +1,,density,nu-fission,5.22e-03,5.08e-03 +1,,density,total,5.43e-03,1.67e-03 +1,,density,absorption,1.29e-03,1.64e-03 +1,,density,fission,3.13e-05,1.30e-03 +1,,density,nu-fission,1.12e-04,3.17e-03 +1,,density,total,-2.91e-01,9.67e-02 +1,,density,absorption,-5.40e-03,1.29e-03 +1,,density,fission,0.00e+00,0.00e+00 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,total,0.00e+00,0.00e+00 +1,,density,absorption,0.00e+00,0.00e+00 +1,,density,fission,0.00e+00,0.00e+00 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,total,4.33e+01,3.24e+00 +1,O-16.71c,nuclide_density,absorption,6.59e-01,5.83e-01 +1,O-16.71c,nuclide_density,fission,4.31e-01,1.26e-01 +1,O-16.71c,nuclide_density,nu-fission,1.08e+00,3.25e-01 +1,O-16.71c,nuclide_density,total,4.52e-01,1.50e-01 +1,O-16.71c,nuclide_density,absorption,4.58e-01,1.12e-01 +1,O-16.71c,nuclide_density,fission,3.54e-01,9.55e-02 +1,O-16.71c,nuclide_density,nu-fission,8.62e-01,2.33e-01 +1,O-16.71c,nuclide_density,total,-4.58e-01,1.17e+01 +1,O-16.71c,nuclide_density,absorption,1.23e-01,1.75e-01 +1,O-16.71c,nuclide_density,fission,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,total,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,absorption,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,fission,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,total,-2.41e+02,5.64e+01 +1,U-235.71c,nuclide_density,absorption,1.11e+02,1.40e+01 +1,U-235.71c,nuclide_density,fission,1.79e+02,9.60e+00 +1,U-235.71c,nuclide_density,nu-fission,3.97e+02,2.44e+01 +1,U-235.71c,nuclide_density,total,4.56e+02,1.09e+01 +1,U-235.71c,nuclide_density,absorption,3.45e+02,1.09e+01 +1,U-235.71c,nuclide_density,fission,2.70e+02,8.42e+00 +1,U-235.71c,nuclide_density,nu-fission,6.59e+02,2.05e+01 +1,U-235.71c,nuclide_density,total,-2.29e+03,2.59e+02 +1,U-235.71c,nuclide_density,absorption,-5.31e+01,5.44e+00 +1,U-235.71c,nuclide_density,fission,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,total,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,absorption,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,fission,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 +3,,density,absorption,-3.29e-02,8.34e-02 +3,,density,absorption,1.21e-01,4.42e-02 +1,,density,absorption,1.51e-02,2.89e-03 +1,,density,absorption,-4.61e-03,2.30e-03 +1,O-16.71c,nuclide_density,absorption,2.87e-01,5.33e-01 +1,O-16.71c,nuclide_density,absorption,2.86e-01,3.59e-01 +1,U-235.71c,nuclide_density,absorption,1.14e+02,1.15e+01 +1,U-235.71c,nuclide_density,absorption,-5.10e+01,4.74e+00 +3,,density,nu-fission,4.24e-04,6.13e-02 +3,,density,nu-fission,2.40e-02,6.37e-02 +3,,density,nu-fission,0.00e+00,0.00e+00 +3,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,nu-fission,-2.85e-02,2.57e-03 +1,,density,nu-fission,-6.16e-02,5.51e-03 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,nu-fission,1.70e-01,2.18e-01 +1,O-16.71c,nuclide_density,nu-fission,6.30e-01,5.11e-01 +1,O-16.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,O-16.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,nu-fission,-2.00e+02,1.68e+01 +1,U-235.71c,nuclide_density,nu-fission,-4.76e+02,1.41e+01 +1,U-235.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,U-235.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py new file mode 100644 index 000000000..2bd0f704d --- /dev/null +++ b/tests/test_diff_tally/test_diff_tally.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +import glob +import os +import pandas as pd +try: + from StringIO import StringIO +except: + from io import StringIO +import sys +sys.path.insert(0, os.pardir) +from testing_harness import PyAPITestHarness +from openmc import Filter, Mesh, Tally, TalliesFile, Summary, StatePoint +#from openmc.statepoint import StatePoint +from openmc.source import Source +from openmc.stats import Box + +class DiffTallyTestHarness(PyAPITestHarness): + def _build_inputs(self): + # Build default materials/geometry + self._input_set.build_default_materials_and_geometry() + + # Set settings explicitly + self._input_set.settings.batches = 5 + self._input_set.settings.inactive = 0 + self._input_set.settings.particles = 400 + self._input_set.settings.source = Source(space=Box( + [-160, -160, -183], [160, 160, 183])) + self._input_set.settings.output = {'summary':True} + + self._input_set.tallies = TalliesFile() + + filt_mats = Filter(type='material', bins=(1, 3)) + filt_eout = Filter(type='energyout', bins=(0.0, 1.0, 20.0)) + + def add_derivs(tally_list): + assert len(tally_list) == 4 + # We want density derivatives for both water and fuel to get + # coverage for both fissile and non-fissile materials. + tally_list[0].diff_variable = 'density' + tally_list[0].diff_material = 3 + tally_list[1].diff_variable = 'density' + tally_list[1].diff_material = 1 + + # O-16 is a good nuclide to test against because it is present + # in both water and fuel. Some routines need to recognize that they + # have the perturbed nuclide but not the perturbed material. + tally_list[2].diff_variable = 'nuclide_density' + tally_list[2].diff_material = 1 + tally_list[2].diff_nuclide = 'O-16' + + # A fissile nuclide, just for good measure. + tally_list[3].diff_variable = 'nuclide_density' + tally_list[3].diff_material = 1 + tally_list[3].diff_nuclide = 'U-235' + + # Cover the flux score. + tallies = [Tally() for i in range(4)] + for t in tallies: t.add_score('flux') + for t in tallies: t.add_filter(filt_mats) + add_derivs(tallies) + for t in tallies: self._input_set.tallies.add_tally(t) + + # Cover supported scores with a collision estimator. + tallies = [Tally() for i in range(4)] + for t in tallies: t.add_score('total') + for t in tallies: t.add_score('absorption') + for t in tallies: t.add_score('fission') + for t in tallies: t.add_score('nu-fission') + for t in tallies: t.add_filter(filt_mats) + for t in tallies: t.add_nuclide('total') + for t in tallies: t.add_nuclide('U-235') + add_derivs(tallies) + for t in tallies: self._input_set.tallies.add_tally(t) + + # Cover an analog estimator. + tallies = [Tally() for i in range(4)] + for t in tallies: t.add_score('absorption') + for t in tallies: t.add_filter(filt_mats) + for t in tallies: t.estimator = 'analog' + add_derivs(tallies) + for t in tallies: self._input_set.tallies.add_tally(t) + + # And the special fission with energyout filter. + tallies = [Tally() for i in range(4)] + for t in tallies: t.add_score('nu-fission') + for t in tallies: t.add_filter(filt_mats) + for t in tallies: t.add_filter(filt_eout) + add_derivs(tallies) + for t in tallies: self._input_set.tallies.add_tally(t) + + self._input_set.export() + + def _get_results(self): + #return super(DiffTallyTestHarness, self)._get_results(hash_output=True) + # Read the statepoint and summary files. + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] + sp = StatePoint(statepoint) + su = Summary('summary.h5') + sp.link_with_summary(su) + + # Extract the tally data as a Pandas DataFrame. + df = pd.DataFrame() + for t in sp.tallies.values(): + df = df.append(t.get_pandas_dataframe(), ignore_index=True) + + # Extract the relevant data as a CSV string. + out = StringIO() + cols = ('d_material', 'd_nuclide', 'd_variable', 'score', 'mean', + 'std. dev.') + df.to_csv(out, columns=cols, index=False, float_format='%.2e') + + return out.getvalue() + + def _cleanup(self): + super(DiffTallyTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = DiffTallyTestHarness('statepoint.5.*', True) + harness.main() From c7350a3da4eecc85a37086f8c568df50f6c29531 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 23 Jan 2016 21:53:35 -0500 Subject: [PATCH 14/60] Remove k_eff nonsense --- src/constants.F90 | 5 ++--- src/input_xml.F90 | 3 --- src/output.F90 | 1 - src/state_point.F90 | 2 -- src/tally.F90 | 11 ++--------- 5 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/constants.F90 b/src/constants.F90 index c8b6d1ad7..5d8ded5af 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -263,7 +263,7 @@ module constants EVENT_ABSORB = 2 ! Tally score type - integer, parameter :: N_SCORE_TYPES = 23 + integer, parameter :: N_SCORE_TYPES = 22 integer, parameter :: & SCORE_FLUX = -1, & ! flux SCORE_TOTAL = -2, & ! total reaction rate @@ -286,8 +286,7 @@ module constants SCORE_NU_SCATTER_YN = -19, & ! angular flux-weighted nu-scattering moment (0:N) SCORE_EVENTS = -20, & ! number of events SCORE_DELAYED_NU_FISSION = -21, & ! delayed neutron production rate - SCORE_INVERSE_VELOCITY = -22, & ! flux-weighted inverse velocity - SCORE_KEFF = -23 ! multiplication factor + SCORE_INVERSE_VELOCITY = -22 ! flux-weighted inverse velocity ! Maximum scattering order supported integer, parameter :: MAX_ANG_ORDER = 10 diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 6f77fd96f..aeab9e6bc 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3374,9 +3374,6 @@ contains case ('events') t % score_bins(j) = SCORE_EVENTS - case ('keff') - t % score_bins(j) = SCORE_KEFF - case ('elastic', '(n,elastic)') t % score_bins(j) = ELASTIC case ('(n,2nd)') diff --git a/src/output.F90 b/src/output.F90 index fde80f94f..b7e8a18ae 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -980,7 +980,6 @@ contains score_names(abs(SCORE_NU_SCATTER_YN)) = "Scattering Prod. Rate Moment" score_names(abs(SCORE_DELAYED_NU_FISSION)) = "Delayed-Nu-Fission Rate" score_names(abs(SCORE_INVERSE_VELOCITY)) = "Flux-Weighted Inverse Velocity" - score_names(abs(SCORE_KEFF)) = "k_eff, multiplaction factor" ! Create filename for tally output filename = trim(path_output) // "tallies.out" diff --git a/src/state_point.F90 b/src/state_point.F90 index 93eaaa69f..c31b2b7a3 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -383,8 +383,6 @@ contains str_array(j) = "events" case (SCORE_INVERSE_VELOCITY) str_array(j) = "inverse-velocity" - case (SCORE_KEFF) - str_array(j) = "keff" case default str_array(j) = reaction_name(tally%score_bins(j)) end select diff --git a/src/tally.F90 b/src/tally.F90 index f290670c0..fca9bf3b9 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -676,13 +676,6 @@ contains end if end if - case (SCORE_KEFF) - if (t % estimator == ESTIMATOR_COLLISION) then - score = p % last_wgt * material_xs % nu_fission / material_xs % total - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then - score = flux * material_xs % nu_fission - end if - case default if (t % estimator == ESTIMATOR_ANALOG) then ! Any other score is assumed to be a MT number. Thus, we just need @@ -2304,7 +2297,7 @@ contains score = score * t % deriv % flux_deriv end if - case (SCORE_NU_FISSION, SCORE_KEFF) + case (SCORE_NU_FISSION) if (materials(p % material) % id == t % deriv % diff_material & .and. material_xs % nu_fission /= ZERO) then score = score * (t % deriv % flux_deriv + ONE & @@ -2391,7 +2384,7 @@ contains score = score * t % deriv % flux_deriv end if - case (SCORE_NU_FISSION, SCORE_KEFF) + case (SCORE_NU_FISSION) if (i_nuclide == -1 .and. & materials(p % material) % id == t % deriv % diff_material) then score = score * (t % deriv % flux_deriv & From 5634993bf9447b4fe98e2f634d206da0ee4dedf4 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 23 Jan 2016 22:13:41 -0500 Subject: [PATCH 15/60] Fix differential fission eout tallies --- src/tally.F90 | 8 ++++++-- tests/test_diff_tally/results_true.dat | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index fca9bf3b9..058595ca9 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -1046,8 +1046,12 @@ contains ! determine score based on bank site weight and keff score = keff * fission_bank(n_bank - p % n_bank + k) % wgt - ! Add derivative information for differenetial tallies. - if (allocated(t % deriv)) score = score * t % deriv % flux_deriv + ! Add derivative information for differenetial tallies. Note that the + ! i_nuclide and atom_density arguments do not matter since this is an + ! analog estimator. + if (allocated(t % deriv)) then + call apply_derivative_to_score(p, t, 0, ZERO, SCORE_NU_FISSION, score) + end if ! determine outgoing energy from fission bank E_out = fission_bank(n_bank - p % n_bank + k) % E diff --git a/tests/test_diff_tally/results_true.dat b/tests/test_diff_tally/results_true.dat index 8b33b8293..3071af772 100644 --- a/tests/test_diff_tally/results_true.dat +++ b/tests/test_diff_tally/results_true.dat @@ -83,15 +83,15 @@ d_material,d_nuclide,d_variable,score,mean,std. dev. 3,,density,nu-fission,2.40e-02,6.37e-02 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,nu-fission,-2.85e-02,2.57e-03 -1,,density,nu-fission,-6.16e-02,5.51e-03 +1,,density,nu-fission,3.45e-03,8.06e-04 +1,,density,nu-fission,7.16e-03,3.66e-03 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,O-16.71c,nuclide_density,nu-fission,1.70e-01,2.18e-01 1,O-16.71c,nuclide_density,nu-fission,6.30e-01,5.11e-01 1,O-16.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O-16.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U-235.71c,nuclide_density,nu-fission,-2.00e+02,1.68e+01 -1,U-235.71c,nuclide_density,nu-fission,-4.76e+02,1.41e+01 +1,U-235.71c,nuclide_density,nu-fission,1.35e+02,7.94e+00 +1,U-235.71c,nuclide_density,nu-fission,2.47e+02,1.29e+01 1,U-235.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U-235.71c,nuclide_density,nu-fission,0.00e+00,0.00e+00 From 55ab085e7499006025545f40613d63f012e2e433 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 29 Jan 2016 16:54:07 -0500 Subject: [PATCH 16/60] Make tally derivatives seperate objects Fix the OpenMP error by making these seperate objects threadprivate --- openmc/__init__.py | 1 + openmc/statepoint.py | 62 +++-- openmc/tallies.py | 117 +++----- openmc/tally_derivative.py | 182 +++++++++++++ src/global.F90 | 7 +- src/input_xml.F90 | 150 +++++++---- src/output.F90 | 30 +-- src/simulation.F90 | 2 +- src/state_point.F90 | 58 ++-- src/tally.F90 | 324 +++++++++++------------ src/tally_header.F90 | 5 +- src/tracking.F90 | 6 +- tests/test_diff_tally/inputs_true.dat | 2 +- tests/test_diff_tally/test_diff_tally.py | 49 ++-- tests/testing_harness.py | 2 +- 15 files changed, 614 insertions(+), 383 deletions(-) create mode 100644 openmc/tally_derivative.py diff --git a/openmc/__init__.py b/openmc/__init__.py index 397d9f3e2..ee3db59ae 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -9,6 +9,7 @@ from openmc.universe import * from openmc.mesh import * from openmc.filter import * from openmc.trigger import * +from openmc.tally_derivative import * from openmc.tallies import * from openmc.cmfd import * from openmc.executor import * diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 0abb4b093..42e957506 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -83,6 +83,9 @@ class StatePoint(object): Dictionary whose keys are tally IDs and whose values are Tally objects tallies_present : bool Indicate whether user-defined tallies are present + tally_derivatives : dict + Dictionary whose keys are tally derivative IDs and whose values are + TallyDerivative objects version: tuple of Integral Version of OpenMC summary : None or openmc.summary.Summary @@ -115,6 +118,7 @@ class StatePoint(object): self._summary = False self._global_tallies = None self._sparse = False + self._derivs_read = False def close(self): self._f.close() @@ -360,27 +364,10 @@ class StatePoint(object): tally.num_realizations = n_realizations # Read derivative information. - derivatives_present = self._f[ - '{0}{1}/derivative present'.format(base, tally_key)].value - assert derivatives_present in (0, 1) - if derivatives_present == 1: - tally.diff_variable = self._f[ - '{0}{1}/derivative/dependent variable'.format( - base, tally_key)].value.decode() - if tally.diff_variable == 'density': - tally.diff_material = self._f[ - '{0}{1}/derivative/material'.format( - base, tally_key)].value - elif tally.diff_variable == 'nuclide_density': - tally.diff_material = self._f[ - '{0}{1}/derivative/material'.format( - base, tally_key)].value - tally.diff_nuclide = self._f[ - '{0}{1}/derivative/nuclide'.format( - base, tally_key)].value.decode() - else: - raise RuntimeError('Unrecognized tally differential' - 'variable') + if 'derivative' in self._f['{0}{1}'.format(base, tally_key)]: + deriv_id = self._f['{0}{1}/derivative'.format( + base, tally_key)].value + tally.derivative = self.tally_derivatives[deriv_id] # Read the number of Filters n_filters = \ @@ -462,6 +449,39 @@ class StatePoint(object): def tallies_present(self): return self._f['tallies/tallies_present'].value + @property + def tally_derivatives(self): + if not self._derivs_read: + # Initialize dictionaries for the Meshes + # Keys - Derivative IDs + # Values - TallyDerivative objects + self._derivs = {} + + # Populate the dictionary if any derivatives are present. + if 'derivatives' in self._f['tallies']: + # Read the derivative ids. + base = 'tallies/derivatives' + deriv_ids = [int(k.split(' ')[1]) for k in self._f[base].keys()] + + # Create each derivative object and add it to the dictionary. + for d_id in deriv_ids: + base = 'tallies/derivatives/derivative {:d}'.format(d_id) + deriv = openmc.TallyDerivative(derivative_id=d_id) + deriv.variable = self._f[base + '/dependent variable'].value + if deriv.variable == 'density': + deriv.material = self._f[base + '/material'].value + elif deriv.variable == 'nuclide_density': + deriv.material = self._f[base + '/material'].value + deriv.nuclide = self._f[base + '/nuclide'].value.decode() + else: + raise RuntimeError('Unrecognized tally differential ' + 'variable') + self._derivs[d_id] = deriv + + self._derivs_read = True + + return self._derivs + @property def version(self): return (self._f['version_major'].value, diff --git a/openmc/tallies.py b/openmc/tallies.py index 2eb632d82..d202497aa 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -11,7 +11,7 @@ import sys import numpy as np -from openmc import Mesh, Filter, Trigger, Nuclide +from openmc import Mesh, Filter, Trigger, Nuclide, TallyDerivative from openmc.cross import CrossScore, CrossNuclide, CrossFilter from openmc.aggregate import AggregateScore, AggregateNuclide, AggregateFilter from openmc.filter import _FILTER_TYPES @@ -95,6 +95,8 @@ class Tally(object): sparse : bool Whether or not the tally uses SciPy's LIL sparse matrix format for compressed data storage + derivative : openmc.tally_derivative.TallyDerivative + A material perturbation derivative to apply to all scores in the tally. """ @@ -107,9 +109,7 @@ class Tally(object): self._scores = [] self._estimator = None self._triggers = [] - self._diff_variable = None - self._diff_material = None - self._diff_nuclide = None + self._derivative = None self._num_realizations = 0 self._with_summary = False @@ -134,9 +134,7 @@ class Tally(object): clone.id = self.id clone.name = self.name clone.estimator = self.estimator - clone._diff_variable = self.diff_variable - clone._diff_material = self.diff_material - clone._diff_nuclide = self.diff_nuclide + clone._derivative = self.derivative clone.num_realizations = self.num_realizations clone._sum = copy.deepcopy(self._sum, memo) clone._sum_sq = copy.deepcopy(self._sum_sq, memo) @@ -194,11 +192,7 @@ class Tally(object): return False # Check derivatives - if self.diff_variable != other.diff_variable: - return False - if self.diff_material != other.diff_material: - return False - if self.diff_nuclide != other.diff_nuclide: + if self.derivative != other.derivative: return False # Check all scores @@ -225,20 +219,9 @@ class Tally(object): string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self.name) - if self.diff_variable is not None: - string += '{0: <16}{1}{2}\n'.format('\tDerivative', '=\t', - self.diff_variable) - if self.diff_variable == 'density': - string += '{0: <16}{1}{2}\n'.format('\tDiff_material', '=\t', - self.diff_material) - elif self.diff_variable == 'nuclide_density': - string += '{0: <16}{1}{2}\n'.format('\tDiff_material', '=\t', - self.diff_material) - string += '{0: <16}{1}{2}\n'.format('\tDiff_nuclide', '=\t', - self.diff_nuclide) - else: - raise RuntimeError("Encountered unrecognized differential " - "variable in a tally.") + if self.derivative is not None: + string += '{0: <16}id =\t{1}\n'.format('\tDerivative', '=\t', + str(self.derivative.id)) string += '{0: <16}{1}\n'.format('\tFilters', '=\t') @@ -443,16 +426,8 @@ class Tally(object): return self._derived @property - def diff_variable(self): - return self._diff_variable - - @property - def diff_material(self): - return self._diff_material - - @property - def diff_nuclide(self): - return self._diff_nuclide + def derivative(self): + return self._derivative @property def sparse(self): @@ -501,26 +476,11 @@ class Tally(object): else: self._name = '' - @diff_variable.setter - def diff_variable(self, var): - if var is not None: - cv.check_type('differential variable', var, basestring) - if var not in ('density', 'nuclide_density'): - raise ValueError("A tally differential variable must be either " - "'density' or 'nuclide_density'") - self._diff_variable = var - - @diff_material.setter - def diff_material(self, mat): - if mat is not None: - cv.check_type('differential material', mat, Integral) - self._diff_material = mat - - @diff_nuclide.setter - def diff_nuclide(self, nuc): - if nuc is not None: - cv.check_type('differential nuclide', nuc, basestring) - self._diff_nuclide = nuc + @derivative.setter + def derivative(self, deriv): + if deriv is not None: + cv.check_type('tally derivative', deriv, TallyDerivative) + self._derivative = deriv def add_filter(self, new_filter): """Add a filter to the tally @@ -884,21 +844,6 @@ class Tally(object): subelement = ET.SubElement(element, "nuclides") subelement.text = nuclides.rstrip(' ') - # Optional derivative - if self.diff_variable is not None: - if self.diff_variable == 'density': - subelement = ET.SubElement(element, "derivative") - subelement.set("variable", self.diff_variable) - subelement.set("material", str(self.diff_material)) - elif self.diff_variable == 'nuclide_density': - subelement = ET.SubElement(element, "derivative") - subelement.set("variable", self.diff_variable) - subelement.set("material", str(self.diff_material)) - subelement.set("nuclide", self.diff_nuclide) - else: - raise RuntimeError("Encountered unrecognized differential " - "variable in a tally.") - # Scores if len(self.scores) == 0: msg = 'Unable to get XML for Tally ID="{0}" since it does not ' \ @@ -922,6 +867,11 @@ class Tally(object): for trigger in self.triggers: trigger.get_trigger_xml(element) + # Optional derivatives + if self.derivative is not None: + subelement = ET.SubElement(element, "derivative") + subelement.text = str(self.derivative.id) + return element def find_filter(self, filter_type): @@ -1421,12 +1371,12 @@ class Tally(object): df['score'] = np.tile(self.scores, int(tile_factor)) # Include columns for derivatives if user requested it - if derivative and (self.diff_variable is not None): - df['d_variable'] = self.diff_variable - if self.diff_material is not None: - df['d_material'] = self.diff_material - if self.diff_nuclide is not None: - df['d_nuclide'] = self.diff_nuclide + if derivative and (self.derivative is not None): + df['d_variable'] = self.derivative.variable + if self.derivative.material is not None: + df['d_material'] = self.derivative.material + if self.derivative.nuclide is not None: + df['d_nuclide'] = self.derivative.nuclide # Append columns with mean, std. dev. for each tally bin df['mean'] = self.mean.ravel() @@ -3199,6 +3149,18 @@ class TalliesFile(object): xml_element = mesh.get_mesh_xml() self._tallies_file.append(xml_element) + def _create_derivative_subelements(self): + # Get a list of all derivatives referenced in a tally. + derivs = [] + for tally in self._tallies: + deriv = tally.derivative + if deriv is not None and deriv not in derivs: + derivs.append(deriv) + + # Add the derivatives to the XML tree. + for d in derivs: + self._tallies_file.append(d.get_derivative_xml()) + def export_to_xml(self): """Create a tallies.xml file that can be used for a simulation. @@ -3209,6 +3171,7 @@ class TalliesFile(object): self._create_mesh_subelements() self._create_tally_subelements() + self._create_derivative_subelements() # Clean the indentation in the file to be user-readable clean_xml_indentation(self._tallies_file) diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py new file mode 100644 index 000000000..0d8f6659e --- /dev/null +++ b/openmc/tally_derivative.py @@ -0,0 +1,182 @@ +from __future__ import division + +#from collections import Iterable, defaultdict +#import copy +#import os +#import pickle +#import itertools +from numbers import Integral +from xml.etree import ElementTree as ET +#import sys +# +#import numpy as np +# +#from openmc import Mesh, Filter, Trigger, Nuclide +#from openmc.cross import CrossScore, CrossNuclide, CrossFilter +#from openmc.aggregate import AggregateScore, AggregateNuclide, AggregateFilter +#from openmc.filter import _FILTER_TYPES +import openmc.checkvalue as cv +#from openmc.clean_xml import * +# +# +#if sys.version_info[0] >= 3: +# basestring = str + +# "Static" variable for auto-generated TallyDerivative IDs +AUTO_TALLY_DERIV_ID = 10000 + +def reset_auto_tally_deriv_id(): + global AUTO_TALLY_ID + AUTO_TALLY_DERIV_ID = 10000 + + +class TallyDerivative(object): + """A material perturbation derivative to apply to a tally. + + Parameters + ---------- + derivative_id : Integral, optional + Unique identifier for the tally derivative. If none is specified, an + identifier will automatically be assigned + + Attributes + ---------- + id : Integral + Unique identifier for the tally derivative + variable : str + Either 'density' or 'nuclide_density' + material : Integral + The perutrubed material + nuclide : str + The perturbed nuclide. Only needed for 'nuclide_density' derivatives. + Ex: 'Xe-135' + + """ + + def __init__(self, derivative_id=None): + # Initialize Tally class attributes + self.id = derivative_id + self._variable = None + self._material = None + self._nuclide = None + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, create a + # copy + if existing is None: + clone = type(self).__new__(type(self)) + clone.id = self.id + clone.variable = self.variable + clone.material = self.material + clone.nuclide = self.nuclide + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + def __eq__(self, other): + if not isinstance(other, TallyDerivative): + return False + + return (self.variable == other.variable and + self.material == other.material and + self.nuclide == other.nuclide) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(repr(self)) + + def __repr__(self): + string = 'Tally Derivative\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) + string += '{0: <16}{1}{2}\n'.format('\tVariable', '=\t', + self.variable) + + if self.variable == 'density': + string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', + self.material) + elif self.variable == 'nuclide_density': + string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', + self.material) + string += '{0: <16}{1}{2}\n'.format('\tNuclide', '=\t', + self.nuclide) + else: + raise RuntimeError("Encountered unrecognized differential " + "variable in a tally.") + + return string + + @property + def id(self): + return self._id + + @property + def variable(self): + return self._variable + + @property + def material(self): + return self._material + + @property + def nuclide(self): + return self._nuclide + + @id.setter + def id(self, deriv_id): + if deriv_id is None: + global AUTO_TALLY_DERIV_ID + self._id = AUTO_TALLY_DERIV_ID + AUTO_TALLY_DERIV_ID += 1 + else: + cv.check_type('tally derivative ID', deriv_id, Integral) + cv.check_greater_than('tally derivative ID', deriv_id, 0, + equality=True) + self._id = deriv_id + + @variable.setter + def variable(self, var): + if var is not None: + cv.check_type('derivative variable', var, basestring) + if var not in ('density', 'nuclide_density'): + raise ValueError("A tally differential variable must be either " + "'density' or 'nuclide_density'") + self._variable = var + + @material.setter + def material(self, mat): + if mat is not None: + cv.check_type('derivative material', mat, Integral) + self._material = mat + + @nuclide.setter + def nuclide(self, nuc): + if nuc is not None: + cv.check_type('derivative nuclide', nuc, basestring) + self._nuclide = nuc + + def get_derivative_xml(self): + """Return XML representation of the tally derivative + + Returns + ------- + element : xml.etree.ElementTree.Element + XML element containing derivative data + + """ + + element = ET.Element("derivative") + element.set("id", str(self.id)) + element.set("variable", self.variable) + element.set("material", str(self.material)) + if self.variable == 'nuclide_density': + element.set("nuclide", self.nuclide) + return element diff --git a/src/global.F90 b/src/global.F90 index a5943b6b7..ebbdb58b2 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -13,7 +13,8 @@ module global use set_header, only: SetInt use surface_header, only: SurfaceContainer use source_header, only: SourceDistribution - use tally_header, only: TallyObject, TallyMap, TallyResult + use tally_header, only: TallyObject, TallyMap, TallyResult, & + TallyDerivative use trigger_header, only: KTrigger use timer_header, only: Timer @@ -145,6 +146,10 @@ module global integer :: n_tallies = 0 ! # of tallies integer :: n_user_tallies = 0 ! # of user tallies + ! Tally derivatives + type(TallyDerivative), allocatable :: tally_derivs(:) +!$omp threadprivate(tally_derivs) + ! Normalization for statistics integer :: n_realizations = 0 ! # of independent realizations real(8) :: total_weight ! total starting particle weight in realization diff --git a/src/input_xml.F90 b/src/input_xml.F90 index aeab9e6bc..fdf92dde3 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2334,12 +2334,13 @@ contains type(Node), pointer :: node_mesh => null() type(Node), pointer :: node_tal => null() type(Node), pointer :: node_filt => null() - type(Node), pointer :: node_trigger=>null() + type(Node), pointer :: node_trigger => null() type(Node), pointer :: node_deriv => null() type(NodeList), pointer :: node_mesh_list => null() type(NodeList), pointer :: node_tal_list => null() type(NodeList), pointer :: node_filt_list => null() type(NodeList), pointer :: node_trigger_list => null() + type(NodeList), pointer :: node_deriv_list => null() type(ElemKeyValueCI), pointer :: scores type(ElemKeyValueCI), pointer :: next @@ -2525,6 +2526,81 @@ contains ! We only need the mesh info for plotting if (run_mode == MODE_PLOTTING) return + ! ========================================================================== + ! READ DATA FOR DERIVATIVES + + ! Get pointer list to XML . + call get_node_list(doc, "derivative", node_deriv_list) + + ! Allocate TallyDerivative array. + allocate(tally_derivs(get_list_size(node_deriv_list))) + + ! Read derivative attributes. + do i = 1, get_list_size(node_deriv_list) + associate(deriv => tally_derivs(i)) + ! Get pointer to derivative node. + call get_list_item(node_deriv_list, i, node_deriv) + + ! Copy the derivative id. + if (check_for_node(node_deriv, "id")) then + call get_node_value(node_deriv, "id", deriv % id) + else + call fatal_error("Must specify an ID for elements in the& + & tally XML file") + end if + + ! Make sure the id is > 0. + if (deriv % id <= 0) call fatal_error(" IDs must be an & + &integer greater than zero") + + ! Make sure this id has not already been used. + do j = 1, i-1 + if (tally_derivs(j) % id == deriv % id) call fatal_error("Two or more& + & 's use the same unique ID: " & + // trim(to_str(deriv % id))) + end do + + ! Read the dependent variable name. + temp_str = "" + call get_node_value(node_deriv, "variable", temp_str) + temp_str = to_lower(temp_str) + + select case(temp_str) + + case("density") + deriv % variable = DIFF_DENSITY + call get_node_value(node_deriv, "material", deriv % diff_material) + + case("nuclide_density") + deriv % variable = DIFF_NUCLIDE_DENSITY + call get_node_value(node_deriv, "material", deriv % diff_material) + + call get_node_value(node_deriv, "nuclide", word) + word = trim(to_lower(word)) + pair_list => nuclide_dict % keys() + do while (associated(pair_list)) + if (starts_with(pair_list % key, word)) then + word = pair_list % key(1:150) + exit + end if + + ! Advance to next + pair_list => pair_list % next + end do + + ! Check if no nuclide was found + if (.not. associated(pair_list)) then + call fatal_error("Could not find the nuclide " & + &// trim(word) // " specified in derivative " & + &// trim(to_str(deriv % id)) // " in any material.") + end if + deallocate(pair_list) + + deriv % diff_nuclide = nuclide_dict % get_key(word) + end select + end associate + end do + ! ========================================================================== ! READ TALLY DATA @@ -2982,52 +3058,6 @@ contains end do end if - ! ======================================================================= - ! READ DATA FOR DERIVATIVES - - if (check_for_node(node_tal, "derivative")) then - call get_node_ptr(node_tal, "derivative", node_deriv) - allocate(t % deriv) - - temp_str = "" - call get_node_value(node_deriv, "variable", temp_str) - temp_str = to_lower(temp_str) - - select case(temp_str) - - case("density") - t % deriv % variable = DIFF_DENSITY - call get_node_value(node_deriv, "material", t % deriv % diff_material) - - case("nuclide_density") - t % deriv % variable = DIFF_NUCLIDE_DENSITY - call get_node_value(node_deriv, "material", t % deriv % diff_material) - - call get_node_value(node_deriv, "nuclide", word) - word = trim(to_lower(word)) - pair_list => nuclide_dict % keys() - do while (associated(pair_list)) - if (starts_with(pair_list % key, word)) then - word = pair_list % key(1:150) - exit - end if - - ! Advance to next - pair_list => pair_list % next - end do - - ! 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.") - end if - deallocate(pair_list) - - t % deriv % diff_nuclide = nuclide_dict % get_key(word) - end select - end if - ! ======================================================================= ! READ DATA FOR SCORES @@ -3479,10 +3509,28 @@ contains &// trim(to_str(t % id)) // ".") end if - ! If a derivative is present, we can only use analog or collision - ! estimators. - if (allocated(t % deriv) .and. t % estimator == ESTIMATOR_TRACKLENGTH) & - t % estimator = ESTIMATOR_COLLISION + ! Check for a tally derivative. + if (check_for_node(node_tal, "derivative")) then + ! Temporarily store the derivative id. + call get_node_value(node_tal, "derivative", t % deriv) + + ! Find the derivative with the given id, and store it's index. + do j = 1, size(tally_derivs) + if (tally_derivs(j) % id == t % deriv) then + t % deriv = j + ! Only analog or collision estimators are supported for differential + ! tallies. + if (t % estimator == ESTIMATOR_TRACKLENGTH) & + t % estimator = ESTIMATOR_COLLISION + exit + end if + if (j == size(tally_derivs)) then + call fatal_error("Could not find derivative " & + // trim(to_str(t % deriv)) // " specified on tally " & + // trim(to_str(t % id))) + end if + end do + end if ! If settings.xml trigger is turned on, create tally triggers if (trigger_on) then diff --git a/src/output.F90 b/src/output.F90 index b7e8a18ae..e09797b28 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -1017,21 +1017,21 @@ contains endif ! Write derivative information. - if (allocated(t % deriv)) then - select case (t % deriv % variable) - case (DIFF_DENSITY) - write(unit=unit_tally, fmt="(' Density derivative Material ',A)") & - to_str(t % deriv % diff_material) - case (DIFF_NUCLIDE_DENSITY) - i_listing = nuclides(t % deriv % diff_nuclide) % listing - write(unit=unit_tally, fmt="(' Nuclide density derivative Material '& - &,A,' Nuclide ',A)") trim(to_str(t % deriv % diff_material)), & - trim(xs_listings(i_listing) % alias) - case default - call fatal_error("Differential tally dependent variable for tally " & - // trim(to_str(t % id)) // " not defined in output.F90.") - end select - end if + !if (allocated(t % deriv)) then + ! select case (t % deriv % variable) + ! case (DIFF_DENSITY) + ! write(unit=unit_tally, fmt="(' Density derivative Material ',A)") & + ! to_str(t % deriv % diff_material) + ! case (DIFF_NUCLIDE_DENSITY) + ! i_listing = nuclides(t % deriv % diff_nuclide) % listing + ! write(unit=unit_tally, fmt="(' Nuclide density derivative Material '& + ! &,A,' Nuclide ',A)") trim(to_str(t % deriv % diff_material)), & + ! trim(xs_listings(i_listing) % alias) + ! case default + ! call fatal_error("Differential tally dependent variable for tally " & + ! // trim(to_str(t % id)) // " not defined in output.F90.") + ! end select + !end if ! Handle surface current tallies separately if (t % type == TALLY_SURFACE_CURRENT) then diff --git a/src/simulation.F90 b/src/simulation.F90 index cc230d645..6e2d7957c 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -80,7 +80,7 @@ contains ! ==================================================================== ! LOOP OVER PARTICLES -!$omp parallel do schedule(static) firstprivate(p) +!$omp parallel do schedule(static) firstprivate(p) copyin(tally_derivs) PARTICLE_LOOP: do i_work = 1, work current_work = i_work diff --git a/src/state_point.F90 b/src/state_point.F90 index c31b2b7a3..4c9d6f000 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -52,7 +52,7 @@ contains integer(HID_T) :: cmfd_group integer(HID_T) :: tallies_group, tally_group integer(HID_T) :: meshes_group, mesh_group - integer(HID_T) :: filter_group, deriv_group + integer(HID_T) :: filter_group, derivs_group, deriv_group character(20), allocatable :: str_array(:) character(MAX_FILE_LEN) :: filename type(RegularMesh), pointer :: meshp @@ -194,6 +194,35 @@ contains call close_group(meshes_group) + ! Write information for derivatives. + if (size(tally_derivs) > 0) then + derivs_group = create_group(tallies_group, "derivatives") + do i = 1, size(tally_derivs) + associate(deriv => tally_derivs(i)) + deriv_group = create_group(derivs_group, "derivative " & + // trim(to_str(deriv % id))) + select case (deriv % variable) + case (DIFF_DENSITY) + call write_dataset(deriv_group, "dependent variable", "density") + call write_dataset(deriv_group, "material", deriv % diff_material) + case (DIFF_NUCLIDE_DENSITY) + call write_dataset(deriv_group, "dependent variable", & + "nuclide_density") + call write_dataset(deriv_group, "material", deriv % diff_material) + i_list = nuclides(deriv % diff_nuclide) % listing + call write_dataset(deriv_group, "nuclide", & + xs_listings(i_list) % alias) + case default + call fatal_error("Dependent variable for derivative " & + // trim(to_str(deriv % id)) // " not defined in & + &state_point.F90.") + end select + call close_group(deriv_group) + end associate + end do + call close_group(derivs_group) + end if + ! Write number of tallies call write_dataset(tallies_group, "n_tallies", n_tallies) @@ -308,30 +337,9 @@ contains deallocate(str_array) ! Write derivative information. - if (allocated(tally % deriv)) then - call write_dataset(tally_group, "derivative present", 1) - deriv_group = create_group(tally_group, "derivative") - select case (tally % deriv % variable) - case (DIFF_DENSITY) - call write_dataset(deriv_group, "dependent variable", "density") - call write_dataset(deriv_group, "material", & - tally % deriv % diff_material) - case (DIFF_NUCLIDE_DENSITY) - call write_dataset(deriv_group, "dependent variable", & - "nuclide_density") - call write_dataset(deriv_group, "material", & - tally % deriv % diff_material) - i_list = nuclides(tally % deriv % diff_nuclide) % listing - call write_dataset(deriv_group, "nuclide", & - xs_listings(i_list) % alias) - case default - call fatal_error("Differential tally dependent variable for & - &tally " // trim(to_str(tally % id)) // " not defined in & - &state_point.F90.") - end select - call close_group(deriv_group) - else - call write_dataset(tally_group, "derivative present", 0) + if (tally % deriv /= NONE) then + call write_dataset(tally_group, "derivative", & + tally_derivs(tally % deriv) % id) end if ! Write scores. diff --git a/src/tally.F90 b/src/tally.F90 index 058595ca9..4dea2e249 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -746,7 +746,7 @@ contains !######################################################################### ! Add derivative information on score for differential tallies. - if (allocated(t % deriv)) then + if (t % deriv /= NONE) then call apply_derivative_to_score(p, t, i_nuclide, atom_density, & score_bin, score) end if @@ -1049,7 +1049,7 @@ contains ! Add derivative information for differenetial tallies. Note that the ! i_nuclide and atom_density arguments do not matter since this is an ! analog estimator. - if (allocated(t % deriv)) then + if (t % deriv /= NONE) then call apply_derivative_to_score(p, t, 0, ZERO, SCORE_NU_FISSION, score) end if @@ -2254,166 +2254,163 @@ contains integer :: l ! loop index for nuclides in material logical :: scoring_diff_nuclide - select case (t % deriv % variable) + associate(deriv => tally_derivs(t % deriv)) + select case (deriv % variable) - case (DIFF_DENSITY) - select case (t % estimator) + case (DIFF_DENSITY) + select case (t % estimator) - case (ESTIMATOR_ANALOG) - if (materials(p % material) % id == t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * t % deriv % flux_deriv - end if - - case (ESTIMATOR_COLLISION) - - select case (score_bin) - - case (SCORE_FLUX) - score = score * t % deriv % flux_deriv - - case (SCORE_TOTAL) - if (materials(p % material) % id == t % deriv % diff_material & - .and. material_xs % total /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE & + case (ESTIMATOR_ANALOG) + if (materials(p % material) % id == deriv % diff_material) then + score = score * (deriv % flux_deriv + ONE & / materials(p % material) % density_gpcc) else - score = score * t % deriv % flux_deriv + score = score * deriv % flux_deriv end if - case (SCORE_ABSORPTION) - if (materials(p % material) % id == t % deriv % diff_material & - .and. material_xs % absorption /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * t % deriv % flux_deriv - end if + case (ESTIMATOR_COLLISION) - case (SCORE_FISSION) - if (materials(p % material) % id == t % deriv % diff_material & - .and. material_xs % fission /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * t % deriv % flux_deriv - end if + select case (score_bin) - case (SCORE_NU_FISSION) - if (materials(p % material) % id == t % deriv % diff_material & - .and. material_xs % nu_fission /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * t % deriv % flux_deriv - end if + case (SCORE_FLUX) + score = score * deriv % flux_deriv + + case (SCORE_TOTAL) + if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % total /= ZERO) then + score = score * (deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_ABSORPTION) + if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % absorption /= ZERO) then + score = score * (deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_FISSION) + if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % fission /= ZERO) then + score = score * (deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_NU_FISSION) + if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % nu_fission /= ZERO) then + score = score * (deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * deriv % flux_deriv + end if + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + end select case default - call fatal_error('Tally derivative not defined for a score on & - &tally ' // trim(to_str(t % id))) - + call fatal_error("Differential tallies are only implemented for & + &analog and collision estimators.") end select - case default - call fatal_error("Differential tallies are only implemented for & - &analog and collision estimators.") + case (DIFF_NUCLIDE_DENSITY) + select case (t % estimator) - end select - - case (DIFF_NUCLIDE_DENSITY) - select case (t % estimator) - - case (ESTIMATOR_ANALOG) - if (materials(p % material) % id == t % deriv % diff_material & - .and. p % event_nuclide == t % deriv % diff_nuclide) then - associate(mat => materials(p % material)) - do l = 1, mat % n_nuclides - if (mat % nuclide(l) == t % deriv % diff_nuclide) exit - end do - score = score * (t % deriv % flux_deriv & - + ONE / mat % atom_density(l)) - end associate - else - score = score * t % deriv % flux_deriv - end if - - case (ESTIMATOR_COLLISION) - scoring_diff_nuclide = & - (materials(p % material) % id == t % deriv % diff_material) & - .and. (i_nuclide == t % deriv % diff_nuclide) - - select case (score_bin) - - case (SCORE_FLUX) - score = score * t % deriv % flux_deriv - - case (SCORE_TOTAL) - if (i_nuclide == -1 .and. & - materials(p % material) % id == t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % total & - / material_xs % total) - else if (scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % total /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) + case (ESTIMATOR_ANALOG) + if (materials(p % material) % id == deriv % diff_material & + .and. p % event_nuclide == deriv % diff_nuclide) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == deriv % diff_nuclide) exit + end do + score = score * (deriv % flux_deriv & + + ONE / mat % atom_density(l)) + end associate else - score = score * t % deriv % flux_deriv + score = score * deriv % flux_deriv end if - case (SCORE_ABSORPTION) - if (i_nuclide == -1 .and. & - materials(p % material) % id == t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % absorption & - / material_xs % absorption ) - else if (scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % absorption /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) - else - score = score * t % deriv % flux_deriv - end if + case (ESTIMATOR_COLLISION) + scoring_diff_nuclide = & + (materials(p % material) % id == deriv % diff_material) & + .and. (i_nuclide == deriv % diff_nuclide) - case (SCORE_FISSION) - if (i_nuclide == -1 .and. & - materials(p % material) % id == t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % fission & - / material_xs % fission) - else if (scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % fission /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) - else - score = score * t % deriv % flux_deriv - end if + select case (score_bin) - case (SCORE_NU_FISSION) - if (i_nuclide == -1 .and. & - materials(p % material) % id == t % deriv % diff_material) then - score = score * (t % deriv % flux_deriv & - + micro_xs(t % deriv % diff_nuclide) % nu_fission & - / material_xs % nu_fission) - else if (scoring_diff_nuclide .and. & - micro_xs(t % deriv % diff_nuclide) % nu_fission /= ZERO) then - score = score * (t % deriv % flux_deriv + ONE / atom_density) - else - score = score * t % deriv % flux_deriv - end if + case (SCORE_FLUX) + score = score * deriv % flux_deriv + + case (SCORE_TOTAL) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material) then + score = score * (deriv % flux_deriv & + + micro_xs(deriv % diff_nuclide) % total & + / material_xs % total) + else if (scoring_diff_nuclide .and. & + micro_xs(deriv % diff_nuclide) % total /= ZERO) then + score = score * (deriv % flux_deriv + ONE / atom_density) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_ABSORPTION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material) then + score = score * (deriv % flux_deriv & + + micro_xs(deriv % diff_nuclide) % absorption & + / material_xs % absorption ) + else if (scoring_diff_nuclide .and. & + micro_xs(deriv % diff_nuclide) % absorption /= ZERO) then + score = score * (deriv % flux_deriv + ONE / atom_density) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_FISSION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material) then + score = score * (deriv % flux_deriv & + + micro_xs(deriv % diff_nuclide) % fission & + / material_xs % fission) + else if (scoring_diff_nuclide .and. & + micro_xs(deriv % diff_nuclide) % fission /= ZERO) then + score = score * (deriv % flux_deriv + ONE / atom_density) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_NU_FISSION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material) then + score = score * (deriv % flux_deriv & + + micro_xs(deriv % diff_nuclide) % nu_fission & + / material_xs % nu_fission) + else if (scoring_diff_nuclide .and. & + micro_xs(deriv % diff_nuclide) % nu_fission /= ZERO) then + score = score * (deriv % flux_deriv + ONE / atom_density) + else + score = score * deriv % flux_deriv + end if + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + end select case default - call fatal_error('Tally derivative not defined for a score on & - &tally ' // trim(to_str(t % id))) - + call fatal_error("Differential tallies are only implemented for & + &analog and collision estimators.") end select - - case default - call fatal_error("Differential tallies are only implemented for & - &analog and collision estimators.") - end select - - end select + end associate end subroutine apply_derivative_to_score !=============================================================================== @@ -2427,33 +2424,32 @@ contains integer :: i + ! A void material cannot be perturbed so it will not affect flux derivatives if (p % material == MATERIAL_VOID) return - do i = 1, active_tallies % size() - associate (t => tallies(active_tallies % get_item(i))) - if (.not. allocated(t % deriv)) cycle ! Ignore non-differential tallies - - select case (t % deriv % variable) + do i = 1, size(tally_derivs) + associate(deriv => tally_derivs(i)) + select case (deriv % variable) case (DIFF_DENSITY) associate (mat => materials(p % material)) - if (mat % id == t % deriv % diff_material) then + if (mat % id == deriv % diff_material) then ! phi = e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_rho) = - (d_Sigma_tot / d_rho) * dist ! (1 / phi) * (d_phi / d_rho) = - Sigma_tot / rho * dist - t % deriv % flux_deriv = t % deriv % flux_deriv & + deriv % flux_deriv = deriv % flux_deriv & - distance * material_xs % total / mat % density_gpcc end if end associate case (DIFF_NUCLIDE_DENSITY) associate (mat => materials(p % material)) - if (mat % id == t % deriv % diff_material) then + if (mat % id == deriv % diff_material) then ! phi = e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_N) = - (d_Sigma_tot / d_N) * dist ! (1 / phi) * (d_phi / d_N) = - sigma_tot * dist - t % deriv % flux_deriv = t % deriv % flux_deriv & - - distance * micro_xs(t % deriv % diff_nuclide) % total + deriv % flux_deriv = deriv % flux_deriv & + - distance * micro_xs(deriv % diff_nuclide) % total end if end associate end select @@ -2471,41 +2467,41 @@ contains integer :: i, j + ! A void material cannot be perturbed so it will not affect flux derivatives if (p % material == MATERIAL_VOID) return - do i = 1, active_tallies % size() - associate (t => tallies(active_tallies % get_item(i))) - if (.not. allocated(t % deriv)) cycle ! Ignore non-differential tallies - select case (t % deriv % variable) + do i = 1, size(tally_derivs) + associate(deriv => tally_derivs(i)) + select case (deriv % variable) case (DIFF_DENSITY) associate (mat => materials(p % material)) - if (mat % id == t % deriv % diff_material) then + if (mat % id == deriv % diff_material) then ! phi = Sigma_MT ! (1 / phi) * (d_phi / d_rho) = (d_Sigma_MT / d_rho) / Sigma_MT ! (1 / phi) * (d_phi / d_rho) = 1 / rho - t % deriv % flux_deriv = t % deriv % flux_deriv & + deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % density_gpcc end if end associate case (DIFF_NUCLIDE_DENSITY) associate (mat => materials(p % material)) - if (mat % id == t % deriv % diff_material & - .and. p % event_nuclide == t % deriv % diff_nuclide) then + if (mat % id == deriv % diff_material & + .and. p % event_nuclide == deriv % diff_nuclide) then ! Find the index in this material for the diff_nuclide. do j = 1, mat % n_nuclides - if (mat % nuclide(j) == t % deriv % diff_nuclide) exit + if (mat % nuclide(j) == deriv % diff_nuclide) exit end do ! Make sure we found the nuclide. - if (mat % nuclide(j) /= t % deriv % diff_nuclide) then + if (mat % nuclide(j) /= deriv % diff_nuclide) then call fatal_error("Couldn't find the right nuclide.") end if ! phi = Sigma_MT ! (1 / phi) * (d_phi / d_N) = (d_Sigma_MT / d_N) / Sigma_MT ! (1 / phi) * (d_phi / d_N) = sigma_MT / Sigma_MT ! (1 / phi) * (d_phi / d_N) = 1 / N - t % deriv % flux_deriv = t % deriv % flux_deriv & + deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % atom_density(j) end if end associate @@ -2520,10 +2516,8 @@ contains subroutine zero_flux_derivs() integer :: i - do i = 1, n_tallies - if (allocated(tallies(i) % deriv)) then - tallies(i) % deriv % flux_deriv = ZERO - end if + do i = 1, size(tally_derivs) + tally_derivs(i) % flux_deriv = ZERO end do end subroutine zero_flux_derivs diff --git a/src/tally_header.F90 b/src/tally_header.F90 index a7b455d74..7d7bb6484 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -66,6 +66,7 @@ module tally_header !=============================================================================== type TallyDerivative + integer :: id real(8) :: flux_deriv integer :: variable integer :: diff_material @@ -138,8 +139,8 @@ module tally_header integer :: n_triggers = 0 ! # of triggers type(TriggerObject), allocatable :: triggers(:) ! Array of triggers - ! Derivative for differentially tallies - type(TallyDerivative), allocatable :: deriv + ! Index for the TallyDerivative for differential tallies. + integer :: deriv = NONE end type TallyObject end module tally_header diff --git a/src/tracking.F90 b/src/tracking.F90 index 587b67809..f20e5e413 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -63,7 +63,7 @@ contains endif ! Every particle starts with no accumulated flux derivative. - call zero_flux_derivs() + if (active_tallies % size() > 0) call zero_flux_derivs() EVENT_LOOP: do ! If the cell hasn't been determined based on the particle's location, @@ -120,7 +120,7 @@ contains end if ! Score flux derivative accumulators for differential tallies. - call score_track_derivative(p, distance) + if (active_tallies % size() > 0) call score_track_derivative(p, distance) if (d_collision > d_boundary) then ! ==================================================================== @@ -197,7 +197,7 @@ contains end do ! Score flux derivative accumulators for differential tallies. - call score_collision_derivative(p) + if (active_tallies % size() > 0) call score_collision_derivative(p) end if ! If particle has too many events, display warning and kill it diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index 22656a483..f3dfdbc0f 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -1 +1 @@ -cb132b2211831bf333bc9be0b10d092ad3bbe9a188743cf4c430ae97037987763b268997757a0602c164d8c2deb3eb9843590d860ba5a4858092a9ad0b8adeba \ No newline at end of file +e398b5d359cab6a448e1273beaf2d5c9125d4ad06546ddfd327111b101ac223e11b6f98d3b490b8544972969f37456c24a78016ce68773abba27828ba43e3173 \ No newline at end of file diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index 2bd0f704d..6a68596dc 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -10,8 +10,8 @@ except: import sys sys.path.insert(0, os.pardir) from testing_harness import PyAPITestHarness -from openmc import Filter, Mesh, Tally, TalliesFile, Summary, StatePoint -#from openmc.statepoint import StatePoint +from openmc import Filter, Mesh, Tally, TalliesFile, Summary, StatePoint, \ + TallyDerivative from openmc.source import Source from openmc.stats import Box @@ -33,26 +33,35 @@ class DiffTallyTestHarness(PyAPITestHarness): filt_mats = Filter(type='material', bins=(1, 3)) filt_eout = Filter(type='energyout', bins=(0.0, 1.0, 20.0)) + # We want density derivatives for both water and fuel to get coverage + # for both fissile and non-fissile materials. + d1 = TallyDerivative(derivative_id=1) + d1.variable = 'density' + d1.material = 3 + d2 = TallyDerivative(derivative_id=2) + d2.variable = 'density' + d2.material = 1 + + # O-16 is a good nuclide to test against because it is present in both + # water and fuel. Some routines need to recognize that they have the + # perturbed nuclide but not the perturbed material. + d3 = TallyDerivative(derivative_id=3) + d3.variable = 'nuclide_density' + d3.material = 1 + d3.nuclide = 'O-16' + + # A fissile nuclide, just for good measure. + d4 = TallyDerivative(derivative_id=4) + d4.variable = 'nuclide_density' + d4.material = 1 + d4.nuclide = 'U-235' + def add_derivs(tally_list): assert len(tally_list) == 4 - # We want density derivatives for both water and fuel to get - # coverage for both fissile and non-fissile materials. - tally_list[0].diff_variable = 'density' - tally_list[0].diff_material = 3 - tally_list[1].diff_variable = 'density' - tally_list[1].diff_material = 1 - - # O-16 is a good nuclide to test against because it is present - # in both water and fuel. Some routines need to recognize that they - # have the perturbed nuclide but not the perturbed material. - tally_list[2].diff_variable = 'nuclide_density' - tally_list[2].diff_material = 1 - tally_list[2].diff_nuclide = 'O-16' - - # A fissile nuclide, just for good measure. - tally_list[3].diff_variable = 'nuclide_density' - tally_list[3].diff_material = 1 - tally_list[3].diff_nuclide = 'U-235' + tally_list[0].derivative = d1 + tally_list[1].derivative = d2 + tally_list[2].derivative = d3 + tally_list[3].derivative = d4 # Cover the flux score. tallies = [Tally() for i in range(4)] diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 66cadfe63..a462cf1bd 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -26,7 +26,7 @@ class TestHarness(object): self.parser = OptionParser() self.parser.add_option('--exe', dest='exe', default='openmc') self.parser.add_option('--mpi_exec', dest='mpi_exec', default=None) - self.parser.add_option('--mpi_np', dest='mpi_np', type=int, default=3) + self.parser.add_option('--mpi_np', dest='mpi_np', type=int, default=1) self.parser.add_option('--update', dest='update', action='store_true', default=False) self._opts = None From 8b45186c37d92c90f9a6de7ac1513d3ecaaf3689 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 30 Jan 2016 23:18:08 -0500 Subject: [PATCH 17/60] Address PR comments --- openmc/tally_derivative.py | 22 +------- src/initialize.F90 | 12 ++-- src/input_xml.F90 | 8 +-- tests/test_diff_tally/test_diff_tally.py | 72 ++++++++++++------------ 4 files changed, 47 insertions(+), 67 deletions(-) diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py index 0d8f6659e..932fd28a2 100644 --- a/openmc/tally_derivative.py +++ b/openmc/tally_derivative.py @@ -1,26 +1,9 @@ from __future__ import division -#from collections import Iterable, defaultdict -#import copy -#import os -#import pickle -#import itertools from numbers import Integral from xml.etree import ElementTree as ET -#import sys -# -#import numpy as np -# -#from openmc import Mesh, Filter, Trigger, Nuclide -#from openmc.cross import CrossScore, CrossNuclide, CrossFilter -#from openmc.aggregate import AggregateScore, AggregateNuclide, AggregateFilter -#from openmc.filter import _FILTER_TYPES + import openmc.checkvalue as cv -#from openmc.clean_xml import * -# -# -#if sys.version_info[0] >= 3: -# basestring = str # "Static" variable for auto-generated TallyDerivative IDs AUTO_TALLY_DERIV_ID = 10000 @@ -108,9 +91,6 @@ class TallyDerivative(object): self.material) string += '{0: <16}{1}{2}\n'.format('\tNuclide', '=\t', self.nuclide) - else: - raise RuntimeError("Encountered unrecognized differential " - "variable in a tally.") return string diff --git a/src/initialize.F90 b/src/initialize.F90 index 51d130c6d..ae6283874 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -849,12 +849,12 @@ contains mat%atom_density = mat%density * mat%atom_density ! Calculate density in g/cm^3. - mat%density_gpcc = ZERO - do j = 1, mat%n_nuclides - index_list = xs_listing_dict%get_key(mat%names(j)) - awr = xs_listings(index_list)%awr - mat%density_gpcc = mat%density_gpcc & - + mat%atom_density(j) * awr * MASS_NEUTRON / N_AVOGADRO + mat % density_gpcc = ZERO + do j = 1, mat % n_nuclides + index_list = xs_listing_dict % get_key(mat % names(j)) + awr = xs_listings(index_list) % awr + mat % density_gpcc = mat % density_gpcc & + + mat % atom_density(j) * awr * MASS_NEUTRON / N_AVOGADRO end do end do diff --git a/src/input_xml.F90 b/src/input_xml.F90 index fdf92dde3..f811cab04 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2591,8 +2591,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 derivative " & - &// trim(to_str(deriv % id)) // " in any material.") + // trim(word) // " specified in derivative " & + // trim(to_str(deriv % id)) // " in any material.") end if deallocate(pair_list) @@ -3021,8 +3021,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) diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index 6a68596dc..a7a020c2d 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -2,12 +2,14 @@ import glob import os -import pandas as pd try: from StringIO import StringIO except: from io import StringIO import sys + +import pandas as pd + sys.path.insert(0, os.pardir) from testing_harness import PyAPITestHarness from openmc import Filter, Mesh, Tally, TalliesFile, Summary, StatePoint, \ @@ -26,7 +28,7 @@ class DiffTallyTestHarness(PyAPITestHarness): self._input_set.settings.particles = 400 self._input_set.settings.source = Source(space=Box( [-160, -160, -183], [160, 160, 183])) - self._input_set.settings.output = {'summary':True} + self._input_set.settings.output = {'summary': True} self._input_set.tallies = TalliesFile() @@ -56,52 +58,50 @@ class DiffTallyTestHarness(PyAPITestHarness): d4.material = 1 d4.nuclide = 'U-235' - def add_derivs(tally_list): - assert len(tally_list) == 4 - tally_list[0].derivative = d1 - tally_list[1].derivative = d2 - tally_list[2].derivative = d3 - tally_list[3].derivative = d4 + derivs = [d1, d2, d3, d4] # Cover the flux score. - tallies = [Tally() for i in range(4)] - for t in tallies: t.add_score('flux') - for t in tallies: t.add_filter(filt_mats) - add_derivs(tallies) - for t in tallies: self._input_set.tallies.add_tally(t) + for i in range(4): + t = Tally() + t.add_score('flux') + t.add_filter(filt_mats) + t.derivative = derivs[i] + self._input_set.tallies.add_tally(t) # Cover supported scores with a collision estimator. - tallies = [Tally() for i in range(4)] - for t in tallies: t.add_score('total') - for t in tallies: t.add_score('absorption') - for t in tallies: t.add_score('fission') - for t in tallies: t.add_score('nu-fission') - for t in tallies: t.add_filter(filt_mats) - for t in tallies: t.add_nuclide('total') - for t in tallies: t.add_nuclide('U-235') - add_derivs(tallies) - for t in tallies: self._input_set.tallies.add_tally(t) + for i in range(4): + t = Tally() + t.add_score('total') + t.add_score('absorption') + t.add_score('fission') + t.add_score('nu-fission') + t.add_filter(filt_mats) + t.add_nuclide('total') + t.add_nuclide('U-235') + t.derivative = derivs[i] + self._input_set.tallies.add_tally(t) # Cover an analog estimator. - tallies = [Tally() for i in range(4)] - for t in tallies: t.add_score('absorption') - for t in tallies: t.add_filter(filt_mats) - for t in tallies: t.estimator = 'analog' - add_derivs(tallies) - for t in tallies: self._input_set.tallies.add_tally(t) + for i in range(4): + t = Tally() + t.add_score('absorption') + t.add_filter(filt_mats) + t.estimator = 'analog' + t.derivative = derivs[i] + self._input_set.tallies.add_tally(t) # And the special fission with energyout filter. - tallies = [Tally() for i in range(4)] - for t in tallies: t.add_score('nu-fission') - for t in tallies: t.add_filter(filt_mats) - for t in tallies: t.add_filter(filt_eout) - add_derivs(tallies) - for t in tallies: self._input_set.tallies.add_tally(t) + for i in range(4): + t = Tally() + t.add_score('nu-fission') + t.add_filter(filt_mats) + t.add_filter(filt_eout) + t.derivative = derivs[i] + self._input_set.tallies.add_tally(t) self._input_set.export() def _get_results(self): - #return super(DiffTallyTestHarness, self)._get_results(hash_output=True) # Read the statepoint and summary files. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) From 0796fb87a40d1447ae28bafa0ef3bd637ebee602 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 30 Jan 2016 23:35:06 -0500 Subject: [PATCH 18/60] Fix allocation check --- src/state_point.F90 | 2 +- tests/testing_harness.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state_point.F90 b/src/state_point.F90 index 7991719c8..84a2a1893 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -195,7 +195,7 @@ contains call close_group(meshes_group) ! Write information for derivatives. - if (size(tally_derivs) > 0) then + if (allocated(tally_derivs) .and. size(tally_derivs) > 0) then derivs_group = create_group(tallies_group, "derivatives") do i = 1, size(tally_derivs) associate(deriv => tally_derivs(i)) diff --git a/tests/testing_harness.py b/tests/testing_harness.py index a462cf1bd..66cadfe63 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -26,7 +26,7 @@ class TestHarness(object): self.parser = OptionParser() self.parser.add_option('--exe', dest='exe', default='openmc') self.parser.add_option('--mpi_exec', dest='mpi_exec', default=None) - self.parser.add_option('--mpi_np', dest='mpi_np', type=int, default=1) + self.parser.add_option('--mpi_np', dest='mpi_np', type=int, default=3) self.parser.add_option('--update', dest='update', action='store_true', default=False) self._opts = None From 5d98438544cb9c6af2b871911b1dc2a5abf0e2ea Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 30 Jan 2016 23:43:11 -0500 Subject: [PATCH 19/60] Fix Python3 string error --- openmc/statepoint.py | 6 ++++-- openmc/tally_derivative.py | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index ab37be78d..ae86c2603 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -467,12 +467,14 @@ class StatePoint(object): for d_id in deriv_ids: base = 'tallies/derivatives/derivative {:d}'.format(d_id) deriv = openmc.TallyDerivative(derivative_id=d_id) - deriv.variable = self._f[base + '/dependent variable'].value + deriv.variable = \ + self._f[base + '/dependent variable'].value.decode() if deriv.variable == 'density': deriv.material = self._f[base + '/material'].value elif deriv.variable == 'nuclide_density': deriv.material = self._f[base + '/material'].value - deriv.nuclide = self._f[base + '/nuclide'].value.decode() + deriv.nuclide = \ + self._f[base + '/nuclide'].value.decode() else: raise RuntimeError('Unrecognized tally differential ' 'variable') diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py index 932fd28a2..9fbad187d 100644 --- a/openmc/tally_derivative.py +++ b/openmc/tally_derivative.py @@ -1,10 +1,16 @@ from __future__ import division +import sys from numbers import Integral + from xml.etree import ElementTree as ET import openmc.checkvalue as cv + +if sys.version_info[0] >= 3: + basestring = str + # "Static" variable for auto-generated TallyDerivative IDs AUTO_TALLY_DERIV_ID = 10000 From 7764b842a03fe2628762156f106a2d3be322be67 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 31 Jan 2016 20:58:53 -0500 Subject: [PATCH 20/60] Fix OpenMP fails --- src/input_xml.F90 | 11 ++++++++++- src/state_point.F90 | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 0a90b5317..be6610224 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2349,6 +2349,11 @@ contains filename = trim(path_input) // "tallies.xml" inquire(FILE=filename, EXIST=file_exists) if (.not. file_exists) then + ! We need each thread to allocate tally_derivs to avoid segfaults +!$omp parallel + allocate(tally_derivs(0)) +!$omp end parallel + ! Since a tallies.xml file is optional, no error is issued here return end if @@ -2533,8 +2538,12 @@ contains ! Get pointer list to XML . call get_node_list(doc, "derivative", node_deriv_list) - ! Allocate TallyDerivative array. + ! Allocate TallyDerivative array on each thread. The attributes of the + ! TallyDerivatives will be set on the master thread and then 'copyin'ed + ! in simulate.F90 +!$omp parallel allocate(tally_derivs(get_list_size(node_deriv_list))) +!$omp end parallel ! Read derivative attributes. do i = 1, get_list_size(node_deriv_list) diff --git a/src/state_point.F90 b/src/state_point.F90 index 84a2a1893..7991719c8 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -195,7 +195,7 @@ contains call close_group(meshes_group) ! Write information for derivatives. - if (allocated(tally_derivs) .and. size(tally_derivs) > 0) then + if (size(tally_derivs) > 0) then derivs_group = create_group(tallies_group, "derivatives") do i = 1, size(tally_derivs) associate(deriv => tally_derivs(i)) From 017a8735c3bd33e236d2685e1b6048d92476aad9 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 1 Feb 2016 12:46:21 -0500 Subject: [PATCH 21/60] Update diff tally docs --- docs/source/usersguide/input.rst | 50 ++++++---- docs/source/usersguide/output/statepoint.rst | 16 ++++ openmc/statepoint.py | 2 +- src/constants.F90 | 2 +- src/input_xml.F90 | 2 +- src/relaxng/tallies.rnc | 22 +++-- src/relaxng/tallies.rng | 98 +++++++++++++------- src/state_point.F90 | 6 +- 8 files changed, 134 insertions(+), 64 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index f6ac53482..d1dac8caf 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1708,25 +1708,11 @@ The ```` element accepts the following sub-elements: *Default*: "all" :derivative: - Tally the first-order derivative of the quantity of interest with respect to - some material perturbation. Differential tallies are currently only - implemented for collision and analog estimators. + The id of a ``derivative`` element. This derivative will be applied to all + scores in the tally. Differential tallies are currently only implemented + for collision and analog estimators. - The ``derivative`` element has the following attributes/sub-elements: - - :variable: - The independent variable of the derivative. Accepted options are - "density" and "nuclide_density". A "density" derivative will give the - derivative with respect to the density of the material in [g / cm^3]. A - "nuclide_density" derivative will give the derivative with respect to - the density of a particular nuclide in units of [atom / b / cm]. - - :material: - The perturbed material. (Necessary for both "density" and - "nuclide_density") - - :nuclide: - The perturbed nuclide. (Necessary only for "nuclide_density") + *Default*: None ```` Element ------------------ @@ -1756,6 +1742,34 @@ attributes/sub-elements: One of ```` or ```` must be specified, but not both (even if they are consistent with one another). +```` Element +------------------------ + +OpenMC can take the first-order derivative of many tallies with respect to +material perturbations. It works by propagating a derivative through the +transport equation. Essentially, OpenMC keeps track of how each particle's +weight would change as materials are perturbed, and then accounts for that +weight change in the tallies. Note that this assumes material perturbations are +small enough not to change the distribution of fission sites. This element has +the following attributes/sub-elements: + + :id: + A unique integer that can be used to identify the derivative. + + :variable: + The independent variable of the derivative. Accepted options are + "density" and "nuclide_density". A "density" derivative will give the + derivative with respect to the density of the material in [g / cm^3]. A + "nuclide_density" derivative will give the derivative with respect to + the density of a particular nuclide in units of [atom / b / cm]. + + :material: + The perturbed material. (Necessary for both "density" and + "nuclide_density") + + :nuclide: + The perturbed nuclide. (Necessary only for "nuclide_density") + ```` Element ----------------------------- diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index 15bc79f73..786b7e8fb 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -156,6 +156,18 @@ if run_mode == 'k-eigenvalue': Width of each mesh cell in each dimension. +**/tallies/derivatives/derivative /independent variable** (*char[]*) + + Independent variable of tally derivative + +**/tallies/derivatives/derivative /material** (*int*) + + ID of the perturbed material + +**/tallies/derivatives/derivative /nuclide** (*char[]*) + + Alias of the perturbed nuclide + **/tallies/n_tallies** (*int*) Number of user-defined tallies. @@ -198,6 +210,10 @@ if run_mode == 'k-eigenvalue': Array of nuclides to tally. Note that if no nuclide is specified in the user input, a single 'total' nuclide appears here. +**/tallies/tally /derivative** (*int*) + + ID of the derivative applied to the tally. + **/tallies/tally /n_score_bins** (*int*) Number of scoring bins for a single nuclide. In general, this can be greater diff --git a/openmc/statepoint.py b/openmc/statepoint.py index ae86c2603..8cd11d735 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -468,7 +468,7 @@ class StatePoint(object): base = 'tallies/derivatives/derivative {:d}'.format(d_id) deriv = openmc.TallyDerivative(derivative_id=d_id) deriv.variable = \ - self._f[base + '/dependent variable'].value.decode() + self._f[base + '/independent variable'].value.decode() if deriv.variable == 'density': deriv.material = self._f[base + '/material'].value elif deriv.variable == 'nuclide_density': diff --git a/src/constants.F90 b/src/constants.F90 index 5d8ded5af..72df3c216 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -352,7 +352,7 @@ module constants K_TRACKLENGTH = 3, & LEAKAGE = 4 - ! Differential tally dependent variables + ! Differential tally independent variables integer, parameter :: & DIFF_DENSITY = 1, & DIFF_NUCLIDE_DENSITY = 2 diff --git a/src/input_xml.F90 b/src/input_xml.F90 index be6610224..f29661352 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2570,7 +2570,7 @@ contains // trim(to_str(deriv % id))) end do - ! Read the dependent variable name. + ! Read the independent variable name. temp_str = "" call get_node_value(node_deriv, "variable", temp_str) temp_str = to_lower(temp_str) diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc index c6f470175..4522adff5 100644 --- a/src/relaxng/tallies.rnc +++ b/src/relaxng/tallies.rnc @@ -15,6 +15,21 @@ element tallies { ) }* & + element derivative { + (element id { xsd:int } | attribute id { xsd:int }) & + (element material { xsd:int } | attribute material { xsd:int }) & + ( (element variable { ( "density") } + | attribute variable { ( "density" ) } ) | + ( + (element variable { ( "nuclide_density" ) } + | attribute variable { ( "nuclide_density" ) } ) + & + (element nuclide { xsd:string { maxLength = "12" } } + | attribute nuclide { xsd:string { maxLength = "12" } } ) + ) + ) + }* & + element tally { (element id { xsd:int } | attribute id { xsd:int }) & (element name { xsd:string { maxLength="52" } } | @@ -42,12 +57,7 @@ element tallies { (element threshold { xsd:double} | attribute threshold { xsd:double }) & (element scores { list { xsd:string { maxLength = "20" }+ } } | attribute scores { list { xsd:string { maxLength = "20"}+ } } )? }* & - element derivative { - (element variable { ( "density" | "nuclide_density") } | - attribute variable { ( "density" | "nuclide_density") } ) & - (element material { xsd:int } | attribute material { xsd:int }) & - (element nuclide { xsd:string } | attribute nuclide { xsd:string })? - }? + (element derivative { xsd:int } | attribute derivative { xsd:int } )? }* & element assume_separate { xsd:boolean }? diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng index 47fcb70f3..3f88b0760 100644 --- a/src/relaxng/tallies.rng +++ b/src/relaxng/tallies.rng @@ -89,6 +89,60 @@ + + + + + + + + + + + + + + + + + + + + + + + density + + + density + + + + + + nuclide_density + + + nuclide_density + + + + + + 12 + + + + + 12 + + + + + + + + @@ -254,6 +308,16 @@ + + + + + + + + + + @@ -262,39 +326,5 @@ - - - - - - density - nuclide_density - - - - - density - nuclide_density - - - - - - - - - - - - - - - - - - - - - diff --git a/src/state_point.F90 b/src/state_point.F90 index 7991719c8..b7a913dd0 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -203,17 +203,17 @@ contains // trim(to_str(deriv % id))) select case (deriv % variable) case (DIFF_DENSITY) - call write_dataset(deriv_group, "dependent variable", "density") + call write_dataset(deriv_group, "independent variable", "density") call write_dataset(deriv_group, "material", deriv % diff_material) case (DIFF_NUCLIDE_DENSITY) - call write_dataset(deriv_group, "dependent variable", & + call write_dataset(deriv_group, "independent variable", & "nuclide_density") call write_dataset(deriv_group, "material", deriv % diff_material) i_list = nuclides(deriv % diff_nuclide) % listing call write_dataset(deriv_group, "nuclide", & xs_listings(i_list) % alias) case default - call fatal_error("Dependent variable for derivative " & + call fatal_error("Independent variable for derivative " & // trim(to_str(deriv % id)) // " not defined in & &state_point.F90.") end select From 6b48b8cf2d7f9771eac8f63ac130f44a85c81d43 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 8 Feb 2016 22:00:51 -0500 Subject: [PATCH 22/60] Add finite-difference temperature derivative --- openmc/statepoint.py | 2 ++ openmc/tally_derivative.py | 11 +++++++---- src/constants.F90 | 3 ++- src/cross_section.F90 | 34 ++++++++++++++++++++++++++++++++++ src/input_xml.F90 | 5 ++++- src/state_point.F90 | 4 ++++ src/tally.F90 | 37 ++++++++++++++++++++++++++++++++++++- 7 files changed, 89 insertions(+), 7 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 8cd11d735..a1f19ecd8 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -475,6 +475,8 @@ class StatePoint(object): deriv.material = self._f[base + '/material'].value deriv.nuclide = \ self._f[base + '/nuclide'].value.decode() + elif deriv.variable == 'temperature': + deriv.material = self._f[base + '/material'].value else: raise RuntimeError('Unrecognized tally differential ' 'variable') diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py index 9fbad187d..0b16ad46f 100644 --- a/openmc/tally_derivative.py +++ b/openmc/tally_derivative.py @@ -33,7 +33,7 @@ class TallyDerivative(object): id : Integral Unique identifier for the tally derivative variable : str - Either 'density' or 'nuclide_density' + Accepted values are 'density', 'nuclide_density', and 'temperature' material : Integral The perutrubed material nuclide : str @@ -97,6 +97,9 @@ class TallyDerivative(object): self.material) string += '{0: <16}{1}{2}\n'.format('\tNuclide', '=\t', self.nuclide) + elif self.variable == 'temperature': + string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', + self.material) return string @@ -132,9 +135,9 @@ class TallyDerivative(object): def variable(self, var): if var is not None: cv.check_type('derivative variable', var, basestring) - if var not in ('density', 'nuclide_density'): - raise ValueError("A tally differential variable must be either " - "'density' or 'nuclide_density'") + if var not in ('density', 'nuclide_density', 'temperature'): + raise ValueError("A tally differential variable must be " + "'density', 'nuclide_density', or 'temperature'") self._variable = var @material.setter diff --git a/src/constants.F90 b/src/constants.F90 index 37f85b830..bdd8c041d 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -357,7 +357,8 @@ module constants ! Differential tally independent variables integer, parameter :: & DIFF_DENSITY = 1, & - DIFF_NUCLIDE_DENSITY = 2 + DIFF_NUCLIDE_DENSITY = 2, & + DIFF_TEMPERATURE = 3 ! ============================================================================ ! RANDOM NUMBER STREAM CONSTANTS diff --git a/src/cross_section.F90 b/src/cross_section.F90 index 033e80b17..c73969500 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -729,6 +729,40 @@ contains end if end subroutine +!=============================================================================== +! MULTIPOLE_DERIV_EVAL evaluates the windowed multipole equations for the +! derivative of cross sections in the resolved resonance regions with respect to +! temperature. +!=============================================================================== + + subroutine multipole_deriv_eval(multipole, Emev, sqrtkT, sigT, sigA, sigF) + type(MultipoleArray), intent(in) :: multipole ! The windowed multipole + ! object to process. + real(8), intent(in) :: Emev ! The energy at which to + ! evaluate the cross section + ! derivative in MeV + real(8), intent(in) :: sqrtkT ! The temperature in the form + ! sqrt(kT (in MeV)), at which + ! to evaluate the XS. + real(8), intent(out) :: sigT ! Total cross section + real(8), intent(out) :: sigA ! Absorption cross section + real(8), intent(out) :: sigF ! Fission cross section + real(8), parameter :: T_DIFF = 10.0_8 + real(8) :: kT, sqrtkT_hi, sqrtkT_lo + real(8) :: sigT_hi, sigT_lo, sigA_hi, sigA_lo, sigF_hi, sigF_lo + + kT = sqrtkT**2 + sqrtkT_hi = sqrt(kT + K_BOLTZMANN*T_DIFF/2.0) + sqrtkT_lo = sqrt(kT - K_BOLTZMANN*T_DIFF/2.0) + + call multipole_eval(multipole, Emev, sqrtkT_hi, sigT_hi, sigA_hi, sigF_hi) + call multipole_eval(multipole, Emev, sqrtkT_lo, sigT_lo, sigA_lo, sigF_lo) + + sigT = (sigT_hi - sigT_lo) / T_DIFF + sigA = (sigA_hi - sigA_lo) / T_DIFF + sigF = (sigF_hi - sigF_lo) / T_DIFF + end subroutine multipole_deriv_eval + !=============================================================================== ! FILL_FACTORS calculates the value of phi, the hardsphere phase shift factor, ! and sigT_factor, a factor inside of the sigT equation not present in the diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 2d29734b7..6939923fb 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -1901,7 +1901,6 @@ contains type(Node), pointer :: doc => null() type(Node), pointer :: node_mat => null() type(Node), pointer :: node_dens => null() - type(Node), pointer :: node_temp => null() type(Node), pointer :: node_nuc => null() type(Node), pointer :: node_ele => null() type(Node), pointer :: node_sab => null() @@ -2642,6 +2641,10 @@ contains deallocate(pair_list) deriv % diff_nuclide = nuclide_dict % get_key(word) + + case("temperature") + deriv % variable = DIFF_TEMPERATURE + call get_node_value(node_deriv, "material", deriv % diff_material) end select end associate end do diff --git a/src/state_point.F90 b/src/state_point.F90 index b7a913dd0..ee7873034 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -212,6 +212,10 @@ contains i_list = nuclides(deriv % diff_nuclide) % listing call write_dataset(deriv_group, "nuclide", & xs_listings(i_list) % alias) + case (DIFF_TEMPERATURE) + call write_dataset(deriv_group, "independent variable", & + "temperature") + call write_dataset(deriv_group, "material", deriv % diff_material) case default call fatal_error("Independent variable for derivative " & // trim(to_str(deriv % id)) // " not defined in & diff --git a/src/tally.F90 b/src/tally.F90 index 4dea2e249..a74e8c52e 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2,6 +2,7 @@ module tally use ace_header, only: Reaction use constants + use cross_section, only: multipole_deriv_eval use error, only: fatal_error use geometry_header use global @@ -2409,6 +2410,21 @@ contains call fatal_error("Differential tallies are only implemented for & &analog and collision estimators.") end select + + case (DIFF_TEMPERATURE) + select case (t % estimator) + + case (ESTIMATOR_ANALOG) + + case (ESTIMATOR_COLLISION) + + select case (score_bin) + + case (SCORE_FLUX) + score = score * deriv % flux_deriv + + end select + end select end select end associate end subroutine apply_derivative_to_score @@ -2422,7 +2438,8 @@ contains type(particle), intent(in) :: p real(8), intent(in) :: distance ! Neutron flight distance - integer :: i + integer :: i, l + real(8) :: dsigT, dsigA, dsigF ! A void material cannot be perturbed so it will not affect flux derivatives if (p % material == MATERIAL_VOID) return @@ -2452,6 +2469,24 @@ contains - distance * micro_xs(deriv % diff_nuclide) % total end if end associate + + case (DIFF_TEMPERATURE) + associate (mat => materials(p % material)) + if (mat % id == deriv % diff_material) then + do l=1, mat % n_nuclides + associate (nuc => nuclides(mat % nuclide(l))) + if (nuc % mp_present .and. & + p % E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % E, & + p % sqrtkT, dsigT, dsigA, dsigF) + deriv % flux_deriv = deriv % flux_deriv & + - distance * dsigT * mat % atom_density(l) + end if + end associate + end do + end if + end associate end select end associate end do From 812aa6ff10a0b807b2c5ea14c10d2f5fe6d1da64 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 10 Feb 2016 15:13:01 -0500 Subject: [PATCH 23/60] Add collison temperature derivative --- src/tally.F90 | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/tally.F90 b/src/tally.F90 index a74e8c52e..219027ff2 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2500,7 +2500,8 @@ contains subroutine score_collision_derivative(p) type(particle), intent(in) :: p - integer :: i, j + integer :: i, j, l + real(8) :: dsigT, dsigA, dsigF ! A void material cannot be perturbed so it will not affect flux derivatives if (p % material == MATERIAL_VOID) return @@ -2540,6 +2541,35 @@ contains + ONE / mat % atom_density(j) end if end associate + + case (DIFF_TEMPERATURE) + associate (mat => materials(p % material)) + if (mat % id == deriv % diff_material) then + do l=1, mat % n_nuclides + associate (nuc => nuclides(mat % nuclide(l))) + if (mat % nuclide(l) == p % event_nuclide .and. & + nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + ! phi = Sigma_MT + ! (1 / phi) * (d_phi / d_T) = (d_Sigma_MT / d_T) / Sigma_MT + ! (1 / phi) * (d_phi / d_T) = (d_sigma_MT / d_T) / sigma_MT + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + select case(p % event) + case (EVENT_SCATTER) + deriv % flux_deriv = deriv % flux_deriv + (dsigT - dsigA)& + / (micro_xs(mat % nuclide(l)) % total & + - micro_xs(mat % nuclide(l)) % absorption) + case (EVENT_ABSORB) + deriv % flux_deriv = deriv % flux_deriv & + + dsigA / micro_xs(mat % nuclide(l)) % absorption + end select + end if + end associate + end do + end if + end associate end select end associate end do From d7e784a080fa84f080598dd92b2b44dafd8957c9 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 11 Feb 2016 17:05:42 -0500 Subject: [PATCH 24/60] Add more temperature derivative scores --- src/tally.F90 | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/src/tally.F90 b/src/tally.F90 index 219027ff2..12d77356b 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2254,6 +2254,7 @@ contains integer :: l ! loop index for nuclides in material logical :: scoring_diff_nuclide + real(8) :: dsigT, dsigA, dsigF, cum_dsig associate(deriv => tally_derivs(t % deriv)) select case (deriv % variable) @@ -2423,7 +2424,170 @@ contains case (SCORE_FLUX) score = score * deriv % flux_deriv + case (SCORE_TOTAL) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material .and. & + material_xs % total > ZERO) then + cum_dsig = ZERO + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + associate (nuc => nuclides(mat % nuclide(l))) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + micro_xs(mat % nuclide(l)) % total > ZERO) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + cum_dsig = cum_dsig + dsigT * mat % atom_density(l) + end if + end associate + end do + end associate + score = score * (deriv % flux_deriv & + + cum_dsig / material_xs % total) + else if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % total > ZERO) then + dsigT = ZERO + associate (nuc => nuclides(i_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigT * atom_density / material_xs % total) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_ABSORPTION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material .and. & + material_xs % absorption > ZERO) then + cum_dsig = ZERO + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + associate (nuc => nuclides(mat % nuclide(l))) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + micro_xs(mat % nuclide(l)) % absorption > ZERO) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + cum_dsig = cum_dsig + dsigA * mat % atom_density(l) + end if + end associate + end do + end associate + score = score * (deriv % flux_deriv & + + cum_dsig / material_xs % absorption) + else if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % absorption > ZERO) then + dsigA = ZERO + associate (nuc => nuclides(i_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigA * atom_density / material_xs % absorption) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_FISSION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material .and. & + material_xs % fission > ZERO) then + cum_dsig = ZERO + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + associate (nuc => nuclides(mat % nuclide(l))) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + micro_xs(mat % nuclide(l)) % fission > ZERO) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + cum_dsig = cum_dsig + dsigF * mat % atom_density(l) + end if + end associate + end do + end associate + score = score * (deriv % flux_deriv & + + cum_dsig / material_xs % fission) + else if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % fission > ZERO) then + dsigF = ZERO + associate (nuc => nuclides(i_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigF * atom_density / material_xs % fission) + else + score = score * deriv % flux_deriv + end if + + case (SCORE_NU_FISSION) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material .and. & + material_xs % nu_fission > ZERO) then + cum_dsig = ZERO + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + associate (nuc => nuclides(mat % nuclide(l))) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + micro_xs(mat % nuclide(l)) % nu_fission > ZERO) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + cum_dsig = cum_dsig + dsigF * mat % atom_density(l) & + * micro_xs(mat % nuclide(l)) % nu_fission & + / micro_xs(mat % nuclide(l)) % fission + end if + end associate + end do + end associate + score = score * (deriv % flux_deriv & + + cum_dsig / material_xs % nu_fission) + else if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % nu_fission > ZERO) then + dsigF = ZERO + associate (nuc => nuclides(i_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigF * atom_density / material_xs % nu_fission & + * micro_xs(i_nuclide) % nu_fission & + / micro_xs(i_nuclide) % fission) + else + score = score * deriv % flux_deriv + end if + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) end select + + case default + call fatal_error("Differential tallies are only implemented for & + &analog and collision estimators.") end select end select end associate From 0bd2dea0f58819732cf3dc5cb7e8bbf1b5bb963e Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 22 Feb 2016 22:11:50 -0500 Subject: [PATCH 25/60] Add some analog tallies to temperature derivative --- CMakeLists.txt | 2 +- src/tally.F90 | 104 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05f03626e..16cf914e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU) endif() if(optimize) list(APPEND f90flags -O3 -flto -fuse-linker-plugin) - list(APPEND cflags -O3 -flto -fuse-linker-plugin) + list(APPEND cflags -O3) endif() if(openmp) list(APPEND f90flags -fopenmp) diff --git a/src/tally.F90 b/src/tally.F90 index 12d77356b..bdd7f84d0 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2417,6 +2417,110 @@ contains case (ESTIMATOR_ANALOG) + select case (score_bin) + + case (SCORE_FLUX) + score = score * deriv % flux_deriv + + case (SCORE_TOTAL) + if (materials(p % material) % id == deriv % diff_material .and. & + micro_xs(p % event_nuclide) % total > ZERO) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == p % event_nuclide) exit + end do + dsigT = ZERO + associate (nuc => nuclides(p % event_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigT * mat % atom_density(l) / material_xs % total) + end associate + else + score = score * deriv % flux_deriv + end if + + case (SCORE_ABSORPTION) + if (materials(p % material) % id == deriv % diff_material .and. & + micro_xs(p % event_nuclide) % absorption > ZERO) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == p % event_nuclide) exit + end do + dsigA = ZERO + associate (nuc => nuclides(p % event_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigA * mat % atom_density(l) / material_xs % absorption) + end associate + else + score = score * deriv % flux_deriv + end if + + case (SCORE_FISSION) + if (materials(p % material) % id == deriv % diff_material .and. & + micro_xs(p % event_nuclide) % fission > ZERO) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == p % event_nuclide) exit + end do + dsigF = ZERO + associate (nuc => nuclides(p % event_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigF * mat % atom_density(l) / material_xs % fission) + end associate + else + score = score * deriv % flux_deriv + end if + + case (SCORE_NU_FISSION) + if (materials(p % material) % id == deriv % diff_material .and. & + micro_xs(p % event_nuclide) % nu_fission > ZERO) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == p % event_nuclide) exit + end do + dsigF = ZERO + associate (nuc => nuclides(p % event_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv & + + dsigF * mat % atom_density(l) / material_xs % fission & + * micro_xs(p % event_nuclide) % nu_fission & + / micro_xs(p % event_nuclide) % fission) + end associate + else + score = score * deriv % flux_deriv + end if + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + end select + case (ESTIMATOR_COLLISION) select case (score_bin) From 8727a7f1b83de1cef559fda161ad41412cee87c5 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 24 Feb 2016 22:34:56 -0500 Subject: [PATCH 26/60] Use analytical multipole derivative evaluation --- src/cross_section.F90 | 104 +++++++++++++++++++++++++++++++++++++++++- src/math.F90 | 17 ++++++- 2 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/cross_section.F90 b/src/cross_section.F90 index c73969500..0a61373e2 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -8,7 +8,7 @@ module cross_section use global use list_header, only: ListElemInt use material_header, only: Material - use math, only: w, broaden_n_polynomials + use math, only: w, w_derivative, broaden_n_polynomials use multipole_header, only: FORM_RM, FORM_MLBW, MP_EA, RM_RT, RM_RA, RM_RF, & MLBW_RT, MLBW_RX, MLBW_RA, MLBW_RF, FIT_T, FIT_A, FIT_F, & MultipoleArray, max_poly, max_L, max_poles @@ -735,7 +735,8 @@ contains ! temperature. !=============================================================================== - subroutine multipole_deriv_eval(multipole, Emev, sqrtkT, sigT, sigA, sigF) + subroutine multipole_deriv_eval_finite_difference(multipole, Emev, sqrtkT, & + sigT, sigA, sigF) type(MultipoleArray), intent(in) :: multipole ! The windowed multipole ! object to process. real(8), intent(in) :: Emev ! The energy at which to @@ -761,6 +762,105 @@ contains sigT = (sigT_hi - sigT_lo) / T_DIFF sigA = (sigA_hi - sigA_lo) / T_DIFF sigF = (sigF_hi - sigF_lo) / T_DIFF + end subroutine multipole_deriv_eval_finite_difference + + subroutine multipole_deriv_eval(multipole, Emev, sqrtkT_, sigT, sigA, sigF) + type(MultipoleArray), intent(in) :: multipole ! The windowed multipole + ! object to process. + real(8), intent(in) :: Emev ! The energy at which to + ! evaluate the cross section + ! in MeV + real(8), intent(in) :: sqrtkT_ ! The temperature in the form + ! sqrt(kT (in MeV)), at which + ! to evaluate the XS. + real(8), intent(out) :: sigT ! Total cross section + real(8), intent(out) :: sigA ! Absorption cross section + real(8), intent(out) :: sigF ! Fission cross section + complex(8) :: psi_ki ! The value of the psi-ki function for the asymptotic + ! form + complex(8) :: c_temp ! complex temporary variable + complex(8) :: w_val ! The faddeeva function evaluated at Z + complex(8) :: Z ! sqrt(atomic weight ratio / kT) * (sqrt(E) - pole) + real(8) :: sqrtE ! sqrt(E), eV + real(8) :: invE ! 1/E, eV + real(8) :: dopp ! sqrt(atomic weight ratio / kT) + real(8) :: dopp_ecoef ! sqrt(atomic weight ratio * pi / kT) / E + real(8) :: temp ! real temporary value + real(8) :: E ! energy, eV + real(8) :: sqrtkT ! sqrt(kT (in eV)) + integer :: iP ! index of pole + integer :: iC ! index of curvefit + integer :: iW ! index of window + integer :: startw ! window start pointer (for poles) + integer :: startw_1 ! window start pointer - 1 + integer :: startw_endw ! window start pointer - window end pointer + integer :: endw ! window end pointer + real(8) :: T + + ! Convert to eV + E = Emev * 1.0e6_8 + sqrtkT = sqrtkT_ * 1.0e3_8 + + T = sqrtkT_**2 / K_BOLTZMANN + + if (sqrtkT == ZERO) call fatal_error("Windowed multipole temperature & + &derivatives are not implemented for 0 Kelvin cross sections.") + + sqrtE = sqrt(E) + invE = ONE/E + + if(.not. mp_already_alloc) then + call multipole_eval_allocate() + end if + + ! Locate us + iW = floor((sqrtE - sqrt(multipole % start_E))/multipole % spacing + ONE) + + startw = multipole % w_start(iW) + startw_1 = startw - 1 ! This is an index shift parameter. + endw = multipole % w_end(iW) + startw_endw = endw - startw + 1 + + ! Fill in factors + if (startw <= endw) then + call fill_factors(multipole, sqrtE, sigT_factor, twophi, multipole % num_l) + end if + + ! dopp_ecoef is inverse of dopp, divided by E, multiplied by sqrt(pi). + dopp = multipole % sqrtAWR / sqrtKT + dopp_ecoef = dopp * invE * SQRT_PI + + sigT = ZERO + sigA = ZERO + sigF = ZERO + + ! TODO Polynomials + + if (endw >= startw) then + do iP = startw, endw + Z = (sqrtE - multipole % data(MP_EA, iP)) * dopp + w_val = -invE * SQRT_PI * HALF * w_derivative(Z, 2) + + if (multipole % formalism == FORM_MLBW) then + sigT = sigT + real((multipole % data(MLBW_RT, iP) * & + sigT_factor(multipole%l_value(iP)) + & + multipole % data(MLBW_RX, iP)) * w_val) + sigA = sigA + real(multipole % data(MLBW_RA, iP) * w_val) + sigF = sigF + real(multipole % data(MLBW_RF, iP) * w_val) + else if (multipole % formalism == FORM_RM) then + sigT = sigT + real(multipole % data(RM_RT, iP) * w_val * & + sigT_factor(multipole % l_value(iP))) + sigA = sigA + real(multipole % data(RM_RA, iP) * w_val) + sigF = sigF + real(multipole % data(RM_RF, iP) * w_val) + end if + end do + sigT = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN*1.0e6_8) * T**(-1.5)& + * sigT + sigA = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN*1.0e6_8) * T**(-1.5)& + * sigA + sigF = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN*1.0e6_8) * T**(-1.5)& + * sigF + end if end subroutine multipole_deriv_eval !=============================================================================== diff --git a/src/math.F90 b/src/math.F90 index ae3ed1a71..f3247fb4a 100644 --- a/src/math.F90 +++ b/src/math.F90 @@ -703,9 +703,24 @@ contains else wv = -conjg(faddeeva_w(conjg(z), relerr)) end if - end function w + recursive function w_derivative(z, order) result(wv) + complex(C_DOUBLE_COMPLEX), intent(in) :: z ! The point to evaluate Z at + integer, intent(in) :: order + complex(8) :: wv ! The resulting w(z) value + + select case(order) + case (0) + wv = w(z) + case (1) + wv = -TWO * z * w(z) + TWO * ONEI / SQRT_PI + case default + wv = -TWO * z * w_derivative(z, order-1) & + - TWO * (order-1) * w_derivative(z, order-2) + end select + end function w_derivative + !=============================================================================== ! BROADEN_N_POLYNOMIALS doppler broadens polynomials of the form ! a/En + b/sqrt(En) + c + d sqrt(En) ... From 21fa844a8ada444c0f081dfc882f1ea7c9e25063 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 3 Mar 2016 11:55:04 -0500 Subject: [PATCH 27/60] Correct another divide by zero error --- src/tally.F90 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index bdd7f84d0..166059d09 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2352,7 +2352,8 @@ contains case (SCORE_TOTAL) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % total /= ZERO) then score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % total & / material_xs % total) @@ -2365,7 +2366,8 @@ contains case (SCORE_ABSORPTION) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % absorption /= ZERO) then score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % absorption & / material_xs % absorption ) @@ -2378,7 +2380,8 @@ contains case (SCORE_FISSION) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % fission /= ZERO) then score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % fission & / material_xs % fission) @@ -2391,7 +2394,9 @@ contains case (SCORE_NU_FISSION) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % nu_fission /= ZERO) then + write(*, *) micro_xs(deriv % diff_nuclide) % nu_fission score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % nu_fission & / material_xs % nu_fission) From d3750c185f03e5d1cf457ec3678e60a0e8c517d5 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 3 Mar 2016 11:55:04 -0500 Subject: [PATCH 28/60] Correct another divide by zero error --- src/tally.F90 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 4dea2e249..019d2d69e 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2350,7 +2350,8 @@ contains case (SCORE_TOTAL) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % total /= ZERO) then score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % total & / material_xs % total) @@ -2363,7 +2364,8 @@ contains case (SCORE_ABSORPTION) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % absorption /= ZERO) then score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % absorption & / material_xs % absorption ) @@ -2376,7 +2378,8 @@ contains case (SCORE_FISSION) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % fission /= ZERO) then score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % fission & / material_xs % fission) @@ -2389,7 +2392,9 @@ contains case (SCORE_NU_FISSION) if (i_nuclide == -1 .and. & - materials(p % material) % id == deriv % diff_material) then + materials(p % material) % id == deriv % diff_material .and. & + material_xs % nu_fission /= ZERO) then + write(*, *) micro_xs(deriv % diff_nuclide) % nu_fission score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % nu_fission & / material_xs % nu_fission) From 4ec05c643fef40fd66b1681fe36771504eae8c85 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 18 Apr 2016 14:41:22 -0400 Subject: [PATCH 29/60] Add collision-estimated scattering derivatives --- src/tally.F90 | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/tally.F90 b/src/tally.F90 index 9f2bdc4a3..0a6603f39 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -3068,6 +3068,16 @@ contains score = score * deriv % flux_deriv end if + case (SCORE_SCATTER) + if (materials(p % material) % id == deriv % diff_material & + .and. material_xs % total - material_xs % absorption /= ZERO) & + then + score = score * (deriv % flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * deriv % flux_deriv + end if + case (SCORE_ABSORPTION) if (materials(p % material) % id == deriv % diff_material & .and. material_xs % absorption /= ZERO) then @@ -3146,6 +3156,22 @@ contains score = score * deriv % flux_deriv end if + case (SCORE_SCATTER) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material .and. & + material_xs % total - material_xs % absorption /= ZERO) then + score = score * (deriv % flux_deriv & + + (micro_xs(deriv % diff_nuclide) % total & + - micro_xs(deriv % diff_nuclide) % absorption) & + / (material_xs % total - material_xs % absorption)) + else if (scoring_diff_nuclide .and. & + (micro_xs(deriv % diff_nuclide) % total & + - micro_xs(deriv % diff_nuclide) % absorption) /= ZERO) then + score = score * (deriv % flux_deriv + ONE / atom_density) + else + score = score * deriv % flux_deriv + end if + case (SCORE_ABSORPTION) if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & @@ -3178,7 +3204,6 @@ contains if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & material_xs % nu_fission /= ZERO) then - write(*, *) micro_xs(deriv % diff_nuclide) % nu_fission score = score * (deriv % flux_deriv & + micro_xs(deriv % diff_nuclide) % nu_fission & / material_xs % nu_fission) From 174ff92b33e01d7274ab7c183814de09266f4ace Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 18 Apr 2016 15:46:02 -0400 Subject: [PATCH 30/60] Add collision-est. scattering temperature deriv --- src/tally.F90 | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/tally.F90 b/src/tally.F90 index 0a5b7b3b4..360bb35bc 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -3258,6 +3258,32 @@ contains score = score * deriv % flux_deriv end if + case (SCORE_SCATTER) + if (materials(p % material) % id == deriv % diff_material .and. & + (micro_xs(p % event_nuclide) % total & + - micro_xs(p % event_nuclide) % absorption) > ZERO) then + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == p % event_nuclide) exit + end do + dsigT = ZERO + dsigA = ZERO + associate (nuc => nuclides(p % event_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv + (dsigT - dsigA) & + * mat % atom_density(l) / & + (material_xs % total - material_xs % absorption)) + end associate + else + score = score * deriv % flux_deriv + end if + case (SCORE_ABSORPTION) if (materials(p % material) % id == deriv % diff_material .and. & micro_xs(p % event_nuclide) % absorption > ZERO) then @@ -3379,6 +3405,48 @@ contains score = score * deriv % flux_deriv end if + case (SCORE_SCATTER) + if (i_nuclide == -1 .and. & + materials(p % material) % id == deriv % diff_material .and. & + (material_xs % total - material_xs % absorption) > ZERO) then + cum_dsig = ZERO + associate(mat => materials(p % material)) + do l = 1, mat % n_nuclides + associate (nuc => nuclides(mat % nuclide(l))) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + (micro_xs(mat % nuclide(l)) % total & + - micro_xs(mat % nuclide(l)) % absorption) > ZERO) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + cum_dsig = cum_dsig & + + (dsigT - dsigA) * mat % atom_density(l) + end if + end associate + end do + end associate + score = score * (deriv % flux_deriv + cum_dsig & + / (material_xs % total - material_xs % absorption)) + else if ( materials(p % material) % id == deriv % diff_material & + .and. (material_xs % total - material_xs % absorption) > ZERO)& + then + dsigT = ZERO + dsigA = ZERO + associate (nuc => nuclides(i_nuclide)) + if (nuc % mp_present .and. & + p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & + p % last_E <= nuc % multipole % end_E/1.0e6_8) then + call multipole_deriv_eval(nuc % multipole, p % last_E, & + p % sqrtkT, dsigT, dsigA, dsigF) + end if + end associate + score = score * (deriv % flux_deriv + (dsigT - dsigA) & + / (material_xs % total - material_xs % absorption)) + else + score = score * deriv % flux_deriv + end if + case (SCORE_ABSORPTION) if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & From 92b58c2b5663c408a345bac337d0d030dac8a5b5 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 18 Apr 2016 19:40:23 -0400 Subject: [PATCH 31/60] Avoid divide-by-zero errors with score==ZERO check --- src/tally.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tally.F90 b/src/tally.F90 index 360bb35bc..43e10986e 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -3039,6 +3039,8 @@ contains logical :: scoring_diff_nuclide real(8) :: dsigT, dsigA, dsigF, cum_dsig + if (score == ZERO) return + associate(deriv => tally_derivs(t % deriv)) select case (deriv % variable) @@ -3347,7 +3349,7 @@ contains end if end associate score = score * (deriv % flux_deriv & - + dsigF * mat % atom_density(l) / material_xs % fission & + + dsigF * mat % atom_density(l) / material_xs % nu_fission& * micro_xs(p % event_nuclide) % nu_fission & / micro_xs(p % event_nuclide) % fission) end associate From 9716920de11c839a5a0e5fa4d4615e4f962b8234 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 22 May 2016 20:57:42 -0400 Subject: [PATCH 32/60] Fix temperature derivative denominator --- src/tally.F90 | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 3884d592a..689a3fdb5 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -3458,7 +3458,7 @@ contains end if end associate score = score * (deriv % flux_deriv & - + dsigT * atom_density / material_xs % total) + + dsigT / micro_xs(i_nuclide) % total) else score = score * deriv % flux_deriv end if @@ -3500,7 +3500,8 @@ contains end if end associate score = score * (deriv % flux_deriv + (dsigT - dsigA) & - / (material_xs % total - material_xs % absorption)) + / (micro_xs(i_nuclide) % total & + - micro_xs(i_nuclide) % absorption)) else score = score * deriv % flux_deriv end if @@ -3538,7 +3539,7 @@ contains end if end associate score = score * (deriv % flux_deriv & - + dsigA * atom_density / material_xs % absorption) + + dsigA / micro_xs(i_nuclide) % absorption) else score = score * deriv % flux_deriv end if @@ -3576,7 +3577,7 @@ contains end if end associate score = score * (deriv % flux_deriv & - + dsigF * atom_density / material_xs % fission) + + dsigF / micro_xs(i_nuclide) % fission) else score = score * deriv % flux_deriv end if @@ -3616,9 +3617,7 @@ contains end if end associate score = score * (deriv % flux_deriv & - + dsigF * atom_density / material_xs % nu_fission & - * micro_xs(i_nuclide) % nu_fission & - / micro_xs(i_nuclide) % fission) + + dsigF / micro_xs(i_nuclide) % fission) else score = score * deriv % flux_deriv end if From c27c9bad6c761bc3fb959e2955de66e78f56a8c8 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 25 May 2016 18:41:09 -0400 Subject: [PATCH 33/60] Use simpler scheme for removing non-WMP XS --- src/multipole.F90 | 103 ++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 73 deletions(-) diff --git a/src/multipole.F90 b/src/multipole.F90 index 59c7fed69..0ded8846a 100644 --- a/src/multipole.F90 +++ b/src/multipole.F90 @@ -27,11 +27,9 @@ contains integer(HID_T) :: file_id integer(HID_T) :: group_id integer :: is_fissionable - real(8) :: insert_pts(4) ! New points in the energy grid integer :: cut1, cut2 ! Old indices just outside MP region integer :: new_n_grid ! Number of points in new E grid real(8), allocatable :: new_energy(:) ! New energy grid - real(8) :: f1, f2 ! Interpolation near cut1 & cut2 real(8), allocatable :: new_xs(:) ! New cross sections integer :: i integer :: IE ! Reaction threshold @@ -90,84 +88,49 @@ contains ! interpolated to these points. The other two points are used to zero the ! cross sections inside the multipole region. - ! Define the four new inserted points. - insert_pts(:) = [multipole % start_E / 1e6_8, & - multipole % start_E / 1e6_8 + 1e-12_8, & - multipole % end_E / 1e6_8 - 1e-12_8, & - multipole % end_E / 1e6_8] - ! Find the points just outside the multipole region. - cut1 = binary_search(nuc % energy, nuc % n_grid, insert_pts(1)) - cut2 = binary_search(nuc % energy, nuc % n_grid, insert_pts(4)) + 1 - if (nuc % energy(cut1) == insert_pts(1)) cut1 = cut1 - 1 - if (nuc % energy(cut2) == insert_pts(4)) cut2 = cut2 + 1 + cut1 = binary_search(nuc % energy, nuc % n_grid, insert_pts(1)) + 2 + cut2 = binary_search(nuc % energy, nuc % n_grid, insert_pts(4)) - 1 ! Generate the new energy grid. - new_n_grid = nuc % n_grid - (cut2 - cut1 - 1) + 4 + new_n_grid = nuc % n_grid - (cut2 - cut1 - 1) allocate(new_energy(new_n_grid)) new_energy(1:cut1) = nuc % energy(1:cut1) - new_energy(cut1+1:cut1+4) = insert_pts(:) - new_energy(cut1+5:new_n_grid) = nuc % energy(cut2:nuc % n_grid) - - ! Compute interpolation factors for the new energy points. - f1 = (insert_pts(1) - nuc % energy(cut1)) & - / (nuc % energy(cut1+1) - nuc % energy(cut1)) - f2 = (insert_pts(4) - nuc % energy(cut2-1)) & - / (nuc % energy(cut2) - nuc % energy(cut2-1)) + new_energy(cut1+1:new_n_grid) = nuc % energy(cut2:nuc % n_grid) ! Adjust the total cross section. allocate(new_xs(new_n_grid)) - new_xs(1:cut1) = nuc % total(1:cut1) - new_xs(cut1+1) = (ONE - f1) * nuc % total(cut1) & - + f1 * nuc % total(cut1+1) - new_xs(cut1+2:cut1+3) = ZERO - new_xs(cut1+4) = (ONE - f2) * nuc % total(cut2-1) & - + f2 * nuc % total(cut2) - new_xs(cut1+5:new_n_grid) = nuc % total(cut2:nuc % n_grid) + new_xs(1:cut1-1) = nuc % total(1:cut1-1) + new_xs(cut1:cut1+1) = ZERO + new_xs(cut1+2:new_n_grid) = nuc % total(cut2+1:nuc % n_grid) call move_alloc(new_xs, nuc % total) ! Adjust the elastic cross section. allocate(new_xs(new_n_grid)) - new_xs(1:cut1) = nuc % elastic(1:cut1) - new_xs(cut1+1) = (ONE - f1) * nuc % elastic(cut1) & - + f1 * nuc % elastic(cut1+1) - new_xs(cut1+2:cut1+3) = ZERO - new_xs(cut1+4) = (ONE - f2) * nuc % elastic(cut2-1) & - + f2 * nuc % elastic(cut2) - new_xs(cut1+5:new_n_grid) = nuc % elastic(cut2:nuc % n_grid) + new_xs(1:cut1-1) = nuc % elastic(1:cut1-1) + new_xs(cut1:cut1+1) = ZERO + new_xs(cut1+2:new_n_grid) = nuc % elastic(cut2+1:nuc % n_grid) call move_alloc(new_xs, nuc % elastic) ! Adjust the fission cross section. allocate(new_xs(new_n_grid)) - new_xs(1:cut1) = nuc % fission(1:cut1) - new_xs(cut1+1) = (ONE - f1) * nuc % fission(cut1) & - + f1 * nuc % fission(cut1+1) - new_xs(cut1+2:cut1+3) = ZERO - new_xs(cut1+4) = (ONE - f2) * nuc % fission(cut2-1) & - + f2 * nuc % fission(cut2) - new_xs(cut1+5:new_n_grid) = nuc % fission(cut2:nuc % n_grid) + new_xs(1:cut1-1) = nuc % fission(1:cut1-1) + new_xs(cut1:cut1+1) = ZERO + new_xs(cut1+2:new_n_grid) = nuc % fission(cut2+1:nuc % n_grid) call move_alloc(new_xs, nuc % fission) ! Adjust the nu-fission cross section. allocate(new_xs(new_n_grid)) - new_xs(1:cut1) = nuc % nu_fission(1:cut1) - new_xs(cut1+1) = (ONE - f1) * nuc % nu_fission(cut1) & - + f1 * nuc % nu_fission(cut1+1) - new_xs(cut1+2:cut1+3) = ZERO - new_xs(cut1+4) = (ONE - f2) * nuc % nu_fission(cut2-1) & - + f2 * nuc % nu_fission(cut2) - new_xs(cut1+5:new_n_grid) = nuc % nu_fission(cut2:nuc % n_grid) + new_xs(1:cut1-1) = nuc % nu_fission(1:cut1-1) + new_xs(cut1:cut1+1) = ZERO + new_xs(cut1+2:new_n_grid) = nuc % nu_fission(cut2+1:nuc % n_grid) call move_alloc(new_xs, nuc % nu_fission) ! Adjust the absorption cross section. allocate(new_xs(new_n_grid)) - new_xs(1:cut1) = nuc % absorption(1:cut1) - new_xs(cut1+1) = (ONE - f1) * nuc % absorption(cut1) & - + f1 * nuc % absorption(cut1+1) - new_xs(cut1+2:cut1+3) = ZERO - new_xs(cut1+4) = (ONE - f2) * nuc % absorption(cut2-1) & - + f2 * nuc % absorption(cut2) - new_xs(cut1+5:new_n_grid) = nuc % absorption(cut2:nuc % n_grid) + new_xs(1:cut1-1) = nuc % absorption(1:cut1-1) + new_xs(cut1:cut1+1) = ZERO + new_xs(cut1+2:new_n_grid) = nuc % absorption(cut2+1:nuc % n_grid) call move_alloc(new_xs, nuc % absorption) ! Adjust other cross sections. @@ -178,30 +141,24 @@ contains if (rxn % threshold >= cut2) then ! The threshold is above the multipole range. All we need to do ! is adjust the threshold index to match the new grid. - rxn % threshold = rxn % threshold - (cut2 - cut1 - 1) + 4 + rxn % threshold = rxn % threshold - (cut2 - cut1 - 1) else if (rxn % threshold <= cut1) then ! The threhold is below the multipole range. Remove the multipole ! region just like we did with the other reactions. - ! The new grid removed (cut2 - cut1 - 1) points and added 4. - allocate(new_xs(size(rxn % sigma) - (cut2 - cut1 - 1) + 4)) - new_xs(1:cut1-IE+1) = rxn % sigma(1:cut1-IE+1) - new_xs(cut1-IE+2) = (ONE - f1) * rxn % sigma(cut1-IE+1) & - + f1 * rxn % sigma(cut1-IE+2) - new_xs(cut1-IE+3:cut1-IE+4) = ZERO - new_xs(cut1-IE+5) = (ONE - f2) * rxn % sigma(cut2-IE) & - + f2 * rxn % sigma(cut2-IE+1) - new_xs(cut1-IE+6:size(new_xs)) = & - rxn % sigma(cut2-IE+1:size(rxn % sigma)) + ! The new grid removed (cut2 - cut1 - 1) points. + allocate(new_xs(size(rxn % sigma) - (cut2 - cut1 - 1))) + new_xs(1:cut1-IE) = rxn % sigma(1:cut1-IE) + new_xs(cut1-IE+1:cut1-IE+2) = ZERO + new_xs(cut1-IE+3:size(new_xs)) = & + rxn % sigma(cut2-IE+2:size(rxn % sigma)) call move_alloc(new_xs, rxn % sigma) else ! The threshold lies within the multipole range. Remove the first - ! cut2-IE points and add an interpolated point - allocate(new_xs(size(rxn % sigma) - (cut2-IE) + 1)) - new_xs(1) = (ONE - f2) * rxn % sigma(cut2-IE) & - + f2 * rxn % sigma(cut2-IE+1) - new_xs(2:size(new_xs)) = rxn % sigma(cut2-IE+1:size(rxn % sigma)) + ! cut2-IE+1 points. + allocate(new_xs(size(rxn % sigma) - (cut2-IE+1))) + new_xs(1:size(new_xs)) = rxn % sigma(cut2-IE+2:size(rxn % sigma)) call move_alloc(new_xs, rxn % sigma) - rxn % threshold = cut1 + 4 + rxn % threshold = cut2 + 1 end if end associate end do From f2674c28abf40b235fcb8a27e2dde9ee5d981cb8 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 2 Oct 2016 11:58:39 -0400 Subject: [PATCH 34/60] Move threadprivate flux derivatives to Particle --- src/global.F90 | 1 - src/input_xml.F90 | 12 +--- src/particle_header.F90 | 3 + src/simulation.F90 | 5 +- src/tally.F90 | 154 +++++++++++++++++++--------------------- src/tally_header.F90 | 1 - src/tracking.F90 | 4 +- 7 files changed, 84 insertions(+), 96 deletions(-) diff --git a/src/global.F90 b/src/global.F90 index 46508ab5b..7ff8a26b6 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -181,7 +181,6 @@ module global ! Tally derivatives type(TallyDerivative), allocatable :: tally_derivs(:) -!$omp threadprivate(tally_derivs) ! Normalization for statistics integer :: n_realizations = 0 ! # of independent realizations diff --git a/src/input_xml.F90 b/src/input_xml.F90 index cd3e66cef..ade883411 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2630,10 +2630,8 @@ contains filename = trim(path_input) // "tallies.xml" inquire(FILE=filename, EXIST=file_exists) if (.not. file_exists) then - ! We need each thread to allocate tally_derivs to avoid segfaults -!$omp parallel + ! We need to allocate tally_derivs to avoid segfaults allocate(tally_derivs(0)) -!$omp end parallel ! Since a tallies.xml file is optional, no error is issued here return @@ -2816,15 +2814,9 @@ contains ! ========================================================================== ! READ DATA FOR DERIVATIVES - ! Get pointer list to XML . + ! Get pointer list to XML nodes and allocate global array. call get_node_list(doc, "derivative", node_deriv_list) - - ! Allocate TallyDerivative array on each thread. The attributes of the - ! TallyDerivatives will be set on the master thread and then 'copyin'ed - ! in simulate.F90 -!$omp parallel allocate(tally_derivs(get_list_size(node_deriv_list))) -!$omp end parallel ! Read derivative attributes. do i = 1, get_list_size(node_deriv_list) diff --git a/src/particle_header.F90 b/src/particle_header.F90 index 53a503ce2..ffb0617e4 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -100,6 +100,9 @@ module particle_header integer(8) :: n_secondary = 0 type(Bank) :: secondary_bank(MAX_SECONDARY) + ! Flux (weight) derivatives for differential tallies + real(8), allocatable :: flux_derivs(:) + contains procedure :: initialize => initialize_particle procedure :: clear => clear_particle diff --git a/src/simulation.F90 b/src/simulation.F90 index 93950b1f9..312b56d82 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -48,6 +48,9 @@ contains if (.not. restart_run) call initialize_source() + ! Allocate flux derivative array for differential tallies + allocate(p % flux_derivs(size(tally_derivs))) + ! Display header if (master) then if (run_mode == MODE_FIXEDSOURCE) then @@ -84,7 +87,7 @@ contains ! ==================================================================== ! LOOP OVER PARTICLES -!$omp parallel do schedule(static) firstprivate(p) copyin(tally_derivs) +!$omp parallel do schedule(static) firstprivate(p) PARTICLE_LOOP: do i_work = 1, work current_work = i_work diff --git a/src/tally.F90 b/src/tally.F90 index 10ab35a79..889adb406 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2743,24 +2743,27 @@ contains integer, intent(in) :: score_bin real(8), intent(inout) :: score - integer :: l ! loop index for nuclides in material + integer :: l logical :: scoring_diff_nuclide + real(8) :: flux_deriv real(8) :: dsigT, dsigA, dsigF, cum_dsig if (score == ZERO) return + flux_deriv = p % flux_derivs(t % deriv) + associate(deriv => tally_derivs(t % deriv)) - select case (deriv % variable) + select case (tally_derivs(t % deriv) % variable) case (DIFF_DENSITY) select case (t % estimator) case (ESTIMATOR_ANALOG) if (materials(p % material) % id == deriv % diff_material) then - score = score * (deriv % flux_deriv + ONE & + score = score * (flux_deriv + ONE & / materials(p % material) % density_gpcc) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (ESTIMATOR_COLLISION) @@ -2768,52 +2771,52 @@ contains select case (score_bin) case (SCORE_FLUX) - score = score * deriv % flux_deriv + score = score * flux_deriv case (SCORE_TOTAL) if (materials(p % material) % id == deriv % diff_material & .and. material_xs % total /= ZERO) then - score = score * (deriv % flux_deriv + ONE & + score = score * (flux_deriv + ONE & / materials(p % material) % density_gpcc) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_SCATTER) if (materials(p % material) % id == deriv % diff_material & .and. material_xs % total - material_xs % absorption /= ZERO) & then - score = score * (deriv % flux_deriv + ONE & + score = score * (flux_deriv + ONE & / materials(p % material) % density_gpcc) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_ABSORPTION) if (materials(p % material) % id == deriv % diff_material & .and. material_xs % absorption /= ZERO) then - score = score * (deriv % flux_deriv + ONE & + score = score * (flux_deriv + ONE & / materials(p % material) % density_gpcc) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_FISSION) if (materials(p % material) % id == deriv % diff_material & .and. material_xs % fission /= ZERO) then - score = score * (deriv % flux_deriv + ONE & + score = score * (flux_deriv + ONE & / materials(p % material) % density_gpcc) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_NU_FISSION) if (materials(p % material) % id == deriv % diff_material & .and. material_xs % nu_fission /= ZERO) then - score = score * (deriv % flux_deriv + ONE & + score = score * (flux_deriv + ONE & / materials(p % material) % density_gpcc) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case default @@ -2836,11 +2839,11 @@ contains do l = 1, mat % n_nuclides if (mat % nuclide(l) == deriv % diff_nuclide) exit end do - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + ONE / mat % atom_density(l)) end associate else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (ESTIMATOR_COLLISION) @@ -2851,78 +2854,78 @@ contains select case (score_bin) case (SCORE_FLUX) - score = score * deriv % flux_deriv + score = score * flux_deriv case (SCORE_TOTAL) if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & material_xs % total /= ZERO) then - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + micro_xs(deriv % diff_nuclide) % total & / material_xs % total) else if (scoring_diff_nuclide .and. & micro_xs(deriv % diff_nuclide) % total /= ZERO) then - score = score * (deriv % flux_deriv + ONE / atom_density) + score = score * (flux_deriv + ONE / atom_density) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_SCATTER) if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & material_xs % total - material_xs % absorption /= ZERO) then - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + (micro_xs(deriv % diff_nuclide) % total & - micro_xs(deriv % diff_nuclide) % absorption) & / (material_xs % total - material_xs % absorption)) else if (scoring_diff_nuclide .and. & (micro_xs(deriv % diff_nuclide) % total & - micro_xs(deriv % diff_nuclide) % absorption) /= ZERO) then - score = score * (deriv % flux_deriv + ONE / atom_density) + score = score * (flux_deriv + ONE / atom_density) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_ABSORPTION) if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & material_xs % absorption /= ZERO) then - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + micro_xs(deriv % diff_nuclide) % absorption & / material_xs % absorption ) else if (scoring_diff_nuclide .and. & micro_xs(deriv % diff_nuclide) % absorption /= ZERO) then - score = score * (deriv % flux_deriv + ONE / atom_density) + score = score * (flux_deriv + ONE / atom_density) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_FISSION) if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & material_xs % fission /= ZERO) then - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + micro_xs(deriv % diff_nuclide) % fission & / material_xs % fission) else if (scoring_diff_nuclide .and. & micro_xs(deriv % diff_nuclide) % fission /= ZERO) then - score = score * (deriv % flux_deriv + ONE / atom_density) + score = score * (flux_deriv + ONE / atom_density) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_NU_FISSION) if (i_nuclide == -1 .and. & materials(p % material) % id == deriv % diff_material .and. & material_xs % nu_fission /= ZERO) then - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + micro_xs(deriv % diff_nuclide) % nu_fission & / material_xs % nu_fission) else if (scoring_diff_nuclide .and. & micro_xs(deriv % diff_nuclide) % nu_fission /= ZERO) then - score = score * (deriv % flux_deriv + ONE / atom_density) + score = score * (flux_deriv + ONE / atom_density) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case default @@ -2943,7 +2946,7 @@ contains select case (score_bin) case (SCORE_FLUX) - score = score * deriv % flux_deriv + score = score * flux_deriv case (SCORE_TOTAL) if (materials(p % material) % id == deriv % diff_material .and. & @@ -2961,11 +2964,11 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigT * mat % atom_density(l) / material_xs % total) end associate else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_SCATTER) @@ -2986,12 +2989,12 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv + (dsigT - dsigA) & + score = score * (flux_deriv + (dsigT - dsigA) & * mat % atom_density(l) / & (material_xs % total - material_xs % absorption)) end associate else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_ABSORPTION) @@ -3010,11 +3013,11 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigA * mat % atom_density(l) / material_xs % absorption) end associate else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_FISSION) @@ -3033,11 +3036,11 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigF * mat % atom_density(l) / material_xs % fission) end associate else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_NU_FISSION) @@ -3056,13 +3059,13 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigF * mat % atom_density(l) / material_xs % nu_fission& * micro_xs(p % event_nuclide) % nu_fission & / micro_xs(p % event_nuclide) % fission) end associate else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case default @@ -3075,7 +3078,7 @@ contains select case (score_bin) case (SCORE_FLUX) - score = score * deriv % flux_deriv + score = score * flux_deriv case (SCORE_TOTAL) if (i_nuclide == -1 .and. & @@ -3096,7 +3099,7 @@ contains end associate end do end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + cum_dsig / material_xs % total) else if (materials(p % material) % id == deriv % diff_material & .and. material_xs % total > ZERO) then @@ -3109,10 +3112,10 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigT / micro_xs(i_nuclide) % total) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_SCATTER) @@ -3136,7 +3139,7 @@ contains end associate end do end associate - score = score * (deriv % flux_deriv + cum_dsig & + score = score * (flux_deriv + cum_dsig & / (material_xs % total - material_xs % absorption)) else if ( materials(p % material) % id == deriv % diff_material & .and. (material_xs % total - material_xs % absorption) > ZERO)& @@ -3151,11 +3154,11 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv + (dsigT - dsigA) & + score = score * (flux_deriv + (dsigT - dsigA) & / (micro_xs(i_nuclide) % total & - micro_xs(i_nuclide) % absorption)) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_ABSORPTION) @@ -3177,7 +3180,7 @@ contains end associate end do end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + cum_dsig / material_xs % absorption) else if (materials(p % material) % id == deriv % diff_material & .and. material_xs % absorption > ZERO) then @@ -3190,10 +3193,10 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigA / micro_xs(i_nuclide) % absorption) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_FISSION) @@ -3215,7 +3218,7 @@ contains end associate end do end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + cum_dsig / material_xs % fission) else if (materials(p % material) % id == deriv % diff_material & .and. material_xs % fission > ZERO) then @@ -3228,10 +3231,10 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigF / micro_xs(i_nuclide) % fission) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case (SCORE_NU_FISSION) @@ -3255,7 +3258,7 @@ contains end associate end do end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + cum_dsig / material_xs % nu_fission) else if (materials(p % material) % id == deriv % diff_material & .and. material_xs % nu_fission > ZERO) then @@ -3268,10 +3271,10 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) end if end associate - score = score * (deriv % flux_deriv & + score = score * (flux_deriv & + dsigF / micro_xs(i_nuclide) % fission) else - score = score * deriv % flux_deriv + score = score * flux_deriv end if case default @@ -3293,8 +3296,8 @@ contains !=============================================================================== subroutine score_track_derivative(p, distance) - type(particle), intent(in) :: p - real(8), intent(in) :: distance ! Neutron flight distance + type(particle), intent(inout) :: p + real(8), intent(in) :: distance ! Neutron flight distance integer :: i, l real(8) :: dsigT, dsigA, dsigF @@ -3312,7 +3315,7 @@ contains ! phi = e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_rho) = - (d_Sigma_tot / d_rho) * dist ! (1 / phi) * (d_phi / d_rho) = - Sigma_tot / rho * dist - deriv % flux_deriv = deriv % flux_deriv & + p % flux_derivs(i) = p % flux_derivs(i) & - distance * material_xs % total / mat % density_gpcc end if end associate @@ -3323,7 +3326,7 @@ contains ! phi = e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_N) = - (d_Sigma_tot / d_N) * dist ! (1 / phi) * (d_phi / d_N) = - sigma_tot * dist - deriv % flux_deriv = deriv % flux_deriv & + p % flux_derivs(i) = p % flux_derivs(i) & - distance * micro_xs(deriv % diff_nuclide) % total end if end associate @@ -3338,7 +3341,7 @@ contains p % E <= nuc % multipole % end_E/1.0e6_8) then call multipole_deriv_eval(nuc % multipole, p % E, & p % sqrtkT, dsigT, dsigA, dsigF) - deriv % flux_deriv = deriv % flux_deriv & + p % flux_derivs(i) = p % flux_derivs(i) & - distance * dsigT * mat % atom_density(l) end if end associate @@ -3356,7 +3359,7 @@ contains !=============================================================================== subroutine score_collision_derivative(p) - type(particle), intent(in) :: p + type(particle), intent(inout) :: p integer :: i, j, l real(8) :: dsigT, dsigA, dsigF @@ -3374,7 +3377,7 @@ contains ! phi = Sigma_MT ! (1 / phi) * (d_phi / d_rho) = (d_Sigma_MT / d_rho) / Sigma_MT ! (1 / phi) * (d_phi / d_rho) = 1 / rho - deriv % flux_deriv = deriv % flux_deriv & + p % flux_derivs(i) = p % flux_derivs(i) & + ONE / mat % density_gpcc end if end associate @@ -3395,7 +3398,7 @@ contains ! (1 / phi) * (d_phi / d_N) = (d_Sigma_MT / d_N) / Sigma_MT ! (1 / phi) * (d_phi / d_N) = sigma_MT / Sigma_MT ! (1 / phi) * (d_phi / d_N) = 1 / N - deriv % flux_deriv = deriv % flux_deriv & + p % flux_derivs(i) = p % flux_derivs(i) & + ONE / mat % atom_density(j) end if end associate @@ -3416,11 +3419,11 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) select case(p % event) case (EVENT_SCATTER) - deriv % flux_deriv = deriv % flux_deriv + (dsigT - dsigA)& + p % flux_derivs(i) = p % flux_derivs(i) + (dsigT - dsigA)& / (micro_xs(mat % nuclide(l)) % total & - micro_xs(mat % nuclide(l)) % absorption) case (EVENT_ABSORB) - deriv % flux_deriv = deriv % flux_deriv & + p % flux_derivs(i) = p % flux_derivs(i) & + dsigA / micro_xs(mat % nuclide(l)) % absorption end select end if @@ -3433,17 +3436,6 @@ contains end do end subroutine score_collision_derivative -!=============================================================================== -! ZERO_FLUX_DERIVS Set the flux derivatives on differential tallies to zero. -!=============================================================================== - - subroutine zero_flux_derivs() - integer :: i - do i = 1, size(tally_derivs) - tally_derivs(i) % flux_deriv = ZERO - end do - end subroutine zero_flux_derivs - !=============================================================================== ! SYNCHRONIZE_TALLIES accumulates the sum of the contributions from each history ! within the batch to a new random variable diff --git a/src/tally_header.F90 b/src/tally_header.F90 index f30a40deb..5a80f249f 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -25,7 +25,6 @@ module tally_header type TallyDerivative integer :: id - real(8) :: flux_deriv integer :: variable integer :: diff_material integer :: diff_nuclide diff --git a/src/tracking.F90 b/src/tracking.F90 index b0ba615ee..7bdd32c22 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -16,7 +16,7 @@ module tracking use tally, only: score_analog_tally, score_tracklength_tally, & score_collision_tally, score_surface_current, & score_track_derivative, & - score_collision_derivative, zero_flux_derivs + score_collision_derivative use track_output, only: initialize_particle_track, write_particle_track, & add_particle_track, finalize_particle_track @@ -66,7 +66,7 @@ contains endif ! Every particle starts with no accumulated flux derivative. - if (active_tallies % size() > 0) call zero_flux_derivs() + p % flux_derivs(:) = ZERO EVENT_LOOP: do ! If the cell hasn't been determined based on the particle's location, From 80a6095cfec49d95e40d09cbecd94cff78fc8a50 Mon Sep 17 00:00:00 2001 From: Sam Shaner Date: Thu, 13 Oct 2016 17:50:43 -0400 Subject: [PATCH 35/60] added prompt and delayed nu-fission matrices --- openmc/mgxs/library.py | 14 +- openmc/mgxs/mdgxs.py | 621 ++++++++++++++++++++++++++++++++++++++++- openmc/mgxs/mgxs.py | 126 ++++++++- openmc/mgxs_library.py | 34 ++- src/mgxs_header.F90 | 236 ++++++++++++++-- 5 files changed, 995 insertions(+), 36 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index e91f3a245..84c17da96 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -527,7 +527,7 @@ class Library(object): ---------- domain : Material or Cell or Universe or Integral The material, cell, or universe object of interest (or its ID) - mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'delayed-nu-fission', 'chi-delayed', 'beta'} + mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'prompt-nu-fission matrix', 'delayed-nu-fission', 'delayed-nu-fission matrix', 'chi-delayed', 'beta'} The type of multi-group cross section object to return Returns @@ -987,12 +987,24 @@ class Library(object): nuclide=[nuclide], subdomain=subdomain) + if 'prompt-nu-fission matrix' in self.mgxs_types: + mymgxs = self.get_mgxs(domain, 'prompt-nu-fission matrix') + xsdata.set_prompt_nu_fission_mgxs(mymgxs, xs_type=xs_type, + nuclide=[nuclide], + subdomain=subdomain) + if 'delayed-nu-fission' in self.mgxs_types: mymgxs = self.get_mgxs(domain, 'delayed-nu-fission') xsdata.set_delayed_nu_fission_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide], subdomain=subdomain) + if 'delayed-nu-fission matrix' in self.mgxs_types: + mymgxs = self.get_mgxs(domain, 'delayed-nu-fission matrix') + xsdata.set_delayed_nu_fission_mgxs(mymgxs, xs_type=xs_type, + nuclide=[nuclide], + subdomain=subdomain) + if 'beta' in self.mgxs_types: mymgxs = self.get_mgxs(domain, 'nu-fission') xsdata.set_beta_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide], diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 2c616b368..dc0d47833 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -22,7 +22,8 @@ if sys.version_info[0] >= 3: MDGXS_TYPES = ['delayed-nu-fission', 'chi-delayed', 'beta', - 'decay-rate'] + 'decay-rate', + 'delayed-nu-fission matrix'] # Maximum number of delayed groups, from src/constants.F90 MAX_DELAYED_GROUPS = 8 @@ -215,7 +216,7 @@ class MDGXS(MGXS): Parameters ---------- - mdgxs_type : {'delayed-nu-fission', 'chi-delayed', 'beta', 'decay-rate'} + mdgxs_type : {'delayed-nu-fission', 'chi-delayed', 'beta', 'decay-rate', 'delayed-nu-fission matrix'} The type of multi-delayed-group cross section object to return domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh @@ -253,6 +254,9 @@ class MDGXS(MGXS): mdgxs = Beta(domain, domain_type, energy_groups, delayed_groups) elif mdgxs_type == 'decay-rate': mdgxs = DecayRate(domain, domain_type, energy_groups, delayed_groups) + elif mdgxs_type == 'delayed-nu-fission matrix': + mdgxs = DelayedNuFissionMatrixXS(domain, domain_type, energy_groups, + delayed_groups) mdgxs.by_nuclide = by_nuclide mdgxs.name = name @@ -1732,3 +1736,616 @@ class DecayRate(MDGXS): super(DecayRate, self)._compute_xs() return self._xs_tally + + +class MatrixMDGXS(MDGXS): + """An abstract multi-delayed-group cross section for some energy group and + delayed group structure within some spatial domain. This class is + specifically intended for cross sections which depend on both the incoming + and outgoing energy groups and are therefore represented by matrices. + An example of this is the delayed-nu-fission matrix. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group and multi-delayed-group cross sections for downstream neutronics + calculations. + + NOTE: Users should instantiate the subclasses of this abstract class. + + Parameters + ---------- + domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh + The domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + The domain type for spatial homogenization + energy_groups : openmc.mgxs.EnergyGroups + The energy group structure for energy condensation + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + name : str, optional + Name of the multi-group cross section. Used as a label to identify + tallies in OpenMC 'tallies.xml' file. + delayed_groups : list of int + Delayed groups to filter out the xs + + Attributes + ---------- + name : str, optional + Name of the multi-group cross section + rxn_type : str + Reaction type (e.g., 'total', 'nu-fission', etc.) + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + domain : Material or Cell or Universe or Mesh + Domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + Domain type for spatial homogenization + energy_groups : openmc.mgxs.EnergyGroups + Energy group structure for energy condensation + delayed_groups : list of int + Delayed groups to filter out the xs + tally_trigger : openmc.Trigger + An (optional) tally precision trigger given to each tally used to + compute the cross section + scores : list of str + The scores in each tally used to compute the multi-group cross section + filters : list of openmc.Filter + The filters in each tally used to compute the multi-group cross section + tally_keys : list of str + The keys into the tallies dictionary for each tally used to compute + the multi-group cross section + estimator : {'tracklength', 'collision', 'analog'} + The tally estimator used to compute the multi-group cross section + tallies : collections.OrderedDict + OpenMC tallies needed to compute the multi-group cross section + rxn_rate_tally : openmc.Tally + Derived tally for the reaction rate tally used in the numerator to + compute the multi-group cross section. This attribute is None + unless the multi-group cross section has been computed. + xs_tally : openmc.Tally + Derived tally for the multi-group cross section. This attribute + is None unless the multi-group cross section has been computed. + num_subdomains : int + The number of subdomains is unity for 'material', 'cell' and 'universe' + domain types. This is equal to the number of cell instances + for 'distribcell' domain types (it is equal to unity prior to loading + tally data from a statepoint file) and the number of mesh cells for + 'mesh' domain types. + num_nuclides : int + The number of nuclides for which the multi-group cross section is + being tracked. This is unity if the by_nuclide attribute is False. + nuclides : Iterable of str or 'sum' + The optional user-specified nuclides for which to compute cross + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides + are not specified by the user, all nuclides in the spatial domain + are included. This attribute is 'sum' if by_nuclide is false. + sparse : bool + Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format + for compressed data storage + loaded_sp : bool + Whether or not a statepoint file has been loaded with tally data + derived : bool + Whether or not the MGXS is merged from one or more other MGXS + hdf5_key : str + The key used to index multi-group cross sections in an HDF5 data store + + """ + + # This is an abstract class which cannot be instantiated + __metaclass__ = abc.ABCMeta + + @property + def filters(self): + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy = openmc.EnergyFilter(group_edges) + energyout = openmc.EnergyoutFilter(group_edges) + + if self.delayed_groups != None: + delayed = openmc.DelayedGroupFilter(self.delayed_groups) + return [[energy], [delayed, energy, energyout]] + else: + return [[energy], [energy, energyout]] + + def get_xs(self, in_groups='all', out_groups='all', + subdomains='all', nuclides='all', + xs_type='macro', order_groups='increasing', + row_column='inout', value='mean', delayed_groups='all', + squeeze=True, **kwargs): + """Returns an array of multi-group cross sections. + + This method constructs a 4D NumPy array for the requested + multi-group cross section data for one or more subdomains + (1st dimension), delayed groups (2nd dimension), energy groups in + (3rd dimension), energy groups out (4th dimension), and nuclides + (5th dimension). + + Parameters + ---------- + in_groups : Iterable of Integral or 'all' + Incoming energy groups of interest. Defaults to 'all'. + out_groups : Iterable of Integral or 'all' + Outgoing energy groups of interest. Defaults to 'all'. + subdomains : Iterable of Integral or 'all' + Subdomain IDs of interest. Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + A list of nuclide name strings (e.g., ['U235', 'U238']). The + special string 'all' will return the cross sections for all + nuclides in the spatial domain. The special string 'sum' will + return the cross section summed over all nuclides. Defaults to + 'all'. + xs_type: {'macro', 'micro'} + Return the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + order_groups: {'increasing', 'decreasing'} + Return the cross section indexed according to increasing or + decreasing energy groups (decreasing or increasing energies). + Defaults to 'increasing'. + row_column: {'inout', 'outin'} + Return the cross section indexed first by incoming group and + second by outgoing group ('inout'), or vice versa ('outin'). + Defaults to 'inout'. + value : {'mean', 'std_dev', 'rel_err'} + A string for the type of value to return. Defaults to 'mean'. + delayed_groups : list of int or 'all' + Delayed groups of interest. Defaults to 'all'. + squeeze : bool + A boolean representing whether to eliminate the extra dimensions + of the multi-dimensional array to be returned. Defaults to True. + + Returns + ------- + ndarray + A NumPy array of the multi-group cross section indexed in the order + each group and subdomain is listed in the parameters. + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + + """ + + cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + # FIXME: Unable to get microscopic xs for mesh domain because the mesh + # cells do not know the nuclide densities in each mesh cell. + if self.domain_type == 'mesh' and xs_type == 'micro': + msg = 'Unable to get micro xs for mesh domain since the mesh ' \ + 'cells do not know the nuclide densities in each mesh cell.' + raise ValueError(msg) + + filters = [] + filter_bins = [] + + # Construct a collection of the domain filter bins + if not isinstance(subdomains, basestring): + cv.check_iterable_type('subdomains', subdomains, Integral, + max_depth=3) + for subdomain in subdomains: + filters.append(_DOMAIN_TO_FILTER[self.domain_type]) + filter_bins.append((subdomain,)) + + # Construct list of energy group bounds tuples for all requested groups + if not isinstance(in_groups, basestring): + cv.check_iterable_type('groups', in_groups, Integral) + for group in in_groups: + filters.append(openmc.EnergyFilter) + filter_bins.append(( + self.energy_groups.get_group_bounds(group),)) + + # Construct list of energy group bounds tuples for all requested groups + if not isinstance(out_groups, basestring): + cv.check_iterable_type('groups', out_groups, Integral) + for group in out_groups: + filters.append(openmc.EnergyoutFilter) + filter_bins.append(( + self.energy_groups.get_group_bounds(group),)) + + # Construct list of delayed group tuples for all requested groups + if not isinstance(delayed_groups, basestring): + cv.check_type('delayed groups', delayed_groups, list, int) + for delayed_group in delayed_groups: + filters.append(openmc.DelayedGroupFilter) + filter_bins.append((delayed_group,)) + + # Construct a collection of the nuclides to retrieve from the xs tally + if self.by_nuclide: + if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: + query_nuclides = self.get_nuclides() + else: + query_nuclides = nuclides + else: + query_nuclides = ['total'] + + # Use tally summation if user requested the sum for all nuclides + if nuclides == 'sum' or nuclides == ['sum']: + xs_tally = self.xs_tally.summation(nuclides=query_nuclides) + xs = xs_tally.get_values(filters=filters, filter_bins=filter_bins, + value=value) + else: + xs = self.xs_tally.get_values(filters=filters, + filter_bins=filter_bins, + nuclides=query_nuclides, value=value) + + # Divide by atom number densities for microscopic cross sections + if xs_type == 'micro': + if self.by_nuclide: + densities = self.get_nuclide_densities(nuclides) + else: + densities = self.get_nuclide_densities('sum') + if value == 'mean' or value == 'std_dev': + xs /= densities[np.newaxis, :, np.newaxis] + + # Eliminate the trivial score dimension + xs = np.squeeze(xs, axis=len(xs.shape) - 1) + xs = np.nan_to_num(xs) + + if in_groups == 'all': + num_in_groups = self.num_groups + else: + num_in_groups = len(in_groups) + + if out_groups == 'all': + num_out_groups = self.num_groups + else: + num_out_groups = len(out_groups) + + if delayed_groups == 'all': + num_delayed_groups = self.num_delayed_groups + else: + num_delayed_groups = len(delayed_groups) + + # Reshape tally data array with separate axes for domain and energy + num_subdomains = int(xs.shape[0] / (num_in_groups * num_out_groups * + num_delayed_groups)) + new_shape = (num_subdomains, num_delayed_groups, num_in_groups, + num_out_groups) + new_shape += xs.shape[1:] + xs = np.reshape(xs, new_shape) + + # Transpose the matrix if requested by user + if row_column == 'outin': + xs = np.swapaxes(xs, 2, 3) + + # Reverse data if user requested increasing energy groups since + # tally data is stored in order of increasing energies + if order_groups == 'increasing': + xs = xs[:, :, ::-1, ::-1, :] + + if squeeze: + xs = np.squeeze(xs) + xs = np.atleast_2d(xs) + + return xs + + def get_slice(self, nuclides=[], in_groups=[], out_groups=[], + delayed_groups=[]): + """Build a sliced MatrixMDGXS object for the specified nuclides and + energy groups. + + This method constructs a new MdGXS to encapsulate a subset of the data + represented by this MdGXS. The subset of data to include in the tally + slice is determined by the nuclides, energy groups, and delayed groups + specified in the input parameters. + + Parameters + ---------- + nuclides : list of str + A list of nuclide name strings + (e.g., ['U235', 'U238']; default is []) + in_groups : list of int + A list of incoming energy group indices starting at 1 for the high + energies (e.g., [1, 2, 3]; default is []) + out_groups : list of int + A list of outgoing energy group indices starting at 1 for the high + energies (e.g., [1, 2, 3]; default is []) + delayed_groups : list of int + A list of delayed group indices + (e.g., [1, 2, 3]; default is []) + + Returns + ------- + openmc.mgxs.MatrixMDGXS + A new MatrixMDGXS object which encapsulates the subset of data + requested for the nuclide(s) and/or energy group(s) requested in + the parameters. + + """ + + # Call super class method and null out derived tallies + slice_xs = super(MatrixMDGXS, self).get_slice(nuclides, in_groups, + delayed_groups) + slice_xs._rxn_rate_tally = None + slice_xs._xs_tally = None + + # Slice outgoing energy groups if needed + if len(out_groups) != 0: + filter_bins = [] + for group in out_groups: + group_bounds = self.energy_groups.get_group_bounds(group) + filter_bins.append(group_bounds) + filter_bins = [tuple(filter_bins)] + + # Slice each of the tallies across energyout groups + for tally_type, tally in slice_xs.tallies.items(): + if tally.contains_filter(openmc.EnergyoutFilter): + tally_slice = tally.get_slice( + filters=[openmc.EnergyoutFilter], + filter_bins=filter_bins) + slice_xs.tallies[tally_type] = tally_slice + + slice_xs.sparse = self.sparse + return slice_xs + + def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'): + """Prints a string representation for the multi-group cross section. + + Parameters + ---------- + subdomains : Iterable of Integral or 'all' + The subdomain IDs of the cross sections to include in the report. + Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + The nuclides of the cross-sections to include in the report. This + may be a list of nuclide name strings (e.g., ['U235', 'U238']). + The special string 'all' will report the cross sections for all + nuclides in the spatial domain. The special string 'sum' will + report the cross sections summed over all nuclides. Defaults to + 'all'. + xs_type: {'macro', 'micro'} + Return the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + + """ + + # Construct a collection of the subdomains to report + if not isinstance(subdomains, basestring): + cv.check_iterable_type('subdomains', subdomains, Integral) + elif self.domain_type == 'distribcell': + subdomains = np.arange(self.num_subdomains, dtype=np.int) + elif self.domain_type == 'mesh': + xyz = [range(1, x+1) for x in self.domain.dimension] + subdomains = list(itertools.product(*xyz)) + else: + subdomains = [self.domain.id] + + # Construct a collection of the nuclides to report + if self.by_nuclide: + if nuclides == 'all': + nuclides = self.get_nuclides() + if nuclides == 'sum': + nuclides = ['sum'] + else: + cv.check_iterable_type('nuclides', nuclides, basestring) + else: + nuclides = ['sum'] + + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + # Build header for string with type and domain info + string = 'Multi-Delayed-Group XS\n' + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) + string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) + string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) + + # Generate the header for an individual XS + xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type)) + + # If cross section data has not been computed, only print string header + if self.tallies is None: + print(string) + return + + string += '{0: <16}\n'.format('\tEnergy Groups:') + template = '{0: <12}Group {1} [{2: <10} - {3: <10}MeV]\n' + + # Loop over energy groups ranges + for group in range(1, self.num_groups + 1): + bounds = self.energy_groups.get_group_bounds(group) + string += template.format('', group, bounds[0], bounds[1]) + + # Loop over all subdomains + for subdomain in subdomains: + + if self.domain_type == 'distribcell': + string += \ + '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) + + # Loop over all Nuclides + for nuclide in nuclides: + + # Build header for nuclide type + if xs_type != 'sum': + string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) + + # Build header for cross section type + string += '{0: <16}\n'.format(xs_header) + + if self.delayed_groups != None: + + for delayed_group in self.delayed_groups: + + template = '{0: <12}Delayed Group {1}:\t' + string += template.format('', delayed_group) + string += '\n' + + template = '{0: <12}Group {1} -> Group {2}:\t\t' + + # Loop over incoming/outgoing energy groups ranges + for in_group in range(1, self.num_groups + 1): + for out_group in range(1, self.num_groups + 1): + string += template.format('', in_group, out_group) + average = \ + self.get_xs([in_group], [out_group], + [subdomain], [nuclide], + xs_type=xs_type, + value='mean', + delayed_groups=[delayed_group]) + rel_err = \ + self.get_xs([in_group], [out_group], + [subdomain], [nuclide], + xs_type=xs_type, + value='rel_err', + delayed_groups=[delayed_group]) + average = average.flatten()[0] + rel_err = rel_err.flatten()[0] * 100. + string += '{:1.2e} +/- {:1.2e}%'.format(average, + rel_err) + string += '\n' + string += '\n' + string += '\n' + else: + + template = '{0: <12}Group {1} -> Group {2}:\t\t' + + # Loop over incoming/outgoing energy groups ranges + for in_group in range(1, self.num_groups + 1): + for out_group in range(1, self.num_groups + 1): + string += template.format('', in_group, out_group) + average = \ + self.get_xs([in_group], [out_group], + [subdomain], [nuclide], + xs_type=xs_type, value='mean') + rel_err = \ + self.get_xs([in_group], [out_group], + [subdomain], [nuclide], + xs_type=xs_type, value='rel_err') + average = average.flatten()[0] + rel_err = rel_err.flatten()[0] * 100. + string += '{:1.2e} +/- {:1.2e}%'.format(average, + rel_err) + string += '\n' + string += '\n' + string += '\n' + string += '\n' + + print(string) + + +class DelayedNuFissionMatrixXS(MatrixMDGXS): + r"""A fission delayed neutron production matrix multi-group cross section. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group fission neutron production cross sections for multi-group + neutronics calculations. At a minimum, one needs to set the + :attr:`DelayedNuFissionMatrixXS.energy_groups` and + :attr:`DelayedNuFissionMatrixXS.domain` properties. Tallies for the flux and + appropriate reaction rates over the specified domain are generated + automatically via the :attr:`DelayedNuFissionMatrixXS.tallies` property, + which can then be appended to a :class:`openmc.Tallies` instance. + + For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the + necessary data to compute multi-group cross sections from a + :class:`openmc.StatePoint` instance. The derived multi-group cross section + can then be obtained from the :attr:`DelayedNuFissionMatrixXS.xs_tally` + property. + + For a spatial domain :math:`V`, energy group :math:`[E_g,E_{g-1}]`, and + delayed group :math:`d`, the fission delayed neutron production cross + section is calculated as: + + .. math:: + + \langle \nu\sigma_{f,g'\rightarrow g} \phi \rangle &= \int_{r \in V} dr + \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{E_g}^{E_{g-1}} dE + \; \chi(E) \nu\sigma_f^d (r, E') \psi(r, E', \Omega')\\ + \langle \phi \rangle &= \int_{r \in V} dr \int_{4\pi} d\Omega + \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega) \\ + \nu\sigma_{f,g'\rightarrow g} &= \frac{\langle \nu\sigma_{f,g'\rightarrow + g}^d \phi \rangle}{\langle \phi \rangle} + + + Parameters + ---------- + domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh + The domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + The domain type for spatial homogenization + groups : openmc.mgxs.EnergyGroups + The energy group structure for energy condensation + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + name : str, optional + Name of the multi-group cross section. Used as a label to identify + tallies in OpenMC 'tallies.xml' file. + delayed_groups : list of int + Delayed groups to filter out the xs + + Attributes + ---------- + name : str, optional + Name of the multi-group cross section + rxn_type : str + Reaction type (e.g., 'total', 'nu-fission', etc.) + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + domain : Material or Cell or Universe or Mesh + Domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + Domain type for spatial homogenization + energy_groups : openmc.mgxs.EnergyGroups + Energy group structure for energy condensation + delayed_groups : list of int + Delayed groups to filter out the xs + tally_trigger : openmc.Trigger + An (optional) tally precision trigger given to each tally used to + compute the cross section + scores : list of str + The scores in each tally used to compute the multi-group cross section + filters : list of openmc.Filter + The filters in each tally used to compute the multi-group cross section + tally_keys : list of str + The keys into the tallies dictionary for each tally used to compute + the multi-group cross section + estimator : {'tracklength', 'analog'} + The tally estimator used to compute the multi-group cross section + tallies : collections.OrderedDict + OpenMC tallies needed to compute the multi-group cross section. The keys + are strings listed in the :attr:`DelayedNuFissionXS.tally_keys` property + and values are instances of :class:`openmc.Tally`. + rxn_rate_tally : openmc.Tally + Derived tally for the reaction rate tally used in the numerator to + compute the multi-group cross section. This attribute is None + unless the multi-group cross section has been computed. + xs_tally : openmc.Tally + Derived tally for the multi-group cross section. This attribute + is None unless the multi-group cross section has been computed. + num_subdomains : int + The number of subdomains is unity for 'material', 'cell' and 'universe' + domain types. When the This is equal to the number of cell instances + for 'distribcell' domain types (it is equal to unity prior to loading + tally data from a statepoint file). + num_nuclides : int + The number of nuclides for which the multi-group cross section is + being tracked. This is unity if the by_nuclide attribute is False. + nuclides : Iterable of str or 'sum' + The optional user-specified nuclides for which to compute cross + sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + are not specified by the user, all nuclides in the spatial domain + are included. This attribute is 'sum' if by_nuclide is false. + sparse : bool + Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format + for compressed data storage + loaded_sp : bool + Whether or not a statepoint file has been loaded with tally data + derived : bool + Whether or not the MGXS is merged from one or more other MGXS + hdf5_key : str + The key used to index multi-group cross sections in an HDF5 data store + + """ + + def __init__(self, domain=None, domain_type=None, energy_groups=None, + delayed_groups=None, by_nuclide=False, name=''): + super(DelayedNuFissionMatrixXS, self).__init__(domain, domain_type, + energy_groups, + delayed_groups, + by_nuclide, name) + self._rxn_type = 'delayed-nu-fission' + self._hdf5_key = 'delayed-nu-fission matrix' + self._estimator = 'analog' + self._valid_estimators = ['analog'] diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 65802f2ef..5a305cf50 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -38,7 +38,8 @@ MGXS_TYPES = ['total', 'chi', 'chi-prompt', 'inverse-velocity', - 'prompt-nu-fission'] + 'prompt-nu-fission', + 'prompt-nu-fission matrix'] # Supported domain types DOMAIN_TYPES = ['cell', @@ -453,7 +454,7 @@ class MGXS(object): Parameters ---------- - mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', 'chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission'} + mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', 'chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'prompt-nu-fission matrix'} The type of multi-group cross section object to return domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh The domain for spatial homogenization @@ -514,6 +515,8 @@ class MGXS(object): mgxs = InverseVelocity(domain, domain_type, energy_groups) elif mgxs_type == 'prompt-nu-fission': mgxs = PromptNuFissionXS(domain, domain_type, energy_groups) + elif mgxs_type == 'prompt-nu-fission matrix': + mgxs = PromptNuFissionMatrixXS(domain, domain_type, energy_groups) mgxs.by_nuclide = by_nuclide mgxs.name = name @@ -1530,7 +1533,7 @@ class MGXS(object): # Override energy groups bounds with indices all_groups = np.arange(self.num_groups, 0, -1, dtype=np.int) - all_groups = np.repeat(all_groups, len(query_nuclides)) + all_groups = np.repeat(all_groups, len(query_nuclides)) if 'energy low [MeV]' in df and 'energyout low [MeV]' in df: df.rename(columns={'energy low [MeV]': 'group in'}, inplace=True) @@ -5140,3 +5143,120 @@ class PromptNuFissionXS(MGXS): super(PromptNuFissionXS, self).__init__(domain, domain_type, groups, by_nuclide, name) self._rxn_type = 'prompt-nu-fission' + + +class PromptNuFissionMatrixXS(MatrixMGXS): + r"""A prompt fission neutron production matrix multi-group cross section. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group cross sections for multi-group neutronics calculations. At a + minimum, one needs to set the :attr:`PromptNuFissionMatrixXS.energy_groups` + and :attr:`PromptNuFissionMatrixXS.domain` properties. Tallies for the flux + and appropriate reaction rates over the specified domain are generated + automatically via the :attr:`PromptNuFissionMatrixXS.tallies` property, + which can then be appended to a :class:`openmc.Tallies` instance. + + For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the + necessary data to compute multi-group cross sections from a + :class:`openmc.StatePoint` instance. The derived multi-group cross section + can then be obtained from the :attr:`PromptNuFissionMatrixXS.xs_tally` + property. + + For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the + fission spectrum is calculated as: + + .. math:: + + \langle \nu\sigma_{f,g'\rightarrow g} \phi \rangle &= \int_{r \in V} dr + \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{E_g}^{E_{g-1}} dE + \; \chi(E) \nu\sigma_f^p (r, E') \psi(r, E', \Omega')\\ + \langle \phi \rangle &= \int_{r \in V} dr \int_{4\pi} d\Omega + \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega) \\ + \nu\sigma_{f,g'\rightarrow g} &= \frac{\langle \nu\sigma_{f,g'\rightarrow + g}^p \phi \rangle}{\langle \phi \rangle} + + Parameters + ---------- + domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh + The domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + The domain type for spatial homogenization + groups : openmc.mgxs.EnergyGroups + The energy group structure for energy condensation + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + name : str, optional + Name of the multi-group cross section. Used as a label to identify + tallies in OpenMC 'tallies.xml' file. + + Attributes + ---------- + name : str, optional + Name of the multi-group cross section + rxn_type : str + Reaction type (e.g., 'total', 'nu-fission', etc.) + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + domain : Material or Cell or Universe or Mesh + Domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + Domain type for spatial homogenization + energy_groups : openmc.mgxs.EnergyGroups + Energy group structure for energy condensation + tally_trigger : openmc.Trigger + An (optional) tally precision trigger given to each tally used to + compute the cross section + scores : list of str + The scores in each tally used to compute the multi-group cross section + filters : list of openmc.Filter + The filters in each tally used to compute the multi-group cross section + tally_keys : list of str + The keys into the tallies dictionary for each tally used to compute + the multi-group cross section + estimator : {'tracklength', 'collision', 'analog'} + The tally estimator used to compute the multi-group cross section + tallies : collections.OrderedDict + OpenMC tallies needed to compute the multi-group cross section. The keys + are strings listed in the :attr:`PromptNuFissionXS.tally_keys` property + and values are instances of :class:`openmc.Tally`. + rxn_rate_tally : openmc.Tally + Derived tally for the reaction rate tally used in the numerator to + compute the multi-group cross section. This attribute is None + unless the multi-group cross section has been computed. + xs_tally : openmc.Tally + Derived tally for the multi-group cross section. This attribute + is None unless the multi-group cross section has been computed. + num_subdomains : int + The number of subdomains is unity for 'material', 'cell' and 'universe' + domain types. This is equal to the number of cell instances + for 'distribcell' domain types (it is equal to unity prior to loading + tally data from a statepoint file). + num_nuclides : int + The number of nuclides for which the multi-group cross section is + being tracked. This is unity if the by_nuclide attribute is False. + nuclides : Iterable of str or 'sum' + The optional user-specified nuclides for which to compute cross + sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides + are not specified by the user, all nuclides in the spatial domain + are included. This attribute is 'sum' if by_nuclide is false. + sparse : bool + Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format + for compressed data storage + loaded_sp : bool + Whether or not a statepoint file has been loaded with tally data + derived : bool + Whether or not the MGXS is merged from one or more other MGXS + hdf5_key : str + The key used to index multi-group cross sections in an HDF5 data store + + """ + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(PromptNuFissionMatrixXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'prompt-nu-fission' + self._hdf5_key = 'prompt-nu-fission matrix' + self._estimator = 'analog' + self._valid_estimators = ['analog'] diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index c661bb52f..f0ed963d8 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -839,9 +839,14 @@ class XSdata(object): # Get the accepted shapes for this xs if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] + shapes = [(self.energy_groups.num_groups,), + (self.energy_groups.num_groups, + self.energy_groups.num_groups)] else: shapes = [(self.num_polar, self.num_azimuthal, + self.energy_groups.num_groups), + (self.num_polar, self.num_azimuthal, + self.energy_groups.num_groups, self.energy_groups.num_groups)] # Convert to a numpy array so we can easily get the shape for checking @@ -877,9 +882,14 @@ class XSdata(object): # Get the accepted shapes for this xs if self.representation is 'isotropic': - shapes = [(self.delayed_groups, self.energy_groups.num_groups,)] + shapes = [(self.delayed_groups, self.energy_groups.num_groups,), + (self.delayed_groups, self.energy_groups.num_groups, + self.energy_groups.num_groups)] else: shapes = [(self.delayed_groups, self.num_polar, self.num_azimuthal, + self.energy_groups.num_groups), + (self.delayed_groups, self.num_polar, self.num_azimuthal, + self.energy_groups.num_groups, self.energy_groups.num_groups)] # Convert to a numpy array so we can easily get the shape for checking @@ -1124,12 +1134,13 @@ class XSdata(object): def set_prompt_nu_fission_mgxs(self, prompt_nu_fission, temperature=294., nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.PromptNuFissionXS to be used to - set the prompt-nu-fission cross section for this XSdata object. + """This method allows for an openmc.mgxs.PromptNuFissionXS or + openmc.mgxs.PromptNuFissionMatrixXS to be used to set the + prompt-nu-fission cross section for this XSdata object. Parameters ---------- - prompt_nu_fission: openmc.mgxs.PromptNuFissionXS + prompt_nu_fission: openmc.mgxs.PromptNuFissionXS or openmc.mgxs.PromptNuFissionMatrixXS MGXS Object containing the prompt-nu-fission cross section for the domain of interest. temperature : float @@ -1153,7 +1164,8 @@ class XSdata(object): """ check_type('prompt_nu_fission', prompt_nu_fission, - (openmc.mgxs.PromptNuFissionXS,)) + (openmc.mgxs.PromptNuFissionXS, + openmc.mgxs.PromptNuFissionMatrixXS)) check_value('energy_groups', prompt_nu_fission.energy_groups, [self.energy_groups]) check_value('domain_type', prompt_nu_fission.domain_type, @@ -1177,12 +1189,13 @@ class XSdata(object): def set_delayed_nu_fission_mgxs(self, delayed_nu_fission, temperature=294., nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.DelayedNuFissionXS to be used - to set the delayed-nu-fission cross section for this XSdata object. + """This method allows for an openmc.mgxs.DelayedNuFissionXS or + openmc.mgxs.DelayedNuFissionMatrixXS to be used to set the + delayed-nu-fission cross section for this XSdata object. Parameters ---------- - delayed_nu_fission: openmc.mgxs.DelayedNuFissionXS + delayed_nu_fission: openmc.mgxs.DelayedNuFissionXS or openmc.mgxs.DelayedNuFissionMatrixXS MGXS Object containing the delayed-nu-fission cross section for the domain of interest. temperature : float @@ -1206,7 +1219,8 @@ class XSdata(object): """ check_type('delayed_nu_fission', delayed_nu_fission, - (openmc.mgxs.DelayedNuFissionXS,)) + (openmc.mgxs.DelayedNuFissionXS, + openmc.mgxs.DelayedNuFissionMatrixXS)) check_value('energy_groups', delayed_nu_fission.energy_groups, [self.energy_groups]) check_value('delayed_groups', delayed_nu_fission.num_delayed_groups, diff --git a/src/mgxs_header.F90 b/src/mgxs_header.F90 index 5acdd64eb..4bd6ac957 100644 --- a/src/mgxs_header.F90 +++ b/src/mgxs_header.F90 @@ -425,7 +425,7 @@ module mgxs_header integer(HID_T) :: xsdata, xsdata_grp, scatt_grp, ndims integer(HSIZE_T) :: dims(2) real(8), allocatable :: temp_arr(:), temp_2d(:, :) - real(8), allocatable :: temp_beta(:, :) + real(8), allocatable :: temp_beta(:, :), temp_3d(:, :, :) real(8) :: dmu, mu, norm, chi_sum integer :: order, order_dim, gin, gout, l, imu, length type(VectorInt) :: temps_to_read @@ -642,11 +642,6 @@ module mgxs_header call fatal_error("nu-fission must be provided as a 1D or 2D & &array") end if - - print *, xs % prompt_nu_fission - print *, xs % delayed_nu_fission - print *, xs % chi_prompt - print *, xs % chi_delayed end if ! If chi_prompt provided, set chi_prompt @@ -755,9 +750,57 @@ module mgxs_header ! If prompt-nu-fission present, set prompt_nu_fission if (check_dataset(xsdata_grp, "prompt-nu-fission")) then - ! Set prompt_nu_fission - call read_dataset(xs % prompt_nu_fission, xsdata_grp, & - "prompt-nu-fission") + ! Get the dimensions of the prompt-nu-fission dataset + xsdata = open_dataset(xsdata_grp, "prompt-nu-fission") + call get_ndims(xsdata, ndims) + + ! If prompt-nu-fission is a vector + if (ndims == 1) then + + ! Set prompt_nu_fission + call read_dataset(xs % prompt_nu_fission, xsdata_grp, & + "prompt-nu-fission") + + ! If prompt-nu-fission is a matrix, set prompt_nu_fission and + ! chi_prompt. + else if (ndims == 2) then + + ! chi_prompt is embedded in prompt_nu_fission -> extract + ! chi_prompt + allocate(temp_arr(energy_groups * energy_groups)) + call read_dataset(temp_arr, xsdata_grp, "prompt-nu-fission") + allocate(temp_2d(energy_groups, energy_groups)) + temp_2d = reshape(temp_arr, (/energy_groups, energy_groups/)) + + ! Deallocate temporary 1D array for prompt_nu_fission matrix + deallocate(temp_arr) + + ! Set the vector prompt-nu-fission from the matrix + ! prompt-nu-fission + do gin = 1, energy_groups + xs % prompt_nu_fission(gin) = sum(temp_2d(:, gin)) + end do + + ! Now pull out information needed for chi + xs % chi_prompt(:, :) = temp_2d + + ! Deallocate temporary 2D array for nu_fission matrix + deallocate(temp_2d) + + ! Normalize chi so its CDF goes to 1 + do gin = 1, energy_groups + chi_sum = sum(xs % chi_prompt(:, gin)) + if (chi_sum == ZERO) then + call fatal_error("Encountered chi prompt for a group & + &that sums to zero") + else + xs % chi_prompt(:, gin) = xs % chi_prompt(:, gin) / chi_sum + end if + end do + else + call fatal_error("prompt-nu-fission must be provided as a 1D & + &or 2D array") + end if end if ! If delayed-nu-fission provided, set delayed_nu_fission. If @@ -836,9 +879,52 @@ module mgxs_header ! Deallocate temporary array for delayed_nu_fission matrix deallocate(temp_arr) + ! If delayed nu-fission is a 3D matrix, set delayed_nu_fission + ! and chi_delayed. + else if (ndims == 3) then + + ! chi_delayed is embedded in delayed_nu_fission -> extract + ! chi_delayed + allocate(temp_arr(delayed_groups * energy_groups * & + energy_groups)) + call read_dataset(temp_arr, xsdata_grp, "delayed-nu-fission") + allocate(temp_3d(energy_groups, energy_groups, delayed_groups)) + temp_3d = reshape(temp_arr, (/energy_groups, energy_groups, & + delayed_groups/)) + + ! Deallocate temporary 1D array for delayed_nu_fission matrix + deallocate(temp_arr) + + ! Set the 2D delayed-nu-fission matrix and 3D chi_dealyed matrix + ! from the 3D delayed-nu-fission matrix + do dg = 1, delayed_groups + do gin = 1, energy_groups + xs % delayed_nu_fission(gin, dg) = sum(temp_3d(:, gin, dg)) + do gout = 1, energy_groups + xs % chi_delayed(gout, gin, dg) = temp_3d(gout, gin, dg) + end do + end do + end do + + ! Normalize chi_delayed so its CDF goes to 1 + do dg = 1, delayed_groups + do gin = 1, energy_groups + chi_sum = sum(xs % chi_delayed(:, gin, dg)) + if (chi_sum == ZERO) then + call fatal_error("Encountered chi delayed for a group & + &that sums to zero") + else + xs % chi_delayed(:, gin, dg) = & + xs % chi_delayed(:, gin, dg) / chi_sum + end if + end do + end do + + ! Deallocate temporary 3D matrix for delayed_nu_fission + deallocate(temp_3d) else call fatal_error("delayed-nu-fission must be provided as a & - &1D or 2D array") + &1D, 2D, or 3D array") end if end if @@ -1107,7 +1193,8 @@ module mgxs_header integer(HSIZE_T) :: dims(4) integer, allocatable :: int_arr(:) real(8), allocatable :: temp_1d(:), temp_3d(:, :, :) - real(8), allocatable :: temp_4d(:, :, :, :), temp_beta(:, :, :, :) + real(8), allocatable :: temp_4d(:, :, :, :), temp_5d(:, :, :, :, :) + real(8), allocatable :: temp_beta(:, :, :, :) real(8) :: dmu, mu, norm integer :: order, order_dim, gin, gout, l, imu, dg type(VectorInt) :: temps_to_read @@ -1401,16 +1488,70 @@ module mgxs_header ! If prompt-nu-fission present, set prompt_nu_fission if (check_dataset(xsdata_grp, "prompt-nu-fission")) then - ! Allocate temporary array for prompt-nu-fission - allocate(temp_1d(energy_groups * this % n_azi * this % n_pol)) + ! Get the dimensions of the prompt-nu-fission dataset + xsdata = open_dataset(xsdata_grp, "prompt-nu-fission") + call get_ndims(xsdata, ndims) - ! Read prompt-nu-fission - call read_dataset(temp_1d, xsdata_grp, "prompt-nu-fission") - xs % prompt_nu_fission = reshape(temp_1d, (/energy_groups, & - this % n_azi, this % n_pol/)) + ! If prompt-nu-fission is a vector for each azi and pol + if (ndims == 3) then - ! Deallocate temporary array for prompt_nu_fission - deallocate(temp_1d) + ! Set prompt_nu_fission + call read_dataset(xs % prompt_nu_fission, xsdata_grp, & + "prompt-nu-fission") + + ! If prompt-nu-fission is a matrix for each azi and pol, + ! set prompt_nu_fission and chi_prompt. + else if (ndims == 4) then + + ! chi_prompt is embedded in prompt_nu_fission -> extract + ! chi_prompt + allocate(temp_1d(energy_groups * energy_groups & + * this % n_azi * this % n_pol)) + allocate(temp_4d(energy_groups, energy_groups, this % n_azi, & + this % n_pol)) + call read_dataset(temp_1d, xsdata_grp, "prompt-nu-fission") + temp_4d = reshape(temp_1d, (/energy_groups, energy_groups, & + this % n_azi, this % n_pol/)) + + ! Deallocate temporary 1D array for prompt_nu_fission matrix + deallocate(temp_1d) + + ! Set the vector prompt-nu-fission from the matrix + ! prompt-nu-fission + do ipol = 1, this % n_pol + do iazi = 1, this % n_azi + do gin = 1, energy_groups + xs % prompt_nu_fission(gin, iazi, ipol) = & + sum(temp_4d(:, gin, iazi, ipol)) + end do + end do + end do + + ! Now pull out information needed for chi + xs % chi_prompt(:, :, :, :) = temp_4d + + ! Deallocate temporary 4D array for nu_fission matrix + deallocate(temp_4d) + + ! Normalize chi so its CDF goes to 1 + do ipol = 1, this % n_pol + do iazi = 1, this % n_azi + do gin = 1, energy_groups + chi_sum = sum(xs % chi_prompt(:, gin, iazi, ipol)) + if (chi_sum == ZERO) then + call fatal_error("Encountered chi prompt for a group & + &that sums to zero") + else + xs % chi_prompt(:, gin, iazi, ipol) = & + xs % chi_prompt(:, gin, iazi, ipol) / chi_sum + end if + end do + end do + end do + else + call fatal_error("prompt-nu-fission must be provided as a 3D & + &or 4D array") + end if end if ! If delayed-nu-fission provided, set delayed_nu_fission. If @@ -1500,9 +1641,64 @@ module mgxs_header ! Deallocate temporary array for delayed_nu_fission matrix deallocate(temp_1d) + ! If delayed nu-fission is a 5D matrix, set delayed_nu_fission + ! and chi_delayed. + else if (ndims == 5) then + + ! chi_delayed is embedded in delayed_nu_fission -> extract + ! chi_delayed + allocate(temp_1d(delayed_groups * energy_groups * & + energy_groups * this % n_azi * this % n_pol)) + allocate(temp_5d(energy_groups, energy_groups, delayed_groups, & + this % n_azi, this % n_pol)) + call read_dataset(temp_1d, xsdata_grp, "delayed-nu-fission") + temp_5d = reshape(temp_1d, (/energy_groups, energy_groups, & + delayed_groups, this % n_azi, this % n_pol/)) + + ! Deallocate temporary 1D array for delayed_nu_fission matrix + deallocate(temp_1d) + + ! Set the 4D delayed-nu-fission matrix and 5D chi_dealyed matrix + ! from the 5D delayed-nu-fission matrix + do ipol = 1, this % n_pol + do iazi = 1, this % n_azi + do dg = 1, delayed_groups + do gin = 1, energy_groups + xs % delayed_nu_fission(gin, dg, iazi, ipol) = & + sum(temp_5d(:, gin, dg, iazi, ipol)) + do gout = 1, energy_groups + xs % chi_delayed(gout, gin, dg, iazi, ipol) = & + temp_5d(gout, gin, dg, iazi, ipol) + end do + end do + end do + end do + end do + + ! Normalize chi_delayed so its CDF goes to 1 + do ipol = 1, this % n_pol + do iazi = 1, this % n_azi + do dg = 1, delayed_groups + do gin = 1, energy_groups + chi_sum = sum(xs % chi_delayed(:, gin, dg, iazi, ipol)) + if (chi_sum == ZERO) then + call fatal_error("Encountered chi delayed for a group& + & that sums to zero") + else + xs % chi_delayed(:, gin, dg, iazi, ipol) = & + xs % chi_delayed(:, gin, dg, iazi, ipol) / & + chi_sum + end if + end do + end do + end do + end do + + ! Deallocate temporary 5D matrix for delayed_nu_fission + deallocate(temp_5d) else call fatal_error("delayed-nu-fission must be provided as a & - &1D or 2D array") + &3D, 4D, or 5D array") end if end if From dc384f5c14a9af1abb72077a9028eeb5c246a1ce Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 19 Oct 2016 15:26:43 -0400 Subject: [PATCH 36/60] Add temperature deriv test; total nuclide err msg --- src/input_xml.F90 | 17 +++ tests/test_diff_tally/inputs_true.dat | 2 +- tests/test_diff_tally/results_true.dat | 172 ++++++++++++++--------- tests/test_diff_tally/test_diff_tally.py | 39 +++-- 4 files changed, 148 insertions(+), 82 deletions(-) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 1fd11a889..bb6024ea7 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3876,6 +3876,23 @@ contains // trim(to_str(t % id))) end if end do + + if (tally_derivs(t % deriv) % variable == DIFF_NUCLIDE_DENSITY & + .or. tally_derivs(t % deriv) % variable == DIFF_TEMPERATURE) then + if (any(t % nuclide_bins == -1)) then + if (t % find_filter(FILTER_ENERGYOUT) > 0) then + call fatal_error("Error on tally " // trim(to_str(t % id)) & + // ": Cannot use a 'nuclide_density' or 'temperature' & + &derivative on a tally with an outgoing energy filter and & + &'total' nuclide rate. Instead, tally each nuclide in the & + &material individually.") + ! Note that diff tallies with these characteristics would work + ! correctly if no tally events occur in the perturbed material + ! (e.g. pertrubing moderator but only tallying fuel), but this + ! case would be hard to check for by only reading inputs. + end if + end if + end if end if ! If settings.xml trigger is turned on, create tally triggers diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index e7215379f..0a23a2c0b 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -1 +1 @@ -f6b3b603cd6ad74c25baf76b57fa222ca395763d0b0317558de8e80ec030af52cf8e266e921b7e36f147e25bcd9cd67cabafd906284a6053b4ca473f4e71252c \ No newline at end of file +7a33d6ea1df959736bf496316b31126523d0578b09a3e6c3440b9cb900e797f21009337e55bbaf90e24edfa6666c838615bc17be163eb062c85a7816fcaee4f9 \ No newline at end of file diff --git a/tests/test_diff_tally/results_true.dat b/tests/test_diff_tally/results_true.dat index b4cef4712..2380050a5 100644 --- a/tests/test_diff_tally/results_true.dat +++ b/tests/test_diff_tally/results_true.dat @@ -1,97 +1,129 @@ d_material,d_nuclide,d_variable,score,mean,std. dev. -3,,density,flux,-5.53e+00,8.45e-01 -3,,density,flux,-9.96e+00,1.01e+00 -1,,density,flux,-2.97e-01,5.83e-02 -1,,density,flux,-3.05e-01,7.69e-02 -1,O16,nuclide_density,flux,-1.10e+01,9.63e+00 -1,O16,nuclide_density,flux,-8.07e+00,7.78e+00 -1,U235,nuclide_density,flux,-1.06e+03,1.30e+02 -1,U235,nuclide_density,flux,-9.28e+02,9.72e+01 -3,,density,total,-2.21e+00,4.04e-01 -3,,density,absorption,6.24e-03,1.37e-01 -3,,density,fission,5.89e-02,7.93e-02 -3,,density,nu-fission,1.47e-01,2.06e-01 -3,,density,total,3.36e-02,6.32e-02 -3,,density,absorption,5.67e-02,6.01e-02 -3,,density,fission,5.46e-02,5.03e-02 -3,,density,nu-fission,1.33e-01,1.23e-01 -3,,density,total,8.38e+00,1.33e+00 -3,,density,absorption,1.30e-01,1.97e-02 +1,,density,nu-fission,1.12e-02,5.75e-03 +1,,density,nu-fission,6.27e-03,1.86e-03 +1,,density,nu-fission,1.90e-02,9.78e-03 +1,,density,nu-fission,1.22e-02,5.45e-03 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,nu-fission,0.00e+00,0.00e+00 +1,O16,nuclide_density,nu-fission,3.71e-01,1.76e-01 +1,O16,nuclide_density,nu-fission,4.32e-01,7.01e-01 +1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,U235,nuclide_density,nu-fission,2.03e+02,2.66e+01 +1,U235,nuclide_density,nu-fission,5.14e+02,1.31e+01 +1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 +1,,temperature,nu-fission,1.26e-05,1.05e-05 +1,,temperature,nu-fission,8.20e-06,7.06e-06 +1,,temperature,nu-fission,0.00e+00,0.00e+00 +1,,temperature,nu-fission,0.00e+00,0.00e+00 +3,,density,flux,-5.93e+00,8.02e-01 +3,,density,flux,-1.17e+01,1.10e+00 +1,,density,flux,-1.93e-01,5.38e-02 +1,,density,flux,-1.87e-01,6.13e-02 +1,O16,nuclide_density,flux,3.42e+00,6.84e+00 +1,O16,nuclide_density,flux,-4.63e+00,9.64e+00 +1,U235,nuclide_density,flux,-1.06e+03,1.25e+02 +1,U235,nuclide_density,flux,-9.00e+02,7.41e+01 +1,,temperature,flux,4.38e-05,1.90e-04 +1,,temperature,flux,1.99e-04,1.73e-04 +3,,density,total,-2.51e+00,3.83e-01 +3,,density,absorption,-7.85e-02,1.16e-01 +3,,density,fission,4.85e-02,6.57e-02 +3,,density,nu-fission,1.22e-01,1.73e-01 +3,,density,total,2.01e-02,4.42e-02 +3,,density,absorption,4.49e-02,4.26e-02 +3,,density,fission,4.30e-02,3.67e-02 +3,,density,nu-fission,1.05e-01,8.95e-02 +3,,density,total,7.29e+00,1.19e+00 +3,,density,absorption,1.39e-01,2.85e-02 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,total,0.00e+00,0.00e+00 3,,density,absorption,0.00e+00,0.00e+00 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,total,3.84e-01,4.09e-02 -1,,density,absorption,1.77e-02,9.66e-03 -1,,density,fission,2.95e-03,4.95e-03 -1,,density,nu-fission,8.23e-03,1.30e-02 -1,,density,total,5.44e-03,4.18e-03 -1,,density,absorption,1.29e-03,3.79e-03 -1,,density,fission,2.91e-04,3.01e-03 -1,,density,nu-fission,7.52e-04,7.35e-03 -1,,density,total,-3.59e-01,8.82e-02 -1,,density,absorption,-7.04e-03,1.23e-03 +1,,density,total,4.53e-01,3.58e-02 +1,,density,absorption,3.35e-02,7.74e-03 +1,,density,fission,1.09e-02,3.66e-03 +1,,density,nu-fission,2.93e-02,9.64e-03 +1,,density,total,1.18e-02,2.90e-03 +1,,density,absorption,6.94e-03,2.59e-03 +1,,density,fission,4.63e-03,2.07e-03 +1,,density,nu-fission,1.13e-02,5.04e-03 +1,,density,total,-2.03e-01,5.89e-02 +1,,density,absorption,-4.86e-03,6.33e-04 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,total,0.00e+00,0.00e+00 1,,density,absorption,0.00e+00,0.00e+00 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,total,3.94e+01,5.38e+00 -1,O16,nuclide_density,absorption,9.23e-02,8.39e-01 -1,O16,nuclide_density,fission,-1.87e-01,4.17e-01 -1,O16,nuclide_density,nu-fission,-5.04e-01,1.09e+00 -1,O16,nuclide_density,total,-1.54e-01,3.77e-01 -1,O16,nuclide_density,absorption,-1.13e-01,3.27e-01 -1,O16,nuclide_density,fission,-8.48e-02,2.51e-01 -1,O16,nuclide_density,nu-fission,-2.07e-01,6.11e-01 -1,O16,nuclide_density,total,-5.63e+00,9.03e+00 -1,O16,nuclide_density,absorption,-1.65e-01,1.27e-01 +1,O16,nuclide_density,total,4.71e+01,3.78e+00 +1,O16,nuclide_density,absorption,9.64e-01,7.50e-01 +1,O16,nuclide_density,fission,3.09e-01,2.99e-01 +1,O16,nuclide_density,nu-fission,8.08e-01,7.82e-01 +1,O16,nuclide_density,total,3.23e-01,2.77e-01 +1,O16,nuclide_density,absorption,2.86e-01,2.44e-01 +1,O16,nuclide_density,fission,1.74e-01,1.89e-01 +1,O16,nuclide_density,nu-fission,4.24e-01,4.61e-01 +1,O16,nuclide_density,total,1.01e+00,1.06e+01 +1,O16,nuclide_density,absorption,6.41e-02,1.52e-01 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O16,nuclide_density,total,0.00e+00,0.00e+00 1,O16,nuclide_density,absorption,0.00e+00,0.00e+00 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,total,-1.95e+02,6.93e+01 -1,U235,nuclide_density,absorption,1.06e+02,2.33e+01 -1,U235,nuclide_density,fission,1.74e+02,1.67e+01 -1,U235,nuclide_density,nu-fission,3.84e+02,4.28e+01 -1,U235,nuclide_density,total,4.48e+02,1.64e+01 -1,U235,nuclide_density,absorption,3.37e+02,1.47e+01 -1,U235,nuclide_density,fission,2.66e+02,1.24e+01 -1,U235,nuclide_density,nu-fission,6.49e+02,3.02e+01 -1,U235,nuclide_density,total,-2.06e+03,2.21e+02 -1,U235,nuclide_density,absorption,-5.23e+01,6.36e+00 +1,U235,nuclide_density,total,-1.76e+02,5.81e+01 +1,U235,nuclide_density,absorption,1.33e+02,1.49e+01 +1,U235,nuclide_density,fission,1.97e+02,9.17e+00 +1,U235,nuclide_density,nu-fission,4.39e+02,2.36e+01 +1,U235,nuclide_density,total,4.79e+02,1.03e+01 +1,U235,nuclide_density,absorption,3.65e+02,8.53e+00 +1,U235,nuclide_density,fission,2.89e+02,6.85e+00 +1,U235,nuclide_density,nu-fission,7.05e+02,1.67e+01 +1,U235,nuclide_density,total,-1.74e+03,1.12e+02 +1,U235,nuclide_density,absorption,-4.22e+01,2.70e+00 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U235,nuclide_density,total,0.00e+00,0.00e+00 1,U235,nuclide_density,absorption,0.00e+00,0.00e+00 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -3,,density,absorption,-7.86e-03,9.22e-02 -3,,density,absorption,1.51e-01,2.10e-02 -1,,density,absorption,2.12e-02,6.60e-03 -1,,density,absorption,-4.94e-03,8.88e-04 -1,O16,nuclide_density,absorption,3.51e-01,6.90e-01 -1,O16,nuclide_density,absorption,1.74e-02,7.71e-02 -1,U235,nuclide_density,absorption,9.98e+01,2.40e+01 -1,U235,nuclide_density,absorption,-4.39e+01,7.07e+00 -3,,density,nu-fission,2.64e-02,7.36e-02 -3,,density,nu-fission,7.70e-02,1.28e-01 +1,,temperature,total,1.91e-04,1.38e-04 +1,,temperature,absorption,7.60e-05,4.02e-05 +1,,temperature,fission,1.60e-05,1.40e-05 +1,,temperature,nu-fission,4.22e-05,3.60e-05 +1,,temperature,total,1.12e-05,1.37e-05 +1,,temperature,absorption,1.08e-05,1.26e-05 +1,,temperature,fission,8.52e-06,1.02e-05 +1,,temperature,nu-fission,2.08e-05,2.50e-05 +1,,temperature,total,3.14e-04,2.80e-04 +1,,temperature,absorption,5.46e-06,6.04e-06 +1,,temperature,fission,0.00e+00,0.00e+00 +1,,temperature,nu-fission,0.00e+00,0.00e+00 +1,,temperature,total,0.00e+00,0.00e+00 +1,,temperature,absorption,0.00e+00,0.00e+00 +1,,temperature,fission,0.00e+00,0.00e+00 +1,,temperature,nu-fission,0.00e+00,0.00e+00 +3,,density,absorption,-9.85e-02,8.35e-02 +3,,density,absorption,9.34e-02,3.83e-02 +1,,density,absorption,2.98e-02,6.51e-03 +1,,density,absorption,-2.83e-03,1.44e-03 +1,O16,nuclide_density,absorption,1.34e+00,4.23e-01 +1,O16,nuclide_density,absorption,5.15e-02,8.53e-02 +1,U235,nuclide_density,absorption,1.25e+02,2.55e+01 +1,U235,nuclide_density,absorption,-4.14e+01,4.30e+00 +1,,temperature,absorption,4.95e-05,2.86e-05 +1,,temperature,absorption,-9.35e-07,6.79e-06 +3,,density,nu-fission,4.60e-02,5.96e-02 +3,,density,nu-fission,3.87e-02,3.71e-02 +3,,density,nu-fission,8.85e-02,9.69e-02 +3,,density,nu-fission,4.16e-02,5.47e-02 +3,,density,nu-fission,0.00e+00,0.00e+00 +3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,nu-fission,2.29e-03,4.63e-03 -1,,density,nu-fission,1.33e-02,1.06e-02 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,-9.08e-02,5.90e-01 -1,O16,nuclide_density,nu-fission,1.48e-01,1.07e+00 -1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,9.91e+01,2.80e+01 -1,U235,nuclide_density,nu-fission,2.64e+02,2.71e+01 -1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index d52d499b1..ce5b4a68e 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -25,7 +25,7 @@ class DiffTallyTestHarness(PyAPITestHarness): self._input_set.settings.particles = 400 self._input_set.settings.source = openmc.Source(space=openmc.stats.Box( [-160, -160, -183], [160, 160, 183])) - self._input_set.settings.output = {'summary': True} + self._input_set.settings.temperature['multipole'] = True self._input_set.tallies = openmc.Tallies() @@ -55,18 +55,23 @@ class DiffTallyTestHarness(PyAPITestHarness): d4.material = 1 d4.nuclide = 'U235' - derivs = [d1, d2, d3, d4] + # Temperature derivatives. + d5 = openmc.TallyDerivative(derivative_id=5) + d5.variable = 'temperature' + d5.material = 1 + + derivs = [d1, d2, d3, d4, d5] # Cover the flux score. - for i in range(4): + for i in range(5): t = openmc.Tally() t.add_score('flux') t.add_filter(filt_mats) t.derivative = derivs[i] - self._input_set.tallies.add_tally(t) + self._input_set.tallies.append(t) # Cover supported scores with a collision estimator. - for i in range(4): + for i in range(5): t = openmc.Tally() t.add_score('total') t.add_score('absorption') @@ -76,25 +81,37 @@ class DiffTallyTestHarness(PyAPITestHarness): t.add_nuclide('total') t.add_nuclide('U235') t.derivative = derivs[i] - self._input_set.tallies.add_tally(t) + self._input_set.tallies.append(t) # Cover an analog estimator. - for i in range(4): + for i in range(5): t = openmc.Tally() t.add_score('absorption') t.add_filter(filt_mats) t.estimator = 'analog' t.derivative = derivs[i] - self._input_set.tallies.add_tally(t) + self._input_set.tallies.append(t) - # And the special fission with energyout filter. - for i in range(4): + # Energyout filter and total nuclide for the density derivatives. + for i in range(2): t = openmc.Tally() t.add_score('nu-fission') t.add_filter(filt_mats) t.add_filter(filt_eout) + t.add_nuclide('total') + t.add_nuclide('U235') t.derivative = derivs[i] - self._input_set.tallies.add_tally(t) + self._input_set.tallies.append(t) + + # Energyout filter without total nuclide for other derivatives. + for i in range(2, 5): + t = openmc.Tally() + t.add_score('nu-fission') + t.add_filter(filt_mats) + t.add_filter(filt_eout) + t.add_nuclide('U235') + t.derivative = derivs[i] + self._input_set.tallies.append(t) self._input_set.export() From 7f2ab62523ce0aa55883f26294d1a391a7df9b18 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 21 Oct 2016 01:56:44 -0400 Subject: [PATCH 37/60] Update tests --- tests/test_diff_tally/inputs_true.dat | 2 +- tests/test_diff_tally/results_true.dat | 168 ++++++++++++------------- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index 0a23a2c0b..a82c8bca8 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -1 +1 @@ -7a33d6ea1df959736bf496316b31126523d0578b09a3e6c3440b9cb900e797f21009337e55bbaf90e24edfa6666c838615bc17be163eb062c85a7816fcaee4f9 \ No newline at end of file +58a47bc1cce52a90cb7d0ed5e8143fe0ac2a3208fb7b4c050647ab2c2f3486272250138b7e548b2bee912085b4a70d818833760e1f90e9ad6aa713caa12473bf \ No newline at end of file diff --git a/tests/test_diff_tally/results_true.dat b/tests/test_diff_tally/results_true.dat index 2380050a5..9342c5a0e 100644 --- a/tests/test_diff_tally/results_true.dat +++ b/tests/test_diff_tally/results_true.dat @@ -1,128 +1,128 @@ d_material,d_nuclide,d_variable,score,mean,std. dev. -1,,density,nu-fission,1.12e-02,5.75e-03 -1,,density,nu-fission,6.27e-03,1.86e-03 -1,,density,nu-fission,1.90e-02,9.78e-03 -1,,density,nu-fission,1.22e-02,5.45e-03 +1,,density,nu-fission,1.05e-02,3.37e-03 +1,,density,nu-fission,8.74e-03,3.45e-03 +1,,density,nu-fission,1.30e-02,4.36e-03 +1,,density,nu-fission,8.97e-03,4.48e-03 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,3.71e-01,1.76e-01 -1,O16,nuclide_density,nu-fission,4.32e-01,7.01e-01 +1,O16,nuclide_density,nu-fission,3.03e-01,4.44e-01 +1,O16,nuclide_density,nu-fission,4.94e-01,3.73e-01 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,2.03e+02,2.66e+01 -1,U235,nuclide_density,nu-fission,5.14e+02,1.31e+01 +1,U235,nuclide_density,nu-fission,2.27e+02,1.86e+01 +1,U235,nuclide_density,nu-fission,5.37e+02,4.27e+01 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,nu-fission,1.26e-05,1.05e-05 -1,,temperature,nu-fission,8.20e-06,7.06e-06 +1,,temperature,nu-fission,1.69e-06,9.41e-06 +1,,temperature,nu-fission,-3.74e-05,1.96e-05 1,,temperature,nu-fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,flux,-5.93e+00,8.02e-01 -3,,density,flux,-1.17e+01,1.10e+00 -1,,density,flux,-1.93e-01,5.38e-02 -1,,density,flux,-1.87e-01,6.13e-02 -1,O16,nuclide_density,flux,3.42e+00,6.84e+00 -1,O16,nuclide_density,flux,-4.63e+00,9.64e+00 -1,U235,nuclide_density,flux,-1.06e+03,1.25e+02 -1,U235,nuclide_density,flux,-9.00e+02,7.41e+01 -1,,temperature,flux,4.38e-05,1.90e-04 -1,,temperature,flux,1.99e-04,1.73e-04 -3,,density,total,-2.51e+00,3.83e-01 -3,,density,absorption,-7.85e-02,1.16e-01 -3,,density,fission,4.85e-02,6.57e-02 -3,,density,nu-fission,1.22e-01,1.73e-01 -3,,density,total,2.01e-02,4.42e-02 -3,,density,absorption,4.49e-02,4.26e-02 -3,,density,fission,4.30e-02,3.67e-02 -3,,density,nu-fission,1.05e-01,8.95e-02 -3,,density,total,7.29e+00,1.19e+00 -3,,density,absorption,1.39e-01,2.85e-02 +3,,density,flux,-7.17e+00,8.72e-01 +3,,density,flux,-1.43e+01,1.05e+00 +1,,density,flux,-3.06e-01,2.93e-02 +1,,density,flux,-2.98e-01,4.72e-02 +1,O16,nuclide_density,flux,-5.61e+00,1.02e+01 +1,O16,nuclide_density,flux,-3.41e-01,1.02e+01 +1,U235,nuclide_density,flux,-2.43e+03,1.53e+02 +1,U235,nuclide_density,flux,-2.36e+03,2.22e+02 +1,,temperature,flux,-1.35e-04,1.54e-04 +1,,temperature,flux,-1.94e-04,2.52e-04 +3,,density,total,-2.92e+00,3.41e-01 +3,,density,absorption,-1.20e-01,4.49e-02 +3,,density,fission,-1.06e-02,3.67e-02 +3,,density,nu-fission,-3.03e-02,8.97e-02 +3,,density,total,-3.40e-02,4.56e-02 +3,,density,absorption,-2.20e-03,4.26e-02 +3,,density,fission,3.33e-03,3.58e-02 +3,,density,nu-fission,7.83e-03,8.71e-02 +3,,density,total,6.37e+00,2.19e+00 +3,,density,absorption,1.18e-01,5.76e-02 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,total,0.00e+00,0.00e+00 3,,density,absorption,0.00e+00,0.00e+00 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,total,4.53e-01,3.58e-02 -1,,density,absorption,3.35e-02,7.74e-03 -1,,density,fission,1.09e-02,3.66e-03 -1,,density,nu-fission,2.93e-02,9.64e-03 -1,,density,total,1.18e-02,2.90e-03 -1,,density,absorption,6.94e-03,2.59e-03 -1,,density,fission,4.63e-03,2.07e-03 -1,,density,nu-fission,1.13e-02,5.04e-03 -1,,density,total,-2.03e-01,5.89e-02 -1,,density,absorption,-4.86e-03,6.33e-04 +1,,density,total,4.23e-01,1.29e-02 +1,,density,absorption,2.07e-02,4.64e-03 +1,,density,fission,8.69e-03,2.42e-03 +1,,density,nu-fission,2.19e-02,5.91e-03 +1,,density,total,1.38e-02,2.91e-03 +1,,density,absorption,9.11e-03,2.82e-03 +1,,density,fission,6.72e-03,2.37e-03 +1,,density,nu-fission,1.64e-02,5.78e-03 +1,,density,total,-3.98e-01,8.90e-02 +1,,density,absorption,-8.83e-03,2.05e-03 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,total,0.00e+00,0.00e+00 1,,density,absorption,0.00e+00,0.00e+00 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,total,4.71e+01,3.78e+00 -1,O16,nuclide_density,absorption,9.64e-01,7.50e-01 -1,O16,nuclide_density,fission,3.09e-01,2.99e-01 -1,O16,nuclide_density,nu-fission,8.08e-01,7.82e-01 -1,O16,nuclide_density,total,3.23e-01,2.77e-01 -1,O16,nuclide_density,absorption,2.86e-01,2.44e-01 -1,O16,nuclide_density,fission,1.74e-01,1.89e-01 -1,O16,nuclide_density,nu-fission,4.24e-01,4.61e-01 -1,O16,nuclide_density,total,1.01e+00,1.06e+01 -1,O16,nuclide_density,absorption,6.41e-02,1.52e-01 +1,O16,nuclide_density,total,4.60e+01,4.63e+00 +1,O16,nuclide_density,absorption,5.47e-01,6.81e-01 +1,O16,nuclide_density,fission,3.14e-01,3.63e-01 +1,O16,nuclide_density,nu-fission,7.49e-01,8.88e-01 +1,O16,nuclide_density,total,3.95e-01,4.83e-01 +1,O16,nuclide_density,absorption,4.18e-01,4.31e-01 +1,O16,nuclide_density,fission,3.50e-01,3.49e-01 +1,O16,nuclide_density,nu-fission,8.52e-01,8.51e-01 +1,O16,nuclide_density,total,6.03e+00,1.43e+01 +1,O16,nuclide_density,absorption,1.71e-01,2.75e-01 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O16,nuclide_density,total,0.00e+00,0.00e+00 1,O16,nuclide_density,absorption,0.00e+00,0.00e+00 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,total,-1.76e+02,5.81e+01 -1,U235,nuclide_density,absorption,1.33e+02,1.49e+01 -1,U235,nuclide_density,fission,1.97e+02,9.17e+00 -1,U235,nuclide_density,nu-fission,4.39e+02,2.36e+01 -1,U235,nuclide_density,total,4.79e+02,1.03e+01 -1,U235,nuclide_density,absorption,3.65e+02,8.53e+00 -1,U235,nuclide_density,fission,2.89e+02,6.85e+00 -1,U235,nuclide_density,nu-fission,7.05e+02,1.67e+01 -1,U235,nuclide_density,total,-1.74e+03,1.12e+02 -1,U235,nuclide_density,absorption,-4.22e+01,2.70e+00 +1,U235,nuclide_density,total,-5.91e+02,6.23e+01 +1,U235,nuclide_density,absorption,2.38e+02,1.22e+01 +1,U235,nuclide_density,fission,3.11e+02,8.54e+00 +1,U235,nuclide_density,nu-fission,7.59e+02,2.07e+01 +1,U235,nuclide_density,total,5.06e+02,1.04e+01 +1,U235,nuclide_density,absorption,3.90e+02,1.01e+01 +1,U235,nuclide_density,fission,3.11e+02,8.69e+00 +1,U235,nuclide_density,nu-fission,7.60e+02,2.11e+01 +1,U235,nuclide_density,total,-4.81e+03,2.90e+02 +1,U235,nuclide_density,absorption,-1.19e+02,5.73e+00 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U235,nuclide_density,total,0.00e+00,0.00e+00 1,U235,nuclide_density,absorption,0.00e+00,0.00e+00 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,total,1.91e-04,1.38e-04 -1,,temperature,absorption,7.60e-05,4.02e-05 -1,,temperature,fission,1.60e-05,1.40e-05 -1,,temperature,nu-fission,4.22e-05,3.60e-05 -1,,temperature,total,1.12e-05,1.37e-05 -1,,temperature,absorption,1.08e-05,1.26e-05 -1,,temperature,fission,8.52e-06,1.02e-05 -1,,temperature,nu-fission,2.08e-05,2.50e-05 -1,,temperature,total,3.14e-04,2.80e-04 -1,,temperature,absorption,5.46e-06,6.04e-06 +1,,temperature,total,6.14e-05,7.41e-05 +1,,temperature,absorption,1.36e-05,1.81e-05 +1,,temperature,fission,-1.97e-05,7.53e-06 +1,,temperature,nu-fission,-4.80e-05,1.84e-05 +1,,temperature,total,-2.32e-05,1.07e-05 +1,,temperature,absorption,-2.22e-05,9.83e-06 +1,,temperature,fission,-1.97e-05,7.53e-06 +1,,temperature,nu-fission,-4.81e-05,1.84e-05 +1,,temperature,total,-2.92e-04,3.88e-04 +1,,temperature,absorption,-4.89e-06,7.21e-06 1,,temperature,fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 1,,temperature,total,0.00e+00,0.00e+00 1,,temperature,absorption,0.00e+00,0.00e+00 1,,temperature,fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,absorption,-9.85e-02,8.35e-02 -3,,density,absorption,9.34e-02,3.83e-02 -1,,density,absorption,2.98e-02,6.51e-03 -1,,density,absorption,-2.83e-03,1.44e-03 -1,O16,nuclide_density,absorption,1.34e+00,4.23e-01 -1,O16,nuclide_density,absorption,5.15e-02,8.53e-02 -1,U235,nuclide_density,absorption,1.25e+02,2.55e+01 -1,U235,nuclide_density,absorption,-4.14e+01,4.30e+00 -1,,temperature,absorption,4.95e-05,2.86e-05 -1,,temperature,absorption,-9.35e-07,6.79e-06 -3,,density,nu-fission,4.60e-02,5.96e-02 -3,,density,nu-fission,3.87e-02,3.71e-02 -3,,density,nu-fission,8.85e-02,9.69e-02 -3,,density,nu-fission,4.16e-02,5.47e-02 +3,,density,absorption,-1.21e-01,6.43e-02 +3,,density,absorption,1.74e-01,6.67e-02 +1,,density,absorption,2.06e-02,3.05e-03 +1,,density,absorption,-9.56e-03,1.86e-03 +1,O16,nuclide_density,absorption,2.49e-01,6.73e-01 +1,O16,nuclide_density,absorption,2.89e-02,1.36e-01 +1,U235,nuclide_density,absorption,2.42e+02,1.74e+01 +1,U235,nuclide_density,absorption,-1.12e+02,1.48e+01 +1,,temperature,absorption,-5.27e-06,2.03e-05 +1,,temperature,absorption,-8.73e-06,7.87e-06 +3,,density,nu-fission,-2.62e-02,9.06e-02 +3,,density,nu-fission,-1.80e-02,8.91e-02 +3,,density,nu-fission,-3.13e-02,9.12e-02 +3,,density,nu-fission,-6.37e-03,9.48e-02 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 From dfe775ed856c7b7f4da8b72e691239a7ab498ce6 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 21 Oct 2016 02:09:11 -0400 Subject: [PATCH 38/60] Fix unallocated flux derivs on particle restart --- src/particle_restart.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index a1c32f723..7d6fd7c62 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -35,6 +35,7 @@ contains ! Initialize the particle to be tracked call p % initialize() + allocate(p % flux_derivs(size(tally_derivs))) ! Read in the restart information call read_particle_restart(p, previous_run_mode) From b9d9f9e838dc608826e58bdd6618c021c1a520f8 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 21 Oct 2016 02:23:46 -0400 Subject: [PATCH 39/60] Raise an error for diff talies with MG mode --- src/input_xml.F90 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index cb13623b8..d0289cbce 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2879,6 +2879,10 @@ contains call get_node_list(doc, "derivative", node_deriv_list) allocate(tally_derivs(get_list_size(node_deriv_list))) + ! Make sure this is not an MG run. + if (.not. run_CE .and. get_list_size(node_deriv_list) > 0) call & + fatal_error("Differential tallies not supported in multi-group mode") + ! Read derivative attributes. do i = 1, get_list_size(node_deriv_list) associate(deriv => tally_derivs(i)) From 9313d8720bbffff58c6143c327a5a363e887a095 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 21 Oct 2016 02:41:39 -0400 Subject: [PATCH 40/60] Remove test code; justify lack of wmp poly derivs --- src/cross_section.F90 | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/src/cross_section.F90 b/src/cross_section.F90 index 652b8b8a3..ffbfbe224 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -726,35 +726,6 @@ contains ! temperature. !=============================================================================== - subroutine multipole_deriv_eval_finite_difference(multipole, Emev, sqrtkT, & - sigT, sigA, sigF) - type(MultipoleArray), intent(in) :: multipole ! The windowed multipole - ! object to process. - real(8), intent(in) :: Emev ! The energy at which to - ! evaluate the cross section - ! derivative in MeV - real(8), intent(in) :: sqrtkT ! The temperature in the form - ! sqrt(kT (in MeV)), at which - ! to evaluate the XS. - real(8), intent(out) :: sigT ! Total cross section - real(8), intent(out) :: sigA ! Absorption cross section - real(8), intent(out) :: sigF ! Fission cross section - real(8), parameter :: T_DIFF = 10.0_8 - real(8) :: kT, sqrtkT_hi, sqrtkT_lo - real(8) :: sigT_hi, sigT_lo, sigA_hi, sigA_lo, sigF_hi, sigF_lo - - kT = sqrtkT**2 - sqrtkT_hi = sqrt(kT + K_BOLTZMANN*T_DIFF/2.0) - sqrtkT_lo = sqrt(kT - K_BOLTZMANN*T_DIFF/2.0) - - call multipole_eval(multipole, Emev, sqrtkT_hi, sigT_hi, sigA_hi, sigF_hi) - call multipole_eval(multipole, Emev, sqrtkT_lo, sigT_lo, sigA_lo, sigF_lo) - - sigT = (sigT_hi - sigT_lo) / T_DIFF - sigA = (sigA_hi - sigA_lo) / T_DIFF - sigF = (sigF_hi - sigF_lo) / T_DIFF - end subroutine multipole_deriv_eval_finite_difference - subroutine multipole_deriv_eval(multipole, Emev, sqrtkT_, sigT, sigA, sigF) type(MultipoleArray), intent(in) :: multipole ! The windowed multipole ! object to process. @@ -813,7 +784,10 @@ contains sigA = ZERO sigF = ZERO - ! TODO Polynomials + ! TODO Polynomials: Some of the curvefit polynomials Doppler broaden so + ! rigorously we should be computing the derivative of those. But in + ! practice, those derivatives are only large at very low energy and they + ! have no effect on reactor calculations. ! ========================================================================== ! Add the contribution from the poles in this window. From f0467e35f41fe49490de8f7abae6568f13c0ba1a Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 21 Oct 2016 02:56:15 -0400 Subject: [PATCH 41/60] Add derivative info to tallies.out --- src/output.F90 | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/output.F90 b/src/output.F90 index f188874d2..883165556 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -778,21 +778,26 @@ contains endif ! Write derivative information. - !if (allocated(t % deriv)) then - ! select case (t % deriv % variable) - ! case (DIFF_DENSITY) - ! write(unit=unit_tally, fmt="(' Density derivative Material ',A)") & - ! to_str(t % deriv % diff_material) - ! case (DIFF_NUCLIDE_DENSITY) - ! i_listing = nuclides(t % deriv % diff_nuclide) % listing - ! write(unit=unit_tally, fmt="(' Nuclide density derivative Material '& - ! &,A,' Nuclide ',A)") trim(to_str(t % deriv % diff_material)), & - ! trim(xs_listings(i_listing) % alias) - ! case default - ! call fatal_error("Differential tally dependent variable for tally " & - ! // trim(to_str(t % id)) // " not defined in output.F90.") - ! end select - !end if + if (t % deriv /= NONE) then + associate(deriv => tally_derivs(t % deriv)) + select case (deriv % variable) + case (DIFF_DENSITY) + write(unit=unit_tally, fmt="(' Density derivative Material ',A)") & + to_str(deriv % diff_material) + case (DIFF_NUCLIDE_DENSITY) + write(unit=unit_tally, fmt="(' Nuclide density derivative & + &Material ',A,' Nuclide ',A)") & + trim(to_str(deriv % diff_material)), & + trim(nuclides(deriv % diff_nuclide) % name) + case (DIFF_TEMPERATURE) + write(unit=unit_tally, fmt="(' Temperature derivative Material ',& + &A)") to_str(deriv % diff_material) + case default + call fatal_error("Differential tally dependent variable for tally "& + // trim(to_str(t % id)) // " not defined in output.F90.") + end select + end associate + end if ! Handle surface current tallies separately if (t % type == TALLY_SURFACE_CURRENT) then From d7971fcace0424e049d6624928a1e3c057c4e55b Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 21 Oct 2016 14:59:48 -0400 Subject: [PATCH 42/60] Add temperature derivative to docs --- docs/source/usersguide/input.rst | 17 +++++++++++------ src/relaxng/tallies.rnc | 4 +++- src/relaxng/tallies.rng | 8 ++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index b27577400..b12f914a4 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -2034,15 +2034,20 @@ the following attributes/sub-elements: A unique integer that can be used to identify the derivative. :variable: - The independent variable of the derivative. Accepted options are - "density" and "nuclide_density". A "density" derivative will give the + The independent variable of the derivative. Accepted options are "density", + "nuclide_density", and "temperature". A "density" derivative will give the derivative with respect to the density of the material in [g / cm^3]. A - "nuclide_density" derivative will give the derivative with respect to - the density of a particular nuclide in units of [atom / b / cm]. + "nuclide_density" derivative will give the derivative with respect to the + density of a particular nuclide in units of [atom / b / cm]. A + "temperature" derivative is with respect to a material temperature in units + of [K]. The temperature derivative requires windowed multipole to be + turned on. Note also that the temperature derivative only acconuts for + resolved resonance Doppler broadening. It does not account for thermal + expansion, S(a, b) scattering, resonance scattering, or unresolved Doppler + broadening. :material: - The perturbed material. (Necessary for both "density" and - "nuclide_density") + The perturbed material. (Necessary for all derivative types) :nuclide: The perturbed nuclide. (Necessary only for "nuclide_density") diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc index 4522adff5..2143c8e47 100644 --- a/src/relaxng/tallies.rnc +++ b/src/relaxng/tallies.rnc @@ -25,8 +25,10 @@ element tallies { | attribute variable { ( "nuclide_density" ) } ) & (element nuclide { xsd:string { maxLength = "12" } } - | attribute nuclide { xsd:string { maxLength = "12" } } ) + | attribute nuclide { xsd:string { maxLength = "12" } } ) | ) + (element variable { ( "temperature") } + | attribute variable { ( "temperature" ) } ) ) }* & diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng index 3f88b0760..fc60b8373 100644 --- a/src/relaxng/tallies.rng +++ b/src/relaxng/tallies.rng @@ -139,6 +139,14 @@ + + + temperature + + + temperature + + From 85501dcab72cce7aacf1264642b015de5c6ceb5a Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 30 Oct 2016 14:57:24 -0400 Subject: [PATCH 43/60] Revert to threadprivate global tally_derivs --- src/global.F90 | 1 + src/input_xml.F90 | 8 +++++++- src/particle_header.F90 | 3 --- src/particle_restart.F90 | 1 - src/simulation.F90 | 5 +---- src/tally.F90 | 35 +++++++++++++++++++++++------------ src/tally_header.F90 | 1 + src/tracking.F90 | 4 ++-- 8 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/global.F90 b/src/global.F90 index 96e93c370..dfdaf161a 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -185,6 +185,7 @@ module global ! Tally derivatives type(TallyDerivative), allocatable :: tally_derivs(:) +!$omp threadprivate(tally_derivs) ! Normalization for statistics integer :: n_realizations = 0 ! # of independent realizations diff --git a/src/input_xml.F90 b/src/input_xml.F90 index d0289cbce..02d0f95db 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2691,8 +2691,11 @@ contains filename = trim(path_input) // "tallies.xml" inquire(FILE=filename, EXIST=file_exists) if (.not. file_exists) then - ! We need to allocate tally_derivs to avoid segfaults + ! We need to allocate tally_derivs to avoid segfaults. Also needs to be + ! done in parallel because tally derivs are threadprivate. +!$omp parallel allocate(tally_derivs(0)) +!$omp end parallel ! Since a tallies.xml file is optional, no error is issued here return @@ -2876,8 +2879,11 @@ contains ! READ DATA FOR DERIVATIVES ! Get pointer list to XML nodes and allocate global array. + ! The array is threadprivate so it must be allocated in parallel. call get_node_list(doc, "derivative", node_deriv_list) +!$omp parallel allocate(tally_derivs(get_list_size(node_deriv_list))) +!$omp end parallel ! Make sure this is not an MG run. if (.not. run_CE .and. get_list_size(node_deriv_list) > 0) call & diff --git a/src/particle_header.F90 b/src/particle_header.F90 index ffb0617e4..53a503ce2 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -100,9 +100,6 @@ module particle_header integer(8) :: n_secondary = 0 type(Bank) :: secondary_bank(MAX_SECONDARY) - ! Flux (weight) derivatives for differential tallies - real(8), allocatable :: flux_derivs(:) - contains procedure :: initialize => initialize_particle procedure :: clear => clear_particle diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index 7d6fd7c62..a1c32f723 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -35,7 +35,6 @@ contains ! Initialize the particle to be tracked call p % initialize() - allocate(p % flux_derivs(size(tally_derivs))) ! Read in the restart information call read_particle_restart(p, previous_run_mode) diff --git a/src/simulation.F90 b/src/simulation.F90 index 312b56d82..93950b1f9 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -48,9 +48,6 @@ contains if (.not. restart_run) call initialize_source() - ! Allocate flux derivative array for differential tallies - allocate(p % flux_derivs(size(tally_derivs))) - ! Display header if (master) then if (run_mode == MODE_FIXEDSOURCE) then @@ -87,7 +84,7 @@ contains ! ==================================================================== ! LOOP OVER PARTICLES -!$omp parallel do schedule(static) firstprivate(p) +!$omp parallel do schedule(static) firstprivate(p) copyin(tally_derivs) PARTICLE_LOOP: do i_work = 1, work current_work = i_work diff --git a/src/tally.F90 b/src/tally.F90 index 606186b77..d17c8c3f9 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2775,9 +2775,9 @@ contains if (score == ZERO) return - flux_deriv = p % flux_derivs(t % deriv) - associate(deriv => tally_derivs(t % deriv)) + flux_deriv = deriv % flux_deriv + select case (tally_derivs(t % deriv) % variable) case (DIFF_DENSITY) @@ -3321,8 +3321,8 @@ contains !=============================================================================== subroutine score_track_derivative(p, distance) - type(particle), intent(inout) :: p - real(8), intent(in) :: distance ! Neutron flight distance + type(Particle), intent(in) :: p + real(8), intent(in) :: distance ! Neutron flight distance integer :: i, l real(8) :: dsigT, dsigA, dsigF @@ -3340,7 +3340,7 @@ contains ! phi = e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_rho) = - (d_Sigma_tot / d_rho) * dist ! (1 / phi) * (d_phi / d_rho) = - Sigma_tot / rho * dist - p % flux_derivs(i) = p % flux_derivs(i) & + deriv % flux_deriv = deriv % flux_deriv & - distance * material_xs % total / mat % density_gpcc end if end associate @@ -3351,7 +3351,7 @@ contains ! phi = e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_N) = - (d_Sigma_tot / d_N) * dist ! (1 / phi) * (d_phi / d_N) = - sigma_tot * dist - p % flux_derivs(i) = p % flux_derivs(i) & + deriv % flux_deriv = deriv % flux_deriv & - distance * micro_xs(deriv % diff_nuclide) % total end if end associate @@ -3366,7 +3366,7 @@ contains p % E <= nuc % multipole % end_E/1.0e6_8) then call multipole_deriv_eval(nuc % multipole, p % E, & p % sqrtkT, dsigT, dsigA, dsigF) - p % flux_derivs(i) = p % flux_derivs(i) & + deriv % flux_deriv = deriv % flux_deriv & - distance * dsigT * mat % atom_density(l) end if end associate @@ -3384,7 +3384,7 @@ contains !=============================================================================== subroutine score_collision_derivative(p) - type(particle), intent(inout) :: p + type(Particle), intent(in) :: p integer :: i, j, l real(8) :: dsigT, dsigA, dsigF @@ -3402,7 +3402,7 @@ contains ! phi = Sigma_MT ! (1 / phi) * (d_phi / d_rho) = (d_Sigma_MT / d_rho) / Sigma_MT ! (1 / phi) * (d_phi / d_rho) = 1 / rho - p % flux_derivs(i) = p % flux_derivs(i) & + deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % density_gpcc end if end associate @@ -3423,7 +3423,7 @@ contains ! (1 / phi) * (d_phi / d_N) = (d_Sigma_MT / d_N) / Sigma_MT ! (1 / phi) * (d_phi / d_N) = sigma_MT / Sigma_MT ! (1 / phi) * (d_phi / d_N) = 1 / N - p % flux_derivs(i) = p % flux_derivs(i) & + deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % atom_density(j) end if end associate @@ -3444,11 +3444,11 @@ contains p % sqrtkT, dsigT, dsigA, dsigF) select case(p % event) case (EVENT_SCATTER) - p % flux_derivs(i) = p % flux_derivs(i) + (dsigT - dsigA)& + deriv % flux_deriv = deriv % flux_deriv + (dsigT - dsigA)& / (micro_xs(mat % nuclide(l)) % total & - micro_xs(mat % nuclide(l)) % absorption) case (EVENT_ABSORB) - p % flux_derivs(i) = p % flux_derivs(i) & + deriv % flux_deriv = deriv % flux_deriv & + dsigA / micro_xs(mat % nuclide(l)) % absorption end select end if @@ -3461,6 +3461,17 @@ contains end do end subroutine score_collision_derivative +!=============================================================================== +! ZERO_FLUX_DERIVS Set the flux derivatives on differential tallies to zero. +!=============================================================================== + + subroutine zero_flux_derivs() + integer :: i + do i = 1, size(tally_derivs) + tally_derivs(i) % flux_deriv = ZERO + end do + end subroutine zero_flux_derivs + !=============================================================================== ! SYNCHRONIZE_TALLIES accumulates the sum of the contributions from each history ! within the batch to a new random variable diff --git a/src/tally_header.F90 b/src/tally_header.F90 index 5a80f249f..f30a40deb 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -25,6 +25,7 @@ module tally_header type TallyDerivative integer :: id + real(8) :: flux_deriv integer :: variable integer :: diff_material integer :: diff_nuclide diff --git a/src/tracking.F90 b/src/tracking.F90 index 8350d284a..a45f8e448 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -16,7 +16,7 @@ module tracking use tally, only: score_analog_tally, score_tracklength_tally, & score_collision_tally, score_surface_current, & score_track_derivative, & - score_collision_derivative + score_collision_derivative, zero_flux_derivs use track_output, only: initialize_particle_track, write_particle_track, & add_particle_track, finalize_particle_track @@ -66,7 +66,7 @@ contains endif ! Every particle starts with no accumulated flux derivative. - p % flux_derivs(:) = ZERO + if (active_tallies % size() > 0) call zero_flux_derivs() EVENT_LOOP: do ! If the cell hasn't been determined based on the particle's location, From 624723141e3cafd8f5d8f4a3647273292816e351 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 30 Oct 2016 15:31:19 -0400 Subject: [PATCH 44/60] Address #746 comments --- openmc/tally_derivative.py | 23 ++++++++++------------- src/input_xml.F90 | 24 +++++++++++++++--------- src/tally.F90 | 12 ++++++++++++ 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py index 0b16ad46f..3c48cf030 100644 --- a/openmc/tally_derivative.py +++ b/openmc/tally_derivative.py @@ -2,15 +2,13 @@ from __future__ import division import sys from numbers import Integral - from xml.etree import ElementTree as ET +from six import string_types + import openmc.checkvalue as cv -if sys.version_info[0] >= 3: - basestring = str - # "Static" variable for auto-generated TallyDerivative IDs AUTO_TALLY_DERIV_ID = 10000 @@ -35,7 +33,7 @@ class TallyDerivative(object): variable : str Accepted values are 'density', 'nuclide_density', and 'temperature' material : Integral - The perutrubed material + The perturubed material nuclide : str The perturbed nuclide. Only needed for 'nuclide_density' derivatives. Ex: 'Xe-135' @@ -134,23 +132,22 @@ class TallyDerivative(object): @variable.setter def variable(self, var): if var is not None: - cv.check_type('derivative variable', var, basestring) - if var not in ('density', 'nuclide_density', 'temperature'): - raise ValueError("A tally differential variable must be " - "'density', 'nuclide_density', or 'temperature'") - self._variable = var + cv.check_type('derivative variable', var, string_types) + cv.check_value('derivative variable', var, ('density', + 'nuclide_density', 'temperature')) + self._variable = var @material.setter def material(self, mat): if mat is not None: cv.check_type('derivative material', mat, Integral) - self._material = mat + self._material = mat @nuclide.setter def nuclide(self, nuc): if nuc is not None: - cv.check_type('derivative nuclide', nuc, basestring) - self._nuclide = nuc + cv.check_type('derivative nuclide', nuc, string_types) + self._nuclide = nuc def get_derivative_xml(self): """Return XML representation of the tally derivative diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 02d0f95db..f40bdb834 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2886,8 +2886,9 @@ contains !$omp end parallel ! Make sure this is not an MG run. - if (.not. run_CE .and. get_list_size(node_deriv_list) > 0) call & - fatal_error("Differential tallies not supported in multi-group mode") + if (.not. run_CE .and. get_list_size(node_deriv_list) > 0) then + call fatal_error("Differential tallies not supported in multi-group mode") + end if ! Read derivative attributes. do i = 1, get_list_size(node_deriv_list) @@ -2904,14 +2905,17 @@ contains end if ! Make sure the id is > 0. - if (deriv % id <= 0) call fatal_error(" IDs must be an & - &integer greater than zero") + if (deriv % id <= 0) then + call fatal_error(" IDs must be an integer greater than & + &zero") + end if ! Make sure this id has not already been used. do j = 1, i-1 - if (tally_derivs(j) % id == deriv % id) call fatal_error("Two or more& - & 's use the same unique ID: " & - // trim(to_str(deriv % id))) + if (tally_derivs(j) % id == deriv % id) then + call fatal_error("Two or more 's use the same unique & + &ID: " // trim(to_str(deriv % id))) + end if end do ! Read the independent variable name. @@ -3927,8 +3931,10 @@ contains t % deriv = j ! Only analog or collision estimators are supported for differential ! tallies. - if (t % estimator == ESTIMATOR_TRACKLENGTH) & - t % estimator = ESTIMATOR_COLLISION + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + t % estimator = ESTIMATOR_COLLISION + end if + ! We found the derivative we were looking for; exit the do loop. exit end if if (j == size(tally_derivs)) then diff --git a/src/tally.F90 b/src/tally.F90 index d17c8c3f9..8aa6c4ef0 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2861,9 +2861,11 @@ contains if (materials(p % material) % id == deriv % diff_material & .and. p % event_nuclide == deriv % diff_nuclide) then associate(mat => materials(p % material)) + ! Search for the index of the perturbed nuclide. do l = 1, mat % n_nuclides if (mat % nuclide(l) == deriv % diff_nuclide) exit end do + score = score * (flux_deriv & + ONE / mat % atom_density(l)) end associate @@ -2977,9 +2979,11 @@ contains if (materials(p % material) % id == deriv % diff_material .and. & micro_xs(p % event_nuclide) % total > ZERO) then associate(mat => materials(p % material)) + ! Search for the index of the perturbed nuclide. do l = 1, mat % n_nuclides if (mat % nuclide(l) == p % event_nuclide) exit end do + dsigT = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & @@ -3001,9 +3005,11 @@ contains (micro_xs(p % event_nuclide) % total & - micro_xs(p % event_nuclide) % absorption) > ZERO) then associate(mat => materials(p % material)) + ! Search for the index of the perturbed nuclide. do l = 1, mat % n_nuclides if (mat % nuclide(l) == p % event_nuclide) exit end do + dsigT = ZERO dsigA = ZERO associate (nuc => nuclides(p % event_nuclide)) @@ -3026,9 +3032,11 @@ contains if (materials(p % material) % id == deriv % diff_material .and. & micro_xs(p % event_nuclide) % absorption > ZERO) then associate(mat => materials(p % material)) + ! Search for the index of the perturbed nuclide. do l = 1, mat % n_nuclides if (mat % nuclide(l) == p % event_nuclide) exit end do + dsigA = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & @@ -3049,9 +3057,11 @@ contains if (materials(p % material) % id == deriv % diff_material .and. & micro_xs(p % event_nuclide) % fission > ZERO) then associate(mat => materials(p % material)) + ! Search for the index of the perturbed nuclide. do l = 1, mat % n_nuclides if (mat % nuclide(l) == p % event_nuclide) exit end do + dsigF = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & @@ -3072,9 +3082,11 @@ contains if (materials(p % material) % id == deriv % diff_material .and. & micro_xs(p % event_nuclide) % nu_fission > ZERO) then associate(mat => materials(p % material)) + ! Search for the index of the perturbed nuclide. do l = 1, mat % n_nuclides if (mat % nuclide(l) == p % event_nuclide) exit end do + dsigF = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & From 48678c92b9a46fddb88370f7ba1d3cf741e8e42c Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 30 Oct 2016 16:32:54 -0400 Subject: [PATCH 45/60] Show me your secrets, Travis --- src/tally.F90 | 3 + tests/run_tests.py | 8 ++ tests/test_diff_tally/inputs_true.dat | 2 +- tests/test_diff_tally/results_true.dat | 168 +++++++++++------------ tests/test_diff_tally/test_diff_tally.py | 2 +- tests/testing_harness.py | 4 + tests/travis.sh | 2 +- 7 files changed, 102 insertions(+), 87 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 8aa6c4ef0..503b6772b 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -3416,6 +3416,7 @@ contains ! (1 / phi) * (d_phi / d_rho) = 1 / rho deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % density_gpcc + write(*, *) 'dens', deriv % flux_deriv end if end associate @@ -3437,6 +3438,7 @@ contains ! (1 / phi) * (d_phi / d_N) = 1 / N deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % atom_density(j) + write(*, *) 'nucd', deriv % flux_deriv end if end associate @@ -3463,6 +3465,7 @@ contains deriv % flux_deriv = deriv % flux_deriv & + dsigA / micro_xs(mat % nuclide(l)) % absorption end select + write(*, *) 'temp', deriv % flux_deriv end if end associate end do diff --git a/tests/run_tests.py b/tests/run_tests.py index 28bedab0d..a1a32a0b7 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -38,6 +38,8 @@ parser.add_option("-u", "--update", action="store_true", dest="update", parser.add_option("-s", "--script", action="store_true", dest="script", help="Activate CTest scripting mode for coverage, valgrind\ and dashboard capability.") +parser.add_option('-v', '--verbose', action='store_true', dest='verbose', + help='Print all test results to stdout.') (options, args) = parser.parse_args() # Default compiler paths @@ -482,6 +484,12 @@ for key in iter(tests): logfilename = logfilename + '_{0}.log'.format(test.name) shutil.copy(logfile[0], logfilename) + # Print tests + if options.verbose: + if len(logfile) > 0: + with open(logfilename) as fh: + print(fh.read()) + # For coverage builds, use lcov to generate HTML output if test.coverage: if which('lcov') is None or which('genhtml') is None: diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index a82c8bca8..173998201 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -1 +1 @@ -58a47bc1cce52a90cb7d0ed5e8143fe0ac2a3208fb7b4c050647ab2c2f3486272250138b7e548b2bee912085b4a70d818833760e1f90e9ad6aa713caa12473bf \ No newline at end of file +6e7d555be9bb40c372932d6b60f06c2dc2bf4076c6aabd1fce64d98fdbda47aaabf155aee6830730e1c6fbae21e84c961d36ef18da652d43c0f36111b3cd3b80 \ No newline at end of file diff --git a/tests/test_diff_tally/results_true.dat b/tests/test_diff_tally/results_true.dat index 9342c5a0e..7062ec2ba 100644 --- a/tests/test_diff_tally/results_true.dat +++ b/tests/test_diff_tally/results_true.dat @@ -1,128 +1,128 @@ d_material,d_nuclide,d_variable,score,mean,std. dev. -1,,density,nu-fission,1.05e-02,3.37e-03 -1,,density,nu-fission,8.74e-03,3.45e-03 -1,,density,nu-fission,1.30e-02,4.36e-03 -1,,density,nu-fission,8.97e-03,4.48e-03 +1,,density,nu-fission,-2.29e-02,1.60e-02 +1,,density,nu-fission,-2.93e-02,1.78e-02 +1,,density,nu-fission,-1.20e-01,3.66e-02 +1,,density,nu-fission,-1.25e-01,3.36e-02 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,3.03e-01,4.44e-01 -1,O16,nuclide_density,nu-fission,4.94e-01,3.73e-01 +1,O16,nuclide_density,nu-fission,-2.09e+00,2.40e+00 +1,O16,nuclide_density,nu-fission,-6.76e+00,3.03e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,2.27e+02,1.86e+01 -1,U235,nuclide_density,nu-fission,5.37e+02,4.27e+01 +1,U235,nuclide_density,nu-fission,2.47e+02,9.53e+01 +1,U235,nuclide_density,nu-fission,2.24e+02,2.28e+02 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,nu-fission,1.69e-06,9.41e-06 -1,,temperature,nu-fission,-3.74e-05,1.96e-05 +1,,temperature,nu-fission,-1.77e-04,2.70e-04 +1,,temperature,nu-fission,-4.43e-04,2.77e-04 1,,temperature,nu-fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,flux,-7.17e+00,8.72e-01 -3,,density,flux,-1.43e+01,1.05e+00 -1,,density,flux,-3.06e-01,2.93e-02 -1,,density,flux,-2.98e-01,4.72e-02 -1,O16,nuclide_density,flux,-5.61e+00,1.02e+01 -1,O16,nuclide_density,flux,-3.41e-01,1.02e+01 -1,U235,nuclide_density,flux,-2.43e+03,1.53e+02 -1,U235,nuclide_density,flux,-2.36e+03,2.22e+02 -1,,temperature,flux,-1.35e-04,1.54e-04 -1,,temperature,flux,-1.94e-04,2.52e-04 -3,,density,total,-2.92e+00,3.41e-01 -3,,density,absorption,-1.20e-01,4.49e-02 -3,,density,fission,-1.06e-02,3.67e-02 -3,,density,nu-fission,-3.03e-02,8.97e-02 -3,,density,total,-3.40e-02,4.56e-02 -3,,density,absorption,-2.20e-03,4.26e-02 -3,,density,fission,3.33e-03,3.58e-02 -3,,density,nu-fission,7.83e-03,8.71e-02 -3,,density,total,6.37e+00,2.19e+00 -3,,density,absorption,1.18e-01,5.76e-02 +3,,density,flux,-9.23e-01,6.00e+00 +3,,density,flux,6.27e+00,6.44e+00 +1,,density,flux,-1.17e+00,2.12e-01 +1,,density,flux,-4.74e-01,4.05e-01 +1,O16,nuclide_density,flux,-5.61e+01,2.63e+01 +1,O16,nuclide_density,flux,-2.83e+01,4.48e+01 +1,U235,nuclide_density,flux,-3.21e+03,1.25e+03 +1,U235,nuclide_density,flux,-2.20e+03,7.78e+02 +1,,temperature,flux,-2.31e-03,1.54e-03 +1,,temperature,flux,-9.64e-04,1.50e-03 +3,,density,total,3.69e-01,2.52e+00 +3,,density,absorption,3.58e-01,3.72e-01 +3,,density,fission,2.70e-01,1.75e-01 +3,,density,nu-fission,6.52e-01,4.28e-01 +3,,density,total,3.72e-01,2.30e-01 +3,,density,absorption,3.63e-01,2.08e-01 +3,,density,fission,2.93e-01,1.71e-01 +3,,density,nu-fission,7.12e-01,4.17e-01 +3,,density,total,2.70e+01,6.62e+00 +3,,density,absorption,4.95e-01,1.51e-01 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,total,0.00e+00,0.00e+00 3,,density,absorption,0.00e+00,0.00e+00 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,total,4.23e-01,1.29e-02 -1,,density,absorption,2.07e-02,4.64e-03 -1,,density,fission,8.69e-03,2.42e-03 -1,,density,nu-fission,2.19e-02,5.91e-03 -1,,density,total,1.38e-02,2.91e-03 -1,,density,absorption,9.11e-03,2.82e-03 -1,,density,fission,6.72e-03,2.37e-03 -1,,density,nu-fission,1.64e-02,5.78e-03 -1,,density,total,-3.98e-01,8.90e-02 -1,,density,absorption,-8.83e-03,2.05e-03 +1,,density,total,-4.02e-02,7.34e-02 +1,,density,absorption,-9.92e-02,2.47e-02 +1,,density,fission,-5.73e-02,1.69e-02 +1,,density,nu-fission,-1.39e-01,4.11e-02 +1,,density,total,-7.20e-02,2.20e-02 +1,,density,absorption,-7.14e-02,2.11e-02 +1,,density,fission,-5.82e-02,1.71e-02 +1,,density,nu-fission,-1.42e-01,4.16e-02 +1,,density,total,-6.72e-01,5.72e-01 +1,,density,absorption,-1.44e-02,1.23e-02 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,total,0.00e+00,0.00e+00 1,,density,absorption,0.00e+00,0.00e+00 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,total,4.60e+01,4.63e+00 -1,O16,nuclide_density,absorption,5.47e-01,6.81e-01 -1,O16,nuclide_density,fission,3.14e-01,3.63e-01 -1,O16,nuclide_density,nu-fission,7.49e-01,8.88e-01 -1,O16,nuclide_density,total,3.95e-01,4.83e-01 -1,O16,nuclide_density,absorption,4.18e-01,4.31e-01 -1,O16,nuclide_density,fission,3.50e-01,3.49e-01 -1,O16,nuclide_density,nu-fission,8.52e-01,8.51e-01 -1,O16,nuclide_density,total,6.03e+00,1.43e+01 -1,O16,nuclide_density,absorption,1.71e-01,2.75e-01 +1,O16,nuclide_density,total,1.67e+01,1.41e+01 +1,O16,nuclide_density,absorption,-7.07e+00,3.32e+00 +1,O16,nuclide_density,fission,-3.84e+00,2.40e+00 +1,O16,nuclide_density,nu-fission,-9.42e+00,5.85e+00 +1,O16,nuclide_density,total,-4.67e+00,2.90e+00 +1,O16,nuclide_density,absorption,-4.33e+00,2.83e+00 +1,O16,nuclide_density,fission,-3.65e+00,2.42e+00 +1,O16,nuclide_density,nu-fission,-8.90e+00,5.90e+00 +1,O16,nuclide_density,total,-2.49e+01,6.00e+01 +1,O16,nuclide_density,absorption,-2.50e-01,9.96e-01 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O16,nuclide_density,total,0.00e+00,0.00e+00 1,O16,nuclide_density,absorption,0.00e+00,0.00e+00 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,total,-5.91e+02,6.23e+01 -1,U235,nuclide_density,absorption,2.38e+02,1.22e+01 -1,U235,nuclide_density,fission,3.11e+02,8.54e+00 -1,U235,nuclide_density,nu-fission,7.59e+02,2.07e+01 -1,U235,nuclide_density,total,5.06e+02,1.04e+01 -1,U235,nuclide_density,absorption,3.90e+02,1.01e+01 -1,U235,nuclide_density,fission,3.11e+02,8.69e+00 -1,U235,nuclide_density,nu-fission,7.60e+02,2.11e+01 -1,U235,nuclide_density,total,-4.81e+03,2.90e+02 -1,U235,nuclide_density,absorption,-1.19e+02,5.73e+00 +1,U235,nuclide_density,total,-9.93e+02,6.71e+02 +1,U235,nuclide_density,absorption,8.10e+01,1.51e+02 +1,U235,nuclide_density,fission,2.19e+02,9.08e+01 +1,U235,nuclide_density,nu-fission,5.34e+02,2.21e+02 +1,U235,nuclide_density,total,4.09e+02,9.76e+01 +1,U235,nuclide_density,absorption,2.96e+02,9.63e+01 +1,U235,nuclide_density,fission,2.21e+02,9.10e+01 +1,U235,nuclide_density,nu-fission,5.40e+02,2.22e+02 +1,U235,nuclide_density,total,-4.43e+03,2.01e+03 +1,U235,nuclide_density,absorption,-1.09e+02,5.87e+01 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U235,nuclide_density,total,0.00e+00,0.00e+00 1,U235,nuclide_density,absorption,0.00e+00,0.00e+00 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,total,6.14e-05,7.41e-05 -1,,temperature,absorption,1.36e-05,1.81e-05 -1,,temperature,fission,-1.97e-05,7.53e-06 -1,,temperature,nu-fission,-4.80e-05,1.84e-05 -1,,temperature,total,-2.32e-05,1.07e-05 -1,,temperature,absorption,-2.22e-05,9.83e-06 -1,,temperature,fission,-1.97e-05,7.53e-06 -1,,temperature,nu-fission,-4.81e-05,1.84e-05 -1,,temperature,total,-2.92e-04,3.88e-04 -1,,temperature,absorption,-4.89e-06,7.21e-06 +1,,temperature,total,-1.18e-03,8.09e-04 +1,,temperature,absorption,-3.65e-04,1.78e-04 +1,,temperature,fission,-2.22e-04,1.10e-04 +1,,temperature,nu-fission,-5.41e-04,2.69e-04 +1,,temperature,total,-3.36e-04,1.85e-04 +1,,temperature,absorption,-3.17e-04,1.73e-04 +1,,temperature,fission,-2.22e-04,1.10e-04 +1,,temperature,nu-fission,-5.41e-04,2.69e-04 +1,,temperature,total,-1.94e-03,2.26e-03 +1,,temperature,absorption,-4.80e-05,4.10e-05 1,,temperature,fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 1,,temperature,total,0.00e+00,0.00e+00 1,,temperature,absorption,0.00e+00,0.00e+00 1,,temperature,fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,absorption,-1.21e-01,6.43e-02 -3,,density,absorption,1.74e-01,6.67e-02 -1,,density,absorption,2.06e-02,3.05e-03 -1,,density,absorption,-9.56e-03,1.86e-03 -1,O16,nuclide_density,absorption,2.49e-01,6.73e-01 -1,O16,nuclide_density,absorption,2.89e-02,1.36e-01 -1,U235,nuclide_density,absorption,2.42e+02,1.74e+01 -1,U235,nuclide_density,absorption,-1.12e+02,1.48e+01 -1,,temperature,absorption,-5.27e-06,2.03e-05 -1,,temperature,absorption,-8.73e-06,7.87e-06 -3,,density,nu-fission,-2.62e-02,9.06e-02 -3,,density,nu-fission,-1.80e-02,8.91e-02 -3,,density,nu-fission,-3.13e-02,9.12e-02 -3,,density,nu-fission,-6.37e-03,9.48e-02 +3,,density,absorption,-3.13e-01,2.77e-01 +3,,density,absorption,7.16e-01,3.10e-01 +1,,density,absorption,-7.32e-02,1.62e-02 +1,,density,absorption,5.35e-03,7.84e-03 +1,O16,nuclide_density,absorption,-6.14e+00,4.05e+00 +1,O16,nuclide_density,absorption,1.12e+00,1.19e+00 +1,U235,nuclide_density,absorption,1.61e+02,1.81e+02 +1,U235,nuclide_density,absorption,-6.52e+01,3.42e+01 +1,,temperature,absorption,-4.02e-04,2.28e-04 +1,,temperature,absorption,-1.41e-06,3.96e-06 +3,,density,nu-fission,1.23e-01,1.54e-01 +3,,density,nu-fission,1.23e-01,1.54e-01 +3,,density,nu-fission,-3.86e-01,2.25e-01 +3,,density,nu-fission,-3.78e-01,2.19e-01 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index ce5b4a68e..17774e400 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -22,7 +22,7 @@ class DiffTallyTestHarness(PyAPITestHarness): # Set settings explicitly self._input_set.settings.batches = 5 self._input_set.settings.inactive = 0 - self._input_set.settings.particles = 400 + self._input_set.settings.particles = 10 self._input_set.settings.source = openmc.Source(space=openmc.stats.Box( [-160, -160, -183], [160, 160, 183])) self._input_set.settings.temperature['multipole'] = True diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 150d124c8..9aa7b5566 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -129,6 +129,10 @@ class TestHarness(object): compare = filecmp.cmp('results_test.dat', 'results_true.dat') if not compare: os.rename('results_test.dat', 'results_error.dat') + with open('results_error.dat') as fh: print(fh.read()) + from subprocess import Popen + p = Popen(('diff', 'results_error.dat', 'results_true.dat')) + p.wait() assert compare, 'Results do not agree.' def _cleanup(self): diff --git a/tests/travis.sh b/tests/travis.sh index 443e951cc..3dd3e5e66 100755 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -5,7 +5,7 @@ set -ev # Run all debug tests ./check_source.py if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - ./run_tests.py -C "^hdf5-debug$|^omp-hdf5-debug|^mpi-hdf5-debug|^phdf5-debug$|^phdf5-omp-debug$" -j 2 -s + ./run_tests.py -C "^hdf5-debug$|^omp-hdf5-debug|^mpi-hdf5-debug|^phdf5-debug$|^phdf5-omp-debug$" -j 2 -s -R "diff" -v else ./run_tests.py -C "^hdf5-debug$" -j 2 fi From dde18cb6f1bc02d88900a2e07ea31ad4fb2f29e6 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 2 Nov 2016 19:33:11 -0400 Subject: [PATCH 46/60] Revert "Show me your secrets, Travis" This reverts commit 48678c92b9a46fddb88370f7ba1d3cf741e8e42c. --- src/tally.F90 | 3 - tests/run_tests.py | 8 -- tests/test_diff_tally/inputs_true.dat | 2 +- tests/test_diff_tally/results_true.dat | 168 +++++++++++------------ tests/test_diff_tally/test_diff_tally.py | 2 +- tests/testing_harness.py | 4 - tests/travis.sh | 2 +- 7 files changed, 87 insertions(+), 102 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 503b6772b..8aa6c4ef0 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -3416,7 +3416,6 @@ contains ! (1 / phi) * (d_phi / d_rho) = 1 / rho deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % density_gpcc - write(*, *) 'dens', deriv % flux_deriv end if end associate @@ -3438,7 +3437,6 @@ contains ! (1 / phi) * (d_phi / d_N) = 1 / N deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % atom_density(j) - write(*, *) 'nucd', deriv % flux_deriv end if end associate @@ -3465,7 +3463,6 @@ contains deriv % flux_deriv = deriv % flux_deriv & + dsigA / micro_xs(mat % nuclide(l)) % absorption end select - write(*, *) 'temp', deriv % flux_deriv end if end associate end do diff --git a/tests/run_tests.py b/tests/run_tests.py index a1a32a0b7..28bedab0d 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -38,8 +38,6 @@ parser.add_option("-u", "--update", action="store_true", dest="update", parser.add_option("-s", "--script", action="store_true", dest="script", help="Activate CTest scripting mode for coverage, valgrind\ and dashboard capability.") -parser.add_option('-v', '--verbose', action='store_true', dest='verbose', - help='Print all test results to stdout.') (options, args) = parser.parse_args() # Default compiler paths @@ -484,12 +482,6 @@ for key in iter(tests): logfilename = logfilename + '_{0}.log'.format(test.name) shutil.copy(logfile[0], logfilename) - # Print tests - if options.verbose: - if len(logfile) > 0: - with open(logfilename) as fh: - print(fh.read()) - # For coverage builds, use lcov to generate HTML output if test.coverage: if which('lcov') is None or which('genhtml') is None: diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index 173998201..a82c8bca8 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -1 +1 @@ -6e7d555be9bb40c372932d6b60f06c2dc2bf4076c6aabd1fce64d98fdbda47aaabf155aee6830730e1c6fbae21e84c961d36ef18da652d43c0f36111b3cd3b80 \ No newline at end of file +58a47bc1cce52a90cb7d0ed5e8143fe0ac2a3208fb7b4c050647ab2c2f3486272250138b7e548b2bee912085b4a70d818833760e1f90e9ad6aa713caa12473bf \ No newline at end of file diff --git a/tests/test_diff_tally/results_true.dat b/tests/test_diff_tally/results_true.dat index 7062ec2ba..9342c5a0e 100644 --- a/tests/test_diff_tally/results_true.dat +++ b/tests/test_diff_tally/results_true.dat @@ -1,128 +1,128 @@ d_material,d_nuclide,d_variable,score,mean,std. dev. -1,,density,nu-fission,-2.29e-02,1.60e-02 -1,,density,nu-fission,-2.93e-02,1.78e-02 -1,,density,nu-fission,-1.20e-01,3.66e-02 -1,,density,nu-fission,-1.25e-01,3.36e-02 +1,,density,nu-fission,1.05e-02,3.37e-03 +1,,density,nu-fission,8.74e-03,3.45e-03 +1,,density,nu-fission,1.30e-02,4.36e-03 +1,,density,nu-fission,8.97e-03,4.48e-03 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,-2.09e+00,2.40e+00 -1,O16,nuclide_density,nu-fission,-6.76e+00,3.03e+00 +1,O16,nuclide_density,nu-fission,3.03e-01,4.44e-01 +1,O16,nuclide_density,nu-fission,4.94e-01,3.73e-01 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,2.47e+02,9.53e+01 -1,U235,nuclide_density,nu-fission,2.24e+02,2.28e+02 +1,U235,nuclide_density,nu-fission,2.27e+02,1.86e+01 +1,U235,nuclide_density,nu-fission,5.37e+02,4.27e+01 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,nu-fission,-1.77e-04,2.70e-04 -1,,temperature,nu-fission,-4.43e-04,2.77e-04 +1,,temperature,nu-fission,1.69e-06,9.41e-06 +1,,temperature,nu-fission,-3.74e-05,1.96e-05 1,,temperature,nu-fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,flux,-9.23e-01,6.00e+00 -3,,density,flux,6.27e+00,6.44e+00 -1,,density,flux,-1.17e+00,2.12e-01 -1,,density,flux,-4.74e-01,4.05e-01 -1,O16,nuclide_density,flux,-5.61e+01,2.63e+01 -1,O16,nuclide_density,flux,-2.83e+01,4.48e+01 -1,U235,nuclide_density,flux,-3.21e+03,1.25e+03 -1,U235,nuclide_density,flux,-2.20e+03,7.78e+02 -1,,temperature,flux,-2.31e-03,1.54e-03 -1,,temperature,flux,-9.64e-04,1.50e-03 -3,,density,total,3.69e-01,2.52e+00 -3,,density,absorption,3.58e-01,3.72e-01 -3,,density,fission,2.70e-01,1.75e-01 -3,,density,nu-fission,6.52e-01,4.28e-01 -3,,density,total,3.72e-01,2.30e-01 -3,,density,absorption,3.63e-01,2.08e-01 -3,,density,fission,2.93e-01,1.71e-01 -3,,density,nu-fission,7.12e-01,4.17e-01 -3,,density,total,2.70e+01,6.62e+00 -3,,density,absorption,4.95e-01,1.51e-01 +3,,density,flux,-7.17e+00,8.72e-01 +3,,density,flux,-1.43e+01,1.05e+00 +1,,density,flux,-3.06e-01,2.93e-02 +1,,density,flux,-2.98e-01,4.72e-02 +1,O16,nuclide_density,flux,-5.61e+00,1.02e+01 +1,O16,nuclide_density,flux,-3.41e-01,1.02e+01 +1,U235,nuclide_density,flux,-2.43e+03,1.53e+02 +1,U235,nuclide_density,flux,-2.36e+03,2.22e+02 +1,,temperature,flux,-1.35e-04,1.54e-04 +1,,temperature,flux,-1.94e-04,2.52e-04 +3,,density,total,-2.92e+00,3.41e-01 +3,,density,absorption,-1.20e-01,4.49e-02 +3,,density,fission,-1.06e-02,3.67e-02 +3,,density,nu-fission,-3.03e-02,8.97e-02 +3,,density,total,-3.40e-02,4.56e-02 +3,,density,absorption,-2.20e-03,4.26e-02 +3,,density,fission,3.33e-03,3.58e-02 +3,,density,nu-fission,7.83e-03,8.71e-02 +3,,density,total,6.37e+00,2.19e+00 +3,,density,absorption,1.18e-01,5.76e-02 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,total,0.00e+00,0.00e+00 3,,density,absorption,0.00e+00,0.00e+00 3,,density,fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,total,-4.02e-02,7.34e-02 -1,,density,absorption,-9.92e-02,2.47e-02 -1,,density,fission,-5.73e-02,1.69e-02 -1,,density,nu-fission,-1.39e-01,4.11e-02 -1,,density,total,-7.20e-02,2.20e-02 -1,,density,absorption,-7.14e-02,2.11e-02 -1,,density,fission,-5.82e-02,1.71e-02 -1,,density,nu-fission,-1.42e-01,4.16e-02 -1,,density,total,-6.72e-01,5.72e-01 -1,,density,absorption,-1.44e-02,1.23e-02 +1,,density,total,4.23e-01,1.29e-02 +1,,density,absorption,2.07e-02,4.64e-03 +1,,density,fission,8.69e-03,2.42e-03 +1,,density,nu-fission,2.19e-02,5.91e-03 +1,,density,total,1.38e-02,2.91e-03 +1,,density,absorption,9.11e-03,2.82e-03 +1,,density,fission,6.72e-03,2.37e-03 +1,,density,nu-fission,1.64e-02,5.78e-03 +1,,density,total,-3.98e-01,8.90e-02 +1,,density,absorption,-8.83e-03,2.05e-03 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 1,,density,total,0.00e+00,0.00e+00 1,,density,absorption,0.00e+00,0.00e+00 1,,density,fission,0.00e+00,0.00e+00 1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,total,1.67e+01,1.41e+01 -1,O16,nuclide_density,absorption,-7.07e+00,3.32e+00 -1,O16,nuclide_density,fission,-3.84e+00,2.40e+00 -1,O16,nuclide_density,nu-fission,-9.42e+00,5.85e+00 -1,O16,nuclide_density,total,-4.67e+00,2.90e+00 -1,O16,nuclide_density,absorption,-4.33e+00,2.83e+00 -1,O16,nuclide_density,fission,-3.65e+00,2.42e+00 -1,O16,nuclide_density,nu-fission,-8.90e+00,5.90e+00 -1,O16,nuclide_density,total,-2.49e+01,6.00e+01 -1,O16,nuclide_density,absorption,-2.50e-01,9.96e-01 +1,O16,nuclide_density,total,4.60e+01,4.63e+00 +1,O16,nuclide_density,absorption,5.47e-01,6.81e-01 +1,O16,nuclide_density,fission,3.14e-01,3.63e-01 +1,O16,nuclide_density,nu-fission,7.49e-01,8.88e-01 +1,O16,nuclide_density,total,3.95e-01,4.83e-01 +1,O16,nuclide_density,absorption,4.18e-01,4.31e-01 +1,O16,nuclide_density,fission,3.50e-01,3.49e-01 +1,O16,nuclide_density,nu-fission,8.52e-01,8.51e-01 +1,O16,nuclide_density,total,6.03e+00,1.43e+01 +1,O16,nuclide_density,absorption,1.71e-01,2.75e-01 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,O16,nuclide_density,total,0.00e+00,0.00e+00 1,O16,nuclide_density,absorption,0.00e+00,0.00e+00 1,O16,nuclide_density,fission,0.00e+00,0.00e+00 1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,total,-9.93e+02,6.71e+02 -1,U235,nuclide_density,absorption,8.10e+01,1.51e+02 -1,U235,nuclide_density,fission,2.19e+02,9.08e+01 -1,U235,nuclide_density,nu-fission,5.34e+02,2.21e+02 -1,U235,nuclide_density,total,4.09e+02,9.76e+01 -1,U235,nuclide_density,absorption,2.96e+02,9.63e+01 -1,U235,nuclide_density,fission,2.21e+02,9.10e+01 -1,U235,nuclide_density,nu-fission,5.40e+02,2.22e+02 -1,U235,nuclide_density,total,-4.43e+03,2.01e+03 -1,U235,nuclide_density,absorption,-1.09e+02,5.87e+01 +1,U235,nuclide_density,total,-5.91e+02,6.23e+01 +1,U235,nuclide_density,absorption,2.38e+02,1.22e+01 +1,U235,nuclide_density,fission,3.11e+02,8.54e+00 +1,U235,nuclide_density,nu-fission,7.59e+02,2.07e+01 +1,U235,nuclide_density,total,5.06e+02,1.04e+01 +1,U235,nuclide_density,absorption,3.90e+02,1.01e+01 +1,U235,nuclide_density,fission,3.11e+02,8.69e+00 +1,U235,nuclide_density,nu-fission,7.60e+02,2.11e+01 +1,U235,nuclide_density,total,-4.81e+03,2.90e+02 +1,U235,nuclide_density,absorption,-1.19e+02,5.73e+00 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 1,U235,nuclide_density,total,0.00e+00,0.00e+00 1,U235,nuclide_density,absorption,0.00e+00,0.00e+00 1,U235,nuclide_density,fission,0.00e+00,0.00e+00 1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,total,-1.18e-03,8.09e-04 -1,,temperature,absorption,-3.65e-04,1.78e-04 -1,,temperature,fission,-2.22e-04,1.10e-04 -1,,temperature,nu-fission,-5.41e-04,2.69e-04 -1,,temperature,total,-3.36e-04,1.85e-04 -1,,temperature,absorption,-3.17e-04,1.73e-04 -1,,temperature,fission,-2.22e-04,1.10e-04 -1,,temperature,nu-fission,-5.41e-04,2.69e-04 -1,,temperature,total,-1.94e-03,2.26e-03 -1,,temperature,absorption,-4.80e-05,4.10e-05 +1,,temperature,total,6.14e-05,7.41e-05 +1,,temperature,absorption,1.36e-05,1.81e-05 +1,,temperature,fission,-1.97e-05,7.53e-06 +1,,temperature,nu-fission,-4.80e-05,1.84e-05 +1,,temperature,total,-2.32e-05,1.07e-05 +1,,temperature,absorption,-2.22e-05,9.83e-06 +1,,temperature,fission,-1.97e-05,7.53e-06 +1,,temperature,nu-fission,-4.81e-05,1.84e-05 +1,,temperature,total,-2.92e-04,3.88e-04 +1,,temperature,absorption,-4.89e-06,7.21e-06 1,,temperature,fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 1,,temperature,total,0.00e+00,0.00e+00 1,,temperature,absorption,0.00e+00,0.00e+00 1,,temperature,fission,0.00e+00,0.00e+00 1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,absorption,-3.13e-01,2.77e-01 -3,,density,absorption,7.16e-01,3.10e-01 -1,,density,absorption,-7.32e-02,1.62e-02 -1,,density,absorption,5.35e-03,7.84e-03 -1,O16,nuclide_density,absorption,-6.14e+00,4.05e+00 -1,O16,nuclide_density,absorption,1.12e+00,1.19e+00 -1,U235,nuclide_density,absorption,1.61e+02,1.81e+02 -1,U235,nuclide_density,absorption,-6.52e+01,3.42e+01 -1,,temperature,absorption,-4.02e-04,2.28e-04 -1,,temperature,absorption,-1.41e-06,3.96e-06 -3,,density,nu-fission,1.23e-01,1.54e-01 -3,,density,nu-fission,1.23e-01,1.54e-01 -3,,density,nu-fission,-3.86e-01,2.25e-01 -3,,density,nu-fission,-3.78e-01,2.19e-01 +3,,density,absorption,-1.21e-01,6.43e-02 +3,,density,absorption,1.74e-01,6.67e-02 +1,,density,absorption,2.06e-02,3.05e-03 +1,,density,absorption,-9.56e-03,1.86e-03 +1,O16,nuclide_density,absorption,2.49e-01,6.73e-01 +1,O16,nuclide_density,absorption,2.89e-02,1.36e-01 +1,U235,nuclide_density,absorption,2.42e+02,1.74e+01 +1,U235,nuclide_density,absorption,-1.12e+02,1.48e+01 +1,,temperature,absorption,-5.27e-06,2.03e-05 +1,,temperature,absorption,-8.73e-06,7.87e-06 +3,,density,nu-fission,-2.62e-02,9.06e-02 +3,,density,nu-fission,-1.80e-02,8.91e-02 +3,,density,nu-fission,-3.13e-02,9.12e-02 +3,,density,nu-fission,-6.37e-03,9.48e-02 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 3,,density,nu-fission,0.00e+00,0.00e+00 diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index 17774e400..ce5b4a68e 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -22,7 +22,7 @@ class DiffTallyTestHarness(PyAPITestHarness): # Set settings explicitly self._input_set.settings.batches = 5 self._input_set.settings.inactive = 0 - self._input_set.settings.particles = 10 + self._input_set.settings.particles = 400 self._input_set.settings.source = openmc.Source(space=openmc.stats.Box( [-160, -160, -183], [160, 160, 183])) self._input_set.settings.temperature['multipole'] = True diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 9aa7b5566..150d124c8 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -129,10 +129,6 @@ class TestHarness(object): compare = filecmp.cmp('results_test.dat', 'results_true.dat') if not compare: os.rename('results_test.dat', 'results_error.dat') - with open('results_error.dat') as fh: print(fh.read()) - from subprocess import Popen - p = Popen(('diff', 'results_error.dat', 'results_true.dat')) - p.wait() assert compare, 'Results do not agree.' def _cleanup(self): diff --git a/tests/travis.sh b/tests/travis.sh index 3dd3e5e66..443e951cc 100755 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -5,7 +5,7 @@ set -ev # Run all debug tests ./check_source.py if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - ./run_tests.py -C "^hdf5-debug$|^omp-hdf5-debug|^mpi-hdf5-debug|^phdf5-debug$|^phdf5-omp-debug$" -j 2 -s -R "diff" -v + ./run_tests.py -C "^hdf5-debug$|^omp-hdf5-debug|^mpi-hdf5-debug|^phdf5-debug$|^phdf5-omp-debug$" -j 2 -s else ./run_tests.py -C "^hdf5-debug$" -j 2 fi From c10859ae024dde5e5ad7efd086522cb49d82f764 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 3 Nov 2016 17:21:12 -0400 Subject: [PATCH 47/60] Move diff tallies from MeV to eV --- src/cross_section.F90 | 28 ++++------ src/tally.F90 | 68 ++++++++++++------------ tests/test_diff_tally/inputs_true.dat | 2 +- tests/test_diff_tally/test_diff_tally.py | 2 +- 4 files changed, 45 insertions(+), 55 deletions(-) diff --git a/src/cross_section.F90 b/src/cross_section.F90 index 5aac3b837..39552a716 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -712,15 +712,14 @@ contains ! temperature. !=============================================================================== - subroutine multipole_deriv_eval(multipole, Emev, sqrtkT_, sigT, sigA, sigF) + subroutine multipole_deriv_eval(multipole, E, sqrtkT, sigT, sigA, sigF) type(MultipoleArray), intent(in) :: multipole ! The windowed multipole ! object to process. - real(8), intent(in) :: Emev ! The energy at which to + real(8), intent(in) :: E ! The energy at which to ! evaluate the cross section - ! in MeV - real(8), intent(in) :: sqrtkT_ ! The temperature in the form - ! sqrt(kT (in MeV)), at which - ! to evaluate the XS. + real(8), intent(in) :: sqrtkT ! The temperature in the form + ! sqrt(kT), at which to + ! evaluate the XS. real(8), intent(out) :: sigT ! Total cross section real(8), intent(out) :: sigA ! Absorption cross section real(8), intent(out) :: sigF ! Fission cross section @@ -730,8 +729,6 @@ contains real(8) :: sqrtE ! sqrt(E), eV real(8) :: invE ! 1/E, eV real(8) :: dopp ! sqrt(atomic weight ratio / kT) - real(8) :: E ! energy, eV - real(8) :: sqrtkT ! sqrt(kT (in eV)) integer :: i_pole ! index of pole integer :: i_window ! index of window integer :: startw ! window start pointer (for poles) @@ -741,15 +738,11 @@ contains ! ========================================================================== ! Bookkeeping - ! Convert to eV. - E = Emev * 1.0e6_8 - sqrtkT = sqrtkT_ * 1.0e3_8 - ! Define some frequently used variables. sqrtE = sqrt(E) invE = ONE / E dopp = multipole % sqrtAWR / sqrtkT - T = sqrtkT_**2 / K_BOLTZMANN + T = sqrtkT**2 / K_BOLTZMANN if (sqrtkT == ZERO) call fatal_error("Windowed multipole temperature & &derivatives are not implemented for 0 Kelvin cross sections.") @@ -795,12 +788,9 @@ contains sigF = sigF + real(multipole % data(RM_RF, i_pole) * w_val) end if end do - sigT = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN*1.0e6_8) * T**(-1.5)& - * sigT - sigA = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN*1.0e6_8) * T**(-1.5)& - * sigA - sigF = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN*1.0e6_8) * T**(-1.5)& - * sigF + sigT = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN) * T**(-1.5) * sigT + sigA = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN) * T**(-1.5) * sigA + sigF = -HALF*multipole % sqrtAWR / sqrt(K_BOLTZMANN) * T**(-1.5) * sigF end if end subroutine multipole_deriv_eval diff --git a/src/tally.F90 b/src/tally.F90 index e99d6072a..f3cd015f7 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2984,8 +2984,8 @@ contains dsigT = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3011,8 +3011,8 @@ contains dsigA = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3037,8 +3037,8 @@ contains dsigA = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3062,8 +3062,8 @@ contains dsigF = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3087,8 +3087,8 @@ contains dsigF = ZERO associate (nuc => nuclides(p % event_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3123,8 +3123,8 @@ contains do l = 1, mat % n_nuclides associate (nuc => nuclides(mat % nuclide(l))) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E .and. & micro_xs(mat % nuclide(l)) % total > ZERO) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) @@ -3140,8 +3140,8 @@ contains dsigT = ZERO associate (nuc => nuclides(i_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3161,8 +3161,8 @@ contains do l = 1, mat % n_nuclides associate (nuc => nuclides(mat % nuclide(l))) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E .and. & (micro_xs(mat % nuclide(l)) % total & - micro_xs(mat % nuclide(l)) % absorption) > ZERO) then call multipole_deriv_eval(nuc % multipole, p % last_E, & @@ -3182,8 +3182,8 @@ contains dsigA = ZERO associate (nuc => nuclides(i_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3204,8 +3204,8 @@ contains do l = 1, mat % n_nuclides associate (nuc => nuclides(mat % nuclide(l))) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E .and. & micro_xs(mat % nuclide(l)) % absorption > ZERO) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) @@ -3221,8 +3221,8 @@ contains dsigA = ZERO associate (nuc => nuclides(i_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3242,8 +3242,8 @@ contains do l = 1, mat % n_nuclides associate (nuc => nuclides(mat % nuclide(l))) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E .and. & micro_xs(mat % nuclide(l)) % fission > ZERO) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) @@ -3259,8 +3259,8 @@ contains dsigF = ZERO associate (nuc => nuclides(i_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3280,8 +3280,8 @@ contains do l = 1, mat % n_nuclides associate (nuc => nuclides(mat % nuclide(l))) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8 .and. & + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E .and. & micro_xs(mat % nuclide(l)) % nu_fission > ZERO) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) @@ -3299,8 +3299,8 @@ contains dsigF = ZERO associate (nuc => nuclides(i_nuclide)) if (nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) end if @@ -3371,8 +3371,8 @@ contains do l=1, mat % n_nuclides associate (nuc => nuclides(mat % nuclide(l))) if (nuc % mp_present .and. & - p % E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % E <= nuc % multipole % end_E/1.0e6_8) then + p % E >= nuc % multipole % start_E .and. & + p % E <= nuc % multipole % end_E) then call multipole_deriv_eval(nuc % multipole, p % E, & p % sqrtkT, dsigT, dsigA, dsigF) deriv % flux_deriv = deriv % flux_deriv & @@ -3444,8 +3444,8 @@ contains associate (nuc => nuclides(mat % nuclide(l))) if (mat % nuclide(l) == p % event_nuclide .and. & nuc % mp_present .and. & - p % last_E >= nuc % multipole % start_E/1.0e6_8 .and. & - p % last_E <= nuc % multipole % end_E/1.0e6_8) then + p % last_E >= nuc % multipole % start_E .and. & + p % last_E <= nuc % multipole % end_E) then ! phi = Sigma_MT ! (1 / phi) * (d_phi / d_T) = (d_Sigma_MT / d_T) / Sigma_MT ! (1 / phi) * (d_phi / d_T) = (d_sigma_MT / d_T) / sigma_MT diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index a82c8bca8..f82b5d8f0 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -1 +1 @@ -58a47bc1cce52a90cb7d0ed5e8143fe0ac2a3208fb7b4c050647ab2c2f3486272250138b7e548b2bee912085b4a70d818833760e1f90e9ad6aa713caa12473bf \ No newline at end of file +be155010540ca076356596aef8511edd58c91772a5e956e5af77437a39ce3d238b91b57df30c2d599fc6e01c887bf73897ee8ed91425c2d475d97202689c2b88 \ No newline at end of file diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index ce5b4a68e..5e34fd886 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -30,7 +30,7 @@ class DiffTallyTestHarness(PyAPITestHarness): self._input_set.tallies = openmc.Tallies() filt_mats = openmc.MaterialFilter((1, 3)) - filt_eout = openmc.EnergyoutFilter((0.0, 1.0, 20.0)) + filt_eout = openmc.EnergyoutFilter((0.0, 1.0e6, 20.0e6)) # We want density derivatives for both water and fuel to get coverage # for both fissile and non-fissile materials. From 225687842379cc264184734a9d4c4f1aca0589e9 Mon Sep 17 00:00:00 2001 From: Sam Shaner Date: Sat, 5 Nov 2016 06:55:22 -0400 Subject: [PATCH 48/60] updated failing tests --- .../inputs_true.dat | 2 +- .../results_true.dat | 27 ++++ .../inputs_true.dat | 2 +- .../results_true.dat | 9 ++ tests/test_mgxs_library_hdf5/inputs_true.dat | 2 +- tests/test_mgxs_library_hdf5/results_true.dat | 120 ++++++++++++++++++ tests/test_mgxs_library_mesh/inputs_true.dat | 2 +- tests/test_mgxs_library_mesh/results_true.dat | 34 ++++- .../inputs_true.dat | 2 +- .../results_true.dat | 90 +++++++++++++ .../inputs_true.dat | 2 +- .../results_true.dat | 2 +- 12 files changed, 286 insertions(+), 8 deletions(-) diff --git a/tests/test_mgxs_library_condense/inputs_true.dat b/tests/test_mgxs_library_condense/inputs_true.dat index e66d3d111..6b3f5ab3a 100644 --- a/tests/test_mgxs_library_condense/inputs_true.dat +++ b/tests/test_mgxs_library_condense/inputs_true.dat @@ -1 +1 @@ -e86f24e20f37096c7898f459fc5bf336f3e0670fb30f321443f2bb3a01a154ef3d234bb48d4cee8e0d3730fd182b6a2051ec1b4c09d771420886a56ba928fdd9 \ No newline at end of file +4291b40470e7d59383c9e51c4178ca923b698cb1aaea16c1982fe3789ca980df10a65b84fb5021dacd4d290ebc232c2579f99b6c990fb6b8f28f67eef2aabcb2 \ No newline at end of file diff --git a/tests/test_mgxs_library_condense/results_true.dat b/tests/test_mgxs_library_condense/results_true.dat index 525d76efe..6f29fbc4c 100644 --- a/tests/test_mgxs_library_condense/results_true.dat +++ b/tests/test_mgxs_library_condense/results_true.dat @@ -40,6 +40,8 @@ 0 10000 1 total 4.996730e-07 3.650635e-08 material group in nuclide mean std. dev. 0 10000 1 total 0.090004 0.006367 + material group in group out nuclide mean std. dev. +0 10000 1 1 total 0.084542 0.005716 material delayedgroup group in nuclide mean std. dev. 0 10000 1 1 total 0.000021 0.000001 1 10000 2 1 total 0.000110 0.000008 @@ -68,6 +70,13 @@ 3 10000 4 1 total 0.302780 0.109110 4 10000 5 1 total 0.000000 0.000000 5 10000 6 1 total 0.000000 0.000000 + material delayedgroup group in group out nuclide mean std. dev. +0 10000 1 1 1 total 0.000000 0.000000 +1 10000 2 1 1 total 0.000384 0.000236 +2 10000 3 1 1 total 0.000179 0.000180 +3 10000 4 1 1 total 0.000730 0.000188 +4 10000 5 1 1 total 0.000000 0.000000 +5 10000 6 1 1 total 0.000000 0.000000 material group in nuclide mean std. dev. 0 10001 1 total 0.311594 0.013793 material group in nuclide mean std. dev. @@ -110,6 +119,8 @@ 0 10001 1 total 5.454760e-07 4.949800e-08 material group in nuclide mean std. dev. 0 10001 1 total 0.0 0.0 + material group in group out nuclide mean std. dev. +0 10001 1 1 total 0.0 0.0 material delayedgroup group in nuclide mean std. dev. 0 10001 1 1 total 0.0 0.0 1 10001 2 1 total 0.0 0.0 @@ -138,6 +149,13 @@ 3 10001 4 1 total 0.0 0.0 4 10001 5 1 total 0.0 0.0 5 10001 6 1 total 0.0 0.0 + material delayedgroup group in group out nuclide mean std. dev. +0 10001 1 1 1 total 0.0 0.0 +1 10001 2 1 1 total 0.0 0.0 +2 10001 3 1 1 total 0.0 0.0 +3 10001 4 1 1 total 0.0 0.0 +4 10001 5 1 1 total 0.0 0.0 +5 10001 6 1 1 total 0.0 0.0 material group in nuclide mean std. dev. 0 10002 1 total 0.904999 0.043964 material group in nuclide mean std. dev. @@ -180,6 +198,8 @@ 0 10002 1 total 5.773006e-07 5.322132e-08 material group in nuclide mean std. dev. 0 10002 1 total 0.0 0.0 + material group in group out nuclide mean std. dev. +0 10002 1 1 total 0.0 0.0 material delayedgroup group in nuclide mean std. dev. 0 10002 1 1 total 0.0 0.0 1 10002 2 1 total 0.0 0.0 @@ -208,3 +228,10 @@ 3 10002 4 1 total 0.0 0.0 4 10002 5 1 total 0.0 0.0 5 10002 6 1 total 0.0 0.0 + material delayedgroup group in group out nuclide mean std. dev. +0 10002 1 1 1 total 0.0 0.0 +1 10002 2 1 1 total 0.0 0.0 +2 10002 3 1 1 total 0.0 0.0 +3 10002 4 1 1 total 0.0 0.0 +4 10002 5 1 1 total 0.0 0.0 +5 10002 6 1 1 total 0.0 0.0 diff --git a/tests/test_mgxs_library_distribcell/inputs_true.dat b/tests/test_mgxs_library_distribcell/inputs_true.dat index f03c41fe7..f00c2133d 100644 --- a/tests/test_mgxs_library_distribcell/inputs_true.dat +++ b/tests/test_mgxs_library_distribcell/inputs_true.dat @@ -1 +1 @@ -67ee414eed54f596464831e734ac365e43b88bf03297e2b08adfb97510e1d8e631ff45061d5b99aa0ad85ec08d5b51e341866e60f35cdbfae078030bcde6c794 \ No newline at end of file +df187239f7481867cc09138709da90bc28eeb647b4bcbb08b894e7fdf6ff45510341b77e34754c2358f0e0665f8e552bb1eafed8c42cd2c50595b60366320ce4 \ No newline at end of file diff --git a/tests/test_mgxs_library_distribcell/results_true.dat b/tests/test_mgxs_library_distribcell/results_true.dat index ef4d93eb9..2b43005aa 100644 --- a/tests/test_mgxs_library_distribcell/results_true.dat +++ b/tests/test_mgxs_library_distribcell/results_true.dat @@ -40,6 +40,8 @@ 0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 total 5.139437e-07 2.133314e-08 avg(distribcell) group in nuclide mean std. dev. 0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 total 0.091725 0.003604 + avg(distribcell) group in group out nuclide mean std. dev. +0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 1 total 0.093985 0.005872 avg(distribcell) delayedgroup group in nuclide mean std. dev. 0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 1 total 0.000021 8.253907e-07 1 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 2 1 total 0.000112 4.284000e-06 @@ -68,3 +70,10 @@ 3 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 4 1 total 0.000000 0.000000 4 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 5 1 total 0.000000 0.000000 5 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 6 1 total 2.853000 4.034751 + avg(distribcell) delayedgroup group in group out nuclide mean std. dev. +0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 1 1 total 0.000000 0.000000 +1 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 2 1 1 total 0.000175 0.000175 +2 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 3 1 1 total 0.000178 0.000178 +3 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 4 1 1 total 0.000000 0.000000 +4 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 5 1 1 total 0.000000 0.000000 +5 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 6 1 1 total 0.000178 0.000178 diff --git a/tests/test_mgxs_library_hdf5/inputs_true.dat b/tests/test_mgxs_library_hdf5/inputs_true.dat index e66d3d111..6b3f5ab3a 100644 --- a/tests/test_mgxs_library_hdf5/inputs_true.dat +++ b/tests/test_mgxs_library_hdf5/inputs_true.dat @@ -1 +1 @@ -e86f24e20f37096c7898f459fc5bf336f3e0670fb30f321443f2bb3a01a154ef3d234bb48d4cee8e0d3730fd182b6a2051ec1b4c09d771420886a56ba928fdd9 \ No newline at end of file +4291b40470e7d59383c9e51c4178ca923b698cb1aaea16c1982fe3789ca980df10a65b84fb5021dacd4d290ebc232c2579f99b6c990fb6b8f28f67eef2aabcb2 \ No newline at end of file diff --git a/tests/test_mgxs_library_hdf5/results_true.dat b/tests/test_mgxs_library_hdf5/results_true.dat index 8b02203c6..d491e72ba 100644 --- a/tests/test_mgxs_library_hdf5/results_true.dat +++ b/tests/test_mgxs_library_hdf5/results_true.dat @@ -72,6 +72,11 @@ domain=10000 type=inverse-velocity domain=10000 type=prompt-nu-fission [1.92392215e-02 4.66719027e-01] [1.30950595e-03 4.14108704e-02] +domain=10000 type=prompt-nu-fission matrix +[[2.01424282e-02 0.00000000e+00] + [4.45819177e-01 0.00000000e+00]] +[[3.14909168e-03 0.00000000e+00] + [2.86750787e-02 0.00000000e+00]] domain=10000 type=delayed-nu-fission [[2.29808234e-05 1.06974158e-04] [1.43606337e-04 5.52167907e-04] @@ -124,6 +129,41 @@ domain=10000 type=decay-rate [0.00000000e+00 1.09109511e-01] [0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00]] +domain=10000 type=delayed-nu-fission matrix +[[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [2.53814542e-03 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [1.18579166e-03 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [8.59787018e-04 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]]] +[[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [1.56094584e-03 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [1.18610401e-03 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [2.22194634e-04 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]]] domain=10001 type=total [3.13737671e-01 3.00821402e-01] [1.55819024e-02 2.80524484e-02] @@ -198,6 +238,11 @@ domain=10001 type=inverse-velocity domain=10001 type=prompt-nu-fission [0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00] +domain=10001 type=prompt-nu-fission matrix +[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] +[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] domain=10001 type=delayed-nu-fission [[0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00] @@ -250,6 +295,41 @@ domain=10001 type=decay-rate [0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00]] +domain=10001 type=delayed-nu-fission matrix +[[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]]] +[[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]]] domain=10002 type=total [6.64572261e-01 2.05238401e+00] [3.12147519e-02 2.24342907e-01] @@ -324,6 +404,11 @@ domain=10002 type=inverse-velocity domain=10002 type=prompt-nu-fission [0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00] +domain=10002 type=prompt-nu-fission matrix +[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] +[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] domain=10002 type=delayed-nu-fission [[0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00] @@ -376,3 +461,38 @@ domain=10002 type=decay-rate [0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00]] +domain=10002 type=delayed-nu-fission matrix +[[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]]] +[[[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]] + + [[0.00000000e+00 0.00000000e+00] + [0.00000000e+00 0.00000000e+00]]] diff --git a/tests/test_mgxs_library_mesh/inputs_true.dat b/tests/test_mgxs_library_mesh/inputs_true.dat index 3b297354d..70799f147 100644 --- a/tests/test_mgxs_library_mesh/inputs_true.dat +++ b/tests/test_mgxs_library_mesh/inputs_true.dat @@ -1 +1 @@ -a0d62fc011ae33756cd87202432f5c49f847793a40ec50efc6e4366755a70196f9ae970b24244766c011e2991961ea92317b53f6839b89363262b4e67ed4b289 \ No newline at end of file +03d894a7995ac40f7971b17349b460f4b563cb1c94abaa7e7241e6f7edad7f0cb80d3f80829db14ea6b7d70d18197cb15e308047cd10f699d834178eeb6396be \ No newline at end of file diff --git a/tests/test_mgxs_library_mesh/results_true.dat b/tests/test_mgxs_library_mesh/results_true.dat index 2fc403c89..b1cdbc4d5 100644 --- a/tests/test_mgxs_library_mesh/results_true.dat +++ b/tests/test_mgxs_library_mesh/results_true.dat @@ -42,7 +42,7 @@ 3 2 2 1 1 total 0.021015 0.004911 mesh 1 group in nuclide mean std. dev. x y z -0 1 1 1 1 total 1.596880e+06 348353.788370 +0 1 1 1 1 total 1.596880e+06 348353.788371 1 1 2 1 1 total 1.610266e+06 638514.814974 2 2 1 1 1 total 2.048209e+06 257681.654621 3 2 2 1 1 total 1.660283e+06 390011.391278 @@ -130,6 +130,12 @@ 1 1 2 1 1 total 0.020397 0.008086 2 2 1 1 1 total 0.025824 0.003192 3 2 2 1 1 total 0.020865 0.004879 + mesh 1 group in group out nuclide mean std. dev. + x y z +0 1 1 1 1 1 total 0.020874 0.002977 +1 1 2 1 1 1 total 0.017348 0.008786 +2 2 1 1 1 1 total 0.020409 0.003354 +3 2 2 1 1 1 total 0.011105 0.003806 mesh 1 delayedgroup group in nuclide mean std. dev. x y z 0 1 1 1 1 1 total 0.000005 1.004627e-06 @@ -234,3 +240,29 @@ 21 2 2 1 4 1 total 0.00000 0.00000 22 2 2 1 5 1 total 0.00000 0.00000 23 2 2 1 6 1 total 0.00000 0.00000 + mesh 1 delayedgroup group in group out nuclide mean std. dev. + x y z +0 1 1 1 1 1 1 total 0.000000 0.000000 +1 1 1 1 2 1 1 total 0.000000 0.000000 +2 1 1 1 3 1 1 total 0.000000 0.000000 +3 1 1 1 4 1 1 total 0.000000 0.000000 +4 1 1 1 5 1 1 total 0.000185 0.000186 +5 1 1 1 6 1 1 total 0.000000 0.000000 +6 1 2 1 1 1 1 total 0.000000 0.000000 +7 1 2 1 2 1 1 total 0.000000 0.000000 +8 1 2 1 3 1 1 total 0.000000 0.000000 +9 1 2 1 4 1 1 total 0.000000 0.000000 +10 1 2 1 5 1 1 total 0.000000 0.000000 +11 1 2 1 6 1 1 total 0.000000 0.000000 +12 2 1 1 1 1 1 total 0.000000 0.000000 +13 2 1 1 2 1 1 total 0.000000 0.000000 +14 2 1 1 3 1 1 total 0.000000 0.000000 +15 2 1 1 4 1 1 total 0.000000 0.000000 +16 2 1 1 5 1 1 total 0.000000 0.000000 +17 2 1 1 6 1 1 total 0.000000 0.000000 +18 2 2 1 1 1 1 total 0.000000 0.000000 +19 2 2 1 2 1 1 total 0.000000 0.000000 +20 2 2 1 3 1 1 total 0.000000 0.000000 +21 2 2 1 4 1 1 total 0.000000 0.000000 +22 2 2 1 5 1 1 total 0.000000 0.000000 +23 2 2 1 6 1 1 total 0.000000 0.000000 diff --git a/tests/test_mgxs_library_no_nuclides/inputs_true.dat b/tests/test_mgxs_library_no_nuclides/inputs_true.dat index e66d3d111..6b3f5ab3a 100644 --- a/tests/test_mgxs_library_no_nuclides/inputs_true.dat +++ b/tests/test_mgxs_library_no_nuclides/inputs_true.dat @@ -1 +1 @@ -e86f24e20f37096c7898f459fc5bf336f3e0670fb30f321443f2bb3a01a154ef3d234bb48d4cee8e0d3730fd182b6a2051ec1b4c09d771420886a56ba928fdd9 \ No newline at end of file +4291b40470e7d59383c9e51c4178ca923b698cb1aaea16c1982fe3789ca980df10a65b84fb5021dacd4d290ebc232c2579f99b6c990fb6b8f28f67eef2aabcb2 \ No newline at end of file diff --git a/tests/test_mgxs_library_no_nuclides/results_true.dat b/tests/test_mgxs_library_no_nuclides/results_true.dat index 07813519a..fac47af46 100644 --- a/tests/test_mgxs_library_no_nuclides/results_true.dat +++ b/tests/test_mgxs_library_no_nuclides/results_true.dat @@ -84,6 +84,11 @@ material group in nuclide mean std. dev. 1 10000 1 total 0.019239 0.001310 0 10000 2 total 0.466719 0.041411 + material group in group out nuclide mean std. dev. +3 10000 1 1 total 0.020142 0.003149 +2 10000 1 2 total 0.000000 0.000000 +1 10000 2 1 total 0.445819 0.028675 +0 10000 2 2 total 0.000000 0.000000 material delayedgroup group in nuclide mean std. dev. 1 10000 1 1 total 0.000023 0.000002 3 10000 2 1 total 0.000144 0.000011 @@ -136,6 +141,31 @@ 6 10000 4 2 total 0.302780 0.109110 8 10000 5 2 total 0.000000 0.000000 10 10000 6 2 total 0.000000 0.000000 + material delayedgroup group in group out nuclide mean std. dev. +3 10000 1 1 1 total 0.000000 0.000000 +7 10000 2 1 1 total 0.000000 0.000000 +11 10000 3 1 1 total 0.000000 0.000000 +15 10000 4 1 1 total 0.000000 0.000000 +19 10000 5 1 1 total 0.000000 0.000000 +23 10000 6 1 1 total 0.000000 0.000000 +2 10000 1 1 2 total 0.000000 0.000000 +6 10000 2 1 2 total 0.000000 0.000000 +10 10000 3 1 2 total 0.000000 0.000000 +14 10000 4 1 2 total 0.000000 0.000000 +18 10000 5 1 2 total 0.000000 0.000000 +22 10000 6 1 2 total 0.000000 0.000000 +1 10000 1 2 1 total 0.000000 0.000000 +5 10000 2 2 1 total 0.002538 0.001561 +9 10000 3 2 1 total 0.001186 0.001186 +13 10000 4 2 1 total 0.000860 0.000222 +17 10000 5 2 1 total 0.000000 0.000000 +21 10000 6 2 1 total 0.000000 0.000000 +0 10000 1 2 2 total 0.000000 0.000000 +4 10000 2 2 2 total 0.000000 0.000000 +8 10000 3 2 2 total 0.000000 0.000000 +12 10000 4 2 2 total 0.000000 0.000000 +16 10000 5 2 2 total 0.000000 0.000000 +20 10000 6 2 2 total 0.000000 0.000000 material group in nuclide mean std. dev. 1 10001 1 total 0.313738 0.015582 0 10001 2 total 0.300821 0.028052 @@ -222,6 +252,11 @@ material group in nuclide mean std. dev. 1 10001 1 total 0.0 0.0 0 10001 2 total 0.0 0.0 + material group in group out nuclide mean std. dev. +3 10001 1 1 total 0.0 0.0 +2 10001 1 2 total 0.0 0.0 +1 10001 2 1 total 0.0 0.0 +0 10001 2 2 total 0.0 0.0 material delayedgroup group in nuclide mean std. dev. 1 10001 1 1 total 0.0 0.0 3 10001 2 1 total 0.0 0.0 @@ -274,6 +309,31 @@ 6 10001 4 2 total 0.0 0.0 8 10001 5 2 total 0.0 0.0 10 10001 6 2 total 0.0 0.0 + material delayedgroup group in group out nuclide mean std. dev. +3 10001 1 1 1 total 0.0 0.0 +7 10001 2 1 1 total 0.0 0.0 +11 10001 3 1 1 total 0.0 0.0 +15 10001 4 1 1 total 0.0 0.0 +19 10001 5 1 1 total 0.0 0.0 +23 10001 6 1 1 total 0.0 0.0 +2 10001 1 1 2 total 0.0 0.0 +6 10001 2 1 2 total 0.0 0.0 +10 10001 3 1 2 total 0.0 0.0 +14 10001 4 1 2 total 0.0 0.0 +18 10001 5 1 2 total 0.0 0.0 +22 10001 6 1 2 total 0.0 0.0 +1 10001 1 2 1 total 0.0 0.0 +5 10001 2 2 1 total 0.0 0.0 +9 10001 3 2 1 total 0.0 0.0 +13 10001 4 2 1 total 0.0 0.0 +17 10001 5 2 1 total 0.0 0.0 +21 10001 6 2 1 total 0.0 0.0 +0 10001 1 2 2 total 0.0 0.0 +4 10001 2 2 2 total 0.0 0.0 +8 10001 3 2 2 total 0.0 0.0 +12 10001 4 2 2 total 0.0 0.0 +16 10001 5 2 2 total 0.0 0.0 +20 10001 6 2 2 total 0.0 0.0 material group in nuclide mean std. dev. 1 10002 1 total 0.664572 0.031215 0 10002 2 total 2.052384 0.224343 @@ -360,6 +420,11 @@ material group in nuclide mean std. dev. 1 10002 1 total 0.0 0.0 0 10002 2 total 0.0 0.0 + material group in group out nuclide mean std. dev. +3 10002 1 1 total 0.0 0.0 +2 10002 1 2 total 0.0 0.0 +1 10002 2 1 total 0.0 0.0 +0 10002 2 2 total 0.0 0.0 material delayedgroup group in nuclide mean std. dev. 1 10002 1 1 total 0.0 0.0 3 10002 2 1 total 0.0 0.0 @@ -412,3 +477,28 @@ 6 10002 4 2 total 0.0 0.0 8 10002 5 2 total 0.0 0.0 10 10002 6 2 total 0.0 0.0 + material delayedgroup group in group out nuclide mean std. dev. +3 10002 1 1 1 total 0.0 0.0 +7 10002 2 1 1 total 0.0 0.0 +11 10002 3 1 1 total 0.0 0.0 +15 10002 4 1 1 total 0.0 0.0 +19 10002 5 1 1 total 0.0 0.0 +23 10002 6 1 1 total 0.0 0.0 +2 10002 1 1 2 total 0.0 0.0 +6 10002 2 1 2 total 0.0 0.0 +10 10002 3 1 2 total 0.0 0.0 +14 10002 4 1 2 total 0.0 0.0 +18 10002 5 1 2 total 0.0 0.0 +22 10002 6 1 2 total 0.0 0.0 +1 10002 1 2 1 total 0.0 0.0 +5 10002 2 2 1 total 0.0 0.0 +9 10002 3 2 1 total 0.0 0.0 +13 10002 4 2 1 total 0.0 0.0 +17 10002 5 2 1 total 0.0 0.0 +21 10002 6 2 1 total 0.0 0.0 +0 10002 1 2 2 total 0.0 0.0 +4 10002 2 2 2 total 0.0 0.0 +8 10002 3 2 2 total 0.0 0.0 +12 10002 4 2 2 total 0.0 0.0 +16 10002 5 2 2 total 0.0 0.0 +20 10002 6 2 2 total 0.0 0.0 diff --git a/tests/test_mgxs_library_nuclides/inputs_true.dat b/tests/test_mgxs_library_nuclides/inputs_true.dat index d7c6eeab0..ed6f4d443 100644 --- a/tests/test_mgxs_library_nuclides/inputs_true.dat +++ b/tests/test_mgxs_library_nuclides/inputs_true.dat @@ -1 +1 @@ -1e8d0f408ba9d47fc9278e750dbf68d3104d248f7783ca1185c8b7666c9ee2ba3ec6fcf4a49bb614956bb8eb3a57dc1c104725b4160171dfbe6dc972a268df56 \ No newline at end of file +eed0190893105747f0146472dfea86ca58b9fc2e8d039961d9fef8f235f79da32215f9b59b840419e6b69c5a04544b4659f2634b63e3a76b6b0f8c75d05e416c \ No newline at end of file diff --git a/tests/test_mgxs_library_nuclides/results_true.dat b/tests/test_mgxs_library_nuclides/results_true.dat index b55ab34ab..bdc0d1768 100644 --- a/tests/test_mgxs_library_nuclides/results_true.dat +++ b/tests/test_mgxs_library_nuclides/results_true.dat @@ -1 +1 @@ -ce682f577fd65dd9b6e5da58763cf2ae4cf8e5041b38b5d1ed64d3ba7a3a4df7338aadfa8830a0764fc9ffb737f05fc989a494158c714047186dd18605a7d2b8 \ No newline at end of file +8bc6694ee99cc05ec59143dac065f3f51026713044c48a36ac486f46014289c1f18d4d8e14ef0bb468050aea0bac5628425fd76154a01c7438c7d85139aa2f06 \ No newline at end of file From 687054e02590474226b3b321a705890fe8363e0e Mon Sep 17 00:00:00 2001 From: samuel shaner Date: Sat, 5 Nov 2016 11:28:11 +0000 Subject: [PATCH 49/60] updated mesh test --- tests/test_mgxs_library_mesh/results_true.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_mgxs_library_mesh/results_true.dat b/tests/test_mgxs_library_mesh/results_true.dat index b1cdbc4d5..b4681d25c 100644 --- a/tests/test_mgxs_library_mesh/results_true.dat +++ b/tests/test_mgxs_library_mesh/results_true.dat @@ -42,7 +42,7 @@ 3 2 2 1 1 total 0.021015 0.004911 mesh 1 group in nuclide mean std. dev. x y z -0 1 1 1 1 total 1.596880e+06 348353.788371 +0 1 1 1 1 total 1.596880e+06 348353.788370 1 1 2 1 1 total 1.610266e+06 638514.814974 2 2 1 1 1 total 2.048209e+06 257681.654621 3 2 2 1 1 total 1.660283e+06 390011.391278 From 008c0ff3c1e70f26b817bddee2fa4a17c67600b7 Mon Sep 17 00:00:00 2001 From: samuel shaner Date: Sat, 5 Nov 2016 17:47:16 +0000 Subject: [PATCH 50/60] changed basestring to string_types in mdgxs.py --- openmc/mgxs/mdgxs.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index ba5f465cb..5a0aee80b 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -1920,7 +1920,7 @@ class MatrixMDGXS(MDGXS): filter_bins = [] # Construct a collection of the domain filter bins - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) for subdomain in subdomains: @@ -1928,7 +1928,7 @@ class MatrixMDGXS(MDGXS): filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(in_groups, basestring): + if not isinstance(in_groups, string_types): cv.check_iterable_type('groups', in_groups, Integral) for group in in_groups: filters.append(openmc.EnergyFilter) @@ -1936,7 +1936,7 @@ class MatrixMDGXS(MDGXS): self.energy_groups.get_group_bounds(group),)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(out_groups, basestring): + if not isinstance(out_groups, string_types): cv.check_iterable_type('groups', out_groups, Integral) for group in out_groups: filters.append(openmc.EnergyoutFilter) @@ -1944,7 +1944,7 @@ class MatrixMDGXS(MDGXS): self.energy_groups.get_group_bounds(group),)) # Construct list of delayed group tuples for all requested groups - if not isinstance(delayed_groups, basestring): + if not isinstance(delayed_groups, string_types): cv.check_type('delayed groups', delayed_groups, list, int) for delayed_group in delayed_groups: filters.append(openmc.DelayedGroupFilter) @@ -2101,7 +2101,7 @@ class MatrixMDGXS(MDGXS): """ # Construct a collection of the subdomains to report - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -2118,7 +2118,7 @@ class MatrixMDGXS(MDGXS): if nuclides == 'sum': nuclides = ['sum'] else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) else: nuclides = ['sum'] From cdf4d271a53e5b6b6217d66f92676a1cff55ceba Mon Sep 17 00:00:00 2001 From: Sam Shaner Date: Mon, 7 Nov 2016 08:07:58 -0500 Subject: [PATCH 51/60] added comment that delayed-nu-fission could be input in shape [G] --- openmc/mgxs_library.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index fc8467b15..ac12847aa 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -137,7 +137,7 @@ class XSdata(object): [Order][G][G']: scatter_matrix [G]: total, absorption, fission, kappa_fission, nu_fission, - prompt_nu_fission, inverse_velocity + prompt_nu_fission, delayed_nu_fission, inverse_velocity [G']: chi, chi_prompt, chi_delayed From 436a14d388456ebdc785a9d021258f5dfc9d174d Mon Sep 17 00:00:00 2001 From: Sam Shaner Date: Mon, 7 Nov 2016 08:11:22 -0500 Subject: [PATCH 52/60] reverted basic materials.xml file --- examples/xml/basic/materials.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/xml/basic/materials.xml b/examples/xml/basic/materials.xml index 82f404a1d..606c676df 100644 --- a/examples/xml/basic/materials.xml +++ b/examples/xml/basic/materials.xml @@ -8,8 +8,8 @@ - - + + From 2adb4f284ff47357e3097105ab43d03143241f22 Mon Sep 17 00:00:00 2001 From: Sam Shaner Date: Fri, 11 Nov 2016 18:29:40 -0500 Subject: [PATCH 53/60] addressed PR comments --- docs/source/pythonapi/index.rst | 2 ++ openmc/mgxs/mdgxs.py | 33 ++++++++++++++------------------- openmc/mgxs/mgxs.py | 4 ++-- openmc/mgxs_library.py | 4 +++- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/docs/source/pythonapi/index.rst b/docs/source/pythonapi/index.rst index 7e310857c..e364452b1 100644 --- a/docs/source/pythonapi/index.rst +++ b/docs/source/pythonapi/index.rst @@ -293,6 +293,7 @@ Multi-group Cross Sections openmc.mgxs.NuScatterXS openmc.mgxs.NuScatterMatrixXS openmc.mgxs.PromptNuFissionXS + openmc.mgxs.PromptNuFissionMatrixXS openmc.mgxs.ScatterXS openmc.mgxs.ScatterMatrixXS openmc.mgxs.TotalXS @@ -309,6 +310,7 @@ Multi-delayed-group Cross Sections openmc.mgxs.MDGXS openmc.mgxs.ChiDelayed openmc.mgxs.DelayedNuFissionXS + openmc.mgxs.DelayedNuFissionMatrixXS openmc.mgxs.Beta openmc.mgxs.DecayRate diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 5a0aee80b..5b2f451c2 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -1840,7 +1840,7 @@ class MatrixMDGXS(MDGXS): energy = openmc.EnergyFilter(group_edges) energyout = openmc.EnergyoutFilter(group_edges) - if self.delayed_groups != None: + if self.delayed_groups is not None: delayed = openmc.DelayedGroupFilter(self.delayed_groups) return [[energy], [delayed, energy, energyout]] else: @@ -1894,7 +1894,7 @@ class MatrixMDGXS(MDGXS): Returns ------- - ndarray + numpy.ndarray A NumPy array of the multi-group cross section indexed in the order each group and subdomain is listed in the parameters. @@ -2150,20 +2150,19 @@ class MatrixMDGXS(MDGXS): for subdomain in subdomains: if self.domain_type == 'distribcell': - string += \ - '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) + string += '{: <16}=\t{}\n'.format('\tSubdomain', subdomain) # Loop over all Nuclides for nuclide in nuclides: # Build header for nuclide type if xs_type != 'sum': - string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) + string += '{: <16}=\t{}\n'.format('\tNuclide', nuclide) # Build header for cross section type - string += '{0: <16}\n'.format(xs_header) + string += '{: <16}\n'.format(xs_header) - if self.delayed_groups != None: + if self.delayed_groups is not None: for delayed_group in self.delayed_groups: @@ -2177,22 +2176,20 @@ class MatrixMDGXS(MDGXS): for in_group in range(1, self.num_groups + 1): for out_group in range(1, self.num_groups + 1): string += template.format('', in_group, out_group) - average = \ - self.get_xs([in_group], [out_group], + average = self.get_xs([in_group], [out_group], [subdomain], [nuclide], xs_type=xs_type, value='mean', delayed_groups=[delayed_group]) - rel_err = \ - self.get_xs([in_group], [out_group], + rel_err = self.get_xs([in_group], [out_group], [subdomain], [nuclide], xs_type=xs_type, value='rel_err', delayed_groups=[delayed_group]) average = average.flatten()[0] rel_err = rel_err.flatten()[0] * 100. - string += '{:1.2e} +/- {:1.2e}%'.format(average, - rel_err) + string += '{:.2e} +/- {:.2e}%'.format(average, + rel_err) string += '\n' string += '\n' string += '\n' @@ -2204,18 +2201,16 @@ class MatrixMDGXS(MDGXS): for in_group in range(1, self.num_groups + 1): for out_group in range(1, self.num_groups + 1): string += template.format('', in_group, out_group) - average = \ - self.get_xs([in_group], [out_group], + average = self.get_xs([in_group], [out_group], [subdomain], [nuclide], xs_type=xs_type, value='mean') - rel_err = \ - self.get_xs([in_group], [out_group], + rel_err = self.get_xs([in_group], [out_group], [subdomain], [nuclide], xs_type=xs_type, value='rel_err') average = average.flatten()[0] rel_err = rel_err.flatten()[0] * 100. - string += '{:1.2e} +/- {:1.2e}%'.format(average, - rel_err) + string += '{:.2e} +/- {:.2e}%'.format(average, + rel_err) string += '\n' string += '\n' string += '\n' diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index a7a2a7811..1936697ee 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -1755,7 +1755,7 @@ class MatrixMGXS(MGXS): Returns ------- - ndarray + numpy.ndarray A NumPy array of the multi-group cross section indexed in the order each group and subdomain is listed in the parameters. @@ -3590,7 +3590,7 @@ class ScatterMatrixXS(MatrixMGXS): Returns ------- - ndarray + numpy.ndarray A NumPy array of the multi-group cross section indexed in the order each group and subdomain is listed in the parameters. diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index ac12847aa..3f3a38b06 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -1092,7 +1092,9 @@ class XSdata(object): def set_prompt_nu_fission_mgxs(self, prompt_nu_fission, temperature=294., nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.PromptNuFissionXS or + """Sets the prompt-nu-fission cross section. + + This method allows for an openmc.mgxs.PromptNuFissionXS or openmc.mgxs.PromptNuFissionMatrixXS to be used to set the prompt-nu-fission cross section for this XSdata object. From 2573fba5fae8a57605a4f025626edb288b993aba Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 13 Nov 2016 13:49:30 -0500 Subject: [PATCH 54/60] Address #746 comments --- docs/source/usersguide/input.rst | 2 +- openmc/statepoint.py | 4 +- openmc/tallies.py | 6 +- openmc/tally_derivative.py | 77 ++---- src/tally.F90 | 197 +++++++++------ src/tally_header.F90 | 2 +- tests/test_diff_tally/inputs_true.dat | 2 +- tests/test_diff_tally/results_true.dat | 304 +++++++++++++---------- tests/test_diff_tally/test_diff_tally.py | 18 +- 9 files changed, 338 insertions(+), 274 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 3c8860475..4a81615a1 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1973,7 +1973,7 @@ the following attributes/sub-elements: density of a particular nuclide in units of [atom / b / cm]. A "temperature" derivative is with respect to a material temperature in units of [K]. The temperature derivative requires windowed multipole to be - turned on. Note also that the temperature derivative only acconuts for + turned on. Note also that the temperature derivative only accounts for resolved resonance Doppler broadening. It does not account for thermal expansion, S(a, b) scattering, resonance scattering, or unresolved Doppler broadening. diff --git a/openmc/statepoint.py b/openmc/statepoint.py index d0e4dbdd5..5a677a8e2 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -479,7 +479,7 @@ class StatePoint(object): if 'derivatives' in self._f['tallies']: # Read the derivative ids. base = 'tallies/derivatives' - deriv_ids = [int(k.split(' ')[1]) for k in self._f[base].keys()] + deriv_ids = [int(k.split(' ')[1]) for k in self._f[base]] # Create each derivative object and add it to the dictionary. for d_id in deriv_ids: @@ -497,7 +497,7 @@ class StatePoint(object): deriv.material = self._f[base + '/material'].value else: raise RuntimeError('Unrecognized tally differential ' - 'variable') + 'variable') self._derivs[d_id] = deriv self._derivs_read = True diff --git a/openmc/tallies.py b/openmc/tallies.py index 3ba24b782..1f02129c0 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -103,7 +103,7 @@ class Tally(object): sparse : bool Whether or not the tally uses SciPy's LIL sparse matrix format for compressed data storage - derivative : openmc.tally_derivative.TallyDerivative + derivative : openmc.TallyDerivative A material perturbation derivative to apply to all scores in the tally. """ @@ -453,7 +453,7 @@ class Tally(object): def derivative(self, deriv): if deriv is not None: cv.check_type('tally derivative', deriv, openmc.TallyDerivative) - self._derivative = deriv + self._derivative = deriv @filters.setter def filters(self, filters): @@ -3608,7 +3608,7 @@ class Tallies(cv.CheckedList): # Add the derivatives to the XML tree. for d in derivs: - self._tallies_file.append(d.get_derivative_xml()) + self._tallies_file.append(d.to_xml_element()) def export_to_xml(self): """Create a tallies.xml file that can be used for a simulation. diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py index 3c48cf030..1c8a316cf 100644 --- a/openmc/tally_derivative.py +++ b/openmc/tally_derivative.py @@ -7,6 +7,7 @@ from xml.etree import ElementTree as ET from six import string_types import openmc.checkvalue as cv +from openmc.mixin import EqualityMixin # "Static" variable for auto-generated TallyDerivative IDs @@ -17,7 +18,7 @@ def reset_auto_tally_deriv_id(): AUTO_TALLY_DERIV_ID = 10000 -class TallyDerivative(object): +class TallyDerivative(EqualityMixin): """A material perturbation derivative to apply to a tally. Parameters @@ -25,6 +26,13 @@ class TallyDerivative(object): derivative_id : Integral, optional Unique identifier for the tally derivative. If none is specified, an identifier will automatically be assigned + variable : str, optional + Accepted values are 'density', 'nuclide_density', and 'temperature' + material : Integral, optional + The perturubed material ID + nuclide : str, optional + The perturbed nuclide. Only needed for 'nuclide_density' derivatives. + Ex: 'Xe135' Attributes ---------- @@ -33,71 +41,36 @@ class TallyDerivative(object): variable : str Accepted values are 'density', 'nuclide_density', and 'temperature' material : Integral - The perturubed material + The perturubed material ID nuclide : str The perturbed nuclide. Only needed for 'nuclide_density' derivatives. - Ex: 'Xe-135' + Ex: 'Xe135' """ - def __init__(self, derivative_id=None): + def __init__(self, derivative_id=None, variable=None, material=None, + nuclide=None): # Initialize Tally class attributes self.id = derivative_id - self._variable = None - self._material = None - self._nuclide = None - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, create a - # copy - if existing is None: - clone = type(self).__new__(type(self)) - clone.id = self.id - clone.variable = self.variable - clone.material = self.material - clone.nuclide = self.nuclide - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - def __eq__(self, other): - if not isinstance(other, TallyDerivative): - return False - - return (self.variable == other.variable and - self.material == other.material and - self.nuclide == other.nuclide) - - def __ne__(self, other): - return not self == other + self.variable = variable + self.material = material + self.nuclide = nuclide def __hash__(self): return hash(repr(self)) def __repr__(self): string = 'Tally Derivative\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) - string += '{0: <16}{1}{2}\n'.format('\tVariable', '=\t', - self.variable) + string += '{: <16}=\t{}\n'.format('\tID', self.id) + string += '{: <16}=\t{}\n'.format('\tVariable', self.variable) if self.variable == 'density': - string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', - self.material) + string += '{: <16}=\t{}\n'.format('\tMaterial', self.material) elif self.variable == 'nuclide_density': - string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', - self.material) - string += '{0: <16}{1}{2}\n'.format('\tNuclide', '=\t', - self.nuclide) + string += '{: <16}=\t{}\n'.format('\tMaterial', self.material) + string += '{: <16}=\t{}\n'.format('\tNuclide', self.nuclide) elif self.variable == 'temperature': - string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', - self.material) + string += '{: <16}=\t{}\n'.format('\tMaterial', self.material) return string @@ -133,8 +106,8 @@ class TallyDerivative(object): def variable(self, var): if var is not None: cv.check_type('derivative variable', var, string_types) - cv.check_value('derivative variable', var, ('density', - 'nuclide_density', 'temperature')) + cv.check_value('derivative variable', var, + ('density', 'nuclide_density', 'temperature')) self._variable = var @material.setter @@ -149,7 +122,7 @@ class TallyDerivative(object): cv.check_type('derivative nuclide', nuc, string_types) self._nuclide = nuc - def get_derivative_xml(self): + def to_xml_element(self): """Return XML representation of the tally derivative Returns diff --git a/src/tally.F90 b/src/tally.F90 index 5b8adf1c2..df8efa0c0 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -3144,21 +3144,47 @@ contains if (score == ZERO) return + ! If our score was previously c then the new score is + ! c * (1/f * d_f/d_p + 1/c * d_c/d_p) + ! where (1/f * d_f/d_p) is the (logarithmic) flux derivative and p is the + ! perturbated variable. + associate(deriv => tally_derivs(t % deriv)) flux_deriv = deriv % flux_deriv select case (tally_derivs(t % deriv) % variable) + !========================================================================= + ! Density derivative: + ! c = Sigma_MT + ! c = sigma_MT * N + ! c = sigma_MT * rho * const + ! d_c / d_rho = sigma_MT * const + ! (1 / c) * (d_c / d_rho) = 1 / rho + case (DIFF_DENSITY) select case (t % estimator) case (ESTIMATOR_ANALOG) - if (materials(p % material) % id == deriv % diff_material) then - score = score * (flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else + + select case (score_bin) + + case (SCORE_FLUX) score = score * flux_deriv - end if + + case (SCORE_TOTAL, SCORE_SCATTER, SCORE_ABSORPTION, SCORE_FISSION, & + SCORE_NU_FISSION) + if (materials(p % material) % id == deriv % diff_material) then + score = score * (flux_deriv + ONE & + / materials(p % material) % density_gpcc) + else + score = score * flux_deriv + end if + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + end select case (ESTIMATOR_COLLISION) @@ -3167,46 +3193,9 @@ contains case (SCORE_FLUX) score = score * flux_deriv - case (SCORE_TOTAL) - if (materials(p % material) % id == deriv % diff_material & - .and. material_xs % total /= ZERO) then - score = score * (flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * flux_deriv - end if - - case (SCORE_SCATTER) - if (materials(p % material) % id == deriv % diff_material & - .and. material_xs % total - material_xs % absorption /= ZERO) & - then - score = score * (flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * flux_deriv - end if - - case (SCORE_ABSORPTION) - if (materials(p % material) % id == deriv % diff_material & - .and. material_xs % absorption /= ZERO) then - score = score * (flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * flux_deriv - end if - - case (SCORE_FISSION) - if (materials(p % material) % id == deriv % diff_material & - .and. material_xs % fission /= ZERO) then - score = score * (flux_deriv + ONE & - / materials(p % material) % density_gpcc) - else - score = score * flux_deriv - end if - - case (SCORE_NU_FISSION) - if (materials(p % material) % id == deriv % diff_material & - .and. material_xs % nu_fission /= ZERO) then + case (SCORE_TOTAL, SCORE_SCATTER, SCORE_ABSORPTION, SCORE_FISSION, & + SCORE_NU_FISSION) + if (materials(p % material) % id == deriv % diff_material) then score = score * (flux_deriv + ONE & / materials(p % material) % density_gpcc) else @@ -3223,24 +3212,50 @@ contains &analog and collision estimators.") end select + !========================================================================= + ! Nuclide density derivative: + ! If we are scoring a reaction rate for a single nuclide then + ! c = Sigma_MT_i + ! c = sigma_MT_i * N_i + ! d_c / d_N_i = sigma_MT_i + ! (1 / c) * (d_c / d_N_i) = 1 / N_i + ! If the score is for the total material (i_nuclide = -1) + ! c = Sum_i(Sigma_MT_i) + ! d_c / d_N_i = sigma_MT_i + ! (1 / c) * (d_c / d_N) = sigma_MT_i / Sigma_MT + ! where i is the perturbed nuclide. + case (DIFF_NUCLIDE_DENSITY) select case (t % estimator) case (ESTIMATOR_ANALOG) - if (materials(p % material) % id == deriv % diff_material & - .and. p % event_nuclide == deriv % diff_nuclide) then - associate(mat => materials(p % material)) - ! Search for the index of the perturbed nuclide. - do l = 1, mat % n_nuclides - if (mat % nuclide(l) == deriv % diff_nuclide) exit - end do - score = score * (flux_deriv & - + ONE / mat % atom_density(l)) - end associate - else + select case (score_bin) + + case (SCORE_FLUX) score = score * flux_deriv - end if + + case (SCORE_TOTAL, SCORE_SCATTER, SCORE_ABSORPTION, SCORE_FISSION, & + SCORE_NU_FISSION) + if (materials(p % material) % id == deriv % diff_material & + .and. p % event_nuclide == deriv % diff_nuclide) then + associate(mat => materials(p % material)) + ! Search for the index of the perturbed nuclide. + do l = 1, mat % n_nuclides + if (mat % nuclide(l) == deriv % diff_nuclide) exit + end do + + score = score * (flux_deriv & + + ONE / mat % atom_density(l)) + end associate + else + score = score * flux_deriv + end if + + case default + call fatal_error('Tally derivative not defined for a score on & + &tally ' // trim(to_str(t % id))) + end select case (ESTIMATOR_COLLISION) scoring_diff_nuclide = & @@ -3334,6 +3349,19 @@ contains &analog and collision estimators.") end select + !========================================================================= + ! Temperature derivative: + ! If we are scoring a reaction rate for a single nuclide then + ! c = Sigma_MT_i + ! c = sigma_MT_i * N_i + ! d_c / d_T = (d_sigma_Mt_i / d_T) * N_i + ! (1 / c) * (d_c / d_T) = (d_sigma_MT_i / d_T) / sigma_MT_i + ! If the score is for the total material (i_nuclide = -1) + ! (1 / c) * (d_c / d_T) = Sum_i((d_sigma_MT_i / d_T) * N_i) / Sigma_MT_i + ! where i is the perturbed nuclide. The d_sigma_MT_i / d_T term is + ! computed by multipole_deriv_eval. It only works for the resolved + ! resonance range and requires multipole data. + case (DIFF_TEMPERATURE) select case (t % estimator) @@ -3718,7 +3746,7 @@ contains case (DIFF_DENSITY) associate (mat => materials(p % material)) if (mat % id == deriv % diff_material) then - ! phi = e^(-Sigma_tot * dist) + ! phi is proportional to e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_rho) = - (d_Sigma_tot / d_rho) * dist ! (1 / phi) * (d_phi / d_rho) = - Sigma_tot / rho * dist deriv % flux_deriv = deriv % flux_deriv & @@ -3729,7 +3757,7 @@ contains case (DIFF_NUCLIDE_DENSITY) associate (mat => materials(p % material)) if (mat % id == deriv % diff_material) then - ! phi = e^(-Sigma_tot * dist) + ! phi is proportional to e^(-Sigma_tot * dist) ! (1 / phi) * (d_phi / d_N) = - (d_Sigma_tot / d_N) * dist ! (1 / phi) * (d_phi / d_N) = - sigma_tot * dist deriv % flux_deriv = deriv % flux_deriv & @@ -3745,6 +3773,9 @@ contains if (nuc % mp_present .and. & p % E >= nuc % multipole % start_E .and. & p % E <= nuc % multipole % end_E) then + ! phi is proportional to e^(-Sigma_tot * dist) + ! (1 / phi) * (d_phi / d_T) = - (d_Sigma_tot / d_T) * dist + ! (1 / phi) * (d_phi / d_T) = - N (d_sigma_tot / d_T) * dist call multipole_deriv_eval(nuc % multipole, p % E, & p % sqrtkT, dsigT, dsigA, dsigF) deriv % flux_deriv = deriv % flux_deriv & @@ -3761,7 +3792,18 @@ contains !=============================================================================== ! SCORE_COLLISION_DERIVATIVE Adjust flux derivatives on differential tallies to -! account for a neutron colliding in the perturbed material. +! account for a neutron scattering in the perturbed material. Note that this +! subroutine will be called after absorption events in addition to scattering +! events, but any flux derivatives scored after an absorption will never be +! tallied. This is because the order of operations is +! 1. Particle is moved. +! 2. score_track_derivative is called. +! 3. Collision physics are computed, and the particle is labeled absorbed. +! 4. Analog- and collision-estimated tallies are scored. +! 5. This subroutine is called. +! 6. Particle is killed and no more tallies are scored. +! Hence, it is safe to assume that only derivative of the scattering cross +! section need to be computed here. !=============================================================================== subroutine score_collision_derivative(p) @@ -3780,8 +3822,8 @@ contains case (DIFF_DENSITY) associate (mat => materials(p % material)) if (mat % id == deriv % diff_material) then - ! phi = Sigma_MT - ! (1 / phi) * (d_phi / d_rho) = (d_Sigma_MT / d_rho) / Sigma_MT + ! phi is proportional to Sigma_s + ! (1 / phi) * (d_phi / d_rho) = (d_Sigma_s / d_rho) / Sigma_s ! (1 / phi) * (d_phi / d_rho) = 1 / rho deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % density_gpcc @@ -3800,9 +3842,9 @@ contains if (mat % nuclide(j) /= deriv % diff_nuclide) then call fatal_error("Couldn't find the right nuclide.") end if - ! phi = Sigma_MT - ! (1 / phi) * (d_phi / d_N) = (d_Sigma_MT / d_N) / Sigma_MT - ! (1 / phi) * (d_phi / d_N) = sigma_MT / Sigma_MT + ! phi is proportional to Sigma_s + ! (1 / phi) * (d_phi / d_N) = (d_Sigma_s / d_N) / Sigma_s + ! (1 / phi) * (d_phi / d_N) = sigma_s / Sigma_s ! (1 / phi) * (d_phi / d_N) = 1 / N deriv % flux_deriv = deriv % flux_deriv & + ONE / mat % atom_density(j) @@ -3818,20 +3860,21 @@ contains nuc % mp_present .and. & p % last_E >= nuc % multipole % start_E .and. & p % last_E <= nuc % multipole % end_E) then - ! phi = Sigma_MT - ! (1 / phi) * (d_phi / d_T) = (d_Sigma_MT / d_T) / Sigma_MT - ! (1 / phi) * (d_phi / d_T) = (d_sigma_MT / d_T) / sigma_MT + ! phi is proportional to Sigma_s + ! (1 / phi) * (d_phi / d_T) = (d_Sigma_s / d_T) / Sigma_s + ! (1 / phi) * (d_phi / d_T) = (d_sigma_s / d_T) / sigma_s call multipole_deriv_eval(nuc % multipole, p % last_E, & p % sqrtkT, dsigT, dsigA, dsigF) - select case(p % event) - case (EVENT_SCATTER) - deriv % flux_deriv = deriv % flux_deriv + (dsigT - dsigA)& - / (micro_xs(mat % nuclide(l)) % total & - - micro_xs(mat % nuclide(l)) % absorption) - case (EVENT_ABSORB) - deriv % flux_deriv = deriv % flux_deriv & - + dsigA / micro_xs(mat % nuclide(l)) % absorption - end select + deriv % flux_deriv = deriv % flux_deriv + (dsigT - dsigA)& + / (micro_xs(mat % nuclide(l)) % total & + - micro_xs(mat % nuclide(l)) % absorption) + ! Note that this is an approximation! The real scattering + ! cross section is Sigma_s(E'->E, uvw'->uvw) = + ! Sigma_s(E') * P(E'->E, uvw'->uvw). We are assuming that + ! d_P(E'->E, uvw'->uvw) / d_T = 0 and only computing + ! d_S(E') / d_T. Using this approximation in the vicinity + ! of low-energy resonances causes errors (~2-5% for PWR + ! pincell eigenvalue derivatives). end if end associate end do diff --git a/src/tally_header.F90 b/src/tally_header.F90 index f30a40deb..e292aba60 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -25,10 +25,10 @@ module tally_header type TallyDerivative integer :: id - real(8) :: flux_deriv integer :: variable integer :: diff_material integer :: diff_nuclide + real(8) :: flux_deriv end type TallyDerivative !=============================================================================== diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index f82b5d8f0..9a6747579 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -1 +1 @@ -be155010540ca076356596aef8511edd58c91772a5e956e5af77437a39ce3d238b91b57df30c2d599fc6e01c887bf73897ee8ed91425c2d475d97202689c2b88 \ No newline at end of file +df5a0ee7d353fe25344496058cea42e3244a7ab32c13c34c03b4b2f6adf88579f08a71ec0d22d8d264e50e3663717068ff54308e2d16aed8e085c222a8c2fdbd \ No newline at end of file diff --git a/tests/test_diff_tally/results_true.dat b/tests/test_diff_tally/results_true.dat index f40c39973..7c4f7f776 100644 --- a/tests/test_diff_tally/results_true.dat +++ b/tests/test_diff_tally/results_true.dat @@ -1,129 +1,177 @@ d_material,d_nuclide,d_variable,score,mean,std. dev. -1,,density,nu-fission,1.11e-02,3.51e-03 -1,,density,nu-fission,9.19e-03,3.48e-03 -1,,density,nu-fission,9.18e-03,5.56e-04 -1,,density,nu-fission,4.82e-03,1.21e-03 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,6.11e-01,4.97e-01 -1,O16,nuclide_density,nu-fission,2.93e-01,6.38e-01 -1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,2.36e+02,1.40e+01 -1,U235,nuclide_density,nu-fission,4.76e+02,2.90e+01 -1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,nu-fission,-2.34e-07,5.70e-06 -1,,temperature,nu-fission,3.95e-06,3.03e-05 -1,,temperature,nu-fission,0.00e+00,0.00e+00 -1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,flux,-4.61e+00,5.24e-01 -3,,density,flux,-1.03e+01,1.44e+00 -1,,density,flux,-3.13e-01,2.59e-02 -1,,density,flux,-2.20e-01,6.88e-02 -1,O16,nuclide_density,flux,-7.42e+00,2.58e+00 -1,O16,nuclide_density,flux,9.12e-02,1.37e+01 -1,U235,nuclide_density,flux,-2.19e+03,1.01e+02 -1,U235,nuclide_density,flux,-1.73e+03,1.03e+02 -1,,temperature,flux,-4.53e-05,1.53e-04 -1,,temperature,flux,9.07e-05,9.43e-05 -3,,density,total,-1.83e+00,1.70e-01 -3,,density,absorption,5.05e-02,1.70e-02 -3,,density,fission,1.02e-01,1.75e-02 -3,,density,nu-fission,2.45e-01,4.27e-02 -3,,density,total,1.09e-01,1.84e-02 -3,,density,absorption,1.28e-01,1.94e-02 -3,,density,fission,1.11e-01,1.73e-02 -3,,density,nu-fission,2.71e-01,4.22e-02 -3,,density,total,7.64e+00,2.06e+00 -3,,density,absorption,1.24e-01,4.94e-02 -3,,density,fission,0.00e+00,0.00e+00 -3,,density,nu-fission,0.00e+00,0.00e+00 -3,,density,total,0.00e+00,0.00e+00 -3,,density,absorption,0.00e+00,0.00e+00 -3,,density,fission,0.00e+00,0.00e+00 -3,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,total,4.23e-01,1.82e-02 -1,,density,absorption,2.15e-02,5.84e-03 -1,,density,fission,7.86e-03,3.45e-03 -1,,density,nu-fission,2.00e-02,8.35e-03 -1,,density,total,1.30e-02,4.22e-03 -1,,density,absorption,8.14e-03,4.13e-03 -1,,density,fission,5.86e-03,3.50e-03 -1,,density,nu-fission,1.43e-02,8.53e-03 -1,,density,total,-2.89e-01,9.44e-02 -1,,density,absorption,-6.94e-03,2.01e-03 -1,,density,fission,0.00e+00,0.00e+00 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,,density,total,0.00e+00,0.00e+00 -1,,density,absorption,0.00e+00,0.00e+00 -1,,density,fission,0.00e+00,0.00e+00 -1,,density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,total,4.54e+01,1.65e+00 -1,O16,nuclide_density,absorption,1.98e-01,4.51e-01 -1,O16,nuclide_density,fission,-3.48e-02,3.76e-01 -1,O16,nuclide_density,nu-fission,-9.43e-02,9.15e-01 -1,O16,nuclide_density,total,-6.13e-02,4.65e-01 -1,O16,nuclide_density,absorption,-3.28e-02,4.51e-01 -1,O16,nuclide_density,fission,-1.46e-02,3.78e-01 -1,O16,nuclide_density,nu-fission,-3.62e-02,9.21e-01 -1,O16,nuclide_density,total,1.04e+00,1.65e+01 -1,O16,nuclide_density,absorption,-3.14e-02,2.69e-01 -1,O16,nuclide_density,fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,total,0.00e+00,0.00e+00 -1,O16,nuclide_density,absorption,0.00e+00,0.00e+00 -1,O16,nuclide_density,fission,0.00e+00,0.00e+00 -1,O16,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,total,-5.09e+02,3.43e+01 -1,U235,nuclide_density,absorption,2.35e+02,1.23e+01 -1,U235,nuclide_density,fission,2.96e+02,1.01e+01 -1,U235,nuclide_density,nu-fission,7.21e+02,2.45e+01 -1,U235,nuclide_density,total,4.95e+02,1.13e+01 -1,U235,nuclide_density,absorption,3.78e+02,1.11e+01 -1,U235,nuclide_density,fission,2.96e+02,1.02e+01 -1,U235,nuclide_density,nu-fission,7.22e+02,2.49e+01 -1,U235,nuclide_density,total,-3.58e+03,2.51e+02 -1,U235,nuclide_density,absorption,-8.88e+01,8.05e+00 -1,U235,nuclide_density,fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,total,0.00e+00,0.00e+00 -1,U235,nuclide_density,absorption,0.00e+00,0.00e+00 -1,U235,nuclide_density,fission,0.00e+00,0.00e+00 -1,U235,nuclide_density,nu-fission,0.00e+00,0.00e+00 -1,,temperature,total,9.57e-05,8.25e-05 -1,,temperature,absorption,1.75e-05,2.01e-05 -1,,temperature,fission,-5.34e-06,5.90e-06 -1,,temperature,nu-fission,-1.30e-05,1.44e-05 -1,,temperature,total,-8.49e-06,7.80e-06 -1,,temperature,absorption,-8.20e-06,7.11e-06 -1,,temperature,fission,-5.31e-06,5.87e-06 -1,,temperature,nu-fission,-1.29e-05,1.43e-05 -1,,temperature,total,1.34e-04,1.35e-04 -1,,temperature,absorption,1.75e-06,2.38e-06 -1,,temperature,fission,0.00e+00,0.00e+00 -1,,temperature,nu-fission,0.00e+00,0.00e+00 -1,,temperature,total,0.00e+00,0.00e+00 -1,,temperature,absorption,0.00e+00,0.00e+00 -1,,temperature,fission,0.00e+00,0.00e+00 -1,,temperature,nu-fission,0.00e+00,0.00e+00 -3,,density,absorption,4.95e-02,4.11e-02 -3,,density,absorption,9.83e-02,3.77e-02 -1,,density,absorption,1.60e-02,5.04e-03 -1,,density,absorption,-7.46e-03,2.08e-03 -1,O16,nuclide_density,absorption,3.63e-01,5.10e-01 -1,O16,nuclide_density,absorption,1.02e-01,1.58e-01 -1,U235,nuclide_density,absorption,2.21e+02,2.59e+01 -1,U235,nuclide_density,absorption,-1.08e+02,8.87e+00 -1,,temperature,absorption,-5.32e-06,2.49e-05 -1,,temperature,absorption,9.82e-06,9.34e-06 -3,,density,nu-fission,-2.30e-02,8.64e-02 -3,,density,nu-fission,-1.58e-02,8.56e-02 -3,,density,nu-fission,1.01e-01,8.75e-02 -3,,density,nu-fission,1.19e-01,8.71e-02 -3,,density,nu-fission,0.00e+00,0.00e+00 -3,,density,nu-fission,0.00e+00,0.00e+00 -3,,density,nu-fission,0.00e+00,0.00e+00 -3,,density,nu-fission,0.00e+00,0.00e+00 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,scatter,3.9902949e-02,9.1258428e-03 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,scatter,9.8213745e-04,9.8213745e-04 +1,,density,nu-fission,2.7945389e-02,2.0999368e-02 +1,,density,scatter,4.0626155e-01,1.7017674e-02 +1,,density,nu-fission,2.4595279e-02,2.1224443e-02 +1,,density,scatter,2.6505962e-03,2.3698970e-03 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,scatter,-1.2721728e-01,1.8810986e-01 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,scatter,0.0000000e+00,0.0000000e+00 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,scatter,4.1950592e-02,7.3680059e-02 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,scatter,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,scatter,-1.9798576e-02,1.9798576e-02 +1,O16,nuclide_density,nu-fission,9.3632921e-01,2.0322286e+00 +1,O16,nuclide_density,scatter,-2.2042881e-01,1.6781767e-01 +1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,scatter,2.3761276e+00,2.3761276e+00 +1,U235,nuclide_density,nu-fission,7.7441690e+02,8.6460933e+01 +1,U235,nuclide_density,scatter,9.6917103e+01,1.0750582e+01 +1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 +1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 +1,,temperature,scatter,-2.0607998e-06,2.0607998e-06 +1,,temperature,nu-fission,3.8845881e-06,3.5405083e-05 +1,,temperature,scatter,-6.6772431e-07,2.0750826e-07 +1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 +1,,temperature,scatter,0.0000000e+00,0.0000000e+00 +1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 +1,,temperature,scatter,0.0000000e+00,0.0000000e+00 +3,,density,flux,-7.6179774e+00,5.0326447e+00 +3,,density,flux,-1.6242019e+01,6.6231774e+00 +1,,density,flux,-2.2394746e-01,5.4534297e-02 +1,,density,flux,-5.7132854e-02,1.6898134e-01 +1,O16,nuclide_density,flux,-1.3403658e+01,1.3017127e+01 +1,O16,nuclide_density,flux,-1.0499715e+01,2.1684953e+01 +1,U235,nuclide_density,flux,-2.4741168e+03,5.7986812e+01 +1,U235,nuclide_density,flux,-1.9955533e+03,4.3254820e+02 +1,,temperature,flux,1.0601815e-04,3.3076550e-04 +1,,temperature,flux,1.6664450e-04,2.8761112e-04 +3,,density,total,-3.3161585e+00,2.5615932e+00 +3,,density,absorption,-4.3491248e-01,5.1559021e-01 +3,,density,scatter,-2.8812460e+00,2.0540305e+00 +3,,density,fission,-2.3060366e-01,3.1191109e-01 +3,,density,nu-fission,-5.6817321e-01,7.6143389e-01 +3,,density,total,-2.8908007e-01,3.9383184e-01 +3,,density,absorption,-2.5237485e-01,3.6565053e-01 +3,,density,scatter,-3.6705221e-02,2.9275371e-02 +3,,density,fission,-2.1271120e-01,3.0873698e-01 +3,,density,nu-fission,-5.1866339e-01,7.5235533e-01 +3,,density,total,2.7320569e+00,8.7709465e+00 +3,,density,absorption,8.4322466e-02,1.2807898e-01 +3,,density,scatter,2.6477344e+00,8.6432567e+00 +3,,density,fission,0.0000000e+00,0.0000000e+00 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,total,0.0000000e+00,0.0000000e+00 +3,,density,absorption,0.0000000e+00,0.0000000e+00 +3,,density,scatter,0.0000000e+00,0.0000000e+00 +3,,density,fission,0.0000000e+00,0.0000000e+00 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,total,4.7523439e-01,2.5652004e-02 +1,,density,absorption,3.1301234e-02,7.6793142e-03 +1,,density,scatter,4.4393315e-01,1.8023252e-02 +1,,density,fission,1.5559355e-02,3.2310294e-03 +1,,density,nu-fission,3.8658109e-02,7.8012233e-03 +1,,density,total,2.2062939e-02,4.3689061e-03 +1,,density,absorption,1.6845626e-02,4.0750601e-03 +1,,density,scatter,5.2173132e-03,2.9663452e-04 +1,,density,fission,1.3503649e-02,3.2642875e-03 +1,,density,nu-fission,3.2945474e-02,7.9507685e-03 +1,,density,total,-9.4735691e-02,2.5584665e-01 +1,,density,absorption,-4.0246397e-03,5.2111770e-03 +1,,density,scatter,-9.0711052e-02,2.5073762e-01 +1,,density,fission,0.0000000e+00,0.0000000e+00 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,density,total,0.0000000e+00,0.0000000e+00 +1,,density,absorption,0.0000000e+00,0.0000000e+00 +1,,density,scatter,0.0000000e+00,0.0000000e+00 +1,,density,fission,0.0000000e+00,0.0000000e+00 +1,,density,nu-fission,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,total,4.4488215e+01,5.3981603e+00 +1,O16,nuclide_density,absorption,-2.9372611e-01,9.3282813e-01 +1,O16,nuclide_density,scatter,4.4781941e+01,4.5257555e+00 +1,O16,nuclide_density,fission,9.9827872e-02,4.0698927e-01 +1,O16,nuclide_density,nu-fission,2.3342880e-01,9.8749212e-01 +1,O16,nuclide_density,total,4.0914051e-02,6.2301812e-01 +1,O16,nuclide_density,absorption,8.8289354e-02,5.5570922e-01 +1,O16,nuclide_density,scatter,-4.7375303e-02,6.7714071e-02 +1,O16,nuclide_density,fission,1.3678733e-01,4.4006413e-01 +1,O16,nuclide_density,nu-fission,3.3257520e-01,1.0719313e+00 +1,O16,nuclide_density,total,-1.6055918e+01,2.3439335e+01 +1,O16,nuclide_density,absorption,-3.9601231e-01,3.0131622e-01 +1,O16,nuclide_density,scatter,-1.5659906e+01,2.3140407e+01 +1,O16,nuclide_density,fission,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,total,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,absorption,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,fission,0.0000000e+00,0.0000000e+00 +1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,total,-6.1444902e+02,6.0111692e+01 +1,U235,nuclide_density,absorption,2.3977134e+02,4.5868405e+01 +1,U235,nuclide_density,scatter,-8.5422036e+02,2.4877920e+01 +1,U235,nuclide_density,fission,3.1319132e+02,3.1465126e+01 +1,U235,nuclide_density,nu-fission,7.6415465e+02,7.6501604e+01 +1,U235,nuclide_density,total,5.0916179e+02,3.5499319e+01 +1,U235,nuclide_density,absorption,3.9477360e+02,3.4326165e+01 +1,U235,nuclide_density,scatter,1.1438818e+02,2.7378217e+00 +1,U235,nuclide_density,fission,3.1360739e+02,3.2243605e+01 +1,U235,nuclide_density,nu-fission,7.6527228e+02,7.8683697e+01 +1,U235,nuclide_density,total,-4.1815711e+03,8.7796611e+02 +1,U235,nuclide_density,absorption,-1.0563226e+02,2.5308627e+01 +1,U235,nuclide_density,scatter,-4.0759388e+03,8.5332185e+02 +1,U235,nuclide_density,fission,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,total,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,absorption,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,fission,0.0000000e+00,0.0000000e+00 +1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 +1,,temperature,total,2.1367130e-04,1.8632816e-04 +1,,temperature,absorption,6.9456249e-05,3.2199390e-05 +1,,temperature,scatter,1.4421505e-04,1.5754180e-04 +1,,temperature,fission,3.0674981e-06,1.8048377e-05 +1,,temperature,nu-fission,7.4768877e-06,4.3976766e-05 +1,,temperature,total,5.8223116e-06,2.3786474e-05 +1,,temperature,absorption,5.2142698e-06,2.1901911e-05 +1,,temperature,scatter,6.0804185e-07,1.9834890e-06 +1,,temperature,fission,3.0674200e-06,1.8048542e-05 +1,,temperature,nu-fission,7.4767028e-06,4.3977153e-05 +1,,temperature,total,2.1510156e-04,4.6388707e-04 +1,,temperature,absorption,2.2409527e-06,8.2901060e-06 +1,,temperature,scatter,2.1286061e-04,4.5560034e-04 +1,,temperature,fission,0.0000000e+00,0.0000000e+00 +1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 +1,,temperature,total,0.0000000e+00,0.0000000e+00 +1,,temperature,absorption,0.0000000e+00,0.0000000e+00 +1,,temperature,scatter,0.0000000e+00,0.0000000e+00 +1,,temperature,fission,0.0000000e+00,0.0000000e+00 +1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,absorption,-1.6517201e-01,3.0984738e-01 +3,,density,absorption,8.0402344e-03,1.4689335e-01 +1,,density,absorption,2.9069882e-02,2.2139609e-03 +1,,density,absorption,-9.4690065e-03,8.6605392e-03 +1,O16,nuclide_density,absorption,7.6911962e-01,4.1945687e-01 +1,O16,nuclide_density,absorption,-6.3724795e-01,6.6341488e-01 +1,U235,nuclide_density,absorption,1.4109543e+02,1.8518890e+01 +1,U235,nuclide_density,absorption,-1.2052822e+02,3.2084002e+01 +1,,temperature,absorption,3.9995404e-05,2.1703384e-05 +1,,temperature,absorption,2.7274361e-06,8.9339257e-06 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,scatter,-8.7934551e-01,1.0210652e+00 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,scatter,-3.5236516e-03,3.5236516e-03 +3,,density,nu-fission,7.2953012e-02,2.9725863e-01 +3,,density,scatter,-2.2716410e+00,1.2546347e+00 +3,,density,nu-fission,8.9171481e-02,3.0634856e-01 +3,,density,scatter,-1.0151747e-03,9.6296775e-03 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,scatter,2.3163923e+00,4.8766690e+00 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,scatter,0.0000000e+00,0.0000000e+00 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,scatter,4.0762434e-01,3.8504141e+00 +3,,density,nu-fission,0.0000000e+00,0.0000000e+00 +3,,density,scatter,0.0000000e+00,0.0000000e+00 diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index 5e34fd886..ecf281034 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -2,10 +2,7 @@ import glob import os -try: - from StringIO import StringIO -except: - from io import StringIO +from io import StringIO import sys import pandas as pd @@ -20,9 +17,9 @@ class DiffTallyTestHarness(PyAPITestHarness): self._input_set.build_default_materials_and_geometry() # Set settings explicitly - self._input_set.settings.batches = 5 + self._input_set.settings.batches = 3 self._input_set.settings.inactive = 0 - self._input_set.settings.particles = 400 + self._input_set.settings.particles = 100 self._input_set.settings.source = openmc.Source(space=openmc.stats.Box( [-160, -160, -183], [160, 160, 183])) self._input_set.settings.temperature['multipole'] = True @@ -30,7 +27,7 @@ class DiffTallyTestHarness(PyAPITestHarness): self._input_set.tallies = openmc.Tallies() filt_mats = openmc.MaterialFilter((1, 3)) - filt_eout = openmc.EnergyoutFilter((0.0, 1.0e6, 20.0e6)) + filt_eout = openmc.EnergyoutFilter((0.0, 0.625, 20.0e6)) # We want density derivatives for both water and fuel to get coverage # for both fissile and non-fissile materials. @@ -75,6 +72,7 @@ class DiffTallyTestHarness(PyAPITestHarness): t = openmc.Tally() t.add_score('total') t.add_score('absorption') + t.add_score('scatter') t.add_score('fission') t.add_score('nu-fission') t.add_filter(filt_mats) @@ -96,6 +94,7 @@ class DiffTallyTestHarness(PyAPITestHarness): for i in range(2): t = openmc.Tally() t.add_score('nu-fission') + t.add_score('scatter') t.add_filter(filt_mats) t.add_filter(filt_eout) t.add_nuclide('total') @@ -107,6 +106,7 @@ class DiffTallyTestHarness(PyAPITestHarness): for i in range(2, 5): t = openmc.Tally() t.add_score('nu-fission') + t.add_score('scatter') t.add_filter(filt_mats) t.add_filter(filt_eout) t.add_nuclide('U235') @@ -129,7 +129,7 @@ class DiffTallyTestHarness(PyAPITestHarness): out = StringIO() cols = ('d_material', 'd_nuclide', 'd_variable', 'score', 'mean', 'std. dev.') - df.to_csv(out, columns=cols, index=False, float_format='%.2e') + df.to_csv(out, columns=cols, index=False, float_format='%.7e') return out.getvalue() @@ -140,5 +140,5 @@ class DiffTallyTestHarness(PyAPITestHarness): if __name__ == '__main__': - harness = DiffTallyTestHarness('statepoint.5.*', True) + harness = DiffTallyTestHarness('statepoint.3.h5', True) harness.main() From 24ae87ea4cc5280093f4233c390502cdd6c4df41 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 13 Nov 2016 14:30:40 -0500 Subject: [PATCH 55/60] Go back to try/except on test_diff_tally StringIO --- tests/test_diff_tally/test_diff_tally.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index ecf281034..c5a0762a6 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -2,7 +2,10 @@ import glob import os -from io import StringIO +try: + from StringIO import StringIO +except: + from io import StringIO import sys import pandas as pd From fb009c6b5e1d5fe5a29eb9707839fef613ba3d3b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 14 Nov 2016 11:26:08 -0600 Subject: [PATCH 56/60] Use multidimensional array for tally results rather than derived type --- docs/source/io_formats/statepoint.rst | 10 +- openmc/particle_restart.py | 8 +- openmc/statepoint.py | 13 +- openmc/summary.py | 10 +- openmc/tallies.py | 13 +- openmc/volume.py | 3 +- src/cmfd_data.F90 | 39 +++-- src/cmfd_execute.F90 | 12 +- src/constants.F90 | 6 + src/eigenvalue.F90 | 14 +- src/finalize.F90 | 4 +- src/global.F90 | 16 +- src/hdf5_interface.F90 | 130 ----------------- src/initialize.F90 | 53 +------ src/input_xml.F90 | 1 - src/math.F90 | 3 +- src/output.F90 | 95 ++++++------ src/physics_mg.F90 | 8 +- src/simulation.F90 | 31 ++-- src/state_point.F90 | 50 +++---- src/tally.F90 | 201 ++++++++++++-------------- src/tally_header.F90 | 91 ++++++++++-- src/tally_initialize.F90 | 6 +- src/trigger.F90 | 16 +- 24 files changed, 331 insertions(+), 502 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index e8b8f8b90..7551f4293 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -224,12 +224,12 @@ if run_mode == 'k-eigenvalue': Tallying moment orders for Legendre and spherical harmonic tally expansions (*e.g.*, 'P2', 'Y1,2', etc.). -**/tallies/tally /results** (Compound type) +**/tallies/tally /results** (*double[][][2]*) - Accumulated sum and sum-of-squares for each bin of the i-th tally. This is a - two-dimensional array, the first dimension of which represents combinations - of filter bins and the second dimensions of which represents scoring - bins. Each element of the array has fields 'sum' and 'sum_sq'. + Accumulated sum and sum-of-squares for each bin of the i-th tally. The first + dimension represents combinations of filter bins, the second dimensions + represents scoring bins, and the third dimension has two entries for the sum + and the sum-of-squares. **/source_present** (*int*) diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index a0410298b..cb1326586 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -1,3 +1,5 @@ +import h5py + class Particle(object): """Information used to restart a specific particle that caused a simulation to fail. @@ -33,12 +35,6 @@ class Particle(object): """ def __init__(self, filename): - import h5py - if h5py.__version__ == '2.6.0': - raise ImportError("h5py 2.6.0 has a known bug which makes it " - "incompatible with OpenMC's HDF5 files. " - "Please switch to a different version.") - self._f = h5py.File(filename, 'r') # Ensure filetype and revision are correct diff --git a/openmc/statepoint.py b/openmc/statepoint.py index aaa5c0b84..e05b18ebe 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -5,6 +5,7 @@ import warnings import glob import numpy as np +import h5py import openmc import openmc.checkvalue as cv @@ -104,12 +105,6 @@ class StatePoint(object): """ def __init__(self, filename, autolink=True): - import h5py - if h5py.__version__ == '2.6.0': - raise ImportError("h5py 2.6.0 has a known bug which makes it " - "incompatible with OpenMC's HDF5 files. " - "Please switch to a different version.") - self._f = h5py.File(filename, 'r') # Ensure filetype and revision are correct @@ -209,13 +204,13 @@ class StatePoint(object): def global_tallies(self): if self._global_tallies is None: data = self._f['global_tallies'].value - gt = np.zeros_like(data, dtype=[ + gt = np.zeros(data.shape[0], dtype=[ ('name', 'a14'), ('sum', 'f8'), ('sum_sq', 'f8'), ('mean', 'f8'), ('std_dev', 'f8')]) gt['name'] = ['k-collision', 'k-absorption', 'k-tracklength', 'leakage'] - gt['sum'] = data['sum'] - gt['sum_sq'] = data['sum_sq'] + gt['sum'] = data[:,1] + gt['sum_sq'] = data[:,2] # Calculate mean and sample standard deviation of mean n = self.n_realizations diff --git a/openmc/summary.py b/openmc/summary.py index fd1689eb2..37509ec37 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -2,6 +2,7 @@ from collections import Iterable import re import numpy as np +import h5py import openmc from openmc.region import Region @@ -23,15 +24,6 @@ class Summary(object): """ def __init__(self, filename): - # A user may not have h5py, but they can still use the rest of the - # Python API so we'll only try to import h5py if the user actually inits - # a Summary object. - import h5py - if h5py.__version__ == '2.6.0': - raise ImportError("h5py 2.6.0 has a known bug which makes it " - "incompatible with OpenMC's HDF5 files. " - "Please switch to a different version.") - openmc.reset_auto_ids() if not filename.endswith(('.h5', '.hdf5')): diff --git a/openmc/tallies.py b/openmc/tallies.py index 604713145..28da08bad 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -13,6 +13,7 @@ from xml.etree import ElementTree as ET from six import string_types import numpy as np +import h5py import openmc import openmc.checkvalue as cv @@ -269,20 +270,14 @@ class Tally(object): return None if not self._results_read: - import h5py - if h5py.__version__ == '2.6.0': - raise ImportError("h5py 2.6.0 has a known bug which makes it " - "incompatible with OpenMC's HDF5 files. " - "Please switch to a different version.") - # Open the HDF5 statepoint file f = h5py.File(self._sp_filename, 'r') # Extract Tally data from the file data = f['tallies/tally {0}/results'.format( self.id)].value - sum = data['sum'] - sum_sq = data['sum_sq'] + sum = data[:,:,0] + sum_sq = data[:,:,1] # Reshape the results arrays sum = np.reshape(sum, self.shape) @@ -1726,8 +1721,6 @@ class Tally(object): # HDF5 binary file if format == 'hdf5': - import h5py - filename = directory + '/' + filename + '.h5' if append: diff --git a/openmc/volume.py b/openmc/volume.py index 2a2a92f61..b1391c687 100644 --- a/openmc/volume.py +++ b/openmc/volume.py @@ -5,6 +5,7 @@ from warnings import warn import numpy as np import pandas as pd +import h5py import openmc import openmc.checkvalue as cv @@ -187,8 +188,6 @@ class VolumeCalculation(object): Results of the stochastic volume calculation """ - import h5py - with h5py.File(filename, 'r') as f: domain_type = f.attrs['domain_type'].decode() samples = f.attrs['samples'] diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index e1bf1f9c3..e5ed5df70 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -164,7 +164,7 @@ contains * t%stride) + 1 ! Get flux - flux = t % results(1,score_index) % sum + flux = t % results(RESULT_SUM,1,score_index) cmfd % flux(h,i,j,k) = flux ! Detect zero flux, abort if located @@ -175,10 +175,10 @@ contains end if ! Get total rr and convert to total xs - cmfd % totalxs(h,i,j,k) = t % results(2,score_index) % sum / flux + cmfd % totalxs(h,i,j,k) = t % results(RESULT_SUM,2,score_index) / flux ! Get p1 scatter rr and convert to p1 scatter xs - cmfd % p1scattxs(h,i,j,k) = t % results(3,score_index) % sum / flux + cmfd % p1scattxs(h,i,j,k) = t % results(RESULT_SUM,3,score_index) / flux ! Calculate diffusion coefficient cmfd % diffcof(h,i,j,k) = ONE/(3.0_8*(cmfd % totalxs(h,i,j,k) - & @@ -211,19 +211,18 @@ contains * t%stride) + 1 ! Get scattering - cmfd % scattxs(h,g,i,j,k) = t % results(1,score_index) % sum /& + cmfd % scattxs(h,g,i,j,k) = t % results(RESULT_SUM,1,score_index) /& cmfd % flux(h,i,j,k) ! Get nu-fission - cmfd % nfissxs(h,g,i,j,k) = t % results(2,score_index) % sum /& + cmfd % nfissxs(h,g,i,j,k) = t % results(RESULT_SUM,2,score_index) /& cmfd % flux(h,i,j,k) ! Bank source cmfd % openmc_src(g,i,j,k) = cmfd % openmc_src(g,i,j,k) + & - t % results(2,score_index) % sum + t % results(RESULT_SUM,2,score_index) cmfd % keff_bal = cmfd % keff_bal + & - t % results(2,score_index) % sum / & - dble(t % n_realizations) + t % results(RESULT_SUM,2,score_index) / t % n_realizations end do INGROUP @@ -243,67 +242,67 @@ contains matching_bins(i_filter_surf) = OUT_LEFT score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(1,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(1,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = IN_LEFT score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(2,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(2,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Right surface matching_bins(i_filter_surf) = IN_RIGHT score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(3,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(3,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = OUT_RIGHT score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(4,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(4,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Back surface matching_bins(i_filter_surf) = OUT_BACK score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(5,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(5,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = IN_BACK score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(6,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(6,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Front surface matching_bins(i_filter_surf) = IN_FRONT score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(7,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(7,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = OUT_FRONT score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(8,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(8,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Bottom surface matching_bins(i_filter_surf) = OUT_BOTTOM score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(9,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(9,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = IN_BOTTOM score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(10,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(10,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Top surface matching_bins(i_filter_surf) = IN_TOP score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(11,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(11,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = OUT_TOP score_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 - cmfd % current(12,h,i,j,k) = t % results(1,score_index) % sum + cmfd % current(12,h,i,j,k) = t % results(RESULT_SUM,1,score_index) end if TALLY diff --git a/src/cmfd_execute.F90 b/src/cmfd_execute.F90 index d2631254b..a5d92002b 100644 --- a/src/cmfd_execute.F90 +++ b/src/cmfd_execute.F90 @@ -365,22 +365,18 @@ contains subroutine cmfd_tally_reset() - use global, only: n_cmfd_tallies, cmfd_tallies + use global, only: cmfd_tallies use output, only: write_message - use tally, only: reset_result integer :: i ! loop counter ! Print message call write_message("CMFD tallies reset", 7) - ! Begin loop around CMFD tallies - do i = 1, n_cmfd_tallies - - ! Reset that tally + ! Reset CMFD tallies + do i = 1, size(cmfd_tallies) cmfd_tallies(i) % n_realizations = 0 - call reset_result(cmfd_tallies(i) % results) - + cmfd_tallies(i) % results(:,:,:) = ZERO end do end subroutine cmfd_tally_reset diff --git a/src/constants.F90 b/src/constants.F90 index ac157d7ad..f2a9fb6f1 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -269,6 +269,12 @@ module constants ! ============================================================================ ! TALLY-RELATED CONSTANTS + ! Tally result entries + integer, parameter :: & + RESULT_VALUE = 1, & + RESULT_SUM = 2, & + RESULT_SUM_SQ = 3 + ! Tally type integer, parameter :: & TALLY_VOLUME = 1, & diff --git a/src/eigenvalue.F90 b/src/eigenvalue.F90 index 713bbc351..05c8190a6 100644 --- a/src/eigenvalue.F90 +++ b/src/eigenvalue.F90 @@ -374,7 +374,7 @@ contains subroutine calculate_generation_keff() ! Get keff for this generation by subtracting off the starting value - keff_generation = global_tallies(K_TRACKLENGTH) % value - keff_generation + keff_generation = global_tallies(RESULT_VALUE, K_TRACKLENGTH) - keff_generation #ifdef MPI ! Combine values across all processors @@ -466,14 +466,14 @@ contains k_combined = ZERO ! Copy estimates of k-effective and its variance (not variance of the mean) - kv(1) = global_tallies(K_COLLISION) % sum / n - kv(2) = global_tallies(K_ABSORPTION) % sum / n - kv(3) = global_tallies(K_TRACKLENGTH) % sum / n - cov(1,1) = (global_tallies(K_COLLISION) % sum_sq - & + kv(1) = global_tallies(RESULT_SUM, K_COLLISION) / n + kv(2) = global_tallies(RESULT_SUM, K_ABSORPTION) / n + kv(3) = global_tallies(RESULT_SUM, K_TRACKLENGTH) / n + cov(1,1) = (global_tallies(RESULT_SUM_SQ, K_COLLISION) - & n * kv(1) * kv(1)) / (n - 1) - cov(2,2) = (global_tallies(K_ABSORPTION) % sum_sq - & + cov(2,2) = (global_tallies(RESULT_SUM_SQ, K_ABSORPTION) - & n * kv(2) * kv(2)) / (n - 1) - cov(3,3) = (global_tallies(K_TRACKLENGTH) % sum_sq - & + cov(3,3) = (global_tallies(RESULT_SUM_SQ, K_TRACKLENGTH) - & n * kv(3) * kv(3)) / (n - 1) ! Calculate covariances based on sums with Bessel's correction diff --git a/src/finalize.F90 b/src/finalize.F90 index 86100d195..83a5ac5fa 100644 --- a/src/finalize.F90 +++ b/src/finalize.F90 @@ -9,7 +9,7 @@ module finalize use message_passing #endif - use hdf5_interface, only: hdf5_bank_t, hdf5_tallyresult_t + use hdf5_interface, only: hdf5_bank_t use hdf5, only: h5tclose_f, h5close_f implicit none @@ -53,7 +53,6 @@ contains call free_memory() ! Release compound datatypes - call h5tclose_f(hdf5_tallyresult_t, hdf5_err) call h5tclose_f(hdf5_bank_t, hdf5_err) ! Close FORTRAN interface. @@ -62,7 +61,6 @@ contains #ifdef MPI ! Free all MPI types call MPI_TYPE_FREE(MPI_BANK, mpi_err) - call MPI_TYPE_FREE(MPI_TALLYRESULT, mpi_err) ! If MPI is in use and enabled, terminate it call MPI_FINALIZE(mpi_err) diff --git a/src/global.F90 b/src/global.F90 index 8111fd514..eb4b33d7d 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -1,5 +1,11 @@ module global + use, intrinsic :: ISO_C_BINDING + +#ifdef MPIF08 + use mpi_f08 +#endif + use bank_header, only: Bank use cmfd_header use constants @@ -14,15 +20,11 @@ module global use set_header, only: SetInt use surface_header, only: SurfaceContainer use source_header, only: SourceDistribution - use tally_header, only: TallyObject, TallyResult + use tally_header, only: TallyObject use trigger_header, only: KTrigger use timer_header, only: Timer use volume_header, only: VolumeCalculation -#ifdef MPIF08 - use mpi_f08 -#endif - implicit none ! ============================================================================ @@ -164,7 +166,7 @@ module global ! 3) track-length estimate of k-eff ! 4) leakage fraction - type(TallyResult), allocatable, target :: global_tallies(:) + real(C_DOUBLE), allocatable, target :: global_tallies(:,:) ! It is possible to protect accumulate operations on global tallies by using ! an atomic update. However, when multiple threads accumulate to the same @@ -272,10 +274,8 @@ module global integer :: mpi_err ! MPI error code #ifdef MPIF08 type(MPI_Datatype) :: MPI_BANK - type(MPI_Datatype) :: MPI_TALLYRESULT #else integer :: MPI_BANK ! MPI datatype for fission bank - integer :: MPI_TALLYRESULT ! MPI datatype for TallyResult #endif #ifdef _OPENMP diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 2a0711954..5e14605ae 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -16,7 +16,6 @@ module hdf5_interface use h5lt use error, only: fatal_error - use tally_header, only: TallyResult #ifdef PHDF5 use message_passing, only: MPI_COMM_WORLD, MPI_INFO_NULL #endif @@ -24,7 +23,6 @@ module hdf5_interface implicit none private - integer(HID_T), public :: hdf5_tallyresult_t ! Compound type for TallyResult integer(HID_T), public :: hdf5_bank_t ! Compound type for Bank integer(HID_T), public :: hdf5_integer8_t ! type for integer(8) @@ -42,8 +40,6 @@ module hdf5_interface module procedure write_long module procedure write_string module procedure write_string_1D - module procedure write_tally_result_1D - module procedure write_tally_result_2D end interface write_dataset interface read_dataset @@ -60,8 +56,6 @@ module hdf5_interface module procedure read_long module procedure read_string module procedure read_string_1D - module procedure read_tally_result_1D - module procedure read_tally_result_2D module procedure read_complex_2D end interface read_dataset @@ -2063,130 +2057,6 @@ contains call h5ltset_attribute_string_f(group_id, var, attr_type, attr_str, hdf5_err) end subroutine write_attribute_string -!=============================================================================== -! WRITE_TALLY_RESULT writes an OpenMC TallyResult type -!=============================================================================== - - subroutine write_tally_result_1D(group_id, name, buffer) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(in), target :: buffer(:) ! data to write - - integer(HSIZE_T) :: dims(1) - - dims(:) = shape(buffer) - call write_tally_result_1D_explicit(group_id, dims, name, buffer) - end subroutine write_tally_result_1D - - subroutine write_tally_result_1D_explicit(group_id, dims, name, buffer) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(in), target :: buffer(dims(1)) - - integer :: hdf5_err - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - call h5screate_simple_f(1, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), hdf5_tallyresult_t, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_tally_result_1D_explicit - - subroutine write_tally_result_2D(group_id, name, buffer) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(in), target :: buffer(:,:) ! data to write - - integer(HSIZE_T) :: dims(2) - - dims(:) = shape(buffer) - call write_tally_result_2D_explicit(group_id, dims, name, buffer) - end subroutine write_tally_result_2D - - subroutine write_tally_result_2D_explicit(group_id, dims, name, buffer) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(2) - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(in), target :: buffer(dims(1),dims(2)) - - integer :: hdf5_err - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - call h5screate_simple_f(2, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), hdf5_tallyresult_t, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_tally_result_2D_explicit - -!=============================================================================== -! READ_TALLY_RESULT reads OpenMC TallyResult data -!=============================================================================== - - subroutine read_tally_result_1D(group_id, name, buffer) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(inout), target :: buffer(:) ! read data here - - integer(HSIZE_T) :: dims(1) - - dims(:) = shape(buffer) - call read_tally_result_1D_explicit(group_id, dims, name, buffer) - end subroutine read_tally_result_1D - - subroutine read_tally_result_1D_explicit(group_id, dims, name, buffer) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(inout), target :: buffer(dims(1)) - - integer :: hdf5_err - integer(HID_T) :: dset ! data set handle - type(c_ptr) :: f_ptr - - call h5dopen_f(group_id, trim(name), dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - call h5dclose_f(dset, hdf5_err) - end subroutine read_tally_result_1D_explicit - - subroutine read_tally_result_2D(group_id, name, buffer) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(inout), target :: buffer(:,:) - - integer(HSIZE_T) :: dims(2) - - dims(:) = shape(buffer) - call read_tally_result_2D_explicit(group_id, dims, name, buffer) - end subroutine read_tally_result_2D - - subroutine read_tally_result_2D_explicit(group_id, dims, name, buffer) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(2) - character(*), intent(in) :: name ! name of data - type(TallyResult), intent(inout), target :: buffer(dims(1),dims(2)) - - integer :: hdf5_err - integer(HID_T) :: dset ! data set handle - type(c_ptr) :: f_ptr - - call h5dopen_f(group_id, trim(name), dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - call h5dclose_f(dset, hdf5_err) - end subroutine read_tally_result_2D_explicit - subroutine read_attribute_double(buffer, obj_id, name) real(8), intent(inout), target :: buffer integer(HID_T), intent(in) :: obj_id diff --git a/src/initialize.F90 b/src/initialize.F90 index 4fe6f8769..d51f9ef8e 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -12,7 +12,7 @@ module initialize &BASE_UNIVERSE use global use hdf5_interface, only: file_open, read_dataset, file_close, hdf5_bank_t,& - hdf5_tallyresult_t, hdf5_integer8_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, create_macro_xs @@ -22,7 +22,7 @@ module initialize 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 + use tally_header, only: TallyObject use tally_initialize,only: configure_tallies use tally_filter use tally, only: init_tally_routines @@ -169,21 +169,11 @@ contains integer :: bank_blocks(5) ! Count for each datatype #ifdef MPIF08 type(MPI_Datatype) :: bank_types(5) - type(MPI_Datatype) :: result_types(1) - type(MPI_Datatype) :: temp_type #else integer :: bank_types(5) ! Datatypes - integer :: result_types(1) ! Datatypes - integer :: temp_type ! temporary derived type #endif integer(MPI_ADDRESS_KIND) :: bank_disp(5) ! Displacements - integer :: result_blocks(1) ! Count for each datatype - integer(MPI_ADDRESS_KIND) :: result_disp(1) ! Displacements - integer(MPI_ADDRESS_KIND) :: result_base_disp ! Base displacement - integer(MPI_ADDRESS_KIND) :: lower_bound ! Lower bound for TallyResult - integer(MPI_ADDRESS_KIND) :: extent ! Extent for TallyResult type(Bank) :: b - type(TallyResult) :: tr ! Indicate that MPI is turned on mpi_enabled = .true. @@ -221,36 +211,6 @@ contains call MPI_TYPE_CREATE_STRUCT(5, bank_blocks, bank_disp, & bank_types, MPI_BANK, mpi_err) call MPI_TYPE_COMMIT(MPI_BANK, mpi_err) - - ! ========================================================================== - ! CREATE MPI_TALLYRESULT TYPE - - ! Determine displacements for MPI_BANK type - call MPI_GET_ADDRESS(tr%value, result_base_disp, mpi_err) - call MPI_GET_ADDRESS(tr%sum, result_disp(1), mpi_err) - - ! Adjust displacements - result_disp = result_disp - result_base_disp - - ! Define temporary type for TallyResult - result_blocks = (/ 2 /) - result_types = (/ MPI_REAL8 /) - call MPI_TYPE_CREATE_STRUCT(1, result_blocks, result_disp, result_types, & - temp_type, mpi_err) - - ! Adjust lower-bound and extent of type for tally score - lower_bound = 0 - extent = result_disp(1) + 16 - call MPI_TYPE_CREATE_RESIZED(temp_type, lower_bound, extent, & - MPI_TALLYRESULT, mpi_err) - - ! Commit derived type for tally scores - call MPI_TYPE_COMMIT(MPI_TALLYRESULT, mpi_err) - - ! Free temporary MPI type - call MPI_TYPE_FREE(temp_type, mpi_err) - - end subroutine initialize_mpi #endif !=============================================================================== @@ -259,7 +219,6 @@ contains subroutine hdf5_initialize() - type(TallyResult), target :: tmp(2) ! temporary TallyResult type(Bank), target :: tmpb(2) ! temporary Bank integer :: hdf5_err integer(HID_T) :: coordinates_t ! HDF5 type for 3 reals @@ -268,14 +227,6 @@ contains ! Initialize FORTRAN interface. call h5open_f(hdf5_err) - ! Create the compound datatype for TallyResult - call h5tcreate_f(H5T_COMPOUND_F, h5offsetof(c_loc(tmp(1)), & - c_loc(tmp(2))), hdf5_tallyresult_t, hdf5_err) - call h5tinsert_f(hdf5_tallyresult_t, "sum", h5offsetof(c_loc(tmp(1)), & - c_loc(tmp(1)%sum)), H5T_NATIVE_DOUBLE, hdf5_err) - call h5tinsert_f(hdf5_tallyresult_t, "sum_sq", h5offsetof(c_loc(tmp(1)), & - c_loc(tmp(1)%sum_sq)), H5T_NATIVE_DOUBLE, hdf5_err) - ! Create compound type for xyz and uvw call h5tarray_create_f(H5T_NATIVE_DOUBLE, 1, dims, coordinates_t, hdf5_err) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index ff530c618..53cb11f98 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2039,7 +2039,6 @@ contains type(Library), allocatable :: libraries(:) type(VectorReal), allocatable :: nuc_temps(:) ! List of T to read for each nuclide type(VectorReal), allocatable :: sab_temps(:) ! List of T to read for each S(a,b) - character(MAX_LINE_LEN) :: temp_str real(8), allocatable :: material_temps(:) logical :: file_exists character(MAX_FILE_LEN) :: env_variable diff --git a/src/math.F90 b/src/math.F90 index 3ab8195aa..11ace6976 100644 --- a/src/math.F90 +++ b/src/math.F90 @@ -1,8 +1,9 @@ module math + use, intrinsic :: ISO_C_BINDING + use constants use random_lcg, only: prn - use ISO_C_BINDING implicit none diff --git a/src/output.F90 b/src/output.F90 index 8127725a6..6a8ba23b5 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -611,7 +611,7 @@ contains t_value = t_percentile(ONE - alpha/TWO, n_realizations - 1) ! Adjust sum_sq - global_tallies(:) % sum_sq = t_value * global_tallies(:) % sum_sq + global_tallies(RESULT_SUM_SQ,:) = t_value * global_tallies(RESULT_SUM_SQ,:) ! Adjust combined estimator if (n_realizations > 3) then @@ -623,26 +623,26 @@ contains ! write global tallies if (n_realizations > 1) then if (run_mode == MODE_EIGENVALUE) then - write(ou,102) "k-effective (Collision)", global_tallies(K_COLLISION) & - % sum, global_tallies(K_COLLISION) % sum_sq - write(ou,102) "k-effective (Track-length)", global_tallies(K_TRACKLENGTH) & - % sum, global_tallies(K_TRACKLENGTH) % sum_sq - write(ou,102) "k-effective (Absorption)", global_tallies(K_ABSORPTION) & - % sum, global_tallies(K_ABSORPTION) % sum_sq + write(ou,102) "k-effective (Collision)", global_tallies(RESULT_SUM, & + K_COLLISION), global_tallies(RESULT_SUM_SQ, K_COLLISION) + write(ou,102) "k-effective (Track-length)", global_tallies(RESULT_SUM, & + K_TRACKLENGTH), global_tallies(RESULT_SUM_SQ, K_TRACKLENGTH) + write(ou,102) "k-effective (Absorption)", global_tallies(RESULT_SUM, & + K_ABSORPTION), global_tallies(RESULT_SUM_SQ, K_ABSORPTION) if (n_realizations > 3) write(ou,102) "Combined k-effective", k_combined end if - write(ou,102) "Leakage Fraction", global_tallies(LEAKAGE) % sum, & - global_tallies(LEAKAGE) % sum_sq + write(ou,102) "Leakage Fraction", global_tallies(RESULT_SUM, LEAKAGE), & + global_tallies(RESULT_SUM_SQ, LEAKAGE) else if (master) call warning("Could not compute uncertainties -- only one & &active batch simulated!") if (run_mode == MODE_EIGENVALUE) then - write(ou,103) "k-effective (Collision)", global_tallies(K_COLLISION) % sum - write(ou,103) "k-effective (Track-length)", global_tallies(K_TRACKLENGTH) % sum - write(ou,103) "k-effective (Absorption)", global_tallies(K_ABSORPTION) % sum + write(ou,103) "k-effective (Collision)", global_tallies(RESULT_SUM, K_COLLISION) + write(ou,103) "k-effective (Track-length)", global_tallies(RESULT_SUM, K_TRACKLENGTH) + write(ou,103) "k-effective (Absorption)", global_tallies(RESULT_SUM, K_ABSORPTION) end if - write(ou,103) "Leakage Fraction", global_tallies(LEAKAGE) % sum + write(ou,103) "Leakage Fraction", global_tallies(RESULT_SUM, LEAKAGE) end if write(ou,*) @@ -765,7 +765,7 @@ contains end if ! Multiply uncertainty by t-value - t % results % sum_sq = t_value * t % results % sum_sq + t % results(RESULT_SUM_SQ,:,:) = t_value * t % results(RESULT_SUM_SQ,:,:) end if ! Write header block @@ -876,8 +876,8 @@ contains score_names(abs(t % score_bins(k))) write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & - to_str(t % results(score_index,filter_index) % sum), & - trim(to_str(t % results(score_index,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,score_index,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,score_index,filter_index))) case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) score_index = score_index - 1 do n_order = 0, t % moment_order(k) @@ -886,9 +886,8 @@ contains score_names(abs(t % score_bins(k))) write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & - to_str(t % results(score_index,filter_index) % sum), & - trim(to_str(t % results(score_index,filter_index) & - % sum_sq)) + to_str(t % results(RESULT_SUM,score_index,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,score_index,filter_index))) end do k = k + t % moment_order(k) case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & @@ -902,9 +901,9 @@ contains // score_names(abs(t % score_bins(k))) write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & - to_str(t % results(score_index,filter_index) % sum), & - trim(to_str(t % results(score_index,filter_index)& - % sum_sq)) + to_str(t % results(RESULT_SUM,score_index,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,score_index,& + filter_index))) end do end do k = k + (t % moment_order(k) + 1)**2 - 1 @@ -916,8 +915,8 @@ contains end if write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & - to_str(t % results(score_index,filter_index) % sum), & - trim(to_str(t % results(score_index,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,score_index,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,score_index,filter_index))) end select end do indent = indent - 2 @@ -1020,16 +1019,16 @@ contains * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Left", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_LEFT filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Left", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) ! Right Surface matching_bins(i_filter_surf) = OUT_RIGHT @@ -1037,16 +1036,16 @@ contains * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Right", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_RIGHT filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Right", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) if (n_dim >= 2) then @@ -1056,16 +1055,16 @@ contains * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Back", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_BACK filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Back", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) ! Front Surface matching_bins(i_filter_surf) = OUT_FRONT @@ -1073,16 +1072,16 @@ contains * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_FRONT filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) end if if (n_dim == 3) then @@ -1092,16 +1091,16 @@ contains * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Bottom", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_BOTTOM filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Bottom", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) ! Top Surface matching_bins(i_filter_surf) = OUT_TOP @@ -1109,16 +1108,16 @@ contains * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Top", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_TOP filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Top", & - to_str(t % results(1,filter_index) % sum), & - trim(to_str(t % results(1,filter_index) % sum_sq)) + to_str(t % results(RESULT_SUM,1,filter_index)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) end if end do end do diff --git a/src/physics_mg.F90 b/src/physics_mg.F90 index 776c7905a..082b337a4 100644 --- a/src/physics_mg.F90 +++ b/src/physics_mg.F90 @@ -119,16 +119,16 @@ contains ! Score implicit absorption estimate of keff !$omp atomic - global_tallies(K_ABSORPTION) % value = & - global_tallies(K_ABSORPTION) % value + p % absorb_wgt * & + global_tallies(RESULT_VALUE, K_ABSORPTION) = & + global_tallies(RESULT_VALUE, K_ABSORPTION) + 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 * & + global_tallies(RESULT_VALUE, K_ABSORPTION) = & + global_tallies(RESULT_VALUE, K_ABSORPTION) + p % wgt * & material_xs % nu_fission / material_xs % absorption p % alive = .false. diff --git a/src/simulation.F90 b/src/simulation.F90 index f59ce371c..ef055a549 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -20,8 +20,7 @@ module simulation use source, only: initialize_source, sample_external_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 tally, only: synchronize_tallies, setup_active_usertallies use trigger, only: check_triggers use tracking, only: transport use volume_calc, only: run_volume_calculations @@ -220,7 +219,7 @@ contains if (ufs) call count_source_for_ufs() ! Store current value of tracklength k - keff_generation = global_tallies(K_TRACKLENGTH) % value + keff_generation = global_tallies(RESULT_VALUE, K_TRACKLENGTH) end if end subroutine initialize_generation @@ -237,24 +236,24 @@ contains !$omp parallel !$omp critical if (run_mode == MODE_EIGENVALUE) then - global_tallies(K_COLLISION) % value = & - global_tallies(K_COLLISION) % value + global_tally_collision - global_tallies(K_ABSORPTION) % value = & - global_tallies(K_ABSORPTION) % value + global_tally_absorption - global_tallies(K_TRACKLENGTH) % value = & - global_tallies(K_TRACKLENGTH) % value + global_tally_tracklength + global_tallies(RESULT_VALUE, K_COLLISION) = & + global_tallies(RESULT_VALUE, K_COLLISION) + global_tally_collision + global_tallies(RESULT_VALUE, K_ABSORPTION) = & + global_tallies(RESULT_VALUE, K_ABSORPTION) + global_tally_absorption + global_tallies(RESULT_VALUE, K_TRACKLENGTH) = & + global_tallies(RESULT_VALUE, K_TRACKLENGTH) + global_tally_tracklength end if - global_tallies(LEAKAGE) % value = & - global_tallies(LEAKAGE) % value + global_tally_leakage + global_tallies(RESULT_VALUE, LEAKAGE) = & + global_tallies(RESULT_VALUE, LEAKAGE) + global_tally_leakage !$omp end critical ! reset private tallies if (run_mode == MODE_EIGENVALUE) then - global_tally_collision = 0 - global_tally_absorption = 0 - global_tally_tracklength = 0 + global_tally_collision = ZERO + global_tally_absorption = ZERO + global_tally_tracklength = ZERO end if - global_tally_leakage = 0 + global_tally_leakage = ZERO !$omp end parallel if (run_mode == MODE_EIGENVALUE) then @@ -302,7 +301,7 @@ contains ! Reset global tally results if (.not. active_batches) then - call reset_result(global_tallies) + global_tallies(:,:) = ZERO n_realizations = 0 end if diff --git a/src/state_point.F90 b/src/state_point.F90 index 6b7a467d4..f9616f228 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -353,7 +353,7 @@ contains ! Write sum and sum_sq for each bin tally_group = open_group(tallies_group, "tally " & // to_str(tally % id)) - call write_dataset(tally_group, "results", tally % results) + call tally % write_results_hdf5(tally_group) call close_group(tally_group) end do TALLY_RESULTS @@ -481,7 +481,7 @@ contains integer :: n_bins ! total number of bins integer(HID_T) :: tallies_group, tally_group real(8), allocatable :: tally_temp(:,:,:) ! contiguous array of results - real(8), target :: global_temp(2,N_GLOBAL_TALLIES) + real(8), target :: global_temp(3,N_GLOBAL_TALLIES) #ifdef MPI real(8) :: dummy ! temporary receive buffer for non-root reduces #endif @@ -489,7 +489,7 @@ contains type(ElemKeyValueII), pointer :: current type(ElemKeyValueII), pointer :: next type(TallyObject), pointer :: tally - type(TallyResult), allocatable :: tallyresult_temp(:,:) + type(TallyObject) :: dummy_tally ! ========================================================================== ! COLLECT AND WRITE GLOBAL TALLIES @@ -505,9 +505,8 @@ contains end if ! Copy global tallies into temporary array for reducing - n_bins = 2 * N_GLOBAL_TALLIES - global_temp(1,:) = global_tallies(:)%sum - global_temp(2,:) = global_tallies(:)%sum_sq + n_bins = 3 * N_GLOBAL_TALLIES + global_temp(:,:) = global_tallies(:,:) if (master) then ! The MPI_IN_PLACE specifier allows the master to copy values into a @@ -519,20 +518,11 @@ contains ! Transfer values to value on master if (current_batch == n_max_batches .or. satisfy_triggers) then - global_tallies(:)%sum = global_temp(1,:) - global_tallies(:)%sum_sq = global_temp(2,:) + global_tallies(:,:) = global_temp(:,:) end if - ! Put reduced value in temporary tally result - allocate(tallyresult_temp(N_GLOBAL_TALLIES, 1)) - tallyresult_temp(:,1)%sum = global_temp(1,:) - tallyresult_temp(:,1)%sum_sq = global_temp(2,:) - ! Write out global tallies sum and sum_sq - call write_dataset(file_id, "global_tallies", tallyresult_temp) - - ! Deallocate temporary tally result - deallocate(tallyresult_temp) + call write_dataset(file_id, "global_tallies", global_temp) else ! Receive buffer not significant at other processors #ifdef MPI @@ -568,15 +558,15 @@ contains tally => tallies(i) ! Determine size of tally results array - m = size(tally%results, 1) - n = size(tally%results, 2) + m = size(tally%results, 2) + n = size(tally%results, 3) n_bins = m*n*2 ! Allocate array for storing sums and sums of squares, but ! contiguously in memory for each allocate(tally_temp(2,m,n)) - tally_temp(1,:,:) = tally%results(:,:)%sum - tally_temp(2,:,:) = tally%results(:,:)%sum_sq + tally_temp(1,:,:) = tally%results(RESULT_SUM,:,:) + tally_temp(2,:,:) = tally%results(RESULT_SUM_SQ,:,:) if (master) then tally_group = open_group(tallies_group, "tally " // & @@ -592,20 +582,20 @@ contains ! At the end of the simulation, store the results back in the ! regular TallyResults array if (current_batch == n_max_batches .or. satisfy_triggers) then - tally%results(:,:)%sum = tally_temp(1,:,:) - tally%results(:,:)%sum_sq = tally_temp(2,:,:) + tally%results(RESULT_SUM,:,:) = tally_temp(1,:,:) + tally%results(RESULT_SUM_SQ,:,:) = tally_temp(2,:,:) end if ! Put in temporary tally result - allocate(tallyresult_temp(m,n)) - tallyresult_temp(:,:)%sum = tally_temp(1,:,:) - tallyresult_temp(:,:)%sum_sq = tally_temp(2,:,:) + allocate(dummy_tally % results(3,m,n)) + dummy_tally % results(RESULT_SUM,:,:) = tally_temp(1,:,:) + dummy_tally % results(RESULT_SUM_SQ,:,:) = tally_temp(2,:,:) ! Write reduced tally results to file - call write_dataset(tally_group, "results", tally%results) + call dummy_tally % write_results_hdf5(tally_group) ! Deallocate temporary tally result - deallocate(tallyresult_temp) + deallocate(dummy_tally % results) else ! Receive buffer not significant at other processors #ifdef MPI @@ -771,7 +761,7 @@ contains call read_dataset(n_realizations, file_id, "n_realizations", indep=.true.) ! Read global tally data - call read_dataset(file_id, "global_tallies", global_tallies) + call read_dataset(global_tallies, file_id, "global_tallies") ! Check if tally results are present tallies_group = open_group(file_id, "tallies") @@ -787,7 +777,7 @@ contains ! Read sum, sum_sq, and N for each bin tally_group = open_group(tallies_group, "tally " // & trim(to_str(tally % id))) - call read_dataset(tally_group, "results", tally % results) + call tally % read_results_hdf5(tally_group) call read_dataset(tally % n_realizations, tally_group, & "n_realizations") call close_group(tally_group) diff --git a/src/tally.F90 b/src/tally.F90 index 69e4e8ecd..d4968d9d6 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -1,5 +1,7 @@ module tally + use, intrinsic :: ISO_C_BINDING + #ifdef MPI use message_passing #endif @@ -18,7 +20,6 @@ module tally use output, only: header use particle_header, only: LocalCoord, Particle use string, only: to_str - use tally_header, only: TallyResult use tally_filter implicit none @@ -1965,8 +1966,8 @@ contains 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 + t % results(RESULT_VALUE, score_index, filter_index) = & + t % results(RESULT_VALUE, score_index, filter_index) + score case(SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN) @@ -1982,10 +1983,9 @@ contains ! 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 & + t % results(RESULT_VALUE, score_index: score_index + num_nm - 1, & + filter_index) = t % results(RESULT_VALUE, & + score_index: score_index + num_nm - 1, filter_index) & + score * calc_pn(n, p % mu) * calc_rn(n, p % last_uvw) !$omp end critical (score_general_scatt_yn) end do @@ -2011,10 +2011,9 @@ contains ! 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 & + t % results(RESULT_VALUE, score_index: score_index + num_nm - 1, & + filter_index) = t % results(RESULT_VALUE, & + score_index: score_index + num_nm - 1, filter_index) & + score * calc_rn(n, uvw) !$omp end critical (score_general_flux_tot_yn) end do @@ -2031,8 +2030,8 @@ contains ! get the score and tally it !$omp atomic - t % results(score_index, filter_index) % value = & - t % results(score_index, filter_index) % value & + t % results(RESULT_VALUE, score_index, filter_index) = & + t % results(RESULT_VALUE, score_index, filter_index) & + score * calc_pn(n, p % mu) end do i = i + t % moment_order(i) @@ -2040,8 +2039,8 @@ contains case default !$omp atomic - t % results(score_index, filter_index) % value = & - t % results(score_index, filter_index) % value + score + t % results(RESULT_VALUE, score_index, filter_index) = & + t % results(RESULT_VALUE, score_index, filter_index) + score end select @@ -2458,8 +2457,8 @@ contains ! Add score to tally !$omp atomic - t % results(i_score, i_filter) % value = & - t % results(i_score, i_filter) % value + score * filter_weight + t % results(RESULT_VALUE, i_score, i_filter) = & + t % results(RESULT_VALUE, i_score, i_filter) + score * filter_weight ! Case for tallying delayed emissions else if (score_bin == SCORE_DELAYED_NU_FISSION .and. g /= 0) then @@ -2498,8 +2497,8 @@ contains ! Add score to tally !$omp atomic - t % results(i_score, i_filter) % value = & - t % results(i_score, i_filter) % value + score * filter_weight + t % results(RESULT_VALUE, i_score, i_filter) = & + t % results(RESULT_VALUE, i_score, i_filter) + score * filter_weight end if end if end do @@ -2536,8 +2535,8 @@ contains filter_weight = product(filter_weights(:size(t % filters))) !$omp atomic - t % results(score_index, filter_index) % value = & - t % results(score_index, filter_index) % value + score * filter_weight + t % results(RESULT_VALUE, score_index, filter_index) = & + t % results(RESULT_VALUE, score_index, filter_index) + score * filter_weight ! reset original delayed group bin matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) = bin_original @@ -2997,8 +2996,8 @@ contains filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 !$omp atomic - t % results(1, filter_index) % value = & - t % results(1, filter_index) % value + p % wgt + t % results(RESULT_VALUE, 1, filter_index) = & + t % results(RESULT_VALUE, 1, filter_index) + p % wgt end if ! Inward current on d1 min surface @@ -3033,8 +3032,8 @@ contains filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 !$omp atomic - t % results(1, filter_index) % value = & - t % results(1, filter_index) % value + p % wgt + t % results(RESULT_VALUE, 1, filter_index) = & + t % results(RESULT_VALUE, 1, filter_index) + p % wgt ijk0(d1) = ijk0(d1) - 1 end if @@ -3053,8 +3052,8 @@ contains filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 !$omp atomic - t % results(1, filter_index) % value = & - t % results(1, filter_index) % value + p % wgt + t % results(RESULT_VALUE, 1, filter_index) = & + t % results(RESULT_VALUE, 1, filter_index) + p % wgt end if ! Inward current on d1 max surface @@ -3089,8 +3088,8 @@ contains filter_index = sum((matching_bins(1:size(t % filters)) - 1) & * t % stride) + 1 !$omp atomic - t % results(1, filter_index) % value = & - t % results(1, filter_index) % value + p % wgt + t % results(RESULT_VALUE, 1, filter_index) = & + t % results(RESULT_VALUE, 1, filter_index) + p % wgt ijk0(d1) = ijk0(d1) + 1 end if @@ -3116,9 +3115,10 @@ contains subroutine synchronize_tallies() integer :: i - real(8) :: k_col ! Copy of batch collision estimate of keff - real(8) :: k_abs ! Copy of batch absorption estimate of keff - real(8) :: k_tra ! Copy of batch tracklength estimate of keff + real(C_DOUBLE) :: k_col ! Copy of batch collision estimate of keff + real(C_DOUBLE) :: k_abs ! Copy of batch absorption estimate of keff + real(C_DOUBLE) :: k_tra ! Copy of batch tracklength estimate of keff + real(C_DOUBLE) :: val #ifdef MPI ! Combine tally results onto master process @@ -3142,9 +3142,9 @@ contains if (run_mode == MODE_EIGENVALUE) then if (active_batches) then ! Accumulate products of different estimators of k - k_col = global_tallies(K_COLLISION) % value / total_weight - k_abs = global_tallies(K_ABSORPTION) % value / total_weight - k_tra = global_tallies(K_TRACKLENGTH) % value / total_weight + k_col = global_tallies(RESULT_VALUE, K_COLLISION) / total_weight + k_abs = global_tallies(RESULT_VALUE, K_ABSORPTION) / total_weight + k_tra = global_tallies(RESULT_VALUE, K_TRACKLENGTH) / total_weight k_col_abs = k_col_abs + k_col * k_abs k_col_tra = k_col_tra + k_col * k_tra k_abs_tra = k_abs_tra + k_abs * k_tra @@ -3152,7 +3152,14 @@ contains end if ! Accumulate results for global tallies - call accumulate_result(global_tallies) + do i = 1, size(global_tallies, 2) + val = global_tallies(RESULT_VALUE, i)/total_weight + global_tallies(RESULT_VALUE, i) = ZERO + + global_tallies(RESULT_SUM, i) = global_tallies(RESULT_SUM, i) + val + global_tallies(RESULT_SUM_SQ, i) = & + global_tallies(RESULT_SUM_SQ, i) + val*val + end do end if end subroutine synchronize_tallies @@ -3182,7 +3189,7 @@ contains allocate(tally_temp(m,n)) - tally_temp = t % results(:,:) % value + tally_temp = t % results(RESULT_VALUE,:,:) if (master) then ! The MPI_IN_PLACE specifier allows the master to copy values into @@ -3191,35 +3198,35 @@ contains MPI_SUM, 0, MPI_COMM_WORLD, mpi_err) ! Transfer values to value on master - t % results(:,:) % value = tally_temp + t % results(RESULT_VALUE,:,:) = tally_temp else ! Receive buffer not significant at other processors call MPI_REDUCE(tally_temp, dummy, n_bins, MPI_REAL8, & MPI_SUM, 0, MPI_COMM_WORLD, mpi_err) ! Reset value on other processors - t % results(:,:) % value = 0 + t % results(RESULT_VALUE,:,:) = ZERO end if deallocate(tally_temp) end do ! Copy global tallies into array to be reduced - global_temp = global_tallies(:) % value + global_temp = global_tallies(RESULT_VALUE, :) if (master) then call MPI_REDUCE(MPI_IN_PLACE, global_temp, N_GLOBAL_TALLIES, & MPI_REAL8, MPI_SUM, 0, MPI_COMM_WORLD, mpi_err) ! Transfer values back to global_tallies on master - global_tallies(:) % value = global_temp + global_tallies(RESULT_VALUE, :) = global_temp else ! Receive buffer not significant at other processors call MPI_REDUCE(global_temp, dummy, N_GLOBAL_TALLIES, & MPI_REAL8, MPI_SUM, 0, MPI_COMM_WORLD, mpi_err) ! Reset value on other processors - global_tallies(:) % value = ZERO + global_tallies(RESULT_VALUE, :) = ZERO end if ! We also need to determine the total starting weight of particles from the @@ -3244,6 +3251,9 @@ contains type(TallyObject), intent(inout) :: t + integer :: i, j + real(C_DOUBLE) :: val + ! Increment number of realizations if (reduce_tallies) then t % n_realizations = t % n_realizations + 1 @@ -3251,92 +3261,59 @@ contains t % n_realizations = t % n_realizations + n_procs end if - ! Accumulate each TallyResult - call accumulate_result(t % results) + ! Accumulate each result + do j = 1, size(t % results, 3) + do i = 1, size(t % results, 2) + val = t % results(RESULT_VALUE, i, j)/total_weight + t % results(RESULT_VALUE, i, j) = ZERO + + t % results(RESULT_SUM, i, j) = & + t % results(RESULT_SUM, i, j) + val + t % results(RESULT_SUM_SQ, i, j) = & + t % results(RESULT_SUM_SQ, i, j) + val*val + end do + end do end subroutine accumulate_tally !=============================================================================== ! TALLY_STATISTICS computes the mean and standard deviation of the mean of each -! tally and stores them in the val and val_sq attributes of the TallyResults -! respectively +! tally and stores them in the RESULT_SUM and RESULT_SUM_SQ positions !=============================================================================== subroutine tally_statistics() - integer :: i ! index in tallies array - type(TallyObject), pointer :: t - - ! Calculate statistics for user-defined tallies - do i = 1, n_tallies - t => tallies(i) - - call statistics_result(t % results, t % n_realizations) - end do - - ! Calculate statistics for global tallies - call statistics_result(global_tallies, n_realizations) - - end subroutine tally_statistics - -!=============================================================================== -! ACCUMULATE_RESULT accumulates results from many histories (or many generations) -! into a single realization of a random variable. -!=============================================================================== - - elemental subroutine accumulate_result(this) - - type(TallyResult), intent(inout) :: this - - real(8) :: val - - ! Add the sum and square of the sum of contributions from a tally result to - ! the variables sum and sum_sq. This will later allow us to calculate a - ! variance on the tallies. - - val = this % value/total_weight - this % sum = this % sum + val - this % sum_sq = this % sum_sq + val*val - - ! Reset the single batch estimate - this % value = ZERO - - end subroutine accumulate_result - -!=============================================================================== -! STATISTICS_RESULT determines the sample mean and the standard deviation of the -! mean for a TallyResult. -!=============================================================================== - - elemental subroutine statistics_result(this, n) - - type(TallyResult), intent(inout) :: this - integer, intent(in) :: n + integer :: j, k ! score/filter indices + integer :: n ! number of realizations ! Calculate sample mean and standard deviation of the mean -- note that we ! have used Bessel's correction so that the estimator of the variance of the ! sample mean is unbiased. - this % sum = this % sum/n - this % sum_sq = sqrt((this % sum_sq/n - this % sum * & - this % sum) / (n - 1)) + do i = 1, n_tallies + n = tallies(i) % n_realizations - end subroutine statistics_result + associate (r => tallies(i) % results) + do k = 1, size(r, 3) + do j = 1, size(r, 2) + r(RESULT_SUM, j, k) = r(RESULT_SUM, j, k) / n + r(RESULT_SUM_SQ, j, k) = sqrt((r(RESULT_SUM_SQ, j, k)/n - & + r(RESULT_SUM, j, k) * r(RESULT_SUM, j, k))/(n - 1)) + end do + end do + end associate + end do -!=============================================================================== -! RESET_RESULT zeroes out the value and accumulated sum and sum-squared for a -! single TallyResult. -!=============================================================================== - - elemental subroutine reset_result(this) - - type(TallyResult), intent(inout) :: this - - this % value = ZERO - this % sum = ZERO - this % sum_sq = ZERO - - end subroutine reset_result + ! Calculate statistics for global tallies + n = n_realizations + associate (r => global_tallies) + do j = 1, size(r, 2) + r(RESULT_SUM, j) = r(RESULT_SUM, j) / n + r(RESULT_SUM_SQ, j) = sqrt((r(RESULT_SUM_SQ, j)/n - & + r(RESULT_SUM, j) * r(RESULT_SUM, j))/(n - 1)) + end do + end associate + end subroutine tally_statistics !=============================================================================== ! SETUP_ACTIVE_USERTALLIES diff --git a/src/tally_header.F90 b/src/tally_header.F90 index fe385458b..eeda03e76 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -1,23 +1,15 @@ module tally_header + use, intrinsic :: ISO_C_BINDING + + use hdf5 + use constants, only: NONE, N_FILTER_TYPES use tally_filter_header, only: TallyFilterContainer use trigger_header, only: TriggerObject - use, intrinsic :: ISO_C_BINDING - implicit none -!=============================================================================== -! TALLYRESULT provides accumulation of results in a particular tally bin -!=============================================================================== - - type, bind(C) :: TallyResult - real(C_DOUBLE) :: value = 0. - real(C_DOUBLE) :: sum = 0. - real(C_DOUBLE) :: sum_sq = 0. - end type TallyResult - !=============================================================================== ! TALLYOBJECT describes a user-specified tally. The region of phase space to ! tally in is given by the TallyFilters and the results are stored in a @@ -68,7 +60,7 @@ module tally_header integer :: total_filter_bins integer :: total_score_bins - type(TallyResult), allocatable :: results(:,:) + real(C_DOUBLE), allocatable :: results(:,:,:) ! reset property - allows a tally to be reset after every batch logical :: reset = .false. @@ -79,6 +71,79 @@ module tally_header ! Tally precision triggers integer :: n_triggers = 0 ! # of triggers type(TriggerObject), allocatable :: triggers(:) ! Array of triggers + + contains + procedure :: write_results_hdf5 + procedure :: read_results_hdf5 end type TallyObject +contains + + subroutine write_results_hdf5(this, group_id) + class(TallyObject), intent(in) :: this + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer(HID_T) :: dset, dspace + integer(HID_T) :: memspace + integer(HSIZE_T) :: dims(3) + integer(HSIZE_T) :: dims_slab(3) + integer(HSIZE_T) :: offset(3) = [1,0,0] + + ! Create file dataspace + dims_slab(:) = shape(this % results) + dims_slab(1) = 2 + call h5screate_simple_f(3, dims_slab, dspace, hdf5_err) + + ! Create memory dataspace that contains only SUM and SUM_SQ values + dims(:) = shape(this % results) + call h5screate_simple_f(3, dims, memspace, hdf5_err) + call h5sselect_hyperslab_f(memspace, H5S_SELECT_SET_F, offset, dims_slab, & + hdf5_err) + + ! Create and write to dataset + call h5dcreate_f(group_id, "results", H5T_NATIVE_DOUBLE, dspace, dset, & + hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, this % results, dims_slab, & + hdf5_err, mem_space_id=memspace) + + ! Close identifiers + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_results_hdf5 + + subroutine read_results_hdf5(this, group_id) + class(TallyObject), intent(inout) :: this + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer(HID_T) :: dset, dspace + integer(HID_T) :: memspace + integer(HSIZE_T) :: dims(3) + integer(HSIZE_T) :: dims_slab(3) + integer(HSIZE_T) :: offset(3) = [1,0,0] + + ! Create file dataspace + dims_slab(:) = shape(this % results) + dims_slab(1) = 2 + call h5screate_simple_f(3, dims_slab, dspace, hdf5_err) + + ! Create memory dataspace that contains only SUM and SUM_SQ values + dims(:) = shape(this % results) + call h5screate_simple_f(3, dims, memspace, hdf5_err) + call h5sselect_hyperslab_f(memspace, H5S_SELECT_SET_F, offset, dims_slab, & + hdf5_err) + + ! Create and write to dataset + call h5dopen_f(group_id, "results", dset, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, this % results, dims_slab, & + hdf5_err, mem_space_id=memspace) + + ! Close identifiers + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine read_results_hdf5 + end module tally_header diff --git a/src/tally_initialize.F90 b/src/tally_initialize.F90 index 1ae403bd6..0e7a50a9c 100644 --- a/src/tally_initialize.F90 +++ b/src/tally_initialize.F90 @@ -20,7 +20,8 @@ contains subroutine configure_tallies() ! Allocate global tallies - allocate(global_tallies(N_GLOBAL_TALLIES)) + allocate(global_tallies(3, N_GLOBAL_TALLIES)) + global_tallies(:,:) = ZERO call setup_tally_arrays() @@ -62,7 +63,8 @@ contains t % total_score_bins = t % n_score_bins * t % n_nuclide_bins ! Allocate results array - allocate(t % results(t % total_score_bins, t % total_filter_bins)) + allocate(t % results(3, t % total_score_bins, t % total_filter_bins)) + t % results(:,:,:) = ZERO end do TALLY_LOOP diff --git a/src/trigger.F90 b/src/trigger.F90 index 39786809b..f41cc46cf 100644 --- a/src/trigger.F90 +++ b/src/trigger.F90 @@ -432,17 +432,19 @@ contains real(8), intent(inout) :: rel_err ! tally relative error integer, intent(in) :: score_index ! tally results score index integer, intent(in) :: filter_index ! tally results filter index - integer :: n ! number of realizations - real(8) :: mean ! tally mean - type(TallyResult) :: tally_result ! pointer to TallyResult - type(TallyObject), pointer :: t ! tally pointer + type(TallyObject), intent(in) :: t ! tally + + integer :: n ! number of realizations + real(8) :: mean ! tally mean + real(8) :: tally_sum, tally_sum_sq ! results for a single tally bin n = t % n_realizations - tally_result = t % results(score_index, filter_index) + tally_sum = t % results(RESULT_SUM, score_index, filter_index) + tally_sum_sq = t % results(RESULT_SUM_SQ, score_index, filter_index) ! Compute the tally mean and standard deviation - mean = tally_result % sum / n - std_dev = sqrt((tally_result % sum_sq / n - mean * mean) / (n - 1)) + mean = tally_sum / n + std_dev = sqrt((tally_sum_sq / n - mean * mean) / (n - 1)) ! Compute the relative error if the mean is non-zero if (mean == ZERO) then From 0bd1ddd569f944b300549911ea9235f52abcae95 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Nov 2016 09:16:03 -0600 Subject: [PATCH 57/60] Add back 'end subroutine' that was accidentally deleted --- src/initialize.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/initialize.F90 b/src/initialize.F90 index d51f9ef8e..692319acb 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -211,6 +211,8 @@ contains call MPI_TYPE_CREATE_STRUCT(5, bank_blocks, bank_disp, & bank_types, MPI_BANK, mpi_err) call MPI_TYPE_COMMIT(MPI_BANK, mpi_err) + + end subroutine initialize_mpi #endif !=============================================================================== From 6a4b00a3f0ef530dbfda6b40947833897aa1bec8 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 16 Nov 2016 12:50:35 -0500 Subject: [PATCH 58/60] Remove StringIO from test_diff_tally --- tests/test_diff_tally/test_diff_tally.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index c5a0762a6..36287a66a 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -2,10 +2,6 @@ import glob import os -try: - from StringIO import StringIO -except: - from io import StringIO import sys import pandas as pd @@ -129,12 +125,9 @@ class DiffTallyTestHarness(PyAPITestHarness): df = df.append(t.get_pandas_dataframe(), ignore_index=True) # Extract the relevant data as a CSV string. - out = StringIO() cols = ('d_material', 'd_nuclide', 'd_variable', 'score', 'mean', 'std. dev.') - df.to_csv(out, columns=cols, index=False, float_format='%.7e') - - return out.getvalue() + return df.to_csv(None, columns=cols, index=False, float_format='%.7e') def _cleanup(self): super(DiffTallyTestHarness, self)._cleanup() From 5df9c4b4400ad1293a2531fff1c48ebb31431ef2 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 16 Nov 2016 15:37:06 -0500 Subject: [PATCH 59/60] Clean up Tally.__repr__ --- openmc/tallies.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index d1789b78e..d5d6df03f 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -179,31 +179,31 @@ class Tally(object): def __repr__(self): string = 'Tally\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self.name) + string += '{: <16}=\t{}\n'.format('\tID', self.id) + string += '{: <16}=\t{}\n'.format('\tName', self.name) if self.derivative is not None: - string += '{0: <16}id =\t{1}\n'.format('\tDerivative', '=\t', - str(self.derivative.id)) + string += '{: <16}=\t{}\n'.format('\tDerivative ID', + str(self.derivative.id)) - string += '{0: <16}{1}\n'.format('\tFilters', '=\t') + string += '{: <16}=\n'.format('\tFilters') for self_filter in self.filters: - string += '{0: <16}\t\t{1}\t{2}\n'.format('', + string += '{: <16}\t\t{}\t{}\n'.format('', type(self_filter).__name__, self_filter.bins) - string += '{0: <16}{1}'.format('\tNuclides', '=\t') + string += '{: <16}=\t'.format('\tNuclides') for nuclide in self.nuclides: if isinstance(nuclide, openmc.Nuclide): - string += '{0} '.format(nuclide.name) + string += nuclide.name + ' ' else: - string += '{0} '.format(nuclide) + string += nuclide + ' ' string += '\n' - string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self.scores) - string += '{0: <16}{1}{2}\n'.format('\tEstimator', '=\t', self.estimator) + string += '{: <16}=\t{}\n'.format('\tScores', self.scores) + string += '{: <16}=\t{}\n'.format('\tEstimator', self.estimator) return string From 5c32103af7bdc840f96abef36d40225a970a6627 Mon Sep 17 00:00:00 2001 From: Colin Josey Date: Wed, 16 Nov 2016 18:00:15 -0500 Subject: [PATCH 60/60] Fix spelling error on NATURAL_ABUNDANCE --- openmc/element.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/element.py b/openmc/element.py index d56c3b350..6e65edab1 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -212,7 +212,7 @@ class Element(object): # its natural nuclides else: for nuclide in natural_nuclides: - abundances[nuclide] = NATURAL_ABUNDNACE[nuclide] + abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] # Modify mole fractions if enrichment provided if enrichment is not None: