From 199d4af9c5e7a274faf36363c9e9e10076376bcf Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 8 Nov 2015 17:24:16 -0500 Subject: [PATCH 01/50] 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 375c517e76..8e8e2db76c 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 9d63eb4e93..6130be0e25 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 58e4013355..052748d139 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 c2f4b51bc0..24e459cbb5 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 55cd5b2a5b..0f667c121b 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 fcd6dfdd9b..7fce90cce5 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 01dcd9bdb5..cfbe0d5376 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 2e4503e139..9502746da7 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 0000000000..d5e50c7e82 --- /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 0000000000..e7e5b097ba --- /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 0000000000..955ea92e7d --- /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 0000000000..5e515c4613 --- /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 0000000000..a41ba9725b --- /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 0000000000..214f33ab37 --- /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 0000000000..ed6addec45 --- /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 0000000000..f77a337cb1 --- /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 0000000000..e7e5b097ba --- /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 0000000000..02b55f4523 --- /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 0000000000..68b611ae15 --- /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 0000000000..a41ba9725b --- /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 0000000000..321b2c9b0e --- /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 0000000000..ed6addec45 --- /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/50] 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 2edf9badd4..047581d1fc 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 0661ab67b1..4ada71519d 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 6130be0e25..82252952d8 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 0f667c121b..0043404805 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 046e7e6669..84554cd947 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 7fce90cce5..d5f36bbe74 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/50] 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 bc2e56bb86..4b9a1b6e4d 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 b4b6e7394f..464379bbd8 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/50] 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 464379bbd8..1613972b24 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/50] 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 1613972b24..4b2a56247c 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/50] 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 ca12d41f60..23ebf1e210 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/50] 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 6d0e2d456d..ef6b548e6c 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 23ebf1e210..3ab6fe5205 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/50] 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 3ab6fe5205..6a020eadb6 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 623fdde415..bbdce44f64 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 9502746da7..1ad379490c 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 68b611ae15..e1c41bdfc3 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/50] 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 6a020eadb6..5d9c3fcd8b 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/50] 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 30e9ed07b9..2553e856bf 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 4cd803cb14..6f77fd96fe 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 5f1b86ef6f..fde80f94f7 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 0f3672c6f2..11b5feec6e 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 36bd5cb85f..83c532b79a 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 5f33eaeb53..93eaaa69fe 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 bd6716f254..ba7581a609 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 9acd05a5ec..a7b455d745 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 1ad379490c..587b678095 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/50] 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 ba7581a609..05c7b2b087 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/50] 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 05c7b2b087..f290670c0c 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 e1c41bdfc3..d0c2e3ad15 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/50] 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 d5e50c7e82..0000000000 --- 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 e7e5b097ba..0000000000 --- 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 955ea92e7d..0000000000 --- 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 5e515c4613..0000000000 --- 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 a41ba9725b..0000000000 --- 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 214f33ab37..0000000000 --- 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 ed6addec45..0000000000 --- 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 f77a337cb1..0000000000 --- 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 e7e5b097ba..0000000000 --- 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 02b55f4523..0000000000 --- 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 d0c2e3ad15..0000000000 --- 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 a41ba9725b..0000000000 --- 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 321b2c9b0e..0000000000 --- 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 ed6addec45..0000000000 --- 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 0000000000..22656a4838 --- /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 0000000000..8b33b82935 --- /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 0000000000..2bd0f704df --- /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/50] 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 c8b6d1ad73..5d8ded5af6 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 6f77fd96fe..aeab9e6bc5 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 fde80f94f7..b7e8a18ae1 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 93eaaa69fe..c31b2b7a31 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 f290670c0c..fca9bf3b95 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/50] 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 fca9bf3b95..058595ca99 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 8b33b82935..3071af772b 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/50] 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 397d9f3e27..ee3db59ae1 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 0abb4b0937..42e9575067 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 2eb632d821..d202497aaf 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 0000000000..0d8f6659e6 --- /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 a5943b6b74..ebbdb58b2e 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 aeab9e6bc5..fdf92dde31 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 b7e8a18ae1..e09797b288 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 cc230d645b..6e2d7957ce 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 c31b2b7a31..4c9d6f000e 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 058595ca99..4dea2e249f 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 a7b455d745..7d7bb6484c 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 587b678095..f20e5e413b 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 22656a4838..f3dfdbc0f6 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 2bd0f704df..6a68596dcc 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 66cadfe633..a462cf1bd3 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/50] 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 0d8f6659e6..932fd28a2f 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 51d130c6d2..ae62838741 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 fdf92dde31..f811cab049 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 6a68596dcc..a7a020c2d1 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/50] 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 7991719c84..84a2a18930 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 a462cf1bd3..66cadfe633 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/50] 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 ab37be78d5..ae86c26032 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 932fd28a2f..9fbad187dc 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/50] 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 0a90b53176..be6610224d 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 84a2a18930..7991719c84 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/50] 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 f6ac534822..d1dac8caff 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 15bc79f739..786b7e8fbb 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 ae86c26032..8cd11d7359 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 5d8ded5af6..72df3c216d 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 be6610224d..f29661352b 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 c6f470175e..4522adff55 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 47fcb70f33..3f88b07608 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 7991719c84..b7a913dd01 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/50] 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 8cd11d7359..a1f19ecd8b 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 9fbad187dc..0b16ad46fa 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 37f85b8303..bdd8c041d0 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 033e80b174..c739695001 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 2d29734b72..6939923fb5 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 b7a913dd01..ee78730342 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 4dea2e249f..a74e8c52e0 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/50] 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 a74e8c52e0..219027ff21 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/50] 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 219027ff21..12d77356b0 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/50] 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 05f03626e7..16cf914e58 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 12d77356b0..bdd7f84d03 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/50] 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 c739695001..0a61373e21 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 ae3ed1a714..f3247fb4ae 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/50] 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 bdd7f84d03..166059d092 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/50] 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 4dea2e249f..019d2d69e2 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/50] 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 9f2bdc4a3a..0a6603f39b 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/50] 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 0a5b7b3b4e..360bb35bcb 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/50] 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 360bb35bcb..43e10986e0 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/50] 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 3884d592a6..689a3fdb5c 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/50] 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 59c7fed695..0ded8846a2 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/50] 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 46508ab5b7..7ff8a26b62 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 cd3e66cefa..ade8834111 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 53a503ce2e..ffb0617e49 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 93950b1f9d..312b56d824 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 10ab35a797..889adb406d 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 f30a40debe..5a80f249fc 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 b0ba615ee5..7bdd32c227 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 dc384f5c14a9af1abb72077a9028eeb5c246a1ce Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 19 Oct 2016 15:26:43 -0400 Subject: [PATCH 35/50] 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 1fd11a889f..bb6024ea7c 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 e7215379f7..0a23a2c0ba 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 b4cef47129..2380050a53 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 d52d499b17..ce5b4a68ef 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 36/50] 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 0a23a2c0ba..a82c8bca86 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 2380050a53..9342c5a0e4 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 37/50] 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 a1c32f723e..7d6fd7c62c 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 38/50] 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 cb13623b8c..d0289cbcef 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 39/50] 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 652b8b8a36..ffbfbe2240 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 40/50] 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 f188874d26..883165556c 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 41/50] 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 b275774002..b12f914a42 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 4522adff55..2143c8e472 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 3f88b07608..fc60b8373a 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 42/50] 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 96e93c3705..dfdaf161a1 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 d0289cbcef..02d0f95db0 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 ffb0617e49..53a503ce2e 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 7d6fd7c62c..a1c32f723e 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 312b56d824..93950b1f9d 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 606186b773..d17c8c3f95 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 5a80f249fc..f30a40debe 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 8350d284aa..a45f8e448f 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 43/50] 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 0b16ad46fa..3c48cf0309 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 02d0f95db0..f40bdb834e 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 d17c8c3f95..8aa6c4ef08 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 44/50] 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 8aa6c4ef08..503b6772b5 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 28bedab0dc..a1a32a0b7c 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 a82c8bca86..1739982016 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 9342c5a0e4..7062ec2ba4 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 ce5b4a68ef..17774e4002 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 150d124c8c..9aa7b55662 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 443e951cc9..3dd3e5e662 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 45/50] 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 503b6772b5..8aa6c4ef08 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 a1a32a0b7c..28bedab0dc 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 1739982016..a82c8bca86 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 7062ec2ba4..9342c5a0e4 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 17774e4002..ce5b4a68ef 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 9aa7b55662..150d124c8c 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 3dd3e5e662..443e951cc9 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 46/50] 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 5aac3b8373..39552a7169 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 e99d6072a1..f3cd015f71 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 a82c8bca86..f82b5d8f07 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 ce5b4a68ef..5e34fd8861 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 2573fba5fae8a57605a4f025626edb288b993aba Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 13 Nov 2016 13:49:30 -0500 Subject: [PATCH 47/50] 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 3c8860475d..4a81615a10 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 d0e4dbdd53..5a677a8e2f 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 3ba24b7827..1f02129c0d 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 3c48cf0309..1c8a316cf5 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 5b8adf1c20..df8efa0c02 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 f30a40debe..e292aba60b 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 f82b5d8f07..9a67475791 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 f40c39973f..7c4f7f7764 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 5e34fd8861..ecf281034d 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 48/50] 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 ecf281034d..c5a0762a69 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 6a4b00a3f0ef530dbfda6b40947833897aa1bec8 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 16 Nov 2016 12:50:35 -0500 Subject: [PATCH 49/50] 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 c5a0762a69..36287a66ac 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 50/50] 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 d1789b78e9..d5d6df03fd 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